diff options
216 files changed, 18946 insertions, 2620 deletions
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index c2fc9ec1417e..7a3b49b3cc3b 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml | |||
| @@ -722,17 +722,22 @@ for more details.</para> | |||
| 722 | </section> | 722 | </section> |
| 723 | 723 | ||
| 724 | <section id="mpeg-controls"> | 724 | <section id="mpeg-controls"> |
| 725 | <title>MPEG Control Reference</title> | 725 | <title>Codec Control Reference</title> |
| 726 | 726 | ||
| 727 | <para>Below all controls within the MPEG control class are | 727 | <para>Below all controls within the Codec control class are |
| 728 | described. First the generic controls, then controls specific for | 728 | described. First the generic controls, then controls specific for |
| 729 | certain hardware.</para> | 729 | certain hardware.</para> |
| 730 | 730 | ||
| 731 | <para>Note: These controls are applicable to all codecs and | ||
| 732 | not just MPEG. The defines are prefixed with V4L2_CID_MPEG/V4L2_MPEG | ||
| 733 | as the controls were originally made for MPEG codecs and later | ||
| 734 | extended to cover all encoding formats.</para> | ||
| 735 | |||
| 731 | <section> | 736 | <section> |
| 732 | <title>Generic MPEG Controls</title> | 737 | <title>Generic Codec Controls</title> |
| 733 | 738 | ||
| 734 | <table pgwide="1" frame="none" id="mpeg-control-id"> | 739 | <table pgwide="1" frame="none" id="mpeg-control-id"> |
| 735 | <title>MPEG Control IDs</title> | 740 | <title>Codec Control IDs</title> |
| 736 | <tgroup cols="4"> | 741 | <tgroup cols="4"> |
| 737 | <colspec colname="c1" colwidth="1*" /> | 742 | <colspec colname="c1" colwidth="1*" /> |
| 738 | <colspec colname="c2" colwidth="6*" /> | 743 | <colspec colname="c2" colwidth="6*" /> |
| @@ -752,7 +757,7 @@ certain hardware.</para> | |||
| 752 | <row> | 757 | <row> |
| 753 | <entry spanname="id"><constant>V4L2_CID_MPEG_CLASS</constant> </entry> | 758 | <entry spanname="id"><constant>V4L2_CID_MPEG_CLASS</constant> </entry> |
| 754 | <entry>class</entry> | 759 | <entry>class</entry> |
| 755 | </row><row><entry spanname="descr">The MPEG class | 760 | </row><row><entry spanname="descr">The Codec class |
| 756 | descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a | 761 | descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a |
| 757 | description of this control class. This description can be used as the | 762 | description of this control class. This description can be used as the |
| 758 | caption of a Tab page in a GUI, for example.</entry> | 763 | caption of a Tab page in a GUI, for example.</entry> |
| @@ -3009,6 +3014,159 @@ in by the application. 0 = do not insert, 1 = insert packets.</entry> | |||
| 3009 | </tgroup> | 3014 | </tgroup> |
| 3010 | </table> | 3015 | </table> |
| 3011 | </section> | 3016 | </section> |
| 3017 | |||
| 3018 | <section> | ||
| 3019 | <title>VPX Control Reference</title> | ||
| 3020 | |||
| 3021 | <para>The VPX controls include controls for encoding parameters | ||
| 3022 | of VPx video codec.</para> | ||
| 3023 | |||
| 3024 | <table pgwide="1" frame="none" id="vpx-control-id"> | ||
| 3025 | <title>VPX Control IDs</title> | ||
| 3026 | |||
| 3027 | <tgroup cols="4"> | ||
| 3028 | <colspec colname="c1" colwidth="1*" /> | ||
| 3029 | <colspec colname="c2" colwidth="6*" /> | ||
| 3030 | <colspec colname="c3" colwidth="2*" /> | ||
| 3031 | <colspec colname="c4" colwidth="6*" /> | ||
| 3032 | <spanspec namest="c1" nameend="c2" spanname="id" /> | ||
| 3033 | <spanspec namest="c2" nameend="c4" spanname="descr" /> | ||
| 3034 | <thead> | ||
| 3035 | <row> | ||
| 3036 | <entry spanname="id" align="left">ID</entry> | ||
| 3037 | <entry align="left">Type</entry> | ||
| 3038 | </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry> | ||
| 3039 | </row> | ||
| 3040 | </thead> | ||
| 3041 | <tbody valign="top"> | ||
| 3042 | <row><entry></entry></row> | ||
| 3043 | |||
| 3044 | <row><entry></entry></row> | ||
| 3045 | <row id="v4l2-vpx-num-partitions"> | ||
| 3046 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS</constant></entry> | ||
| 3047 | <entry>enum v4l2_vp8_num_partitions</entry> | ||
| 3048 | </row> | ||
| 3049 | <row><entry spanname="descr">The number of token partitions to use in VP8 encoder. | ||
| 3050 | Possible values are:</entry> | ||
| 3051 | </row> | ||
| 3052 | <row> | ||
| 3053 | <entrytbl spanname="descr" cols="2"> | ||
| 3054 | <tbody valign="top"> | ||
| 3055 | <row> | ||
| 3056 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION</constant></entry> | ||
| 3057 | <entry>1 coefficient partition</entry> | ||
| 3058 | </row> | ||
| 3059 | <row> | ||
| 3060 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS</constant></entry> | ||
| 3061 | <entry>2 coefficient partitions</entry> | ||
| 3062 | </row> | ||
| 3063 | <row> | ||
| 3064 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS</constant></entry> | ||
| 3065 | <entry>4 coefficient partitions</entry> | ||
| 3066 | </row> | ||
| 3067 | <row> | ||
| 3068 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS</constant></entry> | ||
| 3069 | <entry>8 coefficient partitions</entry> | ||
| 3070 | </row> | ||
| 3071 | </tbody> | ||
| 3072 | </entrytbl> | ||
| 3073 | </row> | ||
| 3074 | |||
| 3075 | <row><entry></entry></row> | ||
| 3076 | <row> | ||
| 3077 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4</constant></entry> | ||
| 3078 | <entry>boolean</entry> | ||
| 3079 | </row> | ||
| 3080 | <row><entry spanname="descr">Setting this prevents intra 4x4 mode in the intra mode decision.</entry> | ||
| 3081 | </row> | ||
| 3082 | |||
| 3083 | <row><entry></entry></row> | ||
| 3084 | <row id="v4l2-vpx-num-ref-frames"> | ||
| 3085 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES</constant></entry> | ||
| 3086 | <entry>enum v4l2_vp8_num_ref_frames</entry> | ||
| 3087 | </row> | ||
| 3088 | <row><entry spanname="descr">The number of reference pictures for encoding P frames. | ||
| 3089 | Possible values are:</entry> | ||
| 3090 | </row> | ||
| 3091 | <row> | ||
| 3092 | <entrytbl spanname="descr" cols="2"> | ||
| 3093 | <tbody valign="top"> | ||
| 3094 | <row> | ||
| 3095 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME</constant></entry> | ||
| 3096 | <entry>Last encoded frame will be searched</entry> | ||
| 3097 | </row> | ||
| 3098 | <row> | ||
| 3099 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME</constant></entry> | ||
| 3100 | <entry>Two frames will be searched among the last encoded frame, the golden frame | ||
| 3101 | and the alternate reference (altref) frame. The encoder implementation will decide which two are chosen.</entry> | ||
| 3102 | </row> | ||
| 3103 | <row> | ||
| 3104 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_3_REF_FRAME</constant></entry> | ||
| 3105 | <entry>The last encoded frame, the golden frame and the altref frame will be searched.</entry> | ||
| 3106 | </row> | ||
| 3107 | </tbody> | ||
| 3108 | </entrytbl> | ||
| 3109 | </row> | ||
| 3110 | |||
| 3111 | <row><entry></entry></row> | ||
| 3112 | <row> | ||
| 3113 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL</constant></entry> | ||
| 3114 | <entry>integer</entry> | ||
| 3115 | </row> | ||
| 3116 | <row><entry spanname="descr">Indicates the loop filter level. The adjustment of the loop | ||
| 3117 | filter level is done via a delta value against a baseline loop filter value.</entry> | ||
| 3118 | </row> | ||
| 3119 | |||
| 3120 | <row><entry></entry></row> | ||
| 3121 | <row> | ||
| 3122 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS</constant></entry> | ||
| 3123 | <entry>integer</entry> | ||
| 3124 | </row> | ||
| 3125 | <row><entry spanname="descr">This parameter affects the loop filter. Anything above | ||
| 3126 | zero weakens the deblocking effect on the loop filter.</entry> | ||
| 3127 | </row> | ||
| 3128 | |||
| 3129 | <row><entry></entry></row> | ||
| 3130 | <row> | ||
| 3131 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD</constant></entry> | ||
| 3132 | <entry>integer</entry> | ||
| 3133 | </row> | ||
| 3134 | <row><entry spanname="descr">Sets the refresh period for the golden frame. The period is defined | ||
| 3135 | in number of frames. For a value of 'n', every nth frame starting from the first key frame will be taken as a golden frame. | ||
| 3136 | For eg. for encoding sequence of 0, 1, 2, 3, 4, 5, 6, 7 where the golden frame refresh period is set as 4, the frames | ||
| 3137 | 0, 4, 8 etc will be taken as the golden frames as frame 0 is always a key frame.</entry> | ||
| 3138 | </row> | ||
| 3139 | |||
| 3140 | <row><entry></entry></row> | ||
| 3141 | <row id="v4l2-vpx-golden-frame-sel"> | ||
| 3142 | <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL</constant></entry> | ||
| 3143 | <entry>enum v4l2_vp8_golden_frame_sel</entry> | ||
| 3144 | </row> | ||
| 3145 | <row><entry spanname="descr">Selects the golden frame for encoding. | ||
| 3146 | Possible values are:</entry> | ||
| 3147 | </row> | ||
| 3148 | <row> | ||
| 3149 | <entrytbl spanname="descr" cols="2"> | ||
| 3150 | <tbody valign="top"> | ||
| 3151 | <row> | ||
| 3152 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV</constant></entry> | ||
| 3153 | <entry>Use the (n-2)th frame as a golden frame, current frame index being 'n'.</entry> | ||
| 3154 | </row> | ||
| 3155 | <row> | ||
| 3156 | <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD</constant></entry> | ||
| 3157 | <entry>Use the previous specific frame indicated by | ||
| 3158 | V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD as a golden frame.</entry> | ||
| 3159 | </row> | ||
| 3160 | </tbody> | ||
| 3161 | </entrytbl> | ||
| 3162 | </row> | ||
| 3163 | |||
| 3164 | <row><entry></entry></row> | ||
| 3165 | </tbody> | ||
| 3166 | </tgroup> | ||
| 3167 | </table> | ||
| 3168 | |||
| 3169 | </section> | ||
| 3012 | </section> | 3170 | </section> |
| 3013 | 3171 | ||
| 3014 | <section id="camera-controls"> | 3172 | <section id="camera-controls"> |
diff --git a/Documentation/DocBook/media/v4l/lirc_device_interface.xml b/Documentation/DocBook/media/v4l/lirc_device_interface.xml index 8d7eb6bf6312..34cada2ca710 100644 --- a/Documentation/DocBook/media/v4l/lirc_device_interface.xml +++ b/Documentation/DocBook/media/v4l/lirc_device_interface.xml | |||
| @@ -46,7 +46,9 @@ describing an IR signal are read from the chardev.</para> | |||
| 46 | values. Pulses and spaces are only marked implicitly by their position. The | 46 | values. Pulses and spaces are only marked implicitly by their position. The |
| 47 | data must start and end with a pulse, therefore, the data must always include | 47 | data must start and end with a pulse, therefore, the data must always include |
| 48 | an uneven number of samples. The write function must block until the data has | 48 | an uneven number of samples. The write function must block until the data has |
| 49 | been transmitted by the hardware.</para> | 49 | been transmitted by the hardware. If more data is provided than the hardware |
| 50 | can send, the driver returns EINVAL.</para> | ||
| 51 | |||
| 50 | </section> | 52 | </section> |
| 51 | 53 | ||
| 52 | <section id="lirc_ioctl"> | 54 | <section id="lirc_ioctl"> |
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml new file mode 100644 index 000000000000..c51d5a4cda09 --- /dev/null +++ b/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | <refentry> | ||
| 2 | <refmeta> | ||
| 3 | <refentrytitle>V4L2_PIX_FMT_NV16M ('NM16'), V4L2_PIX_FMT_NV61M ('NM61')</refentrytitle> | ||
| 4 | &manvol; | ||
| 5 | </refmeta> | ||
| 6 | <refnamediv> | ||
| 7 | <refname id="V4L2-PIX-FMT-NV16M"><constant>V4L2_PIX_FMT_NV16M</constant></refname> | ||
| 8 | <refname id="V4L2-PIX-FMT-NV61M"><constant>V4L2_PIX_FMT_NV61M</constant></refname> | ||
| 9 | <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV16</constant> and <constant>V4L2_PIX_FMT_NV61</constant> with planes | ||
| 10 | non contiguous in memory. </refpurpose> | ||
| 11 | </refnamediv> | ||
| 12 | <refsect1> | ||
| 13 | <title>Description</title> | ||
| 14 | |||
| 15 | <para>This is a multi-planar, two-plane version of the YUV 4:2:0 format. | ||
| 16 | The three components are separated into two sub-images or planes. | ||
| 17 | <constant>V4L2_PIX_FMT_NV16M</constant> differs from <constant>V4L2_PIX_FMT_NV16 | ||
| 18 | </constant> in that the two planes are non-contiguous in memory, i.e. the chroma | ||
| 19 | plane does not necessarily immediately follows the luma plane. | ||
| 20 | The luminance data occupies the first plane. The Y plane has one byte per pixel. | ||
| 21 | In the second plane there is chrominance data with alternating chroma samples. | ||
| 22 | The CbCr plane is the same width and height, in bytes, as the Y plane. | ||
| 23 | Each CbCr pair belongs to four pixels. For example, | ||
| 24 | Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to | ||
| 25 | Y'<subscript>00</subscript>, Y'<subscript>01</subscript>, | ||
| 26 | Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. | ||
| 27 | <constant>V4L2_PIX_FMT_NV61M</constant> is the same as <constant>V4L2_PIX_FMT_NV16M</constant> | ||
| 28 | except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para> | ||
| 29 | |||
| 30 | <para><constant>V4L2_PIX_FMT_NV16M</constant> and | ||
| 31 | <constant>V4L2_PIX_FMT_NV61M</constant> are intended to be used only in drivers | ||
| 32 | and applications that support the multi-planar API, described in | ||
| 33 | <xref linkend="planar-apis"/>. </para> | ||
| 34 | |||
| 35 | <example> | ||
| 36 | <title><constant>V4L2_PIX_FMT_NV16M</constant> 4 × 4 pixel image</title> | ||
| 37 | |||
| 38 | <formalpara> | ||
| 39 | <title>Byte Order.</title> | ||
| 40 | <para>Each cell is one byte. | ||
| 41 | <informaltable frame="none"> | ||
| 42 | <tgroup cols="5" align="center"> | ||
| 43 | <colspec align="left" colwidth="2*" /> | ||
| 44 | <tbody valign="top"> | ||
| 45 | <row> | ||
| 46 | <entry>start0 + 0:</entry> | ||
| 47 | <entry>Y'<subscript>00</subscript></entry> | ||
| 48 | <entry>Y'<subscript>01</subscript></entry> | ||
| 49 | <entry>Y'<subscript>02</subscript></entry> | ||
| 50 | <entry>Y'<subscript>03</subscript></entry> | ||
| 51 | </row> | ||
| 52 | <row> | ||
| 53 | <entry>start0 + 4:</entry> | ||
| 54 | <entry>Y'<subscript>10</subscript></entry> | ||
| 55 | <entry>Y'<subscript>11</subscript></entry> | ||
| 56 | <entry>Y'<subscript>12</subscript></entry> | ||
| 57 | <entry>Y'<subscript>13</subscript></entry> | ||
| 58 | </row> | ||
| 59 | <row> | ||
| 60 | <entry>start0 + 8:</entry> | ||
| 61 | <entry>Y'<subscript>20</subscript></entry> | ||
| 62 | <entry>Y'<subscript>21</subscript></entry> | ||
| 63 | <entry>Y'<subscript>22</subscript></entry> | ||
| 64 | <entry>Y'<subscript>23</subscript></entry> | ||
| 65 | </row> | ||
| 66 | <row> | ||
| 67 | <entry>start0 + 12:</entry> | ||
| 68 | <entry>Y'<subscript>30</subscript></entry> | ||
| 69 | <entry>Y'<subscript>31</subscript></entry> | ||
| 70 | <entry>Y'<subscript>32</subscript></entry> | ||
| 71 | <entry>Y'<subscript>33</subscript></entry> | ||
| 72 | </row> | ||
| 73 | <row> | ||
| 74 | <entry></entry> | ||
| 75 | </row> | ||
| 76 | <row> | ||
| 77 | <entry>start1 + 0:</entry> | ||
| 78 | <entry>Cb<subscript>00</subscript></entry> | ||
| 79 | <entry>Cr<subscript>00</subscript></entry> | ||
| 80 | <entry>Cb<subscript>02</subscript></entry> | ||
| 81 | <entry>Cr<subscript>02</subscript></entry> | ||
| 82 | </row> | ||
| 83 | <row> | ||
| 84 | <entry>start1 + 4:</entry> | ||
| 85 | <entry>Cb<subscript>10</subscript></entry> | ||
| 86 | <entry>Cr<subscript>10</subscript></entry> | ||
| 87 | <entry>Cb<subscript>12</subscript></entry> | ||
| 88 | <entry>Cr<subscript>12</subscript></entry> | ||
| 89 | </row> | ||
| 90 | <row> | ||
| 91 | <entry>start1 + 8:</entry> | ||
| 92 | <entry>Cb<subscript>20</subscript></entry> | ||
| 93 | <entry>Cr<subscript>20</subscript></entry> | ||
| 94 | <entry>Cb<subscript>22</subscript></entry> | ||
| 95 | <entry>Cr<subscript>22</subscript></entry> | ||
| 96 | </row> | ||
| 97 | <row> | ||
| 98 | <entry>start1 + 12:</entry> | ||
| 99 | <entry>Cb<subscript>30</subscript></entry> | ||
| 100 | <entry>Cr<subscript>30</subscript></entry> | ||
| 101 | <entry>Cb<subscript>32</subscript></entry> | ||
| 102 | <entry>Cr<subscript>32</subscript></entry> | ||
| 103 | </row> | ||
| 104 | </tbody> | ||
| 105 | </tgroup> | ||
| 106 | </informaltable> | ||
| 107 | </para> | ||
| 108 | </formalpara> | ||
| 109 | |||
| 110 | <formalpara> | ||
| 111 | <title>Color Sample Location.</title> | ||
| 112 | <para> | ||
| 113 | <informaltable frame="none"> | ||
| 114 | <tgroup cols="7" align="center"> | ||
| 115 | <tbody valign="top"> | ||
| 116 | <row> | ||
| 117 | <entry></entry> | ||
| 118 | <entry>0</entry><entry></entry><entry>1</entry><entry></entry> | ||
| 119 | <entry>2</entry><entry></entry><entry>3</entry> | ||
| 120 | </row> | ||
| 121 | <row> | ||
| 122 | <entry>0</entry> | ||
| 123 | <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | ||
| 124 | <entry>Y</entry><entry></entry><entry>Y</entry> | ||
| 125 | </row> | ||
| 126 | <row> | ||
| 127 | <entry></entry> | ||
| 128 | <entry></entry><entry>C</entry><entry></entry><entry></entry> | ||
| 129 | <entry></entry><entry>C</entry><entry></entry> | ||
| 130 | </row> | ||
| 131 | <row> | ||
| 132 | <entry>1</entry> | ||
| 133 | <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | ||
| 134 | <entry>Y</entry><entry></entry><entry>Y</entry> | ||
| 135 | </row> | ||
| 136 | <row> | ||
| 137 | <entry></entry> | ||
| 138 | <entry></entry><entry>C</entry><entry></entry><entry></entry> | ||
| 139 | <entry></entry><entry>C</entry><entry></entry> | ||
| 140 | </row> | ||
| 141 | <row> | ||
| 142 | <entry></entry> | ||
| 143 | </row> | ||
| 144 | <row> | ||
| 145 | <entry>2</entry> | ||
| 146 | <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | ||
| 147 | <entry>Y</entry><entry></entry><entry>Y</entry> | ||
| 148 | </row> | ||
| 149 | <row> | ||
| 150 | <entry></entry> | ||
| 151 | <entry></entry><entry>C</entry><entry></entry><entry></entry> | ||
| 152 | <entry></entry><entry>C</entry><entry></entry> | ||
| 153 | </row> | ||
| 154 | <row> | ||
| 155 | <entry>3</entry> | ||
| 156 | <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | ||
| 157 | <entry>Y</entry><entry></entry><entry>Y</entry> | ||
| 158 | </row> | ||
| 159 | <row> | ||
| 160 | <entry></entry> | ||
| 161 | <entry></entry><entry>C</entry><entry></entry><entry></entry> | ||
| 162 | <entry></entry><entry>C</entry><entry></entry> | ||
| 163 | </row> | ||
| 164 | </tbody> | ||
| 165 | </tgroup> | ||
| 166 | </informaltable> | ||
| 167 | </para> | ||
| 168 | </formalpara> | ||
| 169 | </example> | ||
| 170 | </refsect1> | ||
| 171 | </refentry> | ||
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index 99b8d2ad6e4f..72d72bd67d0a 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml | |||
| @@ -391,9 +391,9 @@ clamp (double x) | |||
| 391 | else return r; | 391 | else return r; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | y1 = (255 / 219.0) * (Y1 - 16); | 394 | y1 = (Y1 - 16) / 219.0; |
| 395 | pb = (255 / 224.0) * (Cb - 128); | 395 | pb = (Cb - 128) / 224.0; |
| 396 | pr = (255 / 224.0) * (Cr - 128); | 396 | pr = (Cr - 128) / 224.0; |
| 397 | 397 | ||
| 398 | r = 1.0 * y1 + 0 * pb + 1.402 * pr; | 398 | r = 1.0 * y1 + 0 * pb + 1.402 * pr; |
| 399 | g = 1.0 * y1 - 0.344 * pb - 0.714 * pr; | 399 | g = 1.0 * y1 - 0.344 * pb - 0.714 * pr; |
| @@ -718,6 +718,7 @@ information.</para> | |||
| 718 | &sub-nv12m; | 718 | &sub-nv12m; |
| 719 | &sub-nv12mt; | 719 | &sub-nv12mt; |
| 720 | &sub-nv16; | 720 | &sub-nv16; |
| 721 | &sub-nv16m; | ||
| 721 | &sub-nv24; | 722 | &sub-nv24; |
| 722 | &sub-m420; | 723 | &sub-m420; |
| 723 | </section> | 724 | </section> |
diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml index adc61982df7b..f72c1cc93a9b 100644 --- a/Documentation/DocBook/media/v4l/subdev-formats.xml +++ b/Documentation/DocBook/media/v4l/subdev-formats.xml | |||
| @@ -97,31 +97,39 @@ | |||
| 97 | <colspec colname="id" align="left" /> | 97 | <colspec colname="id" align="left" /> |
| 98 | <colspec colname="code" align="center"/> | 98 | <colspec colname="code" align="center"/> |
| 99 | <colspec colname="bit" /> | 99 | <colspec colname="bit" /> |
| 100 | <colspec colnum="4" colname="b23" align="center" /> | 100 | <colspec colnum="4" colname="b31" align="center" /> |
| 101 | <colspec colnum="5" colname="b22" align="center" /> | 101 | <colspec colnum="5" colname="b20" align="center" /> |
| 102 | <colspec colnum="6" colname="b21" align="center" /> | 102 | <colspec colnum="6" colname="b29" align="center" /> |
| 103 | <colspec colnum="7" colname="b20" align="center" /> | 103 | <colspec colnum="7" colname="b28" align="center" /> |
| 104 | <colspec colnum="8" colname="b19" align="center" /> | 104 | <colspec colnum="8" colname="b27" align="center" /> |
| 105 | <colspec colnum="9" colname="b18" align="center" /> | 105 | <colspec colnum="9" colname="b26" align="center" /> |
| 106 | <colspec colnum="10" colname="b17" align="center" /> | 106 | <colspec colnum="10" colname="b25" align="center" /> |
| 107 | <colspec colnum="11" colname="b16" align="center" /> | 107 | <colspec colnum="11" colname="b24" align="center" /> |
| 108 | <colspec colnum="12" colname="b15" align="center" /> | 108 | <colspec colnum="12" colname="b23" align="center" /> |
| 109 | <colspec colnum="13" colname="b14" align="center" /> | 109 | <colspec colnum="13" colname="b22" align="center" /> |
| 110 | <colspec colnum="14" colname="b13" align="center" /> | 110 | <colspec colnum="14" colname="b21" align="center" /> |
| 111 | <colspec colnum="15" colname="b12" align="center" /> | 111 | <colspec colnum="15" colname="b20" align="center" /> |
| 112 | <colspec colnum="16" colname="b11" align="center" /> | 112 | <colspec colnum="16" colname="b19" align="center" /> |
| 113 | <colspec colnum="17" colname="b10" align="center" /> | 113 | <colspec colnum="17" colname="b18" align="center" /> |
| 114 | <colspec colnum="18" colname="b09" align="center" /> | 114 | <colspec colnum="18" colname="b17" align="center" /> |
| 115 | <colspec colnum="19" colname="b08" align="center" /> | 115 | <colspec colnum="19" colname="b16" align="center" /> |
| 116 | <colspec colnum="20" colname="b07" align="center" /> | 116 | <colspec colnum="20" colname="b15" align="center" /> |
| 117 | <colspec colnum="21" colname="b06" align="center" /> | 117 | <colspec colnum="21" colname="b14" align="center" /> |
| 118 | <colspec colnum="22" colname="b05" align="center" /> | 118 | <colspec colnum="22" colname="b13" align="center" /> |
| 119 | <colspec colnum="23" colname="b04" align="center" /> | 119 | <colspec colnum="23" colname="b12" align="center" /> |
| 120 | <colspec colnum="24" colname="b03" align="center" /> | 120 | <colspec colnum="24" colname="b11" align="center" /> |
| 121 | <colspec colnum="25" colname="b02" align="center" /> | 121 | <colspec colnum="25" colname="b10" align="center" /> |
| 122 | <colspec colnum="26" colname="b01" align="center" /> | 122 | <colspec colnum="26" colname="b09" align="center" /> |
| 123 | <colspec colnum="27" colname="b00" align="center" /> | 123 | <colspec colnum="27" colname="b08" align="center" /> |
| 124 | <spanspec namest="b23" nameend="b00" spanname="b0" /> | 124 | <colspec colnum="28" colname="b07" align="center" /> |
| 125 | <colspec colnum="29" colname="b06" align="center" /> | ||
| 126 | <colspec colnum="30" colname="b05" align="center" /> | ||
| 127 | <colspec colnum="31" colname="b04" align="center" /> | ||
| 128 | <colspec colnum="32" colname="b03" align="center" /> | ||
| 129 | <colspec colnum="33" colname="b02" align="center" /> | ||
| 130 | <colspec colnum="34" colname="b01" align="center" /> | ||
| 131 | <colspec colnum="35" colname="b00" align="center" /> | ||
| 132 | <spanspec namest="b31" nameend="b00" spanname="b0" /> | ||
| 125 | <thead> | 133 | <thead> |
| 126 | <row> | 134 | <row> |
| 127 | <entry>Identifier</entry> | 135 | <entry>Identifier</entry> |
| @@ -133,6 +141,14 @@ | |||
| 133 | <entry></entry> | 141 | <entry></entry> |
| 134 | <entry></entry> | 142 | <entry></entry> |
| 135 | <entry>Bit</entry> | 143 | <entry>Bit</entry> |
| 144 | <entry>31</entry> | ||
| 145 | <entry>30</entry> | ||
| 146 | <entry>29</entry> | ||
| 147 | <entry>28</entry> | ||
| 148 | <entry>27</entry> | ||
| 149 | <entry>26</entry> | ||
| 150 | <entry>25</entry> | ||
| 151 | <entry>24</entry> | ||
| 136 | <entry>23</entry> | 152 | <entry>23</entry> |
| 137 | <entry>22</entry> | 153 | <entry>22</entry> |
| 138 | <entry>21</entry> | 154 | <entry>21</entry> |
| @@ -164,7 +180,7 @@ | |||
| 164 | <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE</entry> | 180 | <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE</entry> |
| 165 | <entry>0x1001</entry> | 181 | <entry>0x1001</entry> |
| 166 | <entry></entry> | 182 | <entry></entry> |
| 167 | &dash-ent-16; | 183 | &dash-ent-24; |
| 168 | <entry>0</entry> | 184 | <entry>0</entry> |
| 169 | <entry>0</entry> | 185 | <entry>0</entry> |
| 170 | <entry>0</entry> | 186 | <entry>0</entry> |
| @@ -178,7 +194,7 @@ | |||
| 178 | <entry></entry> | 194 | <entry></entry> |
| 179 | <entry></entry> | 195 | <entry></entry> |
| 180 | <entry></entry> | 196 | <entry></entry> |
| 181 | &dash-ent-16; | 197 | &dash-ent-24; |
| 182 | <entry>g<subscript>3</subscript></entry> | 198 | <entry>g<subscript>3</subscript></entry> |
| 183 | <entry>g<subscript>2</subscript></entry> | 199 | <entry>g<subscript>2</subscript></entry> |
| 184 | <entry>g<subscript>1</subscript></entry> | 200 | <entry>g<subscript>1</subscript></entry> |
| @@ -192,7 +208,7 @@ | |||
| 192 | <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE</entry> | 208 | <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE</entry> |
| 193 | <entry>0x1002</entry> | 209 | <entry>0x1002</entry> |
| 194 | <entry></entry> | 210 | <entry></entry> |
| 195 | &dash-ent-16; | 211 | &dash-ent-24; |
| 196 | <entry>g<subscript>3</subscript></entry> | 212 | <entry>g<subscript>3</subscript></entry> |
| 197 | <entry>g<subscript>2</subscript></entry> | 213 | <entry>g<subscript>2</subscript></entry> |
| 198 | <entry>g<subscript>1</subscript></entry> | 214 | <entry>g<subscript>1</subscript></entry> |
| @@ -206,7 +222,7 @@ | |||
| 206 | <entry></entry> | 222 | <entry></entry> |
| 207 | <entry></entry> | 223 | <entry></entry> |
| 208 | <entry></entry> | 224 | <entry></entry> |
| 209 | &dash-ent-16; | 225 | &dash-ent-24; |
| 210 | <entry>0</entry> | 226 | <entry>0</entry> |
| 211 | <entry>0</entry> | 227 | <entry>0</entry> |
| 212 | <entry>0</entry> | 228 | <entry>0</entry> |
| @@ -220,7 +236,7 @@ | |||
| 220 | <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</entry> | 236 | <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</entry> |
| 221 | <entry>0x1003</entry> | 237 | <entry>0x1003</entry> |
| 222 | <entry></entry> | 238 | <entry></entry> |
| 223 | &dash-ent-16; | 239 | &dash-ent-24; |
| 224 | <entry>0</entry> | 240 | <entry>0</entry> |
| 225 | <entry>r<subscript>4</subscript></entry> | 241 | <entry>r<subscript>4</subscript></entry> |
| 226 | <entry>r<subscript>3</subscript></entry> | 242 | <entry>r<subscript>3</subscript></entry> |
| @@ -234,7 +250,7 @@ | |||
| 234 | <entry></entry> | 250 | <entry></entry> |
| 235 | <entry></entry> | 251 | <entry></entry> |
| 236 | <entry></entry> | 252 | <entry></entry> |
| 237 | &dash-ent-16; | 253 | &dash-ent-24; |
| 238 | <entry>g<subscript>2</subscript></entry> | 254 | <entry>g<subscript>2</subscript></entry> |
| 239 | <entry>g<subscript>1</subscript></entry> | 255 | <entry>g<subscript>1</subscript></entry> |
| 240 | <entry>g<subscript>0</subscript></entry> | 256 | <entry>g<subscript>0</subscript></entry> |
| @@ -248,7 +264,7 @@ | |||
| 248 | <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE</entry> | 264 | <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE</entry> |
| 249 | <entry>0x1004</entry> | 265 | <entry>0x1004</entry> |
| 250 | <entry></entry> | 266 | <entry></entry> |
| 251 | &dash-ent-16; | 267 | &dash-ent-24; |
| 252 | <entry>g<subscript>2</subscript></entry> | 268 | <entry>g<subscript>2</subscript></entry> |
| 253 | <entry>g<subscript>1</subscript></entry> | 269 | <entry>g<subscript>1</subscript></entry> |
| 254 | <entry>g<subscript>0</subscript></entry> | 270 | <entry>g<subscript>0</subscript></entry> |
| @@ -262,7 +278,7 @@ | |||
| 262 | <entry></entry> | 278 | <entry></entry> |
| 263 | <entry></entry> | 279 | <entry></entry> |
| 264 | <entry></entry> | 280 | <entry></entry> |
| 265 | &dash-ent-16; | 281 | &dash-ent-24; |
| 266 | <entry>0</entry> | 282 | <entry>0</entry> |
| 267 | <entry>r<subscript>4</subscript></entry> | 283 | <entry>r<subscript>4</subscript></entry> |
| 268 | <entry>r<subscript>3</subscript></entry> | 284 | <entry>r<subscript>3</subscript></entry> |
| @@ -276,7 +292,7 @@ | |||
| 276 | <entry>V4L2_MBUS_FMT_BGR565_2X8_BE</entry> | 292 | <entry>V4L2_MBUS_FMT_BGR565_2X8_BE</entry> |
| 277 | <entry>0x1005</entry> | 293 | <entry>0x1005</entry> |
| 278 | <entry></entry> | 294 | <entry></entry> |
| 279 | &dash-ent-16; | 295 | &dash-ent-24; |
| 280 | <entry>b<subscript>4</subscript></entry> | 296 | <entry>b<subscript>4</subscript></entry> |
| 281 | <entry>b<subscript>3</subscript></entry> | 297 | <entry>b<subscript>3</subscript></entry> |
| 282 | <entry>b<subscript>2</subscript></entry> | 298 | <entry>b<subscript>2</subscript></entry> |
| @@ -290,7 +306,7 @@ | |||
| 290 | <entry></entry> | 306 | <entry></entry> |
| 291 | <entry></entry> | 307 | <entry></entry> |
| 292 | <entry></entry> | 308 | <entry></entry> |
| 293 | &dash-ent-16; | 309 | &dash-ent-24; |
| 294 | <entry>g<subscript>2</subscript></entry> | 310 | <entry>g<subscript>2</subscript></entry> |
| 295 | <entry>g<subscript>1</subscript></entry> | 311 | <entry>g<subscript>1</subscript></entry> |
| 296 | <entry>g<subscript>0</subscript></entry> | 312 | <entry>g<subscript>0</subscript></entry> |
| @@ -304,7 +320,7 @@ | |||
| 304 | <entry>V4L2_MBUS_FMT_BGR565_2X8_LE</entry> | 320 | <entry>V4L2_MBUS_FMT_BGR565_2X8_LE</entry> |
| 305 | <entry>0x1006</entry> | 321 | <entry>0x1006</entry> |
| 306 | <entry></entry> | 322 | <entry></entry> |
| 307 | &dash-ent-16; | 323 | &dash-ent-24; |
| 308 | <entry>g<subscript>2</subscript></entry> | 324 | <entry>g<subscript>2</subscript></entry> |
| 309 | <entry>g<subscript>1</subscript></entry> | 325 | <entry>g<subscript>1</subscript></entry> |
| 310 | <entry>g<subscript>0</subscript></entry> | 326 | <entry>g<subscript>0</subscript></entry> |
| @@ -318,7 +334,7 @@ | |||
| 318 | <entry></entry> | 334 | <entry></entry> |
| 319 | <entry></entry> | 335 | <entry></entry> |
| 320 | <entry></entry> | 336 | <entry></entry> |
| 321 | &dash-ent-16; | 337 | &dash-ent-24; |
| 322 | <entry>b<subscript>4</subscript></entry> | 338 | <entry>b<subscript>4</subscript></entry> |
| 323 | <entry>b<subscript>3</subscript></entry> | 339 | <entry>b<subscript>3</subscript></entry> |
| 324 | <entry>b<subscript>2</subscript></entry> | 340 | <entry>b<subscript>2</subscript></entry> |
| @@ -332,7 +348,7 @@ | |||
| 332 | <entry>V4L2_MBUS_FMT_RGB565_2X8_BE</entry> | 348 | <entry>V4L2_MBUS_FMT_RGB565_2X8_BE</entry> |
| 333 | <entry>0x1007</entry> | 349 | <entry>0x1007</entry> |
| 334 | <entry></entry> | 350 | <entry></entry> |
| 335 | &dash-ent-16; | 351 | &dash-ent-24; |
| 336 | <entry>r<subscript>4</subscript></entry> | 352 | <entry>r<subscript>4</subscript></entry> |
| 337 | <entry>r<subscript>3</subscript></entry> | 353 | <entry>r<subscript>3</subscript></entry> |
| 338 | <entry>r<subscript>2</subscript></entry> | 354 | <entry>r<subscript>2</subscript></entry> |
| @@ -346,7 +362,7 @@ | |||
| 346 | <entry></entry> | 362 | <entry></entry> |
| 347 | <entry></entry> | 363 | <entry></entry> |
| 348 | <entry></entry> | 364 | <entry></entry> |
| 349 | &dash-ent-16; | 365 | &dash-ent-24; |
| 350 | <entry>g<subscript>2</subscript></entry> | 366 | <entry>g<subscript>2</subscript></entry> |
| 351 | <entry>g<subscript>1</subscript></entry> | 367 | <entry>g<subscript>1</subscript></entry> |
| 352 | <entry>g<subscript>0</subscript></entry> | 368 | <entry>g<subscript>0</subscript></entry> |
| @@ -360,7 +376,7 @@ | |||
| 360 | <entry>V4L2_MBUS_FMT_RGB565_2X8_LE</entry> | 376 | <entry>V4L2_MBUS_FMT_RGB565_2X8_LE</entry> |
| 361 | <entry>0x1008</entry> | 377 | <entry>0x1008</entry> |
| 362 | <entry></entry> | 378 | <entry></entry> |
| 363 | &dash-ent-16; | 379 | &dash-ent-24; |
| 364 | <entry>g<subscript>2</subscript></entry> | 380 | <entry>g<subscript>2</subscript></entry> |
| 365 | <entry>g<subscript>1</subscript></entry> | 381 | <entry>g<subscript>1</subscript></entry> |
| 366 | <entry>g<subscript>0</subscript></entry> | 382 | <entry>g<subscript>0</subscript></entry> |
| @@ -374,7 +390,7 @@ | |||
| 374 | <entry></entry> | 390 | <entry></entry> |
| 375 | <entry></entry> | 391 | <entry></entry> |
| 376 | <entry></entry> | 392 | <entry></entry> |
| 377 | &dash-ent-16; | 393 | &dash-ent-24; |
| 378 | <entry>r<subscript>4</subscript></entry> | 394 | <entry>r<subscript>4</subscript></entry> |
| 379 | <entry>r<subscript>3</subscript></entry> | 395 | <entry>r<subscript>3</subscript></entry> |
| 380 | <entry>r<subscript>2</subscript></entry> | 396 | <entry>r<subscript>2</subscript></entry> |
| @@ -388,12 +404,7 @@ | |||
| 388 | <entry>V4L2_MBUS_FMT_RGB666_1X18</entry> | 404 | <entry>V4L2_MBUS_FMT_RGB666_1X18</entry> |
| 389 | <entry>0x1009</entry> | 405 | <entry>0x1009</entry> |
| 390 | <entry></entry> | 406 | <entry></entry> |
| 391 | <entry>-</entry> | 407 | &dash-ent-14; |
| 392 | <entry>-</entry> | ||
| 393 | <entry>-</entry> | ||
| 394 | <entry>-</entry> | ||
| 395 | <entry>-</entry> | ||
| 396 | <entry>-</entry> | ||
| 397 | <entry>r<subscript>5</subscript></entry> | 408 | <entry>r<subscript>5</subscript></entry> |
| 398 | <entry>r<subscript>4</subscript></entry> | 409 | <entry>r<subscript>4</subscript></entry> |
| 399 | <entry>r<subscript>3</subscript></entry> | 410 | <entry>r<subscript>3</subscript></entry> |
| @@ -417,6 +428,7 @@ | |||
| 417 | <entry>V4L2_MBUS_FMT_RGB888_1X24</entry> | 428 | <entry>V4L2_MBUS_FMT_RGB888_1X24</entry> |
| 418 | <entry>0x100a</entry> | 429 | <entry>0x100a</entry> |
| 419 | <entry></entry> | 430 | <entry></entry> |
| 431 | &dash-ent-8; | ||
| 420 | <entry>r<subscript>7</subscript></entry> | 432 | <entry>r<subscript>7</subscript></entry> |
| 421 | <entry>r<subscript>6</subscript></entry> | 433 | <entry>r<subscript>6</subscript></entry> |
| 422 | <entry>r<subscript>5</subscript></entry> | 434 | <entry>r<subscript>5</subscript></entry> |
| @@ -446,9 +458,7 @@ | |||
| 446 | <entry>V4L2_MBUS_FMT_RGB888_2X12_BE</entry> | 458 | <entry>V4L2_MBUS_FMT_RGB888_2X12_BE</entry> |
| 447 | <entry>0x100b</entry> | 459 | <entry>0x100b</entry> |
| 448 | <entry></entry> | 460 | <entry></entry> |
| 449 | &dash-ent-10; | 461 | &dash-ent-20; |
| 450 | <entry>-</entry> | ||
| 451 | <entry>-</entry> | ||
| 452 | <entry>r<subscript>7</subscript></entry> | 462 | <entry>r<subscript>7</subscript></entry> |
| 453 | <entry>r<subscript>6</subscript></entry> | 463 | <entry>r<subscript>6</subscript></entry> |
| 454 | <entry>r<subscript>5</subscript></entry> | 464 | <entry>r<subscript>5</subscript></entry> |
| @@ -466,9 +476,7 @@ | |||
| 466 | <entry></entry> | 476 | <entry></entry> |
| 467 | <entry></entry> | 477 | <entry></entry> |
| 468 | <entry></entry> | 478 | <entry></entry> |
| 469 | &dash-ent-10; | 479 | &dash-ent-20; |
| 470 | <entry>-</entry> | ||
| 471 | <entry>-</entry> | ||
| 472 | <entry>g<subscript>3</subscript></entry> | 480 | <entry>g<subscript>3</subscript></entry> |
| 473 | <entry>g<subscript>2</subscript></entry> | 481 | <entry>g<subscript>2</subscript></entry> |
| 474 | <entry>g<subscript>1</subscript></entry> | 482 | <entry>g<subscript>1</subscript></entry> |
| @@ -486,9 +494,7 @@ | |||
| 486 | <entry>V4L2_MBUS_FMT_RGB888_2X12_LE</entry> | 494 | <entry>V4L2_MBUS_FMT_RGB888_2X12_LE</entry> |
| 487 | <entry>0x100c</entry> | 495 | <entry>0x100c</entry> |
| 488 | <entry></entry> | 496 | <entry></entry> |
| 489 | &dash-ent-10; | 497 | &dash-ent-20; |
| 490 | <entry>-</entry> | ||
| 491 | <entry>-</entry> | ||
| 492 | <entry>g<subscript>3</subscript></entry> | 498 | <entry>g<subscript>3</subscript></entry> |
| 493 | <entry>g<subscript>2</subscript></entry> | 499 | <entry>g<subscript>2</subscript></entry> |
| 494 | <entry>g<subscript>1</subscript></entry> | 500 | <entry>g<subscript>1</subscript></entry> |
| @@ -506,9 +512,7 @@ | |||
| 506 | <entry></entry> | 512 | <entry></entry> |
| 507 | <entry></entry> | 513 | <entry></entry> |
| 508 | <entry></entry> | 514 | <entry></entry> |
| 509 | &dash-ent-10; | 515 | &dash-ent-20; |
| 510 | <entry>-</entry> | ||
| 511 | <entry>-</entry> | ||
| 512 | <entry>r<subscript>7</subscript></entry> | 516 | <entry>r<subscript>7</subscript></entry> |
| 513 | <entry>r<subscript>6</subscript></entry> | 517 | <entry>r<subscript>6</subscript></entry> |
| 514 | <entry>r<subscript>5</subscript></entry> | 518 | <entry>r<subscript>5</subscript></entry> |
| @@ -522,6 +526,43 @@ | |||
| 522 | <entry>g<subscript>5</subscript></entry> | 526 | <entry>g<subscript>5</subscript></entry> |
| 523 | <entry>g<subscript>4</subscript></entry> | 527 | <entry>g<subscript>4</subscript></entry> |
| 524 | </row> | 528 | </row> |
| 529 | <row id="V4L2-MBUS-FMT-ARGB888-1X32"> | ||
| 530 | <entry>V4L2_MBUS_FMT_ARGB888_1X32</entry> | ||
| 531 | <entry>0x100d</entry> | ||
| 532 | <entry></entry> | ||
| 533 | <entry>a<subscript>7</subscript></entry> | ||
| 534 | <entry>a<subscript>6</subscript></entry> | ||
| 535 | <entry>a<subscript>5</subscript></entry> | ||
| 536 | <entry>a<subscript>4</subscript></entry> | ||
| 537 | <entry>a<subscript>3</subscript></entry> | ||
| 538 | <entry>a<subscript>2</subscript></entry> | ||
| 539 | <entry>a<subscript>1</subscript></entry> | ||
| 540 | <entry>a<subscript>0</subscript></entry> | ||
| 541 | <entry>r<subscript>7</subscript></entry> | ||
| 542 | <entry>r<subscript>6</subscript></entry> | ||
| 543 | <entry>r<subscript>5</subscript></entry> | ||
| 544 | <entry>r<subscript>4</subscript></entry> | ||
| 545 | <entry>r<subscript>3</subscript></entry> | ||
| 546 | <entry>r<subscript>2</subscript></entry> | ||
| 547 | <entry>r<subscript>1</subscript></entry> | ||
| 548 | <entry>r<subscript>0</subscript></entry> | ||
| 549 | <entry>g<subscript>7</subscript></entry> | ||
| 550 | <entry>g<subscript>6</subscript></entry> | ||
| 551 | <entry>g<subscript>5</subscript></entry> | ||
| 552 | <entry>g<subscript>4</subscript></entry> | ||
| 553 | <entry>g<subscript>3</subscript></entry> | ||
| 554 | <entry>g<subscript>2</subscript></entry> | ||
| 555 | <entry>g<subscript>1</subscript></entry> | ||
| 556 | <entry>g<subscript>0</subscript></entry> | ||
| 557 | <entry>b<subscript>7</subscript></entry> | ||
| 558 | <entry>b<subscript>6</subscript></entry> | ||
| 559 | <entry>b<subscript>5</subscript></entry> | ||
| 560 | <entry>b<subscript>4</subscript></entry> | ||
| 561 | <entry>b<subscript>3</subscript></entry> | ||
| 562 | <entry>b<subscript>2</subscript></entry> | ||
| 563 | <entry>b<subscript>1</subscript></entry> | ||
| 564 | <entry>b<subscript>0</subscript></entry> | ||
| 565 | </row> | ||
| 525 | </tbody> | 566 | </tbody> |
| 526 | </tgroup> | 567 | </tgroup> |
| 527 | </table> | 568 | </table> |
| @@ -1149,6 +1190,7 @@ | |||
| 1149 | <listitem><para>y<subscript>x</subscript> for luma component bit number x</para></listitem> | 1190 | <listitem><para>y<subscript>x</subscript> for luma component bit number x</para></listitem> |
| 1150 | <listitem><para>u<subscript>x</subscript> for blue chroma component bit number x</para></listitem> | 1191 | <listitem><para>u<subscript>x</subscript> for blue chroma component bit number x</para></listitem> |
| 1151 | <listitem><para>v<subscript>x</subscript> for red chroma component bit number x</para></listitem> | 1192 | <listitem><para>v<subscript>x</subscript> for red chroma component bit number x</para></listitem> |
| 1193 | <listitem><para>a<subscript>x</subscript> for alpha component bit number x</para></listitem> | ||
| 1152 | <listitem><para>- for non-available bits (for positions higher than the bus width)</para></listitem> | 1194 | <listitem><para>- for non-available bits (for positions higher than the bus width)</para></listitem> |
| 1153 | <listitem><para>d for dummy bits</para></listitem> | 1195 | <listitem><para>d for dummy bits</para></listitem> |
| 1154 | </itemizedlist> | 1196 | </itemizedlist> |
| @@ -1159,37 +1201,39 @@ | |||
| 1159 | <colspec colname="id" align="left" /> | 1201 | <colspec colname="id" align="left" /> |
| 1160 | <colspec colname="code" align="center"/> | 1202 | <colspec colname="code" align="center"/> |
| 1161 | <colspec colname="bit" /> | 1203 | <colspec colname="bit" /> |
| 1162 | <colspec colnum="4" colname="b29" align="center" /> | 1204 | <colspec colnum="4" colname="b31" align="center" /> |
| 1163 | <colspec colnum="5" colname="b28" align="center" /> | 1205 | <colspec colnum="5" colname="b20" align="center" /> |
| 1164 | <colspec colnum="6" colname="b27" align="center" /> | 1206 | <colspec colnum="6" colname="b29" align="center" /> |
| 1165 | <colspec colnum="7" colname="b26" align="center" /> | 1207 | <colspec colnum="7" colname="b28" align="center" /> |
| 1166 | <colspec colnum="8" colname="b25" align="center" /> | 1208 | <colspec colnum="8" colname="b27" align="center" /> |
| 1167 | <colspec colnum="9" colname="b24" align="center" /> | 1209 | <colspec colnum="9" colname="b26" align="center" /> |
| 1168 | <colspec colnum="10" colname="b23" align="center" /> | 1210 | <colspec colnum="10" colname="b25" align="center" /> |
| 1169 | <colspec colnum="11" colname="b22" align="center" /> | 1211 | <colspec colnum="11" colname="b24" align="center" /> |
| 1170 | <colspec colnum="12" colname="b21" align="center" /> | 1212 | <colspec colnum="12" colname="b23" align="center" /> |
| 1171 | <colspec colnum="13" colname="b20" align="center" /> | 1213 | <colspec colnum="13" colname="b22" align="center" /> |
| 1172 | <colspec colnum="14" colname="b19" align="center" /> | 1214 | <colspec colnum="14" colname="b21" align="center" /> |
| 1173 | <colspec colnum="15" colname="b18" align="center" /> | 1215 | <colspec colnum="15" colname="b20" align="center" /> |
| 1174 | <colspec colnum="16" colname="b17" align="center" /> | 1216 | <colspec colnum="16" colname="b19" align="center" /> |
| 1175 | <colspec colnum="17" colname="b16" align="center" /> | 1217 | <colspec colnum="17" colname="b18" align="center" /> |
| 1176 | <colspec colnum="18" colname="b15" align="center" /> | 1218 | <colspec colnum="18" colname="b17" align="center" /> |
| 1177 | <colspec colnum="19" colname="b14" align="center" /> | 1219 | <colspec colnum="19" colname="b16" align="center" /> |
| 1178 | <colspec colnum="20" colname="b13" align="center" /> | 1220 | <colspec colnum="20" colname="b15" align="center" /> |
| 1179 | <colspec colnum="21" colname="b12" align="center" /> | 1221 | <colspec colnum="21" colname="b14" align="center" /> |
| 1180 | <colspec colnum="22" colname="b11" align="center" /> | 1222 | <colspec colnum="22" colname="b13" align="center" /> |
| 1181 | <colspec colnum="23" colname="b10" align="center" /> | 1223 | <colspec colnum="23" colname="b12" align="center" /> |
| 1182 | <colspec colnum="24" colname="b09" align="center" /> | 1224 | <colspec colnum="24" colname="b11" align="center" /> |
| 1183 | <colspec colnum="25" colname="b08" align="center" /> | 1225 | <colspec colnum="25" colname="b10" align="center" /> |
| 1184 | <colspec colnum="26" colname="b07" align="center" /> | 1226 | <colspec colnum="26" colname="b09" align="center" /> |
| 1185 | <colspec colnum="27" colname="b06" align="center" /> | 1227 | <colspec colnum="27" colname="b08" align="center" /> |
| 1186 | <colspec colnum="28" colname="b05" align="center" /> | 1228 | <colspec colnum="28" colname="b07" align="center" /> |
| 1187 | <colspec colnum="29" colname="b04" align="center" /> | 1229 | <colspec colnum="29" colname="b06" align="center" /> |
| 1188 | <colspec colnum="30" colname="b03" align="center" /> | 1230 | <colspec colnum="30" colname="b05" align="center" /> |
| 1189 | <colspec colnum="31" colname="b02" align="center" /> | 1231 | <colspec colnum="31" colname="b04" align="center" /> |
| 1190 | <colspec colnum="32" colname="b01" align="center" /> | 1232 | <colspec colnum="32" colname="b03" align="center" /> |
| 1191 | <colspec colnum="33" colname="b00" align="center" /> | 1233 | <colspec colnum="33" colname="b02" align="center" /> |
| 1192 | <spanspec namest="b29" nameend="b00" spanname="b0" /> | 1234 | <colspec colnum="34" colname="b01" align="center" /> |
| 1235 | <colspec colnum="35" colname="b00" align="center" /> | ||
| 1236 | <spanspec namest="b31" nameend="b00" spanname="b0" /> | ||
| 1193 | <thead> | 1237 | <thead> |
| 1194 | <row> | 1238 | <row> |
| 1195 | <entry>Identifier</entry> | 1239 | <entry>Identifier</entry> |
| @@ -1201,6 +1245,8 @@ | |||
| 1201 | <entry></entry> | 1245 | <entry></entry> |
| 1202 | <entry></entry> | 1246 | <entry></entry> |
| 1203 | <entry>Bit</entry> | 1247 | <entry>Bit</entry> |
| 1248 | <entry>31</entry> | ||
| 1249 | <entry>30</entry> | ||
| 1204 | <entry>29</entry> | 1250 | <entry>29</entry> |
| 1205 | <entry>28</entry> | 1251 | <entry>28</entry> |
| 1206 | <entry>27</entry> | 1252 | <entry>27</entry> |
| @@ -1238,10 +1284,7 @@ | |||
| 1238 | <entry>V4L2_MBUS_FMT_Y8_1X8</entry> | 1284 | <entry>V4L2_MBUS_FMT_Y8_1X8</entry> |
| 1239 | <entry>0x2001</entry> | 1285 | <entry>0x2001</entry> |
| 1240 | <entry></entry> | 1286 | <entry></entry> |
| 1241 | &dash-ent-10; | 1287 | &dash-ent-24; |
| 1242 | &dash-ent-10; | ||
| 1243 | <entry>-</entry> | ||
| 1244 | <entry>-</entry> | ||
| 1245 | <entry>y<subscript>7</subscript></entry> | 1288 | <entry>y<subscript>7</subscript></entry> |
| 1246 | <entry>y<subscript>6</subscript></entry> | 1289 | <entry>y<subscript>6</subscript></entry> |
| 1247 | <entry>y<subscript>5</subscript></entry> | 1290 | <entry>y<subscript>5</subscript></entry> |
| @@ -1255,18 +1298,7 @@ | |||
| 1255 | <entry>V4L2_MBUS_FMT_UV8_1X8</entry> | 1298 | <entry>V4L2_MBUS_FMT_UV8_1X8</entry> |
| 1256 | <entry>0x2015</entry> | 1299 | <entry>0x2015</entry> |
| 1257 | <entry></entry> | 1300 | <entry></entry> |
| 1258 | <entry>-</entry> | 1301 | &dash-ent-24; |
| 1259 | <entry>-</entry> | ||
| 1260 | <entry>-</entry> | ||
| 1261 | <entry>-</entry> | ||
| 1262 | <entry>-</entry> | ||
| 1263 | <entry>-</entry> | ||
| 1264 | <entry>-</entry> | ||
| 1265 | <entry>-</entry> | ||
| 1266 | <entry>-</entry> | ||
| 1267 | <entry>-</entry> | ||
| 1268 | <entry>-</entry> | ||
| 1269 | <entry>-</entry> | ||
| 1270 | <entry>u<subscript>7</subscript></entry> | 1302 | <entry>u<subscript>7</subscript></entry> |
| 1271 | <entry>u<subscript>6</subscript></entry> | 1303 | <entry>u<subscript>6</subscript></entry> |
| 1272 | <entry>u<subscript>5</subscript></entry> | 1304 | <entry>u<subscript>5</subscript></entry> |
| @@ -1280,18 +1312,7 @@ | |||
| 1280 | <entry></entry> | 1312 | <entry></entry> |
| 1281 | <entry></entry> | 1313 | <entry></entry> |
| 1282 | <entry></entry> | 1314 | <entry></entry> |
| 1283 | <entry>-</entry> | 1315 | &dash-ent-24; |
| 1284 | <entry>-</entry> | ||
| 1285 | <entry>-</entry> | ||
| 1286 | <entry>-</entry> | ||
| 1287 | <entry>-</entry> | ||
| 1288 | <entry>-</entry> | ||
| 1289 | <entry>-</entry> | ||
| 1290 | <entry>-</entry> | ||
| 1291 | <entry>-</entry> | ||
| 1292 | <entry>-</entry> | ||
| 1293 | <entry>-</entry> | ||
| 1294 | <entry>-</entry> | ||
| 1295 | <entry>v<subscript>7</subscript></entry> | 1316 | <entry>v<subscript>7</subscript></entry> |
| 1296 | <entry>v<subscript>6</subscript></entry> | 1317 | <entry>v<subscript>6</subscript></entry> |
| 1297 | <entry>v<subscript>5</subscript></entry> | 1318 | <entry>v<subscript>5</subscript></entry> |
| @@ -1305,10 +1326,7 @@ | |||
| 1305 | <entry>V4L2_MBUS_FMT_UYVY8_1_5X8</entry> | 1326 | <entry>V4L2_MBUS_FMT_UYVY8_1_5X8</entry> |
| 1306 | <entry>0x2002</entry> | 1327 | <entry>0x2002</entry> |
| 1307 | <entry></entry> | 1328 | <entry></entry> |
| 1308 | &dash-ent-10; | 1329 | &dash-ent-24; |
| 1309 | &dash-ent-10; | ||
| 1310 | <entry>-</entry> | ||
| 1311 | <entry>-</entry> | ||
| 1312 | <entry>u<subscript>7</subscript></entry> | 1330 | <entry>u<subscript>7</subscript></entry> |
| 1313 | <entry>u<subscript>6</subscript></entry> | 1331 | <entry>u<subscript>6</subscript></entry> |
| 1314 | <entry>u<subscript>5</subscript></entry> | 1332 | <entry>u<subscript>5</subscript></entry> |
| @@ -1322,10 +1340,7 @@ | |||
| 1322 | <entry></entry> | 1340 | <entry></entry> |
| 1323 | <entry></entry> | 1341 | <entry></entry> |
| 1324 | <entry></entry> | 1342 | <entry></entry> |
| 1325 | &dash-ent-10; | 1343 | &dash-ent-24; |
| 1326 | &dash-ent-10; | ||
| 1327 | <entry>-</entry> | ||
| 1328 | <entry>-</entry> | ||
| 1329 | <entry>y<subscript>7</subscript></entry> | 1344 | <entry>y<subscript>7</subscript></entry> |
| 1330 | <entry>y<subscript>6</subscript></entry> | 1345 | <entry>y<subscript>6</subscript></entry> |
| 1331 | <entry>y<subscript>5</subscript></entry> | 1346 | <entry>y<subscript>5</subscript></entry> |
| @@ -1339,10 +1354,7 @@ | |||
| 1339 | <entry></entry> | 1354 | <entry></entry> |
| 1340 | <entry></entry> | 1355 | <entry></entry> |
| 1341 | <entry></entry> | 1356 | <entry></entry> |
| 1342 | &dash-ent-10; | 1357 | &dash-ent-24; |
| 1343 | &dash-ent-10; | ||
| 1344 | <entry>-</entry> | ||
| 1345 | <entry>-</entry> | ||
| 1346 | <entry>y<subscript>7</subscript></entry> | 1358 | <entry>y<subscript>7</subscript></entry> |
| 1347 | <entry>y<subscript>6</subscript></entry> | 1359 | <entry>y<subscript>6</subscript></entry> |
| 1348 | <entry>y<subscript>5</subscript></entry> | 1360 | <entry>y<subscript>5</subscript></entry> |
| @@ -1356,10 +1368,7 @@ | |||
| 1356 | <entry></entry> | 1368 | <entry></entry> |
| 1357 | <entry></entry> | 1369 | <entry></entry> |
| 1358 | <entry></entry> | 1370 | <entry></entry> |
| 1359 | &dash-ent-10; | 1371 | &dash-ent-24; |
| 1360 | &dash-ent-10; | ||
| 1361 | <entry>-</entry> | ||
| 1362 | <entry>-</entry> | ||
| 1363 | <entry>v<subscript>7</subscript></entry> | 1372 | <entry>v<subscript>7</subscript></entry> |
| 1364 | <entry>v<subscript>6</subscript></entry> | 1373 | <entry>v<subscript>6</subscript></entry> |
| 1365 | <entry>v<subscript>5</subscript></entry> | 1374 | <entry>v<subscript>5</subscript></entry> |
| @@ -1373,10 +1382,7 @@ | |||
| 1373 | <entry></entry> | 1382 | <entry></entry> |
| 1374 | <entry></entry> | 1383 | <entry></entry> |
| 1375 | <entry></entry> | 1384 | <entry></entry> |
| 1376 | &dash-ent-10; | 1385 | &dash-ent-24; |
| 1377 | &dash-ent-10; | ||
| 1378 | <entry>-</entry> | ||
| 1379 | <entry>-</entry> | ||
| 1380 | <entry>y<subscript>7</subscript></entry> | 1386 | <entry>y<subscript>7</subscript></entry> |
| 1381 | <entry>y<subscript>6</subscript></entry> | 1387 | <entry>y<subscript>6</subscript></entry> |
| 1382 | <entry>y<subscript>5</subscript></entry> | 1388 | <entry>y<subscript>5</subscript></entry> |
| @@ -1390,10 +1396,7 @@ | |||
| 1390 | <entry></entry> | 1396 | <entry></entry> |
| 1391 | <entry></entry> | 1397 | <entry></entry> |
| 1392 | <entry></entry> | 1398 | <entry></entry> |
| 1393 | &dash-ent-10; | 1399 | &dash-ent-24; |
| 1394 | &dash-ent-10; | ||
| 1395 | <entry>-</entry> | ||
| 1396 | <entry>-</entry> | ||
| 1397 | <entry>y<subscript>7</subscript></entry> | 1400 | <entry>y<subscript>7</subscript></entry> |
| 1398 | <entry>y<subscript>6</subscript></entry> | 1401 | <entry>y<subscript>6</subscript></entry> |
| 1399 | <entry>y<subscript>5</subscript></entry> | 1402 | <entry>y<subscript>5</subscript></entry> |
| @@ -1407,10 +1410,7 @@ | |||
| 1407 | <entry>V4L2_MBUS_FMT_VYUY8_1_5X8</entry> | 1410 | <entry>V4L2_MBUS_FMT_VYUY8_1_5X8</entry> |
| 1408 | <entry>0x2003</entry> | 1411 | <entry>0x2003</entry> |
| 1409 | <entry></entry> | 1412 | <entry></entry> |
| 1410 | &dash-ent-10; | 1413 | &dash-ent-24; |
| 1411 | &dash-ent-10; | ||
| 1412 | <entry>-</entry> | ||
| 1413 | <entry>-</entry> | ||
| 1414 | <entry>v<subscript>7</subscript></entry> | 1414 | <entry>v<subscript>7</subscript></entry> |
| 1415 | <entry>v<subscript>6</subscript></entry> | 1415 | <entry>v<subscript>6</subscript></entry> |
| 1416 | <entry>v<subscript>5</subscript></entry> | 1416 | <entry>v<subscript>5</subscript></entry> |
| @@ -1424,10 +1424,7 @@ | |||
| 1424 | <entry></entry> | 1424 | <entry></entry> |
| 1425 | <entry></entry> | 1425 | <entry></entry> |
| 1426 | <entry></entry> | 1426 | <entry></entry> |
| 1427 | &dash-ent-10; | 1427 | &dash-ent-24; |
| 1428 | &dash-ent-10; | ||
| 1429 | <entry>-</entry> | ||
| 1430 | <entry>-</entry> | ||
| 1431 | <entry>y<subscript>7</subscript></entry> | 1428 | <entry>y<subscript>7</subscript></entry> |
| 1432 | <entry>y<subscript>6</subscript></entry> | 1429 | <entry>y<subscript>6</subscript></entry> |
| 1433 | <entry>y<subscript>5</subscript></entry> | 1430 | <entry>y<subscript>5</subscript></entry> |
| @@ -1441,10 +1438,7 @@ | |||
| 1441 | <entry></entry> | 1438 | <entry></entry> |
| 1442 | <entry></entry> | 1439 | <entry></entry> |
| 1443 | <entry></entry> | 1440 | <entry></entry> |
| 1444 | &dash-ent-10; | 1441 | &dash-ent-24; |
| 1445 | &dash-ent-10; | ||
| 1446 | <entry>-</entry> | ||
| 1447 | <entry>-</entry> | ||
| 1448 | <entry>y<subscript>7</subscript></entry> | 1442 | <entry>y<subscript>7</subscript></entry> |
| 1449 | <entry>y<subscript>6</subscript></entry> | 1443 | <entry>y<subscript>6</subscript></entry> |
| 1450 | <entry>y<subscript>5</subscript></entry> | 1444 | <entry>y<subscript>5</subscript></entry> |
| @@ -1458,10 +1452,7 @@ | |||
| 1458 | <entry></entry> | 1452 | <entry></entry> |
| 1459 | <entry></entry> | 1453 | <entry></entry> |
| 1460 | <entry></entry> | 1454 | <entry></entry> |
| 1461 | &dash-ent-10; | 1455 | &dash-ent-24; |
| 1462 | &dash-ent-10; | ||
| 1463 | <entry>-</entry> | ||
| 1464 | <entry>-</entry> | ||
| 1465 | <entry>u<subscript>7</subscript></entry> | 1456 | <entry>u<subscript>7</subscript></entry> |
| 1466 | <entry>u<subscript>6</subscript></entry> | 1457 | <entry>u<subscript>6</subscript></entry> |
| 1467 | <entry>u<subscript>5</subscript></entry> | 1458 | <entry>u<subscript>5</subscript></entry> |
| @@ -1475,10 +1466,7 @@ | |||
| 1475 | <entry></entry> | 1466 | <entry></entry> |
| 1476 | <entry></entry> | 1467 | <entry></entry> |
| 1477 | <entry></entry> | 1468 | <entry></entry> |
| 1478 | &dash-ent-10; | 1469 | &dash-ent-24; |
| 1479 | &dash-ent-10; | ||
| 1480 | <entry>-</entry> | ||
| 1481 | <entry>-</entry> | ||
| 1482 | <entry>y<subscript>7</subscript></entry> | 1470 | <entry>y<subscript>7</subscript></entry> |
| 1483 | <entry>y<subscript>6</subscript></entry> | 1471 | <entry>y<subscript>6</subscript></entry> |
| 1484 | <entry>y<subscript>5</subscript></entry> | 1472 | <entry>y<subscript>5</subscript></entry> |
| @@ -1492,10 +1480,7 @@ | |||
| 1492 | <entry></entry> | 1480 | <entry></entry> |
| 1493 | <entry></entry> | 1481 | <entry></entry> |
| 1494 | <entry></entry> | 1482 | <entry></entry> |
| 1495 | &dash-ent-10; | 1483 | &dash-ent-24; |
| 1496 | &dash-ent-10; | ||
| 1497 | <entry>-</entry> | ||
| 1498 | <entry>-</entry> | ||
| 1499 | <entry>y<subscript>7</subscript></entry> | 1484 | <entry>y<subscript>7</subscript></entry> |
| 1500 | <entry>y<subscript>6</subscript></entry> | 1485 | <entry>y<subscript>6</subscript></entry> |
| 1501 | <entry>y<subscript>5</subscript></entry> | 1486 | <entry>y<subscript>5</subscript></entry> |
| @@ -1509,10 +1494,7 @@ | |||
| 1509 | <entry>V4L2_MBUS_FMT_YUYV8_1_5X8</entry> | 1494 | <entry>V4L2_MBUS_FMT_YUYV8_1_5X8</entry> |
| 1510 | <entry>0x2004</entry> | 1495 | <entry>0x2004</entry> |
| 1511 | <entry></entry> | 1496 | <entry></entry> |
| 1512 | &dash-ent-10; | 1497 | &dash-ent-24; |
| 1513 | &dash-ent-10; | ||
| 1514 | <entry>-</entry> | ||
| 1515 | <entry>-</entry> | ||
| 1516 | <entry>y<subscript>7</subscript></entry> | 1498 | <entry>y<subscript>7</subscript></entry> |
| 1517 | <entry>y<subscript>6</subscript></entry> | 1499 | <entry>y<subscript>6</subscript></entry> |
| 1518 | <entry>y<subscript>5</subscript></entry> | 1500 | <entry>y<subscript>5</subscript></entry> |
| @@ -1526,10 +1508,7 @@ | |||
| 1526 | <entry></entry> | 1508 | <entry></entry> |
| 1527 | <entry></entry> | 1509 | <entry></entry> |
| 1528 | <entry></entry> | 1510 | <entry></entry> |
| 1529 | &dash-ent-10; | 1511 | &dash-ent-24; |
| 1530 | &dash-ent-10; | ||
| 1531 | <entry>-</entry> | ||
| 1532 | <entry>-</entry> | ||
| 1533 | <entry>y<subscript>7</subscript></entry> | 1512 | <entry>y<subscript>7</subscript></entry> |
| 1534 | <entry>y<subscript>6</subscript></entry> | 1513 | <entry>y<subscript>6</subscript></entry> |
| 1535 | <entry>y<subscript>5</subscript></entry> | 1514 | <entry>y<subscript>5</subscript></entry> |
| @@ -1543,10 +1522,7 @@ | |||
| 1543 | <entry></entry> | 1522 | <entry></entry> |
| 1544 | <entry></entry> | 1523 | <entry></entry> |
| 1545 | <entry></entry> | 1524 | <entry></entry> |
| 1546 | &dash-ent-10; | 1525 | &dash-ent-24; |
| 1547 | &dash-ent-10; | ||
| 1548 | <entry>-</entry> | ||
| 1549 | <entry>-</entry> | ||
| 1550 | <entry>u<subscript>7</subscript></entry> | 1526 | <entry>u<subscript>7</subscript></entry> |
| 1551 | <entry>u<subscript>6</subscript></entry> | 1527 | <entry>u<subscript>6</subscript></entry> |
| 1552 | <entry>u<subscript>5</subscript></entry> | 1528 | <entry>u<subscript>5</subscript></entry> |
| @@ -1560,10 +1536,7 @@ | |||
| 1560 | <entry></entry> | 1536 | <entry></entry> |
| 1561 | <entry></entry> | 1537 | <entry></entry> |
| 1562 | <entry></entry> | 1538 | <entry></entry> |
| 1563 | &dash-ent-10; | 1539 | &dash-ent-24; |
| 1564 | &dash-ent-10; | ||
| 1565 | <entry>-</entry> | ||
| 1566 | <entry>-</entry> | ||
| 1567 | <entry>y<subscript>7</subscript></entry> | 1540 | <entry>y<subscript>7</subscript></entry> |
| 1568 | <entry>y<subscript>6</subscript></entry> | 1541 | <entry>y<subscript>6</subscript></entry> |
| 1569 | <entry>y<subscript>5</subscript></entry> | 1542 | <entry>y<subscript>5</subscript></entry> |
| @@ -1577,10 +1550,7 @@ | |||
| 1577 | <entry></entry> | 1550 | <entry></entry> |
| 1578 | <entry></entry> | 1551 | <entry></entry> |
| 1579 | <entry></entry> | 1552 | <entry></entry> |
| 1580 | &dash-ent-10; | 1553 | &dash-ent-24; |
| 1581 | &dash-ent-10; | ||
| 1582 | <entry>-</entry> | ||
| 1583 | <entry>-</entry> | ||
| 1584 | <entry>y<subscript>7</subscript></entry> | 1554 | <entry>y<subscript>7</subscript></entry> |
| 1585 | <entry>y<subscript>6</subscript></entry> | 1555 | <entry>y<subscript>6</subscript></entry> |
| 1586 | <entry>y<subscript>5</subscript></entry> | 1556 | <entry>y<subscript>5</subscript></entry> |
| @@ -1594,10 +1564,7 @@ | |||
| 1594 | <entry></entry> | 1564 | <entry></entry> |
| 1595 | <entry></entry> | 1565 | <entry></entry> |
| 1596 | <entry></entry> | 1566 | <entry></entry> |
| 1597 | &dash-ent-10; | 1567 | &dash-ent-24; |
| 1598 | &dash-ent-10; | ||
| 1599 | <entry>-</entry> | ||
| 1600 | <entry>-</entry> | ||
| 1601 | <entry>v<subscript>7</subscript></entry> | 1568 | <entry>v<subscript>7</subscript></entry> |
| 1602 | <entry>v<subscript>6</subscript></entry> | 1569 | <entry>v<subscript>6</subscript></entry> |
| 1603 | <entry>v<subscript>5</subscript></entry> | 1570 | <entry>v<subscript>5</subscript></entry> |
| @@ -1611,10 +1578,7 @@ | |||
| 1611 | <entry>V4L2_MBUS_FMT_YVYU8_1_5X8</entry> | 1578 | <entry>V4L2_MBUS_FMT_YVYU8_1_5X8</entry> |
| 1612 | <entry>0x2005</entry> | 1579 | <entry>0x2005</entry> |
| 1613 | <entry></entry> | 1580 | <entry></entry> |
| 1614 | &dash-ent-10; | 1581 | &dash-ent-24; |
| 1615 | &dash-ent-10; | ||
| 1616 | <entry>-</entry> | ||
| 1617 | <entry>-</entry> | ||
| 1618 | <entry>y<subscript>7</subscript></entry> | 1582 | <entry>y<subscript>7</subscript></entry> |
| 1619 | <entry>y<subscript>6</subscript></entry> | 1583 | <entry>y<subscript>6</subscript></entry> |
| 1620 | <entry>y<subscript>5</subscript></entry> | 1584 | <entry>y<subscript>5</subscript></entry> |
| @@ -1628,10 +1592,7 @@ | |||
| 1628 | <entry></entry> | 1592 | <entry></entry> |
| 1629 | <entry></entry> | 1593 | <entry></entry> |
| 1630 | <entry></entry> | 1594 | <entry></entry> |
| 1631 | &dash-ent-10; | 1595 | &dash-ent-24; |
| 1632 | &dash-ent-10; | ||
| 1633 | <entry>-</entry> | ||
| 1634 | <entry>-</entry> | ||
| 1635 | <entry>y<subscript>7</subscript></entry> | 1596 | <entry>y<subscript>7</subscript></entry> |
| 1636 | <entry>y<subscript>6</subscript></entry> | 1597 | <entry>y<subscript>6</subscript></entry> |
| 1637 | <entry>y<subscript>5</subscript></entry> | 1598 | <entry>y<subscript>5</subscript></entry> |
| @@ -1645,10 +1606,7 @@ | |||
| 1645 | <entry></entry> | 1606 | <entry></entry> |
| 1646 | <entry></entry> | 1607 | <entry></entry> |
| 1647 | <entry></entry> | 1608 | <entry></entry> |
| 1648 | &dash-ent-10; | 1609 | &dash-ent-24; |
| 1649 | &dash-ent-10; | ||
| 1650 | <entry>-</entry> | ||
| 1651 | <entry>-</entry> | ||
| 1652 | <entry>v<subscript>7</subscript></entry> | 1610 | <entry>v<subscript>7</subscript></entry> |
| 1653 | <entry>v<subscript>6</subscript></entry> | 1611 | <entry>v<subscript>6</subscript></entry> |
| 1654 | <entry>v<subscript>5</subscript></entry> | 1612 | <entry>v<subscript>5</subscript></entry> |
| @@ -1662,10 +1620,7 @@ | |||
| 1662 | <entry></entry> | 1620 | <entry></entry> |
| 1663 | <entry></entry> | 1621 | <entry></entry> |
| 1664 | <entry></entry> | 1622 | <entry></entry> |
| 1665 | &dash-ent-10; | 1623 | &dash-ent-24; |
| 1666 | &dash-ent-10; | ||
| 1667 | <entry>-</entry> | ||
| 1668 | <entry>-</entry> | ||
| 1669 | <entry>y<subscript>7</subscript></entry> | 1624 | <entry>y<subscript>7</subscript></entry> |
| 1670 | <entry>y<subscript>6</subscript></entry> | 1625 | <entry>y<subscript>6</subscript></entry> |
| 1671 | <entry>y<subscript>5</subscript></entry> | 1626 | <entry>y<subscript>5</subscript></entry> |
| @@ -1679,10 +1634,7 @@ | |||
| 1679 | <entry></entry> | 1634 | <entry></entry> |
| 1680 | <entry></entry> | 1635 | <entry></entry> |
| 1681 | <entry></entry> | 1636 | <entry></entry> |
| 1682 | &dash-ent-10; | 1637 | &dash-ent-24; |
| 1683 | &dash-ent-10; | ||
| 1684 | <entry>-</entry> | ||
| 1685 | <entry>-</entry> | ||
| 1686 | <entry>y<subscript>7</subscript></entry> | 1638 | <entry>y<subscript>7</subscript></entry> |
| 1687 | <entry>y<subscript>6</subscript></entry> | 1639 | <entry>y<subscript>6</subscript></entry> |
| 1688 | <entry>y<subscript>5</subscript></entry> | 1640 | <entry>y<subscript>5</subscript></entry> |
| @@ -1696,10 +1648,7 @@ | |||
| 1696 | <entry></entry> | 1648 | <entry></entry> |
| 1697 | <entry></entry> | 1649 | <entry></entry> |
| 1698 | <entry></entry> | 1650 | <entry></entry> |
| 1699 | &dash-ent-10; | 1651 | &dash-ent-24; |
| 1700 | &dash-ent-10; | ||
| 1701 | <entry>-</entry> | ||
| 1702 | <entry>-</entry> | ||
| 1703 | <entry>u<subscript>7</subscript></entry> | 1652 | <entry>u<subscript>7</subscript></entry> |
| 1704 | <entry>u<subscript>6</subscript></entry> | 1653 | <entry>u<subscript>6</subscript></entry> |
| 1705 | <entry>u<subscript>5</subscript></entry> | 1654 | <entry>u<subscript>5</subscript></entry> |
| @@ -1713,10 +1662,7 @@ | |||
| 1713 | <entry>V4L2_MBUS_FMT_UYVY8_2X8</entry> | 1662 | <entry>V4L2_MBUS_FMT_UYVY8_2X8</entry> |
| 1714 | <entry>0x2006</entry> | 1663 | <entry>0x2006</entry> |
| 1715 | <entry></entry> | 1664 | <entry></entry> |
| 1716 | &dash-ent-10; | 1665 | &dash-ent-24; |
| 1717 | &dash-ent-10; | ||
| 1718 | <entry>-</entry> | ||
| 1719 | <entry>-</entry> | ||
| 1720 | <entry>u<subscript>7</subscript></entry> | 1666 | <entry>u<subscript>7</subscript></entry> |
| 1721 | <entry>u<subscript>6</subscript></entry> | 1667 | <entry>u<subscript>6</subscript></entry> |
| 1722 | <entry>u<subscript>5</subscript></entry> | 1668 | <entry>u<subscript>5</subscript></entry> |
| @@ -1730,10 +1676,7 @@ | |||
| 1730 | <entry></entry> | 1676 | <entry></entry> |
| 1731 | <entry></entry> | 1677 | <entry></entry> |
| 1732 | <entry></entry> | 1678 | <entry></entry> |
| 1733 | &dash-ent-10; | 1679 | &dash-ent-24; |
| 1734 | &dash-ent-10; | ||
| 1735 | <entry>-</entry> | ||
| 1736 | <entry>-</entry> | ||
| 1737 | <entry>y<subscript>7</subscript></entry> | 1680 | <entry>y<subscript>7</subscript></entry> |
| 1738 | <entry>y<subscript>6</subscript></entry> | 1681 | <entry>y<subscript>6</subscript></entry> |
| 1739 | <entry>y<subscript>5</subscript></entry> | 1682 | <entry>y<subscript>5</subscript></entry> |
| @@ -1747,10 +1690,7 @@ | |||
| 1747 | <entry></entry> | 1690 | <entry></entry> |
| 1748 | <entry></entry> | 1691 | <entry></entry> |
| 1749 | <entry></entry> | 1692 | <entry></entry> |
| 1750 | &dash-ent-10; | 1693 | &dash-ent-24; |
| 1751 | &dash-ent-10; | ||
| 1752 | <entry>-</entry> | ||
| 1753 | <entry>-</entry> | ||
| 1754 | <entry>v<subscript>7</subscript></entry> | 1694 | <entry>v<subscript>7</subscript></entry> |
| 1755 | <entry>v<subscript>6</subscript></entry> | 1695 | <entry>v<subscript>6</subscript></entry> |
| 1756 | <entry>v<subscript>5</subscript></entry> | 1696 | <entry>v<subscript>5</subscript></entry> |
| @@ -1764,10 +1704,7 @@ | |||
| 1764 | <entry></entry> | 1704 | <entry></entry> |
| 1765 | <entry></entry> | 1705 | <entry></entry> |
| 1766 | <entry></entry> | 1706 | <entry></entry> |
| 1767 | &dash-ent-10; | 1707 | &dash-ent-24; |
| 1768 | &dash-ent-10; | ||
| 1769 | <entry>-</entry> | ||
| 1770 | <entry>-</entry> | ||
| 1771 | <entry>y<subscript>7</subscript></entry> | 1708 | <entry>y<subscript>7</subscript></entry> |
| 1772 | <entry>y<subscript>6</subscript></entry> | 1709 | <entry>y<subscript>6</subscript></entry> |
| 1773 | <entry>y<subscript>5</subscript></entry> | 1710 | <entry>y<subscript>5</subscript></entry> |
| @@ -1781,10 +1718,7 @@ | |||
| 1781 | <entry>V4L2_MBUS_FMT_VYUY8_2X8</entry> | 1718 | <entry>V4L2_MBUS_FMT_VYUY8_2X8</entry> |
| 1782 | <entry>0x2007</entry> | 1719 | <entry>0x2007</entry> |
| 1783 | <entry></entry> | 1720 | <entry></entry> |
| 1784 | &dash-ent-10; | 1721 | &dash-ent-24; |
| 1785 | &dash-ent-10; | ||
| 1786 | <entry>-</entry> | ||
| 1787 | <entry>-</entry> | ||
| 1788 | <entry>v<subscript>7</subscript></entry> | 1722 | <entry>v<subscript>7</subscript></entry> |
| 1789 | <entry>v<subscript>6</subscript></entry> | 1723 | <entry>v<subscript>6</subscript></entry> |
| 1790 | <entry>v<subscript>5</subscript></entry> | 1724 | <entry>v<subscript>5</subscript></entry> |
| @@ -1798,10 +1732,7 @@ | |||
| 1798 | <entry></entry> | 1732 | <entry></entry> |
| 1799 | <entry></entry> | 1733 | <entry></entry> |
| 1800 | <entry></entry> | 1734 | <entry></entry> |
| 1801 | &dash-ent-10; | 1735 | &dash-ent-24; |
| 1802 | &dash-ent-10; | ||
| 1803 | <entry>-</entry> | ||
| 1804 | <entry>-</entry> | ||
| 1805 | <entry>y<subscript>7</subscript></entry> | 1736 | <entry>y<subscript>7</subscript></entry> |
| 1806 | <entry>y<subscript>6</subscript></entry> | 1737 | <entry>y<subscript>6</subscript></entry> |
| 1807 | <entry>y<subscript>5</subscript></entry> | 1738 | <entry>y<subscript>5</subscript></entry> |
| @@ -1815,10 +1746,7 @@ | |||
| 1815 | <entry></entry> | 1746 | <entry></entry> |
| 1816 | <entry></entry> | 1747 | <entry></entry> |
| 1817 | <entry></entry> | 1748 | <entry></entry> |
| 1818 | &dash-ent-10; | 1749 | &dash-ent-24; |
| 1819 | &dash-ent-10; | ||
| 1820 | <entry>-</entry> | ||
| 1821 | <entry>-</entry> | ||
| 1822 | <entry>u<subscript>7</subscript></entry> | 1750 | <entry>u<subscript>7</subscript></entry> |
| 1823 | <entry>u<subscript>6</subscript></entry> | 1751 | <entry>u<subscript>6</subscript></entry> |
| 1824 | <entry>u<subscript>5</subscript></entry> | 1752 | <entry>u<subscript>5</subscript></entry> |
| @@ -1832,10 +1760,7 @@ | |||
| 1832 | <entry></entry> | 1760 | <entry></entry> |
| 1833 | <entry></entry> | 1761 | <entry></entry> |
| 1834 | <entry></entry> | 1762 | <entry></entry> |
| 1835 | &dash-ent-10; | 1763 | &dash-ent-24; |
| 1836 | &dash-ent-10; | ||
| 1837 | <entry>-</entry> | ||
| 1838 | <entry>-</entry> | ||
| 1839 | <entry>y<subscript>7</subscript></entry> | 1764 | <entry>y<subscript>7</subscript></entry> |
| 1840 | <entry>y<subscript>6</subscript></entry> | 1765 | <entry>y<subscript>6</subscript></entry> |
| 1841 | <entry>y<subscript>5</subscript></entry> | 1766 | <entry>y<subscript>5</subscript></entry> |
| @@ -1849,10 +1774,7 @@ | |||
| 1849 | <entry>V4L2_MBUS_FMT_YUYV8_2X8</entry> | 1774 | <entry>V4L2_MBUS_FMT_YUYV8_2X8</entry> |
| 1850 | <entry>0x2008</entry> | 1775 | <entry>0x2008</entry> |
| 1851 | <entry></entry> | 1776 | <entry></entry> |
| 1852 | &dash-ent-10; | 1777 | &dash-ent-24; |
| 1853 | &dash-ent-10; | ||
| 1854 | <entry>-</entry> | ||
| 1855 | <entry>-</entry> | ||
| 1856 | <entry>y<subscript>7</subscript></entry> | 1778 | <entry>y<subscript>7</subscript></entry> |
| 1857 | <entry>y<subscript>6</subscript></entry> | 1779 | <entry>y<subscript>6</subscript></entry> |
| 1858 | <entry>y<subscript>5</subscript></entry> | 1780 | <entry>y<subscript>5</subscript></entry> |
| @@ -1866,10 +1788,7 @@ | |||
| 1866 | <entry></entry> | 1788 | <entry></entry> |
| 1867 | <entry></entry> | 1789 | <entry></entry> |
| 1868 | <entry></entry> | 1790 | <entry></entry> |
| 1869 | &dash-ent-10; | 1791 | &dash-ent-24; |
| 1870 | &dash-ent-10; | ||
| 1871 | <entry>-</entry> | ||
| 1872 | <entry>-</entry> | ||
| 1873 | <entry>u<subscript>7</subscript></entry> | 1792 | <entry>u<subscript>7</subscript></entry> |
| 1874 | <entry>u<subscript>6</subscript></entry> | 1793 | <entry>u<subscript>6</subscript></entry> |
| 1875 | <entry>u<subscript>5</subscript></entry> | 1794 | <entry>u<subscript>5</subscript></entry> |
| @@ -1883,10 +1802,7 @@ | |||
| 1883 | <entry></entry> | 1802 | <entry></entry> |
| 1884 | <entry></entry> | 1803 | <entry></entry> |
| 1885 | <entry></entry> | 1804 | <entry></entry> |
| 1886 | &dash-ent-10; | 1805 | &dash-ent-24; |
| 1887 | &dash-ent-10; | ||
| 1888 | <entry>-</entry> | ||
| 1889 | <entry>-</entry> | ||
| 1890 | <entry>y<subscript>7</subscript></entry> | 1806 | <entry>y<subscript>7</subscript></entry> |
| 1891 | <entry>y<subscript>6</subscript></entry> | 1807 | <entry>y<subscript>6</subscript></entry> |
| 1892 | <entry>y<subscript>5</subscript></entry> | 1808 | <entry>y<subscript>5</subscript></entry> |
| @@ -1900,10 +1816,7 @@ | |||
| 1900 | <entry></entry> | 1816 | <entry></entry> |
| 1901 | <entry></entry> | 1817 | <entry></entry> |
| 1902 | <entry></entry> | 1818 | <entry></entry> |
| 1903 | &dash-ent-10; | 1819 | &dash-ent-24; |
| 1904 | &dash-ent-10; | ||
| 1905 | <entry>-</entry> | ||
| 1906 | <entry>-</entry> | ||
| 1907 | <entry>v<subscript>7</subscript></entry> | 1820 | <entry>v<subscript>7</subscript></entry> |
| 1908 | <entry>v<subscript>6</subscript></entry> | 1821 | <entry>v<subscript>6</subscript></entry> |
| 1909 | <entry>v<subscript>5</subscript></entry> | 1822 | <entry>v<subscript>5</subscript></entry> |
| @@ -1917,10 +1830,7 @@ | |||
| 1917 | <entry>V4L2_MBUS_FMT_YVYU8_2X8</entry> | 1830 | <entry>V4L2_MBUS_FMT_YVYU8_2X8</entry> |
| 1918 | <entry>0x2009</entry> | 1831 | <entry>0x2009</entry> |
| 1919 | <entry></entry> | 1832 | <entry></entry> |
| 1920 | &dash-ent-10; | 1833 | &dash-ent-24; |
| 1921 | &dash-ent-10; | ||
| 1922 | <entry>-</entry> | ||
| 1923 | <entry>-</entry> | ||
| 1924 | <entry>y<subscript>7</subscript></entry> | 1834 | <entry>y<subscript>7</subscript></entry> |
| 1925 | <entry>y<subscript>6</subscript></entry> | 1835 | <entry>y<subscript>6</subscript></entry> |
| 1926 | <entry>y<subscript>5</subscript></entry> | 1836 | <entry>y<subscript>5</subscript></entry> |
| @@ -1934,10 +1844,7 @@ | |||
| 1934 | <entry></entry> | 1844 | <entry></entry> |
| 1935 | <entry></entry> | 1845 | <entry></entry> |
| 1936 | <entry></entry> | 1846 | <entry></entry> |
| 1937 | &dash-ent-10; | 1847 | &dash-ent-24; |
| 1938 | &dash-ent-10; | ||
| 1939 | <entry>-</entry> | ||
| 1940 | <entry>-</entry> | ||
| 1941 | <entry>v<subscript>7</subscript></entry> | 1848 | <entry>v<subscript>7</subscript></entry> |
| 1942 | <entry>v<subscript>6</subscript></entry> | 1849 | <entry>v<subscript>6</subscript></entry> |
| 1943 | <entry>v<subscript>5</subscript></entry> | 1850 | <entry>v<subscript>5</subscript></entry> |
| @@ -1951,10 +1858,7 @@ | |||
| 1951 | <entry></entry> | 1858 | <entry></entry> |
| 1952 | <entry></entry> | 1859 | <entry></entry> |
| 1953 | <entry></entry> | 1860 | <entry></entry> |
| 1954 | &dash-ent-10; | 1861 | &dash-ent-24; |
| 1955 | &dash-ent-10; | ||
| 1956 | <entry>-</entry> | ||
| 1957 | <entry>-</entry> | ||
| 1958 | <entry>y<subscript>7</subscript></entry> | 1862 | <entry>y<subscript>7</subscript></entry> |
| 1959 | <entry>y<subscript>6</subscript></entry> | 1863 | <entry>y<subscript>6</subscript></entry> |
| 1960 | <entry>y<subscript>5</subscript></entry> | 1864 | <entry>y<subscript>5</subscript></entry> |
| @@ -1968,10 +1872,7 @@ | |||
| 1968 | <entry></entry> | 1872 | <entry></entry> |
| 1969 | <entry></entry> | 1873 | <entry></entry> |
| 1970 | <entry></entry> | 1874 | <entry></entry> |
| 1971 | &dash-ent-10; | 1875 | &dash-ent-24; |
| 1972 | &dash-ent-10; | ||
| 1973 | <entry>-</entry> | ||
| 1974 | <entry>-</entry> | ||
| 1975 | <entry>u<subscript>7</subscript></entry> | 1876 | <entry>u<subscript>7</subscript></entry> |
| 1976 | <entry>u<subscript>6</subscript></entry> | 1877 | <entry>u<subscript>6</subscript></entry> |
| 1977 | <entry>u<subscript>5</subscript></entry> | 1878 | <entry>u<subscript>5</subscript></entry> |
| @@ -1985,8 +1886,7 @@ | |||
| 1985 | <entry>V4L2_MBUS_FMT_Y10_1X10</entry> | 1886 | <entry>V4L2_MBUS_FMT_Y10_1X10</entry> |
| 1986 | <entry>0x200a</entry> | 1887 | <entry>0x200a</entry> |
| 1987 | <entry></entry> | 1888 | <entry></entry> |
| 1988 | &dash-ent-10; | 1889 | &dash-ent-22; |
| 1989 | &dash-ent-10; | ||
| 1990 | <entry>y<subscript>9</subscript></entry> | 1890 | <entry>y<subscript>9</subscript></entry> |
| 1991 | <entry>y<subscript>8</subscript></entry> | 1891 | <entry>y<subscript>8</subscript></entry> |
| 1992 | <entry>y<subscript>7</subscript></entry> | 1892 | <entry>y<subscript>7</subscript></entry> |
| @@ -2002,8 +1902,7 @@ | |||
| 2002 | <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry> | 1902 | <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry> |
| 2003 | <entry>0x200b</entry> | 1903 | <entry>0x200b</entry> |
| 2004 | <entry></entry> | 1904 | <entry></entry> |
| 2005 | &dash-ent-10; | 1905 | &dash-ent-22; |
| 2006 | &dash-ent-10; | ||
| 2007 | <entry>y<subscript>9</subscript></entry> | 1906 | <entry>y<subscript>9</subscript></entry> |
| 2008 | <entry>y<subscript>8</subscript></entry> | 1907 | <entry>y<subscript>8</subscript></entry> |
| 2009 | <entry>y<subscript>7</subscript></entry> | 1908 | <entry>y<subscript>7</subscript></entry> |
| @@ -2019,8 +1918,7 @@ | |||
| 2019 | <entry></entry> | 1918 | <entry></entry> |
| 2020 | <entry></entry> | 1919 | <entry></entry> |
| 2021 | <entry></entry> | 1920 | <entry></entry> |
| 2022 | &dash-ent-10; | 1921 | &dash-ent-22; |
| 2023 | &dash-ent-10; | ||
| 2024 | <entry>u<subscript>9</subscript></entry> | 1922 | <entry>u<subscript>9</subscript></entry> |
| 2025 | <entry>u<subscript>8</subscript></entry> | 1923 | <entry>u<subscript>8</subscript></entry> |
| 2026 | <entry>u<subscript>7</subscript></entry> | 1924 | <entry>u<subscript>7</subscript></entry> |
| @@ -2036,8 +1934,7 @@ | |||
| 2036 | <entry></entry> | 1934 | <entry></entry> |
| 2037 | <entry></entry> | 1935 | <entry></entry> |
| 2038 | <entry></entry> | 1936 | <entry></entry> |
| 2039 | &dash-ent-10; | 1937 | &dash-ent-22; |
| 2040 | &dash-ent-10; | ||
| 2041 | <entry>y<subscript>9</subscript></entry> | 1938 | <entry>y<subscript>9</subscript></entry> |
| 2042 | <entry>y<subscript>8</subscript></entry> | 1939 | <entry>y<subscript>8</subscript></entry> |
| 2043 | <entry>y<subscript>7</subscript></entry> | 1940 | <entry>y<subscript>7</subscript></entry> |
| @@ -2053,8 +1950,7 @@ | |||
| 2053 | <entry></entry> | 1950 | <entry></entry> |
| 2054 | <entry></entry> | 1951 | <entry></entry> |
| 2055 | <entry></entry> | 1952 | <entry></entry> |
| 2056 | &dash-ent-10; | 1953 | &dash-ent-22; |
| 2057 | &dash-ent-10; | ||
| 2058 | <entry>v<subscript>9</subscript></entry> | 1954 | <entry>v<subscript>9</subscript></entry> |
| 2059 | <entry>v<subscript>8</subscript></entry> | 1955 | <entry>v<subscript>8</subscript></entry> |
| 2060 | <entry>v<subscript>7</subscript></entry> | 1956 | <entry>v<subscript>7</subscript></entry> |
| @@ -2070,8 +1966,7 @@ | |||
| 2070 | <entry>V4L2_MBUS_FMT_YVYU10_2X10</entry> | 1966 | <entry>V4L2_MBUS_FMT_YVYU10_2X10</entry> |
| 2071 | <entry>0x200c</entry> | 1967 | <entry>0x200c</entry> |
| 2072 | <entry></entry> | 1968 | <entry></entry> |
| 2073 | &dash-ent-10; | 1969 | &dash-ent-22; |
| 2074 | &dash-ent-10; | ||
| 2075 | <entry>y<subscript>9</subscript></entry> | 1970 | <entry>y<subscript>9</subscript></entry> |
| 2076 | <entry>y<subscript>8</subscript></entry> | 1971 | <entry>y<subscript>8</subscript></entry> |
| 2077 | <entry>y<subscript>7</subscript></entry> | 1972 | <entry>y<subscript>7</subscript></entry> |
| @@ -2087,8 +1982,7 @@ | |||
| 2087 | <entry></entry> | 1982 | <entry></entry> |
| 2088 | <entry></entry> | 1983 | <entry></entry> |
| 2089 | <entry></entry> | 1984 | <entry></entry> |
| 2090 | &dash-ent-10; | 1985 | &dash-ent-22; |
| 2091 | &dash-ent-10; | ||
| 2092 | <entry>v<subscript>9</subscript></entry> | 1986 | <entry>v<subscript>9</subscript></entry> |
| 2093 | <entry>v<subscript>8</subscript></entry> | 1987 | <entry>v<subscript>8</subscript></entry> |
| 2094 | <entry>v<subscript>7</subscript></entry> | 1988 | <entry>v<subscript>7</subscript></entry> |
| @@ -2104,8 +1998,7 @@ | |||
| 2104 | <entry></entry> | 1998 | <entry></entry> |
| 2105 | <entry></entry> | 1999 | <entry></entry> |
| 2106 | <entry></entry> | 2000 | <entry></entry> |
| 2107 | &dash-ent-10; | 2001 | &dash-ent-22; |
| 2108 | &dash-ent-10; | ||
| 2109 | <entry>y<subscript>9</subscript></entry> | 2002 | <entry>y<subscript>9</subscript></entry> |
| 2110 | <entry>y<subscript>8</subscript></entry> | 2003 | <entry>y<subscript>8</subscript></entry> |
| 2111 | <entry>y<subscript>7</subscript></entry> | 2004 | <entry>y<subscript>7</subscript></entry> |
| @@ -2121,8 +2014,7 @@ | |||
| 2121 | <entry></entry> | 2014 | <entry></entry> |
| 2122 | <entry></entry> | 2015 | <entry></entry> |
| 2123 | <entry></entry> | 2016 | <entry></entry> |
| 2124 | &dash-ent-10; | 2017 | &dash-ent-22; |
| 2125 | &dash-ent-10; | ||
| 2126 | <entry>u<subscript>9</subscript></entry> | 2018 | <entry>u<subscript>9</subscript></entry> |
| 2127 | <entry>u<subscript>8</subscript></entry> | 2019 | <entry>u<subscript>8</subscript></entry> |
| 2128 | <entry>u<subscript>7</subscript></entry> | 2020 | <entry>u<subscript>7</subscript></entry> |
| @@ -2138,15 +2030,7 @@ | |||
| 2138 | <entry>V4L2_MBUS_FMT_Y12_1X12</entry> | 2030 | <entry>V4L2_MBUS_FMT_Y12_1X12</entry> |
| 2139 | <entry>0x2013</entry> | 2031 | <entry>0x2013</entry> |
| 2140 | <entry></entry> | 2032 | <entry></entry> |
| 2141 | &dash-ent-10; | 2033 | &dash-ent-20; |
| 2142 | <entry>-</entry> | ||
| 2143 | <entry>-</entry> | ||
| 2144 | <entry>-</entry> | ||
| 2145 | <entry>-</entry> | ||
| 2146 | <entry>-</entry> | ||
| 2147 | <entry>-</entry> | ||
| 2148 | <entry>-</entry> | ||
| 2149 | <entry>-</entry> | ||
| 2150 | <entry>y<subscript>11</subscript></entry> | 2034 | <entry>y<subscript>11</subscript></entry> |
| 2151 | <entry>y<subscript>10</subscript></entry> | 2035 | <entry>y<subscript>10</subscript></entry> |
| 2152 | <entry>y<subscript>9</subscript></entry> | 2036 | <entry>y<subscript>9</subscript></entry> |
| @@ -2164,11 +2048,7 @@ | |||
| 2164 | <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry> | 2048 | <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry> |
| 2165 | <entry>0x200f</entry> | 2049 | <entry>0x200f</entry> |
| 2166 | <entry></entry> | 2050 | <entry></entry> |
| 2167 | &dash-ent-10; | 2051 | &dash-ent-16; |
| 2168 | <entry>-</entry> | ||
| 2169 | <entry>-</entry> | ||
| 2170 | <entry>-</entry> | ||
| 2171 | <entry>-</entry> | ||
| 2172 | <entry>u<subscript>7</subscript></entry> | 2052 | <entry>u<subscript>7</subscript></entry> |
| 2173 | <entry>u<subscript>6</subscript></entry> | 2053 | <entry>u<subscript>6</subscript></entry> |
| 2174 | <entry>u<subscript>5</subscript></entry> | 2054 | <entry>u<subscript>5</subscript></entry> |
| @@ -2190,11 +2070,7 @@ | |||
| 2190 | <entry></entry> | 2070 | <entry></entry> |
| 2191 | <entry></entry> | 2071 | <entry></entry> |
| 2192 | <entry></entry> | 2072 | <entry></entry> |
| 2193 | &dash-ent-10; | 2073 | &dash-ent-16; |
| 2194 | <entry>-</entry> | ||
| 2195 | <entry>-</entry> | ||
| 2196 | <entry>-</entry> | ||
| 2197 | <entry>-</entry> | ||
| 2198 | <entry>v<subscript>7</subscript></entry> | 2074 | <entry>v<subscript>7</subscript></entry> |
| 2199 | <entry>v<subscript>6</subscript></entry> | 2075 | <entry>v<subscript>6</subscript></entry> |
| 2200 | <entry>v<subscript>5</subscript></entry> | 2076 | <entry>v<subscript>5</subscript></entry> |
| @@ -2216,11 +2092,7 @@ | |||
| 2216 | <entry>V4L2_MBUS_FMT_VYUY8_1X16</entry> | 2092 | <entry>V4L2_MBUS_FMT_VYUY8_1X16</entry> |
| 2217 | <entry>0x2010</entry> | 2093 | <entry>0x2010</entry> |
| 2218 | <entry></entry> | 2094 | <entry></entry> |
| 2219 | &dash-ent-10; | 2095 | &dash-ent-16; |
| 2220 | <entry>-</entry> | ||
| 2221 | <entry>-</entry> | ||
| 2222 | <entry>-</entry> | ||
| 2223 | <entry>-</entry> | ||
| 2224 | <entry>v<subscript>7</subscript></entry> | 2096 | <entry>v<subscript>7</subscript></entry> |
| 2225 | <entry>v<subscript>6</subscript></entry> | 2097 | <entry>v<subscript>6</subscript></entry> |
| 2226 | <entry>v<subscript>5</subscript></entry> | 2098 | <entry>v<subscript>5</subscript></entry> |
| @@ -2242,11 +2114,7 @@ | |||
| 2242 | <entry></entry> | 2114 | <entry></entry> |
| 2243 | <entry></entry> | 2115 | <entry></entry> |
| 2244 | <entry></entry> | 2116 | <entry></entry> |
| 2245 | &dash-ent-10; | 2117 | &dash-ent-16; |
| 2246 | <entry>-</entry> | ||
| 2247 | <entry>-</entry> | ||
| 2248 | <entry>-</entry> | ||
| 2249 | <entry>-</entry> | ||
| 2250 | <entry>u<subscript>7</subscript></entry> | 2118 | <entry>u<subscript>7</subscript></entry> |
| 2251 | <entry>u<subscript>6</subscript></entry> | 2119 | <entry>u<subscript>6</subscript></entry> |
| 2252 | <entry>u<subscript>5</subscript></entry> | 2120 | <entry>u<subscript>5</subscript></entry> |
| @@ -2268,11 +2136,7 @@ | |||
| 2268 | <entry>V4L2_MBUS_FMT_YUYV8_1X16</entry> | 2136 | <entry>V4L2_MBUS_FMT_YUYV8_1X16</entry> |
| 2269 | <entry>0x2011</entry> | 2137 | <entry>0x2011</entry> |
| 2270 | <entry></entry> | 2138 | <entry></entry> |
| 2271 | &dash-ent-10; | 2139 | &dash-ent-16; |
| 2272 | <entry>-</entry> | ||
| 2273 | <entry>-</entry> | ||
| 2274 | <entry>-</entry> | ||
| 2275 | <entry>-</entry> | ||
| 2276 | <entry>y<subscript>7</subscript></entry> | 2140 | <entry>y<subscript>7</subscript></entry> |
| 2277 | <entry>y<subscript>6</subscript></entry> | 2141 | <entry>y<subscript>6</subscript></entry> |
| 2278 | <entry>y<subscript>5</subscript></entry> | 2142 | <entry>y<subscript>5</subscript></entry> |
| @@ -2294,11 +2158,7 @@ | |||
| 2294 | <entry></entry> | 2158 | <entry></entry> |
| 2295 | <entry></entry> | 2159 | <entry></entry> |
| 2296 | <entry></entry> | 2160 | <entry></entry> |
| 2297 | &dash-ent-10; | 2161 | &dash-ent-16; |
| 2298 | <entry>-</entry> | ||
| 2299 | <entry>-</entry> | ||
| 2300 | <entry>-</entry> | ||
| 2301 | <entry>-</entry> | ||
| 2302 | <entry>y<subscript>7</subscript></entry> | 2162 | <entry>y<subscript>7</subscript></entry> |
| 2303 | <entry>y<subscript>6</subscript></entry> | 2163 | <entry>y<subscript>6</subscript></entry> |
| 2304 | <entry>y<subscript>5</subscript></entry> | 2164 | <entry>y<subscript>5</subscript></entry> |
| @@ -2320,11 +2180,7 @@ | |||
| 2320 | <entry>V4L2_MBUS_FMT_YVYU8_1X16</entry> | 2180 | <entry>V4L2_MBUS_FMT_YVYU8_1X16</entry> |
| 2321 | <entry>0x2012</entry> | 2181 | <entry>0x2012</entry> |
| 2322 | <entry></entry> | 2182 | <entry></entry> |
| 2323 | &dash-ent-10; | 2183 | &dash-ent-16; |
| 2324 | <entry>-</entry> | ||
| 2325 | <entry>-</entry> | ||
| 2326 | <entry>-</entry> | ||
| 2327 | <entry>-</entry> | ||
| 2328 | <entry>y<subscript>7</subscript></entry> | 2184 | <entry>y<subscript>7</subscript></entry> |
| 2329 | <entry>y<subscript>6</subscript></entry> | 2185 | <entry>y<subscript>6</subscript></entry> |
| 2330 | <entry>y<subscript>5</subscript></entry> | 2186 | <entry>y<subscript>5</subscript></entry> |
| @@ -2346,11 +2202,7 @@ | |||
| 2346 | <entry></entry> | 2202 | <entry></entry> |
| 2347 | <entry></entry> | 2203 | <entry></entry> |
| 2348 | <entry></entry> | 2204 | <entry></entry> |
| 2349 | &dash-ent-10; | 2205 | &dash-ent-16; |
| 2350 | <entry>-</entry> | ||
| 2351 | <entry>-</entry> | ||
| 2352 | <entry>-</entry> | ||
| 2353 | <entry>-</entry> | ||
| 2354 | <entry>y<subscript>7</subscript></entry> | 2206 | <entry>y<subscript>7</subscript></entry> |
| 2355 | <entry>y<subscript>6</subscript></entry> | 2207 | <entry>y<subscript>6</subscript></entry> |
| 2356 | <entry>y<subscript>5</subscript></entry> | 2208 | <entry>y<subscript>5</subscript></entry> |
| @@ -2372,10 +2224,7 @@ | |||
| 2372 | <entry>V4L2_MBUS_FMT_YDYUYDYV8_1X16</entry> | 2224 | <entry>V4L2_MBUS_FMT_YDYUYDYV8_1X16</entry> |
| 2373 | <entry>0x2014</entry> | 2225 | <entry>0x2014</entry> |
| 2374 | <entry></entry> | 2226 | <entry></entry> |
| 2375 | <entry>-</entry> | 2227 | &dash-ent-16; |
| 2376 | <entry>-</entry> | ||
| 2377 | <entry>-</entry> | ||
| 2378 | <entry>-</entry> | ||
| 2379 | <entry>y<subscript>7</subscript></entry> | 2228 | <entry>y<subscript>7</subscript></entry> |
| 2380 | <entry>y<subscript>6</subscript></entry> | 2229 | <entry>y<subscript>6</subscript></entry> |
| 2381 | <entry>y<subscript>5</subscript></entry> | 2230 | <entry>y<subscript>5</subscript></entry> |
| @@ -2397,10 +2246,7 @@ | |||
| 2397 | <entry></entry> | 2246 | <entry></entry> |
| 2398 | <entry></entry> | 2247 | <entry></entry> |
| 2399 | <entry></entry> | 2248 | <entry></entry> |
| 2400 | <entry>-</entry> | 2249 | &dash-ent-16; |
| 2401 | <entry>-</entry> | ||
| 2402 | <entry>-</entry> | ||
| 2403 | <entry>-</entry> | ||
| 2404 | <entry>y<subscript>7</subscript></entry> | 2250 | <entry>y<subscript>7</subscript></entry> |
| 2405 | <entry>y<subscript>6</subscript></entry> | 2251 | <entry>y<subscript>6</subscript></entry> |
| 2406 | <entry>y<subscript>5</subscript></entry> | 2252 | <entry>y<subscript>5</subscript></entry> |
| @@ -2422,10 +2268,7 @@ | |||
| 2422 | <entry></entry> | 2268 | <entry></entry> |
| 2423 | <entry></entry> | 2269 | <entry></entry> |
| 2424 | <entry></entry> | 2270 | <entry></entry> |
| 2425 | <entry>-</entry> | 2271 | &dash-ent-16; |
| 2426 | <entry>-</entry> | ||
| 2427 | <entry>-</entry> | ||
| 2428 | <entry>-</entry> | ||
| 2429 | <entry>y<subscript>7</subscript></entry> | 2272 | <entry>y<subscript>7</subscript></entry> |
| 2430 | <entry>y<subscript>6</subscript></entry> | 2273 | <entry>y<subscript>6</subscript></entry> |
| 2431 | <entry>y<subscript>5</subscript></entry> | 2274 | <entry>y<subscript>5</subscript></entry> |
| @@ -2447,10 +2290,7 @@ | |||
| 2447 | <entry></entry> | 2290 | <entry></entry> |
| 2448 | <entry></entry> | 2291 | <entry></entry> |
| 2449 | <entry></entry> | 2292 | <entry></entry> |
| 2450 | <entry>-</entry> | 2293 | &dash-ent-16; |
| 2451 | <entry>-</entry> | ||
| 2452 | <entry>-</entry> | ||
| 2453 | <entry>-</entry> | ||
| 2454 | <entry>y<subscript>7</subscript></entry> | 2294 | <entry>y<subscript>7</subscript></entry> |
| 2455 | <entry>y<subscript>6</subscript></entry> | 2295 | <entry>y<subscript>6</subscript></entry> |
| 2456 | <entry>y<subscript>5</subscript></entry> | 2296 | <entry>y<subscript>5</subscript></entry> |
| @@ -2472,7 +2312,7 @@ | |||
| 2472 | <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry> | 2312 | <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry> |
| 2473 | <entry>0x200d</entry> | 2313 | <entry>0x200d</entry> |
| 2474 | <entry></entry> | 2314 | <entry></entry> |
| 2475 | &dash-ent-10; | 2315 | &dash-ent-12; |
| 2476 | <entry>y<subscript>9</subscript></entry> | 2316 | <entry>y<subscript>9</subscript></entry> |
| 2477 | <entry>y<subscript>8</subscript></entry> | 2317 | <entry>y<subscript>8</subscript></entry> |
| 2478 | <entry>y<subscript>7</subscript></entry> | 2318 | <entry>y<subscript>7</subscript></entry> |
| @@ -2498,7 +2338,7 @@ | |||
| 2498 | <entry></entry> | 2338 | <entry></entry> |
| 2499 | <entry></entry> | 2339 | <entry></entry> |
| 2500 | <entry></entry> | 2340 | <entry></entry> |
| 2501 | &dash-ent-10; | 2341 | &dash-ent-12; |
| 2502 | <entry>y<subscript>9</subscript></entry> | 2342 | <entry>y<subscript>9</subscript></entry> |
| 2503 | <entry>y<subscript>8</subscript></entry> | 2343 | <entry>y<subscript>8</subscript></entry> |
| 2504 | <entry>y<subscript>7</subscript></entry> | 2344 | <entry>y<subscript>7</subscript></entry> |
| @@ -2524,7 +2364,7 @@ | |||
| 2524 | <entry>V4L2_MBUS_FMT_YVYU10_1X20</entry> | 2364 | <entry>V4L2_MBUS_FMT_YVYU10_1X20</entry> |
| 2525 | <entry>0x200e</entry> | 2365 | <entry>0x200e</entry> |
| 2526 | <entry></entry> | 2366 | <entry></entry> |
| 2527 | &dash-ent-10; | 2367 | &dash-ent-12; |
| 2528 | <entry>y<subscript>9</subscript></entry> | 2368 | <entry>y<subscript>9</subscript></entry> |
| 2529 | <entry>y<subscript>8</subscript></entry> | 2369 | <entry>y<subscript>8</subscript></entry> |
| 2530 | <entry>y<subscript>7</subscript></entry> | 2370 | <entry>y<subscript>7</subscript></entry> |
| @@ -2550,7 +2390,7 @@ | |||
| 2550 | <entry></entry> | 2390 | <entry></entry> |
| 2551 | <entry></entry> | 2391 | <entry></entry> |
| 2552 | <entry></entry> | 2392 | <entry></entry> |
| 2553 | &dash-ent-10; | 2393 | &dash-ent-12; |
| 2554 | <entry>y<subscript>9</subscript></entry> | 2394 | <entry>y<subscript>9</subscript></entry> |
| 2555 | <entry>y<subscript>8</subscript></entry> | 2395 | <entry>y<subscript>8</subscript></entry> |
| 2556 | <entry>y<subscript>7</subscript></entry> | 2396 | <entry>y<subscript>7</subscript></entry> |
| @@ -2574,8 +2414,10 @@ | |||
| 2574 | </row> | 2414 | </row> |
| 2575 | <row id="V4L2-MBUS-FMT-YUV10-1X30"> | 2415 | <row id="V4L2-MBUS-FMT-YUV10-1X30"> |
| 2576 | <entry>V4L2_MBUS_FMT_YUV10_1X30</entry> | 2416 | <entry>V4L2_MBUS_FMT_YUV10_1X30</entry> |
| 2577 | <entry>0x2014</entry> | 2417 | <entry>0x2016</entry> |
| 2578 | <entry></entry> | 2418 | <entry></entry> |
| 2419 | <entry>-</entry> | ||
| 2420 | <entry>-</entry> | ||
| 2579 | <entry>y<subscript>9</subscript></entry> | 2421 | <entry>y<subscript>9</subscript></entry> |
| 2580 | <entry>y<subscript>8</subscript></entry> | 2422 | <entry>y<subscript>8</subscript></entry> |
| 2581 | <entry>y<subscript>7</subscript></entry> | 2423 | <entry>y<subscript>7</subscript></entry> |
| @@ -2607,6 +2449,43 @@ | |||
| 2607 | <entry>v<subscript>1</subscript></entry> | 2449 | <entry>v<subscript>1</subscript></entry> |
| 2608 | <entry>v<subscript>0</subscript></entry> | 2450 | <entry>v<subscript>0</subscript></entry> |
| 2609 | </row> | 2451 | </row> |
| 2452 | <row id="V4L2-MBUS-FMT-AYUV8-1X32"> | ||
| 2453 | <entry>V4L2_MBUS_FMT_AYUV8_1X32</entry> | ||
| 2454 | <entry>0x2017</entry> | ||
| 2455 | <entry></entry> | ||
| 2456 | <entry>a<subscript>7</subscript></entry> | ||
| 2457 | <entry>a<subscript>6</subscript></entry> | ||
| 2458 | <entry>a<subscript>5</subscript></entry> | ||
| 2459 | <entry>a<subscript>4</subscript></entry> | ||
| 2460 | <entry>a<subscript>3</subscript></entry> | ||
| 2461 | <entry>a<subscript>2</subscript></entry> | ||
| 2462 | <entry>a<subscript>1</subscript></entry> | ||
| 2463 | <entry>a<subscript>0</subscript></entry> | ||
| 2464 | <entry>y<subscript>7</subscript></entry> | ||
| 2465 | <entry>y<subscript>6</subscript></entry> | ||
| 2466 | <entry>y<subscript>5</subscript></entry> | ||
| 2467 | <entry>y<subscript>4</subscript></entry> | ||
| 2468 | <entry>y<subscript>3</subscript></entry> | ||
| 2469 | <entry>y<subscript>2</subscript></entry> | ||
| 2470 | <entry>y<subscript>1</subscript></entry> | ||
| 2471 | <entry>y<subscript>0</subscript></entry> | ||
| 2472 | <entry>u<subscript>7</subscript></entry> | ||
| 2473 | <entry>u<subscript>6</subscript></entry> | ||
| 2474 | <entry>u<subscript>5</subscript></entry> | ||
| 2475 | <entry>u<subscript>4</subscript></entry> | ||
| 2476 | <entry>u<subscript>3</subscript></entry> | ||
| 2477 | <entry>u<subscript>2</subscript></entry> | ||
| 2478 | <entry>u<subscript>1</subscript></entry> | ||
| 2479 | <entry>u<subscript>0</subscript></entry> | ||
| 2480 | <entry>v<subscript>7</subscript></entry> | ||
| 2481 | <entry>v<subscript>6</subscript></entry> | ||
| 2482 | <entry>v<subscript>5</subscript></entry> | ||
| 2483 | <entry>v<subscript>4</subscript></entry> | ||
| 2484 | <entry>v<subscript>3</subscript></entry> | ||
| 2485 | <entry>v<subscript>2</subscript></entry> | ||
| 2486 | <entry>v<subscript>1</subscript></entry> | ||
| 2487 | <entry>v<subscript>0</subscript></entry> | ||
| 2488 | </row> | ||
| 2610 | </tbody> | 2489 | </tbody> |
| 2611 | </tgroup> | 2490 | </tgroup> |
| 2612 | </table> | 2491 | </table> |
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index cd9943672434..9b700a5f4df7 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml | |||
| @@ -62,18 +62,29 @@ addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter | |||
| 62 | control over buffers is required. This ioctl can be called multiple times to | 62 | control over buffers is required. This ioctl can be called multiple times to |
| 63 | create buffers of different sizes.</para> | 63 | create buffers of different sizes.</para> |
| 64 | 64 | ||
| 65 | <para>To allocate device buffers applications initialize relevant fields of | 65 | <para>To allocate the device buffers applications must initialize the |
| 66 | the <structname>v4l2_create_buffers</structname> structure. They set the | 66 | relevant fields of the <structname>v4l2_create_buffers</structname> structure. |
| 67 | <structfield>type</structfield> field in the | 67 | The <structfield>count</structfield> field must be set to the number of |
| 68 | &v4l2-format; structure, embedded in this | 68 | requested buffers, the <structfield>memory</structfield> field specifies the |
| 69 | structure, to the respective stream or buffer type. | 69 | requested I/O method and the <structfield>reserved</structfield> array must be |
| 70 | <structfield>count</structfield> must be set to the number of required buffers. | 70 | zeroed.</para> |
| 71 | <structfield>memory</structfield> specifies the required I/O method. The | 71 | |
| 72 | <structfield>format</structfield> field shall typically be filled in using | 72 | <para>The <structfield>format</structfield> field specifies the image format |
| 73 | either the <constant>VIDIOC_TRY_FMT</constant> or | 73 | that the buffers must be able to handle. The application has to fill in this |
| 74 | <constant>VIDIOC_G_FMT</constant> ioctl(). Additionally, applications can adjust | 74 | &v4l2-format;. Usually this will be done using the |
| 75 | <structfield>sizeimage</structfield> fields to fit their specific needs. The | 75 | <constant>VIDIOC_TRY_FMT</constant> or <constant>VIDIOC_G_FMT</constant> ioctl() |
| 76 | <structfield>reserved</structfield> array must be zeroed.</para> | 76 | to ensure that the requested format is supported by the driver. Unsupported |
| 77 | formats will result in an error.</para> | ||
| 78 | |||
| 79 | <para>The buffers created by this ioctl will have as minimum size the size | ||
| 80 | defined by the <structfield>format.pix.sizeimage</structfield> field. If the | ||
| 81 | <structfield>format.pix.sizeimage</structfield> field is less than the minimum | ||
| 82 | required for the given format, then <structfield>sizeimage</structfield> will be | ||
| 83 | increased by the driver to that minimum to allocate the buffers. If it is | ||
| 84 | larger, then the value will be used as-is. The same applies to the | ||
| 85 | <structfield>sizeimage</structfield> field of the | ||
| 86 | <structname>v4l2_plane_pix_format</structname> structure in the case of | ||
| 87 | multiplanar formats.</para> | ||
| 77 | 88 | ||
| 78 | <para>When the ioctl is called with a pointer to this structure the driver | 89 | <para>When the ioctl is called with a pointer to this structure the driver |
| 79 | will attempt to allocate up to the requested number of buffers and store the | 90 | will attempt to allocate up to the requested number of buffers and store the |
| @@ -144,9 +155,9 @@ mapped</link> I/O.</para> | |||
| 144 | <varlistentry> | 155 | <varlistentry> |
| 145 | <term><errorcode>EINVAL</errorcode></term> | 156 | <term><errorcode>EINVAL</errorcode></term> |
| 146 | <listitem> | 157 | <listitem> |
| 147 | <para>The buffer type (<structfield>type</structfield> field) or the | 158 | <para>The buffer type (<structfield>format.type</structfield> field), |
| 148 | requested I/O method (<structfield>memory</structfield>) is not | 159 | requested I/O method (<structfield>memory</structfield>) or format |
| 149 | supported.</para> | 160 | (<structfield>format</structfield> field) is not valid.</para> |
| 150 | </listitem> | 161 | </listitem> |
| 151 | </varlistentry> | 162 | </varlistentry> |
| 152 | </variablelist> | 163 | </variablelist> |
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml index 72369707bd77..c4336577ff06 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml | |||
| @@ -156,19 +156,19 @@ bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_H | |||
| 156 | <entry>__u32</entry> | 156 | <entry>__u32</entry> |
| 157 | <entry><structfield>il_vfrontporch</structfield></entry> | 157 | <entry><structfield>il_vfrontporch</structfield></entry> |
| 158 | <entry>Vertical front porch in lines for the even field (aka field 2) of | 158 | <entry>Vertical front porch in lines for the even field (aka field 2) of |
| 159 | interlaced field formats.</entry> | 159 | interlaced field formats. Must be 0 for progressive formats.</entry> |
| 160 | </row> | 160 | </row> |
| 161 | <row> | 161 | <row> |
| 162 | <entry>__u32</entry> | 162 | <entry>__u32</entry> |
| 163 | <entry><structfield>il_vsync</structfield></entry> | 163 | <entry><structfield>il_vsync</structfield></entry> |
| 164 | <entry>Vertical sync length in lines for the even field (aka field 2) of | 164 | <entry>Vertical sync length in lines for the even field (aka field 2) of |
| 165 | interlaced field formats.</entry> | 165 | interlaced field formats. Must be 0 for progressive formats.</entry> |
| 166 | </row> | 166 | </row> |
| 167 | <row> | 167 | <row> |
| 168 | <entry>__u32</entry> | 168 | <entry>__u32</entry> |
| 169 | <entry><structfield>il_vbackporch</structfield></entry> | 169 | <entry><structfield>il_vbackporch</structfield></entry> |
| 170 | <entry>Vertical back porch in lines for the even field (aka field 2) of | 170 | <entry>Vertical back porch in lines for the even field (aka field 2) of |
| 171 | interlaced field formats.</entry> | 171 | interlaced field formats. Must be 0 for progressive formats.</entry> |
| 172 | </row> | 172 | </row> |
| 173 | <row> | 173 | <row> |
| 174 | <entry>__u32</entry> | 174 | <entry>__u32</entry> |
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml b/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml index 48748499c097..098ff483802e 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml | |||
| @@ -92,8 +92,8 @@ to add them.</para> | |||
| 92 | <entry>int</entry> | 92 | <entry>int</entry> |
| 93 | <entry><structfield>quality</structfield></entry> | 93 | <entry><structfield>quality</structfield></entry> |
| 94 | <entry>Deprecated. If <link linkend="jpeg-quality-control"><constant> | 94 | <entry>Deprecated. If <link linkend="jpeg-quality-control"><constant> |
| 95 | V4L2_CID_JPEG_IMAGE_QUALITY</constant></link> control is exposed by | 95 | V4L2_CID_JPEG_COMPRESSION_QUALITY</constant></link> control is exposed |
| 96 | a driver applications should use it instead and ignore this field. | 96 | by a driver applications should use it instead and ignore this field. |
| 97 | </entry> | 97 | </entry> |
| 98 | </row> | 98 | </row> |
| 99 | <row> | 99 | <row> |
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl index 9c92bb879b6d..4c8d282545a2 100644 --- a/Documentation/DocBook/media_api.tmpl +++ b/Documentation/DocBook/media_api.tmpl | |||
| @@ -22,8 +22,14 @@ | |||
| 22 | 22 | ||
| 23 | <!-- LinuxTV v4l-dvb repository. --> | 23 | <!-- LinuxTV v4l-dvb repository. --> |
| 24 | <!ENTITY v4l-dvb "<ulink url='http://linuxtv.org/repo/'>http://linuxtv.org/repo/</ulink>"> | 24 | <!ENTITY v4l-dvb "<ulink url='http://linuxtv.org/repo/'>http://linuxtv.org/repo/</ulink>"> |
| 25 | <!ENTITY dash-ent-8 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 25 | <!ENTITY dash-ent-10 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | 26 | <!ENTITY dash-ent-10 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> |
| 27 | <!ENTITY dash-ent-12 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 28 | <!ENTITY dash-ent-14 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 26 | <!ENTITY dash-ent-16 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | 29 | <!ENTITY dash-ent-16 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> |
| 30 | <!ENTITY dash-ent-20 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 31 | <!ENTITY dash-ent-22 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 32 | <!ENTITY dash-ent-24 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>"> | ||
| 27 | ]> | 33 | ]> |
| 28 | 34 | ||
| 29 | <book id="media_api"> | 35 | <book id="media_api"> |
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7343.txt b/Documentation/devicetree/bindings/media/i2c/adv7343.txt new file mode 100644 index 000000000000..5653bc2428b8 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/adv7343.txt | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | * Analog Devices adv7343 video encoder | ||
| 2 | |||
| 3 | The ADV7343 are high speed, digital-to-analog video encoders in a 64-lead LQFP | ||
| 4 | package. Six high speed, 3.3 V, 11-bit video DACs provide support for composite | ||
| 5 | (CVBS), S-Video (Y-C), and component (YPrPb/RGB) analog outputs in standard | ||
| 6 | definition (SD), enhanced definition (ED), or high definition (HD) video | ||
| 7 | formats. | ||
| 8 | |||
| 9 | Required Properties : | ||
| 10 | - compatible: Must be "adi,adv7343" | ||
| 11 | |||
| 12 | Optional Properties : | ||
| 13 | - adi,power-mode-sleep-mode: on enable the current consumption is reduced to | ||
| 14 | micro ampere level. All DACs and the internal PLL | ||
| 15 | circuit are disabled. | ||
| 16 | - adi,power-mode-pll-ctrl: PLL and oversampling control. This control allows | ||
| 17 | internal PLL 1 circuit to be powered down and the | ||
| 18 | oversampling to be switched off. | ||
| 19 | - ad,adv7343-power-mode-dac: array configuring the power on/off DAC's 1..6, | ||
| 20 | 0 = OFF and 1 = ON, Default value when this | ||
| 21 | property is not specified is <0 0 0 0 0 0>. | ||
| 22 | - ad,adv7343-sd-config-dac-out: array configure SD DAC Output's 1 and 2, 0 = OFF | ||
| 23 | and 1 = ON, Default value when this property is | ||
| 24 | not specified is <0 0>. | ||
| 25 | |||
| 26 | Example: | ||
| 27 | |||
| 28 | i2c0@1c22000 { | ||
| 29 | ... | ||
| 30 | ... | ||
| 31 | |||
| 32 | adv7343@2a { | ||
| 33 | compatible = "adi,adv7343"; | ||
| 34 | reg = <0x2a>; | ||
| 35 | |||
| 36 | port { | ||
| 37 | adv7343_1: endpoint { | ||
| 38 | adi,power-mode-sleep-mode; | ||
| 39 | adi,power-mode-pll-ctrl; | ||
| 40 | /* Use DAC1..3, DAC6 */ | ||
| 41 | adi,dac-enable = <1 1 1 0 0 1>; | ||
| 42 | /* Use SD DAC output 1 */ | ||
| 43 | adi,sd-dac-enable = <1 0>; | ||
| 44 | }; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | ... | ||
| 48 | }; | ||
diff --git a/Documentation/devicetree/bindings/media/i2c/ths8200.txt b/Documentation/devicetree/bindings/media/i2c/ths8200.txt new file mode 100644 index 000000000000..285f6ae7dfa9 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ths8200.txt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | * Texas Instruments THS8200 video encoder | ||
| 2 | |||
| 3 | The ths8200 device is a digital to analog converter used in DVD players, video | ||
| 4 | recorders, set-top boxes. | ||
| 5 | |||
| 6 | Required Properties : | ||
| 7 | - compatible : value must be "ti,ths8200" | ||
| 8 | |||
| 9 | Example: | ||
| 10 | |||
| 11 | i2c0@1c22000 { | ||
| 12 | ... | ||
| 13 | ... | ||
| 14 | ths8200@5c { | ||
| 15 | compatible = "ti,ths8200"; | ||
| 16 | reg = <0x5c>; | ||
| 17 | }; | ||
| 18 | ... | ||
| 19 | }; | ||
diff --git a/Documentation/devicetree/bindings/media/i2c/tvp7002.txt b/Documentation/devicetree/bindings/media/i2c/tvp7002.txt new file mode 100644 index 000000000000..5f28b5d9abcc --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp7002.txt | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | * Texas Instruments TV7002 video decoder | ||
| 2 | |||
| 3 | The TVP7002 device supports digitizing of video and graphics signal in RGB and | ||
| 4 | YPbPr color space. | ||
| 5 | |||
| 6 | Required Properties : | ||
| 7 | - compatible : Must be "ti,tvp7002" | ||
| 8 | |||
| 9 | Optional Properties: | ||
| 10 | - hsync-active: HSYNC Polarity configuration for the bus. Default value when | ||
| 11 | this property is not specified is <0>. | ||
| 12 | |||
| 13 | - vsync-active: VSYNC Polarity configuration for the bus. Default value when | ||
| 14 | this property is not specified is <0>. | ||
| 15 | |||
| 16 | - pclk-sample: Clock polarity of the bus. Default value when this property is | ||
| 17 | not specified is <0>. | ||
| 18 | |||
| 19 | - sync-on-green-active: Active state of Sync-on-green signal property of the | ||
| 20 | endpoint. | ||
| 21 | 0 = Normal Operation (Active Low, Default) | ||
| 22 | 1 = Inverted operation | ||
| 23 | |||
| 24 | - field-even-active: Active-high Field ID output polarity control of the bus. | ||
| 25 | Under normal operation, the field ID output is set to logic 1 for an odd field | ||
| 26 | (field 1) and set to logic 0 for an even field (field 0). | ||
| 27 | 0 = Normal Operation (Active Low, Default) | ||
| 28 | 1 = FID output polarity inverted | ||
| 29 | |||
| 30 | For further reading of port node refer Documentation/devicetree/bindings/media/ | ||
| 31 | video-interfaces.txt. | ||
| 32 | |||
| 33 | Example: | ||
| 34 | |||
| 35 | i2c0@1c22000 { | ||
| 36 | ... | ||
| 37 | ... | ||
| 38 | tvp7002@5c { | ||
| 39 | compatible = "ti,tvp7002"; | ||
| 40 | reg = <0x5c>; | ||
| 41 | |||
| 42 | port { | ||
| 43 | tvp7002_1: endpoint { | ||
| 44 | hsync-active = <1>; | ||
| 45 | vsync-active = <1>; | ||
| 46 | pclk-sample = <0>; | ||
| 47 | sync-on-green-active = <1>; | ||
| 48 | field-even-active = <0>; | ||
| 49 | }; | ||
| 50 | }; | ||
| 51 | }; | ||
| 52 | ... | ||
| 53 | }; | ||
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt index df37b0230c75..36bd2d6725c8 100644 --- a/Documentation/devicetree/bindings/media/s5p-mfc.txt +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt | |||
| @@ -10,6 +10,7 @@ Required properties: | |||
| 10 | - compatible : value should be either one among the following | 10 | - compatible : value should be either one among the following |
| 11 | (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs | 11 | (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs |
| 12 | (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs | 12 | (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs |
| 13 | (b) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC | ||
| 13 | 14 | ||
| 14 | - reg : Physical base address of the IP registers and length of memory | 15 | - reg : Physical base address of the IP registers and length of memory |
| 15 | mapped region. | 16 | mapped region. |
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt index e022d2dc4962..ce719f89dd1c 100644 --- a/Documentation/devicetree/bindings/media/video-interfaces.txt +++ b/Documentation/devicetree/bindings/media/video-interfaces.txt | |||
| @@ -88,6 +88,8 @@ Optional endpoint properties | |||
| 88 | - field-even-active: field signal level during the even field data transmission. | 88 | - field-even-active: field signal level during the even field data transmission. |
| 89 | - pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock | 89 | - pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock |
| 90 | signal. | 90 | signal. |
| 91 | - sync-on-green-active: active state of Sync-on-green (SoG) signal, 0/1 for | ||
| 92 | LOW/HIGH respectively. | ||
| 91 | - data-lanes: an array of physical data lane indexes. Position of an entry | 93 | - data-lanes: an array of physical data lane indexes. Position of an entry |
| 92 | determines the logical lane number, while the value of an entry indicates | 94 | determines the logical lane number, while the value of an entry indicates |
| 93 | physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have | 95 | physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have |
diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt index 676f87366025..06cf3ac83631 100644 --- a/Documentation/video4linux/v4l2-controls.txt +++ b/Documentation/video4linux/v4l2-controls.txt | |||
| @@ -124,26 +124,27 @@ You add non-menu controls by calling v4l2_ctrl_new_std: | |||
| 124 | const struct v4l2_ctrl_ops *ops, | 124 | const struct v4l2_ctrl_ops *ops, |
| 125 | u32 id, s32 min, s32 max, u32 step, s32 def); | 125 | u32 id, s32 min, s32 max, u32 step, s32 def); |
| 126 | 126 | ||
| 127 | Menu controls are added by calling v4l2_ctrl_new_std_menu: | 127 | Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu: |
| 128 | 128 | ||
| 129 | struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | 129 | struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, |
| 130 | const struct v4l2_ctrl_ops *ops, | 130 | const struct v4l2_ctrl_ops *ops, |
| 131 | u32 id, s32 max, s32 skip_mask, s32 def); | 131 | u32 id, s32 max, s32 skip_mask, s32 def); |
| 132 | 132 | ||
| 133 | Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu: | 133 | Menu controls with a driver specific menu are added by calling |
| 134 | v4l2_ctrl_new_std_menu_items: | ||
| 135 | |||
| 136 | struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items( | ||
| 137 | struct v4l2_ctrl_handler *hdl, | ||
| 138 | const struct v4l2_ctrl_ops *ops, u32 id, s32 max, | ||
| 139 | s32 skip_mask, s32 def, const char * const *qmenu); | ||
| 140 | |||
| 141 | Integer menu controls with a driver specific menu can be added by calling | ||
| 142 | v4l2_ctrl_new_int_menu: | ||
| 134 | 143 | ||
| 135 | struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, | 144 | struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, |
| 136 | const struct v4l2_ctrl_ops *ops, | 145 | const struct v4l2_ctrl_ops *ops, |
| 137 | u32 id, s32 max, s32 def, const s64 *qmenu_int); | 146 | u32 id, s32 max, s32 def, const s64 *qmenu_int); |
| 138 | 147 | ||
| 139 | Standard menu controls with a driver specific menu are added by calling | ||
| 140 | v4l2_ctrl_new_std_menu_items: | ||
| 141 | |||
| 142 | struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items( | ||
| 143 | struct v4l2_ctrl_handler *hdl, | ||
| 144 | const struct v4l2_ctrl_ops *ops, u32 id, s32 max, | ||
| 145 | s32 skip_mask, s32 def, const char * const *qmenu); | ||
| 146 | |||
| 147 | These functions are typically called right after the v4l2_ctrl_handler_init: | 148 | These functions are typically called right after the v4l2_ctrl_handler_init: |
| 148 | 149 | ||
| 149 | static const s64 exp_bias_qmenu[] = { | 150 | static const s64 exp_bias_qmenu[] = { |
diff --git a/MAINTAINERS b/MAINTAINERS index 4bb5689000f8..69d42b6ff28a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -580,12 +580,24 @@ L: linux-media@vger.kernel.org | |||
| 580 | S: Maintained | 580 | S: Maintained |
| 581 | F: drivers/media/i2c/ad9389b* | 581 | F: drivers/media/i2c/ad9389b* |
| 582 | 582 | ||
| 583 | ANALOG DEVICES INC ADV7511 DRIVER | ||
| 584 | M: Hans Verkuil <hans.verkuil@cisco.com> | ||
| 585 | L: linux-media@vger.kernel.org | ||
| 586 | S: Maintained | ||
| 587 | F: drivers/media/i2c/adv7511* | ||
| 588 | |||
| 583 | ANALOG DEVICES INC ADV7604 DRIVER | 589 | ANALOG DEVICES INC ADV7604 DRIVER |
| 584 | M: Hans Verkuil <hans.verkuil@cisco.com> | 590 | M: Hans Verkuil <hans.verkuil@cisco.com> |
| 585 | L: linux-media@vger.kernel.org | 591 | L: linux-media@vger.kernel.org |
| 586 | S: Maintained | 592 | S: Maintained |
| 587 | F: drivers/media/i2c/adv7604* | 593 | F: drivers/media/i2c/adv7604* |
| 588 | 594 | ||
| 595 | ANALOG DEVICES INC ADV7842 DRIVER | ||
| 596 | M: Hans Verkuil <hans.verkuil@cisco.com> | ||
| 597 | L: linux-media@vger.kernel.org | ||
| 598 | S: Maintained | ||
| 599 | F: drivers/media/i2c/adv7842* | ||
| 600 | |||
| 589 | ANALOG DEVICES INC ASOC CODEC DRIVERS | 601 | ANALOG DEVICES INC ASOC CODEC DRIVERS |
| 590 | M: Lars-Peter Clausen <lars@metafoo.de> | 602 | M: Lars-Peter Clausen <lars@metafoo.de> |
| 591 | L: device-drivers-devel@blackfin.uclinux.org | 603 | L: device-drivers-devel@blackfin.uclinux.org |
| @@ -639,6 +651,12 @@ S: Maintained | |||
| 639 | F: drivers/net/appletalk/ | 651 | F: drivers/net/appletalk/ |
| 640 | F: net/appletalk/ | 652 | F: net/appletalk/ |
| 641 | 653 | ||
| 654 | APTINA CAMERA SENSOR PLL | ||
| 655 | M: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> | ||
| 656 | L: linux-media@vger.kernel.org | ||
| 657 | S: Maintained | ||
| 658 | F: drivers/media/i2c/aptina-pll.* | ||
| 659 | |||
| 642 | ARASAN COMPACT FLASH PATA CONTROLLER | 660 | ARASAN COMPACT FLASH PATA CONTROLLER |
| 643 | M: Viresh Kumar <viresh.linux@gmail.com> | 661 | M: Viresh Kumar <viresh.linux@gmail.com> |
| 644 | L: linux-ide@vger.kernel.org | 662 | L: linux-ide@vger.kernel.org |
| @@ -5518,7 +5536,7 @@ L: platform-driver-x86@vger.kernel.org | |||
| 5518 | S: Supported | 5536 | S: Supported |
| 5519 | F: drivers/platform/x86/msi-wmi.c | 5537 | F: drivers/platform/x86/msi-wmi.c |
| 5520 | 5538 | ||
| 5521 | MT9M032 SENSOR DRIVER | 5539 | MT9M032 APTINA SENSOR DRIVER |
| 5522 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 5540 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 5523 | L: linux-media@vger.kernel.org | 5541 | L: linux-media@vger.kernel.org |
| 5524 | T: git git://linuxtv.org/media_tree.git | 5542 | T: git git://linuxtv.org/media_tree.git |
| @@ -5526,7 +5544,7 @@ S: Maintained | |||
| 5526 | F: drivers/media/i2c/mt9m032.c | 5544 | F: drivers/media/i2c/mt9m032.c |
| 5527 | F: include/media/mt9m032.h | 5545 | F: include/media/mt9m032.h |
| 5528 | 5546 | ||
| 5529 | MT9P031 SENSOR DRIVER | 5547 | MT9P031 APTINA CAMERA SENSOR |
| 5530 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 5548 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 5531 | L: linux-media@vger.kernel.org | 5549 | L: linux-media@vger.kernel.org |
| 5532 | T: git git://linuxtv.org/media_tree.git | 5550 | T: git git://linuxtv.org/media_tree.git |
| @@ -5534,7 +5552,7 @@ S: Maintained | |||
| 5534 | F: drivers/media/i2c/mt9p031.c | 5552 | F: drivers/media/i2c/mt9p031.c |
| 5535 | F: include/media/mt9p031.h | 5553 | F: include/media/mt9p031.h |
| 5536 | 5554 | ||
| 5537 | MT9T001 SENSOR DRIVER | 5555 | MT9T001 APTINA CAMERA SENSOR |
| 5538 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 5556 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 5539 | L: linux-media@vger.kernel.org | 5557 | L: linux-media@vger.kernel.org |
| 5540 | T: git git://linuxtv.org/media_tree.git | 5558 | T: git git://linuxtv.org/media_tree.git |
| @@ -5542,7 +5560,7 @@ S: Maintained | |||
| 5542 | F: drivers/media/i2c/mt9t001.c | 5560 | F: drivers/media/i2c/mt9t001.c |
| 5543 | F: include/media/mt9t001.h | 5561 | F: include/media/mt9t001.h |
| 5544 | 5562 | ||
| 5545 | MT9V032 SENSOR DRIVER | 5563 | MT9V032 APTINA CAMERA SENSOR |
| 5546 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 5564 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 5547 | L: linux-media@vger.kernel.org | 5565 | L: linux-media@vger.kernel.org |
| 5548 | T: git git://linuxtv.org/media_tree.git | 5566 | T: git git://linuxtv.org/media_tree.git |
diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig index 845f5cdf62b5..e7e94948d194 100644 --- a/arch/arm/configs/bockw_defconfig +++ b/arch/arm/configs/bockw_defconfig | |||
| @@ -82,6 +82,13 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y | |||
| 82 | # CONFIG_HWMON is not set | 82 | # CONFIG_HWMON is not set |
| 83 | CONFIG_I2C=y | 83 | CONFIG_I2C=y |
| 84 | CONFIG_I2C_RCAR=y | 84 | CONFIG_I2C_RCAR=y |
| 85 | CONFIG_MEDIA_SUPPORT=y | ||
| 86 | CONFIG_MEDIA_CAMERA_SUPPORT=y | ||
| 87 | CONFIG_V4L_PLATFORM_DRIVERS=y | ||
| 88 | CONFIG_SOC_CAMERA=y | ||
| 89 | CONFIG_VIDEO_RCAR_VIN=y | ||
| 90 | # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set | ||
| 91 | CONFIG_VIDEO_ML86V7667=y | ||
| 85 | CONFIG_SPI=y | 92 | CONFIG_SPI=y |
| 86 | CONFIG_SPI_SH_HSPI=y | 93 | CONFIG_SPI_SH_HSPI=y |
| 87 | CONFIG_USB=y | 94 | CONFIG_USB=y |
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig index 494e70aeb9e1..c50e52be4463 100644 --- a/arch/arm/configs/marzen_defconfig +++ b/arch/arm/configs/marzen_defconfig | |||
| @@ -84,6 +84,13 @@ CONFIG_GPIO_RCAR=y | |||
| 84 | CONFIG_THERMAL=y | 84 | CONFIG_THERMAL=y |
| 85 | CONFIG_RCAR_THERMAL=y | 85 | CONFIG_RCAR_THERMAL=y |
| 86 | CONFIG_SSB=y | 86 | CONFIG_SSB=y |
| 87 | CONFIG_MEDIA_SUPPORT=y | ||
| 88 | CONFIG_MEDIA_CAMERA_SUPPORT=y | ||
| 89 | CONFIG_V4L_PLATFORM_DRIVERS=y | ||
| 90 | CONFIG_SOC_CAMERA=y | ||
| 91 | CONFIG_VIDEO_RCAR_VIN=y | ||
| 92 | # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set | ||
| 93 | CONFIG_VIDEO_ADV7180=y | ||
| 87 | CONFIG_USB=y | 94 | CONFIG_USB=y |
| 88 | CONFIG_USB_RCAR_PHY=y | 95 | CONFIG_USB_RCAR_PHY=y |
| 89 | CONFIG_MMC=y | 96 | CONFIG_MMC=y |
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index bea6793a7ede..9f09f45835f8 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c | |||
| @@ -1249,12 +1249,10 @@ static struct vpif_capture_config da850_vpif_capture_config = { | |||
| 1249 | 1249 | ||
| 1250 | static struct adv7343_platform_data adv7343_pdata = { | 1250 | static struct adv7343_platform_data adv7343_pdata = { |
| 1251 | .mode_config = { | 1251 | .mode_config = { |
| 1252 | .dac_3 = 1, | 1252 | .dac = { 1, 1, 1 }, |
| 1253 | .dac_2 = 1, | ||
| 1254 | .dac_1 = 1, | ||
| 1255 | }, | 1253 | }, |
| 1256 | .sd_config = { | 1254 | .sd_config = { |
| 1257 | .sd_dac_out1 = 1, | 1255 | .sd_dac_out = { 1 }, |
| 1258 | }, | 1256 | }, |
| 1259 | }; | 1257 | }; |
| 1260 | 1258 | ||
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index 3354a85c90f7..24f26ee97f42 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | 4 | * Copyright (C) 2013 Renesas Solutions Corp. |
| 5 | * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 5 | * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| 6 | * Copyright (C) 2013 Cogent Embedded, Inc. | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/smsc911x.h> | 29 | #include <linux/smsc911x.h> |
| 29 | #include <linux/spi/spi.h> | 30 | #include <linux/spi/spi.h> |
| 30 | #include <linux/spi/flash.h> | 31 | #include <linux/spi/flash.h> |
| 32 | #include <media/soc_camera.h> | ||
| 31 | #include <mach/common.h> | 33 | #include <mach/common.h> |
| 32 | #include <mach/irqs.h> | 34 | #include <mach/irqs.h> |
| 33 | #include <mach/r8a7778.h> | 35 | #include <mach/r8a7778.h> |
| @@ -143,6 +145,25 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = { | |||
| 143 | MMC_CAP_NEEDS_POLL, | 145 | MMC_CAP_NEEDS_POLL, |
| 144 | }; | 146 | }; |
| 145 | 147 | ||
| 148 | static struct rcar_vin_platform_data vin_platform_data __initdata = { | ||
| 149 | .flags = RCAR_VIN_BT656, | ||
| 150 | }; | ||
| 151 | |||
| 152 | /* In the default configuration both decoders reside on I2C bus 0 */ | ||
| 153 | #define BOCKW_CAMERA(idx) \ | ||
| 154 | static struct i2c_board_info camera##idx##_info = { \ | ||
| 155 | I2C_BOARD_INFO("ml86v7667", 0x41 + 2 * (idx)), \ | ||
| 156 | }; \ | ||
| 157 | \ | ||
| 158 | static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \ | ||
| 159 | .bus_id = idx, \ | ||
| 160 | .i2c_adapter_id = 0, \ | ||
| 161 | .board_info = &camera##idx##_info, \ | ||
| 162 | } | ||
| 163 | |||
| 164 | BOCKW_CAMERA(0); | ||
| 165 | BOCKW_CAMERA(1); | ||
| 166 | |||
| 146 | static const struct pinctrl_map bockw_pinctrl_map[] = { | 167 | static const struct pinctrl_map bockw_pinctrl_map[] = { |
| 147 | /* Ether */ | 168 | /* Ether */ |
| 148 | PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778", | 169 | PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778", |
| @@ -174,6 +195,16 @@ static const struct pinctrl_map bockw_pinctrl_map[] = { | |||
| 174 | "sdhi0_cd", "sdhi0"), | 195 | "sdhi0_cd", "sdhi0"), |
| 175 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", | 196 | PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", |
| 176 | "sdhi0_wp", "sdhi0"), | 197 | "sdhi0_wp", "sdhi0"), |
| 198 | /* VIN0 */ | ||
| 199 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778", | ||
| 200 | "vin0_clk", "vin0"), | ||
| 201 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778", | ||
| 202 | "vin0_data8", "vin0"), | ||
| 203 | /* VIN1 */ | ||
| 204 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778", | ||
| 205 | "vin1_clk", "vin1"), | ||
| 206 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778", | ||
| 207 | "vin1_data8", "vin1"), | ||
| 177 | }; | 208 | }; |
| 178 | 209 | ||
| 179 | #define FPGA 0x18200000 | 210 | #define FPGA 0x18200000 |
| @@ -192,6 +223,16 @@ static void __init bockw_init(void) | |||
| 192 | r8a7778_add_i2c_device(0); | 223 | r8a7778_add_i2c_device(0); |
| 193 | r8a7778_add_hspi_device(0); | 224 | r8a7778_add_hspi_device(0); |
| 194 | r8a7778_add_mmc_device(&sh_mmcif_plat); | 225 | r8a7778_add_mmc_device(&sh_mmcif_plat); |
| 226 | r8a7778_add_vin_device(0, &vin_platform_data); | ||
| 227 | /* VIN1 has a pin conflict with Ether */ | ||
| 228 | if (!IS_ENABLED(CONFIG_SH_ETH)) | ||
| 229 | r8a7778_add_vin_device(1, &vin_platform_data); | ||
| 230 | platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0, | ||
| 231 | &iclink0_ml86v7667, | ||
| 232 | sizeof(iclink0_ml86v7667)); | ||
| 233 | platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1, | ||
| 234 | &iclink1_ml86v7667, | ||
| 235 | sizeof(iclink1_ml86v7667)); | ||
| 195 | 236 | ||
| 196 | i2c_register_board_info(0, i2c0_devices, | 237 | i2c_register_board_info(0, i2c0_devices, |
| 197 | ARRAY_SIZE(i2c0_devices)); | 238 | ARRAY_SIZE(i2c0_devices)); |
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index a7d1010505bf..ca7fb2e63c60 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * marzen board support | 2 | * marzen board support |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Renesas Solutions Corp. | 4 | * Copyright (C) 2011, 2013 Renesas Solutions Corp. |
| 5 | * Copyright (C) 2011 Magnus Damm | 5 | * Copyright (C) 2011 Magnus Damm |
| 6 | * Copyright (C) 2013 Cogent Embedded, Inc. | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -37,6 +38,7 @@ | |||
| 37 | #include <linux/mmc/host.h> | 38 | #include <linux/mmc/host.h> |
| 38 | #include <linux/mmc/sh_mobile_sdhi.h> | 39 | #include <linux/mmc/sh_mobile_sdhi.h> |
| 39 | #include <linux/mfd/tmio.h> | 40 | #include <linux/mfd/tmio.h> |
| 41 | #include <media/soc_camera.h> | ||
| 40 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
| 41 | #include <mach/r8a7779.h> | 43 | #include <mach/r8a7779.h> |
| 42 | #include <mach/common.h> | 44 | #include <mach/common.h> |
| @@ -178,12 +180,40 @@ static struct platform_device leds_device = { | |||
| 178 | }, | 180 | }, |
| 179 | }; | 181 | }; |
| 180 | 182 | ||
| 183 | static struct rcar_vin_platform_data vin_platform_data __initdata = { | ||
| 184 | .flags = RCAR_VIN_BT656, | ||
| 185 | }; | ||
| 186 | |||
| 187 | #define MARZEN_CAMERA(idx) \ | ||
| 188 | static struct i2c_board_info camera##idx##_info = { \ | ||
| 189 | I2C_BOARD_INFO("adv7180", 0x20 + (idx)), \ | ||
| 190 | }; \ | ||
| 191 | \ | ||
| 192 | static struct soc_camera_link iclink##idx##_adv7180 = { \ | ||
| 193 | .bus_id = 1 + 2 * (idx), \ | ||
| 194 | .i2c_adapter_id = 0, \ | ||
| 195 | .board_info = &camera##idx##_info, \ | ||
| 196 | }; \ | ||
| 197 | \ | ||
| 198 | static struct platform_device camera##idx##_device = { \ | ||
| 199 | .name = "soc-camera-pdrv", \ | ||
| 200 | .id = idx, \ | ||
| 201 | .dev = { \ | ||
| 202 | .platform_data = &iclink##idx##_adv7180, \ | ||
| 203 | }, \ | ||
| 204 | }; | ||
| 205 | |||
| 206 | MARZEN_CAMERA(0); | ||
| 207 | MARZEN_CAMERA(1); | ||
| 208 | |||
| 181 | static struct platform_device *marzen_devices[] __initdata = { | 209 | static struct platform_device *marzen_devices[] __initdata = { |
| 182 | ð_device, | 210 | ð_device, |
| 183 | &sdhi0_device, | 211 | &sdhi0_device, |
| 184 | &thermal_device, | 212 | &thermal_device, |
| 185 | &hspi_device, | 213 | &hspi_device, |
| 186 | &leds_device, | 214 | &leds_device, |
| 215 | &camera0_device, | ||
| 216 | &camera1_device, | ||
| 187 | }; | 217 | }; |
| 188 | 218 | ||
| 189 | static const struct pinctrl_map marzen_pinctrl_map[] = { | 219 | static const struct pinctrl_map marzen_pinctrl_map[] = { |
| @@ -219,6 +249,16 @@ static const struct pinctrl_map marzen_pinctrl_map[] = { | |||
| 219 | /* USB2 */ | 249 | /* USB2 */ |
| 220 | PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779", | 250 | PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779", |
| 221 | "usb2", "usb2"), | 251 | "usb2", "usb2"), |
| 252 | /* VIN1 */ | ||
| 253 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779", | ||
| 254 | "vin1_clk", "vin1"), | ||
| 255 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779", | ||
| 256 | "vin1_data8", "vin1"), | ||
| 257 | /* VIN3 */ | ||
| 258 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779", | ||
| 259 | "vin3_clk", "vin3"), | ||
| 260 | PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779", | ||
| 261 | "vin3_data8", "vin3"), | ||
| 222 | }; | 262 | }; |
| 223 | 263 | ||
| 224 | static void __init marzen_init(void) | 264 | static void __init marzen_init(void) |
| @@ -235,6 +275,8 @@ static void __init marzen_init(void) | |||
| 235 | 275 | ||
| 236 | r8a7779_add_standard_devices(); | 276 | r8a7779_add_standard_devices(); |
| 237 | r8a7779_add_usb_phy_device(&usb_phy_platform_data); | 277 | r8a7779_add_usb_phy_device(&usb_phy_platform_data); |
| 278 | r8a7779_add_vin_device(1, &vin_platform_data); | ||
| 279 | r8a7779_add_vin_device(3, &vin_platform_data); | ||
| 238 | platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); | 280 | platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); |
| 239 | } | 281 | } |
| 240 | 282 | ||
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c index a0e9eb72e46d..c4bf2d8fb111 100644 --- a/arch/arm/mach-shmobile/clock-r8a7778.c +++ b/arch/arm/mach-shmobile/clock-r8a7778.c | |||
| @@ -106,6 +106,7 @@ enum { | |||
| 106 | MSTP331, | 106 | MSTP331, |
| 107 | MSTP323, MSTP322, MSTP321, | 107 | MSTP323, MSTP322, MSTP321, |
| 108 | MSTP114, | 108 | MSTP114, |
| 109 | MSTP110, MSTP109, | ||
| 109 | MSTP100, | 110 | MSTP100, |
| 110 | MSTP030, | 111 | MSTP030, |
| 111 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, | 112 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, |
| @@ -119,6 +120,8 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
| 119 | [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */ | 120 | [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */ |
| 120 | [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */ | 121 | [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */ |
| 121 | [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */ | 122 | [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */ |
| 123 | [MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */ | ||
| 124 | [MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 9, 0), /* VIN1 */ | ||
| 122 | [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */ | 125 | [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */ |
| 123 | [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */ | 126 | [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */ |
| 124 | [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */ | 127 | [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */ |
| @@ -146,6 +149,8 @@ static struct clk_lookup lookups[] = { | |||
| 146 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ | 149 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ |
| 147 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ | 150 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ |
| 148 | CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ | 151 | CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ |
| 152 | CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */ | ||
| 153 | CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */ | ||
| 149 | CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ | 154 | CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ |
| 150 | CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */ | 155 | CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */ |
| 151 | CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */ | 156 | CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */ |
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 10340f5becbb..bd6ad922eb7e 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c | |||
| @@ -112,7 +112,9 @@ static struct clk *main_clks[] = { | |||
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | enum { MSTP323, MSTP322, MSTP321, MSTP320, | 114 | enum { MSTP323, MSTP322, MSTP321, MSTP320, |
| 115 | MSTP120, | ||
| 115 | MSTP116, MSTP115, MSTP114, | 116 | MSTP116, MSTP115, MSTP114, |
| 117 | MSTP110, MSTP109, MSTP108, | ||
| 116 | MSTP103, MSTP101, MSTP100, | 118 | MSTP103, MSTP101, MSTP100, |
| 117 | MSTP030, | 119 | MSTP030, |
| 118 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, | 120 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, |
| @@ -125,9 +127,13 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
| 125 | [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */ | 127 | [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */ |
| 126 | [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ | 128 | [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ |
| 127 | [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ | 129 | [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ |
| 130 | [MSTP120] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 20, 0), /* VIN3 */ | ||
| 128 | [MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */ | 131 | [MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */ |
| 129 | [MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */ | 132 | [MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */ |
| 130 | [MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */ | 133 | [MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */ |
| 134 | [MSTP110] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 10, 0), /* VIN0 */ | ||
| 135 | [MSTP109] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 9, 0), /* VIN1 */ | ||
| 136 | [MSTP108] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 8, 0), /* VIN2 */ | ||
| 131 | [MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */ | 137 | [MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */ |
| 132 | [MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */ | 138 | [MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */ |
| 133 | [MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */ | 139 | [MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */ |
| @@ -162,10 +168,14 @@ static struct clk_lookup lookups[] = { | |||
| 162 | CLKDEV_CON_ID("peripheral_clk", &clkp_clk), | 168 | CLKDEV_CON_ID("peripheral_clk", &clkp_clk), |
| 163 | 169 | ||
| 164 | /* MSTP32 clocks */ | 170 | /* MSTP32 clocks */ |
| 171 | CLKDEV_DEV_ID("r8a7779-vin.3", &mstp_clks[MSTP120]), /* VIN3 */ | ||
| 165 | CLKDEV_DEV_ID("rcar-pcie", &mstp_clks[MSTP116]), /* PCIe */ | 172 | CLKDEV_DEV_ID("rcar-pcie", &mstp_clks[MSTP116]), /* PCIe */ |
| 166 | CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ | 173 | CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ |
| 167 | CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ | 174 | CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ |
| 168 | CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ | 175 | CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ |
| 176 | CLKDEV_DEV_ID("r8a7779-vin.0", &mstp_clks[MSTP110]), /* VIN0 */ | ||
| 177 | CLKDEV_DEV_ID("r8a7779-vin.1", &mstp_clks[MSTP109]), /* VIN1 */ | ||
| 178 | CLKDEV_DEV_ID("r8a7779-vin.2", &mstp_clks[MSTP108]), /* VIN2 */ | ||
| 169 | CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ | 179 | CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ |
| 170 | CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ | 180 | CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ |
| 171 | CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ | 181 | CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ |
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h index 851d027a2f06..a7c6d151cdd5 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7778.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/mmc/sh_mobile_sdhi.h> | 22 | #include <linux/mmc/sh_mobile_sdhi.h> |
| 23 | #include <linux/sh_eth.h> | 23 | #include <linux/sh_eth.h> |
| 24 | #include <linux/platform_data/usb-rcar-phy.h> | 24 | #include <linux/platform_data/usb-rcar-phy.h> |
| 25 | #include <linux/platform_data/camera-rcar.h> | ||
| 25 | 26 | ||
| 26 | extern void r8a7778_add_standard_devices(void); | 27 | extern void r8a7778_add_standard_devices(void); |
| 27 | extern void r8a7778_add_standard_devices_dt(void); | 28 | extern void r8a7778_add_standard_devices_dt(void); |
| @@ -30,6 +31,8 @@ extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata); | |||
| 30 | extern void r8a7778_add_i2c_device(int id); | 31 | extern void r8a7778_add_i2c_device(int id); |
| 31 | extern void r8a7778_add_hspi_device(int id); | 32 | extern void r8a7778_add_hspi_device(int id); |
| 32 | extern void r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info); | 33 | extern void r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info); |
| 34 | extern void r8a7778_add_vin_device(int id, | ||
| 35 | struct rcar_vin_platform_data *pdata); | ||
| 33 | 36 | ||
| 34 | extern void r8a7778_init_late(void); | 37 | extern void r8a7778_init_late(void); |
| 35 | extern void r8a7778_init_delay(void); | 38 | extern void r8a7778_init_delay(void); |
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h index fc47073c7ba9..6d2b6417fe2a 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7779.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/pm_domain.h> | 5 | #include <linux/pm_domain.h> |
| 6 | #include <linux/sh_eth.h> | 6 | #include <linux/sh_eth.h> |
| 7 | #include <linux/platform_data/usb-rcar-phy.h> | 7 | #include <linux/platform_data/usb-rcar-phy.h> |
| 8 | #include <linux/platform_data/camera-rcar.h> | ||
| 8 | 9 | ||
| 9 | struct platform_device; | 10 | struct platform_device; |
| 10 | 11 | ||
| @@ -35,6 +36,8 @@ extern void r8a7779_add_standard_devices(void); | |||
| 35 | extern void r8a7779_add_standard_devices_dt(void); | 36 | extern void r8a7779_add_standard_devices_dt(void); |
| 36 | extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata); | 37 | extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata); |
| 37 | extern void r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata); | 38 | extern void r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata); |
| 39 | extern void r8a7779_add_vin_device(int idx, | ||
| 40 | struct rcar_vin_platform_data *pdata); | ||
| 38 | extern void r8a7779_init_late(void); | 41 | extern void r8a7779_init_late(void); |
| 39 | extern void r8a7779_clock_init(void); | 42 | extern void r8a7779_clock_init(void); |
| 40 | extern void r8a7779_pinmux_init(void); | 43 | extern void r8a7779_pinmux_init(void); |
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index 80c20392ad7c..0174f059eac3 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c | |||
| @@ -333,6 +333,40 @@ void __init r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info) | |||
| 333 | info, sizeof(*info)); | 333 | info, sizeof(*info)); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | /* VIN */ | ||
| 337 | #define R8A7778_VIN(idx) \ | ||
| 338 | static struct resource vin##idx##_resources[] __initdata = { \ | ||
| 339 | DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ | ||
| 340 | DEFINE_RES_IRQ(gic_iid(0x5a)), \ | ||
| 341 | }; \ | ||
| 342 | \ | ||
| 343 | static struct platform_device_info vin##idx##_info __initdata = { \ | ||
| 344 | .parent = &platform_bus, \ | ||
| 345 | .name = "r8a7778-vin", \ | ||
| 346 | .id = idx, \ | ||
| 347 | .res = vin##idx##_resources, \ | ||
| 348 | .num_res = ARRAY_SIZE(vin##idx##_resources), \ | ||
| 349 | .dma_mask = DMA_BIT_MASK(32), \ | ||
| 350 | } | ||
| 351 | |||
| 352 | R8A7778_VIN(0); | ||
| 353 | R8A7778_VIN(1); | ||
| 354 | |||
| 355 | static struct platform_device_info *vin_info_table[] __initdata = { | ||
| 356 | &vin0_info, | ||
| 357 | &vin1_info, | ||
| 358 | }; | ||
| 359 | |||
| 360 | void __init r8a7778_add_vin_device(int id, struct rcar_vin_platform_data *pdata) | ||
| 361 | { | ||
| 362 | BUG_ON(id < 0 || id > 1); | ||
| 363 | |||
| 364 | vin_info_table[id]->data = pdata; | ||
| 365 | vin_info_table[id]->size_data = sizeof(*pdata); | ||
| 366 | |||
| 367 | platform_device_register_full(vin_info_table[id]); | ||
| 368 | } | ||
| 369 | |||
| 336 | void __init r8a7778_add_standard_devices(void) | 370 | void __init r8a7778_add_standard_devices(void) |
| 337 | { | 371 | { |
| 338 | int i; | 372 | int i; |
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 398687761f50..3d8928895503 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c | |||
| @@ -559,6 +559,33 @@ static struct resource ether_resources[] = { | |||
| 559 | }, | 559 | }, |
| 560 | }; | 560 | }; |
| 561 | 561 | ||
| 562 | #define R8A7779_VIN(idx) \ | ||
| 563 | static struct resource vin##idx##_resources[] __initdata = { \ | ||
| 564 | DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \ | ||
| 565 | DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \ | ||
| 566 | }; \ | ||
| 567 | \ | ||
| 568 | static struct platform_device_info vin##idx##_info __initdata = { \ | ||
| 569 | .parent = &platform_bus, \ | ||
| 570 | .name = "r8a7779-vin", \ | ||
| 571 | .id = idx, \ | ||
| 572 | .res = vin##idx##_resources, \ | ||
| 573 | .num_res = ARRAY_SIZE(vin##idx##_resources), \ | ||
| 574 | .dma_mask = DMA_BIT_MASK(32), \ | ||
| 575 | } | ||
| 576 | |||
| 577 | R8A7779_VIN(0); | ||
| 578 | R8A7779_VIN(1); | ||
| 579 | R8A7779_VIN(2); | ||
| 580 | R8A7779_VIN(3); | ||
| 581 | |||
| 582 | static struct platform_device_info *vin_info_table[] __initdata = { | ||
| 583 | &vin0_info, | ||
| 584 | &vin1_info, | ||
| 585 | &vin2_info, | ||
| 586 | &vin3_info, | ||
| 587 | }; | ||
| 588 | |||
| 562 | static struct platform_device *r8a7779_devices_dt[] __initdata = { | 589 | static struct platform_device *r8a7779_devices_dt[] __initdata = { |
| 563 | &scif0_device, | 590 | &scif0_device, |
| 564 | &scif1_device, | 591 | &scif1_device, |
| @@ -610,6 +637,16 @@ void __init r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata) | |||
| 610 | pdata, sizeof(*pdata)); | 637 | pdata, sizeof(*pdata)); |
| 611 | } | 638 | } |
| 612 | 639 | ||
| 640 | void __init r8a7779_add_vin_device(int id, struct rcar_vin_platform_data *pdata) | ||
| 641 | { | ||
| 642 | BUG_ON(id < 0 || id > 3); | ||
| 643 | |||
| 644 | vin_info_table[id]->data = pdata; | ||
| 645 | vin_info_table[id]->size_data = sizeof(*pdata); | ||
| 646 | |||
| 647 | platform_device_register_full(vin_info_table[id]); | ||
| 648 | } | ||
| 649 | |||
| 613 | /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ | 650 | /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ |
| 614 | void __init __weak r8a7779_register_twd(void) { } | 651 | void __init __weak r8a7779_register_twd(void) { } |
| 615 | 652 | ||
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig index f3f5ec44e685..f953d33ee151 100644 --- a/drivers/media/common/siano/Kconfig +++ b/drivers/media/common/siano/Kconfig | |||
| @@ -23,6 +23,8 @@ config SMS_SIANO_DEBUGFS | |||
| 23 | depends on SMS_SIANO_MDTV | 23 | depends on SMS_SIANO_MDTV |
| 24 | depends on DEBUG_FS | 24 | depends on DEBUG_FS |
| 25 | depends on SMS_USB_DRV | 25 | depends on SMS_USB_DRV |
| 26 | depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV | ||
| 27 | |||
| 26 | ---help--- | 28 | ---help--- |
| 27 | Choose Y to enable visualizing a dump of the frontend | 29 | Choose Y to enable visualizing a dump of the frontend |
| 28 | statistics response packets via debugfs. Currently, works | 30 | statistics response packets via debugfs. Currently, works |
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 086262252230..63676a8b024c 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c | |||
| @@ -276,7 +276,8 @@ static void smsdvb_update_per_slices(struct smsdvb_client_t *client, | |||
| 276 | 276 | ||
| 277 | /* Legacy PER/BER */ | 277 | /* Legacy PER/BER */ |
| 278 | tmp = p->ets_packets * 65535; | 278 | tmp = p->ets_packets * 65535; |
| 279 | do_div(tmp, p->ts_packets + p->ets_packets); | 279 | if (p->ts_packets + p->ets_packets) |
| 280 | do_div(tmp, p->ts_packets + p->ets_packets); | ||
| 280 | client->legacy_per = tmp; | 281 | client->legacy_per = tmp; |
| 281 | } | 282 | } |
| 282 | 283 | ||
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 886da16e14f2..419a2d6b4349 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h | |||
| @@ -369,4 +369,6 @@ | |||
| 369 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 | 369 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 |
| 370 | #define USB_PID_CPYTO_REDI_PC50A 0xa803 | 370 | #define USB_PID_CPYTO_REDI_PC50A 0xa803 |
| 371 | #define USB_PID_CTVDIGDUAL_V2 0xe410 | 371 | #define USB_PID_CTVDIGDUAL_V2 0xe410 |
| 372 | #define USB_PID_PCTV_2002E 0x025c | ||
| 373 | #define USB_PID_PCTV_2002E_SE 0x025d | ||
| 372 | #endif | 374 | #endif |
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index 856374bd3676..2c7217fb1415 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c | |||
| @@ -157,7 +157,6 @@ static struct regdata mb86a20s_init2[] = { | |||
| 157 | { 0x45, 0x04 }, /* CN symbol 4 */ | 157 | { 0x45, 0x04 }, /* CN symbol 4 */ |
| 158 | { 0x48, 0x04 }, /* CN manual mode */ | 158 | { 0x48, 0x04 }, /* CN manual mode */ |
| 159 | 159 | ||
| 160 | { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */ | ||
| 161 | { 0x50, 0xd6 }, { 0x51, 0x1f }, | 160 | { 0x50, 0xd6 }, { 0x51, 0x1f }, |
| 162 | { 0x50, 0xd2 }, { 0x51, 0x03 }, | 161 | { 0x50, 0xd2 }, { 0x51, 0x03 }, |
| 163 | { 0x50, 0xd7 }, { 0x51, 0xbf }, | 162 | { 0x50, 0xd7 }, { 0x51, 0xbf }, |
| @@ -1860,16 +1859,15 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) | |||
| 1860 | dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", | 1859 | dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n", |
| 1861 | __func__, state->if_freq, (long long)pll); | 1860 | __func__, state->if_freq, (long long)pll); |
| 1862 | 1861 | ||
| 1863 | if (!state->config->is_serial) { | 1862 | if (!state->config->is_serial) |
| 1864 | regD5 &= ~1; | 1863 | regD5 &= ~1; |
| 1865 | 1864 | ||
| 1866 | rc = mb86a20s_writereg(state, 0x50, 0xd5); | 1865 | rc = mb86a20s_writereg(state, 0x50, 0xd5); |
| 1867 | if (rc < 0) | 1866 | if (rc < 0) |
| 1868 | goto err; | 1867 | goto err; |
| 1869 | rc = mb86a20s_writereg(state, 0x51, regD5); | 1868 | rc = mb86a20s_writereg(state, 0x51, regD5); |
| 1870 | if (rc < 0) | 1869 | if (rc < 0) |
| 1871 | goto err; | 1870 | goto err; |
| 1872 | } | ||
| 1873 | 1871 | ||
| 1874 | rc = mb86a20s_writeregdata(state, mb86a20s_init2); | 1872 | rc = mb86a20s_writeregdata(state, mb86a20s_init2); |
| 1875 | if (rc < 0) | 1873 | if (rc < 0) |
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index b2cd8ca51af7..d18be19c96cd 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig | |||
| @@ -206,6 +206,18 @@ config VIDEO_ADV7604 | |||
| 206 | To compile this driver as a module, choose M here: the | 206 | To compile this driver as a module, choose M here: the |
| 207 | module will be called adv7604. | 207 | module will be called adv7604. |
| 208 | 208 | ||
| 209 | config VIDEO_ADV7842 | ||
| 210 | tristate "Analog Devices ADV7842 decoder" | ||
| 211 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | ||
| 212 | ---help--- | ||
| 213 | Support for the Analog Devices ADV7842 video decoder. | ||
| 214 | |||
| 215 | This is a Analog Devices Component/Graphics/SD Digitizer | ||
| 216 | with 2:1 Multiplexed HDMI Receiver. | ||
| 217 | |||
| 218 | To compile this driver as a module, choose M here: the | ||
| 219 | module will be called adv7842. | ||
| 220 | |||
| 209 | config VIDEO_BT819 | 221 | config VIDEO_BT819 |
| 210 | tristate "BT819A VideoStream decoder" | 222 | tristate "BT819A VideoStream decoder" |
| 211 | depends on VIDEO_V4L2 && I2C | 223 | depends on VIDEO_V4L2 && I2C |
| @@ -417,6 +429,17 @@ config VIDEO_ADV7393 | |||
| 417 | To compile this driver as a module, choose M here: the | 429 | To compile this driver as a module, choose M here: the |
| 418 | module will be called adv7393. | 430 | module will be called adv7393. |
| 419 | 431 | ||
| 432 | config VIDEO_ADV7511 | ||
| 433 | tristate "Analog Devices ADV7511 encoder" | ||
| 434 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | ||
| 435 | ---help--- | ||
| 436 | Support for the Analog Devices ADV7511 video encoder. | ||
| 437 | |||
| 438 | This is a Analog Devices HDMI transmitter. | ||
| 439 | |||
| 440 | To compile this driver as a module, choose M here: the | ||
| 441 | module will be called adv7511. | ||
| 442 | |||
| 420 | config VIDEO_AD9389B | 443 | config VIDEO_AD9389B |
| 421 | tristate "Analog Devices AD9389B encoder" | 444 | tristate "Analog Devices AD9389B encoder" |
| 422 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API | 445 | depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API |
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index dc20653bb5ad..9f462df77b4a 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile | |||
| @@ -26,7 +26,9 @@ obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o | |||
| 26 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o | 26 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o |
| 27 | obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o | 27 | obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o |
| 28 | obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o | 28 | obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o |
| 29 | obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o | ||
| 29 | obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o | 30 | obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o |
| 31 | obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o | ||
| 30 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o | 32 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o |
| 31 | obj-$(CONFIG_VIDEO_VS6624) += vs6624.o | 33 | obj-$(CONFIG_VIDEO_VS6624) += vs6624.o |
| 32 | obj-$(CONFIG_VIDEO_BT819) += bt819.o | 34 | obj-$(CONFIG_VIDEO_BT819) += bt819.o |
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index ba4364dfae66..bb0c99d7a4f1 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/v4l2-dv-timings.h> | 33 | #include <linux/v4l2-dv-timings.h> |
| 34 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
| 35 | #include <media/v4l2-common.h> | 35 | #include <media/v4l2-common.h> |
| 36 | #include <media/v4l2-dv-timings.h> | ||
| 36 | #include <media/v4l2-ctrls.h> | 37 | #include <media/v4l2-ctrls.h> |
| 37 | #include <media/ad9389b.h> | 38 | #include <media/ad9389b.h> |
| 38 | 39 | ||
| @@ -442,22 +443,11 @@ static int ad9389b_log_status(struct v4l2_subdev *sd) | |||
| 442 | vic_detect, vic_sent); | 443 | vic_detect, vic_sent); |
| 443 | } | 444 | } |
| 444 | } | 445 | } |
| 445 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) { | 446 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) |
| 446 | struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt; | 447 | v4l2_print_dv_timings(sd->name, "timings: ", |
| 447 | u32 frame_width = bt->width + bt->hfrontporch + | 448 | &state->dv_timings, false); |
| 448 | bt->hsync + bt->hbackporch; | 449 | else |
| 449 | u32 frame_height = bt->height + bt->vfrontporch + | ||
| 450 | bt->vsync + bt->vbackporch; | ||
| 451 | u32 frame_size = frame_width * frame_height; | ||
| 452 | |||
| 453 | v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n", | ||
| 454 | bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
| 455 | frame_size > 0 ? (unsigned)bt->pixelclock / frame_size : 0, | ||
| 456 | frame_width, frame_height, | ||
| 457 | (unsigned)bt->pixelclock, bt->polarities); | ||
| 458 | } else { | ||
| 459 | v4l2_info(sd, "no timings set\n"); | 450 | v4l2_info(sd, "no timings set\n"); |
| 460 | } | ||
| 461 | return 0; | 451 | return 0; |
| 462 | } | 452 | } |
| 463 | 453 | ||
| @@ -636,95 +626,34 @@ static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable) | |||
| 636 | return 0; | 626 | return 0; |
| 637 | } | 627 | } |
| 638 | 628 | ||
| 639 | static const struct v4l2_dv_timings ad9389b_timings[] = { | 629 | static const struct v4l2_dv_timings_cap ad9389b_timings_cap = { |
| 640 | V4L2_DV_BT_CEA_720X480P59_94, | 630 | .type = V4L2_DV_BT_656_1120, |
| 641 | V4L2_DV_BT_CEA_720X576P50, | 631 | .bt = { |
| 642 | V4L2_DV_BT_CEA_1280X720P24, | 632 | .max_width = 1920, |
| 643 | V4L2_DV_BT_CEA_1280X720P25, | 633 | .max_height = 1200, |
| 644 | V4L2_DV_BT_CEA_1280X720P30, | 634 | .min_pixelclock = 25000000, |
| 645 | V4L2_DV_BT_CEA_1280X720P50, | 635 | .max_pixelclock = 170000000, |
| 646 | V4L2_DV_BT_CEA_1280X720P60, | 636 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | |
| 647 | V4L2_DV_BT_CEA_1920X1080P24, | 637 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, |
| 648 | V4L2_DV_BT_CEA_1920X1080P25, | 638 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | |
| 649 | V4L2_DV_BT_CEA_1920X1080P30, | 639 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, |
| 650 | V4L2_DV_BT_CEA_1920X1080P50, | 640 | }, |
| 651 | V4L2_DV_BT_CEA_1920X1080P60, | ||
| 652 | |||
| 653 | V4L2_DV_BT_DMT_640X350P85, | ||
| 654 | V4L2_DV_BT_DMT_640X400P85, | ||
| 655 | V4L2_DV_BT_DMT_720X400P85, | ||
| 656 | V4L2_DV_BT_DMT_640X480P60, | ||
| 657 | V4L2_DV_BT_DMT_640X480P72, | ||
| 658 | V4L2_DV_BT_DMT_640X480P75, | ||
| 659 | V4L2_DV_BT_DMT_640X480P85, | ||
| 660 | V4L2_DV_BT_DMT_800X600P56, | ||
| 661 | V4L2_DV_BT_DMT_800X600P60, | ||
| 662 | V4L2_DV_BT_DMT_800X600P72, | ||
| 663 | V4L2_DV_BT_DMT_800X600P75, | ||
| 664 | V4L2_DV_BT_DMT_800X600P85, | ||
| 665 | V4L2_DV_BT_DMT_848X480P60, | ||
| 666 | V4L2_DV_BT_DMT_1024X768P60, | ||
| 667 | V4L2_DV_BT_DMT_1024X768P70, | ||
| 668 | V4L2_DV_BT_DMT_1024X768P75, | ||
| 669 | V4L2_DV_BT_DMT_1024X768P85, | ||
| 670 | V4L2_DV_BT_DMT_1152X864P75, | ||
| 671 | V4L2_DV_BT_DMT_1280X768P60_RB, | ||
| 672 | V4L2_DV_BT_DMT_1280X768P60, | ||
| 673 | V4L2_DV_BT_DMT_1280X768P75, | ||
| 674 | V4L2_DV_BT_DMT_1280X768P85, | ||
| 675 | V4L2_DV_BT_DMT_1280X800P60_RB, | ||
| 676 | V4L2_DV_BT_DMT_1280X800P60, | ||
| 677 | V4L2_DV_BT_DMT_1280X800P75, | ||
| 678 | V4L2_DV_BT_DMT_1280X800P85, | ||
| 679 | V4L2_DV_BT_DMT_1280X960P60, | ||
| 680 | V4L2_DV_BT_DMT_1280X960P85, | ||
| 681 | V4L2_DV_BT_DMT_1280X1024P60, | ||
| 682 | V4L2_DV_BT_DMT_1280X1024P75, | ||
| 683 | V4L2_DV_BT_DMT_1280X1024P85, | ||
| 684 | V4L2_DV_BT_DMT_1360X768P60, | ||
| 685 | V4L2_DV_BT_DMT_1400X1050P60_RB, | ||
| 686 | V4L2_DV_BT_DMT_1400X1050P60, | ||
| 687 | V4L2_DV_BT_DMT_1400X1050P75, | ||
| 688 | V4L2_DV_BT_DMT_1400X1050P85, | ||
| 689 | V4L2_DV_BT_DMT_1440X900P60_RB, | ||
| 690 | V4L2_DV_BT_DMT_1440X900P60, | ||
| 691 | V4L2_DV_BT_DMT_1600X1200P60, | ||
| 692 | V4L2_DV_BT_DMT_1680X1050P60_RB, | ||
| 693 | V4L2_DV_BT_DMT_1680X1050P60, | ||
| 694 | V4L2_DV_BT_DMT_1792X1344P60, | ||
| 695 | V4L2_DV_BT_DMT_1856X1392P60, | ||
| 696 | V4L2_DV_BT_DMT_1920X1200P60_RB, | ||
| 697 | V4L2_DV_BT_DMT_1366X768P60, | ||
| 698 | V4L2_DV_BT_DMT_1920X1080P60, | ||
| 699 | {}, | ||
| 700 | }; | 641 | }; |
| 701 | 642 | ||
| 702 | static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, | 643 | static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, |
| 703 | struct v4l2_dv_timings *timings) | 644 | struct v4l2_dv_timings *timings) |
| 704 | { | 645 | { |
| 705 | struct ad9389b_state *state = get_ad9389b_state(sd); | 646 | struct ad9389b_state *state = get_ad9389b_state(sd); |
| 706 | int i; | ||
| 707 | 647 | ||
| 708 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | 648 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
| 709 | 649 | ||
| 710 | /* quick sanity check */ | 650 | /* quick sanity check */ |
| 711 | if (timings->type != V4L2_DV_BT_656_1120) | 651 | if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL)) |
| 712 | return -EINVAL; | ||
| 713 | |||
| 714 | if (timings->bt.interlaced) | ||
| 715 | return -EINVAL; | ||
| 716 | if (timings->bt.pixelclock < 27000000 || | ||
| 717 | timings->bt.pixelclock > 170000000) | ||
| 718 | return -EINVAL; | 652 | return -EINVAL; |
| 719 | 653 | ||
| 720 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | 654 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings |
| 721 | if the format is listed in ad9389b_timings[] */ | 655 | if the format is one of the CEA or DMT timings. */ |
| 722 | for (i = 0; ad9389b_timings[i].bt.width; i++) { | 656 | v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL); |
| 723 | if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) { | ||
| 724 | *timings = ad9389b_timings[i]; | ||
| 725 | break; | ||
| 726 | } | ||
| 727 | } | ||
| 728 | 657 | ||
| 729 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; | 658 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; |
| 730 | 659 | ||
| @@ -762,26 +691,14 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd, | |||
| 762 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, | 691 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, |
| 763 | struct v4l2_enum_dv_timings *timings) | 692 | struct v4l2_enum_dv_timings *timings) |
| 764 | { | 693 | { |
| 765 | if (timings->index >= ARRAY_SIZE(ad9389b_timings)) | 694 | return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap, |
| 766 | return -EINVAL; | 695 | NULL, NULL); |
| 767 | |||
| 768 | memset(timings->reserved, 0, sizeof(timings->reserved)); | ||
| 769 | timings->timings = ad9389b_timings[timings->index]; | ||
| 770 | return 0; | ||
| 771 | } | 696 | } |
| 772 | 697 | ||
| 773 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, | 698 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, |
| 774 | struct v4l2_dv_timings_cap *cap) | 699 | struct v4l2_dv_timings_cap *cap) |
| 775 | { | 700 | { |
| 776 | cap->type = V4L2_DV_BT_656_1120; | 701 | *cap = ad9389b_timings_cap; |
| 777 | cap->bt.max_width = 1920; | ||
| 778 | cap->bt.max_height = 1200; | ||
| 779 | cap->bt.min_pixelclock = 27000000; | ||
| 780 | cap->bt.max_pixelclock = 170000000; | ||
| 781 | cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
| 782 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; | ||
| 783 | cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
| 784 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; | ||
| 785 | return 0; | 702 | return 0; |
| 786 | } | 703 | } |
| 787 | 704 | ||
| @@ -930,8 +847,10 @@ static void ad9389b_edid_handler(struct work_struct *work) | |||
| 930 | * (DVI connectors are particularly prone to this problem). */ | 847 | * (DVI connectors are particularly prone to this problem). */ |
| 931 | if (state->edid.read_retries) { | 848 | if (state->edid.read_retries) { |
| 932 | state->edid.read_retries--; | 849 | state->edid.read_retries--; |
| 933 | /* EDID read failed, trigger a retry */ | 850 | v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__); |
| 934 | ad9389b_wr(sd, 0xc9, 0xf); | 851 | state->have_monitor = false; |
| 852 | ad9389b_s_power(sd, false); | ||
| 853 | ad9389b_s_power(sd, true); | ||
| 935 | queue_delayed_work(state->work_queue, | 854 | queue_delayed_work(state->work_queue, |
| 936 | &state->edid_handler, EDID_DELAY); | 855 | &state->edid_handler, EDID_DELAY); |
| 937 | return; | 856 | return; |
| @@ -967,11 +886,9 @@ static void ad9389b_setup(struct v4l2_subdev *sd) | |||
| 967 | ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0); | 886 | ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0); |
| 968 | /* Output format: RGB 4:4:4 */ | 887 | /* Output format: RGB 4:4:4 */ |
| 969 | ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0); | 888 | ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0); |
| 970 | /* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up | 889 | /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, |
| 971 | conversion, Aspect ratio: 16:9 */ | 890 | Aspect ratio: 16:9 */ |
| 972 | ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e); | 891 | ad9389b_wr_and_or(sd, 0x17, 0xf9, 0x06); |
| 973 | /* Disable pixel repetition and CSC */ | ||
| 974 | ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0); | ||
| 975 | /* Output format: RGB 4:4:4, Active Format Information is valid. */ | 892 | /* Output format: RGB 4:4:4, Active Format Information is valid. */ |
| 976 | ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08); | 893 | ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08); |
| 977 | /* Underscanned */ | 894 | /* Underscanned */ |
| @@ -1056,12 +973,12 @@ static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd) | |||
| 1056 | 973 | ||
| 1057 | static bool edid_block_verify_crc(u8 *edid_block) | 974 | static bool edid_block_verify_crc(u8 *edid_block) |
| 1058 | { | 975 | { |
| 1059 | int i; | ||
| 1060 | u8 sum = 0; | 976 | u8 sum = 0; |
| 977 | int i; | ||
| 1061 | 978 | ||
| 1062 | for (i = 0; i < 127; i++) | 979 | for (i = 0; i < 128; i++) |
| 1063 | sum += *(edid_block + i); | 980 | sum += edid_block[i]; |
| 1064 | return ((255 - sum + 1) == edid_block[127]); | 981 | return sum == 0; |
| 1065 | } | 982 | } |
| 1066 | 983 | ||
| 1067 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) | 984 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) |
| @@ -1107,6 +1024,8 @@ static bool ad9389b_check_edid_status(struct v4l2_subdev *sd) | |||
| 1107 | } | 1024 | } |
| 1108 | if (!edid_segment_verify_crc(sd, segment)) { | 1025 | if (!edid_segment_verify_crc(sd, segment)) { |
| 1109 | /* edid crc error, force reread of edid segment */ | 1026 | /* edid crc error, force reread of edid segment */ |
| 1027 | v4l2_err(sd, "%s: edid crc error\n", __func__); | ||
| 1028 | state->have_monitor = false; | ||
| 1110 | ad9389b_s_power(sd, false); | 1029 | ad9389b_s_power(sd, false); |
| 1111 | ad9389b_s_power(sd, true); | 1030 | ad9389b_s_power(sd, true); |
| 1112 | return false; | 1031 | return false; |
| @@ -1190,27 +1109,27 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * | |||
| 1190 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, | 1109 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, |
| 1191 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, | 1110 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, |
| 1192 | 0, V4L2_DV_TX_MODE_DVI_D); | 1111 | 0, V4L2_DV_TX_MODE_DVI_D); |
| 1193 | state->hdmi_mode_ctrl->is_private = true; | ||
| 1194 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1112 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
| 1195 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); | 1113 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); |
| 1196 | state->hotplug_ctrl->is_private = true; | ||
| 1197 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1114 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
| 1198 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); | 1115 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); |
| 1199 | state->rx_sense_ctrl->is_private = true; | ||
| 1200 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 1116 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
| 1201 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); | 1117 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); |
| 1202 | state->have_edid0_ctrl->is_private = true; | ||
| 1203 | state->rgb_quantization_range_ctrl = | 1118 | state->rgb_quantization_range_ctrl = |
| 1204 | v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, | 1119 | v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, |
| 1205 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | 1120 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, |
| 1206 | 0, V4L2_DV_RGB_RANGE_AUTO); | 1121 | 0, V4L2_DV_RGB_RANGE_AUTO); |
| 1207 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 1208 | sd->ctrl_handler = hdl; | 1122 | sd->ctrl_handler = hdl; |
| 1209 | if (hdl->error) { | 1123 | if (hdl->error) { |
| 1210 | err = hdl->error; | 1124 | err = hdl->error; |
| 1211 | 1125 | ||
| 1212 | goto err_hdl; | 1126 | goto err_hdl; |
| 1213 | } | 1127 | } |
| 1128 | state->hdmi_mode_ctrl->is_private = true; | ||
| 1129 | state->hotplug_ctrl->is_private = true; | ||
| 1130 | state->rx_sense_ctrl->is_private = true; | ||
| 1131 | state->have_edid0_ctrl->is_private = true; | ||
| 1132 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 1214 | 1133 | ||
| 1215 | state->pad.flags = MEDIA_PAD_FL_SINK; | 1134 | state->pad.flags = MEDIA_PAD_FL_SINK; |
| 1216 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 1135 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); |
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 7606218ec4a7..aeb56c53e39f 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c | |||
| @@ -27,8 +27,10 @@ | |||
| 27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 28 | 28 | ||
| 29 | #include <media/adv7343.h> | 29 | #include <media/adv7343.h> |
| 30 | #include <media/v4l2-async.h> | ||
| 30 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
| 31 | #include <media/v4l2-ctrls.h> | 32 | #include <media/v4l2-ctrls.h> |
| 33 | #include <media/v4l2-of.h> | ||
| 32 | 34 | ||
| 33 | #include "adv7343_regs.h" | 35 | #include "adv7343_regs.h" |
| 34 | 36 | ||
| @@ -226,12 +228,12 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) | |||
| 226 | else | 228 | else |
| 227 | val = state->pdata->mode_config.sleep_mode << 0 | | 229 | val = state->pdata->mode_config.sleep_mode << 0 | |
| 228 | state->pdata->mode_config.pll_control << 1 | | 230 | state->pdata->mode_config.pll_control << 1 | |
| 229 | state->pdata->mode_config.dac_3 << 2 | | 231 | state->pdata->mode_config.dac[2] << 2 | |
| 230 | state->pdata->mode_config.dac_2 << 3 | | 232 | state->pdata->mode_config.dac[1] << 3 | |
| 231 | state->pdata->mode_config.dac_1 << 4 | | 233 | state->pdata->mode_config.dac[0] << 4 | |
| 232 | state->pdata->mode_config.dac_6 << 5 | | 234 | state->pdata->mode_config.dac[5] << 5 | |
| 233 | state->pdata->mode_config.dac_5 << 6 | | 235 | state->pdata->mode_config.dac[4] << 6 | |
| 234 | state->pdata->mode_config.dac_4 << 7; | 236 | state->pdata->mode_config.dac[3] << 7; |
| 235 | 237 | ||
| 236 | err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); | 238 | err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); |
| 237 | if (err < 0) | 239 | if (err < 0) |
| @@ -250,15 +252,15 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) | |||
| 250 | /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ | 252 | /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ |
| 251 | val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); | 253 | val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); |
| 252 | 254 | ||
| 253 | if (state->pdata && state->pdata->sd_config.sd_dac_out1) | 255 | if (state->pdata && state->pdata->sd_config.sd_dac_out[0]) |
| 254 | val = val | (state->pdata->sd_config.sd_dac_out1 << 1); | 256 | val = val | (state->pdata->sd_config.sd_dac_out[0] << 1); |
| 255 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out1) | 257 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out[0]) |
| 256 | val = val & ~(state->pdata->sd_config.sd_dac_out1 << 1); | 258 | val = val & ~(state->pdata->sd_config.sd_dac_out[0] << 1); |
| 257 | 259 | ||
| 258 | if (state->pdata && state->pdata->sd_config.sd_dac_out2) | 260 | if (state->pdata && state->pdata->sd_config.sd_dac_out[1]) |
| 259 | val = val | (state->pdata->sd_config.sd_dac_out2 << 2); | 261 | val = val | (state->pdata->sd_config.sd_dac_out[1] << 2); |
| 260 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out2) | 262 | else if (state->pdata && !state->pdata->sd_config.sd_dac_out[1]) |
| 261 | val = val & ~(state->pdata->sd_config.sd_dac_out2 << 2); | 263 | val = val & ~(state->pdata->sd_config.sd_dac_out[1] << 2); |
| 262 | 264 | ||
| 263 | err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); | 265 | err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); |
| 264 | if (err < 0) | 266 | if (err < 0) |
| @@ -398,6 +400,40 @@ static int adv7343_initialize(struct v4l2_subdev *sd) | |||
| 398 | return err; | 400 | return err; |
| 399 | } | 401 | } |
| 400 | 402 | ||
| 403 | static struct adv7343_platform_data * | ||
| 404 | adv7343_get_pdata(struct i2c_client *client) | ||
| 405 | { | ||
| 406 | struct adv7343_platform_data *pdata; | ||
| 407 | struct device_node *np; | ||
| 408 | |||
| 409 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) | ||
| 410 | return client->dev.platform_data; | ||
| 411 | |||
| 412 | np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); | ||
| 413 | if (!np) | ||
| 414 | return NULL; | ||
| 415 | |||
| 416 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 417 | if (!pdata) | ||
| 418 | goto done; | ||
| 419 | |||
| 420 | pdata->mode_config.sleep_mode = | ||
| 421 | of_property_read_bool(np, "adi,power-mode-sleep-mode"); | ||
| 422 | |||
| 423 | pdata->mode_config.pll_control = | ||
| 424 | of_property_read_bool(np, "adi,power-mode-pll-ctrl"); | ||
| 425 | |||
| 426 | of_property_read_u32_array(np, "adi,dac-enable", | ||
| 427 | pdata->mode_config.dac, 6); | ||
| 428 | |||
| 429 | of_property_read_u32_array(np, "adi,sd-dac-enable", | ||
| 430 | pdata->sd_config.sd_dac_out, 2); | ||
| 431 | |||
| 432 | done: | ||
| 433 | of_node_put(np); | ||
| 434 | return pdata; | ||
| 435 | } | ||
| 436 | |||
| 401 | static int adv7343_probe(struct i2c_client *client, | 437 | static int adv7343_probe(struct i2c_client *client, |
| 402 | const struct i2c_device_id *id) | 438 | const struct i2c_device_id *id) |
| 403 | { | 439 | { |
| @@ -416,7 +452,7 @@ static int adv7343_probe(struct i2c_client *client, | |||
| 416 | return -ENOMEM; | 452 | return -ENOMEM; |
| 417 | 453 | ||
| 418 | /* Copy board specific information here */ | 454 | /* Copy board specific information here */ |
| 419 | state->pdata = client->dev.platform_data; | 455 | state->pdata = adv7343_get_pdata(client); |
| 420 | 456 | ||
| 421 | state->reg00 = 0x80; | 457 | state->reg00 = 0x80; |
| 422 | state->reg01 = 0x00; | 458 | state->reg01 = 0x00; |
| @@ -445,16 +481,21 @@ static int adv7343_probe(struct i2c_client *client, | |||
| 445 | ADV7343_GAIN_DEF); | 481 | ADV7343_GAIN_DEF); |
| 446 | state->sd.ctrl_handler = &state->hdl; | 482 | state->sd.ctrl_handler = &state->hdl; |
| 447 | if (state->hdl.error) { | 483 | if (state->hdl.error) { |
| 448 | int err = state->hdl.error; | 484 | err = state->hdl.error; |
| 449 | 485 | goto done; | |
| 450 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 451 | return err; | ||
| 452 | } | 486 | } |
| 453 | v4l2_ctrl_handler_setup(&state->hdl); | 487 | v4l2_ctrl_handler_setup(&state->hdl); |
| 454 | 488 | ||
| 455 | err = adv7343_initialize(&state->sd); | 489 | err = adv7343_initialize(&state->sd); |
| 456 | if (err) | 490 | if (err) |
| 491 | goto done; | ||
| 492 | |||
| 493 | err = v4l2_async_register_subdev(&state->sd); | ||
| 494 | |||
| 495 | done: | ||
| 496 | if (err < 0) | ||
| 457 | v4l2_ctrl_handler_free(&state->hdl); | 497 | v4l2_ctrl_handler_free(&state->hdl); |
| 498 | |||
| 458 | return err; | 499 | return err; |
| 459 | } | 500 | } |
| 460 | 501 | ||
| @@ -463,6 +504,7 @@ static int adv7343_remove(struct i2c_client *client) | |||
| 463 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 504 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 464 | struct adv7343_state *state = to_state(sd); | 505 | struct adv7343_state *state = to_state(sd); |
| 465 | 506 | ||
| 507 | v4l2_async_unregister_subdev(&state->sd); | ||
| 466 | v4l2_device_unregister_subdev(sd); | 508 | v4l2_device_unregister_subdev(sd); |
| 467 | v4l2_ctrl_handler_free(&state->hdl); | 509 | v4l2_ctrl_handler_free(&state->hdl); |
| 468 | 510 | ||
| @@ -476,8 +518,17 @@ static const struct i2c_device_id adv7343_id[] = { | |||
| 476 | 518 | ||
| 477 | MODULE_DEVICE_TABLE(i2c, adv7343_id); | 519 | MODULE_DEVICE_TABLE(i2c, adv7343_id); |
| 478 | 520 | ||
| 521 | #if IS_ENABLED(CONFIG_OF) | ||
| 522 | static const struct of_device_id adv7343_of_match[] = { | ||
| 523 | {.compatible = "adi,adv7343", }, | ||
| 524 | { /* sentinel */ }, | ||
| 525 | }; | ||
| 526 | MODULE_DEVICE_TABLE(of, adv7343_of_match); | ||
| 527 | #endif | ||
| 528 | |||
| 479 | static struct i2c_driver adv7343_driver = { | 529 | static struct i2c_driver adv7343_driver = { |
| 480 | .driver = { | 530 | .driver = { |
| 531 | .of_match_table = of_match_ptr(adv7343_of_match), | ||
| 481 | .owner = THIS_MODULE, | 532 | .owner = THIS_MODULE, |
| 482 | .name = "adv7343", | 533 | .name = "adv7343", |
| 483 | }, | 534 | }, |
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c new file mode 100644 index 000000000000..7a576097471f --- /dev/null +++ b/drivers/media/i2c/adv7511.c | |||
| @@ -0,0 +1,1198 @@ | |||
| 1 | /* | ||
| 2 | * Analog Devices ADV7511 HDMI Transmitter Device Driver | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | */ | ||
| 19 | |||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/videodev2.h> | ||
| 27 | #include <linux/gpio.h> | ||
| 28 | #include <linux/workqueue.h> | ||
| 29 | #include <linux/v4l2-dv-timings.h> | ||
| 30 | #include <media/v4l2-device.h> | ||
| 31 | #include <media/v4l2-common.h> | ||
| 32 | #include <media/v4l2-ctrls.h> | ||
| 33 | #include <media/v4l2-dv-timings.h> | ||
| 34 | #include <media/adv7511.h> | ||
| 35 | |||
| 36 | static int debug; | ||
| 37 | module_param(debug, int, 0644); | ||
| 38 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
| 39 | |||
| 40 | MODULE_DESCRIPTION("Analog Devices ADV7511 HDMI Transmitter Device Driver"); | ||
| 41 | MODULE_AUTHOR("Hans Verkuil"); | ||
| 42 | MODULE_LICENSE("GPL"); | ||
| 43 | |||
| 44 | #define MASK_ADV7511_EDID_RDY_INT 0x04 | ||
| 45 | #define MASK_ADV7511_MSEN_INT 0x40 | ||
| 46 | #define MASK_ADV7511_HPD_INT 0x80 | ||
| 47 | |||
| 48 | #define MASK_ADV7511_HPD_DETECT 0x40 | ||
| 49 | #define MASK_ADV7511_MSEN_DETECT 0x20 | ||
| 50 | #define MASK_ADV7511_EDID_RDY 0x10 | ||
| 51 | |||
| 52 | #define EDID_MAX_RETRIES (8) | ||
| 53 | #define EDID_DELAY 250 | ||
| 54 | #define EDID_MAX_SEGM 8 | ||
| 55 | |||
| 56 | #define ADV7511_MAX_WIDTH 1920 | ||
| 57 | #define ADV7511_MAX_HEIGHT 1200 | ||
| 58 | #define ADV7511_MIN_PIXELCLOCK 20000000 | ||
| 59 | #define ADV7511_MAX_PIXELCLOCK 225000000 | ||
| 60 | |||
| 61 | /* | ||
| 62 | ********************************************************************** | ||
| 63 | * | ||
| 64 | * Arrays with configuration parameters for the ADV7511 | ||
| 65 | * | ||
| 66 | ********************************************************************** | ||
| 67 | */ | ||
| 68 | |||
| 69 | struct i2c_reg_value { | ||
| 70 | unsigned char reg; | ||
| 71 | unsigned char value; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct adv7511_state_edid { | ||
| 75 | /* total number of blocks */ | ||
| 76 | u32 blocks; | ||
| 77 | /* Number of segments read */ | ||
| 78 | u32 segments; | ||
| 79 | uint8_t data[EDID_MAX_SEGM * 256]; | ||
| 80 | /* Number of EDID read retries left */ | ||
| 81 | unsigned read_retries; | ||
| 82 | bool complete; | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct adv7511_state { | ||
| 86 | struct adv7511_platform_data pdata; | ||
| 87 | struct v4l2_subdev sd; | ||
| 88 | struct media_pad pad; | ||
| 89 | struct v4l2_ctrl_handler hdl; | ||
| 90 | int chip_revision; | ||
| 91 | uint8_t i2c_edid_addr; | ||
| 92 | uint8_t i2c_cec_addr; | ||
| 93 | /* Is the adv7511 powered on? */ | ||
| 94 | bool power_on; | ||
| 95 | /* Did we receive hotplug and rx-sense signals? */ | ||
| 96 | bool have_monitor; | ||
| 97 | /* timings from s_dv_timings */ | ||
| 98 | struct v4l2_dv_timings dv_timings; | ||
| 99 | /* controls */ | ||
| 100 | struct v4l2_ctrl *hdmi_mode_ctrl; | ||
| 101 | struct v4l2_ctrl *hotplug_ctrl; | ||
| 102 | struct v4l2_ctrl *rx_sense_ctrl; | ||
| 103 | struct v4l2_ctrl *have_edid0_ctrl; | ||
| 104 | struct v4l2_ctrl *rgb_quantization_range_ctrl; | ||
| 105 | struct i2c_client *i2c_edid; | ||
| 106 | struct adv7511_state_edid edid; | ||
| 107 | /* Running counter of the number of detected EDIDs (for debugging) */ | ||
| 108 | unsigned edid_detect_counter; | ||
| 109 | struct workqueue_struct *work_queue; | ||
| 110 | struct delayed_work edid_handler; /* work entry */ | ||
| 111 | }; | ||
| 112 | |||
| 113 | static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd); | ||
| 114 | static bool adv7511_check_edid_status(struct v4l2_subdev *sd); | ||
| 115 | static void adv7511_setup(struct v4l2_subdev *sd); | ||
| 116 | static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq); | ||
| 117 | static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq); | ||
| 118 | |||
| 119 | |||
| 120 | static const struct v4l2_dv_timings_cap adv7511_timings_cap = { | ||
| 121 | .type = V4L2_DV_BT_656_1120, | ||
| 122 | .bt = { | ||
| 123 | .max_width = ADV7511_MAX_WIDTH, | ||
| 124 | .max_height = ADV7511_MAX_HEIGHT, | ||
| 125 | .min_pixelclock = ADV7511_MIN_PIXELCLOCK, | ||
| 126 | .max_pixelclock = ADV7511_MAX_PIXELCLOCK, | ||
| 127 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
| 128 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
| 129 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
| 130 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
| 131 | }, | ||
| 132 | }; | ||
| 133 | |||
| 134 | static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd) | ||
| 135 | { | ||
| 136 | return container_of(sd, struct adv7511_state, sd); | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
| 140 | { | ||
| 141 | return &container_of(ctrl->handler, struct adv7511_state, hdl)->sd; | ||
| 142 | } | ||
| 143 | |||
| 144 | /* ------------------------ I2C ----------------------------------------------- */ | ||
| 145 | |||
| 146 | static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, | ||
| 147 | u8 command, bool check) | ||
| 148 | { | ||
| 149 | union i2c_smbus_data data; | ||
| 150 | |||
| 151 | if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
| 152 | I2C_SMBUS_READ, command, | ||
| 153 | I2C_SMBUS_BYTE_DATA, &data)) | ||
| 154 | return data.byte; | ||
| 155 | if (check) | ||
| 156 | v4l_err(client, "error reading %02x, %02x\n", | ||
| 157 | client->addr, command); | ||
| 158 | return -1; | ||
| 159 | } | ||
| 160 | |||
| 161 | static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) | ||
| 162 | { | ||
| 163 | int i; | ||
| 164 | for (i = 0; i < 3; i++) { | ||
| 165 | int ret = adv_smbus_read_byte_data_check(client, command, true); | ||
| 166 | if (ret >= 0) { | ||
| 167 | if (i) | ||
| 168 | v4l_err(client, "read ok after %d retries\n", i); | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | v4l_err(client, "read failed\n"); | ||
| 173 | return -1; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int adv7511_rd(struct v4l2_subdev *sd, u8 reg) | ||
| 177 | { | ||
| 178 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 179 | |||
| 180 | return adv_smbus_read_byte_data(client, reg); | ||
| 181 | } | ||
| 182 | |||
| 183 | static int adv7511_wr(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 184 | { | ||
| 185 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 186 | int ret; | ||
| 187 | int i; | ||
| 188 | |||
| 189 | for (i = 0; i < 3; i++) { | ||
| 190 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
| 191 | if (ret == 0) | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | v4l2_err(sd, "%s: i2c write error\n", __func__); | ||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | /* To set specific bits in the register, a clear-mask is given (to be AND-ed), | ||
| 199 | and then the value-mask (to be OR-ed). */ | ||
| 200 | static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, uint8_t clr_mask, uint8_t val_mask) | ||
| 201 | { | ||
| 202 | adv7511_wr(sd, reg, (adv7511_rd(sd, reg) & clr_mask) | val_mask); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int adv_smbus_read_i2c_block_data(struct i2c_client *client, | ||
| 206 | u8 command, unsigned length, u8 *values) | ||
| 207 | { | ||
| 208 | union i2c_smbus_data data; | ||
| 209 | int ret; | ||
| 210 | |||
| 211 | if (length > I2C_SMBUS_BLOCK_MAX) | ||
| 212 | length = I2C_SMBUS_BLOCK_MAX; | ||
| 213 | data.block[0] = length; | ||
| 214 | |||
| 215 | ret = i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
| 216 | I2C_SMBUS_READ, command, | ||
| 217 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | ||
| 218 | memcpy(values, data.block + 1, length); | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static inline void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf) | ||
| 223 | { | ||
| 224 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 225 | int i; | ||
| 226 | int err = 0; | ||
| 227 | |||
| 228 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 229 | |||
| 230 | for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX) | ||
| 231 | err = adv_smbus_read_i2c_block_data(state->i2c_edid, i, | ||
| 232 | I2C_SMBUS_BLOCK_MAX, buf + i); | ||
| 233 | if (err) | ||
| 234 | v4l2_err(sd, "%s: i2c read error\n", __func__); | ||
| 235 | } | ||
| 236 | |||
| 237 | static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd) | ||
| 238 | { | ||
| 239 | return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT; | ||
| 240 | } | ||
| 241 | |||
| 242 | static inline bool adv7511_have_rx_sense(struct v4l2_subdev *sd) | ||
| 243 | { | ||
| 244 | return adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT; | ||
| 245 | } | ||
| 246 | |||
| 247 | static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, uint8_t mode) | ||
| 248 | { | ||
| 249 | adv7511_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5); | ||
| 250 | } | ||
| 251 | |||
| 252 | static void adv7511_csc_coeff(struct v4l2_subdev *sd, | ||
| 253 | u16 A1, u16 A2, u16 A3, u16 A4, | ||
| 254 | u16 B1, u16 B2, u16 B3, u16 B4, | ||
| 255 | u16 C1, u16 C2, u16 C3, u16 C4) | ||
| 256 | { | ||
| 257 | /* A */ | ||
| 258 | adv7511_wr_and_or(sd, 0x18, 0xe0, A1>>8); | ||
| 259 | adv7511_wr(sd, 0x19, A1); | ||
| 260 | adv7511_wr_and_or(sd, 0x1A, 0xe0, A2>>8); | ||
| 261 | adv7511_wr(sd, 0x1B, A2); | ||
| 262 | adv7511_wr_and_or(sd, 0x1c, 0xe0, A3>>8); | ||
| 263 | adv7511_wr(sd, 0x1d, A3); | ||
| 264 | adv7511_wr_and_or(sd, 0x1e, 0xe0, A4>>8); | ||
| 265 | adv7511_wr(sd, 0x1f, A4); | ||
| 266 | |||
| 267 | /* B */ | ||
| 268 | adv7511_wr_and_or(sd, 0x20, 0xe0, B1>>8); | ||
| 269 | adv7511_wr(sd, 0x21, B1); | ||
| 270 | adv7511_wr_and_or(sd, 0x22, 0xe0, B2>>8); | ||
| 271 | adv7511_wr(sd, 0x23, B2); | ||
| 272 | adv7511_wr_and_or(sd, 0x24, 0xe0, B3>>8); | ||
| 273 | adv7511_wr(sd, 0x25, B3); | ||
| 274 | adv7511_wr_and_or(sd, 0x26, 0xe0, B4>>8); | ||
| 275 | adv7511_wr(sd, 0x27, B4); | ||
| 276 | |||
| 277 | /* C */ | ||
| 278 | adv7511_wr_and_or(sd, 0x28, 0xe0, C1>>8); | ||
| 279 | adv7511_wr(sd, 0x29, C1); | ||
| 280 | adv7511_wr_and_or(sd, 0x2A, 0xe0, C2>>8); | ||
| 281 | adv7511_wr(sd, 0x2B, C2); | ||
| 282 | adv7511_wr_and_or(sd, 0x2C, 0xe0, C3>>8); | ||
| 283 | adv7511_wr(sd, 0x2D, C3); | ||
| 284 | adv7511_wr_and_or(sd, 0x2E, 0xe0, C4>>8); | ||
| 285 | adv7511_wr(sd, 0x2F, C4); | ||
| 286 | } | ||
| 287 | |||
| 288 | static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) | ||
| 289 | { | ||
| 290 | if (enable) { | ||
| 291 | uint8_t csc_mode = 0; | ||
| 292 | adv7511_csc_conversion_mode(sd, csc_mode); | ||
| 293 | adv7511_csc_coeff(sd, | ||
| 294 | 4096-564, 0, 0, 256, | ||
| 295 | 0, 4096-564, 0, 256, | ||
| 296 | 0, 0, 4096-564, 256); | ||
| 297 | /* enable CSC */ | ||
| 298 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x80); | ||
| 299 | /* AVI infoframe: Limited range RGB (16-235) */ | ||
| 300 | adv7511_wr_and_or(sd, 0x57, 0xf3, 0x04); | ||
| 301 | } else { | ||
| 302 | /* disable CSC */ | ||
| 303 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); | ||
| 304 | /* AVI infoframe: Full range RGB (0-255) */ | ||
| 305 | adv7511_wr_and_or(sd, 0x57, 0xf3, 0x08); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | static void adv7511_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd) | ||
| 310 | { | ||
| 311 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 312 | if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
| 313 | /* CEA format, not IT */ | ||
| 314 | adv7511_wr_and_or(sd, 0x57, 0x7f, 0x00); | ||
| 315 | } else { | ||
| 316 | /* IT format */ | ||
| 317 | adv7511_wr_and_or(sd, 0x57, 0x7f, 0x80); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) | ||
| 322 | { | ||
| 323 | switch (ctrl->val) { | ||
| 324 | default: | ||
| 325 | return -EINVAL; | ||
| 326 | break; | ||
| 327 | case V4L2_DV_RGB_RANGE_AUTO: { | ||
| 328 | /* automatic */ | ||
| 329 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 330 | |||
| 331 | if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
| 332 | /* cea format, RGB limited range (16-235) */ | ||
| 333 | adv7511_csc_rgb_full2limit(sd, true); | ||
| 334 | } else { | ||
| 335 | /* not cea format, RGB full range (0-255) */ | ||
| 336 | adv7511_csc_rgb_full2limit(sd, false); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | break; | ||
| 340 | case V4L2_DV_RGB_RANGE_LIMITED: | ||
| 341 | /* RGB limited range (16-235) */ | ||
| 342 | adv7511_csc_rgb_full2limit(sd, true); | ||
| 343 | break; | ||
| 344 | case V4L2_DV_RGB_RANGE_FULL: | ||
| 345 | /* RGB full range (0-255) */ | ||
| 346 | adv7511_csc_rgb_full2limit(sd, false); | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* ------------------------------ CTRL OPS ------------------------------ */ | ||
| 353 | |||
| 354 | static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 355 | { | ||
| 356 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
| 357 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 358 | |||
| 359 | v4l2_dbg(1, debug, sd, "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val); | ||
| 360 | |||
| 361 | if (state->hdmi_mode_ctrl == ctrl) { | ||
| 362 | /* Set HDMI or DVI-D */ | ||
| 363 | adv7511_wr_and_or(sd, 0xaf, 0xfd, ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00); | ||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | if (state->rgb_quantization_range_ctrl == ctrl) | ||
| 367 | return adv7511_set_rgb_quantization_mode(sd, ctrl); | ||
| 368 | |||
| 369 | return -EINVAL; | ||
| 370 | } | ||
| 371 | |||
| 372 | static const struct v4l2_ctrl_ops adv7511_ctrl_ops = { | ||
| 373 | .s_ctrl = adv7511_s_ctrl, | ||
| 374 | }; | ||
| 375 | |||
| 376 | /* ---------------------------- CORE OPS ------------------------------------------- */ | ||
| 377 | |||
| 378 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 379 | static void adv7511_inv_register(struct v4l2_subdev *sd) | ||
| 380 | { | ||
| 381 | v4l2_info(sd, "0x000-0x0ff: Main Map\n"); | ||
| 382 | } | ||
| 383 | |||
| 384 | static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
| 385 | { | ||
| 386 | reg->size = 1; | ||
| 387 | switch (reg->reg >> 8) { | ||
| 388 | case 0: | ||
| 389 | reg->val = adv7511_rd(sd, reg->reg & 0xff); | ||
| 390 | break; | ||
| 391 | default: | ||
| 392 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
| 393 | adv7511_inv_register(sd); | ||
| 394 | break; | ||
| 395 | } | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) | ||
| 400 | { | ||
| 401 | switch (reg->reg >> 8) { | ||
| 402 | case 0: | ||
| 403 | adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff); | ||
| 404 | break; | ||
| 405 | default: | ||
| 406 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
| 407 | adv7511_inv_register(sd); | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | #endif | ||
| 413 | |||
| 414 | static int adv7511_log_status(struct v4l2_subdev *sd) | ||
| 415 | { | ||
| 416 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 417 | struct adv7511_state_edid *edid = &state->edid; | ||
| 418 | |||
| 419 | static const char * const states[] = { | ||
| 420 | "in reset", | ||
| 421 | "reading EDID", | ||
| 422 | "idle", | ||
| 423 | "initializing HDCP", | ||
| 424 | "HDCP enabled", | ||
| 425 | "initializing HDCP repeater", | ||
| 426 | "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" | ||
| 427 | }; | ||
| 428 | static const char * const errors[] = { | ||
| 429 | "no error", | ||
| 430 | "bad receiver BKSV", | ||
| 431 | "Ri mismatch", | ||
| 432 | "Pj mismatch", | ||
| 433 | "i2c error", | ||
| 434 | "timed out", | ||
| 435 | "max repeater cascade exceeded", | ||
| 436 | "hash check failed", | ||
| 437 | "too many devices", | ||
| 438 | "9", "A", "B", "C", "D", "E", "F" | ||
| 439 | }; | ||
| 440 | |||
| 441 | v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off"); | ||
| 442 | v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n", | ||
| 443 | (adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT) ? "detected" : "no", | ||
| 444 | (adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT) ? "detected" : "no", | ||
| 445 | edid->segments ? "found" : "no", | ||
| 446 | edid->blocks); | ||
| 447 | v4l2_info(sd, "%s output %s\n", | ||
| 448 | (adv7511_rd(sd, 0xaf) & 0x02) ? | ||
| 449 | "HDMI" : "DVI-D", | ||
| 450 | (adv7511_rd(sd, 0xa1) & 0x3c) ? | ||
| 451 | "disabled" : "enabled"); | ||
| 452 | v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n", | ||
| 453 | states[adv7511_rd(sd, 0xc8) & 0xf], | ||
| 454 | errors[adv7511_rd(sd, 0xc8) >> 4], state->edid_detect_counter, | ||
| 455 | adv7511_rd(sd, 0x94), adv7511_rd(sd, 0x96)); | ||
| 456 | v4l2_info(sd, "RGB quantization: %s range\n", adv7511_rd(sd, 0x18) & 0x80 ? "limited" : "full"); | ||
| 457 | if (state->dv_timings.type == V4L2_DV_BT_656_1120) | ||
| 458 | v4l2_print_dv_timings(sd->name, "timings: ", | ||
| 459 | &state->dv_timings, false); | ||
| 460 | else | ||
| 461 | v4l2_info(sd, "no timings set\n"); | ||
| 462 | v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr); | ||
| 463 | v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr); | ||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* Power up/down adv7511 */ | ||
| 468 | static int adv7511_s_power(struct v4l2_subdev *sd, int on) | ||
| 469 | { | ||
| 470 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 471 | const int retries = 20; | ||
| 472 | int i; | ||
| 473 | |||
| 474 | v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); | ||
| 475 | |||
| 476 | state->power_on = on; | ||
| 477 | |||
| 478 | if (!on) { | ||
| 479 | /* Power down */ | ||
| 480 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); | ||
| 481 | return true; | ||
| 482 | } | ||
| 483 | |||
| 484 | /* Power up */ | ||
| 485 | /* The adv7511 does not always come up immediately. | ||
| 486 | Retry multiple times. */ | ||
| 487 | for (i = 0; i < retries; i++) { | ||
| 488 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x0); | ||
| 489 | if ((adv7511_rd(sd, 0x41) & 0x40) == 0) | ||
| 490 | break; | ||
| 491 | adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); | ||
| 492 | msleep(10); | ||
| 493 | } | ||
| 494 | if (i == retries) { | ||
| 495 | v4l2_dbg(1, debug, sd, "%s: failed to powerup the adv7511!\n", __func__); | ||
| 496 | adv7511_s_power(sd, 0); | ||
| 497 | return false; | ||
| 498 | } | ||
| 499 | if (i > 1) | ||
| 500 | v4l2_dbg(1, debug, sd, "%s: needed %d retries to powerup the adv7511\n", __func__, i); | ||
| 501 | |||
| 502 | /* Reserved registers that must be set */ | ||
| 503 | adv7511_wr(sd, 0x98, 0x03); | ||
| 504 | adv7511_wr_and_or(sd, 0x9a, 0xfe, 0x70); | ||
| 505 | adv7511_wr(sd, 0x9c, 0x30); | ||
| 506 | adv7511_wr_and_or(sd, 0x9d, 0xfc, 0x01); | ||
| 507 | adv7511_wr(sd, 0xa2, 0xa4); | ||
| 508 | adv7511_wr(sd, 0xa3, 0xa4); | ||
| 509 | adv7511_wr(sd, 0xe0, 0xd0); | ||
| 510 | adv7511_wr(sd, 0xf9, 0x00); | ||
| 511 | |||
| 512 | adv7511_wr(sd, 0x43, state->i2c_edid_addr); | ||
| 513 | |||
| 514 | /* Set number of attempts to read the EDID */ | ||
| 515 | adv7511_wr(sd, 0xc9, 0xf); | ||
| 516 | return true; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* Enable interrupts */ | ||
| 520 | static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) | ||
| 521 | { | ||
| 522 | uint8_t irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT; | ||
| 523 | uint8_t irqs_rd; | ||
| 524 | int retries = 100; | ||
| 525 | |||
| 526 | v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable"); | ||
| 527 | |||
| 528 | /* The datasheet says that the EDID ready interrupt should be | ||
| 529 | disabled if there is no hotplug. */ | ||
| 530 | if (!enable) | ||
| 531 | irqs = 0; | ||
| 532 | else if (adv7511_have_hotplug(sd)) | ||
| 533 | irqs |= MASK_ADV7511_EDID_RDY_INT; | ||
| 534 | |||
| 535 | /* | ||
| 536 | * This i2c write can fail (approx. 1 in 1000 writes). But it | ||
| 537 | * is essential that this register is correct, so retry it | ||
| 538 | * multiple times. | ||
| 539 | * | ||
| 540 | * Note that the i2c write does not report an error, but the readback | ||
| 541 | * clearly shows the wrong value. | ||
| 542 | */ | ||
| 543 | do { | ||
| 544 | adv7511_wr(sd, 0x94, irqs); | ||
| 545 | irqs_rd = adv7511_rd(sd, 0x94); | ||
| 546 | } while (retries-- && irqs_rd != irqs); | ||
| 547 | |||
| 548 | if (irqs_rd == irqs) | ||
| 549 | return; | ||
| 550 | v4l2_err(sd, "Could not set interrupts: hw failure?\n"); | ||
| 551 | } | ||
| 552 | |||
| 553 | /* Interrupt handler */ | ||
| 554 | static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | ||
| 555 | { | ||
| 556 | uint8_t irq_status; | ||
| 557 | |||
| 558 | /* disable interrupts to prevent a race condition */ | ||
| 559 | adv7511_set_isr(sd, false); | ||
| 560 | irq_status = adv7511_rd(sd, 0x96); | ||
| 561 | /* clear detected interrupts */ | ||
| 562 | adv7511_wr(sd, 0x96, irq_status); | ||
| 563 | |||
| 564 | v4l2_dbg(1, debug, sd, "%s: irq 0x%x\n", __func__, irq_status); | ||
| 565 | |||
| 566 | if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT)) | ||
| 567 | adv7511_check_monitor_present_status(sd); | ||
| 568 | if (irq_status & MASK_ADV7511_EDID_RDY_INT) | ||
| 569 | adv7511_check_edid_status(sd); | ||
| 570 | |||
| 571 | /* enable interrupts */ | ||
| 572 | adv7511_set_isr(sd, true); | ||
| 573 | |||
| 574 | if (handled) | ||
| 575 | *handled = true; | ||
| 576 | return 0; | ||
| 577 | } | ||
| 578 | |||
| 579 | static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) | ||
| 580 | { | ||
| 581 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 582 | |||
| 583 | if (edid->pad != 0) | ||
| 584 | return -EINVAL; | ||
| 585 | if ((edid->blocks == 0) || (edid->blocks > 256)) | ||
| 586 | return -EINVAL; | ||
| 587 | if (!edid->edid) | ||
| 588 | return -EINVAL; | ||
| 589 | if (!state->edid.segments) { | ||
| 590 | v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | ||
| 591 | return -ENODATA; | ||
| 592 | } | ||
| 593 | if (edid->start_block >= state->edid.segments * 2) | ||
| 594 | return -E2BIG; | ||
| 595 | if ((edid->blocks + edid->start_block) >= state->edid.segments * 2) | ||
| 596 | edid->blocks = state->edid.segments * 2 - edid->start_block; | ||
| 597 | |||
| 598 | memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | ||
| 599 | 128 * edid->blocks); | ||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | |||
| 603 | static const struct v4l2_subdev_pad_ops adv7511_pad_ops = { | ||
| 604 | .get_edid = adv7511_get_edid, | ||
| 605 | }; | ||
| 606 | |||
| 607 | static const struct v4l2_subdev_core_ops adv7511_core_ops = { | ||
| 608 | .log_status = adv7511_log_status, | ||
| 609 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 610 | .g_register = adv7511_g_register, | ||
| 611 | .s_register = adv7511_s_register, | ||
| 612 | #endif | ||
| 613 | .s_power = adv7511_s_power, | ||
| 614 | .interrupt_service_routine = adv7511_isr, | ||
| 615 | }; | ||
| 616 | |||
| 617 | /* ------------------------------ VIDEO OPS ------------------------------ */ | ||
| 618 | |||
| 619 | /* Enable/disable adv7511 output */ | ||
| 620 | static int adv7511_s_stream(struct v4l2_subdev *sd, int enable) | ||
| 621 | { | ||
| 622 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 623 | |||
| 624 | v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); | ||
| 625 | adv7511_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c)); | ||
| 626 | if (enable) { | ||
| 627 | adv7511_check_monitor_present_status(sd); | ||
| 628 | } else { | ||
| 629 | adv7511_s_power(sd, 0); | ||
| 630 | state->have_monitor = false; | ||
| 631 | } | ||
| 632 | return 0; | ||
| 633 | } | ||
| 634 | |||
| 635 | static int adv7511_s_dv_timings(struct v4l2_subdev *sd, | ||
| 636 | struct v4l2_dv_timings *timings) | ||
| 637 | { | ||
| 638 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 639 | |||
| 640 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 641 | |||
| 642 | /* quick sanity check */ | ||
| 643 | if (!v4l2_valid_dv_timings(timings, &adv7511_timings_cap, NULL, NULL)) | ||
| 644 | return -EINVAL; | ||
| 645 | |||
| 646 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | ||
| 647 | if the format is one of the CEA or DMT timings. */ | ||
| 648 | v4l2_find_dv_timings_cap(timings, &adv7511_timings_cap, 0, NULL, NULL); | ||
| 649 | |||
| 650 | timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; | ||
| 651 | |||
| 652 | /* save timings */ | ||
| 653 | state->dv_timings = *timings; | ||
| 654 | |||
| 655 | /* update quantization range based on new dv_timings */ | ||
| 656 | adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); | ||
| 657 | |||
| 658 | /* update AVI infoframe */ | ||
| 659 | adv7511_set_IT_content_AVI_InfoFrame(sd); | ||
| 660 | |||
| 661 | return 0; | ||
| 662 | } | ||
| 663 | |||
| 664 | static int adv7511_g_dv_timings(struct v4l2_subdev *sd, | ||
| 665 | struct v4l2_dv_timings *timings) | ||
| 666 | { | ||
| 667 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 668 | |||
| 669 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 670 | |||
| 671 | if (!timings) | ||
| 672 | return -EINVAL; | ||
| 673 | |||
| 674 | *timings = state->dv_timings; | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static int adv7511_enum_dv_timings(struct v4l2_subdev *sd, | ||
| 680 | struct v4l2_enum_dv_timings *timings) | ||
| 681 | { | ||
| 682 | return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL); | ||
| 683 | } | ||
| 684 | |||
| 685 | static int adv7511_dv_timings_cap(struct v4l2_subdev *sd, | ||
| 686 | struct v4l2_dv_timings_cap *cap) | ||
| 687 | { | ||
| 688 | *cap = adv7511_timings_cap; | ||
| 689 | return 0; | ||
| 690 | } | ||
| 691 | |||
| 692 | static const struct v4l2_subdev_video_ops adv7511_video_ops = { | ||
| 693 | .s_stream = adv7511_s_stream, | ||
| 694 | .s_dv_timings = adv7511_s_dv_timings, | ||
| 695 | .g_dv_timings = adv7511_g_dv_timings, | ||
| 696 | .enum_dv_timings = adv7511_enum_dv_timings, | ||
| 697 | .dv_timings_cap = adv7511_dv_timings_cap, | ||
| 698 | }; | ||
| 699 | |||
| 700 | /* ------------------------------ AUDIO OPS ------------------------------ */ | ||
| 701 | static int adv7511_s_audio_stream(struct v4l2_subdev *sd, int enable) | ||
| 702 | { | ||
| 703 | v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); | ||
| 704 | |||
| 705 | if (enable) | ||
| 706 | adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x80); | ||
| 707 | else | ||
| 708 | adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x40); | ||
| 709 | |||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | ||
| 714 | { | ||
| 715 | u32 N; | ||
| 716 | |||
| 717 | switch (freq) { | ||
| 718 | case 32000: N = 4096; break; | ||
| 719 | case 44100: N = 6272; break; | ||
| 720 | case 48000: N = 6144; break; | ||
| 721 | case 88200: N = 12544; break; | ||
| 722 | case 96000: N = 12288; break; | ||
| 723 | case 176400: N = 25088; break; | ||
| 724 | case 192000: N = 24576; break; | ||
| 725 | default: | ||
| 726 | return -EINVAL; | ||
| 727 | } | ||
| 728 | |||
| 729 | /* Set N (used with CTS to regenerate the audio clock) */ | ||
| 730 | adv7511_wr(sd, 0x01, (N >> 16) & 0xf); | ||
| 731 | adv7511_wr(sd, 0x02, (N >> 8) & 0xff); | ||
| 732 | adv7511_wr(sd, 0x03, N & 0xff); | ||
| 733 | |||
| 734 | return 0; | ||
| 735 | } | ||
| 736 | |||
| 737 | static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) | ||
| 738 | { | ||
| 739 | u32 i2s_sf; | ||
| 740 | |||
| 741 | switch (freq) { | ||
| 742 | case 32000: i2s_sf = 0x30; break; | ||
| 743 | case 44100: i2s_sf = 0x00; break; | ||
| 744 | case 48000: i2s_sf = 0x20; break; | ||
| 745 | case 88200: i2s_sf = 0x80; break; | ||
| 746 | case 96000: i2s_sf = 0xa0; break; | ||
| 747 | case 176400: i2s_sf = 0xc0; break; | ||
| 748 | case 192000: i2s_sf = 0xe0; break; | ||
| 749 | default: | ||
| 750 | return -EINVAL; | ||
| 751 | } | ||
| 752 | |||
| 753 | /* Set sampling frequency for I2S audio to 48 kHz */ | ||
| 754 | adv7511_wr_and_or(sd, 0x15, 0xf, i2s_sf); | ||
| 755 | |||
| 756 | return 0; | ||
| 757 | } | ||
| 758 | |||
| 759 | static int adv7511_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) | ||
| 760 | { | ||
| 761 | /* Only 2 channels in use for application */ | ||
| 762 | adv7511_wr_and_or(sd, 0x73, 0xf8, 0x1); | ||
| 763 | /* Speaker mapping */ | ||
| 764 | adv7511_wr(sd, 0x76, 0x00); | ||
| 765 | |||
| 766 | /* 16 bit audio word length */ | ||
| 767 | adv7511_wr_and_or(sd, 0x14, 0xf0, 0x02); | ||
| 768 | |||
| 769 | return 0; | ||
| 770 | } | ||
| 771 | |||
| 772 | static const struct v4l2_subdev_audio_ops adv7511_audio_ops = { | ||
| 773 | .s_stream = adv7511_s_audio_stream, | ||
| 774 | .s_clock_freq = adv7511_s_clock_freq, | ||
| 775 | .s_i2s_clock_freq = adv7511_s_i2s_clock_freq, | ||
| 776 | .s_routing = adv7511_s_routing, | ||
| 777 | }; | ||
| 778 | |||
| 779 | /* --------------------- SUBDEV OPS --------------------------------------- */ | ||
| 780 | |||
| 781 | static const struct v4l2_subdev_ops adv7511_ops = { | ||
| 782 | .core = &adv7511_core_ops, | ||
| 783 | .pad = &adv7511_pad_ops, | ||
| 784 | .video = &adv7511_video_ops, | ||
| 785 | .audio = &adv7511_audio_ops, | ||
| 786 | }; | ||
| 787 | |||
| 788 | /* ----------------------------------------------------------------------- */ | ||
| 789 | static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, uint8_t *buf) | ||
| 790 | { | ||
| 791 | if (debug >= lvl) { | ||
| 792 | int i, j; | ||
| 793 | v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment); | ||
| 794 | for (i = 0; i < 256; i += 16) { | ||
| 795 | u8 b[128]; | ||
| 796 | u8 *bp = b; | ||
| 797 | if (i == 128) | ||
| 798 | v4l2_dbg(lvl, debug, sd, "\n"); | ||
| 799 | for (j = i; j < i + 16; j++) { | ||
| 800 | sprintf(bp, "0x%02x, ", buf[j]); | ||
| 801 | bp += 6; | ||
| 802 | } | ||
| 803 | bp[0] = '\0'; | ||
| 804 | v4l2_dbg(lvl, debug, sd, "%s\n", b); | ||
| 805 | } | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 809 | static void adv7511_edid_handler(struct work_struct *work) | ||
| 810 | { | ||
| 811 | struct delayed_work *dwork = to_delayed_work(work); | ||
| 812 | struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); | ||
| 813 | struct v4l2_subdev *sd = &state->sd; | ||
| 814 | struct adv7511_edid_detect ed; | ||
| 815 | |||
| 816 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 817 | |||
| 818 | if (adv7511_check_edid_status(sd)) { | ||
| 819 | /* Return if we received the EDID. */ | ||
| 820 | return; | ||
| 821 | } | ||
| 822 | |||
| 823 | if (adv7511_have_hotplug(sd)) { | ||
| 824 | /* We must retry reading the EDID several times, it is possible | ||
| 825 | * that initially the EDID couldn't be read due to i2c errors | ||
| 826 | * (DVI connectors are particularly prone to this problem). */ | ||
| 827 | if (state->edid.read_retries) { | ||
| 828 | state->edid.read_retries--; | ||
| 829 | v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__); | ||
| 830 | state->have_monitor = false; | ||
| 831 | adv7511_s_power(sd, false); | ||
| 832 | adv7511_s_power(sd, true); | ||
| 833 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
| 834 | return; | ||
| 835 | } | ||
| 836 | } | ||
| 837 | |||
| 838 | /* We failed to read the EDID, so send an event for this. */ | ||
| 839 | ed.present = false; | ||
| 840 | ed.segment = adv7511_rd(sd, 0xc4); | ||
| 841 | v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); | ||
| 842 | v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); | ||
| 843 | } | ||
| 844 | |||
| 845 | static void adv7511_audio_setup(struct v4l2_subdev *sd) | ||
| 846 | { | ||
| 847 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
| 848 | |||
| 849 | adv7511_s_i2s_clock_freq(sd, 48000); | ||
| 850 | adv7511_s_clock_freq(sd, 48000); | ||
| 851 | adv7511_s_routing(sd, 0, 0, 0); | ||
| 852 | } | ||
| 853 | |||
| 854 | /* Configure hdmi transmitter. */ | ||
| 855 | static void adv7511_setup(struct v4l2_subdev *sd) | ||
| 856 | { | ||
| 857 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 858 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
| 859 | |||
| 860 | /* Input format: RGB 4:4:4 */ | ||
| 861 | adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0); | ||
| 862 | /* Output format: RGB 4:4:4 */ | ||
| 863 | adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0); | ||
| 864 | /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */ | ||
| 865 | adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06); | ||
| 866 | /* Disable pixel repetition */ | ||
| 867 | adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0); | ||
| 868 | /* Disable CSC */ | ||
| 869 | adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); | ||
| 870 | /* Output format: RGB 4:4:4, Active Format Information is valid, | ||
| 871 | * underscanned */ | ||
| 872 | adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12); | ||
| 873 | /* AVI Info frame packet enable, Audio Info frame disable */ | ||
| 874 | adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10); | ||
| 875 | /* Colorimetry, Active format aspect ratio: same as picure. */ | ||
| 876 | adv7511_wr(sd, 0x56, 0xa8); | ||
| 877 | /* No encryption */ | ||
| 878 | adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0); | ||
| 879 | |||
| 880 | /* Positive clk edge capture for input video clock */ | ||
| 881 | adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60); | ||
| 882 | |||
| 883 | adv7511_audio_setup(sd); | ||
| 884 | |||
| 885 | v4l2_ctrl_handler_setup(&state->hdl); | ||
| 886 | } | ||
| 887 | |||
| 888 | static void adv7511_notify_monitor_detect(struct v4l2_subdev *sd) | ||
| 889 | { | ||
| 890 | struct adv7511_monitor_detect mdt; | ||
| 891 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 892 | |||
| 893 | mdt.present = state->have_monitor; | ||
| 894 | v4l2_subdev_notify(sd, ADV7511_MONITOR_DETECT, (void *)&mdt); | ||
| 895 | } | ||
| 896 | |||
| 897 | static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) | ||
| 898 | { | ||
| 899 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 900 | /* read hotplug and rx-sense state */ | ||
| 901 | uint8_t status = adv7511_rd(sd, 0x42); | ||
| 902 | |||
| 903 | v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n", | ||
| 904 | __func__, | ||
| 905 | status, | ||
| 906 | status & MASK_ADV7511_HPD_DETECT ? ", hotplug" : "", | ||
| 907 | status & MASK_ADV7511_MSEN_DETECT ? ", rx-sense" : ""); | ||
| 908 | |||
| 909 | /* update read only ctrls */ | ||
| 910 | v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); | ||
| 911 | v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); | ||
| 912 | v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); | ||
| 913 | |||
| 914 | if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { | ||
| 915 | v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); | ||
| 916 | if (!state->have_monitor) { | ||
| 917 | v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__); | ||
| 918 | state->have_monitor = true; | ||
| 919 | adv7511_set_isr(sd, true); | ||
| 920 | if (!adv7511_s_power(sd, true)) { | ||
| 921 | v4l2_dbg(1, debug, sd, "%s: monitor detected, powerup failed\n", __func__); | ||
| 922 | return; | ||
| 923 | } | ||
| 924 | adv7511_setup(sd); | ||
| 925 | adv7511_notify_monitor_detect(sd); | ||
| 926 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
| 927 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
| 928 | } | ||
| 929 | } else if (status & MASK_ADV7511_HPD_DETECT) { | ||
| 930 | v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__); | ||
| 931 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
| 932 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
| 933 | } else if (!(status & MASK_ADV7511_HPD_DETECT)) { | ||
| 934 | v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__); | ||
| 935 | if (state->have_monitor) { | ||
| 936 | v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__); | ||
| 937 | state->have_monitor = false; | ||
| 938 | adv7511_notify_monitor_detect(sd); | ||
| 939 | } | ||
| 940 | adv7511_s_power(sd, false); | ||
| 941 | memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | static bool edid_block_verify_crc(uint8_t *edid_block) | ||
| 946 | { | ||
| 947 | int i; | ||
| 948 | uint8_t sum = 0; | ||
| 949 | |||
| 950 | for (i = 0; i < 128; i++) | ||
| 951 | sum += *(edid_block + i); | ||
| 952 | return (sum == 0); | ||
| 953 | } | ||
| 954 | |||
| 955 | static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) | ||
| 956 | { | ||
| 957 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 958 | u32 blocks = state->edid.blocks; | ||
| 959 | uint8_t *data = state->edid.data; | ||
| 960 | |||
| 961 | if (edid_block_verify_crc(&data[segment * 256])) { | ||
| 962 | if ((segment + 1) * 2 <= blocks) | ||
| 963 | return edid_block_verify_crc(&data[segment * 256 + 128]); | ||
| 964 | return true; | ||
| 965 | } | ||
| 966 | return false; | ||
| 967 | } | ||
| 968 | |||
| 969 | static bool adv7511_check_edid_status(struct v4l2_subdev *sd) | ||
| 970 | { | ||
| 971 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 972 | uint8_t edidRdy = adv7511_rd(sd, 0xc5); | ||
| 973 | |||
| 974 | v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n", | ||
| 975 | __func__, EDID_MAX_RETRIES - state->edid.read_retries); | ||
| 976 | |||
| 977 | if (state->edid.complete) | ||
| 978 | return true; | ||
| 979 | |||
| 980 | if (edidRdy & MASK_ADV7511_EDID_RDY) { | ||
| 981 | int segment = adv7511_rd(sd, 0xc4); | ||
| 982 | struct adv7511_edid_detect ed; | ||
| 983 | |||
| 984 | if (segment >= EDID_MAX_SEGM) { | ||
| 985 | v4l2_err(sd, "edid segment number too big\n"); | ||
| 986 | return false; | ||
| 987 | } | ||
| 988 | v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment); | ||
| 989 | adv7511_edid_rd(sd, 256, &state->edid.data[segment * 256]); | ||
| 990 | adv7511_dbg_dump_edid(2, debug, sd, segment, &state->edid.data[segment * 256]); | ||
| 991 | if (segment == 0) { | ||
| 992 | state->edid.blocks = state->edid.data[0x7e] + 1; | ||
| 993 | v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks); | ||
| 994 | } | ||
| 995 | if (!edid_segment_verify_crc(sd, segment)) { | ||
| 996 | /* edid crc error, force reread of edid segment */ | ||
| 997 | v4l2_dbg(1, debug, sd, "%s: edid crc error\n", __func__); | ||
| 998 | state->have_monitor = false; | ||
| 999 | adv7511_s_power(sd, false); | ||
| 1000 | adv7511_s_power(sd, true); | ||
| 1001 | return false; | ||
| 1002 | } | ||
| 1003 | /* one more segment read ok */ | ||
| 1004 | state->edid.segments = segment + 1; | ||
| 1005 | if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { | ||
| 1006 | /* Request next EDID segment */ | ||
| 1007 | v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); | ||
| 1008 | adv7511_wr(sd, 0xc9, 0xf); | ||
| 1009 | adv7511_wr(sd, 0xc4, state->edid.segments); | ||
| 1010 | state->edid.read_retries = EDID_MAX_RETRIES; | ||
| 1011 | queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); | ||
| 1012 | return false; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments); | ||
| 1016 | state->edid.complete = true; | ||
| 1017 | |||
| 1018 | /* report when we have all segments | ||
| 1019 | but report only for segment 0 | ||
| 1020 | */ | ||
| 1021 | ed.present = true; | ||
| 1022 | ed.segment = 0; | ||
| 1023 | state->edid_detect_counter++; | ||
| 1024 | v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); | ||
| 1025 | v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); | ||
| 1026 | return ed.present; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | return false; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | /* ----------------------------------------------------------------------- */ | ||
| 1033 | /* Setup ADV7511 */ | ||
| 1034 | static void adv7511_init_setup(struct v4l2_subdev *sd) | ||
| 1035 | { | ||
| 1036 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 1037 | struct adv7511_state_edid *edid = &state->edid; | ||
| 1038 | |||
| 1039 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
| 1040 | |||
| 1041 | /* clear all interrupts */ | ||
| 1042 | adv7511_wr(sd, 0x96, 0xff); | ||
| 1043 | memset(edid, 0, sizeof(struct adv7511_state_edid)); | ||
| 1044 | state->have_monitor = false; | ||
| 1045 | adv7511_set_isr(sd, false); | ||
| 1046 | adv7511_s_stream(sd, false); | ||
| 1047 | adv7511_s_audio_stream(sd, false); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
| 1051 | { | ||
| 1052 | struct adv7511_state *state; | ||
| 1053 | struct adv7511_platform_data *pdata = client->dev.platform_data; | ||
| 1054 | struct v4l2_ctrl_handler *hdl; | ||
| 1055 | struct v4l2_subdev *sd; | ||
| 1056 | u8 chip_id[2]; | ||
| 1057 | int err = -EIO; | ||
| 1058 | |||
| 1059 | /* Check if the adapter supports the needed features */ | ||
| 1060 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 1061 | return -EIO; | ||
| 1062 | |||
| 1063 | state = devm_kzalloc(&client->dev, sizeof(struct adv7511_state), GFP_KERNEL); | ||
| 1064 | if (!state) | ||
| 1065 | return -ENOMEM; | ||
| 1066 | |||
| 1067 | /* Platform data */ | ||
| 1068 | if (!pdata) { | ||
| 1069 | v4l_err(client, "No platform data!\n"); | ||
| 1070 | return -ENODEV; | ||
| 1071 | } | ||
| 1072 | memcpy(&state->pdata, pdata, sizeof(state->pdata)); | ||
| 1073 | |||
| 1074 | sd = &state->sd; | ||
| 1075 | |||
| 1076 | v4l2_dbg(1, debug, sd, "detecting adv7511 client on address 0x%x\n", | ||
| 1077 | client->addr << 1); | ||
| 1078 | |||
| 1079 | v4l2_i2c_subdev_init(sd, client, &adv7511_ops); | ||
| 1080 | |||
| 1081 | hdl = &state->hdl; | ||
| 1082 | v4l2_ctrl_handler_init(hdl, 10); | ||
| 1083 | /* add in ascending ID order */ | ||
| 1084 | state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, | ||
| 1085 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, | ||
| 1086 | 0, V4L2_DV_TX_MODE_DVI_D); | ||
| 1087 | state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1088 | V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); | ||
| 1089 | state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1090 | V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); | ||
| 1091 | state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1092 | V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); | ||
| 1093 | state->rgb_quantization_range_ctrl = | ||
| 1094 | v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, | ||
| 1095 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | ||
| 1096 | 0, V4L2_DV_RGB_RANGE_AUTO); | ||
| 1097 | sd->ctrl_handler = hdl; | ||
| 1098 | if (hdl->error) { | ||
| 1099 | err = hdl->error; | ||
| 1100 | goto err_hdl; | ||
| 1101 | } | ||
| 1102 | state->hdmi_mode_ctrl->is_private = true; | ||
| 1103 | state->hotplug_ctrl->is_private = true; | ||
| 1104 | state->rx_sense_ctrl->is_private = true; | ||
| 1105 | state->have_edid0_ctrl->is_private = true; | ||
| 1106 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 1107 | |||
| 1108 | state->pad.flags = MEDIA_PAD_FL_SINK; | ||
| 1109 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | ||
| 1110 | if (err) | ||
| 1111 | goto err_hdl; | ||
| 1112 | |||
| 1113 | /* EDID and CEC i2c addr */ | ||
| 1114 | state->i2c_edid_addr = state->pdata.i2c_edid << 1; | ||
| 1115 | state->i2c_cec_addr = state->pdata.i2c_cec << 1; | ||
| 1116 | |||
| 1117 | state->chip_revision = adv7511_rd(sd, 0x0); | ||
| 1118 | chip_id[0] = adv7511_rd(sd, 0xf5); | ||
| 1119 | chip_id[1] = adv7511_rd(sd, 0xf6); | ||
| 1120 | if (chip_id[0] != 0x75 || chip_id[1] != 0x11) { | ||
| 1121 | v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], chip_id[1]); | ||
| 1122 | err = -EIO; | ||
| 1123 | goto err_entity; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1); | ||
| 1127 | if (state->i2c_edid == NULL) { | ||
| 1128 | v4l2_err(sd, "failed to register edid i2c client\n"); | ||
| 1129 | goto err_entity; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ | ||
| 1133 | state->work_queue = create_singlethread_workqueue(sd->name); | ||
| 1134 | if (state->work_queue == NULL) { | ||
| 1135 | v4l2_err(sd, "could not create workqueue\n"); | ||
| 1136 | goto err_unreg_cec; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler); | ||
| 1140 | |||
| 1141 | adv7511_init_setup(sd); | ||
| 1142 | adv7511_set_isr(sd, true); | ||
| 1143 | adv7511_check_monitor_present_status(sd); | ||
| 1144 | |||
| 1145 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | ||
| 1146 | client->addr << 1, client->adapter->name); | ||
| 1147 | return 0; | ||
| 1148 | |||
| 1149 | err_unreg_cec: | ||
| 1150 | i2c_unregister_device(state->i2c_edid); | ||
| 1151 | err_entity: | ||
| 1152 | media_entity_cleanup(&sd->entity); | ||
| 1153 | err_hdl: | ||
| 1154 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 1155 | return err; | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | /* ----------------------------------------------------------------------- */ | ||
| 1159 | |||
| 1160 | static int adv7511_remove(struct i2c_client *client) | ||
| 1161 | { | ||
| 1162 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 1163 | struct adv7511_state *state = get_adv7511_state(sd); | ||
| 1164 | |||
| 1165 | state->chip_revision = -1; | ||
| 1166 | |||
| 1167 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, | ||
| 1168 | client->addr << 1, client->adapter->name); | ||
| 1169 | |||
| 1170 | adv7511_init_setup(sd); | ||
| 1171 | cancel_delayed_work(&state->edid_handler); | ||
| 1172 | i2c_unregister_device(state->i2c_edid); | ||
| 1173 | destroy_workqueue(state->work_queue); | ||
| 1174 | v4l2_device_unregister_subdev(sd); | ||
| 1175 | media_entity_cleanup(&sd->entity); | ||
| 1176 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | /* ----------------------------------------------------------------------- */ | ||
| 1181 | |||
| 1182 | static struct i2c_device_id adv7511_id[] = { | ||
| 1183 | { "adv7511", 0 }, | ||
| 1184 | { } | ||
| 1185 | }; | ||
| 1186 | MODULE_DEVICE_TABLE(i2c, adv7511_id); | ||
| 1187 | |||
| 1188 | static struct i2c_driver adv7511_driver = { | ||
| 1189 | .driver = { | ||
| 1190 | .owner = THIS_MODULE, | ||
| 1191 | .name = "adv7511", | ||
| 1192 | }, | ||
| 1193 | .probe = adv7511_probe, | ||
| 1194 | .remove = adv7511_remove, | ||
| 1195 | .id_table = adv7511_id, | ||
| 1196 | }; | ||
| 1197 | |||
| 1198 | module_i2c_driver(adv7511_driver); | ||
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 1d675b58fd71..fbfdd2fc2a36 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/v4l2-dv-timings.h> | 38 | #include <linux/v4l2-dv-timings.h> |
| 39 | #include <media/v4l2-device.h> | 39 | #include <media/v4l2-device.h> |
| 40 | #include <media/v4l2-ctrls.h> | 40 | #include <media/v4l2-ctrls.h> |
| 41 | #include <media/v4l2-dv-timings.h> | ||
| 41 | #include <media/adv7604.h> | 42 | #include <media/adv7604.h> |
| 42 | 43 | ||
| 43 | static int debug; | 44 | static int debug; |
| @@ -76,6 +77,7 @@ struct adv7604_state { | |||
| 76 | struct delayed_work delayed_work_enable_hotplug; | 77 | struct delayed_work delayed_work_enable_hotplug; |
| 77 | bool connector_hdmi; | 78 | bool connector_hdmi; |
| 78 | bool restart_stdi_once; | 79 | bool restart_stdi_once; |
| 80 | u32 prev_input_status; | ||
| 79 | 81 | ||
| 80 | /* i2c clients */ | 82 | /* i2c clients */ |
| 81 | struct i2c_client *i2c_avlink; | 83 | struct i2c_client *i2c_avlink; |
| @@ -260,22 +262,22 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | |||
| 260 | 262 | ||
| 261 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | 263 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) |
| 262 | { | 264 | { |
| 263 | return t->hfrontporch + t->hsync + t->hbackporch; | 265 | return V4L2_DV_BT_BLANKING_WIDTH(t); |
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | 268 | static inline unsigned htotal(const struct v4l2_bt_timings *t) |
| 267 | { | 269 | { |
| 268 | return t->width + t->hfrontporch + t->hsync + t->hbackporch; | 270 | return V4L2_DV_BT_FRAME_WIDTH(t); |
| 269 | } | 271 | } |
| 270 | 272 | ||
| 271 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | 273 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) |
| 272 | { | 274 | { |
| 273 | return t->vfrontporch + t->vsync + t->vbackporch; | 275 | return V4L2_DV_BT_BLANKING_HEIGHT(t); |
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | 278 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) |
| 277 | { | 279 | { |
| 278 | return t->height + t->vfrontporch + t->vsync + t->vbackporch; | 280 | return V4L2_DV_BT_FRAME_HEIGHT(t); |
| 279 | } | 281 | } |
| 280 | 282 | ||
| 281 | /* ----------------------------------------------------------------------- */ | 283 | /* ----------------------------------------------------------------------- */ |
| @@ -761,7 +763,7 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, | |||
| 761 | int i; | 763 | int i; |
| 762 | 764 | ||
| 763 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { | 765 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { |
| 764 | if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings, | 766 | if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, |
| 765 | DIGITAL_INPUT ? 250000 : 1000000)) | 767 | DIGITAL_INPUT ? 250000 : 1000000)) |
| 766 | continue; | 768 | continue; |
| 767 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ | 769 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ |
| @@ -990,6 +992,11 @@ static inline bool no_lock_tmds(struct v4l2_subdev *sd) | |||
| 990 | return (io_read(sd, 0x6a) & 0xe0) != 0xe0; | 992 | return (io_read(sd, 0x6a) & 0xe0) != 0xe0; |
| 991 | } | 993 | } |
| 992 | 994 | ||
| 995 | static inline bool is_hdmi(struct v4l2_subdev *sd) | ||
| 996 | { | ||
| 997 | return hdmi_read(sd, 0x05) & 0x80; | ||
| 998 | } | ||
| 999 | |||
| 993 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) | 1000 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) |
| 994 | { | 1001 | { |
| 995 | /* TODO channel 2 */ | 1002 | /* TODO channel 2 */ |
| @@ -1044,38 +1051,6 @@ static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status) | |||
| 1044 | 1051 | ||
| 1045 | /* ----------------------------------------------------------------------- */ | 1052 | /* ----------------------------------------------------------------------- */ |
| 1046 | 1053 | ||
| 1047 | static void adv7604_print_timings(struct v4l2_subdev *sd, | ||
| 1048 | struct v4l2_dv_timings *timings, const char *txt, bool detailed) | ||
| 1049 | { | ||
| 1050 | struct v4l2_bt_timings *bt = &timings->bt; | ||
| 1051 | u32 htot, vtot; | ||
| 1052 | |||
| 1053 | if (timings->type != V4L2_DV_BT_656_1120) | ||
| 1054 | return; | ||
| 1055 | |||
| 1056 | htot = htotal(bt); | ||
| 1057 | vtot = vtotal(bt); | ||
| 1058 | |||
| 1059 | v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", | ||
| 1060 | txt, bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
| 1061 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / | ||
| 1062 | (htot * vtot)) : 0, | ||
| 1063 | htot, vtot); | ||
| 1064 | |||
| 1065 | if (detailed) { | ||
| 1066 | v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", | ||
| 1067 | bt->hfrontporch, | ||
| 1068 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
| 1069 | bt->hsync, bt->hbackporch); | ||
| 1070 | v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", | ||
| 1071 | bt->vfrontporch, | ||
| 1072 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
| 1073 | bt->vsync, bt->vbackporch); | ||
| 1074 | v4l2_info(sd, " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", | ||
| 1075 | bt->pixelclock, bt->flags, bt->standards); | ||
| 1076 | } | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | struct stdi_readback { | 1054 | struct stdi_readback { |
| 1080 | u16 bl, lcf, lcvs; | 1055 | u16 bl, lcf, lcvs; |
| 1081 | u8 hs_pol, vs_pol; | 1056 | u8 hs_pol, vs_pol; |
| @@ -1187,7 +1162,7 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd, | |||
| 1187 | cap->type = V4L2_DV_BT_656_1120; | 1162 | cap->type = V4L2_DV_BT_656_1120; |
| 1188 | cap->bt.max_width = 1920; | 1163 | cap->bt.max_width = 1920; |
| 1189 | cap->bt.max_height = 1200; | 1164 | cap->bt.max_height = 1200; |
| 1190 | cap->bt.min_pixelclock = 27000000; | 1165 | cap->bt.min_pixelclock = 25000000; |
| 1191 | if (DIGITAL_INPUT) | 1166 | if (DIGITAL_INPUT) |
| 1192 | cap->bt.max_pixelclock = 225000000; | 1167 | cap->bt.max_pixelclock = 225000000; |
| 1193 | else | 1168 | else |
| @@ -1208,7 +1183,7 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, | |||
| 1208 | int i; | 1183 | int i; |
| 1209 | 1184 | ||
| 1210 | for (i = 0; adv7604_timings[i].bt.width; i++) { | 1185 | for (i = 0; adv7604_timings[i].bt.width; i++) { |
| 1211 | if (v4l_match_dv_timings(timings, &adv7604_timings[i], | 1186 | if (v4l2_match_dv_timings(timings, &adv7604_timings[i], |
| 1212 | DIGITAL_INPUT ? 250000 : 1000000)) { | 1187 | DIGITAL_INPUT ? 250000 : 1000000)) { |
| 1213 | *timings = adv7604_timings[i]; | 1188 | *timings = adv7604_timings[i]; |
| 1214 | break; | 1189 | break; |
| @@ -1242,12 +1217,21 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | |||
| 1242 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | 1217 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; |
| 1243 | 1218 | ||
| 1244 | if (DIGITAL_INPUT) { | 1219 | if (DIGITAL_INPUT) { |
| 1220 | uint32_t freq; | ||
| 1221 | |||
| 1245 | timings->type = V4L2_DV_BT_656_1120; | 1222 | timings->type = V4L2_DV_BT_656_1120; |
| 1246 | 1223 | ||
| 1247 | bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); | 1224 | bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); |
| 1248 | bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); | 1225 | bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); |
| 1249 | bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) + | 1226 | freq = (hdmi_read(sd, 0x06) * 1000000) + |
| 1250 | ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; | 1227 | ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; |
| 1228 | if (is_hdmi(sd)) { | ||
| 1229 | /* adjust for deep color mode */ | ||
| 1230 | unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; | ||
| 1231 | |||
| 1232 | freq = freq * 8 / bits_per_channel; | ||
| 1233 | } | ||
| 1234 | bt->pixelclock = freq; | ||
| 1251 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 + | 1235 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 + |
| 1252 | hdmi_read(sd, 0x21); | 1236 | hdmi_read(sd, 0x21); |
| 1253 | bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 + | 1237 | bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 + |
| @@ -1329,8 +1313,8 @@ found: | |||
| 1329 | } | 1313 | } |
| 1330 | 1314 | ||
| 1331 | if (debug > 1) | 1315 | if (debug > 1) |
| 1332 | adv7604_print_timings(sd, timings, | 1316 | v4l2_print_dv_timings(sd->name, "adv7604_query_dv_timings: ", |
| 1333 | "adv7604_query_dv_timings:", true); | 1317 | timings, true); |
| 1334 | 1318 | ||
| 1335 | return 0; | 1319 | return 0; |
| 1336 | } | 1320 | } |
| @@ -1372,8 +1356,8 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, | |||
| 1372 | 1356 | ||
| 1373 | 1357 | ||
| 1374 | if (debug > 1) | 1358 | if (debug > 1) |
| 1375 | adv7604_print_timings(sd, timings, | 1359 | v4l2_print_dv_timings(sd->name, "adv7604_s_dv_timings: ", |
| 1376 | "adv7604_s_dv_timings:", true); | 1360 | timings, true); |
| 1377 | return 0; | 1361 | return 0; |
| 1378 | } | 1362 | } |
| 1379 | 1363 | ||
| @@ -1534,6 +1518,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
| 1534 | { | 1518 | { |
| 1535 | struct adv7604_state *state = to_state(sd); | 1519 | struct adv7604_state *state = to_state(sd); |
| 1536 | u8 fmt_change, fmt_change_digital, tx_5v; | 1520 | u8 fmt_change, fmt_change_digital, tx_5v; |
| 1521 | u32 input_status; | ||
| 1537 | 1522 | ||
| 1538 | /* format change */ | 1523 | /* format change */ |
| 1539 | fmt_change = io_read(sd, 0x43) & 0x98; | 1524 | fmt_change = io_read(sd, 0x43) & 0x98; |
| @@ -1544,9 +1529,18 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
| 1544 | io_write(sd, 0x6c, fmt_change_digital); | 1529 | io_write(sd, 0x6c, fmt_change_digital); |
| 1545 | if (fmt_change || fmt_change_digital) { | 1530 | if (fmt_change || fmt_change_digital) { |
| 1546 | v4l2_dbg(1, debug, sd, | 1531 | v4l2_dbg(1, debug, sd, |
| 1547 | "%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n", | 1532 | "%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n", |
| 1548 | __func__, fmt_change, fmt_change_digital); | 1533 | __func__, fmt_change, fmt_change_digital); |
| 1549 | v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL); | 1534 | |
| 1535 | adv7604_g_input_status(sd, &input_status); | ||
| 1536 | if (input_status != state->prev_input_status) { | ||
| 1537 | v4l2_dbg(1, debug, sd, | ||
| 1538 | "%s: input_status = 0x%x, prev_input_status = 0x%x\n", | ||
| 1539 | __func__, input_status, state->prev_input_status); | ||
| 1540 | state->prev_input_status = input_status; | ||
| 1541 | v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL); | ||
| 1542 | } | ||
| 1543 | |||
| 1550 | if (handled) | 1544 | if (handled) |
| 1551 | *handled = true; | 1545 | *handled = true; |
| 1552 | } | 1546 | } |
| @@ -1625,7 +1619,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd) | |||
| 1625 | u8 avi_len; | 1619 | u8 avi_len; |
| 1626 | u8 avi_ver; | 1620 | u8 avi_ver; |
| 1627 | 1621 | ||
| 1628 | if (!(hdmi_read(sd, 0x05) & 0x80)) { | 1622 | if (!is_hdmi(sd)) { |
| 1629 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); | 1623 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); |
| 1630 | return; | 1624 | return; |
| 1631 | } | 1625 | } |
| @@ -1686,6 +1680,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
| 1686 | "RGB limited range (16-235)", | 1680 | "RGB limited range (16-235)", |
| 1687 | "RGB full range (0-255)", | 1681 | "RGB full range (0-255)", |
| 1688 | }; | 1682 | }; |
| 1683 | char *deep_color_mode_txt[4] = { | ||
| 1684 | "8-bits per channel", | ||
| 1685 | "10-bits per channel", | ||
| 1686 | "12-bits per channel", | ||
| 1687 | "16-bits per channel (not supported)" | ||
| 1688 | }; | ||
| 1689 | 1689 | ||
| 1690 | v4l2_info(sd, "-----Chip status-----\n"); | 1690 | v4l2_info(sd, "-----Chip status-----\n"); |
| 1691 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); | 1691 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); |
| @@ -1723,8 +1723,13 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
| 1723 | if (adv7604_query_dv_timings(sd, &timings)) | 1723 | if (adv7604_query_dv_timings(sd, &timings)) |
| 1724 | v4l2_info(sd, "No video detected\n"); | 1724 | v4l2_info(sd, "No video detected\n"); |
| 1725 | else | 1725 | else |
| 1726 | adv7604_print_timings(sd, &timings, "Detected format:", true); | 1726 | v4l2_print_dv_timings(sd->name, "Detected format: ", |
| 1727 | adv7604_print_timings(sd, &state->timings, "Configured format:", true); | 1727 | &timings, true); |
| 1728 | v4l2_print_dv_timings(sd->name, "Configured format: ", | ||
| 1729 | &state->timings, true); | ||
| 1730 | |||
| 1731 | if (no_signal(sd)) | ||
| 1732 | return 0; | ||
| 1728 | 1733 | ||
| 1729 | v4l2_info(sd, "-----Color space-----\n"); | 1734 | v4l2_info(sd, "-----Color space-----\n"); |
| 1730 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", | 1735 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", |
| @@ -1735,15 +1740,40 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
| 1735 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", | 1740 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", |
| 1736 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", | 1741 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", |
| 1737 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? | 1742 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? |
| 1738 | "enabled" : "disabled"); | 1743 | "enabled" : "disabled"); |
| 1739 | v4l2_info(sd, "Color space conversion: %s\n", | 1744 | v4l2_info(sd, "Color space conversion: %s\n", |
| 1740 | csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]); | 1745 | csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]); |
| 1741 | 1746 | ||
| 1742 | /* Digital video */ | 1747 | if (!DIGITAL_INPUT) |
| 1743 | if (DIGITAL_INPUT) { | 1748 | return 0; |
| 1744 | v4l2_info(sd, "-----HDMI status-----\n"); | 1749 | |
| 1745 | v4l2_info(sd, "HDCP encrypted content: %s\n", | 1750 | v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); |
| 1746 | hdmi_read(sd, 0x05) & 0x40 ? "true" : "false"); | 1751 | v4l2_info(sd, "HDCP encrypted content: %s\n", (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false"); |
| 1752 | v4l2_info(sd, "HDCP keys read: %s%s\n", | ||
| 1753 | (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", | ||
| 1754 | (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); | ||
| 1755 | if (!is_hdmi(sd)) { | ||
| 1756 | bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; | ||
| 1757 | bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; | ||
| 1758 | bool audio_mute = io_read(sd, 0x65) & 0x40; | ||
| 1759 | |||
| 1760 | v4l2_info(sd, "Audio: pll %s, samples %s, %s\n", | ||
| 1761 | audio_pll_locked ? "locked" : "not locked", | ||
| 1762 | audio_sample_packet_detect ? "detected" : "not detected", | ||
| 1763 | audio_mute ? "muted" : "enabled"); | ||
| 1764 | if (audio_pll_locked && audio_sample_packet_detect) { | ||
| 1765 | v4l2_info(sd, "Audio format: %s\n", | ||
| 1766 | (hdmi_read(sd, 0x07) & 0x20) ? "multi-channel" : "stereo"); | ||
| 1767 | } | ||
| 1768 | v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) + | ||
| 1769 | (hdmi_read(sd, 0x5c) << 8) + | ||
| 1770 | (hdmi_read(sd, 0x5d) & 0xf0)); | ||
| 1771 | v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) + | ||
| 1772 | (hdmi_read(sd, 0x5e) << 8) + | ||
| 1773 | hdmi_read(sd, 0x5f)); | ||
| 1774 | v4l2_info(sd, "AV Mute: %s\n", (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off"); | ||
| 1775 | |||
| 1776 | v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[(hdmi_read(sd, 0x0b) & 0x60) >> 5]); | ||
| 1747 | 1777 | ||
| 1748 | print_avi_infoframe(sd); | 1778 | print_avi_infoframe(sd); |
| 1749 | } | 1779 | } |
| @@ -1952,6 +1982,10 @@ static int adv7604_probe(struct i2c_client *client, | |||
| 1952 | return -ENOMEM; | 1982 | return -ENOMEM; |
| 1953 | } | 1983 | } |
| 1954 | 1984 | ||
| 1985 | /* initialize variables */ | ||
| 1986 | state->restart_stdi_once = true; | ||
| 1987 | state->prev_input_status = ~0; | ||
| 1988 | |||
| 1955 | /* platform data */ | 1989 | /* platform data */ |
| 1956 | if (!pdata) { | 1990 | if (!pdata) { |
| 1957 | v4l_err(client, "No platform data!\n"); | 1991 | v4l_err(client, "No platform data!\n"); |
| @@ -1987,29 +2021,30 @@ static int adv7604_probe(struct i2c_client *client, | |||
| 1987 | /* private controls */ | 2021 | /* private controls */ |
| 1988 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 2022 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
| 1989 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); | 2023 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); |
| 1990 | state->detect_tx_5v_ctrl->is_private = true; | ||
| 1991 | state->rgb_quantization_range_ctrl = | 2024 | state->rgb_quantization_range_ctrl = |
| 1992 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, | 2025 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, |
| 1993 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | 2026 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, |
| 1994 | 0, V4L2_DV_RGB_RANGE_AUTO); | 2027 | 0, V4L2_DV_RGB_RANGE_AUTO); |
| 1995 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 1996 | 2028 | ||
| 1997 | /* custom controls */ | 2029 | /* custom controls */ |
| 1998 | state->analog_sampling_phase_ctrl = | 2030 | state->analog_sampling_phase_ctrl = |
| 1999 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); | 2031 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); |
| 2000 | state->analog_sampling_phase_ctrl->is_private = true; | ||
| 2001 | state->free_run_color_manual_ctrl = | 2032 | state->free_run_color_manual_ctrl = |
| 2002 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); | 2033 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); |
| 2003 | state->free_run_color_manual_ctrl->is_private = true; | ||
| 2004 | state->free_run_color_ctrl = | 2034 | state->free_run_color_ctrl = |
| 2005 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL); | 2035 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL); |
| 2006 | state->free_run_color_ctrl->is_private = true; | ||
| 2007 | 2036 | ||
| 2008 | sd->ctrl_handler = hdl; | 2037 | sd->ctrl_handler = hdl; |
| 2009 | if (hdl->error) { | 2038 | if (hdl->error) { |
| 2010 | err = hdl->error; | 2039 | err = hdl->error; |
| 2011 | goto err_hdl; | 2040 | goto err_hdl; |
| 2012 | } | 2041 | } |
| 2042 | state->detect_tx_5v_ctrl->is_private = true; | ||
| 2043 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 2044 | state->analog_sampling_phase_ctrl->is_private = true; | ||
| 2045 | state->free_run_color_manual_ctrl->is_private = true; | ||
| 2046 | state->free_run_color_ctrl->is_private = true; | ||
| 2047 | |||
| 2013 | if (adv7604_s_detect_tx_5v_ctrl(sd)) { | 2048 | if (adv7604_s_detect_tx_5v_ctrl(sd)) { |
| 2014 | err = -ENODEV; | 2049 | err = -ENODEV; |
| 2015 | goto err_hdl; | 2050 | goto err_hdl; |
| @@ -2035,7 +2070,6 @@ static int adv7604_probe(struct i2c_client *client, | |||
| 2035 | v4l2_err(sd, "failed to create all i2c clients\n"); | 2070 | v4l2_err(sd, "failed to create all i2c clients\n"); |
| 2036 | goto err_i2c; | 2071 | goto err_i2c; |
| 2037 | } | 2072 | } |
| 2038 | state->restart_stdi_once = true; | ||
| 2039 | 2073 | ||
| 2040 | /* work queues */ | 2074 | /* work queues */ |
| 2041 | state->work_queues = create_singlethread_workqueue(client->name); | 2075 | state->work_queues = create_singlethread_workqueue(client->name); |
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c new file mode 100644 index 000000000000..d1748901337c --- /dev/null +++ b/drivers/media/i2c/adv7842.c | |||
| @@ -0,0 +1,2946 @@ | |||
| 1 | /* | ||
| 2 | * adv7842 - Analog Devices ADV7842 video decoder driver | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * References (c = chapter, p = page): | ||
| 23 | * REF_01 - Analog devices, ADV7842, Register Settings Recommendations, | ||
| 24 | * Revision 2.5, June 2010 | ||
| 25 | * REF_02 - Analog devices, Register map documentation, Documentation of | ||
| 26 | * the register maps, Software manual, Rev. F, June 2010 | ||
| 27 | */ | ||
| 28 | |||
| 29 | |||
| 30 | #include <linux/kernel.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | #include <linux/i2c.h> | ||
| 34 | #include <linux/delay.h> | ||
| 35 | #include <linux/videodev2.h> | ||
| 36 | #include <linux/workqueue.h> | ||
| 37 | #include <linux/v4l2-dv-timings.h> | ||
| 38 | #include <media/v4l2-device.h> | ||
| 39 | #include <media/v4l2-ctrls.h> | ||
| 40 | #include <media/v4l2-dv-timings.h> | ||
| 41 | #include <media/adv7842.h> | ||
| 42 | |||
| 43 | static int debug; | ||
| 44 | module_param(debug, int, 0644); | ||
| 45 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
| 46 | |||
| 47 | MODULE_DESCRIPTION("Analog Devices ADV7842 video decoder driver"); | ||
| 48 | MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); | ||
| 49 | MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>"); | ||
| 50 | MODULE_LICENSE("GPL"); | ||
| 51 | |||
| 52 | /* ADV7842 system clock frequency */ | ||
| 53 | #define ADV7842_fsc (28636360) | ||
| 54 | |||
| 55 | /* | ||
| 56 | ********************************************************************** | ||
| 57 | * | ||
| 58 | * Arrays with configuration parameters for the ADV7842 | ||
| 59 | * | ||
| 60 | ********************************************************************** | ||
| 61 | */ | ||
| 62 | |||
| 63 | struct adv7842_state { | ||
| 64 | struct v4l2_subdev sd; | ||
| 65 | struct media_pad pad; | ||
| 66 | struct v4l2_ctrl_handler hdl; | ||
| 67 | enum adv7842_mode mode; | ||
| 68 | struct v4l2_dv_timings timings; | ||
| 69 | enum adv7842_vid_std_select vid_std_select; | ||
| 70 | v4l2_std_id norm; | ||
| 71 | struct { | ||
| 72 | u8 edid[256]; | ||
| 73 | u32 present; | ||
| 74 | } hdmi_edid; | ||
| 75 | struct { | ||
| 76 | u8 edid[256]; | ||
| 77 | u32 present; | ||
| 78 | } vga_edid; | ||
| 79 | struct v4l2_fract aspect_ratio; | ||
| 80 | u32 rgb_quantization_range; | ||
| 81 | bool is_cea_format; | ||
| 82 | struct workqueue_struct *work_queues; | ||
| 83 | struct delayed_work delayed_work_enable_hotplug; | ||
| 84 | bool connector_hdmi; | ||
| 85 | bool hdmi_port_a; | ||
| 86 | |||
| 87 | /* i2c clients */ | ||
| 88 | struct i2c_client *i2c_sdp_io; | ||
| 89 | struct i2c_client *i2c_sdp; | ||
| 90 | struct i2c_client *i2c_cp; | ||
| 91 | struct i2c_client *i2c_vdp; | ||
| 92 | struct i2c_client *i2c_afe; | ||
| 93 | struct i2c_client *i2c_hdmi; | ||
| 94 | struct i2c_client *i2c_repeater; | ||
| 95 | struct i2c_client *i2c_edid; | ||
| 96 | struct i2c_client *i2c_infoframe; | ||
| 97 | struct i2c_client *i2c_cec; | ||
| 98 | struct i2c_client *i2c_avlink; | ||
| 99 | |||
| 100 | /* controls */ | ||
| 101 | struct v4l2_ctrl *detect_tx_5v_ctrl; | ||
| 102 | struct v4l2_ctrl *analog_sampling_phase_ctrl; | ||
| 103 | struct v4l2_ctrl *free_run_color_ctrl_manual; | ||
| 104 | struct v4l2_ctrl *free_run_color_ctrl; | ||
| 105 | struct v4l2_ctrl *rgb_quantization_range_ctrl; | ||
| 106 | }; | ||
| 107 | |||
| 108 | /* Unsupported timings. This device cannot support 720p30. */ | ||
| 109 | static const struct v4l2_dv_timings adv7842_timings_exceptions[] = { | ||
| 110 | V4L2_DV_BT_CEA_1280X720P30, | ||
| 111 | { } | ||
| 112 | }; | ||
| 113 | |||
| 114 | static bool adv7842_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl) | ||
| 115 | { | ||
| 116 | int i; | ||
| 117 | |||
| 118 | for (i = 0; adv7842_timings_exceptions[i].bt.width; i++) | ||
| 119 | if (v4l2_match_dv_timings(t, adv7842_timings_exceptions + i, 0)) | ||
| 120 | return false; | ||
| 121 | return true; | ||
| 122 | } | ||
| 123 | |||
| 124 | struct adv7842_video_standards { | ||
| 125 | struct v4l2_dv_timings timings; | ||
| 126 | u8 vid_std; | ||
| 127 | u8 v_freq; | ||
| 128 | }; | ||
| 129 | |||
| 130 | /* sorted by number of lines */ | ||
| 131 | static const struct adv7842_video_standards adv7842_prim_mode_comp[] = { | ||
| 132 | /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */ | ||
| 133 | { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, | ||
| 134 | { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 }, | ||
| 135 | { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 }, | ||
| 136 | { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, | ||
| 137 | { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, | ||
| 138 | { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, | ||
| 139 | { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, | ||
| 140 | { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, | ||
| 141 | /* TODO add 1920x1080P60_RB (CVT timing) */ | ||
| 142 | { }, | ||
| 143 | }; | ||
| 144 | |||
| 145 | /* sorted by number of lines */ | ||
| 146 | static const struct adv7842_video_standards adv7842_prim_mode_gr[] = { | ||
| 147 | { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, | ||
| 148 | { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, | ||
| 149 | { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, | ||
| 150 | { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, | ||
| 151 | { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, | ||
| 152 | { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, | ||
| 153 | { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, | ||
| 154 | { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, | ||
| 155 | { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, | ||
| 156 | { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, | ||
| 157 | { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, | ||
| 158 | { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, | ||
| 159 | { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, | ||
| 160 | { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, | ||
| 161 | { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, | ||
| 162 | { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 }, | ||
| 163 | { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 }, | ||
| 164 | { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 }, | ||
| 165 | { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 }, | ||
| 166 | { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */ | ||
| 167 | /* TODO add 1600X1200P60_RB (not a DMT timing) */ | ||
| 168 | { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 }, | ||
| 169 | { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */ | ||
| 170 | { }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | /* sorted by number of lines */ | ||
| 174 | static const struct adv7842_video_standards adv7842_prim_mode_hdmi_comp[] = { | ||
| 175 | { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, | ||
| 176 | { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, | ||
| 177 | { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 }, | ||
| 178 | { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 }, | ||
| 179 | { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, | ||
| 180 | { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, | ||
| 181 | { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, | ||
| 182 | { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, | ||
| 183 | { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, | ||
| 184 | { }, | ||
| 185 | }; | ||
| 186 | |||
| 187 | /* sorted by number of lines */ | ||
| 188 | static const struct adv7842_video_standards adv7842_prim_mode_hdmi_gr[] = { | ||
| 189 | { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, | ||
| 190 | { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, | ||
| 191 | { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, | ||
| 192 | { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, | ||
| 193 | { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, | ||
| 194 | { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, | ||
| 195 | { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, | ||
| 196 | { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, | ||
| 197 | { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, | ||
| 198 | { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, | ||
| 199 | { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, | ||
| 200 | { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, | ||
| 201 | { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, | ||
| 202 | { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, | ||
| 203 | { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, | ||
| 204 | { }, | ||
| 205 | }; | ||
| 206 | |||
| 207 | /* ----------------------------------------------------------------------- */ | ||
| 208 | |||
| 209 | static inline struct adv7842_state *to_state(struct v4l2_subdev *sd) | ||
| 210 | { | ||
| 211 | return container_of(sd, struct adv7842_state, sd); | ||
| 212 | } | ||
| 213 | |||
| 214 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
| 215 | { | ||
| 216 | return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd; | ||
| 217 | } | ||
| 218 | |||
| 219 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | ||
| 220 | { | ||
| 221 | return V4L2_DV_BT_BLANKING_WIDTH(t); | ||
| 222 | } | ||
| 223 | |||
| 224 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | ||
| 225 | { | ||
| 226 | return V4L2_DV_BT_FRAME_WIDTH(t); | ||
| 227 | } | ||
| 228 | |||
| 229 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | ||
| 230 | { | ||
| 231 | return V4L2_DV_BT_BLANKING_HEIGHT(t); | ||
| 232 | } | ||
| 233 | |||
| 234 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | ||
| 235 | { | ||
| 236 | return V4L2_DV_BT_FRAME_HEIGHT(t); | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | /* ----------------------------------------------------------------------- */ | ||
| 241 | |||
| 242 | static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, | ||
| 243 | u8 command, bool check) | ||
| 244 | { | ||
| 245 | union i2c_smbus_data data; | ||
| 246 | |||
| 247 | if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
| 248 | I2C_SMBUS_READ, command, | ||
| 249 | I2C_SMBUS_BYTE_DATA, &data)) | ||
| 250 | return data.byte; | ||
| 251 | if (check) | ||
| 252 | v4l_err(client, "error reading %02x, %02x\n", | ||
| 253 | client->addr, command); | ||
| 254 | return -EIO; | ||
| 255 | } | ||
| 256 | |||
| 257 | static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) | ||
| 258 | { | ||
| 259 | int i; | ||
| 260 | |||
| 261 | for (i = 0; i < 3; i++) { | ||
| 262 | int ret = adv_smbus_read_byte_data_check(client, command, true); | ||
| 263 | |||
| 264 | if (ret >= 0) { | ||
| 265 | if (i) | ||
| 266 | v4l_err(client, "read ok after %d retries\n", i); | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | v4l_err(client, "read failed\n"); | ||
| 271 | return -EIO; | ||
| 272 | } | ||
| 273 | |||
| 274 | static s32 adv_smbus_write_byte_data(struct i2c_client *client, | ||
| 275 | u8 command, u8 value) | ||
| 276 | { | ||
| 277 | union i2c_smbus_data data; | ||
| 278 | int err; | ||
| 279 | int i; | ||
| 280 | |||
| 281 | data.byte = value; | ||
| 282 | for (i = 0; i < 3; i++) { | ||
| 283 | err = i2c_smbus_xfer(client->adapter, client->addr, | ||
| 284 | client->flags, | ||
| 285 | I2C_SMBUS_WRITE, command, | ||
| 286 | I2C_SMBUS_BYTE_DATA, &data); | ||
| 287 | if (!err) | ||
| 288 | break; | ||
| 289 | } | ||
| 290 | if (err < 0) | ||
| 291 | v4l_err(client, "error writing %02x, %02x, %02x\n", | ||
| 292 | client->addr, command, value); | ||
| 293 | return err; | ||
| 294 | } | ||
| 295 | |||
| 296 | static void adv_smbus_write_byte_no_check(struct i2c_client *client, | ||
| 297 | u8 command, u8 value) | ||
| 298 | { | ||
| 299 | union i2c_smbus_data data; | ||
| 300 | data.byte = value; | ||
| 301 | |||
| 302 | i2c_smbus_xfer(client->adapter, client->addr, | ||
| 303 | client->flags, | ||
| 304 | I2C_SMBUS_WRITE, command, | ||
| 305 | I2C_SMBUS_BYTE_DATA, &data); | ||
| 306 | } | ||
| 307 | |||
| 308 | static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client, | ||
| 309 | u8 command, unsigned length, const u8 *values) | ||
| 310 | { | ||
| 311 | union i2c_smbus_data data; | ||
| 312 | |||
| 313 | if (length > I2C_SMBUS_BLOCK_MAX) | ||
| 314 | length = I2C_SMBUS_BLOCK_MAX; | ||
| 315 | data.block[0] = length; | ||
| 316 | memcpy(data.block + 1, values, length); | ||
| 317 | return i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
| 318 | I2C_SMBUS_WRITE, command, | ||
| 319 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | ||
| 320 | } | ||
| 321 | |||
| 322 | /* ----------------------------------------------------------------------- */ | ||
| 323 | |||
| 324 | static inline int io_read(struct v4l2_subdev *sd, u8 reg) | ||
| 325 | { | ||
| 326 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 327 | |||
| 328 | return adv_smbus_read_byte_data(client, reg); | ||
| 329 | } | ||
| 330 | |||
| 331 | static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 332 | { | ||
| 333 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 334 | |||
| 335 | return adv_smbus_write_byte_data(client, reg, val); | ||
| 336 | } | ||
| 337 | |||
| 338 | static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 339 | { | ||
| 340 | return io_write(sd, reg, (io_read(sd, reg) & mask) | val); | ||
| 341 | } | ||
| 342 | |||
| 343 | static inline int avlink_read(struct v4l2_subdev *sd, u8 reg) | ||
| 344 | { | ||
| 345 | struct adv7842_state *state = to_state(sd); | ||
| 346 | |||
| 347 | return adv_smbus_read_byte_data(state->i2c_avlink, reg); | ||
| 348 | } | ||
| 349 | |||
| 350 | static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 351 | { | ||
| 352 | struct adv7842_state *state = to_state(sd); | ||
| 353 | |||
| 354 | return adv_smbus_write_byte_data(state->i2c_avlink, reg, val); | ||
| 355 | } | ||
| 356 | |||
| 357 | static inline int cec_read(struct v4l2_subdev *sd, u8 reg) | ||
| 358 | { | ||
| 359 | struct adv7842_state *state = to_state(sd); | ||
| 360 | |||
| 361 | return adv_smbus_read_byte_data(state->i2c_cec, reg); | ||
| 362 | } | ||
| 363 | |||
| 364 | static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 365 | { | ||
| 366 | struct adv7842_state *state = to_state(sd); | ||
| 367 | |||
| 368 | return adv_smbus_write_byte_data(state->i2c_cec, reg, val); | ||
| 369 | } | ||
| 370 | |||
| 371 | static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 372 | { | ||
| 373 | return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val); | ||
| 374 | } | ||
| 375 | |||
| 376 | static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) | ||
| 377 | { | ||
| 378 | struct adv7842_state *state = to_state(sd); | ||
| 379 | |||
| 380 | return adv_smbus_read_byte_data(state->i2c_infoframe, reg); | ||
| 381 | } | ||
| 382 | |||
| 383 | static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 384 | { | ||
| 385 | struct adv7842_state *state = to_state(sd); | ||
| 386 | |||
| 387 | return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val); | ||
| 388 | } | ||
| 389 | |||
| 390 | static inline int sdp_io_read(struct v4l2_subdev *sd, u8 reg) | ||
| 391 | { | ||
| 392 | struct adv7842_state *state = to_state(sd); | ||
| 393 | |||
| 394 | return adv_smbus_read_byte_data(state->i2c_sdp_io, reg); | ||
| 395 | } | ||
| 396 | |||
| 397 | static inline int sdp_io_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 398 | { | ||
| 399 | struct adv7842_state *state = to_state(sd); | ||
| 400 | |||
| 401 | return adv_smbus_write_byte_data(state->i2c_sdp_io, reg, val); | ||
| 402 | } | ||
| 403 | |||
| 404 | static inline int sdp_io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 405 | { | ||
| 406 | return sdp_io_write(sd, reg, (sdp_io_read(sd, reg) & mask) | val); | ||
| 407 | } | ||
| 408 | |||
| 409 | static inline int sdp_read(struct v4l2_subdev *sd, u8 reg) | ||
| 410 | { | ||
| 411 | struct adv7842_state *state = to_state(sd); | ||
| 412 | |||
| 413 | return adv_smbus_read_byte_data(state->i2c_sdp, reg); | ||
| 414 | } | ||
| 415 | |||
| 416 | static inline int sdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 417 | { | ||
| 418 | struct adv7842_state *state = to_state(sd); | ||
| 419 | |||
| 420 | return adv_smbus_write_byte_data(state->i2c_sdp, reg, val); | ||
| 421 | } | ||
| 422 | |||
| 423 | static inline int sdp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 424 | { | ||
| 425 | return sdp_write(sd, reg, (sdp_read(sd, reg) & mask) | val); | ||
| 426 | } | ||
| 427 | |||
| 428 | static inline int afe_read(struct v4l2_subdev *sd, u8 reg) | ||
| 429 | { | ||
| 430 | struct adv7842_state *state = to_state(sd); | ||
| 431 | |||
| 432 | return adv_smbus_read_byte_data(state->i2c_afe, reg); | ||
| 433 | } | ||
| 434 | |||
| 435 | static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 436 | { | ||
| 437 | struct adv7842_state *state = to_state(sd); | ||
| 438 | |||
| 439 | return adv_smbus_write_byte_data(state->i2c_afe, reg, val); | ||
| 440 | } | ||
| 441 | |||
| 442 | static inline int afe_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 443 | { | ||
| 444 | return afe_write(sd, reg, (afe_read(sd, reg) & mask) | val); | ||
| 445 | } | ||
| 446 | |||
| 447 | static inline int rep_read(struct v4l2_subdev *sd, u8 reg) | ||
| 448 | { | ||
| 449 | struct adv7842_state *state = to_state(sd); | ||
| 450 | |||
| 451 | return adv_smbus_read_byte_data(state->i2c_repeater, reg); | ||
| 452 | } | ||
| 453 | |||
| 454 | static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 455 | { | ||
| 456 | struct adv7842_state *state = to_state(sd); | ||
| 457 | |||
| 458 | return adv_smbus_write_byte_data(state->i2c_repeater, reg, val); | ||
| 459 | } | ||
| 460 | |||
| 461 | static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 462 | { | ||
| 463 | return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val); | ||
| 464 | } | ||
| 465 | |||
| 466 | static inline int edid_read(struct v4l2_subdev *sd, u8 reg) | ||
| 467 | { | ||
| 468 | struct adv7842_state *state = to_state(sd); | ||
| 469 | |||
| 470 | return adv_smbus_read_byte_data(state->i2c_edid, reg); | ||
| 471 | } | ||
| 472 | |||
| 473 | static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 474 | { | ||
| 475 | struct adv7842_state *state = to_state(sd); | ||
| 476 | |||
| 477 | return adv_smbus_write_byte_data(state->i2c_edid, reg, val); | ||
| 478 | } | ||
| 479 | |||
| 480 | static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg) | ||
| 481 | { | ||
| 482 | struct adv7842_state *state = to_state(sd); | ||
| 483 | |||
| 484 | return adv_smbus_read_byte_data(state->i2c_hdmi, reg); | ||
| 485 | } | ||
| 486 | |||
| 487 | static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 488 | { | ||
| 489 | struct adv7842_state *state = to_state(sd); | ||
| 490 | |||
| 491 | return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val); | ||
| 492 | } | ||
| 493 | |||
| 494 | static inline int cp_read(struct v4l2_subdev *sd, u8 reg) | ||
| 495 | { | ||
| 496 | struct adv7842_state *state = to_state(sd); | ||
| 497 | |||
| 498 | return adv_smbus_read_byte_data(state->i2c_cp, reg); | ||
| 499 | } | ||
| 500 | |||
| 501 | static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 502 | { | ||
| 503 | struct adv7842_state *state = to_state(sd); | ||
| 504 | |||
| 505 | return adv_smbus_write_byte_data(state->i2c_cp, reg, val); | ||
| 506 | } | ||
| 507 | |||
| 508 | static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) | ||
| 509 | { | ||
| 510 | return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val); | ||
| 511 | } | ||
| 512 | |||
| 513 | static inline int vdp_read(struct v4l2_subdev *sd, u8 reg) | ||
| 514 | { | ||
| 515 | struct adv7842_state *state = to_state(sd); | ||
| 516 | |||
| 517 | return adv_smbus_read_byte_data(state->i2c_vdp, reg); | ||
| 518 | } | ||
| 519 | |||
| 520 | static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | ||
| 521 | { | ||
| 522 | struct adv7842_state *state = to_state(sd); | ||
| 523 | |||
| 524 | return adv_smbus_write_byte_data(state->i2c_vdp, reg, val); | ||
| 525 | } | ||
| 526 | |||
| 527 | static void main_reset(struct v4l2_subdev *sd) | ||
| 528 | { | ||
| 529 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 530 | |||
| 531 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 532 | |||
| 533 | adv_smbus_write_byte_no_check(client, 0xff, 0x80); | ||
| 534 | |||
| 535 | mdelay(2); | ||
| 536 | } | ||
| 537 | |||
| 538 | /* ----------------------------------------------------------------------- */ | ||
| 539 | |||
| 540 | static inline bool is_digital_input(struct v4l2_subdev *sd) | ||
| 541 | { | ||
| 542 | struct adv7842_state *state = to_state(sd); | ||
| 543 | |||
| 544 | return state->mode == ADV7842_MODE_HDMI; | ||
| 545 | } | ||
| 546 | |||
| 547 | static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = { | ||
| 548 | .type = V4L2_DV_BT_656_1120, | ||
| 549 | .bt = { | ||
| 550 | .max_width = 1920, | ||
| 551 | .max_height = 1200, | ||
| 552 | .min_pixelclock = 25000000, | ||
| 553 | .max_pixelclock = 170000000, | ||
| 554 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
| 555 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
| 556 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
| 557 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
| 558 | }, | ||
| 559 | }; | ||
| 560 | |||
| 561 | static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = { | ||
| 562 | .type = V4L2_DV_BT_656_1120, | ||
| 563 | .bt = { | ||
| 564 | .max_width = 1920, | ||
| 565 | .max_height = 1200, | ||
| 566 | .min_pixelclock = 25000000, | ||
| 567 | .max_pixelclock = 225000000, | ||
| 568 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
| 569 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
| 570 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
| 571 | V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM, | ||
| 572 | }, | ||
| 573 | }; | ||
| 574 | |||
| 575 | static inline const struct v4l2_dv_timings_cap * | ||
| 576 | adv7842_get_dv_timings_cap(struct v4l2_subdev *sd) | ||
| 577 | { | ||
| 578 | return is_digital_input(sd) ? &adv7842_timings_cap_digital : | ||
| 579 | &adv7842_timings_cap_analog; | ||
| 580 | } | ||
| 581 | |||
| 582 | /* ----------------------------------------------------------------------- */ | ||
| 583 | |||
| 584 | static void adv7842_delayed_work_enable_hotplug(struct work_struct *work) | ||
| 585 | { | ||
| 586 | struct delayed_work *dwork = to_delayed_work(work); | ||
| 587 | struct adv7842_state *state = container_of(dwork, | ||
| 588 | struct adv7842_state, delayed_work_enable_hotplug); | ||
| 589 | struct v4l2_subdev *sd = &state->sd; | ||
| 590 | int present = state->hdmi_edid.present; | ||
| 591 | u8 mask = 0; | ||
| 592 | |||
| 593 | v4l2_dbg(2, debug, sd, "%s: enable hotplug on ports: 0x%x\n", | ||
| 594 | __func__, present); | ||
| 595 | |||
| 596 | if (present & 0x1) | ||
| 597 | mask |= 0x20; /* port A */ | ||
| 598 | if (present & 0x2) | ||
| 599 | mask |= 0x10; /* port B */ | ||
| 600 | io_write_and_or(sd, 0x20, 0xcf, mask); | ||
| 601 | } | ||
| 602 | |||
| 603 | static int edid_write_vga_segment(struct v4l2_subdev *sd) | ||
| 604 | { | ||
| 605 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 606 | struct adv7842_state *state = to_state(sd); | ||
| 607 | const u8 *val = state->vga_edid.edid; | ||
| 608 | int err = 0; | ||
| 609 | int i; | ||
| 610 | |||
| 611 | v4l2_dbg(2, debug, sd, "%s: write EDID on VGA port\n", __func__); | ||
| 612 | |||
| 613 | /* HPA disable on port A and B */ | ||
| 614 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
| 615 | |||
| 616 | /* Disable I2C access to internal EDID ram from VGA DDC port */ | ||
| 617 | rep_write_and_or(sd, 0x7f, 0x7f, 0x00); | ||
| 618 | |||
| 619 | /* edid segment pointer '1' for VGA port */ | ||
| 620 | rep_write_and_or(sd, 0x77, 0xef, 0x10); | ||
| 621 | |||
| 622 | for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX) | ||
| 623 | err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, | ||
| 624 | I2C_SMBUS_BLOCK_MAX, val + i); | ||
| 625 | if (err) | ||
| 626 | return err; | ||
| 627 | |||
| 628 | /* Calculates the checksums and enables I2C access | ||
| 629 | * to internal EDID ram from VGA DDC port. | ||
| 630 | */ | ||
| 631 | rep_write_and_or(sd, 0x7f, 0x7f, 0x80); | ||
| 632 | |||
| 633 | for (i = 0; i < 1000; i++) { | ||
| 634 | if (rep_read(sd, 0x79) & 0x20) | ||
| 635 | break; | ||
| 636 | mdelay(1); | ||
| 637 | } | ||
| 638 | if (i == 1000) { | ||
| 639 | v4l_err(client, "error enabling edid on VGA port\n"); | ||
| 640 | return -EIO; | ||
| 641 | } | ||
| 642 | |||
| 643 | /* enable hotplug after 200 ms */ | ||
| 644 | queue_delayed_work(state->work_queues, | ||
| 645 | &state->delayed_work_enable_hotplug, HZ / 5); | ||
| 646 | |||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | |||
| 650 | static int edid_spa_location(const u8 *edid) | ||
| 651 | { | ||
| 652 | u8 d; | ||
| 653 | |||
| 654 | /* | ||
| 655 | * TODO, improve and update for other CEA extensions | ||
| 656 | * currently only for 1 segment (256 bytes), | ||
| 657 | * i.e. 1 extension block and CEA revision 3. | ||
| 658 | */ | ||
| 659 | if ((edid[0x7e] != 1) || | ||
| 660 | (edid[0x80] != 0x02) || | ||
| 661 | (edid[0x81] != 0x03)) { | ||
| 662 | return -EINVAL; | ||
| 663 | } | ||
| 664 | /* | ||
| 665 | * search Vendor Specific Data Block (tag 3) | ||
| 666 | */ | ||
| 667 | d = edid[0x82] & 0x7f; | ||
| 668 | if (d > 4) { | ||
| 669 | int i = 0x84; | ||
| 670 | int end = 0x80 + d; | ||
| 671 | do { | ||
| 672 | u8 tag = edid[i]>>5; | ||
| 673 | u8 len = edid[i] & 0x1f; | ||
| 674 | |||
| 675 | if ((tag == 3) && (len >= 5)) | ||
| 676 | return i + 4; | ||
| 677 | i += len + 1; | ||
| 678 | } while (i < end); | ||
| 679 | } | ||
| 680 | return -EINVAL; | ||
| 681 | } | ||
| 682 | |||
| 683 | static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) | ||
| 684 | { | ||
| 685 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 686 | struct adv7842_state *state = to_state(sd); | ||
| 687 | const u8 *val = state->hdmi_edid.edid; | ||
| 688 | u8 cur_mask = rep_read(sd, 0x77) & 0x0c; | ||
| 689 | u8 mask = port == 0 ? 0x4 : 0x8; | ||
| 690 | int spa_loc = edid_spa_location(val); | ||
| 691 | int err = 0; | ||
| 692 | int i; | ||
| 693 | |||
| 694 | v4l2_dbg(2, debug, sd, "%s: write EDID on port %d (spa at 0x%x)\n", | ||
| 695 | __func__, port, spa_loc); | ||
| 696 | |||
| 697 | /* HPA disable on port A and B */ | ||
| 698 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
| 699 | |||
| 700 | /* Disable I2C access to internal EDID ram from HDMI DDC ports */ | ||
| 701 | rep_write_and_or(sd, 0x77, 0xf3, 0x00); | ||
| 702 | |||
| 703 | /* edid segment pointer '0' for HDMI ports */ | ||
| 704 | rep_write_and_or(sd, 0x77, 0xef, 0x00); | ||
| 705 | |||
| 706 | for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX) | ||
| 707 | err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, | ||
| 708 | I2C_SMBUS_BLOCK_MAX, val + i); | ||
| 709 | if (err) | ||
| 710 | return err; | ||
| 711 | |||
| 712 | if (spa_loc > 0) { | ||
| 713 | if (port == 0) { | ||
| 714 | /* port A SPA */ | ||
| 715 | rep_write(sd, 0x72, val[spa_loc]); | ||
| 716 | rep_write(sd, 0x73, val[spa_loc + 1]); | ||
| 717 | } else { | ||
| 718 | /* port B SPA */ | ||
| 719 | rep_write(sd, 0x74, val[spa_loc]); | ||
| 720 | rep_write(sd, 0x75, val[spa_loc + 1]); | ||
| 721 | } | ||
| 722 | rep_write(sd, 0x76, spa_loc); | ||
| 723 | } else { | ||
| 724 | /* default register values for SPA */ | ||
| 725 | if (port == 0) { | ||
| 726 | /* port A SPA */ | ||
| 727 | rep_write(sd, 0x72, 0); | ||
| 728 | rep_write(sd, 0x73, 0); | ||
| 729 | } else { | ||
| 730 | /* port B SPA */ | ||
| 731 | rep_write(sd, 0x74, 0); | ||
| 732 | rep_write(sd, 0x75, 0); | ||
| 733 | } | ||
| 734 | rep_write(sd, 0x76, 0xc0); | ||
| 735 | } | ||
| 736 | rep_write_and_or(sd, 0x77, 0xbf, 0x00); | ||
| 737 | |||
| 738 | /* Calculates the checksums and enables I2C access to internal | ||
| 739 | * EDID ram from HDMI DDC ports | ||
| 740 | */ | ||
| 741 | rep_write_and_or(sd, 0x77, 0xf3, mask | cur_mask); | ||
| 742 | |||
| 743 | for (i = 0; i < 1000; i++) { | ||
| 744 | if (rep_read(sd, 0x7d) & mask) | ||
| 745 | break; | ||
| 746 | mdelay(1); | ||
| 747 | } | ||
| 748 | if (i == 1000) { | ||
| 749 | v4l_err(client, "error enabling edid on port %d\n", port); | ||
| 750 | return -EIO; | ||
| 751 | } | ||
| 752 | |||
| 753 | /* enable hotplug after 200 ms */ | ||
| 754 | queue_delayed_work(state->work_queues, | ||
| 755 | &state->delayed_work_enable_hotplug, HZ / 5); | ||
| 756 | |||
| 757 | return 0; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* ----------------------------------------------------------------------- */ | ||
| 761 | |||
| 762 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 763 | static void adv7842_inv_register(struct v4l2_subdev *sd) | ||
| 764 | { | ||
| 765 | v4l2_info(sd, "0x000-0x0ff: IO Map\n"); | ||
| 766 | v4l2_info(sd, "0x100-0x1ff: AVLink Map\n"); | ||
| 767 | v4l2_info(sd, "0x200-0x2ff: CEC Map\n"); | ||
| 768 | v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n"); | ||
| 769 | v4l2_info(sd, "0x400-0x4ff: SDP_IO Map\n"); | ||
| 770 | v4l2_info(sd, "0x500-0x5ff: SDP Map\n"); | ||
| 771 | v4l2_info(sd, "0x600-0x6ff: AFE Map\n"); | ||
| 772 | v4l2_info(sd, "0x700-0x7ff: Repeater Map\n"); | ||
| 773 | v4l2_info(sd, "0x800-0x8ff: EDID Map\n"); | ||
| 774 | v4l2_info(sd, "0x900-0x9ff: HDMI Map\n"); | ||
| 775 | v4l2_info(sd, "0xa00-0xaff: CP Map\n"); | ||
| 776 | v4l2_info(sd, "0xb00-0xbff: VDP Map\n"); | ||
| 777 | } | ||
| 778 | |||
| 779 | static int adv7842_g_register(struct v4l2_subdev *sd, | ||
| 780 | struct v4l2_dbg_register *reg) | ||
| 781 | { | ||
| 782 | reg->size = 1; | ||
| 783 | switch (reg->reg >> 8) { | ||
| 784 | case 0: | ||
| 785 | reg->val = io_read(sd, reg->reg & 0xff); | ||
| 786 | break; | ||
| 787 | case 1: | ||
| 788 | reg->val = avlink_read(sd, reg->reg & 0xff); | ||
| 789 | break; | ||
| 790 | case 2: | ||
| 791 | reg->val = cec_read(sd, reg->reg & 0xff); | ||
| 792 | break; | ||
| 793 | case 3: | ||
| 794 | reg->val = infoframe_read(sd, reg->reg & 0xff); | ||
| 795 | break; | ||
| 796 | case 4: | ||
| 797 | reg->val = sdp_io_read(sd, reg->reg & 0xff); | ||
| 798 | break; | ||
| 799 | case 5: | ||
| 800 | reg->val = sdp_read(sd, reg->reg & 0xff); | ||
| 801 | break; | ||
| 802 | case 6: | ||
| 803 | reg->val = afe_read(sd, reg->reg & 0xff); | ||
| 804 | break; | ||
| 805 | case 7: | ||
| 806 | reg->val = rep_read(sd, reg->reg & 0xff); | ||
| 807 | break; | ||
| 808 | case 8: | ||
| 809 | reg->val = edid_read(sd, reg->reg & 0xff); | ||
| 810 | break; | ||
| 811 | case 9: | ||
| 812 | reg->val = hdmi_read(sd, reg->reg & 0xff); | ||
| 813 | break; | ||
| 814 | case 0xa: | ||
| 815 | reg->val = cp_read(sd, reg->reg & 0xff); | ||
| 816 | break; | ||
| 817 | case 0xb: | ||
| 818 | reg->val = vdp_read(sd, reg->reg & 0xff); | ||
| 819 | break; | ||
| 820 | default: | ||
| 821 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
| 822 | adv7842_inv_register(sd); | ||
| 823 | break; | ||
| 824 | } | ||
| 825 | return 0; | ||
| 826 | } | ||
| 827 | |||
| 828 | static int adv7842_s_register(struct v4l2_subdev *sd, | ||
| 829 | const struct v4l2_dbg_register *reg) | ||
| 830 | { | ||
| 831 | u8 val = reg->val & 0xff; | ||
| 832 | |||
| 833 | switch (reg->reg >> 8) { | ||
| 834 | case 0: | ||
| 835 | io_write(sd, reg->reg & 0xff, val); | ||
| 836 | break; | ||
| 837 | case 1: | ||
| 838 | avlink_write(sd, reg->reg & 0xff, val); | ||
| 839 | break; | ||
| 840 | case 2: | ||
| 841 | cec_write(sd, reg->reg & 0xff, val); | ||
| 842 | break; | ||
| 843 | case 3: | ||
| 844 | infoframe_write(sd, reg->reg & 0xff, val); | ||
| 845 | break; | ||
| 846 | case 4: | ||
| 847 | sdp_io_write(sd, reg->reg & 0xff, val); | ||
| 848 | break; | ||
| 849 | case 5: | ||
| 850 | sdp_write(sd, reg->reg & 0xff, val); | ||
| 851 | break; | ||
| 852 | case 6: | ||
| 853 | afe_write(sd, reg->reg & 0xff, val); | ||
| 854 | break; | ||
| 855 | case 7: | ||
| 856 | rep_write(sd, reg->reg & 0xff, val); | ||
| 857 | break; | ||
| 858 | case 8: | ||
| 859 | edid_write(sd, reg->reg & 0xff, val); | ||
| 860 | break; | ||
| 861 | case 9: | ||
| 862 | hdmi_write(sd, reg->reg & 0xff, val); | ||
| 863 | break; | ||
| 864 | case 0xa: | ||
| 865 | cp_write(sd, reg->reg & 0xff, val); | ||
| 866 | break; | ||
| 867 | case 0xb: | ||
| 868 | vdp_write(sd, reg->reg & 0xff, val); | ||
| 869 | break; | ||
| 870 | default: | ||
| 871 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | ||
| 872 | adv7842_inv_register(sd); | ||
| 873 | break; | ||
| 874 | } | ||
| 875 | return 0; | ||
| 876 | } | ||
| 877 | #endif | ||
| 878 | |||
| 879 | static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) | ||
| 880 | { | ||
| 881 | struct adv7842_state *state = to_state(sd); | ||
| 882 | int prev = v4l2_ctrl_g_ctrl(state->detect_tx_5v_ctrl); | ||
| 883 | u8 reg_io_6f = io_read(sd, 0x6f); | ||
| 884 | int val = 0; | ||
| 885 | |||
| 886 | if (reg_io_6f & 0x02) | ||
| 887 | val |= 1; /* port A */ | ||
| 888 | if (reg_io_6f & 0x01) | ||
| 889 | val |= 2; /* port B */ | ||
| 890 | |||
| 891 | v4l2_dbg(1, debug, sd, "%s: 0x%x -> 0x%x\n", __func__, prev, val); | ||
| 892 | |||
| 893 | if (val != prev) | ||
| 894 | return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, val); | ||
| 895 | return 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, | ||
| 899 | u8 prim_mode, | ||
| 900 | const struct adv7842_video_standards *predef_vid_timings, | ||
| 901 | const struct v4l2_dv_timings *timings) | ||
| 902 | { | ||
| 903 | int i; | ||
| 904 | |||
| 905 | for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { | ||
| 906 | if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings, | ||
| 907 | is_digital_input(sd) ? 250000 : 1000000)) | ||
| 908 | continue; | ||
| 909 | /* video std */ | ||
| 910 | io_write(sd, 0x00, predef_vid_timings[i].vid_std); | ||
| 911 | /* v_freq and prim mode */ | ||
| 912 | io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) + prim_mode); | ||
| 913 | return 0; | ||
| 914 | } | ||
| 915 | |||
| 916 | return -1; | ||
| 917 | } | ||
| 918 | |||
| 919 | static int configure_predefined_video_timings(struct v4l2_subdev *sd, | ||
| 920 | struct v4l2_dv_timings *timings) | ||
| 921 | { | ||
| 922 | struct adv7842_state *state = to_state(sd); | ||
| 923 | int err; | ||
| 924 | |||
| 925 | v4l2_dbg(1, debug, sd, "%s\n", __func__); | ||
| 926 | |||
| 927 | /* reset to default values */ | ||
| 928 | io_write(sd, 0x16, 0x43); | ||
| 929 | io_write(sd, 0x17, 0x5a); | ||
| 930 | /* disable embedded syncs for auto graphics mode */ | ||
| 931 | cp_write_and_or(sd, 0x81, 0xef, 0x00); | ||
| 932 | cp_write(sd, 0x26, 0x00); | ||
| 933 | cp_write(sd, 0x27, 0x00); | ||
| 934 | cp_write(sd, 0x28, 0x00); | ||
| 935 | cp_write(sd, 0x29, 0x00); | ||
| 936 | cp_write(sd, 0x8f, 0x00); | ||
| 937 | cp_write(sd, 0x90, 0x00); | ||
| 938 | cp_write(sd, 0xa5, 0x00); | ||
| 939 | cp_write(sd, 0xa6, 0x00); | ||
| 940 | cp_write(sd, 0xa7, 0x00); | ||
| 941 | cp_write(sd, 0xab, 0x00); | ||
| 942 | cp_write(sd, 0xac, 0x00); | ||
| 943 | |||
| 944 | switch (state->mode) { | ||
| 945 | case ADV7842_MODE_COMP: | ||
| 946 | case ADV7842_MODE_RGB: | ||
| 947 | err = find_and_set_predefined_video_timings(sd, | ||
| 948 | 0x01, adv7842_prim_mode_comp, timings); | ||
| 949 | if (err) | ||
| 950 | err = find_and_set_predefined_video_timings(sd, | ||
| 951 | 0x02, adv7842_prim_mode_gr, timings); | ||
| 952 | break; | ||
| 953 | case ADV7842_MODE_HDMI: | ||
| 954 | err = find_and_set_predefined_video_timings(sd, | ||
| 955 | 0x05, adv7842_prim_mode_hdmi_comp, timings); | ||
| 956 | if (err) | ||
| 957 | err = find_and_set_predefined_video_timings(sd, | ||
| 958 | 0x06, adv7842_prim_mode_hdmi_gr, timings); | ||
| 959 | break; | ||
| 960 | default: | ||
| 961 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
| 962 | __func__, state->mode); | ||
| 963 | err = -1; | ||
| 964 | break; | ||
| 965 | } | ||
| 966 | |||
| 967 | |||
| 968 | return err; | ||
| 969 | } | ||
| 970 | |||
| 971 | static void configure_custom_video_timings(struct v4l2_subdev *sd, | ||
| 972 | const struct v4l2_bt_timings *bt) | ||
| 973 | { | ||
| 974 | struct adv7842_state *state = to_state(sd); | ||
| 975 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 976 | u32 width = htotal(bt); | ||
| 977 | u32 height = vtotal(bt); | ||
| 978 | u16 cp_start_sav = bt->hsync + bt->hbackporch - 4; | ||
| 979 | u16 cp_start_eav = width - bt->hfrontporch; | ||
| 980 | u16 cp_start_vbi = height - bt->vfrontporch + 1; | ||
| 981 | u16 cp_end_vbi = bt->vsync + bt->vbackporch + 1; | ||
| 982 | u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ? | ||
| 983 | ((width * (ADV7842_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0; | ||
| 984 | const u8 pll[2] = { | ||
| 985 | 0xc0 | ((width >> 8) & 0x1f), | ||
| 986 | width & 0xff | ||
| 987 | }; | ||
| 988 | |||
| 989 | v4l2_dbg(2, debug, sd, "%s\n", __func__); | ||
| 990 | |||
| 991 | switch (state->mode) { | ||
| 992 | case ADV7842_MODE_COMP: | ||
| 993 | case ADV7842_MODE_RGB: | ||
| 994 | /* auto graphics */ | ||
| 995 | io_write(sd, 0x00, 0x07); /* video std */ | ||
| 996 | io_write(sd, 0x01, 0x02); /* prim mode */ | ||
| 997 | /* enable embedded syncs for auto graphics mode */ | ||
| 998 | cp_write_and_or(sd, 0x81, 0xef, 0x10); | ||
| 999 | |||
| 1000 | /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */ | ||
| 1001 | /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */ | ||
| 1002 | /* IO-map reg. 0x16 and 0x17 should be written in sequence */ | ||
| 1003 | if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) { | ||
| 1004 | v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n"); | ||
| 1005 | break; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /* active video - horizontal timing */ | ||
| 1009 | cp_write(sd, 0x26, (cp_start_sav >> 8) & 0xf); | ||
| 1010 | cp_write(sd, 0x27, (cp_start_sav & 0xff)); | ||
| 1011 | cp_write(sd, 0x28, (cp_start_eav >> 8) & 0xf); | ||
| 1012 | cp_write(sd, 0x29, (cp_start_eav & 0xff)); | ||
| 1013 | |||
| 1014 | /* active video - vertical timing */ | ||
| 1015 | cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff); | ||
| 1016 | cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | | ||
| 1017 | ((cp_end_vbi >> 8) & 0xf)); | ||
| 1018 | cp_write(sd, 0xa7, cp_end_vbi & 0xff); | ||
| 1019 | break; | ||
| 1020 | case ADV7842_MODE_HDMI: | ||
| 1021 | /* set default prim_mode/vid_std for HDMI | ||
| 1022 | accoring to [REF_03, c. 4.2] */ | ||
| 1023 | io_write(sd, 0x00, 0x02); /* video std */ | ||
| 1024 | io_write(sd, 0x01, 0x06); /* prim mode */ | ||
| 1025 | break; | ||
| 1026 | default: | ||
| 1027 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
| 1028 | __func__, state->mode); | ||
| 1029 | break; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); | ||
| 1033 | cp_write(sd, 0x90, ch1_fr_ll & 0xff); | ||
| 1034 | cp_write(sd, 0xab, (height >> 4) & 0xff); | ||
| 1035 | cp_write(sd, 0xac, (height & 0x0f) << 4); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static void set_rgb_quantization_range(struct v4l2_subdev *sd) | ||
| 1039 | { | ||
| 1040 | struct adv7842_state *state = to_state(sd); | ||
| 1041 | |||
| 1042 | switch (state->rgb_quantization_range) { | ||
| 1043 | case V4L2_DV_RGB_RANGE_AUTO: | ||
| 1044 | /* automatic */ | ||
| 1045 | if (is_digital_input(sd) && !(hdmi_read(sd, 0x05) & 0x80)) { | ||
| 1046 | /* receiving DVI-D signal */ | ||
| 1047 | |||
| 1048 | /* ADV7842 selects RGB limited range regardless of | ||
| 1049 | input format (CE/IT) in automatic mode */ | ||
| 1050 | if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
| 1051 | /* RGB limited range (16-235) */ | ||
| 1052 | io_write_and_or(sd, 0x02, 0x0f, 0x00); | ||
| 1053 | |||
| 1054 | } else { | ||
| 1055 | /* RGB full range (0-255) */ | ||
| 1056 | io_write_and_or(sd, 0x02, 0x0f, 0x10); | ||
| 1057 | } | ||
| 1058 | } else { | ||
| 1059 | /* receiving HDMI or analog signal, set automode */ | ||
| 1060 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); | ||
| 1061 | } | ||
| 1062 | break; | ||
| 1063 | case V4L2_DV_RGB_RANGE_LIMITED: | ||
| 1064 | /* RGB limited range (16-235) */ | ||
| 1065 | io_write_and_or(sd, 0x02, 0x0f, 0x00); | ||
| 1066 | break; | ||
| 1067 | case V4L2_DV_RGB_RANGE_FULL: | ||
| 1068 | /* RGB full range (0-255) */ | ||
| 1069 | io_write_and_or(sd, 0x02, 0x0f, 0x10); | ||
| 1070 | break; | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static int adv7842_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1075 | { | ||
| 1076 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
| 1077 | struct adv7842_state *state = to_state(sd); | ||
| 1078 | |||
| 1079 | /* TODO SDP ctrls | ||
| 1080 | contrast/brightness/hue/free run is acting a bit strange, | ||
| 1081 | not sure if sdp csc is correct. | ||
| 1082 | */ | ||
| 1083 | switch (ctrl->id) { | ||
| 1084 | /* standard ctrls */ | ||
| 1085 | case V4L2_CID_BRIGHTNESS: | ||
| 1086 | cp_write(sd, 0x3c, ctrl->val); | ||
| 1087 | sdp_write(sd, 0x14, ctrl->val); | ||
| 1088 | /* ignore lsb sdp 0x17[3:2] */ | ||
| 1089 | return 0; | ||
| 1090 | case V4L2_CID_CONTRAST: | ||
| 1091 | cp_write(sd, 0x3a, ctrl->val); | ||
| 1092 | sdp_write(sd, 0x13, ctrl->val); | ||
| 1093 | /* ignore lsb sdp 0x17[1:0] */ | ||
| 1094 | return 0; | ||
| 1095 | case V4L2_CID_SATURATION: | ||
| 1096 | cp_write(sd, 0x3b, ctrl->val); | ||
| 1097 | sdp_write(sd, 0x15, ctrl->val); | ||
| 1098 | /* ignore lsb sdp 0x17[5:4] */ | ||
| 1099 | return 0; | ||
| 1100 | case V4L2_CID_HUE: | ||
| 1101 | cp_write(sd, 0x3d, ctrl->val); | ||
| 1102 | sdp_write(sd, 0x16, ctrl->val); | ||
| 1103 | /* ignore lsb sdp 0x17[7:6] */ | ||
| 1104 | return 0; | ||
| 1105 | /* custom ctrls */ | ||
| 1106 | case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE: | ||
| 1107 | afe_write(sd, 0xc8, ctrl->val); | ||
| 1108 | return 0; | ||
| 1109 | case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL: | ||
| 1110 | cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2)); | ||
| 1111 | sdp_write_and_or(sd, 0xdd, ~0x04, (ctrl->val << 2)); | ||
| 1112 | return 0; | ||
| 1113 | case V4L2_CID_ADV_RX_FREE_RUN_COLOR: { | ||
| 1114 | u8 R = (ctrl->val & 0xff0000) >> 16; | ||
| 1115 | u8 G = (ctrl->val & 0x00ff00) >> 8; | ||
| 1116 | u8 B = (ctrl->val & 0x0000ff); | ||
| 1117 | /* RGB -> YUV, numerical approximation */ | ||
| 1118 | int Y = 66 * R + 129 * G + 25 * B; | ||
| 1119 | int U = -38 * R - 74 * G + 112 * B; | ||
| 1120 | int V = 112 * R - 94 * G - 18 * B; | ||
| 1121 | |||
| 1122 | /* Scale down to 8 bits with rounding */ | ||
| 1123 | Y = (Y + 128) >> 8; | ||
| 1124 | U = (U + 128) >> 8; | ||
| 1125 | V = (V + 128) >> 8; | ||
| 1126 | /* make U,V positive */ | ||
| 1127 | Y += 16; | ||
| 1128 | U += 128; | ||
| 1129 | V += 128; | ||
| 1130 | |||
| 1131 | v4l2_dbg(1, debug, sd, "R %x, G %x, B %x\n", R, G, B); | ||
| 1132 | v4l2_dbg(1, debug, sd, "Y %x, U %x, V %x\n", Y, U, V); | ||
| 1133 | |||
| 1134 | /* CP */ | ||
| 1135 | cp_write(sd, 0xc1, R); | ||
| 1136 | cp_write(sd, 0xc0, G); | ||
| 1137 | cp_write(sd, 0xc2, B); | ||
| 1138 | /* SDP */ | ||
| 1139 | sdp_write(sd, 0xde, Y); | ||
| 1140 | sdp_write(sd, 0xdf, (V & 0xf0) | ((U >> 4) & 0x0f)); | ||
| 1141 | return 0; | ||
| 1142 | } | ||
| 1143 | case V4L2_CID_DV_RX_RGB_RANGE: | ||
| 1144 | state->rgb_quantization_range = ctrl->val; | ||
| 1145 | set_rgb_quantization_range(sd); | ||
| 1146 | return 0; | ||
| 1147 | } | ||
| 1148 | return -EINVAL; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | static inline bool no_power(struct v4l2_subdev *sd) | ||
| 1152 | { | ||
| 1153 | return io_read(sd, 0x0c) & 0x24; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | static inline bool no_cp_signal(struct v4l2_subdev *sd) | ||
| 1157 | { | ||
| 1158 | return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0) || !(cp_read(sd, 0xb1) & 0x80); | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | static inline bool is_hdmi(struct v4l2_subdev *sd) | ||
| 1162 | { | ||
| 1163 | return hdmi_read(sd, 0x05) & 0x80; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | static int adv7842_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
| 1167 | { | ||
| 1168 | struct adv7842_state *state = to_state(sd); | ||
| 1169 | |||
| 1170 | *status = 0; | ||
| 1171 | |||
| 1172 | if (io_read(sd, 0x0c) & 0x24) | ||
| 1173 | *status |= V4L2_IN_ST_NO_POWER; | ||
| 1174 | |||
| 1175 | if (state->mode == ADV7842_MODE_SDP) { | ||
| 1176 | /* status from SDP block */ | ||
| 1177 | if (!(sdp_read(sd, 0x5A) & 0x01)) | ||
| 1178 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
| 1179 | |||
| 1180 | v4l2_dbg(1, debug, sd, "%s: SDP status = 0x%x\n", | ||
| 1181 | __func__, *status); | ||
| 1182 | return 0; | ||
| 1183 | } | ||
| 1184 | /* status from CP block */ | ||
| 1185 | if ((cp_read(sd, 0xb5) & 0xd0) != 0xd0 || | ||
| 1186 | !(cp_read(sd, 0xb1) & 0x80)) | ||
| 1187 | /* TODO channel 2 */ | ||
| 1188 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
| 1189 | |||
| 1190 | if (is_digital_input(sd) && ((io_read(sd, 0x74) & 0x03) != 0x03)) | ||
| 1191 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
| 1192 | |||
| 1193 | v4l2_dbg(1, debug, sd, "%s: CP status = 0x%x\n", | ||
| 1194 | __func__, *status); | ||
| 1195 | |||
| 1196 | return 0; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | struct stdi_readback { | ||
| 1200 | u16 bl, lcf, lcvs; | ||
| 1201 | u8 hs_pol, vs_pol; | ||
| 1202 | bool interlaced; | ||
| 1203 | }; | ||
| 1204 | |||
| 1205 | static int stdi2dv_timings(struct v4l2_subdev *sd, | ||
| 1206 | struct stdi_readback *stdi, | ||
| 1207 | struct v4l2_dv_timings *timings) | ||
| 1208 | { | ||
| 1209 | struct adv7842_state *state = to_state(sd); | ||
| 1210 | u32 hfreq = (ADV7842_fsc * 8) / stdi->bl; | ||
| 1211 | u32 pix_clk; | ||
| 1212 | int i; | ||
| 1213 | |||
| 1214 | for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
| 1215 | const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; | ||
| 1216 | |||
| 1217 | if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], | ||
| 1218 | adv7842_get_dv_timings_cap(sd), | ||
| 1219 | adv7842_check_dv_timings, NULL)) | ||
| 1220 | continue; | ||
| 1221 | if (vtotal(bt) != stdi->lcf + 1) | ||
| 1222 | continue; | ||
| 1223 | if (bt->vsync != stdi->lcvs) | ||
| 1224 | continue; | ||
| 1225 | |||
| 1226 | pix_clk = hfreq * htotal(bt); | ||
| 1227 | |||
| 1228 | if ((pix_clk < bt->pixelclock + 1000000) && | ||
| 1229 | (pix_clk > bt->pixelclock - 1000000)) { | ||
| 1230 | *timings = v4l2_dv_timings_presets[i]; | ||
| 1231 | return 0; | ||
| 1232 | } | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, | ||
| 1236 | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | | ||
| 1237 | (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), | ||
| 1238 | timings)) | ||
| 1239 | return 0; | ||
| 1240 | if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs, | ||
| 1241 | (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | | ||
| 1242 | (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), | ||
| 1243 | state->aspect_ratio, timings)) | ||
| 1244 | return 0; | ||
| 1245 | |||
| 1246 | v4l2_dbg(2, debug, sd, | ||
| 1247 | "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n", | ||
| 1248 | __func__, stdi->lcvs, stdi->lcf, stdi->bl, | ||
| 1249 | stdi->hs_pol, stdi->vs_pol); | ||
| 1250 | return -1; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) | ||
| 1254 | { | ||
| 1255 | u32 status; | ||
| 1256 | |||
| 1257 | adv7842_g_input_status(sd, &status); | ||
| 1258 | if (status & V4L2_IN_ST_NO_SIGNAL) { | ||
| 1259 | v4l2_dbg(2, debug, sd, "%s: no signal\n", __func__); | ||
| 1260 | return -ENOLINK; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2); | ||
| 1264 | stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4); | ||
| 1265 | stdi->lcvs = cp_read(sd, 0xb3) >> 3; | ||
| 1266 | |||
| 1267 | if ((cp_read(sd, 0xb5) & 0x80) && ((cp_read(sd, 0xb5) & 0x03) == 0x01)) { | ||
| 1268 | stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ? | ||
| 1269 | ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x'); | ||
| 1270 | stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ? | ||
| 1271 | ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x'); | ||
| 1272 | } else { | ||
| 1273 | stdi->hs_pol = 'x'; | ||
| 1274 | stdi->vs_pol = 'x'; | ||
| 1275 | } | ||
| 1276 | stdi->interlaced = (cp_read(sd, 0xb1) & 0x40) ? true : false; | ||
| 1277 | |||
| 1278 | if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) { | ||
| 1279 | v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__); | ||
| 1280 | return -ENOLINK; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | v4l2_dbg(2, debug, sd, | ||
| 1284 | "%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n", | ||
| 1285 | __func__, stdi->lcf, stdi->bl, stdi->lcvs, | ||
| 1286 | stdi->hs_pol, stdi->vs_pol, | ||
| 1287 | stdi->interlaced ? "interlaced" : "progressive"); | ||
| 1288 | |||
| 1289 | return 0; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | static int adv7842_enum_dv_timings(struct v4l2_subdev *sd, | ||
| 1293 | struct v4l2_enum_dv_timings *timings) | ||
| 1294 | { | ||
| 1295 | return v4l2_enum_dv_timings_cap(timings, | ||
| 1296 | adv7842_get_dv_timings_cap(sd), adv7842_check_dv_timings, NULL); | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | static int adv7842_dv_timings_cap(struct v4l2_subdev *sd, | ||
| 1300 | struct v4l2_dv_timings_cap *cap) | ||
| 1301 | { | ||
| 1302 | *cap = *adv7842_get_dv_timings_cap(sd); | ||
| 1303 | return 0; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings | ||
| 1307 | if the format is listed in adv7604_timings[] */ | ||
| 1308 | static void adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, | ||
| 1309 | struct v4l2_dv_timings *timings) | ||
| 1310 | { | ||
| 1311 | v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd), | ||
| 1312 | is_digital_input(sd) ? 250000 : 1000000, | ||
| 1313 | adv7842_check_dv_timings, NULL); | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | static int adv7842_query_dv_timings(struct v4l2_subdev *sd, | ||
| 1317 | struct v4l2_dv_timings *timings) | ||
| 1318 | { | ||
| 1319 | struct adv7842_state *state = to_state(sd); | ||
| 1320 | struct v4l2_bt_timings *bt = &timings->bt; | ||
| 1321 | struct stdi_readback stdi = { 0 }; | ||
| 1322 | |||
| 1323 | /* SDP block */ | ||
| 1324 | if (state->mode == ADV7842_MODE_SDP) | ||
| 1325 | return -ENODATA; | ||
| 1326 | |||
| 1327 | /* read STDI */ | ||
| 1328 | if (read_stdi(sd, &stdi)) { | ||
| 1329 | v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); | ||
| 1330 | return -ENOLINK; | ||
| 1331 | } | ||
| 1332 | bt->interlaced = stdi.interlaced ? | ||
| 1333 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | ||
| 1334 | bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) | | ||
| 1335 | ((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0); | ||
| 1336 | bt->vsync = stdi.lcvs; | ||
| 1337 | |||
| 1338 | if (is_digital_input(sd)) { | ||
| 1339 | bool lock = hdmi_read(sd, 0x04) & 0x02; | ||
| 1340 | bool interlaced = hdmi_read(sd, 0x0b) & 0x20; | ||
| 1341 | unsigned w = (hdmi_read(sd, 0x07) & 0x1f) * 256 + hdmi_read(sd, 0x08); | ||
| 1342 | unsigned h = (hdmi_read(sd, 0x09) & 0x1f) * 256 + hdmi_read(sd, 0x0a); | ||
| 1343 | unsigned w_total = (hdmi_read(sd, 0x1e) & 0x3f) * 256 + | ||
| 1344 | hdmi_read(sd, 0x1f); | ||
| 1345 | unsigned h_total = ((hdmi_read(sd, 0x26) & 0x3f) * 256 + | ||
| 1346 | hdmi_read(sd, 0x27)) / 2; | ||
| 1347 | unsigned freq = (((hdmi_read(sd, 0x51) << 1) + | ||
| 1348 | (hdmi_read(sd, 0x52) >> 7)) * 1000000) + | ||
| 1349 | ((hdmi_read(sd, 0x52) & 0x7f) * 1000000) / 128; | ||
| 1350 | int i; | ||
| 1351 | |||
| 1352 | if (is_hdmi(sd)) { | ||
| 1353 | /* adjust for deep color mode */ | ||
| 1354 | freq = freq * 8 / (((hdmi_read(sd, 0x0b) & 0xc0)>>6) * 2 + 8); | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | /* No lock? */ | ||
| 1358 | if (!lock) { | ||
| 1359 | v4l2_dbg(1, debug, sd, "%s: no lock on TMDS signal\n", __func__); | ||
| 1360 | return -ENOLCK; | ||
| 1361 | } | ||
| 1362 | /* Interlaced? */ | ||
| 1363 | if (interlaced) { | ||
| 1364 | v4l2_dbg(1, debug, sd, "%s: interlaced video not supported\n", __func__); | ||
| 1365 | return -ERANGE; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
| 1369 | const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt; | ||
| 1370 | |||
| 1371 | if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i], | ||
| 1372 | adv7842_get_dv_timings_cap(sd), | ||
| 1373 | adv7842_check_dv_timings, NULL)) | ||
| 1374 | continue; | ||
| 1375 | if (w_total != htotal(bt) || h_total != vtotal(bt)) | ||
| 1376 | continue; | ||
| 1377 | |||
| 1378 | if (w != bt->width || h != bt->height) | ||
| 1379 | continue; | ||
| 1380 | |||
| 1381 | if (abs(freq - bt->pixelclock) > 1000000) | ||
| 1382 | continue; | ||
| 1383 | *timings = v4l2_dv_timings_presets[i]; | ||
| 1384 | return 0; | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | timings->type = V4L2_DV_BT_656_1120; | ||
| 1388 | |||
| 1389 | bt->width = w; | ||
| 1390 | bt->height = h; | ||
| 1391 | bt->interlaced = (hdmi_read(sd, 0x0b) & 0x20) ? | ||
| 1392 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | ||
| 1393 | bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? | ||
| 1394 | V4L2_DV_VSYNC_POS_POL : 0) | ((hdmi_read(sd, 0x05) & 0x20) ? | ||
| 1395 | V4L2_DV_HSYNC_POS_POL : 0); | ||
| 1396 | bt->pixelclock = (((hdmi_read(sd, 0x51) << 1) + | ||
| 1397 | (hdmi_read(sd, 0x52) >> 7)) * 1000000) + | ||
| 1398 | ((hdmi_read(sd, 0x52) & 0x7f) * 1000000) / 128; | ||
| 1399 | bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x1f) * 256 + | ||
| 1400 | hdmi_read(sd, 0x21); | ||
| 1401 | bt->hsync = (hdmi_read(sd, 0x22) & 0x1f) * 256 + | ||
| 1402 | hdmi_read(sd, 0x23); | ||
| 1403 | bt->hbackporch = (hdmi_read(sd, 0x24) & 0x1f) * 256 + | ||
| 1404 | hdmi_read(sd, 0x25); | ||
| 1405 | bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x3f) * 256 + | ||
| 1406 | hdmi_read(sd, 0x2b)) / 2; | ||
| 1407 | bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x3f) * 256 + | ||
| 1408 | hdmi_read(sd, 0x2d)) / 2; | ||
| 1409 | bt->vsync = ((hdmi_read(sd, 0x2e) & 0x3f) * 256 + | ||
| 1410 | hdmi_read(sd, 0x2f)) / 2; | ||
| 1411 | bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x3f) * 256 + | ||
| 1412 | hdmi_read(sd, 0x31)) / 2; | ||
| 1413 | bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x3f) * 256 + | ||
| 1414 | hdmi_read(sd, 0x33)) / 2; | ||
| 1415 | bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 0x3f) * 256 + | ||
| 1416 | hdmi_read(sd, 0x35)) / 2; | ||
| 1417 | |||
| 1418 | bt->standards = 0; | ||
| 1419 | bt->flags = 0; | ||
| 1420 | } else { | ||
| 1421 | /* Interlaced? */ | ||
| 1422 | if (stdi.interlaced) { | ||
| 1423 | v4l2_dbg(1, debug, sd, "%s: interlaced video not supported\n", __func__); | ||
| 1424 | return -ERANGE; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | if (stdi2dv_timings(sd, &stdi, timings)) { | ||
| 1428 | v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); | ||
| 1429 | return -ERANGE; | ||
| 1430 | } | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | if (debug > 1) | ||
| 1434 | v4l2_print_dv_timings(sd->name, "adv7842_query_dv_timings: ", | ||
| 1435 | timings, true); | ||
| 1436 | return 0; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | static int adv7842_s_dv_timings(struct v4l2_subdev *sd, | ||
| 1440 | struct v4l2_dv_timings *timings) | ||
| 1441 | { | ||
| 1442 | struct adv7842_state *state = to_state(sd); | ||
| 1443 | struct v4l2_bt_timings *bt; | ||
| 1444 | int err; | ||
| 1445 | |||
| 1446 | if (state->mode == ADV7842_MODE_SDP) | ||
| 1447 | return -ENODATA; | ||
| 1448 | |||
| 1449 | bt = &timings->bt; | ||
| 1450 | |||
| 1451 | if (!v4l2_valid_dv_timings(timings, adv7842_get_dv_timings_cap(sd), | ||
| 1452 | adv7842_check_dv_timings, NULL)) | ||
| 1453 | return -ERANGE; | ||
| 1454 | |||
| 1455 | adv7842_fill_optional_dv_timings_fields(sd, timings); | ||
| 1456 | |||
| 1457 | state->timings = *timings; | ||
| 1458 | |||
| 1459 | cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10); | ||
| 1460 | |||
| 1461 | /* Use prim_mode and vid_std when available */ | ||
| 1462 | err = configure_predefined_video_timings(sd, timings); | ||
| 1463 | if (err) { | ||
| 1464 | /* custom settings when the video format | ||
| 1465 | does not have prim_mode/vid_std */ | ||
| 1466 | configure_custom_video_timings(sd, bt); | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | set_rgb_quantization_range(sd); | ||
| 1470 | |||
| 1471 | |||
| 1472 | if (debug > 1) | ||
| 1473 | v4l2_print_dv_timings(sd->name, "adv7842_s_dv_timings: ", | ||
| 1474 | timings, true); | ||
| 1475 | return 0; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | static int adv7842_g_dv_timings(struct v4l2_subdev *sd, | ||
| 1479 | struct v4l2_dv_timings *timings) | ||
| 1480 | { | ||
| 1481 | struct adv7842_state *state = to_state(sd); | ||
| 1482 | |||
| 1483 | if (state->mode == ADV7842_MODE_SDP) | ||
| 1484 | return -ENODATA; | ||
| 1485 | *timings = state->timings; | ||
| 1486 | return 0; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static void enable_input(struct v4l2_subdev *sd) | ||
| 1490 | { | ||
| 1491 | struct adv7842_state *state = to_state(sd); | ||
| 1492 | switch (state->mode) { | ||
| 1493 | case ADV7842_MODE_SDP: | ||
| 1494 | case ADV7842_MODE_COMP: | ||
| 1495 | case ADV7842_MODE_RGB: | ||
| 1496 | /* enable */ | ||
| 1497 | io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ | ||
| 1498 | break; | ||
| 1499 | case ADV7842_MODE_HDMI: | ||
| 1500 | /* enable */ | ||
| 1501 | hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */ | ||
| 1502 | hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ | ||
| 1503 | io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ | ||
| 1504 | break; | ||
| 1505 | default: | ||
| 1506 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
| 1507 | __func__, state->mode); | ||
| 1508 | break; | ||
| 1509 | } | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | static void disable_input(struct v4l2_subdev *sd) | ||
| 1513 | { | ||
| 1514 | /* disable */ | ||
| 1515 | io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */ | ||
| 1516 | hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */ | ||
| 1517 | hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | static void sdp_csc_coeff(struct v4l2_subdev *sd, | ||
| 1521 | const struct adv7842_sdp_csc_coeff *c) | ||
| 1522 | { | ||
| 1523 | /* csc auto/manual */ | ||
| 1524 | sdp_io_write_and_or(sd, 0xe0, 0xbf, c->manual ? 0x00 : 0x40); | ||
| 1525 | |||
| 1526 | if (!c->manual) | ||
| 1527 | return; | ||
| 1528 | |||
| 1529 | /* csc scaling */ | ||
| 1530 | sdp_io_write_and_or(sd, 0xe0, 0x7f, c->scaling == 2 ? 0x80 : 0x00); | ||
| 1531 | |||
| 1532 | /* A coeff */ | ||
| 1533 | sdp_io_write_and_or(sd, 0xe0, 0xe0, c->A1 >> 8); | ||
| 1534 | sdp_io_write(sd, 0xe1, c->A1); | ||
| 1535 | sdp_io_write_and_or(sd, 0xe2, 0xe0, c->A2 >> 8); | ||
| 1536 | sdp_io_write(sd, 0xe3, c->A2); | ||
| 1537 | sdp_io_write_and_or(sd, 0xe4, 0xe0, c->A3 >> 8); | ||
| 1538 | sdp_io_write(sd, 0xe5, c->A3); | ||
| 1539 | |||
| 1540 | /* A scale */ | ||
| 1541 | sdp_io_write_and_or(sd, 0xe6, 0x80, c->A4 >> 8); | ||
| 1542 | sdp_io_write(sd, 0xe7, c->A4); | ||
| 1543 | |||
| 1544 | /* B coeff */ | ||
| 1545 | sdp_io_write_and_or(sd, 0xe8, 0xe0, c->B1 >> 8); | ||
| 1546 | sdp_io_write(sd, 0xe9, c->B1); | ||
| 1547 | sdp_io_write_and_or(sd, 0xea, 0xe0, c->B2 >> 8); | ||
| 1548 | sdp_io_write(sd, 0xeb, c->B2); | ||
| 1549 | sdp_io_write_and_or(sd, 0xec, 0xe0, c->B3 >> 8); | ||
| 1550 | sdp_io_write(sd, 0xed, c->B3); | ||
| 1551 | |||
| 1552 | /* B scale */ | ||
| 1553 | sdp_io_write_and_or(sd, 0xee, 0x80, c->B4 >> 8); | ||
| 1554 | sdp_io_write(sd, 0xef, c->B4); | ||
| 1555 | |||
| 1556 | /* C coeff */ | ||
| 1557 | sdp_io_write_and_or(sd, 0xf0, 0xe0, c->C1 >> 8); | ||
| 1558 | sdp_io_write(sd, 0xf1, c->C1); | ||
| 1559 | sdp_io_write_and_or(sd, 0xf2, 0xe0, c->C2 >> 8); | ||
| 1560 | sdp_io_write(sd, 0xf3, c->C2); | ||
| 1561 | sdp_io_write_and_or(sd, 0xf4, 0xe0, c->C3 >> 8); | ||
| 1562 | sdp_io_write(sd, 0xf5, c->C3); | ||
| 1563 | |||
| 1564 | /* C scale */ | ||
| 1565 | sdp_io_write_and_or(sd, 0xf6, 0x80, c->C4 >> 8); | ||
| 1566 | sdp_io_write(sd, 0xf7, c->C4); | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | static void select_input(struct v4l2_subdev *sd, | ||
| 1570 | enum adv7842_vid_std_select vid_std_select) | ||
| 1571 | { | ||
| 1572 | struct adv7842_state *state = to_state(sd); | ||
| 1573 | |||
| 1574 | switch (state->mode) { | ||
| 1575 | case ADV7842_MODE_SDP: | ||
| 1576 | io_write(sd, 0x00, vid_std_select); /* video std: CVBS or YC mode */ | ||
| 1577 | io_write(sd, 0x01, 0); /* prim mode */ | ||
| 1578 | /* enable embedded syncs for auto graphics mode */ | ||
| 1579 | cp_write_and_or(sd, 0x81, 0xef, 0x10); | ||
| 1580 | |||
| 1581 | afe_write(sd, 0x00, 0x00); /* power up ADC */ | ||
| 1582 | afe_write(sd, 0xc8, 0x00); /* phase control */ | ||
| 1583 | |||
| 1584 | io_write(sd, 0x19, 0x83); /* LLC DLL phase */ | ||
| 1585 | io_write(sd, 0x33, 0x40); /* LLC DLL enable */ | ||
| 1586 | |||
| 1587 | io_write(sd, 0xdd, 0x90); /* Manual 2x output clock */ | ||
| 1588 | /* script says register 0xde, which don't exist in manual */ | ||
| 1589 | |||
| 1590 | /* Manual analog input muxing mode, CVBS (6.4)*/ | ||
| 1591 | afe_write_and_or(sd, 0x02, 0x7f, 0x80); | ||
| 1592 | if (vid_std_select == ADV7842_SDP_VID_STD_CVBS_SD_4x1) { | ||
| 1593 | afe_write(sd, 0x03, 0xa0); /* ADC0 to AIN10 (CVBS), ADC1 N/C*/ | ||
| 1594 | afe_write(sd, 0x04, 0x00); /* ADC2 N/C,ADC3 N/C*/ | ||
| 1595 | } else { | ||
| 1596 | afe_write(sd, 0x03, 0xa0); /* ADC0 to AIN10 (CVBS), ADC1 N/C*/ | ||
| 1597 | afe_write(sd, 0x04, 0xc0); /* ADC2 to AIN12, ADC3 N/C*/ | ||
| 1598 | } | ||
| 1599 | afe_write(sd, 0x0c, 0x1f); /* ADI recommend write */ | ||
| 1600 | afe_write(sd, 0x12, 0x63); /* ADI recommend write */ | ||
| 1601 | |||
| 1602 | sdp_io_write(sd, 0xb2, 0x60); /* Disable AV codes */ | ||
| 1603 | sdp_io_write(sd, 0xc8, 0xe3); /* Disable Ancillary data */ | ||
| 1604 | |||
| 1605 | /* SDP recommended settings */ | ||
| 1606 | sdp_write(sd, 0x00, 0x3F); /* Autodetect PAL NTSC (not SECAM) */ | ||
| 1607 | sdp_write(sd, 0x01, 0x00); /* Pedestal Off */ | ||
| 1608 | |||
| 1609 | sdp_write(sd, 0x03, 0xE4); /* Manual VCR Gain Luma 0x40B */ | ||
| 1610 | sdp_write(sd, 0x04, 0x0B); /* Manual Luma setting */ | ||
| 1611 | sdp_write(sd, 0x05, 0xC3); /* Manual Chroma setting 0x3FE */ | ||
| 1612 | sdp_write(sd, 0x06, 0xFE); /* Manual Chroma setting */ | ||
| 1613 | sdp_write(sd, 0x12, 0x0D); /* Frame TBC,I_P, 3D comb enabled */ | ||
| 1614 | sdp_write(sd, 0xA7, 0x00); /* ADI Recommended Write */ | ||
| 1615 | sdp_io_write(sd, 0xB0, 0x00); /* Disable H and v blanking */ | ||
| 1616 | |||
| 1617 | /* deinterlacer enabled and 3D comb */ | ||
| 1618 | sdp_write_and_or(sd, 0x12, 0xf6, 0x09); | ||
| 1619 | |||
| 1620 | sdp_write(sd, 0xdd, 0x08); /* free run auto */ | ||
| 1621 | |||
| 1622 | break; | ||
| 1623 | |||
| 1624 | case ADV7842_MODE_COMP: | ||
| 1625 | case ADV7842_MODE_RGB: | ||
| 1626 | /* Automatic analog input muxing mode */ | ||
| 1627 | afe_write_and_or(sd, 0x02, 0x7f, 0x00); | ||
| 1628 | /* set mode and select free run resolution */ | ||
| 1629 | io_write(sd, 0x00, vid_std_select); /* video std */ | ||
| 1630 | io_write(sd, 0x01, 0x02); /* prim mode */ | ||
| 1631 | cp_write_and_or(sd, 0x81, 0xef, 0x10); /* enable embedded syncs | ||
| 1632 | for auto graphics mode */ | ||
| 1633 | |||
| 1634 | afe_write(sd, 0x00, 0x00); /* power up ADC */ | ||
| 1635 | afe_write(sd, 0xc8, 0x00); /* phase control */ | ||
| 1636 | |||
| 1637 | /* set ADI recommended settings for digitizer */ | ||
| 1638 | /* "ADV7842 Register Settings Recommendations | ||
| 1639 | * (rev. 1.8, November 2010)" p. 9. */ | ||
| 1640 | afe_write(sd, 0x0c, 0x1f); /* ADC Range improvement */ | ||
| 1641 | afe_write(sd, 0x12, 0x63); /* ADC Range improvement */ | ||
| 1642 | |||
| 1643 | /* set to default gain for RGB */ | ||
| 1644 | cp_write(sd, 0x73, 0x10); | ||
| 1645 | cp_write(sd, 0x74, 0x04); | ||
| 1646 | cp_write(sd, 0x75, 0x01); | ||
| 1647 | cp_write(sd, 0x76, 0x00); | ||
| 1648 | |||
| 1649 | cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */ | ||
| 1650 | cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ | ||
| 1651 | cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ | ||
| 1652 | break; | ||
| 1653 | |||
| 1654 | case ADV7842_MODE_HDMI: | ||
| 1655 | /* Automatic analog input muxing mode */ | ||
| 1656 | afe_write_and_or(sd, 0x02, 0x7f, 0x00); | ||
| 1657 | /* set mode and select free run resolution */ | ||
| 1658 | if (state->hdmi_port_a) | ||
| 1659 | hdmi_write(sd, 0x00, 0x02); /* select port A */ | ||
| 1660 | else | ||
| 1661 | hdmi_write(sd, 0x00, 0x03); /* select port B */ | ||
| 1662 | io_write(sd, 0x00, vid_std_select); /* video std */ | ||
| 1663 | io_write(sd, 0x01, 5); /* prim mode */ | ||
| 1664 | cp_write_and_or(sd, 0x81, 0xef, 0x00); /* disable embedded syncs | ||
| 1665 | for auto graphics mode */ | ||
| 1666 | |||
| 1667 | /* set ADI recommended settings for HDMI: */ | ||
| 1668 | /* "ADV7842 Register Settings Recommendations | ||
| 1669 | * (rev. 1.8, November 2010)" p. 3. */ | ||
| 1670 | hdmi_write(sd, 0xc0, 0x00); | ||
| 1671 | hdmi_write(sd, 0x0d, 0x34); /* ADI recommended write */ | ||
| 1672 | hdmi_write(sd, 0x3d, 0x10); /* ADI recommended write */ | ||
| 1673 | hdmi_write(sd, 0x44, 0x85); /* TMDS PLL optimization */ | ||
| 1674 | hdmi_write(sd, 0x46, 0x1f); /* ADI recommended write */ | ||
| 1675 | hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */ | ||
| 1676 | hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */ | ||
| 1677 | hdmi_write(sd, 0x60, 0x88); /* TMDS PLL optimization */ | ||
| 1678 | hdmi_write(sd, 0x61, 0x88); /* TMDS PLL optimization */ | ||
| 1679 | hdmi_write(sd, 0x6c, 0x18); /* Disable ISRC clearing bit, | ||
| 1680 | Improve robustness */ | ||
| 1681 | hdmi_write(sd, 0x75, 0x10); /* DDC drive strength */ | ||
| 1682 | hdmi_write(sd, 0x85, 0x1f); /* equaliser */ | ||
| 1683 | hdmi_write(sd, 0x87, 0x70); /* ADI recommended write */ | ||
| 1684 | hdmi_write(sd, 0x89, 0x04); /* equaliser */ | ||
| 1685 | hdmi_write(sd, 0x8a, 0x1e); /* equaliser */ | ||
| 1686 | hdmi_write(sd, 0x93, 0x04); /* equaliser */ | ||
| 1687 | hdmi_write(sd, 0x94, 0x1e); /* equaliser */ | ||
| 1688 | hdmi_write(sd, 0x99, 0xa1); /* ADI recommended write */ | ||
| 1689 | hdmi_write(sd, 0x9b, 0x09); /* ADI recommended write */ | ||
| 1690 | hdmi_write(sd, 0x9d, 0x02); /* equaliser */ | ||
| 1691 | |||
| 1692 | afe_write(sd, 0x00, 0xff); /* power down ADC */ | ||
| 1693 | afe_write(sd, 0xc8, 0x40); /* phase control */ | ||
| 1694 | |||
| 1695 | /* set to default gain for HDMI */ | ||
| 1696 | cp_write(sd, 0x73, 0x10); | ||
| 1697 | cp_write(sd, 0x74, 0x04); | ||
| 1698 | cp_write(sd, 0x75, 0x01); | ||
| 1699 | cp_write(sd, 0x76, 0x00); | ||
| 1700 | |||
| 1701 | /* reset ADI recommended settings for digitizer */ | ||
| 1702 | /* "ADV7842 Register Settings Recommendations | ||
| 1703 | * (rev. 2.5, June 2010)" p. 17. */ | ||
| 1704 | afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */ | ||
| 1705 | afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */ | ||
| 1706 | cp_write(sd, 0x3e, 0x80); /* CP core pre-gain control, | ||
| 1707 | enable color control */ | ||
| 1708 | /* CP coast control */ | ||
| 1709 | cp_write(sd, 0xc3, 0x33); /* Component mode */ | ||
| 1710 | |||
| 1711 | /* color space conversion, autodetect color space */ | ||
| 1712 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); | ||
| 1713 | break; | ||
| 1714 | |||
| 1715 | default: | ||
| 1716 | v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", | ||
| 1717 | __func__, state->mode); | ||
| 1718 | break; | ||
| 1719 | } | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | static int adv7842_s_routing(struct v4l2_subdev *sd, | ||
| 1723 | u32 input, u32 output, u32 config) | ||
| 1724 | { | ||
| 1725 | struct adv7842_state *state = to_state(sd); | ||
| 1726 | |||
| 1727 | v4l2_dbg(2, debug, sd, "%s: input %d\n", __func__, input); | ||
| 1728 | |||
| 1729 | switch (input) { | ||
| 1730 | case ADV7842_SELECT_HDMI_PORT_A: | ||
| 1731 | /* TODO select HDMI_COMP or HDMI_GR */ | ||
| 1732 | state->mode = ADV7842_MODE_HDMI; | ||
| 1733 | state->vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P; | ||
| 1734 | state->hdmi_port_a = true; | ||
| 1735 | break; | ||
| 1736 | case ADV7842_SELECT_HDMI_PORT_B: | ||
| 1737 | /* TODO select HDMI_COMP or HDMI_GR */ | ||
| 1738 | state->mode = ADV7842_MODE_HDMI; | ||
| 1739 | state->vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P; | ||
| 1740 | state->hdmi_port_a = false; | ||
| 1741 | break; | ||
| 1742 | case ADV7842_SELECT_VGA_COMP: | ||
| 1743 | v4l2_info(sd, "%s: VGA component: todo\n", __func__); | ||
| 1744 | case ADV7842_SELECT_VGA_RGB: | ||
| 1745 | state->mode = ADV7842_MODE_RGB; | ||
| 1746 | state->vid_std_select = ADV7842_RGB_VID_STD_AUTO_GRAPH_MODE; | ||
| 1747 | break; | ||
| 1748 | case ADV7842_SELECT_SDP_CVBS: | ||
| 1749 | state->mode = ADV7842_MODE_SDP; | ||
| 1750 | state->vid_std_select = ADV7842_SDP_VID_STD_CVBS_SD_4x1; | ||
| 1751 | break; | ||
| 1752 | case ADV7842_SELECT_SDP_YC: | ||
| 1753 | state->mode = ADV7842_MODE_SDP; | ||
| 1754 | state->vid_std_select = ADV7842_SDP_VID_STD_YC_SD4_x1; | ||
| 1755 | break; | ||
| 1756 | default: | ||
| 1757 | return -EINVAL; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | disable_input(sd); | ||
| 1761 | select_input(sd, state->vid_std_select); | ||
| 1762 | enable_input(sd); | ||
| 1763 | |||
| 1764 | v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL); | ||
| 1765 | |||
| 1766 | return 0; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, | ||
| 1770 | enum v4l2_mbus_pixelcode *code) | ||
| 1771 | { | ||
| 1772 | if (index) | ||
| 1773 | return -EINVAL; | ||
| 1774 | /* Good enough for now */ | ||
| 1775 | *code = V4L2_MBUS_FMT_FIXED; | ||
| 1776 | return 0; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | static int adv7842_g_mbus_fmt(struct v4l2_subdev *sd, | ||
| 1780 | struct v4l2_mbus_framefmt *fmt) | ||
| 1781 | { | ||
| 1782 | struct adv7842_state *state = to_state(sd); | ||
| 1783 | |||
| 1784 | fmt->width = state->timings.bt.width; | ||
| 1785 | fmt->height = state->timings.bt.height; | ||
| 1786 | fmt->code = V4L2_MBUS_FMT_FIXED; | ||
| 1787 | fmt->field = V4L2_FIELD_NONE; | ||
| 1788 | |||
| 1789 | if (state->mode == ADV7842_MODE_SDP) { | ||
| 1790 | /* SPD block */ | ||
| 1791 | if (!(sdp_read(sd, 0x5A) & 0x01)) | ||
| 1792 | return -EINVAL; | ||
| 1793 | fmt->width = 720; | ||
| 1794 | /* valid signal */ | ||
| 1795 | if (state->norm & V4L2_STD_525_60) | ||
| 1796 | fmt->height = 480; | ||
| 1797 | else | ||
| 1798 | fmt->height = 576; | ||
| 1799 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
| 1800 | return 0; | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { | ||
| 1804 | fmt->colorspace = (state->timings.bt.height <= 576) ? | ||
| 1805 | V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709; | ||
| 1806 | } | ||
| 1807 | return 0; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | static void adv7842_irq_enable(struct v4l2_subdev *sd, bool enable) | ||
| 1811 | { | ||
| 1812 | if (enable) { | ||
| 1813 | /* Enable SSPD, STDI and CP locked/unlocked interrupts */ | ||
| 1814 | io_write(sd, 0x46, 0x9c); | ||
| 1815 | /* ESDP_50HZ_DET interrupt */ | ||
| 1816 | io_write(sd, 0x5a, 0x10); | ||
| 1817 | /* Enable CABLE_DET_A/B_ST (+5v) interrupt */ | ||
| 1818 | io_write(sd, 0x73, 0x03); | ||
| 1819 | /* Enable V_LOCKED and DE_REGEN_LCK interrupts */ | ||
| 1820 | io_write(sd, 0x78, 0x03); | ||
| 1821 | /* Enable SDP Standard Detection Change and SDP Video Detected */ | ||
| 1822 | io_write(sd, 0xa0, 0x09); | ||
| 1823 | } else { | ||
| 1824 | io_write(sd, 0x46, 0x0); | ||
| 1825 | io_write(sd, 0x5a, 0x0); | ||
| 1826 | io_write(sd, 0x73, 0x0); | ||
| 1827 | io_write(sd, 0x78, 0x0); | ||
| 1828 | io_write(sd, 0xa0, 0x0); | ||
| 1829 | } | ||
| 1830 | } | ||
| 1831 | |||
| 1832 | static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | ||
| 1833 | { | ||
| 1834 | struct adv7842_state *state = to_state(sd); | ||
| 1835 | u8 fmt_change_cp, fmt_change_digital, fmt_change_sdp; | ||
| 1836 | u8 irq_status[5]; | ||
| 1837 | u8 irq_cfg = io_read(sd, 0x40); | ||
| 1838 | |||
| 1839 | /* disable irq-pin output */ | ||
| 1840 | io_write(sd, 0x40, irq_cfg | 0x3); | ||
| 1841 | |||
| 1842 | /* read status */ | ||
| 1843 | irq_status[0] = io_read(sd, 0x43); | ||
| 1844 | irq_status[1] = io_read(sd, 0x57); | ||
| 1845 | irq_status[2] = io_read(sd, 0x70); | ||
| 1846 | irq_status[3] = io_read(sd, 0x75); | ||
| 1847 | irq_status[4] = io_read(sd, 0x9d); | ||
| 1848 | |||
| 1849 | /* and clear */ | ||
| 1850 | if (irq_status[0]) | ||
| 1851 | io_write(sd, 0x44, irq_status[0]); | ||
| 1852 | if (irq_status[1]) | ||
| 1853 | io_write(sd, 0x58, irq_status[1]); | ||
| 1854 | if (irq_status[2]) | ||
| 1855 | io_write(sd, 0x71, irq_status[2]); | ||
| 1856 | if (irq_status[3]) | ||
| 1857 | io_write(sd, 0x76, irq_status[3]); | ||
| 1858 | if (irq_status[4]) | ||
| 1859 | io_write(sd, 0x9e, irq_status[4]); | ||
| 1860 | |||
| 1861 | v4l2_dbg(1, debug, sd, "%s: irq %x, %x, %x, %x, %x\n", __func__, | ||
| 1862 | irq_status[0], irq_status[1], irq_status[2], | ||
| 1863 | irq_status[3], irq_status[4]); | ||
| 1864 | |||
| 1865 | /* format change CP */ | ||
| 1866 | fmt_change_cp = irq_status[0] & 0x9c; | ||
| 1867 | |||
| 1868 | /* format change SDP */ | ||
| 1869 | if (state->mode == ADV7842_MODE_SDP) | ||
| 1870 | fmt_change_sdp = (irq_status[1] & 0x30) | (irq_status[4] & 0x09); | ||
| 1871 | else | ||
| 1872 | fmt_change_sdp = 0; | ||
| 1873 | |||
| 1874 | /* digital format CP */ | ||
| 1875 | if (is_digital_input(sd)) | ||
| 1876 | fmt_change_digital = irq_status[3] & 0x03; | ||
| 1877 | else | ||
| 1878 | fmt_change_digital = 0; | ||
| 1879 | |||
| 1880 | /* notify */ | ||
| 1881 | if (fmt_change_cp || fmt_change_digital || fmt_change_sdp) { | ||
| 1882 | v4l2_dbg(1, debug, sd, | ||
| 1883 | "%s: fmt_change_cp = 0x%x, fmt_change_digital = 0x%x, fmt_change_sdp = 0x%x\n", | ||
| 1884 | __func__, fmt_change_cp, fmt_change_digital, | ||
| 1885 | fmt_change_sdp); | ||
| 1886 | v4l2_subdev_notify(sd, ADV7842_FMT_CHANGE, NULL); | ||
| 1887 | } | ||
| 1888 | |||
| 1889 | /* 5v cable detect */ | ||
| 1890 | if (irq_status[2]) | ||
| 1891 | adv7842_s_detect_tx_5v_ctrl(sd); | ||
| 1892 | |||
| 1893 | if (handled) | ||
| 1894 | *handled = true; | ||
| 1895 | |||
| 1896 | /* re-enable irq-pin output */ | ||
| 1897 | io_write(sd, 0x40, irq_cfg); | ||
| 1898 | |||
| 1899 | return 0; | ||
| 1900 | } | ||
| 1901 | |||
| 1902 | static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e) | ||
| 1903 | { | ||
| 1904 | struct adv7842_state *state = to_state(sd); | ||
| 1905 | int err = 0; | ||
| 1906 | |||
| 1907 | if (e->pad > 2) | ||
| 1908 | return -EINVAL; | ||
| 1909 | if (e->start_block != 0) | ||
| 1910 | return -EINVAL; | ||
| 1911 | if (e->blocks > 2) | ||
| 1912 | return -E2BIG; | ||
| 1913 | if (!e->edid) | ||
| 1914 | return -EINVAL; | ||
| 1915 | |||
| 1916 | /* todo, per edid */ | ||
| 1917 | state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15], | ||
| 1918 | e->edid[0x16]); | ||
| 1919 | |||
| 1920 | if (e->pad == 2) { | ||
| 1921 | memset(&state->vga_edid.edid, 0, 256); | ||
| 1922 | state->vga_edid.present = e->blocks ? 0x1 : 0x0; | ||
| 1923 | memcpy(&state->vga_edid.edid, e->edid, 128 * e->blocks); | ||
| 1924 | err = edid_write_vga_segment(sd); | ||
| 1925 | } else { | ||
| 1926 | u32 mask = 0x1<<e->pad; | ||
| 1927 | memset(&state->hdmi_edid.edid, 0, 256); | ||
| 1928 | if (e->blocks) | ||
| 1929 | state->hdmi_edid.present |= mask; | ||
| 1930 | else | ||
| 1931 | state->hdmi_edid.present &= ~mask; | ||
| 1932 | memcpy(&state->hdmi_edid.edid, e->edid, 128*e->blocks); | ||
| 1933 | err = edid_write_hdmi_segment(sd, e->pad); | ||
| 1934 | } | ||
| 1935 | if (err < 0) | ||
| 1936 | v4l2_err(sd, "error %d writing edid on port %d\n", err, e->pad); | ||
| 1937 | return err; | ||
| 1938 | } | ||
| 1939 | |||
| 1940 | /*********** avi info frame CEA-861-E **************/ | ||
| 1941 | /* TODO move to common library */ | ||
| 1942 | |||
| 1943 | struct avi_info_frame { | ||
| 1944 | uint8_t f17; | ||
| 1945 | uint8_t y10; | ||
| 1946 | uint8_t a0; | ||
| 1947 | uint8_t b10; | ||
| 1948 | uint8_t s10; | ||
| 1949 | uint8_t c10; | ||
| 1950 | uint8_t m10; | ||
| 1951 | uint8_t r3210; | ||
| 1952 | uint8_t itc; | ||
| 1953 | uint8_t ec210; | ||
| 1954 | uint8_t q10; | ||
| 1955 | uint8_t sc10; | ||
| 1956 | uint8_t f47; | ||
| 1957 | uint8_t vic; | ||
| 1958 | uint8_t yq10; | ||
| 1959 | uint8_t cn10; | ||
| 1960 | uint8_t pr3210; | ||
| 1961 | uint16_t etb; | ||
| 1962 | uint16_t sbb; | ||
| 1963 | uint16_t elb; | ||
| 1964 | uint16_t srb; | ||
| 1965 | }; | ||
| 1966 | |||
| 1967 | static const char *y10_txt[4] = { | ||
| 1968 | "RGB", | ||
| 1969 | "YCbCr 4:2:2", | ||
| 1970 | "YCbCr 4:4:4", | ||
| 1971 | "Future", | ||
| 1972 | }; | ||
| 1973 | |||
| 1974 | static const char *c10_txt[4] = { | ||
| 1975 | "No Data", | ||
| 1976 | "SMPTE 170M", | ||
| 1977 | "ITU-R 709", | ||
| 1978 | "Extended Colorimetry information valied", | ||
| 1979 | }; | ||
| 1980 | |||
| 1981 | static const char *itc_txt[2] = { | ||
| 1982 | "No Data", | ||
| 1983 | "IT content", | ||
| 1984 | }; | ||
| 1985 | |||
| 1986 | static const char *ec210_txt[8] = { | ||
| 1987 | "xvYCC601", | ||
| 1988 | "xvYCC709", | ||
| 1989 | "sYCC601", | ||
| 1990 | "AdobeYCC601", | ||
| 1991 | "AdobeRGB", | ||
| 1992 | "5 reserved", | ||
| 1993 | "6 reserved", | ||
| 1994 | "7 reserved", | ||
| 1995 | }; | ||
| 1996 | |||
| 1997 | static const char *q10_txt[4] = { | ||
| 1998 | "Default", | ||
| 1999 | "Limited Range", | ||
| 2000 | "Full Range", | ||
| 2001 | "Reserved", | ||
| 2002 | }; | ||
| 2003 | |||
| 2004 | static void parse_avi_infoframe(struct v4l2_subdev *sd, uint8_t *buf, | ||
| 2005 | struct avi_info_frame *avi) | ||
| 2006 | { | ||
| 2007 | avi->f17 = (buf[1] >> 7) & 0x1; | ||
| 2008 | avi->y10 = (buf[1] >> 5) & 0x3; | ||
| 2009 | avi->a0 = (buf[1] >> 4) & 0x1; | ||
| 2010 | avi->b10 = (buf[1] >> 2) & 0x3; | ||
| 2011 | avi->s10 = buf[1] & 0x3; | ||
| 2012 | avi->c10 = (buf[2] >> 6) & 0x3; | ||
| 2013 | avi->m10 = (buf[2] >> 4) & 0x3; | ||
| 2014 | avi->r3210 = buf[2] & 0xf; | ||
| 2015 | avi->itc = (buf[3] >> 7) & 0x1; | ||
| 2016 | avi->ec210 = (buf[3] >> 4) & 0x7; | ||
| 2017 | avi->q10 = (buf[3] >> 2) & 0x3; | ||
| 2018 | avi->sc10 = buf[3] & 0x3; | ||
| 2019 | avi->f47 = (buf[4] >> 7) & 0x1; | ||
| 2020 | avi->vic = buf[4] & 0x7f; | ||
| 2021 | avi->yq10 = (buf[5] >> 6) & 0x3; | ||
| 2022 | avi->cn10 = (buf[5] >> 4) & 0x3; | ||
| 2023 | avi->pr3210 = buf[5] & 0xf; | ||
| 2024 | avi->etb = buf[6] + 256*buf[7]; | ||
| 2025 | avi->sbb = buf[8] + 256*buf[9]; | ||
| 2026 | avi->elb = buf[10] + 256*buf[11]; | ||
| 2027 | avi->srb = buf[12] + 256*buf[13]; | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static void print_avi_infoframe(struct v4l2_subdev *sd) | ||
| 2031 | { | ||
| 2032 | int i; | ||
| 2033 | uint8_t buf[14]; | ||
| 2034 | uint8_t avi_inf_len; | ||
| 2035 | struct avi_info_frame avi; | ||
| 2036 | |||
| 2037 | if (!(hdmi_read(sd, 0x05) & 0x80)) { | ||
| 2038 | v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); | ||
| 2039 | return; | ||
| 2040 | } | ||
| 2041 | if (!(io_read(sd, 0x60) & 0x01)) { | ||
| 2042 | v4l2_info(sd, "AVI infoframe not received\n"); | ||
| 2043 | return; | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | if (io_read(sd, 0x88) & 0x10) { | ||
| 2047 | /* Note: the ADV7842 calculated incorrect checksums for InfoFrames | ||
| 2048 | with a length of 14 or 15. See the ADV7842 Register Settings | ||
| 2049 | Recommendations document for more details. */ | ||
| 2050 | v4l2_info(sd, "AVI infoframe checksum error\n"); | ||
| 2051 | return; | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | avi_inf_len = infoframe_read(sd, 0xe2); | ||
| 2055 | v4l2_info(sd, "AVI infoframe version %d (%d byte)\n", | ||
| 2056 | infoframe_read(sd, 0xe1), avi_inf_len); | ||
| 2057 | |||
| 2058 | if (infoframe_read(sd, 0xe1) != 0x02) | ||
| 2059 | return; | ||
| 2060 | |||
| 2061 | for (i = 0; i < 14; i++) | ||
| 2062 | buf[i] = infoframe_read(sd, i); | ||
| 2063 | |||
| 2064 | v4l2_info(sd, "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
| 2065 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], | ||
| 2066 | buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]); | ||
| 2067 | |||
| 2068 | parse_avi_infoframe(sd, buf, &avi); | ||
| 2069 | |||
| 2070 | if (avi.vic) | ||
| 2071 | v4l2_info(sd, "\tVIC: %d\n", avi.vic); | ||
| 2072 | if (avi.itc) | ||
| 2073 | v4l2_info(sd, "\t%s\n", itc_txt[avi.itc]); | ||
| 2074 | |||
| 2075 | if (avi.y10) | ||
| 2076 | v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], !avi.c10 ? "" : | ||
| 2077 | (avi.c10 == 0x3 ? ec210_txt[avi.ec210] : c10_txt[avi.c10])); | ||
| 2078 | else | ||
| 2079 | v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], q10_txt[avi.q10]); | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | static const char * const prim_mode_txt[] = { | ||
| 2083 | "SDP", | ||
| 2084 | "Component", | ||
| 2085 | "Graphics", | ||
| 2086 | "Reserved", | ||
| 2087 | "CVBS & HDMI AUDIO", | ||
| 2088 | "HDMI-Comp", | ||
| 2089 | "HDMI-GR", | ||
| 2090 | "Reserved", | ||
| 2091 | "Reserved", | ||
| 2092 | "Reserved", | ||
| 2093 | "Reserved", | ||
| 2094 | "Reserved", | ||
| 2095 | "Reserved", | ||
| 2096 | "Reserved", | ||
| 2097 | "Reserved", | ||
| 2098 | "Reserved", | ||
| 2099 | }; | ||
| 2100 | |||
| 2101 | static int adv7842_sdp_log_status(struct v4l2_subdev *sd) | ||
| 2102 | { | ||
| 2103 | /* SDP (Standard definition processor) block */ | ||
| 2104 | uint8_t sdp_signal_detected = sdp_read(sd, 0x5A) & 0x01; | ||
| 2105 | |||
| 2106 | v4l2_info(sd, "Chip powered %s\n", no_power(sd) ? "off" : "on"); | ||
| 2107 | v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n", | ||
| 2108 | io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f); | ||
| 2109 | |||
| 2110 | v4l2_info(sd, "SDP: free run: %s\n", | ||
| 2111 | (sdp_read(sd, 0x56) & 0x01) ? "on" : "off"); | ||
| 2112 | v4l2_info(sd, "SDP: %s\n", sdp_signal_detected ? | ||
| 2113 | "valid SD/PR signal detected" : "invalid/no signal"); | ||
| 2114 | if (sdp_signal_detected) { | ||
| 2115 | static const char * const sdp_std_txt[] = { | ||
| 2116 | "NTSC-M/J", | ||
| 2117 | "1?", | ||
| 2118 | "NTSC-443", | ||
| 2119 | "60HzSECAM", | ||
| 2120 | "PAL-M", | ||
| 2121 | "5?", | ||
| 2122 | "PAL-60", | ||
| 2123 | "7?", "8?", "9?", "a?", "b?", | ||
| 2124 | "PAL-CombN", | ||
| 2125 | "d?", | ||
| 2126 | "PAL-BGHID", | ||
| 2127 | "SECAM" | ||
| 2128 | }; | ||
| 2129 | v4l2_info(sd, "SDP: standard %s\n", | ||
| 2130 | sdp_std_txt[sdp_read(sd, 0x52) & 0x0f]); | ||
| 2131 | v4l2_info(sd, "SDP: %s\n", | ||
| 2132 | (sdp_read(sd, 0x59) & 0x08) ? "50Hz" : "60Hz"); | ||
| 2133 | v4l2_info(sd, "SDP: %s\n", | ||
| 2134 | (sdp_read(sd, 0x57) & 0x08) ? "Interlaced" : "Progressive"); | ||
| 2135 | v4l2_info(sd, "SDP: deinterlacer %s\n", | ||
| 2136 | (sdp_read(sd, 0x12) & 0x08) ? "enabled" : "disabled"); | ||
| 2137 | v4l2_info(sd, "SDP: csc %s mode\n", | ||
| 2138 | (sdp_io_read(sd, 0xe0) & 0x40) ? "auto" : "manual"); | ||
| 2139 | } | ||
| 2140 | return 0; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | static int adv7842_cp_log_status(struct v4l2_subdev *sd) | ||
| 2144 | { | ||
| 2145 | /* CP block */ | ||
| 2146 | struct adv7842_state *state = to_state(sd); | ||
| 2147 | struct v4l2_dv_timings timings; | ||
| 2148 | uint8_t reg_io_0x02 = io_read(sd, 0x02); | ||
| 2149 | uint8_t reg_io_0x21 = io_read(sd, 0x21); | ||
| 2150 | uint8_t reg_rep_0x77 = rep_read(sd, 0x77); | ||
| 2151 | uint8_t reg_rep_0x7d = rep_read(sd, 0x7d); | ||
| 2152 | bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; | ||
| 2153 | bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; | ||
| 2154 | bool audio_mute = io_read(sd, 0x65) & 0x40; | ||
| 2155 | |||
| 2156 | static const char * const csc_coeff_sel_rb[16] = { | ||
| 2157 | "bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB", | ||
| 2158 | "reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709", | ||
| 2159 | "reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709", | ||
| 2160 | "reserved", "reserved", "reserved", "reserved", "manual" | ||
| 2161 | }; | ||
| 2162 | static const char * const input_color_space_txt[16] = { | ||
| 2163 | "RGB limited range (16-235)", "RGB full range (0-255)", | ||
| 2164 | "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)", | ||
| 2165 | "XvYCC Bt.601", "XvYCC Bt.709", | ||
| 2166 | "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)", | ||
| 2167 | "invalid", "invalid", "invalid", "invalid", "invalid", | ||
| 2168 | "invalid", "invalid", "automatic" | ||
| 2169 | }; | ||
| 2170 | static const char * const rgb_quantization_range_txt[] = { | ||
| 2171 | "Automatic", | ||
| 2172 | "RGB limited range (16-235)", | ||
| 2173 | "RGB full range (0-255)", | ||
| 2174 | }; | ||
| 2175 | static const char * const deep_color_mode_txt[4] = { | ||
| 2176 | "8-bits per channel", | ||
| 2177 | "10-bits per channel", | ||
| 2178 | "12-bits per channel", | ||
| 2179 | "16-bits per channel (not supported)" | ||
| 2180 | }; | ||
| 2181 | |||
| 2182 | v4l2_info(sd, "-----Chip status-----\n"); | ||
| 2183 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); | ||
| 2184 | v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ? | ||
| 2185 | "HDMI" : (is_digital_input(sd) ? "DVI-D" : "DVI-A")); | ||
| 2186 | v4l2_info(sd, "HDMI/DVI-D port selected: %s\n", | ||
| 2187 | state->hdmi_port_a ? "A" : "B"); | ||
| 2188 | v4l2_info(sd, "EDID A %s, B %s\n", | ||
| 2189 | ((reg_rep_0x7d & 0x04) && (reg_rep_0x77 & 0x04)) ? | ||
| 2190 | "enabled" : "disabled", | ||
| 2191 | ((reg_rep_0x7d & 0x08) && (reg_rep_0x77 & 0x08)) ? | ||
| 2192 | "enabled" : "disabled"); | ||
| 2193 | v4l2_info(sd, "HPD A %s, B %s\n", | ||
| 2194 | reg_io_0x21 & 0x02 ? "enabled" : "disabled", | ||
| 2195 | reg_io_0x21 & 0x01 ? "enabled" : "disabled"); | ||
| 2196 | v4l2_info(sd, "CEC %s\n", !!(cec_read(sd, 0x2a) & 0x01) ? | ||
| 2197 | "enabled" : "disabled"); | ||
| 2198 | |||
| 2199 | v4l2_info(sd, "-----Signal status-----\n"); | ||
| 2200 | if (state->hdmi_port_a) { | ||
| 2201 | v4l2_info(sd, "Cable detected (+5V power): %s\n", | ||
| 2202 | io_read(sd, 0x6f) & 0x02 ? "true" : "false"); | ||
| 2203 | v4l2_info(sd, "TMDS signal detected: %s\n", | ||
| 2204 | (io_read(sd, 0x6a) & 0x02) ? "true" : "false"); | ||
| 2205 | v4l2_info(sd, "TMDS signal locked: %s\n", | ||
| 2206 | (io_read(sd, 0x6a) & 0x20) ? "true" : "false"); | ||
| 2207 | } else { | ||
| 2208 | v4l2_info(sd, "Cable detected (+5V power):%s\n", | ||
| 2209 | io_read(sd, 0x6f) & 0x01 ? "true" : "false"); | ||
| 2210 | v4l2_info(sd, "TMDS signal detected: %s\n", | ||
| 2211 | (io_read(sd, 0x6a) & 0x01) ? "true" : "false"); | ||
| 2212 | v4l2_info(sd, "TMDS signal locked: %s\n", | ||
| 2213 | (io_read(sd, 0x6a) & 0x10) ? "true" : "false"); | ||
| 2214 | } | ||
| 2215 | v4l2_info(sd, "CP free run: %s\n", | ||
| 2216 | (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off")); | ||
| 2217 | v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n", | ||
| 2218 | io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f, | ||
| 2219 | (io_read(sd, 0x01) & 0x70) >> 4); | ||
| 2220 | |||
| 2221 | v4l2_info(sd, "-----Video Timings-----\n"); | ||
| 2222 | if (no_cp_signal(sd)) { | ||
| 2223 | v4l2_info(sd, "STDI: not locked\n"); | ||
| 2224 | } else { | ||
| 2225 | uint32_t bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2); | ||
| 2226 | uint32_t lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4); | ||
| 2227 | uint32_t lcvs = cp_read(sd, 0xb3) >> 3; | ||
| 2228 | uint32_t fcl = ((cp_read(sd, 0xb8) & 0x1f) << 8) | cp_read(sd, 0xb9); | ||
| 2229 | char hs_pol = ((cp_read(sd, 0xb5) & 0x10) ? | ||
| 2230 | ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x'); | ||
| 2231 | char vs_pol = ((cp_read(sd, 0xb5) & 0x40) ? | ||
| 2232 | ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x'); | ||
| 2233 | v4l2_info(sd, | ||
| 2234 | "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, fcl = %d, %s, %chsync, %cvsync\n", | ||
| 2235 | lcf, bl, lcvs, fcl, | ||
| 2236 | (cp_read(sd, 0xb1) & 0x40) ? | ||
| 2237 | "interlaced" : "progressive", | ||
| 2238 | hs_pol, vs_pol); | ||
| 2239 | } | ||
| 2240 | if (adv7842_query_dv_timings(sd, &timings)) | ||
| 2241 | v4l2_info(sd, "No video detected\n"); | ||
| 2242 | else | ||
| 2243 | v4l2_print_dv_timings(sd->name, "Detected format: ", | ||
| 2244 | &timings, true); | ||
| 2245 | v4l2_print_dv_timings(sd->name, "Configured format: ", | ||
| 2246 | &state->timings, true); | ||
| 2247 | |||
| 2248 | if (no_cp_signal(sd)) | ||
| 2249 | return 0; | ||
| 2250 | |||
| 2251 | v4l2_info(sd, "-----Color space-----\n"); | ||
| 2252 | v4l2_info(sd, "RGB quantization range ctrl: %s\n", | ||
| 2253 | rgb_quantization_range_txt[state->rgb_quantization_range]); | ||
| 2254 | v4l2_info(sd, "Input color space: %s\n", | ||
| 2255 | input_color_space_txt[reg_io_0x02 >> 4]); | ||
| 2256 | v4l2_info(sd, "Output color space: %s %s, saturator %s\n", | ||
| 2257 | (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", | ||
| 2258 | (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", | ||
| 2259 | ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? | ||
| 2260 | "enabled" : "disabled"); | ||
| 2261 | v4l2_info(sd, "Color space conversion: %s\n", | ||
| 2262 | csc_coeff_sel_rb[cp_read(sd, 0xf4) >> 4]); | ||
| 2263 | |||
| 2264 | if (!is_digital_input(sd)) | ||
| 2265 | return 0; | ||
| 2266 | |||
| 2267 | v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); | ||
| 2268 | v4l2_info(sd, "HDCP encrypted content: %s\n", | ||
| 2269 | (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false"); | ||
| 2270 | v4l2_info(sd, "HDCP keys read: %s%s\n", | ||
| 2271 | (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", | ||
| 2272 | (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); | ||
| 2273 | if (!is_hdmi(sd)) | ||
| 2274 | return 0; | ||
| 2275 | |||
| 2276 | v4l2_info(sd, "Audio: pll %s, samples %s, %s\n", | ||
| 2277 | audio_pll_locked ? "locked" : "not locked", | ||
| 2278 | audio_sample_packet_detect ? "detected" : "not detected", | ||
| 2279 | audio_mute ? "muted" : "enabled"); | ||
| 2280 | if (audio_pll_locked && audio_sample_packet_detect) { | ||
| 2281 | v4l2_info(sd, "Audio format: %s\n", | ||
| 2282 | (hdmi_read(sd, 0x07) & 0x40) ? "multi-channel" : "stereo"); | ||
| 2283 | } | ||
| 2284 | v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) + | ||
| 2285 | (hdmi_read(sd, 0x5c) << 8) + | ||
| 2286 | (hdmi_read(sd, 0x5d) & 0xf0)); | ||
| 2287 | v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) + | ||
| 2288 | (hdmi_read(sd, 0x5e) << 8) + | ||
| 2289 | hdmi_read(sd, 0x5f)); | ||
| 2290 | v4l2_info(sd, "AV Mute: %s\n", | ||
| 2291 | (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off"); | ||
| 2292 | v4l2_info(sd, "Deep color mode: %s\n", | ||
| 2293 | deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]); | ||
| 2294 | |||
| 2295 | print_avi_infoframe(sd); | ||
| 2296 | return 0; | ||
| 2297 | } | ||
| 2298 | |||
| 2299 | static int adv7842_log_status(struct v4l2_subdev *sd) | ||
| 2300 | { | ||
| 2301 | struct adv7842_state *state = to_state(sd); | ||
| 2302 | |||
| 2303 | if (state->mode == ADV7842_MODE_SDP) | ||
| 2304 | return adv7842_sdp_log_status(sd); | ||
| 2305 | return adv7842_cp_log_status(sd); | ||
| 2306 | } | ||
| 2307 | |||
| 2308 | static int adv7842_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) | ||
| 2309 | { | ||
| 2310 | struct adv7842_state *state = to_state(sd); | ||
| 2311 | |||
| 2312 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 2313 | |||
| 2314 | if (state->mode != ADV7842_MODE_SDP) | ||
| 2315 | return -ENODATA; | ||
| 2316 | |||
| 2317 | if (!(sdp_read(sd, 0x5A) & 0x01)) { | ||
| 2318 | *std = 0; | ||
| 2319 | v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); | ||
| 2320 | return 0; | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | switch (sdp_read(sd, 0x52) & 0x0f) { | ||
| 2324 | case 0: | ||
| 2325 | /* NTSC-M/J */ | ||
| 2326 | *std &= V4L2_STD_NTSC; | ||
| 2327 | break; | ||
| 2328 | case 2: | ||
| 2329 | /* NTSC-443 */ | ||
| 2330 | *std &= V4L2_STD_NTSC_443; | ||
| 2331 | break; | ||
| 2332 | case 3: | ||
| 2333 | /* 60HzSECAM */ | ||
| 2334 | *std &= V4L2_STD_SECAM; | ||
| 2335 | break; | ||
| 2336 | case 4: | ||
| 2337 | /* PAL-M */ | ||
| 2338 | *std &= V4L2_STD_PAL_M; | ||
| 2339 | break; | ||
| 2340 | case 6: | ||
| 2341 | /* PAL-60 */ | ||
| 2342 | *std &= V4L2_STD_PAL_60; | ||
| 2343 | break; | ||
| 2344 | case 0xc: | ||
| 2345 | /* PAL-CombN */ | ||
| 2346 | *std &= V4L2_STD_PAL_Nc; | ||
| 2347 | break; | ||
| 2348 | case 0xe: | ||
| 2349 | /* PAL-BGHID */ | ||
| 2350 | *std &= V4L2_STD_PAL; | ||
| 2351 | break; | ||
| 2352 | case 0xf: | ||
| 2353 | /* SECAM */ | ||
| 2354 | *std &= V4L2_STD_SECAM; | ||
| 2355 | break; | ||
| 2356 | default: | ||
| 2357 | *std &= V4L2_STD_ALL; | ||
| 2358 | break; | ||
| 2359 | } | ||
| 2360 | return 0; | ||
| 2361 | } | ||
| 2362 | |||
| 2363 | static int adv7842_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | ||
| 2364 | { | ||
| 2365 | struct adv7842_state *state = to_state(sd); | ||
| 2366 | |||
| 2367 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 2368 | |||
| 2369 | if (state->mode != ADV7842_MODE_SDP) | ||
| 2370 | return -ENODATA; | ||
| 2371 | |||
| 2372 | if (norm & V4L2_STD_ALL) { | ||
| 2373 | state->norm = norm; | ||
| 2374 | return 0; | ||
| 2375 | } | ||
| 2376 | return -EINVAL; | ||
| 2377 | } | ||
| 2378 | |||
| 2379 | static int adv7842_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) | ||
| 2380 | { | ||
| 2381 | struct adv7842_state *state = to_state(sd); | ||
| 2382 | |||
| 2383 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
| 2384 | |||
| 2385 | if (state->mode != ADV7842_MODE_SDP) | ||
| 2386 | return -ENODATA; | ||
| 2387 | |||
| 2388 | *norm = state->norm; | ||
| 2389 | return 0; | ||
| 2390 | } | ||
| 2391 | |||
| 2392 | /* ----------------------------------------------------------------------- */ | ||
| 2393 | |||
| 2394 | static int adv7842_core_init(struct v4l2_subdev *sd, | ||
| 2395 | const struct adv7842_platform_data *pdata) | ||
| 2396 | { | ||
| 2397 | hdmi_write(sd, 0x48, | ||
| 2398 | (pdata->disable_pwrdnb ? 0x80 : 0) | | ||
| 2399 | (pdata->disable_cable_det_rst ? 0x40 : 0)); | ||
| 2400 | |||
| 2401 | disable_input(sd); | ||
| 2402 | |||
| 2403 | /* power */ | ||
| 2404 | io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */ | ||
| 2405 | io_write(sd, 0x15, 0x80); /* Power up pads */ | ||
| 2406 | |||
| 2407 | /* video format */ | ||
| 2408 | io_write(sd, 0x02, | ||
| 2409 | pdata->inp_color_space << 4 | | ||
| 2410 | pdata->alt_gamma << 3 | | ||
| 2411 | pdata->op_656_range << 2 | | ||
| 2412 | pdata->rgb_out << 1 | | ||
| 2413 | pdata->alt_data_sat << 0); | ||
| 2414 | io_write(sd, 0x03, pdata->op_format_sel); | ||
| 2415 | io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5); | ||
| 2416 | io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 | | ||
| 2417 | pdata->insert_av_codes << 2 | | ||
| 2418 | pdata->replicate_av_codes << 1 | | ||
| 2419 | pdata->invert_cbcr << 0); | ||
| 2420 | |||
| 2421 | /* Drive strength */ | ||
| 2422 | io_write_and_or(sd, 0x14, 0xc0, pdata->drive_strength.data<<4 | | ||
| 2423 | pdata->drive_strength.clock<<2 | | ||
| 2424 | pdata->drive_strength.sync); | ||
| 2425 | |||
| 2426 | /* HDMI free run */ | ||
| 2427 | cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); | ||
| 2428 | |||
| 2429 | /* TODO from platform data */ | ||
| 2430 | cp_write(sd, 0x69, 0x14); /* Enable CP CSC */ | ||
| 2431 | io_write(sd, 0x06, 0xa6); /* positive VS and HS and DE */ | ||
| 2432 | cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */ | ||
| 2433 | afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */ | ||
| 2434 | |||
| 2435 | afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ | ||
| 2436 | io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); | ||
| 2437 | |||
| 2438 | sdp_csc_coeff(sd, &pdata->sdp_csc_coeff); | ||
| 2439 | |||
| 2440 | if (pdata->sdp_io_sync.adjust) { | ||
| 2441 | const struct adv7842_sdp_io_sync_adjustment *s = &pdata->sdp_io_sync; | ||
| 2442 | sdp_io_write(sd, 0x94, (s->hs_beg>>8) & 0xf); | ||
| 2443 | sdp_io_write(sd, 0x95, s->hs_beg & 0xff); | ||
| 2444 | sdp_io_write(sd, 0x96, (s->hs_width>>8) & 0xf); | ||
| 2445 | sdp_io_write(sd, 0x97, s->hs_width & 0xff); | ||
| 2446 | sdp_io_write(sd, 0x98, (s->de_beg>>8) & 0xf); | ||
| 2447 | sdp_io_write(sd, 0x99, s->de_beg & 0xff); | ||
| 2448 | sdp_io_write(sd, 0x9a, (s->de_end>>8) & 0xf); | ||
| 2449 | sdp_io_write(sd, 0x9b, s->de_end & 0xff); | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | /* todo, improve settings for sdram */ | ||
| 2453 | if (pdata->sd_ram_size >= 128) { | ||
| 2454 | sdp_write(sd, 0x12, 0x0d); /* Frame TBC,3D comb enabled */ | ||
| 2455 | if (pdata->sd_ram_ddr) { | ||
| 2456 | /* SDP setup for the AD eval board */ | ||
| 2457 | sdp_io_write(sd, 0x6f, 0x00); /* DDR mode */ | ||
| 2458 | sdp_io_write(sd, 0x75, 0x0a); /* 128 MB memory size */ | ||
| 2459 | sdp_io_write(sd, 0x7a, 0xa5); /* Timing Adjustment */ | ||
| 2460 | sdp_io_write(sd, 0x7b, 0x8f); /* Timing Adjustment */ | ||
| 2461 | sdp_io_write(sd, 0x60, 0x01); /* SDRAM reset */ | ||
| 2462 | } else { | ||
| 2463 | sdp_io_write(sd, 0x75, 0x0a); /* 64 MB memory size ?*/ | ||
| 2464 | sdp_io_write(sd, 0x74, 0x00); /* must be zero for sdr sdram */ | ||
| 2465 | sdp_io_write(sd, 0x79, 0x33); /* CAS latency to 3, | ||
| 2466 | depends on memory */ | ||
| 2467 | sdp_io_write(sd, 0x6f, 0x01); /* SDR mode */ | ||
| 2468 | sdp_io_write(sd, 0x7a, 0xa5); /* Timing Adjustment */ | ||
| 2469 | sdp_io_write(sd, 0x7b, 0x8f); /* Timing Adjustment */ | ||
| 2470 | sdp_io_write(sd, 0x60, 0x01); /* SDRAM reset */ | ||
| 2471 | } | ||
| 2472 | } else { | ||
| 2473 | /* | ||
| 2474 | * Manual UG-214, rev 0 is bit confusing on this bit | ||
| 2475 | * but a '1' disables any signal if the Ram is active. | ||
| 2476 | */ | ||
| 2477 | sdp_io_write(sd, 0x29, 0x10); /* Tristate memory interface */ | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | select_input(sd, pdata->vid_std_select); | ||
| 2481 | |||
| 2482 | enable_input(sd); | ||
| 2483 | |||
| 2484 | /* disable I2C access to internal EDID ram from HDMI DDC ports */ | ||
| 2485 | rep_write_and_or(sd, 0x77, 0xf3, 0x00); | ||
| 2486 | |||
| 2487 | hdmi_write(sd, 0x69, 0xa3); /* HPA manual */ | ||
| 2488 | /* HPA disable on port A and B */ | ||
| 2489 | io_write_and_or(sd, 0x20, 0xcf, 0x00); | ||
| 2490 | |||
| 2491 | /* LLC */ | ||
| 2492 | /* Set phase to 16. TODO: get this from platform_data */ | ||
| 2493 | io_write(sd, 0x19, 0x90); | ||
| 2494 | io_write(sd, 0x33, 0x40); | ||
| 2495 | |||
| 2496 | /* interrupts */ | ||
| 2497 | io_write(sd, 0x40, 0xe2); /* Configure INT1 */ | ||
| 2498 | |||
| 2499 | adv7842_irq_enable(sd, true); | ||
| 2500 | |||
| 2501 | return v4l2_ctrl_handler_setup(sd->ctrl_handler); | ||
| 2502 | } | ||
| 2503 | |||
| 2504 | /* ----------------------------------------------------------------------- */ | ||
| 2505 | |||
| 2506 | static int adv7842_ddr_ram_test(struct v4l2_subdev *sd) | ||
| 2507 | { | ||
| 2508 | /* | ||
| 2509 | * From ADV784x external Memory test.pdf | ||
| 2510 | * | ||
| 2511 | * Reset must just been performed before running test. | ||
| 2512 | * Recommended to reset after test. | ||
| 2513 | */ | ||
| 2514 | int i; | ||
| 2515 | int pass = 0; | ||
| 2516 | int fail = 0; | ||
| 2517 | int complete = 0; | ||
| 2518 | |||
| 2519 | io_write(sd, 0x00, 0x01); /* Program SDP 4x1 */ | ||
| 2520 | io_write(sd, 0x01, 0x00); /* Program SDP mode */ | ||
| 2521 | afe_write(sd, 0x80, 0x92); /* SDP Recommeneded Write */ | ||
| 2522 | afe_write(sd, 0x9B, 0x01); /* SDP Recommeneded Write ADV7844ES1 */ | ||
| 2523 | afe_write(sd, 0x9C, 0x60); /* SDP Recommeneded Write ADV7844ES1 */ | ||
| 2524 | afe_write(sd, 0x9E, 0x02); /* SDP Recommeneded Write ADV7844ES1 */ | ||
| 2525 | afe_write(sd, 0xA0, 0x0B); /* SDP Recommeneded Write ADV7844ES1 */ | ||
| 2526 | afe_write(sd, 0xC3, 0x02); /* Memory BIST Initialisation */ | ||
| 2527 | io_write(sd, 0x0C, 0x40); /* Power up ADV7844 */ | ||
| 2528 | io_write(sd, 0x15, 0xBA); /* Enable outputs */ | ||
| 2529 | sdp_write(sd, 0x12, 0x00); /* Disable 3D comb, Frame TBC & 3DNR */ | ||
| 2530 | io_write(sd, 0xFF, 0x04); /* Reset memory controller */ | ||
| 2531 | |||
| 2532 | mdelay(5); | ||
| 2533 | |||
| 2534 | sdp_write(sd, 0x12, 0x00); /* Disable 3D Comb, Frame TBC & 3DNR */ | ||
| 2535 | sdp_io_write(sd, 0x2A, 0x01); /* Memory BIST Initialisation */ | ||
| 2536 | sdp_io_write(sd, 0x7c, 0x19); /* Memory BIST Initialisation */ | ||
| 2537 | sdp_io_write(sd, 0x80, 0x87); /* Memory BIST Initialisation */ | ||
| 2538 | sdp_io_write(sd, 0x81, 0x4a); /* Memory BIST Initialisation */ | ||
| 2539 | sdp_io_write(sd, 0x82, 0x2c); /* Memory BIST Initialisation */ | ||
| 2540 | sdp_io_write(sd, 0x83, 0x0e); /* Memory BIST Initialisation */ | ||
| 2541 | sdp_io_write(sd, 0x84, 0x94); /* Memory BIST Initialisation */ | ||
| 2542 | sdp_io_write(sd, 0x85, 0x62); /* Memory BIST Initialisation */ | ||
| 2543 | sdp_io_write(sd, 0x7d, 0x00); /* Memory BIST Initialisation */ | ||
| 2544 | sdp_io_write(sd, 0x7e, 0x1a); /* Memory BIST Initialisation */ | ||
| 2545 | |||
| 2546 | mdelay(5); | ||
| 2547 | |||
| 2548 | sdp_io_write(sd, 0xd9, 0xd5); /* Enable BIST Test */ | ||
| 2549 | sdp_write(sd, 0x12, 0x05); /* Enable FRAME TBC & 3D COMB */ | ||
| 2550 | |||
| 2551 | mdelay(20); | ||
| 2552 | |||
| 2553 | for (i = 0; i < 10; i++) { | ||
| 2554 | u8 result = sdp_io_read(sd, 0xdb); | ||
| 2555 | if (result & 0x10) { | ||
| 2556 | complete++; | ||
| 2557 | if (result & 0x20) | ||
| 2558 | fail++; | ||
| 2559 | else | ||
| 2560 | pass++; | ||
| 2561 | } | ||
| 2562 | mdelay(20); | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | v4l2_dbg(1, debug, sd, | ||
| 2566 | "Ram Test: completed %d of %d: pass %d, fail %d\n", | ||
| 2567 | complete, i, pass, fail); | ||
| 2568 | |||
| 2569 | if (!complete || fail) | ||
| 2570 | return -EIO; | ||
| 2571 | return 0; | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | static void adv7842_rewrite_i2c_addresses(struct v4l2_subdev *sd, | ||
| 2575 | struct adv7842_platform_data *pdata) | ||
| 2576 | { | ||
| 2577 | io_write(sd, 0xf1, pdata->i2c_sdp << 1); | ||
| 2578 | io_write(sd, 0xf2, pdata->i2c_sdp_io << 1); | ||
| 2579 | io_write(sd, 0xf3, pdata->i2c_avlink << 1); | ||
| 2580 | io_write(sd, 0xf4, pdata->i2c_cec << 1); | ||
| 2581 | io_write(sd, 0xf5, pdata->i2c_infoframe << 1); | ||
| 2582 | |||
| 2583 | io_write(sd, 0xf8, pdata->i2c_afe << 1); | ||
| 2584 | io_write(sd, 0xf9, pdata->i2c_repeater << 1); | ||
| 2585 | io_write(sd, 0xfa, pdata->i2c_edid << 1); | ||
| 2586 | io_write(sd, 0xfb, pdata->i2c_hdmi << 1); | ||
| 2587 | |||
| 2588 | io_write(sd, 0xfd, pdata->i2c_cp << 1); | ||
| 2589 | io_write(sd, 0xfe, pdata->i2c_vdp << 1); | ||
| 2590 | } | ||
| 2591 | |||
| 2592 | static int adv7842_command_ram_test(struct v4l2_subdev *sd) | ||
| 2593 | { | ||
| 2594 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 2595 | struct adv7842_state *state = to_state(sd); | ||
| 2596 | struct adv7842_platform_data *pdata = client->dev.platform_data; | ||
| 2597 | int ret = 0; | ||
| 2598 | |||
| 2599 | if (!pdata) | ||
| 2600 | return -ENODEV; | ||
| 2601 | |||
| 2602 | if (!pdata->sd_ram_size || !pdata->sd_ram_ddr) { | ||
| 2603 | v4l2_info(sd, "no sdram or no ddr sdram\n"); | ||
| 2604 | return -EINVAL; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | main_reset(sd); | ||
| 2608 | |||
| 2609 | adv7842_rewrite_i2c_addresses(sd, pdata); | ||
| 2610 | |||
| 2611 | /* run ram test */ | ||
| 2612 | ret = adv7842_ddr_ram_test(sd); | ||
| 2613 | |||
| 2614 | main_reset(sd); | ||
| 2615 | |||
| 2616 | adv7842_rewrite_i2c_addresses(sd, pdata); | ||
| 2617 | |||
| 2618 | /* and re-init chip and state */ | ||
| 2619 | adv7842_core_init(sd, pdata); | ||
| 2620 | |||
| 2621 | disable_input(sd); | ||
| 2622 | |||
| 2623 | select_input(sd, state->vid_std_select); | ||
| 2624 | |||
| 2625 | enable_input(sd); | ||
| 2626 | |||
| 2627 | adv7842_s_dv_timings(sd, &state->timings); | ||
| 2628 | |||
| 2629 | edid_write_vga_segment(sd); | ||
| 2630 | edid_write_hdmi_segment(sd, 0); | ||
| 2631 | edid_write_hdmi_segment(sd, 1); | ||
| 2632 | |||
| 2633 | return ret; | ||
| 2634 | } | ||
| 2635 | |||
| 2636 | static long adv7842_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | ||
| 2637 | { | ||
| 2638 | switch (cmd) { | ||
| 2639 | case ADV7842_CMD_RAM_TEST: | ||
| 2640 | return adv7842_command_ram_test(sd); | ||
| 2641 | } | ||
| 2642 | return -ENOTTY; | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | /* ----------------------------------------------------------------------- */ | ||
| 2646 | |||
| 2647 | static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { | ||
| 2648 | .s_ctrl = adv7842_s_ctrl, | ||
| 2649 | }; | ||
| 2650 | |||
| 2651 | static const struct v4l2_subdev_core_ops adv7842_core_ops = { | ||
| 2652 | .log_status = adv7842_log_status, | ||
| 2653 | .g_std = adv7842_g_std, | ||
| 2654 | .s_std = adv7842_s_std, | ||
| 2655 | .ioctl = adv7842_ioctl, | ||
| 2656 | .interrupt_service_routine = adv7842_isr, | ||
| 2657 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 2658 | .g_register = adv7842_g_register, | ||
| 2659 | .s_register = adv7842_s_register, | ||
| 2660 | #endif | ||
| 2661 | }; | ||
| 2662 | |||
| 2663 | static const struct v4l2_subdev_video_ops adv7842_video_ops = { | ||
| 2664 | .s_routing = adv7842_s_routing, | ||
| 2665 | .querystd = adv7842_querystd, | ||
| 2666 | .g_input_status = adv7842_g_input_status, | ||
| 2667 | .s_dv_timings = adv7842_s_dv_timings, | ||
| 2668 | .g_dv_timings = adv7842_g_dv_timings, | ||
| 2669 | .query_dv_timings = adv7842_query_dv_timings, | ||
| 2670 | .enum_dv_timings = adv7842_enum_dv_timings, | ||
| 2671 | .dv_timings_cap = adv7842_dv_timings_cap, | ||
| 2672 | .enum_mbus_fmt = adv7842_enum_mbus_fmt, | ||
| 2673 | .g_mbus_fmt = adv7842_g_mbus_fmt, | ||
| 2674 | .try_mbus_fmt = adv7842_g_mbus_fmt, | ||
| 2675 | .s_mbus_fmt = adv7842_g_mbus_fmt, | ||
| 2676 | }; | ||
| 2677 | |||
| 2678 | static const struct v4l2_subdev_pad_ops adv7842_pad_ops = { | ||
| 2679 | .set_edid = adv7842_set_edid, | ||
| 2680 | }; | ||
| 2681 | |||
| 2682 | static const struct v4l2_subdev_ops adv7842_ops = { | ||
| 2683 | .core = &adv7842_core_ops, | ||
| 2684 | .video = &adv7842_video_ops, | ||
| 2685 | .pad = &adv7842_pad_ops, | ||
| 2686 | }; | ||
| 2687 | |||
| 2688 | /* -------------------------- custom ctrls ---------------------------------- */ | ||
| 2689 | |||
| 2690 | static const struct v4l2_ctrl_config adv7842_ctrl_analog_sampling_phase = { | ||
| 2691 | .ops = &adv7842_ctrl_ops, | ||
| 2692 | .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE, | ||
| 2693 | .name = "Analog Sampling Phase", | ||
| 2694 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 2695 | .min = 0, | ||
| 2696 | .max = 0x1f, | ||
| 2697 | .step = 1, | ||
| 2698 | .def = 0, | ||
| 2699 | }; | ||
| 2700 | |||
| 2701 | static const struct v4l2_ctrl_config adv7842_ctrl_free_run_color_manual = { | ||
| 2702 | .ops = &adv7842_ctrl_ops, | ||
| 2703 | .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL, | ||
| 2704 | .name = "Free Running Color, Manual", | ||
| 2705 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 2706 | .max = 1, | ||
| 2707 | .step = 1, | ||
| 2708 | .def = 1, | ||
| 2709 | }; | ||
| 2710 | |||
| 2711 | static const struct v4l2_ctrl_config adv7842_ctrl_free_run_color = { | ||
| 2712 | .ops = &adv7842_ctrl_ops, | ||
| 2713 | .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR, | ||
| 2714 | .name = "Free Running Color", | ||
| 2715 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 2716 | .max = 0xffffff, | ||
| 2717 | .step = 0x1, | ||
| 2718 | }; | ||
| 2719 | |||
| 2720 | |||
| 2721 | static void adv7842_unregister_clients(struct adv7842_state *state) | ||
| 2722 | { | ||
| 2723 | if (state->i2c_avlink) | ||
| 2724 | i2c_unregister_device(state->i2c_avlink); | ||
| 2725 | if (state->i2c_cec) | ||
| 2726 | i2c_unregister_device(state->i2c_cec); | ||
| 2727 | if (state->i2c_infoframe) | ||
| 2728 | i2c_unregister_device(state->i2c_infoframe); | ||
| 2729 | if (state->i2c_sdp_io) | ||
| 2730 | i2c_unregister_device(state->i2c_sdp_io); | ||
| 2731 | if (state->i2c_sdp) | ||
| 2732 | i2c_unregister_device(state->i2c_sdp); | ||
| 2733 | if (state->i2c_afe) | ||
| 2734 | i2c_unregister_device(state->i2c_afe); | ||
| 2735 | if (state->i2c_repeater) | ||
| 2736 | i2c_unregister_device(state->i2c_repeater); | ||
| 2737 | if (state->i2c_edid) | ||
| 2738 | i2c_unregister_device(state->i2c_edid); | ||
| 2739 | if (state->i2c_hdmi) | ||
| 2740 | i2c_unregister_device(state->i2c_hdmi); | ||
| 2741 | if (state->i2c_cp) | ||
| 2742 | i2c_unregister_device(state->i2c_cp); | ||
| 2743 | if (state->i2c_vdp) | ||
| 2744 | i2c_unregister_device(state->i2c_vdp); | ||
| 2745 | } | ||
| 2746 | |||
| 2747 | static struct i2c_client *adv7842_dummy_client(struct v4l2_subdev *sd, | ||
| 2748 | u8 addr, u8 io_reg) | ||
| 2749 | { | ||
| 2750 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 2751 | |||
| 2752 | io_write(sd, io_reg, addr << 1); | ||
| 2753 | return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | static int adv7842_probe(struct i2c_client *client, | ||
| 2757 | const struct i2c_device_id *id) | ||
| 2758 | { | ||
| 2759 | struct adv7842_state *state; | ||
| 2760 | struct adv7842_platform_data *pdata = client->dev.platform_data; | ||
| 2761 | struct v4l2_ctrl_handler *hdl; | ||
| 2762 | struct v4l2_subdev *sd; | ||
| 2763 | u16 rev; | ||
| 2764 | int err; | ||
| 2765 | |||
| 2766 | /* Check if the adapter supports the needed features */ | ||
| 2767 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 2768 | return -EIO; | ||
| 2769 | |||
| 2770 | v4l_dbg(1, debug, client, "detecting adv7842 client on address 0x%x\n", | ||
| 2771 | client->addr << 1); | ||
| 2772 | |||
| 2773 | if (!pdata) { | ||
| 2774 | v4l_err(client, "No platform data!\n"); | ||
| 2775 | return -ENODEV; | ||
| 2776 | } | ||
| 2777 | |||
| 2778 | state = devm_kzalloc(&client->dev, sizeof(struct adv7842_state), GFP_KERNEL); | ||
| 2779 | if (!state) { | ||
| 2780 | v4l_err(client, "Could not allocate adv7842_state memory!\n"); | ||
| 2781 | return -ENOMEM; | ||
| 2782 | } | ||
| 2783 | |||
| 2784 | sd = &state->sd; | ||
| 2785 | v4l2_i2c_subdev_init(sd, client, &adv7842_ops); | ||
| 2786 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 2787 | state->connector_hdmi = pdata->connector_hdmi; | ||
| 2788 | state->mode = pdata->mode; | ||
| 2789 | |||
| 2790 | state->hdmi_port_a = true; | ||
| 2791 | |||
| 2792 | /* i2c access to adv7842? */ | ||
| 2793 | rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 | | ||
| 2794 | adv_smbus_read_byte_data_check(client, 0xeb, false); | ||
| 2795 | if (rev != 0x2012) { | ||
| 2796 | v4l2_info(sd, "got rev=0x%04x on first read attempt\n", rev); | ||
| 2797 | rev = adv_smbus_read_byte_data_check(client, 0xea, false) << 8 | | ||
| 2798 | adv_smbus_read_byte_data_check(client, 0xeb, false); | ||
| 2799 | } | ||
| 2800 | if (rev != 0x2012) { | ||
| 2801 | v4l2_info(sd, "not an adv7842 on address 0x%x (rev=0x%04x)\n", | ||
| 2802 | client->addr << 1, rev); | ||
| 2803 | return -ENODEV; | ||
| 2804 | } | ||
| 2805 | |||
| 2806 | if (pdata->chip_reset) | ||
| 2807 | main_reset(sd); | ||
| 2808 | |||
| 2809 | /* control handlers */ | ||
| 2810 | hdl = &state->hdl; | ||
| 2811 | v4l2_ctrl_handler_init(hdl, 6); | ||
| 2812 | |||
| 2813 | /* add in ascending ID order */ | ||
| 2814 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
| 2815 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); | ||
| 2816 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
| 2817 | V4L2_CID_CONTRAST, 0, 255, 1, 128); | ||
| 2818 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
| 2819 | V4L2_CID_SATURATION, 0, 255, 1, 128); | ||
| 2820 | v4l2_ctrl_new_std(hdl, &adv7842_ctrl_ops, | ||
| 2821 | V4L2_CID_HUE, 0, 128, 1, 0); | ||
| 2822 | |||
| 2823 | /* custom controls */ | ||
| 2824 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
| 2825 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 3, 0, 0); | ||
| 2826 | state->analog_sampling_phase_ctrl = v4l2_ctrl_new_custom(hdl, | ||
| 2827 | &adv7842_ctrl_analog_sampling_phase, NULL); | ||
| 2828 | state->free_run_color_ctrl_manual = v4l2_ctrl_new_custom(hdl, | ||
| 2829 | &adv7842_ctrl_free_run_color_manual, NULL); | ||
| 2830 | state->free_run_color_ctrl = v4l2_ctrl_new_custom(hdl, | ||
| 2831 | &adv7842_ctrl_free_run_color, NULL); | ||
| 2832 | state->rgb_quantization_range_ctrl = | ||
| 2833 | v4l2_ctrl_new_std_menu(hdl, &adv7842_ctrl_ops, | ||
| 2834 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | ||
| 2835 | 0, V4L2_DV_RGB_RANGE_AUTO); | ||
| 2836 | sd->ctrl_handler = hdl; | ||
| 2837 | if (hdl->error) { | ||
| 2838 | err = hdl->error; | ||
| 2839 | goto err_hdl; | ||
| 2840 | } | ||
| 2841 | state->detect_tx_5v_ctrl->is_private = true; | ||
| 2842 | state->rgb_quantization_range_ctrl->is_private = true; | ||
| 2843 | state->analog_sampling_phase_ctrl->is_private = true; | ||
| 2844 | state->free_run_color_ctrl_manual->is_private = true; | ||
| 2845 | state->free_run_color_ctrl->is_private = true; | ||
| 2846 | |||
| 2847 | if (adv7842_s_detect_tx_5v_ctrl(sd)) { | ||
| 2848 | err = -ENODEV; | ||
| 2849 | goto err_hdl; | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | state->i2c_avlink = adv7842_dummy_client(sd, pdata->i2c_avlink, 0xf3); | ||
| 2853 | state->i2c_cec = adv7842_dummy_client(sd, pdata->i2c_cec, 0xf4); | ||
| 2854 | state->i2c_infoframe = adv7842_dummy_client(sd, pdata->i2c_infoframe, 0xf5); | ||
| 2855 | state->i2c_sdp_io = adv7842_dummy_client(sd, pdata->i2c_sdp_io, 0xf2); | ||
| 2856 | state->i2c_sdp = adv7842_dummy_client(sd, pdata->i2c_sdp, 0xf1); | ||
| 2857 | state->i2c_afe = adv7842_dummy_client(sd, pdata->i2c_afe, 0xf8); | ||
| 2858 | state->i2c_repeater = adv7842_dummy_client(sd, pdata->i2c_repeater, 0xf9); | ||
| 2859 | state->i2c_edid = adv7842_dummy_client(sd, pdata->i2c_edid, 0xfa); | ||
| 2860 | state->i2c_hdmi = adv7842_dummy_client(sd, pdata->i2c_hdmi, 0xfb); | ||
| 2861 | state->i2c_cp = adv7842_dummy_client(sd, pdata->i2c_cp, 0xfd); | ||
| 2862 | state->i2c_vdp = adv7842_dummy_client(sd, pdata->i2c_vdp, 0xfe); | ||
| 2863 | if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe || | ||
| 2864 | !state->i2c_sdp_io || !state->i2c_sdp || !state->i2c_afe || | ||
| 2865 | !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || | ||
| 2866 | !state->i2c_cp || !state->i2c_vdp) { | ||
| 2867 | err = -ENOMEM; | ||
| 2868 | v4l2_err(sd, "failed to create all i2c clients\n"); | ||
| 2869 | goto err_i2c; | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | /* work queues */ | ||
| 2873 | state->work_queues = create_singlethread_workqueue(client->name); | ||
| 2874 | if (!state->work_queues) { | ||
| 2875 | v4l2_err(sd, "Could not create work queue\n"); | ||
| 2876 | err = -ENOMEM; | ||
| 2877 | goto err_i2c; | ||
| 2878 | } | ||
| 2879 | |||
| 2880 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, | ||
| 2881 | adv7842_delayed_work_enable_hotplug); | ||
| 2882 | |||
| 2883 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
| 2884 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | ||
| 2885 | if (err) | ||
| 2886 | goto err_work_queues; | ||
| 2887 | |||
| 2888 | err = adv7842_core_init(sd, pdata); | ||
| 2889 | if (err) | ||
| 2890 | goto err_entity; | ||
| 2891 | |||
| 2892 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | ||
| 2893 | client->addr << 1, client->adapter->name); | ||
| 2894 | return 0; | ||
| 2895 | |||
| 2896 | err_entity: | ||
| 2897 | media_entity_cleanup(&sd->entity); | ||
| 2898 | err_work_queues: | ||
| 2899 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
| 2900 | destroy_workqueue(state->work_queues); | ||
| 2901 | err_i2c: | ||
| 2902 | adv7842_unregister_clients(state); | ||
| 2903 | err_hdl: | ||
| 2904 | v4l2_ctrl_handler_free(hdl); | ||
| 2905 | return err; | ||
| 2906 | } | ||
| 2907 | |||
| 2908 | /* ----------------------------------------------------------------------- */ | ||
| 2909 | |||
| 2910 | static int adv7842_remove(struct i2c_client *client) | ||
| 2911 | { | ||
| 2912 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 2913 | struct adv7842_state *state = to_state(sd); | ||
| 2914 | |||
| 2915 | adv7842_irq_enable(sd, false); | ||
| 2916 | |||
| 2917 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
| 2918 | destroy_workqueue(state->work_queues); | ||
| 2919 | v4l2_device_unregister_subdev(sd); | ||
| 2920 | media_entity_cleanup(&sd->entity); | ||
| 2921 | adv7842_unregister_clients(to_state(sd)); | ||
| 2922 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
| 2923 | return 0; | ||
| 2924 | } | ||
| 2925 | |||
| 2926 | /* ----------------------------------------------------------------------- */ | ||
| 2927 | |||
| 2928 | static struct i2c_device_id adv7842_id[] = { | ||
| 2929 | { "adv7842", 0 }, | ||
| 2930 | { } | ||
| 2931 | }; | ||
| 2932 | MODULE_DEVICE_TABLE(i2c, adv7842_id); | ||
| 2933 | |||
| 2934 | /* ----------------------------------------------------------------------- */ | ||
| 2935 | |||
| 2936 | static struct i2c_driver adv7842_driver = { | ||
| 2937 | .driver = { | ||
| 2938 | .owner = THIS_MODULE, | ||
| 2939 | .name = "adv7842", | ||
| 2940 | }, | ||
| 2941 | .probe = adv7842_probe, | ||
| 2942 | .remove = adv7842_remove, | ||
| 2943 | .id_table = adv7842_id, | ||
| 2944 | }; | ||
| 2945 | |||
| 2946 | module_i2c_driver(adv7842_driver); | ||
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index a9857022f71d..a9110d8bbbcd 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c | |||
| @@ -209,7 +209,8 @@ static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd, | |||
| 209 | 209 | ||
| 210 | fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; | 210 | fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; |
| 211 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | 211 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 212 | fmt->field = V4L2_FIELD_INTERLACED; | 212 | /* The top field is always transferred first by the chip */ |
| 213 | fmt->field = V4L2_FIELD_INTERLACED_TB; | ||
| 213 | fmt->width = 720; | 214 | fmt->width = 720; |
| 214 | fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; | 215 | fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; |
| 215 | 216 | ||
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 60c6f6739560..2c50effaa334 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/clk.h> | ||
| 15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 16 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
| 17 | #include <linux/log2.h> | 18 | #include <linux/log2.h> |
| @@ -135,6 +136,8 @@ struct mt9v032 { | |||
| 135 | struct mutex power_lock; | 136 | struct mutex power_lock; |
| 136 | int power_count; | 137 | int power_count; |
| 137 | 138 | ||
| 139 | struct clk *clk; | ||
| 140 | |||
| 138 | struct mt9v032_platform_data *pdata; | 141 | struct mt9v032_platform_data *pdata; |
| 139 | 142 | ||
| 140 | u32 sysclk; | 143 | u32 sysclk; |
| @@ -219,10 +222,9 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) | |||
| 219 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); | 222 | struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); |
| 220 | int ret; | 223 | int ret; |
| 221 | 224 | ||
| 222 | if (mt9v032->pdata->set_clock) { | 225 | clk_set_rate(mt9v032->clk, mt9v032->sysclk); |
| 223 | mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk); | 226 | clk_prepare_enable(mt9v032->clk); |
| 224 | udelay(1); | 227 | udelay(1); |
| 225 | } | ||
| 226 | 228 | ||
| 227 | /* Reset the chip and stop data read out */ | 229 | /* Reset the chip and stop data read out */ |
| 228 | ret = mt9v032_write(client, MT9V032_RESET, 1); | 230 | ret = mt9v032_write(client, MT9V032_RESET, 1); |
| @@ -238,8 +240,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) | |||
| 238 | 240 | ||
| 239 | static void mt9v032_power_off(struct mt9v032 *mt9v032) | 241 | static void mt9v032_power_off(struct mt9v032 *mt9v032) |
| 240 | { | 242 | { |
| 241 | if (mt9v032->pdata->set_clock) | 243 | clk_disable_unprepare(mt9v032->clk); |
| 242 | mt9v032->pdata->set_clock(&mt9v032->subdev, 0); | ||
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) | 246 | static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) |
| @@ -748,6 +749,10 @@ static int mt9v032_probe(struct i2c_client *client, | |||
| 748 | if (!mt9v032) | 749 | if (!mt9v032) |
| 749 | return -ENOMEM; | 750 | return -ENOMEM; |
| 750 | 751 | ||
| 752 | mt9v032->clk = devm_clk_get(&client->dev, NULL); | ||
| 753 | if (IS_ERR(mt9v032->clk)) | ||
| 754 | return PTR_ERR(mt9v032->clk); | ||
| 755 | |||
| 751 | mutex_init(&mt9v032->power_lock); | 756 | mutex_init(&mt9v032->power_lock); |
| 752 | mt9v032->pdata = pdata; | 757 | mt9v032->pdata = pdata; |
| 753 | 758 | ||
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 1dbb8118a285..4da90c621f7e 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c | |||
| @@ -1083,7 +1083,7 @@ static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd, | |||
| 1083 | { | 1083 | { |
| 1084 | int i = ARRAY_SIZE(ov965x_formats); | 1084 | int i = ARRAY_SIZE(ov965x_formats); |
| 1085 | 1085 | ||
| 1086 | if (fse->index > ARRAY_SIZE(ov965x_framesizes)) | 1086 | if (fse->index >= ARRAY_SIZE(ov965x_framesizes)) |
| 1087 | return -EINVAL; | 1087 | return -EINVAL; |
| 1088 | 1088 | ||
| 1089 | while (--i) | 1089 | while (--i) |
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 825ea86d982d..b76ec0e7e685 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c | |||
| @@ -1111,6 +1111,11 @@ static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd, | |||
| 1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1112 | mf = v4l2_subdev_get_try_format(fh, fmt->pad); | 1112 | mf = v4l2_subdev_get_try_format(fh, fmt->pad); |
| 1113 | *mf = fmt->format; | 1113 | *mf = fmt->format; |
| 1114 | if (fmt->pad == OIF_ISP_PAD) { | ||
| 1115 | mf = v4l2_subdev_get_try_format(fh, OIF_SOURCE_PAD); | ||
| 1116 | mf->width = fmt->format.width; | ||
| 1117 | mf->height = fmt->format.height; | ||
| 1118 | } | ||
| 1114 | } else { | 1119 | } else { |
| 1115 | switch (fmt->pad) { | 1120 | switch (fmt->pad) { |
| 1116 | case OIF_ISP_PAD: | 1121 | case OIF_ISP_PAD: |
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 789c02a6ca1a..629a5cdadd3a 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c | |||
| @@ -1003,7 +1003,7 @@ static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd, | |||
| 1003 | const struct s5k6aa_interval *fi; | 1003 | const struct s5k6aa_interval *fi; |
| 1004 | int ret = 0; | 1004 | int ret = 0; |
| 1005 | 1005 | ||
| 1006 | if (fie->index > ARRAY_SIZE(s5k6aa_intervals)) | 1006 | if (fie->index >= ARRAY_SIZE(s5k6aa_intervals)) |
| 1007 | return -EINVAL; | 1007 | return -EINVAL; |
| 1008 | 1008 | ||
| 1009 | v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN, | 1009 | v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN, |
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 7fd766ec64c8..637d02634527 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c | |||
| @@ -225,19 +225,63 @@ static const unsigned char saa7111_init[] = { | |||
| 225 | 0x00, 0x00 | 225 | 0x00, 0x00 |
| 226 | }; | 226 | }; |
| 227 | 227 | ||
| 228 | /* SAA7113/GM7113C init codes | 228 | /* |
| 229 | * It's important that R_14... R_17 == 0x00 | 229 | * This table has one illegal value, and some values that are not |
| 230 | * for the gm7113c chip to deliver stable video | 230 | * correct according to the datasheet initialization table. |
| 231 | * | ||
| 232 | * If you need a table with legal/default values tell the driver in | ||
| 233 | * i2c_board_info.platform_data, and you will get the gm7113c_init | ||
| 234 | * table instead. | ||
| 231 | */ | 235 | */ |
| 236 | |||
| 237 | /* SAA7113 Init codes */ | ||
| 232 | static const unsigned char saa7113_init[] = { | 238 | static const unsigned char saa7113_init[] = { |
| 233 | R_01_INC_DELAY, 0x08, | 239 | R_01_INC_DELAY, 0x08, |
| 234 | R_02_INPUT_CNTL_1, 0xc2, | 240 | R_02_INPUT_CNTL_1, 0xc2, |
| 235 | R_03_INPUT_CNTL_2, 0x30, | 241 | R_03_INPUT_CNTL_2, 0x30, |
| 236 | R_04_INPUT_CNTL_3, 0x00, | 242 | R_04_INPUT_CNTL_3, 0x00, |
| 237 | R_05_INPUT_CNTL_4, 0x00, | 243 | R_05_INPUT_CNTL_4, 0x00, |
| 238 | R_06_H_SYNC_START, 0x89, | 244 | R_06_H_SYNC_START, 0x89, /* Illegal value -119, |
| 245 | * min. value = -108 (0x94) */ | ||
| 246 | R_07_H_SYNC_STOP, 0x0d, | ||
| 247 | R_08_SYNC_CNTL, 0x88, /* Not datasheet default. | ||
| 248 | * HTC = VTR mode, should be 0x98 */ | ||
| 249 | R_09_LUMA_CNTL, 0x01, | ||
| 250 | R_0A_LUMA_BRIGHT_CNTL, 0x80, | ||
| 251 | R_0B_LUMA_CONTRAST_CNTL, 0x47, | ||
| 252 | R_0C_CHROMA_SAT_CNTL, 0x40, | ||
| 253 | R_0D_CHROMA_HUE_CNTL, 0x00, | ||
| 254 | R_0E_CHROMA_CNTL_1, 0x01, | ||
| 255 | R_0F_CHROMA_GAIN_CNTL, 0x2a, | ||
| 256 | R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default. | ||
| 257 | * VRLN enabled, should be 0x00 */ | ||
| 258 | R_11_MODE_DELAY_CNTL, 0x0c, | ||
| 259 | R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default, | ||
| 260 | * should be 0x01 */ | ||
| 261 | R_13_RT_X_PORT_OUT_CNTL, 0x00, | ||
| 262 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, | ||
| 263 | R_15_VGATE_START_FID_CHG, 0x00, | ||
| 264 | R_16_VGATE_STOP, 0x00, | ||
| 265 | R_17_MISC_VGATE_CONF_AND_MSB, 0x00, | ||
| 266 | |||
| 267 | 0x00, 0x00 | ||
| 268 | }; | ||
| 269 | |||
| 270 | /* | ||
| 271 | * GM7113C is a clone of the SAA7113 chip | ||
| 272 | * This init table is copied out of the saa7113 datasheet. | ||
| 273 | * In R_08 we enable "Automatic Field Detection" [AUFD], | ||
| 274 | * this is disabled when saa711x_set_v4lstd is called. | ||
| 275 | */ | ||
| 276 | static const unsigned char gm7113c_init[] = { | ||
| 277 | R_01_INC_DELAY, 0x08, | ||
| 278 | R_02_INPUT_CNTL_1, 0xc0, | ||
| 279 | R_03_INPUT_CNTL_2, 0x33, | ||
| 280 | R_04_INPUT_CNTL_3, 0x00, | ||
| 281 | R_05_INPUT_CNTL_4, 0x00, | ||
| 282 | R_06_H_SYNC_START, 0xe9, | ||
| 239 | R_07_H_SYNC_STOP, 0x0d, | 283 | R_07_H_SYNC_STOP, 0x0d, |
| 240 | R_08_SYNC_CNTL, 0x88, | 284 | R_08_SYNC_CNTL, 0x98, |
| 241 | R_09_LUMA_CNTL, 0x01, | 285 | R_09_LUMA_CNTL, 0x01, |
| 242 | R_0A_LUMA_BRIGHT_CNTL, 0x80, | 286 | R_0A_LUMA_BRIGHT_CNTL, 0x80, |
| 243 | R_0B_LUMA_CONTRAST_CNTL, 0x47, | 287 | R_0B_LUMA_CONTRAST_CNTL, 0x47, |
| @@ -245,9 +289,9 @@ static const unsigned char saa7113_init[] = { | |||
| 245 | R_0D_CHROMA_HUE_CNTL, 0x00, | 289 | R_0D_CHROMA_HUE_CNTL, 0x00, |
| 246 | R_0E_CHROMA_CNTL_1, 0x01, | 290 | R_0E_CHROMA_CNTL_1, 0x01, |
| 247 | R_0F_CHROMA_GAIN_CNTL, 0x2a, | 291 | R_0F_CHROMA_GAIN_CNTL, 0x2a, |
| 248 | R_10_CHROMA_CNTL_2, 0x08, | 292 | R_10_CHROMA_CNTL_2, 0x00, |
| 249 | R_11_MODE_DELAY_CNTL, 0x0c, | 293 | R_11_MODE_DELAY_CNTL, 0x0c, |
| 250 | R_12_RT_SIGNAL_CNTL, 0x07, | 294 | R_12_RT_SIGNAL_CNTL, 0x01, |
| 251 | R_13_RT_X_PORT_OUT_CNTL, 0x00, | 295 | R_13_RT_X_PORT_OUT_CNTL, 0x00, |
| 252 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, | 296 | R_14_ANAL_ADC_COMPAT_CNTL, 0x00, |
| 253 | R_15_VGATE_START_FID_CHG, 0x00, | 297 | R_15_VGATE_START_FID_CHG, 0x00, |
| @@ -462,24 +506,6 @@ static const unsigned char saa7115_cfg_50hz_video[] = { | |||
| 462 | 506 | ||
| 463 | /* ============== SAA7715 VIDEO templates (end) ======= */ | 507 | /* ============== SAA7715 VIDEO templates (end) ======= */ |
| 464 | 508 | ||
| 465 | /* ============== GM7113C VIDEO templates ============= */ | ||
| 466 | static const unsigned char gm7113c_cfg_60hz_video[] = { | ||
| 467 | R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ | ||
| 468 | R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */ | ||
| 469 | |||
| 470 | 0x00, 0x00 | ||
| 471 | }; | ||
| 472 | |||
| 473 | static const unsigned char gm7113c_cfg_50hz_video[] = { | ||
| 474 | R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */ | ||
| 475 | R_0E_CHROMA_CNTL_1, 0x07, | ||
| 476 | |||
| 477 | 0x00, 0x00 | ||
| 478 | }; | ||
| 479 | |||
| 480 | /* ============== GM7113C VIDEO templates (end) ======= */ | ||
| 481 | |||
| 482 | |||
| 483 | static const unsigned char saa7115_cfg_vbi_on[] = { | 509 | static const unsigned char saa7115_cfg_vbi_on[] = { |
| 484 | R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ | 510 | R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ |
| 485 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ | 511 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ |
| @@ -964,17 +990,24 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) | |||
| 964 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | 990 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. |
| 965 | if (std & V4L2_STD_525_60) { | 991 | if (std & V4L2_STD_525_60) { |
| 966 | v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); | 992 | v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); |
| 967 | if (state->ident == GM7113C) | 993 | if (state->ident == GM7113C) { |
| 968 | saa711x_writeregs(sd, gm7113c_cfg_60hz_video); | 994 | u8 reg = saa711x_read(sd, R_08_SYNC_CNTL); |
| 969 | else | 995 | reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD); |
| 996 | reg |= SAA7113_R_08_FSEL; | ||
| 997 | saa711x_write(sd, R_08_SYNC_CNTL, reg); | ||
| 998 | } else { | ||
| 970 | saa711x_writeregs(sd, saa7115_cfg_60hz_video); | 999 | saa711x_writeregs(sd, saa7115_cfg_60hz_video); |
| 1000 | } | ||
| 971 | saa711x_set_size(sd, 720, 480); | 1001 | saa711x_set_size(sd, 720, 480); |
| 972 | } else { | 1002 | } else { |
| 973 | v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); | 1003 | v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); |
| 974 | if (state->ident == GM7113C) | 1004 | if (state->ident == GM7113C) { |
| 975 | saa711x_writeregs(sd, gm7113c_cfg_50hz_video); | 1005 | u8 reg = saa711x_read(sd, R_08_SYNC_CNTL); |
| 976 | else | 1006 | reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD); |
| 1007 | saa711x_write(sd, R_08_SYNC_CNTL, reg); | ||
| 1008 | } else { | ||
| 977 | saa711x_writeregs(sd, saa7115_cfg_50hz_video); | 1009 | saa711x_writeregs(sd, saa7115_cfg_50hz_video); |
| 1010 | } | ||
| 978 | saa711x_set_size(sd, 720, 576); | 1011 | saa711x_set_size(sd, 720, 576); |
| 979 | } | 1012 | } |
| 980 | 1013 | ||
| @@ -1596,6 +1629,65 @@ static const struct v4l2_subdev_ops saa711x_ops = { | |||
| 1596 | 1629 | ||
| 1597 | /* ----------------------------------------------------------------------- */ | 1630 | /* ----------------------------------------------------------------------- */ |
| 1598 | 1631 | ||
| 1632 | static void saa711x_write_platform_data(struct saa711x_state *state, | ||
| 1633 | struct saa7115_platform_data *data) | ||
| 1634 | { | ||
| 1635 | struct v4l2_subdev *sd = &state->sd; | ||
| 1636 | u8 work; | ||
| 1637 | |||
| 1638 | if (state->ident != GM7113C && | ||
| 1639 | state->ident != SAA7113) | ||
| 1640 | return; | ||
| 1641 | |||
| 1642 | if (data->saa7113_r08_htc) { | ||
| 1643 | work = saa711x_read(sd, R_08_SYNC_CNTL); | ||
| 1644 | work &= ~SAA7113_R_08_HTC_MASK; | ||
| 1645 | work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET); | ||
| 1646 | saa711x_write(sd, R_08_SYNC_CNTL, work); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | if (data->saa7113_r10_vrln) { | ||
| 1650 | work = saa711x_read(sd, R_10_CHROMA_CNTL_2); | ||
| 1651 | work &= ~SAA7113_R_10_VRLN_MASK; | ||
| 1652 | if (*data->saa7113_r10_vrln) | ||
| 1653 | work |= (1 << SAA7113_R_10_VRLN_OFFSET); | ||
| 1654 | saa711x_write(sd, R_10_CHROMA_CNTL_2, work); | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | if (data->saa7113_r10_ofts) { | ||
| 1658 | work = saa711x_read(sd, R_10_CHROMA_CNTL_2); | ||
| 1659 | work &= ~SAA7113_R_10_OFTS_MASK; | ||
| 1660 | work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET); | ||
| 1661 | saa711x_write(sd, R_10_CHROMA_CNTL_2, work); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | if (data->saa7113_r12_rts0) { | ||
| 1665 | work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL); | ||
| 1666 | work &= ~SAA7113_R_12_RTS0_MASK; | ||
| 1667 | work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET); | ||
| 1668 | |||
| 1669 | /* According to the datasheet, | ||
| 1670 | * SAA7113_RTS_DOT_IN should only be used on RTS1 */ | ||
| 1671 | WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN); | ||
| 1672 | saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work); | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | if (data->saa7113_r12_rts1) { | ||
| 1676 | work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL); | ||
| 1677 | work &= ~SAA7113_R_12_RTS1_MASK; | ||
| 1678 | work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET); | ||
| 1679 | saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work); | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | if (data->saa7113_r13_adlsb) { | ||
| 1683 | work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL); | ||
| 1684 | work &= ~SAA7113_R_13_ADLSB_MASK; | ||
| 1685 | if (*data->saa7113_r13_adlsb) | ||
| 1686 | work |= (1 << SAA7113_R_13_ADLSB_OFFSET); | ||
| 1687 | saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work); | ||
| 1688 | } | ||
| 1689 | } | ||
| 1690 | |||
| 1599 | /** | 1691 | /** |
| 1600 | * saa711x_detect_chip - Detects the saa711x (or clone) variant | 1692 | * saa711x_detect_chip - Detects the saa711x (or clone) variant |
| 1601 | * @client: I2C client structure. | 1693 | * @client: I2C client structure. |
| @@ -1704,6 +1796,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
| 1704 | struct saa711x_state *state; | 1796 | struct saa711x_state *state; |
| 1705 | struct v4l2_subdev *sd; | 1797 | struct v4l2_subdev *sd; |
| 1706 | struct v4l2_ctrl_handler *hdl; | 1798 | struct v4l2_ctrl_handler *hdl; |
| 1799 | struct saa7115_platform_data *pdata; | ||
| 1707 | int ident; | 1800 | int ident; |
| 1708 | char name[CHIP_VER_SIZE + 1]; | 1801 | char name[CHIP_VER_SIZE + 1]; |
| 1709 | 1802 | ||
| @@ -1767,21 +1860,31 @@ static int saa711x_probe(struct i2c_client *client, | |||
| 1767 | 1860 | ||
| 1768 | /* init to 60hz/48khz */ | 1861 | /* init to 60hz/48khz */ |
| 1769 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | 1862 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; |
| 1863 | pdata = client->dev.platform_data; | ||
| 1770 | switch (state->ident) { | 1864 | switch (state->ident) { |
| 1771 | case SAA7111: | 1865 | case SAA7111: |
| 1772 | case SAA7111A: | 1866 | case SAA7111A: |
| 1773 | saa711x_writeregs(sd, saa7111_init); | 1867 | saa711x_writeregs(sd, saa7111_init); |
| 1774 | break; | 1868 | break; |
| 1775 | case GM7113C: | 1869 | case GM7113C: |
| 1870 | saa711x_writeregs(sd, gm7113c_init); | ||
| 1871 | break; | ||
| 1776 | case SAA7113: | 1872 | case SAA7113: |
| 1777 | saa711x_writeregs(sd, saa7113_init); | 1873 | if (pdata && pdata->saa7113_force_gm7113c_init) |
| 1874 | saa711x_writeregs(sd, gm7113c_init); | ||
| 1875 | else | ||
| 1876 | saa711x_writeregs(sd, saa7113_init); | ||
| 1778 | break; | 1877 | break; |
| 1779 | default: | 1878 | default: |
| 1780 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1879 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
| 1781 | saa711x_writeregs(sd, saa7115_init_auto_input); | 1880 | saa711x_writeregs(sd, saa7115_init_auto_input); |
| 1782 | } | 1881 | } |
| 1783 | if (state->ident > SAA7111A) | 1882 | if (state->ident > SAA7111A && state->ident != GM7113C) |
| 1784 | saa711x_writeregs(sd, saa7115_init_misc); | 1883 | saa711x_writeregs(sd, saa7115_init_misc); |
| 1884 | |||
| 1885 | if (pdata) | ||
| 1886 | saa711x_write_platform_data(state, pdata); | ||
| 1887 | |||
| 1785 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); | 1888 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); |
| 1786 | v4l2_ctrl_handler_setup(hdl); | 1889 | v4l2_ctrl_handler_setup(hdl); |
| 1787 | 1890 | ||
diff --git a/drivers/media/i2c/saa711x_regs.h b/drivers/media/i2c/saa711x_regs.h index 4e5f2eb0a2c1..730ca90b30ac 100644 --- a/drivers/media/i2c/saa711x_regs.h +++ b/drivers/media/i2c/saa711x_regs.h | |||
| @@ -201,6 +201,25 @@ | |||
| 201 | #define R_FB_PULSE_C_POS_MSB 0xfb | 201 | #define R_FB_PULSE_C_POS_MSB 0xfb |
| 202 | #define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES 0xff | 202 | #define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES 0xff |
| 203 | 203 | ||
| 204 | /* SAA7113 bit-masks */ | ||
| 205 | #define SAA7113_R_08_HTC_OFFSET 3 | ||
| 206 | #define SAA7113_R_08_HTC_MASK (0x3 << SAA7113_R_08_HTC_OFFSET) | ||
| 207 | #define SAA7113_R_08_FSEL 0x40 | ||
| 208 | #define SAA7113_R_08_AUFD 0x80 | ||
| 209 | |||
| 210 | #define SAA7113_R_10_VRLN_OFFSET 3 | ||
| 211 | #define SAA7113_R_10_VRLN_MASK (0x1 << SAA7113_R_10_VRLN_OFFSET) | ||
| 212 | #define SAA7113_R_10_OFTS_OFFSET 6 | ||
| 213 | #define SAA7113_R_10_OFTS_MASK (0x3 << SAA7113_R_10_OFTS_OFFSET) | ||
| 214 | |||
| 215 | #define SAA7113_R_12_RTS0_OFFSET 0 | ||
| 216 | #define SAA7113_R_12_RTS0_MASK (0xf << SAA7113_R_12_RTS0_OFFSET) | ||
| 217 | #define SAA7113_R_12_RTS1_OFFSET 4 | ||
| 218 | #define SAA7113_R_12_RTS1_MASK (0xf << SAA7113_R_12_RTS1_OFFSET) | ||
| 219 | |||
| 220 | #define SAA7113_R_13_ADLSB_OFFSET 7 | ||
| 221 | #define SAA7113_R_13_ADLSB_MASK (0x1 << SAA7113_R_13_ADLSB_OFFSET) | ||
| 222 | |||
| 204 | #if 0 | 223 | #if 0 |
| 205 | /* Those structs will be used in the future for debug purposes */ | 224 | /* Those structs will be used in the future for debug purposes */ |
| 206 | struct saa711x_reg_descr { | 225 | struct saa711x_reg_descr { |
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c index d8d5da7c52db..2335529b195c 100644 --- a/drivers/media/i2c/smiapp-pll.c +++ b/drivers/media/i2c/smiapp-pll.c | |||
| @@ -87,6 +87,17 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) | |||
| 87 | dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); | 87 | dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | /* | ||
| 91 | * Heuristically guess the PLL tree for a given common multiplier and | ||
| 92 | * divisor. Begin with the operational timing and continue to video | ||
| 93 | * timing once operational timing has been verified. | ||
| 94 | * | ||
| 95 | * @mul is the PLL multiplier and @div is the common divisor | ||
| 96 | * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL | ||
| 97 | * multiplier will be a multiple of @mul. | ||
| 98 | * | ||
| 99 | * @return Zero on success, error code on error. | ||
| 100 | */ | ||
| 90 | static int __smiapp_pll_calculate(struct device *dev, | 101 | static int __smiapp_pll_calculate(struct device *dev, |
| 91 | const struct smiapp_pll_limits *limits, | 102 | const struct smiapp_pll_limits *limits, |
| 92 | struct smiapp_pll *pll, uint32_t mul, | 103 | struct smiapp_pll *pll, uint32_t mul, |
| @@ -95,6 +106,12 @@ static int __smiapp_pll_calculate(struct device *dev, | |||
| 95 | uint32_t sys_div; | 106 | uint32_t sys_div; |
| 96 | uint32_t best_pix_div = INT_MAX >> 1; | 107 | uint32_t best_pix_div = INT_MAX >> 1; |
| 97 | uint32_t vt_op_binning_div; | 108 | uint32_t vt_op_binning_div; |
| 109 | /* | ||
| 110 | * Higher multipliers (and divisors) are often required than | ||
| 111 | * necessitated by the external clock and the output clocks. | ||
| 112 | * There are limits for all values in the clock tree. These | ||
| 113 | * are the minimum and maximum multiplier for mul. | ||
| 114 | */ | ||
| 98 | uint32_t more_mul_min, more_mul_max; | 115 | uint32_t more_mul_min, more_mul_max; |
| 99 | uint32_t more_mul_factor; | 116 | uint32_t more_mul_factor; |
| 100 | uint32_t min_vt_div, max_vt_div, vt_div; | 117 | uint32_t min_vt_div, max_vt_div, vt_div; |
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 7ac7580f85c9..ae66d91bf713 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c | |||
| @@ -1122,9 +1122,9 @@ static int smiapp_power_on(struct smiapp_sensor *sensor) | |||
| 1122 | rval = sensor->platform_data->set_xclk( | 1122 | rval = sensor->platform_data->set_xclk( |
| 1123 | &sensor->src->sd, sensor->platform_data->ext_clk); | 1123 | &sensor->src->sd, sensor->platform_data->ext_clk); |
| 1124 | else | 1124 | else |
| 1125 | rval = clk_enable(sensor->ext_clk); | 1125 | rval = clk_prepare_enable(sensor->ext_clk); |
| 1126 | if (rval < 0) { | 1126 | if (rval < 0) { |
| 1127 | dev_dbg(&client->dev, "failed to set xclk\n"); | 1127 | dev_dbg(&client->dev, "failed to enable xclk\n"); |
| 1128 | goto out_xclk_fail; | 1128 | goto out_xclk_fail; |
| 1129 | } | 1129 | } |
| 1130 | usleep_range(1000, 1000); | 1130 | usleep_range(1000, 1000); |
| @@ -1244,7 +1244,7 @@ out_cci_addr_fail: | |||
| 1244 | if (sensor->platform_data->set_xclk) | 1244 | if (sensor->platform_data->set_xclk) |
| 1245 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 1245 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| 1246 | else | 1246 | else |
| 1247 | clk_disable(sensor->ext_clk); | 1247 | clk_disable_unprepare(sensor->ext_clk); |
| 1248 | 1248 | ||
| 1249 | out_xclk_fail: | 1249 | out_xclk_fail: |
| 1250 | regulator_disable(sensor->vana); | 1250 | regulator_disable(sensor->vana); |
| @@ -1270,7 +1270,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor) | |||
| 1270 | if (sensor->platform_data->set_xclk) | 1270 | if (sensor->platform_data->set_xclk) |
| 1271 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 1271 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| 1272 | else | 1272 | else |
| 1273 | clk_disable(sensor->ext_clk); | 1273 | clk_disable_unprepare(sensor->ext_clk); |
| 1274 | usleep_range(5000, 5000); | 1274 | usleep_range(5000, 5000); |
| 1275 | regulator_disable(sensor->vana); | 1275 | regulator_disable(sensor->vana); |
| 1276 | sensor->streaming = 0; | 1276 | sensor->streaming = 0; |
| @@ -1835,12 +1835,12 @@ static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev, | |||
| 1835 | * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] | 1835 | * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] |
| 1836 | / sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE]; | 1836 | / sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE]; |
| 1837 | 1837 | ||
| 1838 | a = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1838 | a = clamp(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
| 1839 | max(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1839 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
| 1840 | b = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1840 | b = clamp(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
| 1841 | max(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1841 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
| 1842 | max_m = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX], | 1842 | max_m = clamp(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN], |
| 1843 | max(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN])); | 1843 | sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]); |
| 1844 | 1844 | ||
| 1845 | dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); | 1845 | dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); |
| 1846 | 1846 | ||
| @@ -2363,11 +2363,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) | |||
| 2363 | } | 2363 | } |
| 2364 | 2364 | ||
| 2365 | if (!sensor->platform_data->set_xclk) { | 2365 | if (!sensor->platform_data->set_xclk) { |
| 2366 | sensor->ext_clk = devm_clk_get(&client->dev, | 2366 | sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk"); |
| 2367 | sensor->platform_data->ext_clk_name); | ||
| 2368 | if (IS_ERR(sensor->ext_clk)) { | 2367 | if (IS_ERR(sensor->ext_clk)) { |
| 2369 | dev_err(&client->dev, "could not get clock %s\n", | 2368 | dev_err(&client->dev, "could not get clock\n"); |
| 2370 | sensor->platform_data->ext_clk_name); | ||
| 2371 | return -ENODEV; | 2369 | return -ENODEV; |
| 2372 | } | 2370 | } |
| 2373 | 2371 | ||
| @@ -2375,8 +2373,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) | |||
| 2375 | sensor->platform_data->ext_clk); | 2373 | sensor->platform_data->ext_clk); |
| 2376 | if (rval < 0) { | 2374 | if (rval < 0) { |
| 2377 | dev_err(&client->dev, | 2375 | dev_err(&client->dev, |
| 2378 | "unable to set clock %s freq to %u\n", | 2376 | "unable to set clock freq to %u\n", |
| 2379 | sensor->platform_data->ext_clk_name, | ||
| 2380 | sensor->platform_data->ext_clk); | 2377 | sensor->platform_data->ext_clk); |
| 2381 | return -ENODEV; | 2378 | return -ENODEV; |
| 2382 | } | 2379 | } |
| @@ -2839,7 +2836,7 @@ static int smiapp_remove(struct i2c_client *client) | |||
| 2839 | if (sensor->platform_data->set_xclk) | 2836 | if (sensor->platform_data->set_xclk) |
| 2840 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); | 2837 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| 2841 | else | 2838 | else |
| 2842 | clk_disable(sensor->ext_clk); | 2839 | clk_disable_unprepare(sensor->ext_clk); |
| 2843 | sensor->power_count = 0; | 2840 | sensor->power_count = 0; |
| 2844 | } | 2841 | } |
| 2845 | 2842 | ||
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index de3605df47c5..6f4056668bbc 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c | |||
| @@ -946,6 +946,10 @@ static int mt9m111_probe(struct i2c_client *client, | |||
| 946 | if (!mt9m111) | 946 | if (!mt9m111) |
| 947 | return -ENOMEM; | 947 | return -ENOMEM; |
| 948 | 948 | ||
| 949 | mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); | ||
| 950 | if (IS_ERR(mt9m111->clk)) | ||
| 951 | return -EPROBE_DEFER; | ||
| 952 | |||
| 949 | /* Default HIGHPOWER context */ | 953 | /* Default HIGHPOWER context */ |
| 950 | mt9m111->ctx = &context_b; | 954 | mt9m111->ctx = &context_b; |
| 951 | 955 | ||
| @@ -963,8 +967,10 @@ static int mt9m111_probe(struct i2c_client *client, | |||
| 963 | &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, | 967 | &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, |
| 964 | V4L2_EXPOSURE_AUTO); | 968 | V4L2_EXPOSURE_AUTO); |
| 965 | mt9m111->subdev.ctrl_handler = &mt9m111->hdl; | 969 | mt9m111->subdev.ctrl_handler = &mt9m111->hdl; |
| 966 | if (mt9m111->hdl.error) | 970 | if (mt9m111->hdl.error) { |
| 967 | return mt9m111->hdl.error; | 971 | ret = mt9m111->hdl.error; |
| 972 | goto out_clkput; | ||
| 973 | } | ||
| 968 | 974 | ||
| 969 | /* Second stage probe - when a capture adapter is there */ | 975 | /* Second stage probe - when a capture adapter is there */ |
| 970 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; | 976 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; |
| @@ -975,18 +981,25 @@ static int mt9m111_probe(struct i2c_client *client, | |||
| 975 | mt9m111->lastpage = -1; | 981 | mt9m111->lastpage = -1; |
| 976 | mutex_init(&mt9m111->power_lock); | 982 | mutex_init(&mt9m111->power_lock); |
| 977 | 983 | ||
| 978 | mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); | 984 | ret = soc_camera_power_init(&client->dev, ssdd); |
| 979 | if (IS_ERR(mt9m111->clk)) { | 985 | if (ret < 0) |
| 980 | ret = PTR_ERR(mt9m111->clk); | 986 | goto out_hdlfree; |
| 981 | goto eclkget; | ||
| 982 | } | ||
| 983 | 987 | ||
| 984 | ret = mt9m111_video_probe(client); | 988 | ret = mt9m111_video_probe(client); |
| 985 | if (ret) { | 989 | if (ret < 0) |
| 986 | v4l2_clk_put(mt9m111->clk); | 990 | goto out_hdlfree; |
| 987 | eclkget: | 991 | |
| 988 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 992 | mt9m111->subdev.dev = &client->dev; |
| 989 | } | 993 | ret = v4l2_async_register_subdev(&mt9m111->subdev); |
| 994 | if (ret < 0) | ||
| 995 | goto out_hdlfree; | ||
| 996 | |||
| 997 | return 0; | ||
| 998 | |||
| 999 | out_hdlfree: | ||
| 1000 | v4l2_ctrl_handler_free(&mt9m111->hdl); | ||
| 1001 | out_clkput: | ||
| 1002 | v4l2_clk_put(mt9m111->clk); | ||
| 990 | 1003 | ||
| 991 | return ret; | 1004 | return ret; |
| 992 | } | 1005 | } |
| @@ -995,6 +1008,7 @@ static int mt9m111_remove(struct i2c_client *client) | |||
| 995 | { | 1008 | { |
| 996 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 1009 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
| 997 | 1010 | ||
| 1011 | v4l2_async_unregister_subdev(&mt9m111->subdev); | ||
| 998 | v4l2_clk_put(mt9m111->clk); | 1012 | v4l2_clk_put(mt9m111->clk); |
| 999 | v4l2_device_unregister_subdev(&mt9m111->subdev); | 1013 | v4l2_device_unregister_subdev(&mt9m111->subdev); |
| 1000 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 1014 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 47d18d0bafe7..ee7bb0ffcecb 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c | |||
| @@ -594,9 +594,12 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on) | |||
| 594 | ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); | 594 | ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); |
| 595 | if (ret < 0) | 595 | if (ret < 0) |
| 596 | return ret; | 596 | return ret; |
| 597 | vdev->dev.type = &mt9t031_dev_type; | 597 | if (vdev) |
| 598 | /* Not needed during probing, when vdev isn't available yet */ | ||
| 599 | vdev->dev.type = &mt9t031_dev_type; | ||
| 598 | } else { | 600 | } else { |
| 599 | vdev->dev.type = NULL; | 601 | if (vdev) |
| 602 | vdev->dev.type = NULL; | ||
| 600 | soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); | 603 | soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); |
| 601 | } | 604 | } |
| 602 | 605 | ||
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 0a2dacbd7a63..42276d93624c 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c | |||
| @@ -291,10 +291,8 @@ static int ths7303_log_status(struct v4l2_subdev *sd) | |||
| 291 | struct v4l2_bt_timings *bt = bt = &state->bt; | 291 | struct v4l2_bt_timings *bt = bt = &state->bt; |
| 292 | u32 frame_width, frame_height; | 292 | u32 frame_width, frame_height; |
| 293 | 293 | ||
| 294 | frame_width = bt->width + bt->hfrontporch + | 294 | frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); |
| 295 | bt->hsync + bt->hbackporch; | 295 | frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt); |
| 296 | frame_height = bt->height + bt->vfrontporch + | ||
| 297 | bt->vsync + bt->vbackporch; | ||
| 298 | v4l2_info(sd, | 296 | v4l2_info(sd, |
| 299 | "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", | 297 | "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", |
| 300 | bt->width, bt->height, bt->interlaced ? "i" : "p", | 298 | bt->width, bt->height, bt->interlaced ? "i" : "p", |
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index a24f90c5261c..a58a8f663ffb 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/v4l2-dv-timings.h> | 22 | #include <linux/v4l2-dv-timings.h> |
| 23 | 23 | ||
| 24 | #include <media/v4l2-dv-timings.h> | ||
| 25 | #include <media/v4l2-async.h> | ||
| 24 | #include <media/v4l2-device.h> | 26 | #include <media/v4l2-device.h> |
| 25 | 27 | ||
| 26 | #include "ths8200_regs.h" | 28 | #include "ths8200_regs.h" |
| @@ -42,18 +44,16 @@ struct ths8200_state { | |||
| 42 | struct v4l2_dv_timings dv_timings; | 44 | struct v4l2_dv_timings dv_timings; |
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | static const struct v4l2_dv_timings ths8200_timings[] = { | 47 | static const struct v4l2_dv_timings_cap ths8200_timings_cap = { |
| 46 | V4L2_DV_BT_CEA_720X480P59_94, | 48 | .type = V4L2_DV_BT_656_1120, |
| 47 | V4L2_DV_BT_CEA_1280X720P24, | 49 | .bt = { |
| 48 | V4L2_DV_BT_CEA_1280X720P25, | 50 | .max_width = 1920, |
| 49 | V4L2_DV_BT_CEA_1280X720P30, | 51 | .max_height = 1080, |
| 50 | V4L2_DV_BT_CEA_1280X720P50, | 52 | .min_pixelclock = 25000000, |
| 51 | V4L2_DV_BT_CEA_1280X720P60, | 53 | .max_pixelclock = 148500000, |
| 52 | V4L2_DV_BT_CEA_1920X1080P24, | 54 | .standards = V4L2_DV_BT_STD_CEA861, |
| 53 | V4L2_DV_BT_CEA_1920X1080P25, | 55 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE, |
| 54 | V4L2_DV_BT_CEA_1920X1080P30, | 56 | }, |
| 55 | V4L2_DV_BT_CEA_1920X1080P50, | ||
| 56 | V4L2_DV_BT_CEA_1920X1080P60, | ||
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) | 59 | static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) |
| @@ -63,22 +63,22 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) | |||
| 63 | 63 | ||
| 64 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) | 64 | static inline unsigned hblanking(const struct v4l2_bt_timings *t) |
| 65 | { | 65 | { |
| 66 | return t->hfrontporch + t->hsync + t->hbackporch; | 66 | return V4L2_DV_BT_BLANKING_WIDTH(t); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static inline unsigned htotal(const struct v4l2_bt_timings *t) | 69 | static inline unsigned htotal(const struct v4l2_bt_timings *t) |
| 70 | { | 70 | { |
| 71 | return t->width + t->hfrontporch + t->hsync + t->hbackporch; | 71 | return V4L2_DV_BT_FRAME_WIDTH(t); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) | 74 | static inline unsigned vblanking(const struct v4l2_bt_timings *t) |
| 75 | { | 75 | { |
| 76 | return t->vfrontporch + t->vsync + t->vbackporch; | 76 | return V4L2_DV_BT_BLANKING_HEIGHT(t); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) | 79 | static inline unsigned vtotal(const struct v4l2_bt_timings *t) |
| 80 | { | 80 | { |
| 81 | return t->height + t->vfrontporch + t->vsync + t->vbackporch; | 81 | return V4L2_DV_BT_FRAME_HEIGHT(t); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static int ths8200_read(struct v4l2_subdev *sd, u8 reg) | 84 | static int ths8200_read(struct v4l2_subdev *sd, u8 reg) |
| @@ -133,39 +133,6 @@ static int ths8200_s_register(struct v4l2_subdev *sd, | |||
| 133 | } | 133 | } |
| 134 | #endif | 134 | #endif |
| 135 | 135 | ||
| 136 | static void ths8200_print_timings(struct v4l2_subdev *sd, | ||
| 137 | struct v4l2_dv_timings *timings, | ||
| 138 | const char *txt, bool detailed) | ||
| 139 | { | ||
| 140 | struct v4l2_bt_timings *bt = &timings->bt; | ||
| 141 | u32 htot, vtot; | ||
| 142 | |||
| 143 | if (timings->type != V4L2_DV_BT_656_1120) | ||
| 144 | return; | ||
| 145 | |||
| 146 | htot = htotal(bt); | ||
| 147 | vtot = vtotal(bt); | ||
| 148 | |||
| 149 | v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", | ||
| 150 | txt, bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
| 151 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, | ||
| 152 | htot, vtot); | ||
| 153 | |||
| 154 | if (detailed) { | ||
| 155 | v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", | ||
| 156 | bt->hfrontporch, | ||
| 157 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
| 158 | bt->hsync, bt->hbackporch); | ||
| 159 | v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", | ||
| 160 | bt->vfrontporch, | ||
| 161 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
| 162 | bt->vsync, bt->vbackporch); | ||
| 163 | v4l2_info(sd, | ||
| 164 | " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", | ||
| 165 | bt->pixelclock, bt->flags, bt->standards); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | static int ths8200_log_status(struct v4l2_subdev *sd) | 136 | static int ths8200_log_status(struct v4l2_subdev *sd) |
| 170 | { | 137 | { |
| 171 | struct ths8200_state *state = to_state(sd); | 138 | struct ths8200_state *state = to_state(sd); |
| @@ -182,9 +149,8 @@ static int ths8200_log_status(struct v4l2_subdev *sd) | |||
| 182 | ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), | 149 | ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), |
| 183 | (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + | 150 | (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + |
| 184 | ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); | 151 | ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); |
| 185 | ths8200_print_timings(sd, &state->dv_timings, | 152 | v4l2_print_dv_timings(sd->name, "Configured format:", |
| 186 | "Configured format:", true); | 153 | &state->dv_timings, true); |
| 187 | |||
| 188 | return 0; | 154 | return 0; |
| 189 | } | 155 | } |
| 190 | 156 | ||
| @@ -409,25 +375,15 @@ static int ths8200_s_dv_timings(struct v4l2_subdev *sd, | |||
| 409 | struct v4l2_dv_timings *timings) | 375 | struct v4l2_dv_timings *timings) |
| 410 | { | 376 | { |
| 411 | struct ths8200_state *state = to_state(sd); | 377 | struct ths8200_state *state = to_state(sd); |
| 412 | int i; | ||
| 413 | 378 | ||
| 414 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | 379 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); |
| 415 | 380 | ||
| 416 | if (timings->type != V4L2_DV_BT_656_1120) | 381 | if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap, |
| 417 | return -EINVAL; | 382 | NULL, NULL)) |
| 418 | |||
| 419 | /* TODO Support interlaced formats */ | ||
| 420 | if (timings->bt.interlaced) { | ||
| 421 | v4l2_dbg(1, debug, sd, "TODO Support interlaced formats\n"); | ||
| 422 | return -EINVAL; | 383 | return -EINVAL; |
| 423 | } | ||
| 424 | |||
| 425 | for (i = 0; i < ARRAY_SIZE(ths8200_timings); i++) { | ||
| 426 | if (v4l_match_dv_timings(&ths8200_timings[i], timings, 10)) | ||
| 427 | break; | ||
| 428 | } | ||
| 429 | 384 | ||
| 430 | if (i == ARRAY_SIZE(ths8200_timings)) { | 385 | if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10, |
| 386 | NULL, NULL)) { | ||
| 431 | v4l2_dbg(1, debug, sd, "Unsupported format\n"); | 387 | v4l2_dbg(1, debug, sd, "Unsupported format\n"); |
| 432 | return -EINVAL; | 388 | return -EINVAL; |
| 433 | } | 389 | } |
| @@ -457,26 +413,14 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd, | |||
| 457 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, | 413 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, |
| 458 | struct v4l2_enum_dv_timings *timings) | 414 | struct v4l2_enum_dv_timings *timings) |
| 459 | { | 415 | { |
| 460 | /* Check requested format index is within range */ | 416 | return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap, |
| 461 | if (timings->index >= ARRAY_SIZE(ths8200_timings)) | 417 | NULL, NULL); |
| 462 | return -EINVAL; | ||
| 463 | |||
| 464 | timings->timings = ths8200_timings[timings->index]; | ||
| 465 | |||
| 466 | return 0; | ||
| 467 | } | 418 | } |
| 468 | 419 | ||
| 469 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, | 420 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, |
| 470 | struct v4l2_dv_timings_cap *cap) | 421 | struct v4l2_dv_timings_cap *cap) |
| 471 | { | 422 | { |
| 472 | cap->type = V4L2_DV_BT_656_1120; | 423 | *cap = ths8200_timings_cap; |
| 473 | cap->bt.max_width = 1920; | ||
| 474 | cap->bt.max_height = 1080; | ||
| 475 | cap->bt.min_pixelclock = 27000000; | ||
| 476 | cap->bt.max_pixelclock = 148500000; | ||
| 477 | cap->bt.standards = V4L2_DV_BT_STD_CEA861; | ||
| 478 | cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE; | ||
| 479 | |||
| 480 | return 0; | 424 | return 0; |
| 481 | } | 425 | } |
| 482 | 426 | ||
| @@ -500,6 +444,7 @@ static int ths8200_probe(struct i2c_client *client, | |||
| 500 | { | 444 | { |
| 501 | struct ths8200_state *state; | 445 | struct ths8200_state *state; |
| 502 | struct v4l2_subdev *sd; | 446 | struct v4l2_subdev *sd; |
| 447 | int error; | ||
| 503 | 448 | ||
| 504 | /* Check if the adapter supports the needed features */ | 449 | /* Check if the adapter supports the needed features */ |
| 505 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 450 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
| @@ -517,6 +462,10 @@ static int ths8200_probe(struct i2c_client *client, | |||
| 517 | 462 | ||
| 518 | ths8200_core_init(sd); | 463 | ths8200_core_init(sd); |
| 519 | 464 | ||
| 465 | error = v4l2_async_register_subdev(&state->sd); | ||
| 466 | if (error) | ||
| 467 | return error; | ||
| 468 | |||
| 520 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | 469 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
| 521 | client->addr << 1, client->adapter->name); | 470 | client->addr << 1, client->adapter->name); |
| 522 | 471 | ||
| @@ -526,12 +475,13 @@ static int ths8200_probe(struct i2c_client *client, | |||
| 526 | static int ths8200_remove(struct i2c_client *client) | 475 | static int ths8200_remove(struct i2c_client *client) |
| 527 | { | 476 | { |
| 528 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 477 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 478 | struct ths8200_state *decoder = to_state(sd); | ||
| 529 | 479 | ||
| 530 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, | 480 | v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, |
| 531 | client->addr << 1, client->adapter->name); | 481 | client->addr << 1, client->adapter->name); |
| 532 | 482 | ||
| 533 | ths8200_s_power(sd, false); | 483 | ths8200_s_power(sd, false); |
| 534 | 484 | v4l2_async_unregister_subdev(&decoder->sd); | |
| 535 | v4l2_device_unregister_subdev(sd); | 485 | v4l2_device_unregister_subdev(sd); |
| 536 | 486 | ||
| 537 | return 0; | 487 | return 0; |
| @@ -543,10 +493,19 @@ static struct i2c_device_id ths8200_id[] = { | |||
| 543 | }; | 493 | }; |
| 544 | MODULE_DEVICE_TABLE(i2c, ths8200_id); | 494 | MODULE_DEVICE_TABLE(i2c, ths8200_id); |
| 545 | 495 | ||
| 496 | #if IS_ENABLED(CONFIG_OF) | ||
| 497 | static const struct of_device_id ths8200_of_match[] = { | ||
| 498 | { .compatible = "ti,ths8200", }, | ||
| 499 | { /* sentinel */ }, | ||
| 500 | }; | ||
| 501 | MODULE_DEVICE_TABLE(of, ths8200_of_match); | ||
| 502 | #endif | ||
| 503 | |||
| 546 | static struct i2c_driver ths8200_driver = { | 504 | static struct i2c_driver ths8200_driver = { |
| 547 | .driver = { | 505 | .driver = { |
| 548 | .owner = THIS_MODULE, | 506 | .owner = THIS_MODULE, |
| 549 | .name = "ths8200", | 507 | .name = "ths8200", |
| 508 | .of_match_table = of_match_ptr(ths8200_of_match), | ||
| 550 | }, | 509 | }, |
| 551 | .probe = ths8200_probe, | 510 | .probe = ths8200_probe, |
| 552 | .remove = ths8200_remove, | 511 | .remove = ths8200_remove, |
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 9c6d66a9868f..91f3dd4cda1b 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 37 | #include <linux/v4l2-mediabus.h> | 37 | #include <linux/v4l2-mediabus.h> |
| 38 | 38 | ||
| 39 | #include <media/v4l2-async.h> | ||
| 39 | #include <media/v4l2-device.h> | 40 | #include <media/v4l2-device.h> |
| 40 | #include <media/v4l2-common.h> | 41 | #include <media/v4l2-common.h> |
| 41 | #include <media/v4l2-mediabus.h> | 42 | #include <media/v4l2-mediabus.h> |
| @@ -1175,16 +1176,22 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 1175 | sd->ctrl_handler = &decoder->hdl; | 1176 | sd->ctrl_handler = &decoder->hdl; |
| 1176 | if (decoder->hdl.error) { | 1177 | if (decoder->hdl.error) { |
| 1177 | ret = decoder->hdl.error; | 1178 | ret = decoder->hdl.error; |
| 1178 | 1179 | goto done; | |
| 1179 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
| 1180 | return ret; | ||
| 1181 | } | 1180 | } |
| 1182 | v4l2_ctrl_handler_setup(&decoder->hdl); | 1181 | v4l2_ctrl_handler_setup(&decoder->hdl); |
| 1183 | 1182 | ||
| 1184 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); | 1183 | ret = v4l2_async_register_subdev(&decoder->sd); |
| 1185 | 1184 | if (!ret) | |
| 1186 | return 0; | 1185 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); |
| 1187 | 1186 | ||
| 1187 | done: | ||
| 1188 | if (ret < 0) { | ||
| 1189 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
| 1190 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1191 | media_entity_cleanup(&decoder->sd.entity); | ||
| 1192 | #endif | ||
| 1193 | } | ||
| 1194 | return ret; | ||
| 1188 | } | 1195 | } |
| 1189 | 1196 | ||
| 1190 | /** | 1197 | /** |
| @@ -1199,6 +1206,7 @@ static int tvp514x_remove(struct i2c_client *client) | |||
| 1199 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 1206 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1200 | struct tvp514x_decoder *decoder = to_decoder(sd); | 1207 | struct tvp514x_decoder *decoder = to_decoder(sd); |
| 1201 | 1208 | ||
| 1209 | v4l2_async_unregister_subdev(&decoder->sd); | ||
| 1202 | v4l2_device_unregister_subdev(sd); | 1210 | v4l2_device_unregister_subdev(sd); |
| 1203 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1211 | #if defined(CONFIG_MEDIA_CONTROLLER) |
| 1204 | media_entity_cleanup(&decoder->sd.entity); | 1212 | media_entity_cleanup(&decoder->sd.entity); |
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index a4e49483de6a..24a08fa7e328 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c | |||
| @@ -31,9 +31,12 @@ | |||
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/v4l2-dv-timings.h> | 32 | #include <linux/v4l2-dv-timings.h> |
| 33 | #include <media/tvp7002.h> | 33 | #include <media/tvp7002.h> |
| 34 | #include <media/v4l2-async.h> | ||
| 34 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
| 35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 36 | #include <media/v4l2-ctrls.h> | 37 | #include <media/v4l2-ctrls.h> |
| 38 | #include <media/v4l2-of.h> | ||
| 39 | |||
| 37 | #include "tvp7002_reg.h" | 40 | #include "tvp7002_reg.h" |
| 38 | 41 | ||
| 39 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); | 42 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); |
| @@ -942,6 +945,48 @@ static const struct v4l2_subdev_ops tvp7002_ops = { | |||
| 942 | .pad = &tvp7002_pad_ops, | 945 | .pad = &tvp7002_pad_ops, |
| 943 | }; | 946 | }; |
| 944 | 947 | ||
| 948 | static struct tvp7002_config * | ||
| 949 | tvp7002_get_pdata(struct i2c_client *client) | ||
| 950 | { | ||
| 951 | struct v4l2_of_endpoint bus_cfg; | ||
| 952 | struct tvp7002_config *pdata; | ||
| 953 | struct device_node *endpoint; | ||
| 954 | unsigned int flags; | ||
| 955 | |||
| 956 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) | ||
| 957 | return client->dev.platform_data; | ||
| 958 | |||
| 959 | endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); | ||
| 960 | if (!endpoint) | ||
| 961 | return NULL; | ||
| 962 | |||
| 963 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 964 | if (!pdata) | ||
| 965 | goto done; | ||
| 966 | |||
| 967 | v4l2_of_parse_endpoint(endpoint, &bus_cfg); | ||
| 968 | flags = bus_cfg.bus.parallel.flags; | ||
| 969 | |||
| 970 | if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) | ||
| 971 | pdata->hs_polarity = 1; | ||
| 972 | |||
| 973 | if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) | ||
| 974 | pdata->vs_polarity = 1; | ||
| 975 | |||
| 976 | if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) | ||
| 977 | pdata->clk_polarity = 1; | ||
| 978 | |||
| 979 | if (flags & V4L2_MBUS_FIELD_EVEN_HIGH) | ||
| 980 | pdata->fid_polarity = 1; | ||
| 981 | |||
| 982 | if (flags & V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH) | ||
| 983 | pdata->sog_polarity = 1; | ||
| 984 | |||
| 985 | done: | ||
| 986 | of_node_put(endpoint); | ||
| 987 | return pdata; | ||
| 988 | } | ||
| 989 | |||
| 945 | /* | 990 | /* |
| 946 | * tvp7002_probe - Probe a TVP7002 device | 991 | * tvp7002_probe - Probe a TVP7002 device |
| 947 | * @c: ptr to i2c_client struct | 992 | * @c: ptr to i2c_client struct |
| @@ -953,32 +998,32 @@ static const struct v4l2_subdev_ops tvp7002_ops = { | |||
| 953 | */ | 998 | */ |
| 954 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | 999 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) |
| 955 | { | 1000 | { |
| 1001 | struct tvp7002_config *pdata = tvp7002_get_pdata(c); | ||
| 956 | struct v4l2_subdev *sd; | 1002 | struct v4l2_subdev *sd; |
| 957 | struct tvp7002 *device; | 1003 | struct tvp7002 *device; |
| 958 | struct v4l2_dv_timings timings; | 1004 | struct v4l2_dv_timings timings; |
| 959 | int polarity_a; | 1005 | int polarity_a; |
| 960 | int polarity_b; | 1006 | int polarity_b; |
| 961 | u8 revision; | 1007 | u8 revision; |
| 962 | |||
| 963 | int error; | 1008 | int error; |
| 964 | 1009 | ||
| 1010 | if (pdata == NULL) { | ||
| 1011 | dev_err(&c->dev, "No platform data\n"); | ||
| 1012 | return -EINVAL; | ||
| 1013 | } | ||
| 1014 | |||
| 965 | /* Check if the adapter supports the needed features */ | 1015 | /* Check if the adapter supports the needed features */ |
| 966 | if (!i2c_check_functionality(c->adapter, | 1016 | if (!i2c_check_functionality(c->adapter, |
| 967 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 1017 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
| 968 | return -EIO; | 1018 | return -EIO; |
| 969 | 1019 | ||
| 970 | if (!c->dev.platform_data) { | ||
| 971 | v4l_err(c, "No platform data!!\n"); | ||
| 972 | return -ENODEV; | ||
| 973 | } | ||
| 974 | |||
| 975 | device = devm_kzalloc(&c->dev, sizeof(struct tvp7002), GFP_KERNEL); | 1020 | device = devm_kzalloc(&c->dev, sizeof(struct tvp7002), GFP_KERNEL); |
| 976 | 1021 | ||
| 977 | if (!device) | 1022 | if (!device) |
| 978 | return -ENOMEM; | 1023 | return -ENOMEM; |
| 979 | 1024 | ||
| 980 | sd = &device->sd; | 1025 | sd = &device->sd; |
| 981 | device->pdata = c->dev.platform_data; | 1026 | device->pdata = pdata; |
| 982 | device->current_timings = tvp7002_timings; | 1027 | device->current_timings = tvp7002_timings; |
| 983 | 1028 | ||
| 984 | /* Tell v4l2 the device is ready */ | 1029 | /* Tell v4l2 the device is ready */ |
| @@ -1039,6 +1084,10 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | |||
| 1039 | } | 1084 | } |
| 1040 | v4l2_ctrl_handler_setup(&device->hdl); | 1085 | v4l2_ctrl_handler_setup(&device->hdl); |
| 1041 | 1086 | ||
| 1087 | error = v4l2_async_register_subdev(&device->sd); | ||
| 1088 | if (error) | ||
| 1089 | goto error; | ||
| 1090 | |||
| 1042 | return 0; | 1091 | return 0; |
| 1043 | 1092 | ||
| 1044 | error: | 1093 | error: |
| @@ -1063,6 +1112,7 @@ static int tvp7002_remove(struct i2c_client *c) | |||
| 1063 | 1112 | ||
| 1064 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" | 1113 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" |
| 1065 | "on address 0x%x\n", c->addr); | 1114 | "on address 0x%x\n", c->addr); |
| 1115 | v4l2_async_unregister_subdev(&device->sd); | ||
| 1066 | #if defined(CONFIG_MEDIA_CONTROLLER) | 1116 | #if defined(CONFIG_MEDIA_CONTROLLER) |
| 1067 | media_entity_cleanup(&device->sd.entity); | 1117 | media_entity_cleanup(&device->sd.entity); |
| 1068 | #endif | 1118 | #endif |
| @@ -1078,9 +1128,18 @@ static const struct i2c_device_id tvp7002_id[] = { | |||
| 1078 | }; | 1128 | }; |
| 1079 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); | 1129 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); |
| 1080 | 1130 | ||
| 1131 | #if IS_ENABLED(CONFIG_OF) | ||
| 1132 | static const struct of_device_id tvp7002_of_match[] = { | ||
| 1133 | { .compatible = "ti,tvp7002", }, | ||
| 1134 | { /* sentinel */ }, | ||
| 1135 | }; | ||
| 1136 | MODULE_DEVICE_TABLE(of, tvp7002_of_match); | ||
| 1137 | #endif | ||
| 1138 | |||
| 1081 | /* I2C driver data */ | 1139 | /* I2C driver data */ |
| 1082 | static struct i2c_driver tvp7002_driver = { | 1140 | static struct i2c_driver tvp7002_driver = { |
| 1083 | .driver = { | 1141 | .driver = { |
| 1142 | .of_match_table = of_match_ptr(tvp7002_of_match), | ||
| 1084 | .owner = THIS_MODULE, | 1143 | .owner = THIS_MODULE, |
| 1085 | .name = TVP7002_MODULE_NAME, | 1144 | .name = TVP7002_MODULE_NAME, |
| 1086 | }, | 1145 | }, |
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index cb30ffbd5ba8..2c286c307145 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/bitmap.h> | ||
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 25 | #include <media/media-entity.h> | 26 | #include <media/media-entity.h> |
| @@ -121,7 +122,6 @@ static struct media_entity *stack_pop(struct media_entity_graph *graph) | |||
| 121 | return entity; | 122 | return entity; |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 124 | #define stack_peek(en) ((en)->stack[(en)->top - 1].entity) | ||
| 125 | #define link_top(en) ((en)->stack[(en)->top].link) | 125 | #define link_top(en) ((en)->stack[(en)->top].link) |
| 126 | #define stack_top(en) ((en)->stack[(en)->top].entity) | 126 | #define stack_top(en) ((en)->stack[(en)->top].entity) |
| 127 | 127 | ||
| @@ -140,6 +140,12 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph, | |||
| 140 | { | 140 | { |
| 141 | graph->top = 0; | 141 | graph->top = 0; |
| 142 | graph->stack[graph->top].entity = NULL; | 142 | graph->stack[graph->top].entity = NULL; |
| 143 | bitmap_zero(graph->entities, MEDIA_ENTITY_ENUM_MAX_ID); | ||
| 144 | |||
| 145 | if (WARN_ON(entity->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
| 146 | return; | ||
| 147 | |||
| 148 | __set_bit(entity->id, graph->entities); | ||
| 143 | stack_push(graph, entity); | 149 | stack_push(graph, entity); |
| 144 | } | 150 | } |
| 145 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); | 151 | EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); |
| @@ -180,9 +186,11 @@ media_entity_graph_walk_next(struct media_entity_graph *graph) | |||
| 180 | 186 | ||
| 181 | /* Get the entity in the other end of the link . */ | 187 | /* Get the entity in the other end of the link . */ |
| 182 | next = media_entity_other(entity, link); | 188 | next = media_entity_other(entity, link); |
| 189 | if (WARN_ON(next->id >= MEDIA_ENTITY_ENUM_MAX_ID)) | ||
| 190 | return NULL; | ||
| 183 | 191 | ||
| 184 | /* Was it the entity we came here from? */ | 192 | /* Has the entity already been visited? */ |
| 185 | if (next == stack_peek(graph)) { | 193 | if (__test_and_set_bit(next->id, graph->entities)) { |
| 186 | link_top(graph)++; | 194 | link_top(graph)++; |
| 187 | continue; | 195 | continue; |
| 188 | } | 196 | } |
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index e564aac0aa30..d85cb0ace4dc 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c | |||
| @@ -4441,9 +4441,7 @@ static void tibetCS16_init(struct bttv *btv) | |||
| 4441 | * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical | 4441 | * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical |
| 4442 | * unit 3, the second (which is the master) is logical unit 0, etc. | 4442 | * unit 3, the second (which is the master) is logical unit 0, etc. |
| 4443 | * We need to maintain the status of the analog switch (which of the 16 | 4443 | * We need to maintain the status of the analog switch (which of the 16 |
| 4444 | * cameras is connected to which of the 4 controllers). Rather than | 4444 | * cameras is connected to which of the 4 controllers) in sw_status array. |
| 4445 | * add to the bttv structure for this, we use the data reserved for | ||
| 4446 | * the mbox (unused for this card type). | ||
| 4447 | */ | 4445 | */ |
| 4448 | 4446 | ||
| 4449 | /* | 4447 | /* |
| @@ -4478,7 +4476,6 @@ static void kodicom4400r_write(struct bttv *btv, | |||
| 4478 | */ | 4476 | */ |
| 4479 | static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | 4477 | static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) |
| 4480 | { | 4478 | { |
| 4481 | char *sw_status; | ||
| 4482 | int xaddr, yaddr; | 4479 | int xaddr, yaddr; |
| 4483 | struct bttv *mctlr; | 4480 | struct bttv *mctlr; |
| 4484 | static unsigned char map[4] = {3, 0, 2, 1}; | 4481 | static unsigned char map[4] = {3, 0, 2, 1}; |
| @@ -4489,14 +4486,13 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | |||
| 4489 | } | 4486 | } |
| 4490 | yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ | 4487 | yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ |
| 4491 | yaddr = map[yaddr]; | 4488 | yaddr = map[yaddr]; |
| 4492 | sw_status = (char *)(&mctlr->mbox_we); | ||
| 4493 | xaddr = input & 0xf; | 4489 | xaddr = input & 0xf; |
| 4494 | /* Check if the controller/camera pair has changed, else ignore */ | 4490 | /* Check if the controller/camera pair has changed, else ignore */ |
| 4495 | if (sw_status[yaddr] != xaddr) | 4491 | if (mctlr->sw_status[yaddr] != xaddr) |
| 4496 | { | 4492 | { |
| 4497 | /* "open" the old switch, "close" the new one, save the new */ | 4493 | /* "open" the old switch, "close" the new one, save the new */ |
| 4498 | kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); | 4494 | kodicom4400r_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0); |
| 4499 | sw_status[yaddr] = xaddr; | 4495 | mctlr->sw_status[yaddr] = xaddr; |
| 4500 | kodicom4400r_write(mctlr, xaddr, yaddr, 1); | 4496 | kodicom4400r_write(mctlr, xaddr, yaddr, 1); |
| 4501 | } | 4497 | } |
| 4502 | } | 4498 | } |
| @@ -4509,7 +4505,6 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) | |||
| 4509 | */ | 4505 | */ |
| 4510 | static void kodicom4400r_init(struct bttv *btv) | 4506 | static void kodicom4400r_init(struct bttv *btv) |
| 4511 | { | 4507 | { |
| 4512 | char *sw_status = (char *)(&btv->mbox_we); | ||
| 4513 | int ix; | 4508 | int ix; |
| 4514 | 4509 | ||
| 4515 | gpio_inout(0x0003ff, 0x0003ff); | 4510 | gpio_inout(0x0003ff, 0x0003ff); |
| @@ -4517,7 +4512,7 @@ static void kodicom4400r_init(struct bttv *btv) | |||
| 4517 | gpio_write(0); | 4512 | gpio_write(0); |
| 4518 | /* Preset camera 0 to the 4 controllers */ | 4513 | /* Preset camera 0 to the 4 controllers */ |
| 4519 | for (ix = 0; ix < 4; ix++) { | 4514 | for (ix = 0; ix < 4; ix++) { |
| 4520 | sw_status[ix] = ix; | 4515 | btv->sw_status[ix] = ix; |
| 4521 | kodicom4400r_write(btv, ix, ix, 1); | 4516 | kodicom4400r_write(btv, ix, ix, 1); |
| 4522 | } | 4517 | } |
| 4523 | /* | 4518 | /* |
| @@ -4794,7 +4789,6 @@ static void gv800s_write(struct bttv *btv, | |||
| 4794 | static void gv800s_muxsel(struct bttv *btv, unsigned int input) | 4789 | static void gv800s_muxsel(struct bttv *btv, unsigned int input) |
| 4795 | { | 4790 | { |
| 4796 | struct bttv *mctlr; | 4791 | struct bttv *mctlr; |
| 4797 | char *sw_status; | ||
| 4798 | int xaddr, yaddr; | 4792 | int xaddr, yaddr; |
| 4799 | static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, | 4793 | static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, |
| 4800 | { 0x1, 0x5, 0xb, 0x7 }, | 4794 | { 0x1, 0x5, 0xb, 0x7 }, |
| @@ -4807,14 +4801,13 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input) | |||
| 4807 | return; | 4801 | return; |
| 4808 | } | 4802 | } |
| 4809 | yaddr = (btv->c.nr - mctlr->c.nr) & 3; | 4803 | yaddr = (btv->c.nr - mctlr->c.nr) & 3; |
| 4810 | sw_status = (char *)(&mctlr->mbox_we); | ||
| 4811 | xaddr = map[yaddr][input] & 0xf; | 4804 | xaddr = map[yaddr][input] & 0xf; |
| 4812 | 4805 | ||
| 4813 | /* Check if the controller/camera pair has changed, ignore otherwise */ | 4806 | /* Check if the controller/camera pair has changed, ignore otherwise */ |
| 4814 | if (sw_status[yaddr] != xaddr) { | 4807 | if (mctlr->sw_status[yaddr] != xaddr) { |
| 4815 | /* disable the old switch, enable the new one and save status */ | 4808 | /* disable the old switch, enable the new one and save status */ |
| 4816 | gv800s_write(mctlr, sw_status[yaddr], yaddr, 0); | 4809 | gv800s_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0); |
| 4817 | sw_status[yaddr] = xaddr; | 4810 | mctlr->sw_status[yaddr] = xaddr; |
| 4818 | gv800s_write(mctlr, xaddr, yaddr, 1); | 4811 | gv800s_write(mctlr, xaddr, yaddr, 1); |
| 4819 | } | 4812 | } |
| 4820 | } | 4813 | } |
| @@ -4822,7 +4815,6 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input) | |||
| 4822 | /* GeoVision GV-800(S) "master" chip init */ | 4815 | /* GeoVision GV-800(S) "master" chip init */ |
| 4823 | static void gv800s_init(struct bttv *btv) | 4816 | static void gv800s_init(struct bttv *btv) |
| 4824 | { | 4817 | { |
| 4825 | char *sw_status = (char *)(&btv->mbox_we); | ||
| 4826 | int ix; | 4818 | int ix; |
| 4827 | 4819 | ||
| 4828 | gpio_inout(0xf107f, 0xf107f); | 4820 | gpio_inout(0xf107f, 0xf107f); |
| @@ -4831,7 +4823,7 @@ static void gv800s_init(struct bttv *btv) | |||
| 4831 | 4823 | ||
| 4832 | /* Preset camera 0 to the 4 controllers */ | 4824 | /* Preset camera 0 to the 4 controllers */ |
| 4833 | for (ix = 0; ix < 4; ix++) { | 4825 | for (ix = 0; ix < 4; ix++) { |
| 4834 | sw_status[ix] = ix; | 4826 | btv->sw_status[ix] = ix; |
| 4835 | gv800s_write(btv, ix, ix, 1); | 4827 | gv800s_write(btv, ix, ix, 1); |
| 4836 | } | 4828 | } |
| 4837 | 4829 | ||
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 9c1cc2c50ee2..6eefb595d0fa 100644 --- a/drivers/media/pci/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h | |||
| @@ -459,6 +459,9 @@ struct bttv { | |||
| 459 | int mbox_iow; | 459 | int mbox_iow; |
| 460 | int mbox_csel; | 460 | int mbox_csel; |
| 461 | 461 | ||
| 462 | /* switch status for multi-controller cards */ | ||
| 463 | char sw_status[4]; | ||
| 464 | |||
| 462 | /* risc memory management data | 465 | /* risc memory management data |
| 463 | - must acquire s_lock before changing these | 466 | - must acquire s_lock before changing these |
| 464 | - only the irq handler is supported to touch top + bottom + vcurr */ | 467 | - only the irq handler is supported to touch top + bottom + vcurr */ |
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index b3688aa8acc3..5104c802f72f 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig | |||
| @@ -29,6 +29,7 @@ config VIDEO_CX23885 | |||
| 29 | select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT | 29 | select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT |
| 30 | select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT | 30 | select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT |
| 31 | select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT | 31 | select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT |
| 32 | select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT | ||
| 32 | select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT | 33 | select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT |
| 33 | select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT | 34 | select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT |
| 34 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | 35 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT |
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c index e958a01fd554..c443b7ac5adf 100644 --- a/drivers/media/pci/cx23885/cx23885-av.c +++ b/drivers/media/pci/cx23885/cx23885-av.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include "cx23885.h" | 24 | #include "cx23885.h" |
| 25 | #include "cx23885-av.h" | 25 | #include "cx23885-av.h" |
| 26 | #include "cx23885-video.h" | ||
| 26 | 27 | ||
| 27 | void cx23885_av_work_handler(struct work_struct *work) | 28 | void cx23885_av_work_handler(struct work_struct *work) |
| 28 | { | 29 | { |
| @@ -32,5 +33,17 @@ void cx23885_av_work_handler(struct work_struct *work) | |||
| 32 | 33 | ||
| 33 | v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, | 34 | v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, |
| 34 | PCI_MSK_AV_CORE, &handled); | 35 | PCI_MSK_AV_CORE, &handled); |
| 36 | |||
| 37 | /* Getting here with the interrupt not handled | ||
| 38 | then probbaly flatiron does have pending interrupts. | ||
| 39 | */ | ||
| 40 | if (!handled) { | ||
| 41 | /* clear left and right adc channel interrupt request flag */ | ||
| 42 | cx23885_flatiron_write(dev, 0x1f, | ||
| 43 | cx23885_flatiron_read(dev, 0x1f) | 0x80); | ||
| 44 | cx23885_flatiron_write(dev, 0x23, | ||
| 45 | cx23885_flatiron_read(dev, 0x23) | 0x80); | ||
| 46 | } | ||
| 47 | |||
| 35 | cx23885_irq_enable(dev, PCI_MSK_AV_CORE); | 48 | cx23885_irq_enable(dev, PCI_MSK_AV_CORE); |
| 36 | } | 49 | } |
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 7e923f8dd2f5..6a71a965e757 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c | |||
| @@ -528,11 +528,12 @@ struct cx23885_board cx23885_boards[] = { | |||
| 528 | } }, | 528 | } }, |
| 529 | }, | 529 | }, |
| 530 | [CX23885_BOARD_MYGICA_X8507] = { | 530 | [CX23885_BOARD_MYGICA_X8507] = { |
| 531 | .name = "Mygica X8507", | 531 | .name = "Mygica X8502/X8507 ISDB-T", |
| 532 | .tuner_type = TUNER_XC5000, | 532 | .tuner_type = TUNER_XC5000, |
| 533 | .tuner_addr = 0x61, | 533 | .tuner_addr = 0x61, |
| 534 | .tuner_bus = 1, | 534 | .tuner_bus = 1, |
| 535 | .porta = CX23885_ANALOG_VIDEO, | 535 | .porta = CX23885_ANALOG_VIDEO, |
| 536 | .portb = CX23885_MPEG_DVB, | ||
| 536 | .input = { | 537 | .input = { |
| 537 | { | 538 | { |
| 538 | .type = CX23885_VMUX_TELEVISION, | 539 | .type = CX23885_VMUX_TELEVISION, |
| @@ -1281,7 +1282,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
| 1281 | case CX23885_BOARD_MYGICA_X8507: | 1282 | case CX23885_BOARD_MYGICA_X8507: |
| 1282 | /* GPIO-0 (0)Analog / (1)Digital TV */ | 1283 | /* GPIO-0 (0)Analog / (1)Digital TV */ |
| 1283 | /* GPIO-1 reset XC5000 */ | 1284 | /* GPIO-1 reset XC5000 */ |
| 1284 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ | 1285 | /* GPIO-2 demod reset */ |
| 1285 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); | 1286 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); |
| 1286 | cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); | 1287 | cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); |
| 1287 | mdelay(100); | 1288 | mdelay(100); |
| @@ -1677,6 +1678,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
| 1677 | break; | 1678 | break; |
| 1678 | case CX23885_BOARD_MYGICA_X8506: | 1679 | case CX23885_BOARD_MYGICA_X8506: |
| 1679 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1680 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
| 1681 | case CX23885_BOARD_MYGICA_X8507: | ||
| 1680 | ts1->gen_ctrl_val = 0x5; /* Parallel */ | 1682 | ts1->gen_ctrl_val = 0x5; /* Parallel */ |
| 1681 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1683 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
| 1682 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1684 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 268654ac9a9f..9f63d93239ec 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c | |||
| @@ -1941,10 +1941,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
| 1941 | 1941 | ||
| 1942 | if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) { | 1942 | if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) { |
| 1943 | cx23885_irq_disable(dev, PCI_MSK_AV_CORE); | 1943 | cx23885_irq_disable(dev, PCI_MSK_AV_CORE); |
| 1944 | if (!schedule_work(&dev->cx25840_work)) | 1944 | schedule_work(&dev->cx25840_work); |
| 1945 | printk(KERN_ERR "%s: failed to set up deferred work for" | ||
| 1946 | " AV Core/IR interrupt. Interrupt is disabled" | ||
| 1947 | " and won't be re-enabled\n", dev->name); | ||
| 1948 | handled++; | 1945 | handled++; |
| 1949 | } | 1946 | } |
| 1950 | 1947 | ||
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 9c5ed10b2c5e..971e4ff1b87f 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c | |||
| @@ -69,6 +69,7 @@ | |||
| 69 | #include "stb6100_cfg.h" | 69 | #include "stb6100_cfg.h" |
| 70 | #include "tda10071.h" | 70 | #include "tda10071.h" |
| 71 | #include "a8293.h" | 71 | #include "a8293.h" |
| 72 | #include "mb86a20s.h" | ||
| 72 | 73 | ||
| 73 | static unsigned int debug; | 74 | static unsigned int debug; |
| 74 | 75 | ||
| @@ -119,8 +120,6 @@ static void dvb_buf_release(struct videobuf_queue *q, | |||
| 119 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); | 120 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe); | ||
| 123 | |||
| 124 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | 123 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) |
| 125 | { | 124 | { |
| 126 | struct videobuf_dvb_frontends *f; | 125 | struct videobuf_dvb_frontends *f; |
| @@ -135,12 +134,6 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | |||
| 135 | 134 | ||
| 136 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) | 135 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) |
| 137 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); | 136 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); |
| 138 | |||
| 139 | /* | ||
| 140 | * FIXME: Improve this path to avoid calling the | ||
| 141 | * cx23885_dvb_set_frontend() every time it passes here. | ||
| 142 | */ | ||
| 143 | cx23885_dvb_set_frontend(fe->dvb.frontend); | ||
| 144 | } | 137 | } |
| 145 | 138 | ||
| 146 | static struct videobuf_queue_ops dvb_qops = { | 139 | static struct videobuf_queue_ops dvb_qops = { |
| @@ -500,6 +493,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = { | |||
| 500 | .if_khz = 5380, | 493 | .if_khz = 5380, |
| 501 | }; | 494 | }; |
| 502 | 495 | ||
| 496 | static struct mb86a20s_config mygica_x8507_mb86a20s_config = { | ||
| 497 | .demod_address = 0x10, | ||
| 498 | }; | ||
| 499 | |||
| 500 | static struct xc5000_config mygica_x8507_xc5000_config = { | ||
| 501 | .i2c_address = 0x61, | ||
| 502 | .if_khz = 4000, | ||
| 503 | }; | ||
| 504 | |||
| 503 | static struct stv090x_config prof_8000_stv090x_config = { | 505 | static struct stv090x_config prof_8000_stv090x_config = { |
| 504 | .device = STV0903, | 506 | .device = STV0903, |
| 505 | .demod_mode = STV090x_SINGLE, | 507 | .demod_mode = STV090x_SINGLE, |
| @@ -556,14 +558,27 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) | |||
| 556 | } | 558 | } |
| 557 | break; | 559 | break; |
| 558 | case CX23885_BOARD_MYGICA_X8506: | 560 | case CX23885_BOARD_MYGICA_X8506: |
| 561 | case CX23885_BOARD_MYGICA_X8507: | ||
| 559 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 562 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
| 560 | /* Select Digital TV */ | 563 | /* Select Digital TV */ |
| 561 | cx23885_gpio_set(dev, GPIO_0); | 564 | cx23885_gpio_set(dev, GPIO_0); |
| 562 | break; | 565 | break; |
| 563 | } | 566 | } |
| 567 | |||
| 568 | /* Call the real set_frontend */ | ||
| 569 | if (port->set_frontend) | ||
| 570 | return port->set_frontend(fe); | ||
| 571 | |||
| 564 | return 0; | 572 | return 0; |
| 565 | } | 573 | } |
| 566 | 574 | ||
| 575 | static void cx23885_set_frontend_hook(struct cx23885_tsport *port, | ||
| 576 | struct dvb_frontend *fe) | ||
| 577 | { | ||
| 578 | port->set_frontend = fe->ops.set_frontend; | ||
| 579 | fe->ops.set_frontend = cx23885_dvb_set_frontend; | ||
| 580 | } | ||
| 581 | |||
| 567 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { | 582 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { |
| 568 | .prod = LGS8GXX_PROD_LGS8G75, | 583 | .prod = LGS8GXX_PROD_LGS8G75, |
| 569 | .demod_address = 0x19, | 584 | .demod_address = 0x19, |
| @@ -771,6 +786,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 771 | 0x60, &dev->i2c_bus[1].i2c_adap, | 786 | 0x60, &dev->i2c_bus[1].i2c_adap, |
| 772 | &hauppauge_hvr127x_config); | 787 | &hauppauge_hvr127x_config); |
| 773 | } | 788 | } |
| 789 | if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1275) | ||
| 790 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
| 774 | break; | 791 | break; |
| 775 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 792 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
| 776 | case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: | 793 | case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: |
| @@ -1106,6 +1123,21 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 1106 | &i2c_bus2->i2c_adap, | 1123 | &i2c_bus2->i2c_adap, |
| 1107 | &mygica_x8506_xc5000_config); | 1124 | &mygica_x8506_xc5000_config); |
| 1108 | } | 1125 | } |
| 1126 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
| 1127 | break; | ||
| 1128 | case CX23885_BOARD_MYGICA_X8507: | ||
| 1129 | i2c_bus = &dev->i2c_bus[0]; | ||
| 1130 | i2c_bus2 = &dev->i2c_bus[1]; | ||
| 1131 | fe0->dvb.frontend = dvb_attach(mb86a20s_attach, | ||
| 1132 | &mygica_x8507_mb86a20s_config, | ||
| 1133 | &i2c_bus->i2c_adap); | ||
| 1134 | if (fe0->dvb.frontend != NULL) { | ||
| 1135 | dvb_attach(xc5000_attach, | ||
| 1136 | fe0->dvb.frontend, | ||
| 1137 | &i2c_bus2->i2c_adap, | ||
| 1138 | &mygica_x8507_xc5000_config); | ||
| 1139 | } | ||
| 1140 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
| 1109 | break; | 1141 | break; |
| 1110 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1142 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
| 1111 | i2c_bus = &dev->i2c_bus[0]; | 1143 | i2c_bus = &dev->i2c_bus[0]; |
| @@ -1119,6 +1151,7 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 1119 | &i2c_bus2->i2c_adap, | 1151 | &i2c_bus2->i2c_adap, |
| 1120 | &magicpro_prohdtve2_xc5000_config); | 1152 | &magicpro_prohdtve2_xc5000_config); |
| 1121 | } | 1153 | } |
| 1154 | cx23885_set_frontend_hook(port, fe0->dvb.frontend); | ||
| 1122 | break; | 1155 | break; |
| 1123 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1156 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
| 1124 | i2c_bus = &dev->i2c_bus[0]; | 1157 | i2c_bus = &dev->i2c_bus[0]; |
| @@ -1249,6 +1282,10 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 1249 | fe0->dvb.frontend = dvb_attach(ds3000_attach, | 1282 | fe0->dvb.frontend = dvb_attach(ds3000_attach, |
| 1250 | &tevii_ds3000_config, | 1283 | &tevii_ds3000_config, |
| 1251 | &i2c_bus->i2c_adap); | 1284 | &i2c_bus->i2c_adap); |
| 1285 | if (fe0->dvb.frontend != NULL) { | ||
| 1286 | dvb_attach(ts2020_attach, fe0->dvb.frontend, | ||
| 1287 | &tevii_ts2020_config, &i2c_bus->i2c_adap); | ||
| 1288 | } | ||
| 1252 | break; | 1289 | break; |
| 1253 | case CX23885_BOARD_PROF_8000: | 1290 | case CX23885_BOARD_PROF_8000: |
| 1254 | i2c_bus = &dev->i2c_bus[0]; | 1291 | i2c_bus = &dev->i2c_bus[0]; |
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index e33d1a7dfdd0..161686832b20 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <asm/div64.h> | 32 | #include <asm/div64.h> |
| 33 | 33 | ||
| 34 | #include "cx23885.h" | 34 | #include "cx23885.h" |
| 35 | #include "cx23885-video.h" | ||
| 35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 36 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
| 37 | #include "cx23885-ioctl.h" | 38 | #include "cx23885-ioctl.h" |
| @@ -417,7 +418,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, | |||
| 417 | mutex_unlock(&dev->lock); | 418 | mutex_unlock(&dev->lock); |
| 418 | } | 419 | } |
| 419 | 420 | ||
| 420 | static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) | 421 | int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) |
| 421 | { | 422 | { |
| 422 | /* 8 bit registers, 8 bit values */ | 423 | /* 8 bit registers, 8 bit values */ |
| 423 | u8 buf[] = { reg, data }; | 424 | u8 buf[] = { reg, data }; |
| @@ -428,7 +429,7 @@ static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data) | |||
| 428 | return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); | 429 | return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1); |
| 429 | } | 430 | } |
| 430 | 431 | ||
| 431 | static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg) | 432 | u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg) |
| 432 | { | 433 | { |
| 433 | /* 8 bit registers, 8 bit values */ | 434 | /* 8 bit registers, 8 bit values */ |
| 434 | int ret; | 435 | int ret; |
diff --git a/drivers/media/pci/cx23885/cx23885-video.h b/drivers/media/pci/cx23885/cx23885-video.h new file mode 100644 index 000000000000..c961a2b0de0f --- /dev/null +++ b/drivers/media/pci/cx23885/cx23885-video.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version 2 | ||
| 9 | * of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
| 19 | * 02110-1301, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _CX23885_VIDEO_H_ | ||
| 23 | #define _CX23885_VIDEO_H_ | ||
| 24 | int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data); | ||
| 25 | u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg); | ||
| 26 | #endif | ||
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 5687d3f678db..038caf53908b 100644 --- a/drivers/media/pci/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h | |||
| @@ -320,6 +320,8 @@ struct cx23885_tsport { | |||
| 320 | 320 | ||
| 321 | /* Workaround for a temp dvb_frontend that the tuner can attached to */ | 321 | /* Workaround for a temp dvb_frontend that the tuner can attached to */ |
| 322 | struct dvb_frontend analog_fe; | 322 | struct dvb_frontend analog_fe; |
| 323 | |||
| 324 | int (*set_frontend)(struct dvb_frontend *fe); | ||
| 323 | }; | 325 | }; |
| 324 | 326 | ||
| 325 | struct cx23885_kernel_ir { | 327 | struct cx23885_kernel_ir { |
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index bb05eca2da29..a63a9ad163b2 100644 --- a/drivers/media/pci/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig | |||
| @@ -72,9 +72,9 @@ config VIDEO_CX88_DVB | |||
| 72 | To compile this driver as a module, choose M here: the | 72 | To compile this driver as a module, choose M here: the |
| 73 | module will be called cx88-dvb. | 73 | module will be called cx88-dvb. |
| 74 | 74 | ||
| 75 | config VIDEO_CX88_VP3054 | 75 | config VIDEO_CX88_ENABLE_VP3054 |
| 76 | tristate "VP-3054 Secondary I2C Bus Support" | 76 | bool "VP-3054 Secondary I2C Bus Support" |
| 77 | default m | 77 | default y |
| 78 | depends on VIDEO_CX88_DVB && DVB_MT352 | 78 | depends on VIDEO_CX88_DVB && DVB_MT352 |
| 79 | ---help--- | 79 | ---help--- |
| 80 | This adds DVB-T support for cards based on the | 80 | This adds DVB-T support for cards based on the |
| @@ -82,6 +82,11 @@ config VIDEO_CX88_VP3054 | |||
| 82 | which also require support for the VP-3054 | 82 | which also require support for the VP-3054 |
| 83 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. | 83 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. |
| 84 | 84 | ||
| 85 | config VIDEO_CX88_VP3054 | ||
| 86 | tristate | ||
| 87 | depends on VIDEO_CX88_DVB && VIDEO_CX88_ENABLE_VP3054 | ||
| 88 | default y | ||
| 89 | |||
| 85 | config VIDEO_CX88_MPEG | 90 | config VIDEO_CX88_MPEG |
| 86 | tristate | 91 | tristate |
| 87 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD | 92 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD |
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index afe0eaea81b4..28893a6b249e 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h | |||
| @@ -259,7 +259,7 @@ struct cx88_input { | |||
| 259 | }; | 259 | }; |
| 260 | 260 | ||
| 261 | enum cx88_audio_chip { | 261 | enum cx88_audio_chip { |
| 262 | CX88_AUDIO_WM8775, | 262 | CX88_AUDIO_WM8775 = 1, |
| 263 | CX88_AUDIO_TVAUDIO, | 263 | CX88_AUDIO_TVAUDIO, |
| 264 | }; | 264 | }; |
| 265 | 265 | ||
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 08de865cc399..8068d7b64155 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig | |||
| @@ -203,13 +203,23 @@ config VIDEO_SAMSUNG_EXYNOS_GSC | |||
| 203 | 203 | ||
| 204 | config VIDEO_SH_VEU | 204 | config VIDEO_SH_VEU |
| 205 | tristate "SuperH VEU mem2mem video processing driver" | 205 | tristate "SuperH VEU mem2mem video processing driver" |
| 206 | depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS | 206 | depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS && HAS_DMA |
| 207 | select VIDEOBUF2_DMA_CONTIG | 207 | select VIDEOBUF2_DMA_CONTIG |
| 208 | select V4L2_MEM2MEM_DEV | 208 | select V4L2_MEM2MEM_DEV |
| 209 | help | 209 | help |
| 210 | Support for the Video Engine Unit (VEU) on SuperH and | 210 | Support for the Video Engine Unit (VEU) on SuperH and |
| 211 | SH-Mobile SoCs. | 211 | SH-Mobile SoCs. |
| 212 | 212 | ||
| 213 | config VIDEO_RENESAS_VSP1 | ||
| 214 | tristate "Renesas VSP1 Video Processing Engine" | ||
| 215 | depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | ||
| 216 | select VIDEOBUF2_DMA_CONTIG | ||
| 217 | ---help--- | ||
| 218 | This is a V4L2 driver for the Renesas VSP1 video processing engine. | ||
| 219 | |||
| 220 | To compile this driver as a module, choose M here: the module | ||
| 221 | will be called vsp1. | ||
| 222 | |||
| 213 | endif # V4L_MEM2MEM_DRIVERS | 223 | endif # V4L_MEM2MEM_DRIVERS |
| 214 | 224 | ||
| 215 | menuconfig V4L_TEST_DRIVERS | 225 | menuconfig V4L_TEST_DRIVERS |
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index eee28dd78d7d..4e4da482c522 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile | |||
| @@ -46,6 +46,8 @@ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o | |||
| 46 | 46 | ||
| 47 | obj-$(CONFIG_SOC_CAMERA) += soc_camera/ | 47 | obj-$(CONFIG_SOC_CAMERA) += soc_camera/ |
| 48 | 48 | ||
| 49 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ | ||
| 50 | |||
| 49 | obj-y += davinci/ | 51 | obj-y += davinci/ |
| 50 | 52 | ||
| 51 | obj-$(CONFIG_ARCH_OMAP) += omap/ | 53 | obj-$(CONFIG_ARCH_OMAP) += omap/ |
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 7f838c681cea..4c1105977090 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c | |||
| @@ -388,13 +388,8 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
| 388 | 388 | ||
| 389 | params.hdelay = bt->hsync + bt->hbackporch; | 389 | params.hdelay = bt->hsync + bt->hbackporch; |
| 390 | params.vdelay = bt->vsync + bt->vbackporch; | 390 | params.vdelay = bt->vsync + bt->vbackporch; |
| 391 | params.line = bt->hfrontporch + bt->hsync | 391 | params.line = V4L2_DV_BT_FRAME_WIDTH(bt); |
| 392 | + bt->hbackporch + bt->width; | 392 | params.frame = V4L2_DV_BT_FRAME_HEIGHT(bt); |
| 393 | params.frame = bt->vfrontporch + bt->vsync | ||
| 394 | + bt->vbackporch + bt->height; | ||
| 395 | if (bt->interlaced) | ||
| 396 | params.frame += bt->il_vfrontporch + bt->il_vsync | ||
| 397 | + bt->il_vbackporch; | ||
| 398 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities | 393 | } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities |
| 399 | & V4L2_IN_CAP_STD) { | 394 | & V4L2_IN_CAP_STD) { |
| 400 | params.hdelay = 0; | 395 | params.hdelay = 0; |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index bd9405df1bd6..449d2fec9e87 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
| 21 | #include <linux/kfifo.h> | ||
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
| 23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | 29 | ||
| 29 | #include <media/v4l2-ctrls.h> | 30 | #include <media/v4l2-ctrls.h> |
| 30 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
| 32 | #include <media/v4l2-event.h> | ||
| 31 | #include <media/v4l2-ioctl.h> | 33 | #include <media/v4l2-ioctl.h> |
| 32 | #include <media/v4l2-mem2mem.h> | 34 | #include <media/v4l2-mem2mem.h> |
| 33 | #include <media/videobuf2-core.h> | 35 | #include <media/videobuf2-core.h> |
| @@ -41,13 +43,16 @@ | |||
| 41 | 43 | ||
| 42 | #define CODA_FMO_BUF_SIZE 32 | 44 | #define CODA_FMO_BUF_SIZE 32 |
| 43 | #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) | 45 | #define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) |
| 44 | #define CODA7_WORK_BUF_SIZE (512 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) | 46 | #define CODA7_WORK_BUF_SIZE (128 * 1024) |
| 47 | #define CODA7_TEMP_BUF_SIZE (304 * 1024) | ||
| 45 | #define CODA_PARA_BUF_SIZE (10 * 1024) | 48 | #define CODA_PARA_BUF_SIZE (10 * 1024) |
| 46 | #define CODA_ISRAM_SIZE (2048 * 2) | 49 | #define CODA_ISRAM_SIZE (2048 * 2) |
| 47 | #define CODADX6_IRAM_SIZE 0xb000 | 50 | #define CODADX6_IRAM_SIZE 0xb000 |
| 48 | #define CODA7_IRAM_SIZE 0x14000 /* 81920 bytes */ | 51 | #define CODA7_IRAM_SIZE 0x14000 |
| 49 | 52 | ||
| 50 | #define CODA_MAX_FRAMEBUFFERS 2 | 53 | #define CODA7_PS_BUF_SIZE 0x28000 |
| 54 | |||
| 55 | #define CODA_MAX_FRAMEBUFFERS 8 | ||
| 51 | 56 | ||
| 52 | #define MAX_W 8192 | 57 | #define MAX_W 8192 |
| 53 | #define MAX_H 8192 | 58 | #define MAX_H 8192 |
| @@ -129,6 +134,7 @@ struct coda_dev { | |||
| 129 | struct clk *clk_ahb; | 134 | struct clk *clk_ahb; |
| 130 | 135 | ||
| 131 | struct coda_aux_buf codebuf; | 136 | struct coda_aux_buf codebuf; |
| 137 | struct coda_aux_buf tempbuf; | ||
| 132 | struct coda_aux_buf workbuf; | 138 | struct coda_aux_buf workbuf; |
| 133 | struct gen_pool *iram_pool; | 139 | struct gen_pool *iram_pool; |
| 134 | long unsigned int iram_vaddr; | 140 | long unsigned int iram_vaddr; |
| @@ -153,6 +159,7 @@ struct coda_params { | |||
| 153 | u8 mpeg4_inter_qp; | 159 | u8 mpeg4_inter_qp; |
| 154 | u8 gop_size; | 160 | u8 gop_size; |
| 155 | int codec_mode; | 161 | int codec_mode; |
| 162 | int codec_mode_aux; | ||
| 156 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; | 163 | enum v4l2_mpeg_video_multi_slice_mode slice_mode; |
| 157 | u32 framerate; | 164 | u32 framerate; |
| 158 | u16 bitrate; | 165 | u16 bitrate; |
| @@ -160,13 +167,30 @@ struct coda_params { | |||
| 160 | u32 slice_max_mb; | 167 | u32 slice_max_mb; |
| 161 | }; | 168 | }; |
| 162 | 169 | ||
| 170 | struct coda_iram_info { | ||
| 171 | u32 axi_sram_use; | ||
| 172 | phys_addr_t buf_bit_use; | ||
| 173 | phys_addr_t buf_ip_ac_dc_use; | ||
| 174 | phys_addr_t buf_dbk_y_use; | ||
| 175 | phys_addr_t buf_dbk_c_use; | ||
| 176 | phys_addr_t buf_ovl_use; | ||
| 177 | phys_addr_t buf_btp_use; | ||
| 178 | phys_addr_t search_ram_paddr; | ||
| 179 | int search_ram_size; | ||
| 180 | }; | ||
| 181 | |||
| 163 | struct coda_ctx { | 182 | struct coda_ctx { |
| 164 | struct coda_dev *dev; | 183 | struct coda_dev *dev; |
| 184 | struct mutex buffer_mutex; | ||
| 165 | struct list_head list; | 185 | struct list_head list; |
| 186 | struct work_struct skip_run; | ||
| 166 | int aborting; | 187 | int aborting; |
| 188 | int initialized; | ||
| 167 | int streamon_out; | 189 | int streamon_out; |
| 168 | int streamon_cap; | 190 | int streamon_cap; |
| 169 | u32 isequence; | 191 | u32 isequence; |
| 192 | u32 qsequence; | ||
| 193 | u32 osequence; | ||
| 170 | struct coda_q_data q_data[2]; | 194 | struct coda_q_data q_data[2]; |
| 171 | enum coda_inst_type inst_type; | 195 | enum coda_inst_type inst_type; |
| 172 | struct coda_codec *codec; | 196 | struct coda_codec *codec; |
| @@ -176,12 +200,25 @@ struct coda_ctx { | |||
| 176 | struct v4l2_ctrl_handler ctrls; | 200 | struct v4l2_ctrl_handler ctrls; |
| 177 | struct v4l2_fh fh; | 201 | struct v4l2_fh fh; |
| 178 | int gopcounter; | 202 | int gopcounter; |
| 203 | int runcounter; | ||
| 179 | char vpu_header[3][64]; | 204 | char vpu_header[3][64]; |
| 180 | int vpu_header_size[3]; | 205 | int vpu_header_size[3]; |
| 206 | struct kfifo bitstream_fifo; | ||
| 207 | struct mutex bitstream_mutex; | ||
| 208 | struct coda_aux_buf bitstream; | ||
| 209 | bool prescan_failed; | ||
| 181 | struct coda_aux_buf parabuf; | 210 | struct coda_aux_buf parabuf; |
| 211 | struct coda_aux_buf psbuf; | ||
| 212 | struct coda_aux_buf slicebuf; | ||
| 182 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; | 213 | struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; |
| 214 | struct coda_aux_buf workbuf; | ||
| 183 | int num_internal_frames; | 215 | int num_internal_frames; |
| 184 | int idx; | 216 | int idx; |
| 217 | int reg_idx; | ||
| 218 | struct coda_iram_info iram_info; | ||
| 219 | u32 bit_stream_param; | ||
| 220 | u32 frm_dis_flg; | ||
| 221 | int display_idx; | ||
| 185 | }; | 222 | }; |
| 186 | 223 | ||
| 187 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, | 224 | static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff, |
| @@ -228,10 +265,22 @@ static int coda_wait_timeout(struct coda_dev *dev) | |||
| 228 | static void coda_command_async(struct coda_ctx *ctx, int cmd) | 265 | static void coda_command_async(struct coda_ctx *ctx, int cmd) |
| 229 | { | 266 | { |
| 230 | struct coda_dev *dev = ctx->dev; | 267 | struct coda_dev *dev = ctx->dev; |
| 268 | |||
| 269 | if (dev->devtype->product == CODA_7541) { | ||
| 270 | /* Restore context related registers to CODA */ | ||
| 271 | coda_write(dev, ctx->bit_stream_param, | ||
| 272 | CODA_REG_BIT_BIT_STREAM_PARAM); | ||
| 273 | coda_write(dev, ctx->frm_dis_flg, | ||
| 274 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
| 275 | coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); | ||
| 276 | } | ||
| 277 | |||
| 231 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); | 278 | coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); |
| 232 | 279 | ||
| 233 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); | 280 | coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); |
| 234 | coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); | 281 | coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); |
| 282 | coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD); | ||
| 283 | |||
| 235 | coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); | 284 | coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); |
| 236 | } | 285 | } |
| 237 | 286 | ||
| @@ -297,6 +346,8 @@ static struct coda_codec codadx6_codecs[] = { | |||
| 297 | static struct coda_codec coda7_codecs[] = { | 346 | static struct coda_codec coda7_codecs[] = { |
| 298 | CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), | 347 | CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), |
| 299 | CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), | 348 | CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), |
| 349 | CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
| 350 | CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080), | ||
| 300 | }; | 351 | }; |
| 301 | 352 | ||
| 302 | static bool coda_format_is_yuv(u32 fourcc) | 353 | static bool coda_format_is_yuv(u32 fourcc) |
| @@ -365,7 +416,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 365 | } | 416 | } |
| 366 | 417 | ||
| 367 | static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | 418 | static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, |
| 368 | enum v4l2_buf_type type) | 419 | enum v4l2_buf_type type, int src_fourcc) |
| 369 | { | 420 | { |
| 370 | struct coda_ctx *ctx = fh_to_ctx(priv); | 421 | struct coda_ctx *ctx = fh_to_ctx(priv); |
| 371 | struct coda_codec *codecs = ctx->dev->devtype->codecs; | 422 | struct coda_codec *codecs = ctx->dev->devtype->codecs; |
| @@ -377,7 +428,8 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
| 377 | 428 | ||
| 378 | for (i = 0; i < num_formats; i++) { | 429 | for (i = 0; i < num_formats; i++) { |
| 379 | /* Both uncompressed formats are always supported */ | 430 | /* Both uncompressed formats are always supported */ |
| 380 | if (coda_format_is_yuv(formats[i].fourcc)) { | 431 | if (coda_format_is_yuv(formats[i].fourcc) && |
| 432 | !coda_format_is_yuv(src_fourcc)) { | ||
| 381 | if (num == f->index) | 433 | if (num == f->index) |
| 382 | break; | 434 | break; |
| 383 | ++num; | 435 | ++num; |
| @@ -385,8 +437,10 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
| 385 | } | 437 | } |
| 386 | /* Compressed formats may be supported, check the codec list */ | 438 | /* Compressed formats may be supported, check the codec list */ |
| 387 | for (k = 0; k < num_codecs; k++) { | 439 | for (k = 0; k < num_codecs; k++) { |
| 440 | /* if src_fourcc is set, only consider matching codecs */ | ||
| 388 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | 441 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && |
| 389 | formats[i].fourcc == codecs[k].dst_fourcc) | 442 | formats[i].fourcc == codecs[k].dst_fourcc && |
| 443 | (!src_fourcc || src_fourcc == codecs[k].src_fourcc)) | ||
| 390 | break; | 444 | break; |
| 391 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 445 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
| 392 | formats[i].fourcc == codecs[k].src_fourcc) | 446 | formats[i].fourcc == codecs[k].src_fourcc) |
| @@ -413,13 +467,26 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, | |||
| 413 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 467 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
| 414 | struct v4l2_fmtdesc *f) | 468 | struct v4l2_fmtdesc *f) |
| 415 | { | 469 | { |
| 416 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 470 | struct coda_ctx *ctx = fh_to_ctx(priv); |
| 471 | struct vb2_queue *src_vq; | ||
| 472 | struct coda_q_data *q_data_src; | ||
| 473 | |||
| 474 | /* If the source format is already fixed, only list matching formats */ | ||
| 475 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 476 | if (vb2_is_streaming(src_vq)) { | ||
| 477 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 478 | |||
| 479 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
| 480 | q_data_src->fourcc); | ||
| 481 | } | ||
| 482 | |||
| 483 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0); | ||
| 417 | } | 484 | } |
| 418 | 485 | ||
| 419 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, | 486 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, |
| 420 | struct v4l2_fmtdesc *f) | 487 | struct v4l2_fmtdesc *f) |
| 421 | { | 488 | { |
| 422 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 489 | return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0); |
| 423 | } | 490 | } |
| 424 | 491 | ||
| 425 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | 492 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) |
| @@ -492,15 +559,45 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 492 | struct v4l2_format *f) | 559 | struct v4l2_format *f) |
| 493 | { | 560 | { |
| 494 | struct coda_ctx *ctx = fh_to_ctx(priv); | 561 | struct coda_ctx *ctx = fh_to_ctx(priv); |
| 495 | struct coda_codec *codec = NULL; | 562 | struct coda_codec *codec; |
| 563 | struct vb2_queue *src_vq; | ||
| 564 | int ret; | ||
| 496 | 565 | ||
| 497 | /* Determine codec by the encoded format */ | 566 | /* |
| 498 | codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, | 567 | * If the source format is already fixed, try to find a codec that |
| 499 | f->fmt.pix.pixelformat); | 568 | * converts to the given destination format |
| 569 | */ | ||
| 570 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 571 | if (vb2_is_streaming(src_vq)) { | ||
| 572 | struct coda_q_data *q_data_src; | ||
| 573 | |||
| 574 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 575 | codec = coda_find_codec(ctx->dev, q_data_src->fourcc, | ||
| 576 | f->fmt.pix.pixelformat); | ||
| 577 | if (!codec) | ||
| 578 | return -EINVAL; | ||
| 579 | } else { | ||
| 580 | /* Otherwise determine codec by encoded format, if possible */ | ||
| 581 | codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, | ||
| 582 | f->fmt.pix.pixelformat); | ||
| 583 | } | ||
| 500 | 584 | ||
| 501 | f->fmt.pix.colorspace = ctx->colorspace; | 585 | f->fmt.pix.colorspace = ctx->colorspace; |
| 502 | 586 | ||
| 503 | return vidioc_try_fmt(codec, f); | 587 | ret = vidioc_try_fmt(codec, f); |
| 588 | if (ret < 0) | ||
| 589 | return ret; | ||
| 590 | |||
| 591 | /* The h.264 decoder only returns complete 16x16 macroblocks */ | ||
| 592 | if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) { | ||
| 593 | f->fmt.pix.width = round_up(f->fmt.pix.width, 16); | ||
| 594 | f->fmt.pix.height = round_up(f->fmt.pix.height, 16); | ||
| 595 | f->fmt.pix.bytesperline = f->fmt.pix.width; | ||
| 596 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * | ||
| 597 | f->fmt.pix.height * 3 / 2; | ||
| 598 | } | ||
| 599 | |||
| 600 | return 0; | ||
| 504 | } | 601 | } |
| 505 | 602 | ||
| 506 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, | 603 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, |
| @@ -610,11 +707,35 @@ static int vidioc_expbuf(struct file *file, void *priv, | |||
| 610 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); | 707 | return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); |
| 611 | } | 708 | } |
| 612 | 709 | ||
| 710 | static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx, | ||
| 711 | struct v4l2_buffer *buf) | ||
| 712 | { | ||
| 713 | struct vb2_queue *src_vq; | ||
| 714 | |||
| 715 | src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 716 | |||
| 717 | return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) && | ||
| 718 | (buf->sequence == (ctx->qsequence - 1))); | ||
| 719 | } | ||
| 720 | |||
| 613 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 721 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
| 614 | { | 722 | { |
| 615 | struct coda_ctx *ctx = fh_to_ctx(priv); | 723 | struct coda_ctx *ctx = fh_to_ctx(priv); |
| 724 | int ret; | ||
| 725 | |||
| 726 | ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
| 727 | |||
| 728 | /* If this is the last capture buffer, emit an end-of-stream event */ | ||
| 729 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
| 730 | coda_buf_is_end_of_stream(ctx, buf)) { | ||
| 731 | const struct v4l2_event eos_event = { | ||
| 732 | .type = V4L2_EVENT_EOS | ||
| 733 | }; | ||
| 616 | 734 | ||
| 617 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 735 | v4l2_event_queue_fh(&ctx->fh, &eos_event); |
| 736 | } | ||
| 737 | |||
| 738 | return ret; | ||
| 618 | } | 739 | } |
| 619 | 740 | ||
| 620 | static int vidioc_create_bufs(struct file *file, void *priv, | 741 | static int vidioc_create_bufs(struct file *file, void *priv, |
| @@ -637,8 +758,53 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
| 637 | enum v4l2_buf_type type) | 758 | enum v4l2_buf_type type) |
| 638 | { | 759 | { |
| 639 | struct coda_ctx *ctx = fh_to_ctx(priv); | 760 | struct coda_ctx *ctx = fh_to_ctx(priv); |
| 761 | int ret; | ||
| 640 | 762 | ||
| 641 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | 763 | /* |
| 764 | * This indirectly calls __vb2_queue_cancel, which dequeues all buffers. | ||
| 765 | * We therefore have to lock it against running hardware in this context, | ||
| 766 | * which still needs the buffers. | ||
| 767 | */ | ||
| 768 | mutex_lock(&ctx->buffer_mutex); | ||
| 769 | ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
| 770 | mutex_unlock(&ctx->buffer_mutex); | ||
| 771 | |||
| 772 | return ret; | ||
| 773 | } | ||
| 774 | |||
| 775 | static int vidioc_decoder_cmd(struct file *file, void *fh, | ||
| 776 | struct v4l2_decoder_cmd *dc) | ||
| 777 | { | ||
| 778 | struct coda_ctx *ctx = fh_to_ctx(fh); | ||
| 779 | |||
| 780 | if (dc->cmd != V4L2_DEC_CMD_STOP) | ||
| 781 | return -EINVAL; | ||
| 782 | |||
| 783 | if ((dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK) || | ||
| 784 | (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)) | ||
| 785 | return -EINVAL; | ||
| 786 | |||
| 787 | if (dc->stop.pts != 0) | ||
| 788 | return -EINVAL; | ||
| 789 | |||
| 790 | if (ctx->inst_type != CODA_INST_DECODER) | ||
| 791 | return -EINVAL; | ||
| 792 | |||
| 793 | /* Set the strem-end flag on this context */ | ||
| 794 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
| 795 | |||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 799 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | ||
| 800 | const struct v4l2_event_subscription *sub) | ||
| 801 | { | ||
| 802 | switch (sub->type) { | ||
| 803 | case V4L2_EVENT_EOS: | ||
| 804 | return v4l2_event_subscribe(fh, sub, 0, NULL); | ||
| 805 | default: | ||
| 806 | return v4l2_ctrl_subscribe_event(fh, sub); | ||
| 807 | } | ||
| 642 | } | 808 | } |
| 643 | 809 | ||
| 644 | static const struct v4l2_ioctl_ops coda_ioctl_ops = { | 810 | static const struct v4l2_ioctl_ops coda_ioctl_ops = { |
| @@ -664,14 +830,206 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { | |||
| 664 | 830 | ||
| 665 | .vidioc_streamon = vidioc_streamon, | 831 | .vidioc_streamon = vidioc_streamon, |
| 666 | .vidioc_streamoff = vidioc_streamoff, | 832 | .vidioc_streamoff = vidioc_streamoff, |
| 833 | |||
| 834 | .vidioc_decoder_cmd = vidioc_decoder_cmd, | ||
| 835 | |||
| 836 | .vidioc_subscribe_event = vidioc_subscribe_event, | ||
| 837 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
| 667 | }; | 838 | }; |
| 668 | 839 | ||
| 840 | static int coda_start_decoding(struct coda_ctx *ctx); | ||
| 841 | |||
| 842 | static void coda_skip_run(struct work_struct *work) | ||
| 843 | { | ||
| 844 | struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run); | ||
| 845 | |||
| 846 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | ||
| 847 | } | ||
| 848 | |||
| 849 | static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) | ||
| 850 | { | ||
| 851 | return kfifo_len(&ctx->bitstream_fifo); | ||
| 852 | } | ||
| 853 | |||
| 854 | static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) | ||
| 855 | { | ||
| 856 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
| 857 | struct coda_dev *dev = ctx->dev; | ||
| 858 | u32 rd_ptr; | ||
| 859 | |||
| 860 | rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); | ||
| 861 | kfifo->out = (kfifo->in & ~kfifo->mask) | | ||
| 862 | (rd_ptr - ctx->bitstream.paddr); | ||
| 863 | if (kfifo->out > kfifo->in) | ||
| 864 | kfifo->out -= kfifo->mask + 1; | ||
| 865 | } | ||
| 866 | |||
| 867 | static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) | ||
| 868 | { | ||
| 869 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
| 870 | struct coda_dev *dev = ctx->dev; | ||
| 871 | u32 rd_ptr, wr_ptr; | ||
| 872 | |||
| 873 | rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); | ||
| 874 | coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); | ||
| 875 | wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); | ||
| 876 | coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); | ||
| 877 | } | ||
| 878 | |||
| 879 | static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) | ||
| 880 | { | ||
| 881 | struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; | ||
| 882 | struct coda_dev *dev = ctx->dev; | ||
| 883 | u32 wr_ptr; | ||
| 884 | |||
| 885 | wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); | ||
| 886 | coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); | ||
| 887 | } | ||
| 888 | |||
| 889 | static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf) | ||
| 890 | { | ||
| 891 | u32 src_size = vb2_get_plane_payload(src_buf, 0); | ||
| 892 | u32 n; | ||
| 893 | |||
| 894 | n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), src_size); | ||
| 895 | if (n < src_size) | ||
| 896 | return -ENOSPC; | ||
| 897 | |||
| 898 | dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr, | ||
| 899 | ctx->bitstream.size, DMA_TO_DEVICE); | ||
| 900 | |||
| 901 | ctx->qsequence++; | ||
| 902 | |||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | static bool coda_bitstream_try_queue(struct coda_ctx *ctx, | ||
| 907 | struct vb2_buffer *src_buf) | ||
| 908 | { | ||
| 909 | int ret; | ||
| 910 | |||
| 911 | if (coda_get_bitstream_payload(ctx) + | ||
| 912 | vb2_get_plane_payload(src_buf, 0) + 512 >= ctx->bitstream.size) | ||
| 913 | return false; | ||
| 914 | |||
| 915 | if (vb2_plane_vaddr(src_buf, 0) == NULL) { | ||
| 916 | v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); | ||
| 917 | return true; | ||
| 918 | } | ||
| 919 | |||
| 920 | ret = coda_bitstream_queue(ctx, src_buf); | ||
| 921 | if (ret < 0) { | ||
| 922 | v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); | ||
| 923 | return false; | ||
| 924 | } | ||
| 925 | /* Sync read pointer to device */ | ||
| 926 | if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) | ||
| 927 | coda_kfifo_sync_to_device_write(ctx); | ||
| 928 | |||
| 929 | ctx->prescan_failed = false; | ||
| 930 | |||
| 931 | return true; | ||
| 932 | } | ||
| 933 | |||
| 934 | static void coda_fill_bitstream(struct coda_ctx *ctx) | ||
| 935 | { | ||
| 936 | struct vb2_buffer *src_buf; | ||
| 937 | |||
| 938 | while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) { | ||
| 939 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
| 940 | |||
| 941 | if (coda_bitstream_try_queue(ctx, src_buf)) { | ||
| 942 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | ||
| 943 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); | ||
| 944 | } else { | ||
| 945 | break; | ||
| 946 | } | ||
| 947 | } | ||
| 948 | } | ||
| 949 | |||
| 669 | /* | 950 | /* |
| 670 | * Mem-to-mem operations. | 951 | * Mem-to-mem operations. |
| 671 | */ | 952 | */ |
| 672 | static void coda_device_run(void *m2m_priv) | 953 | static int coda_prepare_decode(struct coda_ctx *ctx) |
| 954 | { | ||
| 955 | struct vb2_buffer *dst_buf; | ||
| 956 | struct coda_dev *dev = ctx->dev; | ||
| 957 | struct coda_q_data *q_data_dst; | ||
| 958 | u32 stridey, height; | ||
| 959 | u32 picture_y, picture_cb, picture_cr; | ||
| 960 | |||
| 961 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
| 962 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
| 963 | |||
| 964 | if (ctx->params.rot_mode & CODA_ROT_90) { | ||
| 965 | stridey = q_data_dst->height; | ||
| 966 | height = q_data_dst->width; | ||
| 967 | } else { | ||
| 968 | stridey = q_data_dst->width; | ||
| 969 | height = q_data_dst->height; | ||
| 970 | } | ||
| 971 | |||
| 972 | /* Try to copy source buffer contents into the bitstream ringbuffer */ | ||
| 973 | mutex_lock(&ctx->bitstream_mutex); | ||
| 974 | coda_fill_bitstream(ctx); | ||
| 975 | mutex_unlock(&ctx->bitstream_mutex); | ||
| 976 | |||
| 977 | if (coda_get_bitstream_payload(ctx) < 512 && | ||
| 978 | (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { | ||
| 979 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 980 | "bitstream payload: %d, skipping\n", | ||
| 981 | coda_get_bitstream_payload(ctx)); | ||
| 982 | schedule_work(&ctx->skip_run); | ||
| 983 | return -EAGAIN; | ||
| 984 | } | ||
| 985 | |||
| 986 | /* Run coda_start_decoding (again) if not yet initialized */ | ||
| 987 | if (!ctx->initialized) { | ||
| 988 | int ret = coda_start_decoding(ctx); | ||
| 989 | if (ret < 0) { | ||
| 990 | v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); | ||
| 991 | schedule_work(&ctx->skip_run); | ||
| 992 | return -EAGAIN; | ||
| 993 | } else { | ||
| 994 | ctx->initialized = 1; | ||
| 995 | } | ||
| 996 | } | ||
| 997 | |||
| 998 | /* Set rotator output */ | ||
| 999 | picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | ||
| 1000 | if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { | ||
| 1001 | /* Switch Cr and Cb for YVU420 format */ | ||
| 1002 | picture_cr = picture_y + stridey * height; | ||
| 1003 | picture_cb = picture_cr + stridey / 2 * height / 2; | ||
| 1004 | } else { | ||
| 1005 | picture_cb = picture_y + stridey * height; | ||
| 1006 | picture_cr = picture_cb + stridey / 2 * height / 2; | ||
| 1007 | } | ||
| 1008 | coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); | ||
| 1009 | coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); | ||
| 1010 | coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); | ||
| 1011 | coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); | ||
| 1012 | coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, | ||
| 1013 | CODA_CMD_DEC_PIC_ROT_MODE); | ||
| 1014 | |||
| 1015 | switch (dev->devtype->product) { | ||
| 1016 | case CODA_DX6: | ||
| 1017 | /* TBD */ | ||
| 1018 | case CODA_7541: | ||
| 1019 | coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); | ||
| 1020 | break; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); | ||
| 1024 | |||
| 1025 | coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); | ||
| 1026 | coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); | ||
| 1027 | |||
| 1028 | return 0; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | static void coda_prepare_encode(struct coda_ctx *ctx) | ||
| 673 | { | 1032 | { |
| 674 | struct coda_ctx *ctx = m2m_priv; | ||
| 675 | struct coda_q_data *q_data_src, *q_data_dst; | 1033 | struct coda_q_data *q_data_src, *q_data_dst; |
| 676 | struct vb2_buffer *src_buf, *dst_buf; | 1034 | struct vb2_buffer *src_buf, *dst_buf; |
| 677 | struct coda_dev *dev = ctx->dev; | 1035 | struct coda_dev *dev = ctx->dev; |
| @@ -681,17 +1039,15 @@ static void coda_device_run(void *m2m_priv) | |||
| 681 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; | 1039 | u32 pic_stream_buffer_addr, pic_stream_buffer_size; |
| 682 | u32 dst_fourcc; | 1040 | u32 dst_fourcc; |
| 683 | 1041 | ||
| 684 | mutex_lock(&dev->coda_mutex); | ||
| 685 | |||
| 686 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | 1042 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); |
| 687 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1043 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
| 688 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 1044 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| 689 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 1045 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
| 690 | dst_fourcc = q_data_dst->fourcc; | 1046 | dst_fourcc = q_data_dst->fourcc; |
| 691 | 1047 | ||
| 692 | src_buf->v4l2_buf.sequence = ctx->isequence; | 1048 | src_buf->v4l2_buf.sequence = ctx->osequence; |
| 693 | dst_buf->v4l2_buf.sequence = ctx->isequence; | 1049 | dst_buf->v4l2_buf.sequence = ctx->osequence; |
| 694 | ctx->isequence++; | 1050 | ctx->osequence++; |
| 695 | 1051 | ||
| 696 | /* | 1052 | /* |
| 697 | * Workaround coda firmware BUG that only marks the first | 1053 | * Workaround coda firmware BUG that only marks the first |
| @@ -793,16 +1149,53 @@ static void coda_device_run(void *m2m_priv) | |||
| 793 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); | 1149 | coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); |
| 794 | coda_write(dev, pic_stream_buffer_size / 1024, | 1150 | coda_write(dev, pic_stream_buffer_size / 1024, |
| 795 | CODA_CMD_ENC_PIC_BB_SIZE); | 1151 | CODA_CMD_ENC_PIC_BB_SIZE); |
| 1152 | } | ||
| 796 | 1153 | ||
| 797 | if (dev->devtype->product == CODA_7541) { | 1154 | static void coda_device_run(void *m2m_priv) |
| 798 | coda_write(dev, CODA7_USE_BIT_ENABLE | CODA7_USE_HOST_BIT_ENABLE | | 1155 | { |
| 799 | CODA7_USE_ME_ENABLE | CODA7_USE_HOST_ME_ENABLE, | 1156 | struct coda_ctx *ctx = m2m_priv; |
| 800 | CODA7_REG_BIT_AXI_SRAM_USE); | 1157 | struct coda_dev *dev = ctx->dev; |
| 1158 | int ret; | ||
| 1159 | |||
| 1160 | mutex_lock(&ctx->buffer_mutex); | ||
| 1161 | |||
| 1162 | /* | ||
| 1163 | * If streamoff dequeued all buffers before we could get the lock, | ||
| 1164 | * just bail out immediately. | ||
| 1165 | */ | ||
| 1166 | if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && | ||
| 1167 | ctx->inst_type != CODA_INST_DECODER) || | ||
| 1168 | !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | ||
| 1169 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 1170 | "%d: device_run without buffers\n", ctx->idx); | ||
| 1171 | mutex_unlock(&ctx->buffer_mutex); | ||
| 1172 | schedule_work(&ctx->skip_run); | ||
| 1173 | return; | ||
| 801 | } | 1174 | } |
| 802 | 1175 | ||
| 1176 | mutex_lock(&dev->coda_mutex); | ||
| 1177 | |||
| 1178 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
| 1179 | ret = coda_prepare_decode(ctx); | ||
| 1180 | if (ret < 0) { | ||
| 1181 | mutex_unlock(&dev->coda_mutex); | ||
| 1182 | mutex_unlock(&ctx->buffer_mutex); | ||
| 1183 | /* job_finish scheduled by prepare_decode */ | ||
| 1184 | return; | ||
| 1185 | } | ||
| 1186 | } else { | ||
| 1187 | coda_prepare_encode(ctx); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | if (dev->devtype->product != CODA_DX6) | ||
| 1191 | coda_write(dev, ctx->iram_info.axi_sram_use, | ||
| 1192 | CODA7_REG_BIT_AXI_SRAM_USE); | ||
| 1193 | |||
| 803 | /* 1 second timeout in case CODA locks up */ | 1194 | /* 1 second timeout in case CODA locks up */ |
| 804 | schedule_delayed_work(&dev->timeout, HZ); | 1195 | schedule_delayed_work(&dev->timeout, HZ); |
| 805 | 1196 | ||
| 1197 | if (ctx->inst_type == CODA_INST_DECODER) | ||
| 1198 | coda_kfifo_sync_to_device_full(ctx); | ||
| 806 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); | 1199 | coda_command_async(ctx, CODA_COMMAND_PIC_RUN); |
| 807 | } | 1200 | } |
| 808 | 1201 | ||
| @@ -812,15 +1205,32 @@ static int coda_job_ready(void *m2m_priv) | |||
| 812 | 1205 | ||
| 813 | /* | 1206 | /* |
| 814 | * For both 'P' and 'key' frame cases 1 picture | 1207 | * For both 'P' and 'key' frame cases 1 picture |
| 815 | * and 1 frame are needed. | 1208 | * and 1 frame are needed. In the decoder case, |
| 1209 | * the compressed frame can be in the bitstream. | ||
| 816 | */ | 1210 | */ |
| 817 | if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) || | 1211 | if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) && |
| 818 | !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | 1212 | ctx->inst_type != CODA_INST_DECODER) { |
| 819 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1213 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
| 820 | "not ready: not enough video buffers.\n"); | 1214 | "not ready: not enough video buffers.\n"); |
| 821 | return 0; | 1215 | return 0; |
| 822 | } | 1216 | } |
| 823 | 1217 | ||
| 1218 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { | ||
| 1219 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
| 1220 | "not ready: not enough video capture buffers.\n"); | ||
| 1221 | return 0; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | if (ctx->prescan_failed || | ||
| 1225 | ((ctx->inst_type == CODA_INST_DECODER) && | ||
| 1226 | (coda_get_bitstream_payload(ctx) < 512) && | ||
| 1227 | !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { | ||
| 1228 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
| 1229 | "%d: not ready: not enough bitstream data.\n", | ||
| 1230 | ctx->idx); | ||
| 1231 | return 0; | ||
| 1232 | } | ||
| 1233 | |||
| 824 | if (ctx->aborting) { | 1234 | if (ctx->aborting) { |
| 825 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 1235 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, |
| 826 | "not ready: aborting\n"); | 1236 | "not ready: aborting\n"); |
| @@ -936,7 +1346,29 @@ static int coda_buf_prepare(struct vb2_buffer *vb) | |||
| 936 | static void coda_buf_queue(struct vb2_buffer *vb) | 1346 | static void coda_buf_queue(struct vb2_buffer *vb) |
| 937 | { | 1347 | { |
| 938 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | 1348 | struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); |
| 939 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | 1349 | struct coda_q_data *q_data; |
| 1350 | |||
| 1351 | q_data = get_q_data(ctx, vb->vb2_queue->type); | ||
| 1352 | |||
| 1353 | /* | ||
| 1354 | * In the decoder case, immediately try to copy the buffer into the | ||
| 1355 | * bitstream ringbuffer and mark it as ready to be dequeued. | ||
| 1356 | */ | ||
| 1357 | if (q_data->fourcc == V4L2_PIX_FMT_H264 && | ||
| 1358 | vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | ||
| 1359 | /* | ||
| 1360 | * For backwards compatiblity, queuing an empty buffer marks | ||
| 1361 | * the stream end | ||
| 1362 | */ | ||
| 1363 | if (vb2_get_plane_payload(vb, 0) == 0) | ||
| 1364 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
| 1365 | mutex_lock(&ctx->bitstream_mutex); | ||
| 1366 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
| 1367 | coda_fill_bitstream(ctx); | ||
| 1368 | mutex_unlock(&ctx->bitstream_mutex); | ||
| 1369 | } else { | ||
| 1370 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
| 1371 | } | ||
| 940 | } | 1372 | } |
| 941 | 1373 | ||
| 942 | static void coda_wait_prepare(struct vb2_queue *q) | 1374 | static void coda_wait_prepare(struct vb2_queue *q) |
| @@ -951,21 +1383,6 @@ static void coda_wait_finish(struct vb2_queue *q) | |||
| 951 | coda_lock(ctx); | 1383 | coda_lock(ctx); |
| 952 | } | 1384 | } |
| 953 | 1385 | ||
| 954 | static void coda_free_framebuffers(struct coda_ctx *ctx) | ||
| 955 | { | ||
| 956 | int i; | ||
| 957 | |||
| 958 | for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) { | ||
| 959 | if (ctx->internal_frames[i].vaddr) { | ||
| 960 | dma_free_coherent(&ctx->dev->plat_dev->dev, | ||
| 961 | ctx->internal_frames[i].size, | ||
| 962 | ctx->internal_frames[i].vaddr, | ||
| 963 | ctx->internal_frames[i].paddr); | ||
| 964 | ctx->internal_frames[i].vaddr = NULL; | ||
| 965 | } | ||
| 966 | } | ||
| 967 | } | ||
| 968 | |||
| 969 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | 1386 | static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) |
| 970 | { | 1387 | { |
| 971 | struct coda_dev *dev = ctx->dev; | 1388 | struct coda_dev *dev = ctx->dev; |
| @@ -977,29 +1394,69 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) | |||
| 977 | p[index ^ 1] = value; | 1394 | p[index ^ 1] = value; |
| 978 | } | 1395 | } |
| 979 | 1396 | ||
| 1397 | static int coda_alloc_aux_buf(struct coda_dev *dev, | ||
| 1398 | struct coda_aux_buf *buf, size_t size) | ||
| 1399 | { | ||
| 1400 | buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr, | ||
| 1401 | GFP_KERNEL); | ||
| 1402 | if (!buf->vaddr) | ||
| 1403 | return -ENOMEM; | ||
| 1404 | |||
| 1405 | buf->size = size; | ||
| 1406 | |||
| 1407 | return 0; | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | static inline int coda_alloc_context_buf(struct coda_ctx *ctx, | ||
| 1411 | struct coda_aux_buf *buf, size_t size) | ||
| 1412 | { | ||
| 1413 | return coda_alloc_aux_buf(ctx->dev, buf, size); | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | static void coda_free_aux_buf(struct coda_dev *dev, | ||
| 1417 | struct coda_aux_buf *buf) | ||
| 1418 | { | ||
| 1419 | if (buf->vaddr) { | ||
| 1420 | dma_free_coherent(&dev->plat_dev->dev, buf->size, | ||
| 1421 | buf->vaddr, buf->paddr); | ||
| 1422 | buf->vaddr = NULL; | ||
| 1423 | buf->size = 0; | ||
| 1424 | } | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | static void coda_free_framebuffers(struct coda_ctx *ctx) | ||
| 1428 | { | ||
| 1429 | int i; | ||
| 1430 | |||
| 1431 | for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) | ||
| 1432 | coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]); | ||
| 1433 | } | ||
| 1434 | |||
| 980 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) | 1435 | static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) |
| 981 | { | 1436 | { |
| 982 | struct coda_dev *dev = ctx->dev; | 1437 | struct coda_dev *dev = ctx->dev; |
| 983 | |||
| 984 | int height = q_data->height; | 1438 | int height = q_data->height; |
| 985 | dma_addr_t paddr; | 1439 | dma_addr_t paddr; |
| 986 | int ysize; | 1440 | int ysize; |
| 1441 | int ret; | ||
| 987 | int i; | 1442 | int i; |
| 988 | 1443 | ||
| 1444 | if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) | ||
| 1445 | height = round_up(height, 16); | ||
| 989 | ysize = round_up(q_data->width, 8) * height; | 1446 | ysize = round_up(q_data->width, 8) * height; |
| 990 | 1447 | ||
| 991 | /* Allocate frame buffers */ | 1448 | /* Allocate frame buffers */ |
| 992 | ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS; | ||
| 993 | for (i = 0; i < ctx->num_internal_frames; i++) { | 1449 | for (i = 0; i < ctx->num_internal_frames; i++) { |
| 994 | ctx->internal_frames[i].size = q_data->sizeimage; | 1450 | size_t size; |
| 995 | if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6) | 1451 | |
| 1452 | size = q_data->sizeimage; | ||
| 1453 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && | ||
| 1454 | dev->devtype->product != CODA_DX6) | ||
| 996 | ctx->internal_frames[i].size += ysize/4; | 1455 | ctx->internal_frames[i].size += ysize/4; |
| 997 | ctx->internal_frames[i].vaddr = dma_alloc_coherent( | 1456 | ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size); |
| 998 | &dev->plat_dev->dev, ctx->internal_frames[i].size, | 1457 | if (ret < 0) { |
| 999 | &ctx->internal_frames[i].paddr, GFP_KERNEL); | ||
| 1000 | if (!ctx->internal_frames[i].vaddr) { | ||
| 1001 | coda_free_framebuffers(ctx); | 1458 | coda_free_framebuffers(ctx); |
| 1002 | return -ENOMEM; | 1459 | return ret; |
| 1003 | } | 1460 | } |
| 1004 | } | 1461 | } |
| 1005 | 1462 | ||
| @@ -1010,10 +1467,20 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d | |||
| 1010 | coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ | 1467 | coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ |
| 1011 | coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ | 1468 | coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ |
| 1012 | 1469 | ||
| 1013 | if (dev->devtype->product != CODA_DX6 && fourcc == V4L2_PIX_FMT_H264) | 1470 | /* mvcol buffer for h.264 */ |
| 1014 | coda_parabuf_write(ctx, 96 + i, ctx->internal_frames[i].paddr + ysize + ysize/4 + ysize/4); | 1471 | if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && |
| 1472 | dev->devtype->product != CODA_DX6) | ||
| 1473 | coda_parabuf_write(ctx, 96 + i, | ||
| 1474 | ctx->internal_frames[i].paddr + | ||
| 1475 | ysize + ysize/4 + ysize/4); | ||
| 1015 | } | 1476 | } |
| 1016 | 1477 | ||
| 1478 | /* mvcol buffer for mpeg4 */ | ||
| 1479 | if ((dev->devtype->product != CODA_DX6) && | ||
| 1480 | (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4)) | ||
| 1481 | coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr + | ||
| 1482 | ysize + ysize/4 + ysize/4); | ||
| 1483 | |||
| 1017 | return 0; | 1484 | return 0; |
| 1018 | } | 1485 | } |
| 1019 | 1486 | ||
| @@ -1035,6 +1502,371 @@ static int coda_h264_padding(int size, char *p) | |||
| 1035 | return nal_size; | 1502 | return nal_size; |
| 1036 | } | 1503 | } |
| 1037 | 1504 | ||
| 1505 | static void coda_setup_iram(struct coda_ctx *ctx) | ||
| 1506 | { | ||
| 1507 | struct coda_iram_info *iram_info = &ctx->iram_info; | ||
| 1508 | struct coda_dev *dev = ctx->dev; | ||
| 1509 | int ipacdc_size; | ||
| 1510 | int bitram_size; | ||
| 1511 | int dbk_size; | ||
| 1512 | int ovl_size; | ||
| 1513 | int mb_width; | ||
| 1514 | int me_size; | ||
| 1515 | int size; | ||
| 1516 | |||
| 1517 | memset(iram_info, 0, sizeof(*iram_info)); | ||
| 1518 | size = dev->iram_size; | ||
| 1519 | |||
| 1520 | if (dev->devtype->product == CODA_DX6) | ||
| 1521 | return; | ||
| 1522 | |||
| 1523 | if (ctx->inst_type == CODA_INST_ENCODER) { | ||
| 1524 | struct coda_q_data *q_data_src; | ||
| 1525 | |||
| 1526 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 1527 | mb_width = DIV_ROUND_UP(q_data_src->width, 16); | ||
| 1528 | |||
| 1529 | /* Prioritize in case IRAM is too small for everything */ | ||
| 1530 | me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048, | ||
| 1531 | 1024); | ||
| 1532 | iram_info->search_ram_size = me_size; | ||
| 1533 | if (size >= iram_info->search_ram_size) { | ||
| 1534 | if (dev->devtype->product == CODA_7541) | ||
| 1535 | iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE; | ||
| 1536 | iram_info->search_ram_paddr = dev->iram_paddr; | ||
| 1537 | size -= iram_info->search_ram_size; | ||
| 1538 | } else { | ||
| 1539 | pr_err("IRAM is smaller than the search ram size\n"); | ||
| 1540 | goto out; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | /* Only H.264BP and H.263P3 are considered */ | ||
| 1544 | dbk_size = round_up(128 * mb_width, 1024); | ||
| 1545 | if (size >= dbk_size) { | ||
| 1546 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | ||
| 1547 | iram_info->buf_dbk_y_use = dev->iram_paddr + | ||
| 1548 | iram_info->search_ram_size; | ||
| 1549 | iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use + | ||
| 1550 | dbk_size / 2; | ||
| 1551 | size -= dbk_size; | ||
| 1552 | } else { | ||
| 1553 | goto out; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | bitram_size = round_up(128 * mb_width, 1024); | ||
| 1557 | if (size >= bitram_size) { | ||
| 1558 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
| 1559 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
| 1560 | dbk_size / 2; | ||
| 1561 | size -= bitram_size; | ||
| 1562 | } else { | ||
| 1563 | goto out; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | ipacdc_size = round_up(128 * mb_width, 1024); | ||
| 1567 | if (size >= ipacdc_size) { | ||
| 1568 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | ||
| 1569 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | ||
| 1570 | bitram_size; | ||
| 1571 | size -= ipacdc_size; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | /* OVL and BTP disabled for encoder */ | ||
| 1575 | } else if (ctx->inst_type == CODA_INST_DECODER) { | ||
| 1576 | struct coda_q_data *q_data_dst; | ||
| 1577 | int mb_height; | ||
| 1578 | |||
| 1579 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
| 1580 | mb_width = DIV_ROUND_UP(q_data_dst->width, 16); | ||
| 1581 | mb_height = DIV_ROUND_UP(q_data_dst->height, 16); | ||
| 1582 | |||
| 1583 | dbk_size = round_up(256 * mb_width, 1024); | ||
| 1584 | if (size >= dbk_size) { | ||
| 1585 | iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE; | ||
| 1586 | iram_info->buf_dbk_y_use = dev->iram_paddr; | ||
| 1587 | iram_info->buf_dbk_c_use = dev->iram_paddr + | ||
| 1588 | dbk_size / 2; | ||
| 1589 | size -= dbk_size; | ||
| 1590 | } else { | ||
| 1591 | goto out; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | bitram_size = round_up(128 * mb_width, 1024); | ||
| 1595 | if (size >= bitram_size) { | ||
| 1596 | iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE; | ||
| 1597 | iram_info->buf_bit_use = iram_info->buf_dbk_c_use + | ||
| 1598 | dbk_size / 2; | ||
| 1599 | size -= bitram_size; | ||
| 1600 | } else { | ||
| 1601 | goto out; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | ipacdc_size = round_up(128 * mb_width, 1024); | ||
| 1605 | if (size >= ipacdc_size) { | ||
| 1606 | iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE; | ||
| 1607 | iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use + | ||
| 1608 | bitram_size; | ||
| 1609 | size -= ipacdc_size; | ||
| 1610 | } else { | ||
| 1611 | goto out; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | ovl_size = round_up(80 * mb_width, 1024); | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | out: | ||
| 1618 | switch (dev->devtype->product) { | ||
| 1619 | case CODA_DX6: | ||
| 1620 | break; | ||
| 1621 | case CODA_7541: | ||
| 1622 | /* i.MX53 uses secondary AXI for IRAM access */ | ||
| 1623 | if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE) | ||
| 1624 | iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE; | ||
| 1625 | if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE) | ||
| 1626 | iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE; | ||
| 1627 | if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE) | ||
| 1628 | iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE; | ||
| 1629 | if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE) | ||
| 1630 | iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE; | ||
| 1631 | if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE) | ||
| 1632 | iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE; | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) | ||
| 1636 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
| 1637 | "IRAM smaller than needed\n"); | ||
| 1638 | |||
| 1639 | if (dev->devtype->product == CODA_7541) { | ||
| 1640 | /* TODO - Enabling these causes picture errors on CODA7541 */ | ||
| 1641 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
| 1642 | /* fw 1.4.50 */ | ||
| 1643 | iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | | ||
| 1644 | CODA7_USE_IP_ENABLE); | ||
| 1645 | } else { | ||
| 1646 | /* fw 13.4.29 */ | ||
| 1647 | iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | | ||
| 1648 | CODA7_USE_HOST_DBK_ENABLE | | ||
| 1649 | CODA7_USE_IP_ENABLE | | ||
| 1650 | CODA7_USE_DBK_ENABLE); | ||
| 1651 | } | ||
| 1652 | } | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | static void coda_free_context_buffers(struct coda_ctx *ctx) | ||
| 1656 | { | ||
| 1657 | struct coda_dev *dev = ctx->dev; | ||
| 1658 | |||
| 1659 | coda_free_aux_buf(dev, &ctx->slicebuf); | ||
| 1660 | coda_free_aux_buf(dev, &ctx->psbuf); | ||
| 1661 | if (dev->devtype->product != CODA_DX6) | ||
| 1662 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | static int coda_alloc_context_buffers(struct coda_ctx *ctx, | ||
| 1666 | struct coda_q_data *q_data) | ||
| 1667 | { | ||
| 1668 | struct coda_dev *dev = ctx->dev; | ||
| 1669 | size_t size; | ||
| 1670 | int ret; | ||
| 1671 | |||
| 1672 | switch (dev->devtype->product) { | ||
| 1673 | case CODA_7541: | ||
| 1674 | size = CODA7_WORK_BUF_SIZE; | ||
| 1675 | break; | ||
| 1676 | default: | ||
| 1677 | return 0; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | if (ctx->psbuf.vaddr) { | ||
| 1681 | v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); | ||
| 1682 | return -EBUSY; | ||
| 1683 | } | ||
| 1684 | if (ctx->slicebuf.vaddr) { | ||
| 1685 | v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n"); | ||
| 1686 | return -EBUSY; | ||
| 1687 | } | ||
| 1688 | if (ctx->workbuf.vaddr) { | ||
| 1689 | v4l2_err(&dev->v4l2_dev, "context buffer still allocated\n"); | ||
| 1690 | ret = -EBUSY; | ||
| 1691 | return -ENOMEM; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | if (q_data->fourcc == V4L2_PIX_FMT_H264) { | ||
| 1695 | /* worst case slice size */ | ||
| 1696 | size = (DIV_ROUND_UP(q_data->width, 16) * | ||
| 1697 | DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; | ||
| 1698 | ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size); | ||
| 1699 | if (ret < 0) { | ||
| 1700 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer", | ||
| 1701 | ctx->slicebuf.size); | ||
| 1702 | return ret; | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | if (dev->devtype->product == CODA_7541) { | ||
| 1707 | ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE); | ||
| 1708 | if (ret < 0) { | ||
| 1709 | v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer"); | ||
| 1710 | goto err; | ||
| 1711 | } | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size); | ||
| 1715 | if (ret < 0) { | ||
| 1716 | v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer", | ||
| 1717 | ctx->workbuf.size); | ||
| 1718 | goto err; | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | return 0; | ||
| 1722 | |||
| 1723 | err: | ||
| 1724 | coda_free_context_buffers(ctx); | ||
| 1725 | return ret; | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | static int coda_start_decoding(struct coda_ctx *ctx) | ||
| 1729 | { | ||
| 1730 | struct coda_q_data *q_data_src, *q_data_dst; | ||
| 1731 | u32 bitstream_buf, bitstream_size; | ||
| 1732 | struct coda_dev *dev = ctx->dev; | ||
| 1733 | int width, height; | ||
| 1734 | u32 src_fourcc; | ||
| 1735 | u32 val; | ||
| 1736 | int ret; | ||
| 1737 | |||
| 1738 | /* Start decoding */ | ||
| 1739 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 1740 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
| 1741 | bitstream_buf = ctx->bitstream.paddr; | ||
| 1742 | bitstream_size = ctx->bitstream.size; | ||
| 1743 | src_fourcc = q_data_src->fourcc; | ||
| 1744 | |||
| 1745 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); | ||
| 1746 | |||
| 1747 | /* Update coda bitstream read and write pointers from kfifo */ | ||
| 1748 | coda_kfifo_sync_to_device_full(ctx); | ||
| 1749 | |||
| 1750 | ctx->display_idx = -1; | ||
| 1751 | ctx->frm_dis_flg = 0; | ||
| 1752 | coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
| 1753 | |||
| 1754 | coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE, | ||
| 1755 | CODA_REG_BIT_BIT_STREAM_PARAM); | ||
| 1756 | |||
| 1757 | coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); | ||
| 1758 | coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); | ||
| 1759 | val = 0; | ||
| 1760 | if (dev->devtype->product == CODA_7541) | ||
| 1761 | val |= CODA_REORDER_ENABLE; | ||
| 1762 | coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); | ||
| 1763 | |||
| 1764 | ctx->params.codec_mode = ctx->codec->mode; | ||
| 1765 | ctx->params.codec_mode_aux = 0; | ||
| 1766 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
| 1767 | if (dev->devtype->product == CODA_7541) { | ||
| 1768 | coda_write(dev, ctx->psbuf.paddr, | ||
| 1769 | CODA_CMD_DEC_SEQ_PS_BB_START); | ||
| 1770 | coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), | ||
| 1771 | CODA_CMD_DEC_SEQ_PS_BB_SIZE); | ||
| 1772 | } | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { | ||
| 1776 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); | ||
| 1777 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
| 1778 | return -ETIMEDOUT; | ||
| 1779 | } | ||
| 1780 | |||
| 1781 | /* Update kfifo out pointer from coda bitstream read pointer */ | ||
| 1782 | coda_kfifo_sync_from_device(ctx); | ||
| 1783 | |||
| 1784 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
| 1785 | |||
| 1786 | if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { | ||
| 1787 | v4l2_err(&dev->v4l2_dev, | ||
| 1788 | "CODA_COMMAND_SEQ_INIT failed, error code = %d\n", | ||
| 1789 | coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); | ||
| 1790 | return -EAGAIN; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); | ||
| 1794 | if (dev->devtype->product == CODA_DX6) { | ||
| 1795 | width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK; | ||
| 1796 | height = val & CODADX6_PICHEIGHT_MASK; | ||
| 1797 | } else { | ||
| 1798 | width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK; | ||
| 1799 | height = val & CODA7_PICHEIGHT_MASK; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | if (width > q_data_dst->width || height > q_data_dst->height) { | ||
| 1803 | v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", | ||
| 1804 | width, height, q_data_dst->width, q_data_dst->height); | ||
| 1805 | return -EINVAL; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | width = round_up(width, 16); | ||
| 1809 | height = round_up(height, 16); | ||
| 1810 | |||
| 1811 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n", | ||
| 1812 | __func__, ctx->idx, width, height); | ||
| 1813 | |||
| 1814 | ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1; | ||
| 1815 | if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { | ||
| 1816 | v4l2_err(&dev->v4l2_dev, | ||
| 1817 | "not enough framebuffers to decode (%d < %d)\n", | ||
| 1818 | CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); | ||
| 1819 | return -EINVAL; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); | ||
| 1823 | if (ret < 0) | ||
| 1824 | return ret; | ||
| 1825 | |||
| 1826 | /* Tell the decoder how many frame buffers we allocated. */ | ||
| 1827 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); | ||
| 1828 | coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE); | ||
| 1829 | |||
| 1830 | if (dev->devtype->product != CODA_DX6) { | ||
| 1831 | /* Set secondary AXI IRAM */ | ||
| 1832 | coda_setup_iram(ctx); | ||
| 1833 | |||
| 1834 | coda_write(dev, ctx->iram_info.buf_bit_use, | ||
| 1835 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); | ||
| 1836 | coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, | ||
| 1837 | CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); | ||
| 1838 | coda_write(dev, ctx->iram_info.buf_dbk_y_use, | ||
| 1839 | CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); | ||
| 1840 | coda_write(dev, ctx->iram_info.buf_dbk_c_use, | ||
| 1841 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | ||
| 1842 | coda_write(dev, ctx->iram_info.buf_ovl_use, | ||
| 1843 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
| 1847 | coda_write(dev, ctx->slicebuf.paddr, | ||
| 1848 | CODA_CMD_SET_FRAME_SLICE_BB_START); | ||
| 1849 | coda_write(dev, ctx->slicebuf.size / 1024, | ||
| 1850 | CODA_CMD_SET_FRAME_SLICE_BB_SIZE); | ||
| 1851 | } | ||
| 1852 | |||
| 1853 | if (dev->devtype->product == CODA_7541) { | ||
| 1854 | int max_mb_x = 1920 / 16; | ||
| 1855 | int max_mb_y = 1088 / 16; | ||
| 1856 | int max_mb_num = max_mb_x * max_mb_y; | ||
| 1857 | coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, | ||
| 1858 | CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { | ||
| 1862 | v4l2_err(&ctx->dev->v4l2_dev, | ||
| 1863 | "CODA_COMMAND_SET_FRAME_BUF timeout\n"); | ||
| 1864 | return -ETIMEDOUT; | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | return 0; | ||
| 1868 | } | ||
| 1869 | |||
| 1038 | static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, | 1870 | static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, |
| 1039 | int header_code, u8 *header, int *size) | 1871 | int header_code, u8 *header, int *size) |
| 1040 | { | 1872 | { |
| @@ -1050,7 +1882,7 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, | |||
| 1050 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); | 1882 | v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); |
| 1051 | return ret; | 1883 | return ret; |
| 1052 | } | 1884 | } |
| 1053 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - | 1885 | *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - |
| 1054 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); | 1886 | coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); |
| 1055 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); | 1887 | memcpy(header, vb2_plane_vaddr(buf, 0), *size); |
| 1056 | 1888 | ||
| @@ -1069,26 +1901,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1069 | u32 value; | 1901 | u32 value; |
| 1070 | int ret = 0; | 1902 | int ret = 0; |
| 1071 | 1903 | ||
| 1072 | if (count < 1) | 1904 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| 1073 | return -EINVAL; | 1905 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
| 1906 | if (q_data_src->fourcc == V4L2_PIX_FMT_H264) { | ||
| 1907 | if (coda_get_bitstream_payload(ctx) < 512) | ||
| 1908 | return -EINVAL; | ||
| 1909 | } else { | ||
| 1910 | if (count < 1) | ||
| 1911 | return -EINVAL; | ||
| 1912 | } | ||
| 1074 | 1913 | ||
| 1075 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
| 1076 | ctx->streamon_out = 1; | 1914 | ctx->streamon_out = 1; |
| 1077 | else | ||
| 1078 | ctx->streamon_cap = 1; | ||
| 1079 | 1915 | ||
| 1080 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
| 1081 | if (ctx->streamon_out) { | ||
| 1082 | if (coda_format_is_yuv(q_data_src->fourcc)) | 1916 | if (coda_format_is_yuv(q_data_src->fourcc)) |
| 1083 | ctx->inst_type = CODA_INST_ENCODER; | 1917 | ctx->inst_type = CODA_INST_ENCODER; |
| 1084 | else | 1918 | else |
| 1085 | ctx->inst_type = CODA_INST_DECODER; | 1919 | ctx->inst_type = CODA_INST_DECODER; |
| 1920 | } else { | ||
| 1921 | if (count < 1) | ||
| 1922 | return -EINVAL; | ||
| 1923 | |||
| 1924 | ctx->streamon_cap = 1; | ||
| 1086 | } | 1925 | } |
| 1087 | 1926 | ||
| 1088 | /* Don't start the coda unless both queues are on */ | 1927 | /* Don't start the coda unless both queues are on */ |
| 1089 | if (!(ctx->streamon_out & ctx->streamon_cap)) | 1928 | if (!(ctx->streamon_out & ctx->streamon_cap)) |
| 1090 | return 0; | 1929 | return 0; |
| 1091 | 1930 | ||
| 1931 | /* Allow device_run with no buffers queued and after streamoff */ | ||
| 1932 | v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true); | ||
| 1933 | |||
| 1092 | ctx->gopcounter = ctx->params.gop_size - 1; | 1934 | ctx->gopcounter = ctx->params.gop_size - 1; |
| 1093 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | 1935 | buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
| 1094 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); | 1936 | bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); |
| @@ -1103,6 +1945,25 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1103 | return -EINVAL; | 1945 | return -EINVAL; |
| 1104 | } | 1946 | } |
| 1105 | 1947 | ||
| 1948 | /* Allocate per-instance buffers */ | ||
| 1949 | ret = coda_alloc_context_buffers(ctx, q_data_src); | ||
| 1950 | if (ret < 0) | ||
| 1951 | return ret; | ||
| 1952 | |||
| 1953 | if (ctx->inst_type == CODA_INST_DECODER) { | ||
| 1954 | mutex_lock(&dev->coda_mutex); | ||
| 1955 | ret = coda_start_decoding(ctx); | ||
| 1956 | mutex_unlock(&dev->coda_mutex); | ||
| 1957 | if (ret == -EAGAIN) { | ||
| 1958 | return 0; | ||
| 1959 | } else if (ret < 0) { | ||
| 1960 | return ret; | ||
| 1961 | } else { | ||
| 1962 | ctx->initialized = 1; | ||
| 1963 | return 0; | ||
| 1964 | } | ||
| 1965 | } | ||
| 1966 | |||
| 1106 | if (!coda_is_initialized(dev)) { | 1967 | if (!coda_is_initialized(dev)) { |
| 1107 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); | 1968 | v4l2_err(v4l2_dev, "coda is not initialized.\n"); |
| 1108 | return -EFAULT; | 1969 | return -EFAULT; |
| @@ -1111,8 +1972,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1111 | mutex_lock(&dev->coda_mutex); | 1972 | mutex_lock(&dev->coda_mutex); |
| 1112 | 1973 | ||
| 1113 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); | 1974 | coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); |
| 1114 | coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx)); | 1975 | coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); |
| 1115 | coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx)); | 1976 | coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); |
| 1116 | switch (dev->devtype->product) { | 1977 | switch (dev->devtype->product) { |
| 1117 | case CODA_DX6: | 1978 | case CODA_DX6: |
| 1118 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | | 1979 | coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | |
| @@ -1207,6 +2068,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1207 | } | 2068 | } |
| 1208 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); | 2069 | coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); |
| 1209 | 2070 | ||
| 2071 | coda_setup_iram(ctx); | ||
| 2072 | |||
| 1210 | if (dst_fourcc == V4L2_PIX_FMT_H264) { | 2073 | if (dst_fourcc == V4L2_PIX_FMT_H264) { |
| 1211 | value = (FMO_SLICE_SAVE_BUF_SIZE << 7); | 2074 | value = (FMO_SLICE_SAVE_BUF_SIZE << 7); |
| 1212 | value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET; | 2075 | value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET; |
| @@ -1214,8 +2077,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1214 | if (dev->devtype->product == CODA_DX6) { | 2077 | if (dev->devtype->product == CODA_DX6) { |
| 1215 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); | 2078 | coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); |
| 1216 | } else { | 2079 | } else { |
| 1217 | coda_write(dev, dev->iram_paddr, CODA7_CMD_ENC_SEQ_SEARCH_BASE); | 2080 | coda_write(dev, ctx->iram_info.search_ram_paddr, |
| 1218 | coda_write(dev, 48 * 1024, CODA7_CMD_ENC_SEQ_SEARCH_SIZE); | 2081 | CODA7_CMD_ENC_SEQ_SEARCH_BASE); |
| 2082 | coda_write(dev, ctx->iram_info.search_ram_size, | ||
| 2083 | CODA7_CMD_ENC_SEQ_SEARCH_SIZE); | ||
| 1219 | } | 2084 | } |
| 1220 | } | 2085 | } |
| 1221 | 2086 | ||
| @@ -1231,6 +2096,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1231 | goto out; | 2096 | goto out; |
| 1232 | } | 2097 | } |
| 1233 | 2098 | ||
| 2099 | ctx->num_internal_frames = 2; | ||
| 1234 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); | 2100 | ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); |
| 1235 | if (ret < 0) { | 2101 | if (ret < 0) { |
| 1236 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); | 2102 | v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); |
| @@ -1239,13 +2105,20 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1239 | 2105 | ||
| 1240 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); | 2106 | coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); |
| 1241 | coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); | 2107 | coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); |
| 2108 | if (dev->devtype->product == CODA_7541) | ||
| 2109 | coda_write(dev, round_up(q_data_src->width, 8), | ||
| 2110 | CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); | ||
| 1242 | if (dev->devtype->product != CODA_DX6) { | 2111 | if (dev->devtype->product != CODA_DX6) { |
| 1243 | coda_write(dev, round_up(q_data_src->width, 8), CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); | 2112 | coda_write(dev, ctx->iram_info.buf_bit_use, |
| 1244 | coda_write(dev, dev->iram_paddr + 48 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); | 2113 | CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); |
| 1245 | coda_write(dev, dev->iram_paddr + 53 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | 2114 | coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, |
| 1246 | coda_write(dev, dev->iram_paddr + 58 * 1024, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); | 2115 | CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); |
| 1247 | coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); | 2116 | coda_write(dev, ctx->iram_info.buf_dbk_y_use, |
| 1248 | coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | 2117 | CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); |
| 2118 | coda_write(dev, ctx->iram_info.buf_dbk_c_use, | ||
| 2119 | CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); | ||
| 2120 | coda_write(dev, ctx->iram_info.buf_ovl_use, | ||
| 2121 | CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); | ||
| 1249 | } | 2122 | } |
| 1250 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); | 2123 | ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); |
| 1251 | if (ret < 0) { | 2124 | if (ret < 0) { |
| @@ -1326,32 +2199,26 @@ static int coda_stop_streaming(struct vb2_queue *q) | |||
| 1326 | struct coda_dev *dev = ctx->dev; | 2199 | struct coda_dev *dev = ctx->dev; |
| 1327 | 2200 | ||
| 1328 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | 2201 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { |
| 1329 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2202 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
| 1330 | "%s: output\n", __func__); | 2203 | "%s: output\n", __func__); |
| 1331 | ctx->streamon_out = 0; | 2204 | ctx->streamon_out = 0; |
| 2205 | |||
| 2206 | ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; | ||
| 2207 | |||
| 2208 | ctx->isequence = 0; | ||
| 1332 | } else { | 2209 | } else { |
| 1333 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2210 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, |
| 1334 | "%s: capture\n", __func__); | 2211 | "%s: capture\n", __func__); |
| 1335 | ctx->streamon_cap = 0; | 2212 | ctx->streamon_cap = 0; |
| 1336 | } | ||
| 1337 | |||
| 1338 | /* Don't stop the coda unless both queues are off */ | ||
| 1339 | if (ctx->streamon_out || ctx->streamon_cap) | ||
| 1340 | return 0; | ||
| 1341 | 2213 | ||
| 1342 | cancel_delayed_work(&dev->timeout); | 2214 | ctx->osequence = 0; |
| 1343 | |||
| 1344 | mutex_lock(&dev->coda_mutex); | ||
| 1345 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 1346 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
| 1347 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
| 1348 | v4l2_err(&dev->v4l2_dev, | ||
| 1349 | "CODA_COMMAND_SEQ_END failed\n"); | ||
| 1350 | return -ETIMEDOUT; | ||
| 1351 | } | 2215 | } |
| 1352 | mutex_unlock(&dev->coda_mutex); | ||
| 1353 | 2216 | ||
| 1354 | coda_free_framebuffers(ctx); | 2217 | if (!ctx->streamon_out && !ctx->streamon_cap) { |
| 2218 | kfifo_init(&ctx->bitstream_fifo, | ||
| 2219 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
| 2220 | ctx->runcounter = 0; | ||
| 2221 | } | ||
| 1355 | 2222 | ||
| 1356 | return 0; | 2223 | return 0; |
| 1357 | } | 2224 | } |
| @@ -1511,23 +2378,41 @@ static int coda_open(struct file *file) | |||
| 1511 | { | 2378 | { |
| 1512 | struct coda_dev *dev = video_drvdata(file); | 2379 | struct coda_dev *dev = video_drvdata(file); |
| 1513 | struct coda_ctx *ctx = NULL; | 2380 | struct coda_ctx *ctx = NULL; |
| 1514 | int ret = 0; | 2381 | int ret; |
| 1515 | int idx; | 2382 | int idx; |
| 1516 | 2383 | ||
| 1517 | idx = coda_next_free_instance(dev); | ||
| 1518 | if (idx >= CODA_MAX_INSTANCES) | ||
| 1519 | return -EBUSY; | ||
| 1520 | set_bit(idx, &dev->instance_mask); | ||
| 1521 | |||
| 1522 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 2384 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); |
| 1523 | if (!ctx) | 2385 | if (!ctx) |
| 1524 | return -ENOMEM; | 2386 | return -ENOMEM; |
| 1525 | 2387 | ||
| 2388 | idx = coda_next_free_instance(dev); | ||
| 2389 | if (idx >= CODA_MAX_INSTANCES) { | ||
| 2390 | ret = -EBUSY; | ||
| 2391 | goto err_coda_max; | ||
| 2392 | } | ||
| 2393 | set_bit(idx, &dev->instance_mask); | ||
| 2394 | |||
| 2395 | INIT_WORK(&ctx->skip_run, coda_skip_run); | ||
| 1526 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | 2396 | v4l2_fh_init(&ctx->fh, video_devdata(file)); |
| 1527 | file->private_data = &ctx->fh; | 2397 | file->private_data = &ctx->fh; |
| 1528 | v4l2_fh_add(&ctx->fh); | 2398 | v4l2_fh_add(&ctx->fh); |
| 1529 | ctx->dev = dev; | 2399 | ctx->dev = dev; |
| 1530 | ctx->idx = idx; | 2400 | ctx->idx = idx; |
| 2401 | switch (dev->devtype->product) { | ||
| 2402 | case CODA_7541: | ||
| 2403 | ctx->reg_idx = 0; | ||
| 2404 | break; | ||
| 2405 | default: | ||
| 2406 | ctx->reg_idx = idx; | ||
| 2407 | } | ||
| 2408 | |||
| 2409 | ret = clk_prepare_enable(dev->clk_per); | ||
| 2410 | if (ret) | ||
| 2411 | goto err_clk_per; | ||
| 2412 | |||
| 2413 | ret = clk_prepare_enable(dev->clk_ahb); | ||
| 2414 | if (ret) | ||
| 2415 | goto err_clk_ahb; | ||
| 1531 | 2416 | ||
| 1532 | set_default_params(ctx); | 2417 | set_default_params(ctx); |
| 1533 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, | 2418 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, |
| @@ -1537,39 +2422,62 @@ static int coda_open(struct file *file) | |||
| 1537 | 2422 | ||
| 1538 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", | 2423 | v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", |
| 1539 | __func__, ret); | 2424 | __func__, ret); |
| 1540 | goto err; | 2425 | goto err_ctx_init; |
| 1541 | } | 2426 | } |
| 1542 | ret = coda_ctrls_setup(ctx); | 2427 | ret = coda_ctrls_setup(ctx); |
| 1543 | if (ret) { | 2428 | if (ret) { |
| 1544 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); | 2429 | v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); |
| 1545 | goto err; | 2430 | goto err_ctrls_setup; |
| 1546 | } | 2431 | } |
| 1547 | 2432 | ||
| 1548 | ctx->fh.ctrl_handler = &ctx->ctrls; | 2433 | ctx->fh.ctrl_handler = &ctx->ctrls; |
| 1549 | 2434 | ||
| 1550 | ctx->parabuf.vaddr = dma_alloc_coherent(&dev->plat_dev->dev, | 2435 | ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE); |
| 1551 | CODA_PARA_BUF_SIZE, &ctx->parabuf.paddr, GFP_KERNEL); | 2436 | if (ret < 0) { |
| 1552 | if (!ctx->parabuf.vaddr) { | ||
| 1553 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); | 2437 | v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); |
| 2438 | goto err_dma_alloc; | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | ctx->bitstream.size = CODA_MAX_FRAME_SIZE; | ||
| 2442 | ctx->bitstream.vaddr = dma_alloc_writecombine(&dev->plat_dev->dev, | ||
| 2443 | ctx->bitstream.size, &ctx->bitstream.paddr, GFP_KERNEL); | ||
| 2444 | if (!ctx->bitstream.vaddr) { | ||
| 2445 | v4l2_err(&dev->v4l2_dev, "failed to allocate bitstream ringbuffer"); | ||
| 1554 | ret = -ENOMEM; | 2446 | ret = -ENOMEM; |
| 1555 | goto err; | 2447 | goto err_dma_writecombine; |
| 1556 | } | 2448 | } |
| 2449 | kfifo_init(&ctx->bitstream_fifo, | ||
| 2450 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
| 2451 | mutex_init(&ctx->bitstream_mutex); | ||
| 2452 | mutex_init(&ctx->buffer_mutex); | ||
| 1557 | 2453 | ||
| 1558 | coda_lock(ctx); | 2454 | coda_lock(ctx); |
| 1559 | list_add(&ctx->list, &dev->instances); | 2455 | list_add(&ctx->list, &dev->instances); |
| 1560 | coda_unlock(ctx); | 2456 | coda_unlock(ctx); |
| 1561 | 2457 | ||
| 1562 | clk_prepare_enable(dev->clk_per); | ||
| 1563 | clk_prepare_enable(dev->clk_ahb); | ||
| 1564 | |||
| 1565 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n", | 2458 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n", |
| 1566 | ctx->idx, ctx); | 2459 | ctx->idx, ctx); |
| 1567 | 2460 | ||
| 1568 | return 0; | 2461 | return 0; |
| 1569 | 2462 | ||
| 1570 | err: | 2463 | err_dma_writecombine: |
| 2464 | coda_free_context_buffers(ctx); | ||
| 2465 | if (ctx->dev->devtype->product == CODA_DX6) | ||
| 2466 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
| 2467 | coda_free_aux_buf(dev, &ctx->parabuf); | ||
| 2468 | err_dma_alloc: | ||
| 2469 | v4l2_ctrl_handler_free(&ctx->ctrls); | ||
| 2470 | err_ctrls_setup: | ||
| 2471 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
| 2472 | err_ctx_init: | ||
| 2473 | clk_disable_unprepare(dev->clk_ahb); | ||
| 2474 | err_clk_ahb: | ||
| 2475 | clk_disable_unprepare(dev->clk_per); | ||
| 2476 | err_clk_per: | ||
| 1571 | v4l2_fh_del(&ctx->fh); | 2477 | v4l2_fh_del(&ctx->fh); |
| 1572 | v4l2_fh_exit(&ctx->fh); | 2478 | v4l2_fh_exit(&ctx->fh); |
| 2479 | clear_bit(ctx->idx, &dev->instance_mask); | ||
| 2480 | err_coda_max: | ||
| 1573 | kfree(ctx); | 2481 | kfree(ctx); |
| 1574 | return ret; | 2482 | return ret; |
| 1575 | } | 2483 | } |
| @@ -1582,16 +2490,37 @@ static int coda_release(struct file *file) | |||
| 1582 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", | 2490 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", |
| 1583 | ctx); | 2491 | ctx); |
| 1584 | 2492 | ||
| 2493 | /* If this instance is running, call .job_abort and wait for it to end */ | ||
| 2494 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
| 2495 | |||
| 2496 | /* In case the instance was not running, we still need to call SEQ_END */ | ||
| 2497 | mutex_lock(&dev->coda_mutex); | ||
| 2498 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 2499 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
| 2500 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
| 2501 | v4l2_err(&dev->v4l2_dev, | ||
| 2502 | "CODA_COMMAND_SEQ_END failed\n"); | ||
| 2503 | mutex_unlock(&dev->coda_mutex); | ||
| 2504 | return -ETIMEDOUT; | ||
| 2505 | } | ||
| 2506 | mutex_unlock(&dev->coda_mutex); | ||
| 2507 | |||
| 2508 | coda_free_framebuffers(ctx); | ||
| 2509 | |||
| 1585 | coda_lock(ctx); | 2510 | coda_lock(ctx); |
| 1586 | list_del(&ctx->list); | 2511 | list_del(&ctx->list); |
| 1587 | coda_unlock(ctx); | 2512 | coda_unlock(ctx); |
| 1588 | 2513 | ||
| 1589 | dma_free_coherent(&dev->plat_dev->dev, CODA_PARA_BUF_SIZE, | 2514 | dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size, |
| 1590 | ctx->parabuf.vaddr, ctx->parabuf.paddr); | 2515 | ctx->bitstream.vaddr, ctx->bitstream.paddr); |
| 1591 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 2516 | coda_free_context_buffers(ctx); |
| 2517 | if (ctx->dev->devtype->product == CODA_DX6) | ||
| 2518 | coda_free_aux_buf(dev, &ctx->workbuf); | ||
| 2519 | |||
| 2520 | coda_free_aux_buf(dev, &ctx->parabuf); | ||
| 1592 | v4l2_ctrl_handler_free(&ctx->ctrls); | 2521 | v4l2_ctrl_handler_free(&ctx->ctrls); |
| 1593 | clk_disable_unprepare(dev->clk_per); | ||
| 1594 | clk_disable_unprepare(dev->clk_ahb); | 2522 | clk_disable_unprepare(dev->clk_ahb); |
| 2523 | clk_disable_unprepare(dev->clk_per); | ||
| 1595 | v4l2_fh_del(&ctx->fh); | 2524 | v4l2_fh_del(&ctx->fh); |
| 1596 | v4l2_fh_exit(&ctx->fh); | 2525 | v4l2_fh_exit(&ctx->fh); |
| 1597 | clear_bit(ctx->idx, &dev->instance_mask); | 2526 | clear_bit(ctx->idx, &dev->instance_mask); |
| @@ -1628,55 +2557,180 @@ static const struct v4l2_file_operations coda_fops = { | |||
| 1628 | .mmap = coda_mmap, | 2557 | .mmap = coda_mmap, |
| 1629 | }; | 2558 | }; |
| 1630 | 2559 | ||
| 1631 | static irqreturn_t coda_irq_handler(int irq, void *data) | 2560 | static void coda_finish_decode(struct coda_ctx *ctx) |
| 1632 | { | 2561 | { |
| 1633 | struct vb2_buffer *src_buf, *dst_buf; | 2562 | struct coda_dev *dev = ctx->dev; |
| 1634 | struct coda_dev *dev = data; | 2563 | struct coda_q_data *q_data_src; |
| 1635 | u32 wr_ptr, start_ptr; | 2564 | struct coda_q_data *q_data_dst; |
| 1636 | struct coda_ctx *ctx; | 2565 | struct vb2_buffer *dst_buf; |
| 2566 | int width, height; | ||
| 2567 | int decoded_idx; | ||
| 2568 | int display_idx; | ||
| 2569 | u32 src_fourcc; | ||
| 2570 | int success; | ||
| 2571 | u32 val; | ||
| 1637 | 2572 | ||
| 1638 | cancel_delayed_work(&dev->timeout); | 2573 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
| 1639 | 2574 | ||
| 1640 | /* read status register to attend the IRQ */ | 2575 | /* Update kfifo out pointer from coda bitstream read pointer */ |
| 1641 | coda_read(dev, CODA_REG_BIT_INT_STATUS); | 2576 | coda_kfifo_sync_from_device(ctx); |
| 1642 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, | ||
| 1643 | CODA_REG_BIT_INT_CLEAR); | ||
| 1644 | 2577 | ||
| 1645 | ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); | 2578 | /* |
| 1646 | if (ctx == NULL) { | 2579 | * in stream-end mode, the read pointer can overshoot the write pointer |
| 1647 | v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); | 2580 | * by up to 512 bytes |
| 1648 | mutex_unlock(&dev->coda_mutex); | 2581 | */ |
| 1649 | return IRQ_HANDLED; | 2582 | if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { |
| 2583 | if (coda_get_bitstream_payload(ctx) >= 0x100000 - 512) | ||
| 2584 | kfifo_init(&ctx->bitstream_fifo, | ||
| 2585 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
| 1650 | } | 2586 | } |
| 1651 | 2587 | ||
| 1652 | if (ctx->aborting) { | 2588 | q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| 1653 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2589 | src_fourcc = q_data_src->fourcc; |
| 1654 | "task has been aborted\n"); | 2590 | |
| 1655 | mutex_unlock(&dev->coda_mutex); | 2591 | val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); |
| 1656 | return IRQ_HANDLED; | 2592 | if (val != 1) |
| 2593 | pr_err("DEC_PIC_SUCCESS = %d\n", val); | ||
| 2594 | |||
| 2595 | success = val & 0x1; | ||
| 2596 | if (!success) | ||
| 2597 | v4l2_err(&dev->v4l2_dev, "decode failed\n"); | ||
| 2598 | |||
| 2599 | if (src_fourcc == V4L2_PIX_FMT_H264) { | ||
| 2600 | if (val & (1 << 3)) | ||
| 2601 | v4l2_err(&dev->v4l2_dev, | ||
| 2602 | "insufficient PS buffer space (%d bytes)\n", | ||
| 2603 | ctx->psbuf.size); | ||
| 2604 | if (val & (1 << 2)) | ||
| 2605 | v4l2_err(&dev->v4l2_dev, | ||
| 2606 | "insufficient slice buffer space (%d bytes)\n", | ||
| 2607 | ctx->slicebuf.size); | ||
| 1657 | } | 2608 | } |
| 1658 | 2609 | ||
| 1659 | if (coda_isbusy(ctx->dev)) { | 2610 | val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); |
| 1660 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | 2611 | width = (val >> 16) & 0xffff; |
| 1661 | "coda is still busy!!!!\n"); | 2612 | height = val & 0xffff; |
| 1662 | return IRQ_NONE; | 2613 | |
| 2614 | q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
| 2615 | |||
| 2616 | val = coda_read(dev, CODA_RET_DEC_PIC_TYPE); | ||
| 2617 | if ((val & 0x7) == 0) { | ||
| 2618 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; | ||
| 2619 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; | ||
| 2620 | } else { | ||
| 2621 | dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; | ||
| 2622 | dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); | ||
| 2626 | if (val > 0) | ||
| 2627 | v4l2_err(&dev->v4l2_dev, | ||
| 2628 | "errors in %d macroblocks\n", val); | ||
| 2629 | |||
| 2630 | if (dev->devtype->product == CODA_7541) { | ||
| 2631 | val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); | ||
| 2632 | if (val == 0) { | ||
| 2633 | /* not enough bitstream data */ | ||
| 2634 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 2635 | "prescan failed: %d\n", val); | ||
| 2636 | ctx->prescan_failed = true; | ||
| 2637 | return; | ||
| 2638 | } | ||
| 2639 | } | ||
| 2640 | |||
| 2641 | ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
| 2642 | |||
| 2643 | /* | ||
| 2644 | * The previous display frame was copied out by the rotator, | ||
| 2645 | * now it can be overwritten again | ||
| 2646 | */ | ||
| 2647 | if (ctx->display_idx >= 0 && | ||
| 2648 | ctx->display_idx < ctx->num_internal_frames) { | ||
| 2649 | ctx->frm_dis_flg &= ~(1 << ctx->display_idx); | ||
| 2650 | coda_write(dev, ctx->frm_dis_flg, | ||
| 2651 | CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); | ||
| 2652 | } | ||
| 2653 | |||
| 2654 | /* | ||
| 2655 | * The index of the last decoded frame, not necessarily in | ||
| 2656 | * display order, and the index of the next display frame. | ||
| 2657 | * The latter could have been decoded in a previous run. | ||
| 2658 | */ | ||
| 2659 | decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); | ||
| 2660 | display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); | ||
| 2661 | |||
| 2662 | if (decoded_idx == -1) { | ||
| 2663 | /* no frame was decoded, but we might have a display frame */ | ||
| 2664 | if (display_idx < 0 && ctx->display_idx < 0) | ||
| 2665 | ctx->prescan_failed = true; | ||
| 2666 | } else if (decoded_idx == -2) { | ||
| 2667 | /* no frame was decoded, we still return the remaining buffers */ | ||
| 2668 | } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { | ||
| 2669 | v4l2_err(&dev->v4l2_dev, | ||
| 2670 | "decoded frame index out of range: %d\n", decoded_idx); | ||
| 1663 | } | 2671 | } |
| 1664 | 2672 | ||
| 2673 | if (display_idx == -1) { | ||
| 2674 | /* | ||
| 2675 | * no more frames to be decoded, but there could still | ||
| 2676 | * be rotator output to dequeue | ||
| 2677 | */ | ||
| 2678 | ctx->prescan_failed = true; | ||
| 2679 | } else if (display_idx == -3) { | ||
| 2680 | /* possibly prescan failure */ | ||
| 2681 | } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { | ||
| 2682 | v4l2_err(&dev->v4l2_dev, | ||
| 2683 | "presentation frame index out of range: %d\n", | ||
| 2684 | display_idx); | ||
| 2685 | } | ||
| 2686 | |||
| 2687 | /* If a frame was copied out, return it */ | ||
| 2688 | if (ctx->display_idx >= 0 && | ||
| 2689 | ctx->display_idx < ctx->num_internal_frames) { | ||
| 2690 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | ||
| 2691 | dst_buf->v4l2_buf.sequence = ctx->osequence++; | ||
| 2692 | |||
| 2693 | vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); | ||
| 2694 | |||
| 2695 | v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE : | ||
| 2696 | VB2_BUF_STATE_ERROR); | ||
| 2697 | |||
| 2698 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 2699 | "job finished: decoding frame (%d) (%s)\n", | ||
| 2700 | dst_buf->v4l2_buf.sequence, | ||
| 2701 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? | ||
| 2702 | "KEYFRAME" : "PFRAME"); | ||
| 2703 | } else { | ||
| 2704 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 2705 | "job finished: no frame decoded\n"); | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | /* The rotator will copy the current display frame next time */ | ||
| 2709 | ctx->display_idx = display_idx; | ||
| 2710 | } | ||
| 2711 | |||
| 2712 | static void coda_finish_encode(struct coda_ctx *ctx) | ||
| 2713 | { | ||
| 2714 | struct vb2_buffer *src_buf, *dst_buf; | ||
| 2715 | struct coda_dev *dev = ctx->dev; | ||
| 2716 | u32 wr_ptr, start_ptr; | ||
| 2717 | |||
| 1665 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | 2718 | src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); |
| 1666 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | 2719 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); |
| 1667 | 2720 | ||
| 1668 | /* Get results from the coda */ | 2721 | /* Get results from the coda */ |
| 1669 | coda_read(dev, CODA_RET_ENC_PIC_TYPE); | 2722 | coda_read(dev, CODA_RET_ENC_PIC_TYPE); |
| 1670 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); | 2723 | start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); |
| 1671 | wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)); | 2724 | wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); |
| 2725 | |||
| 1672 | /* Calculate bytesused field */ | 2726 | /* Calculate bytesused field */ |
| 1673 | if (dst_buf->v4l2_buf.sequence == 0) { | 2727 | if (dst_buf->v4l2_buf.sequence == 0) { |
| 1674 | dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr) + | 2728 | vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr + |
| 1675 | ctx->vpu_header_size[0] + | 2729 | ctx->vpu_header_size[0] + |
| 1676 | ctx->vpu_header_size[1] + | 2730 | ctx->vpu_header_size[1] + |
| 1677 | ctx->vpu_header_size[2]; | 2731 | ctx->vpu_header_size[2]); |
| 1678 | } else { | 2732 | } else { |
| 1679 | dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr); | 2733 | vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr); |
| 1680 | } | 2734 | } |
| 1681 | 2735 | ||
| 1682 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", | 2736 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", |
| @@ -1708,8 +2762,62 @@ static irqreturn_t coda_irq_handler(int irq, void *data) | |||
| 1708 | dst_buf->v4l2_buf.sequence, | 2762 | dst_buf->v4l2_buf.sequence, |
| 1709 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? | 2763 | (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? |
| 1710 | "KEYFRAME" : "PFRAME"); | 2764 | "KEYFRAME" : "PFRAME"); |
| 2765 | } | ||
| 2766 | |||
| 2767 | static irqreturn_t coda_irq_handler(int irq, void *data) | ||
| 2768 | { | ||
| 2769 | struct coda_dev *dev = data; | ||
| 2770 | struct coda_ctx *ctx; | ||
| 2771 | |||
| 2772 | cancel_delayed_work(&dev->timeout); | ||
| 2773 | |||
| 2774 | /* read status register to attend the IRQ */ | ||
| 2775 | coda_read(dev, CODA_REG_BIT_INT_STATUS); | ||
| 2776 | coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, | ||
| 2777 | CODA_REG_BIT_INT_CLEAR); | ||
| 2778 | |||
| 2779 | ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); | ||
| 2780 | if (ctx == NULL) { | ||
| 2781 | v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); | ||
| 2782 | mutex_unlock(&dev->coda_mutex); | ||
| 2783 | return IRQ_HANDLED; | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | if (ctx->aborting) { | ||
| 2787 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
| 2788 | "task has been aborted\n"); | ||
| 2789 | goto out; | ||
| 2790 | } | ||
| 2791 | |||
| 2792 | if (coda_isbusy(ctx->dev)) { | ||
| 2793 | v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, | ||
| 2794 | "coda is still busy!!!!\n"); | ||
| 2795 | return IRQ_NONE; | ||
| 2796 | } | ||
| 2797 | |||
| 2798 | if (ctx->inst_type == CODA_INST_DECODER) | ||
| 2799 | coda_finish_decode(ctx); | ||
| 2800 | else | ||
| 2801 | coda_finish_encode(ctx); | ||
| 2802 | |||
| 2803 | out: | ||
| 2804 | if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) { | ||
| 2805 | v4l2_dbg(1, coda_debug, &dev->v4l2_dev, | ||
| 2806 | "%s: sent command 'SEQ_END' to coda\n", __func__); | ||
| 2807 | if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { | ||
| 2808 | v4l2_err(&dev->v4l2_dev, | ||
| 2809 | "CODA_COMMAND_SEQ_END failed\n"); | ||
| 2810 | } | ||
| 2811 | |||
| 2812 | kfifo_init(&ctx->bitstream_fifo, | ||
| 2813 | ctx->bitstream.vaddr, ctx->bitstream.size); | ||
| 2814 | |||
| 2815 | coda_free_framebuffers(ctx); | ||
| 2816 | coda_free_context_buffers(ctx); | ||
| 2817 | } | ||
| 1711 | 2818 | ||
| 1712 | mutex_unlock(&dev->coda_mutex); | 2819 | mutex_unlock(&dev->coda_mutex); |
| 2820 | mutex_unlock(&ctx->buffer_mutex); | ||
| 1713 | 2821 | ||
| 1714 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); | 2822 | v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); |
| 1715 | 2823 | ||
| @@ -1726,6 +2834,8 @@ static void coda_timeout(struct work_struct *work) | |||
| 1726 | 2834 | ||
| 1727 | mutex_lock(&dev->dev_mutex); | 2835 | mutex_lock(&dev->dev_mutex); |
| 1728 | list_for_each_entry(ctx, &dev->instances, list) { | 2836 | list_for_each_entry(ctx, &dev->instances, list) { |
| 2837 | if (mutex_is_locked(&ctx->buffer_mutex)) | ||
| 2838 | mutex_unlock(&ctx->buffer_mutex); | ||
| 1729 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 2839 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
| 1730 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | 2840 | v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); |
| 1731 | } | 2841 | } |
| @@ -1738,7 +2848,7 @@ static void coda_timeout(struct work_struct *work) | |||
| 1738 | 2848 | ||
| 1739 | static u32 coda_supported_firmwares[] = { | 2849 | static u32 coda_supported_firmwares[] = { |
| 1740 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), | 2850 | CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), |
| 1741 | CODA_FIRMWARE_VERNUM(CODA_7541, 13, 4, 29), | 2851 | CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), |
| 1742 | }; | 2852 | }; |
| 1743 | 2853 | ||
| 1744 | static bool coda_firmware_supported(u32 vernum) | 2854 | static bool coda_firmware_supported(u32 vernum) |
| @@ -1771,10 +2881,15 @@ static int coda_hw_init(struct coda_dev *dev) | |||
| 1771 | u16 product, major, minor, release; | 2881 | u16 product, major, minor, release; |
| 1772 | u32 data; | 2882 | u32 data; |
| 1773 | u16 *p; | 2883 | u16 *p; |
| 1774 | int i; | 2884 | int i, ret; |
| 1775 | 2885 | ||
| 1776 | clk_prepare_enable(dev->clk_per); | 2886 | ret = clk_prepare_enable(dev->clk_per); |
| 1777 | clk_prepare_enable(dev->clk_ahb); | 2887 | if (ret) |
| 2888 | return ret; | ||
| 2889 | |||
| 2890 | ret = clk_prepare_enable(dev->clk_ahb); | ||
| 2891 | if (ret) | ||
| 2892 | goto err_clk_ahb; | ||
| 1778 | 2893 | ||
| 1779 | /* | 2894 | /* |
| 1780 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. | 2895 | * Copy the first CODA_ISRAM_SIZE in the internal SRAM. |
| @@ -1803,8 +2918,14 @@ static int coda_hw_init(struct coda_dev *dev) | |||
| 1803 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); | 2918 | coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); |
| 1804 | 2919 | ||
| 1805 | /* Tell the BIT where to find everything it needs */ | 2920 | /* Tell the BIT where to find everything it needs */ |
| 1806 | coda_write(dev, dev->workbuf.paddr, | 2921 | if (dev->devtype->product == CODA_7541) { |
| 1807 | CODA_REG_BIT_WORK_BUF_ADDR); | 2922 | coda_write(dev, dev->tempbuf.paddr, |
| 2923 | CODA_REG_BIT_TEMP_BUF_ADDR); | ||
| 2924 | coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); | ||
| 2925 | } else { | ||
| 2926 | coda_write(dev, dev->workbuf.paddr, | ||
| 2927 | CODA_REG_BIT_WORK_BUF_ADDR); | ||
| 2928 | } | ||
| 1808 | coda_write(dev, dev->codebuf.paddr, | 2929 | coda_write(dev, dev->codebuf.paddr, |
| 1809 | CODA_REG_BIT_CODE_BUF_ADDR); | 2930 | CODA_REG_BIT_CODE_BUF_ADDR); |
| 1810 | coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); | 2931 | coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); |
| @@ -1877,6 +2998,10 @@ static int coda_hw_init(struct coda_dev *dev) | |||
| 1877 | } | 2998 | } |
| 1878 | 2999 | ||
| 1879 | return 0; | 3000 | return 0; |
| 3001 | |||
| 3002 | err_clk_ahb: | ||
| 3003 | clk_disable_unprepare(dev->clk_per); | ||
| 3004 | return ret; | ||
| 1880 | } | 3005 | } |
| 1881 | 3006 | ||
| 1882 | static void coda_fw_callback(const struct firmware *fw, void *context) | 3007 | static void coda_fw_callback(const struct firmware *fw, void *context) |
| @@ -1891,11 +3016,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context) | |||
| 1891 | } | 3016 | } |
| 1892 | 3017 | ||
| 1893 | /* allocate auxiliary per-device code buffer for the BIT processor */ | 3018 | /* allocate auxiliary per-device code buffer for the BIT processor */ |
| 1894 | dev->codebuf.size = fw->size; | 3019 | ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size); |
| 1895 | dev->codebuf.vaddr = dma_alloc_coherent(&pdev->dev, fw->size, | 3020 | if (ret < 0) { |
| 1896 | &dev->codebuf.paddr, | ||
| 1897 | GFP_KERNEL); | ||
| 1898 | if (!dev->codebuf.vaddr) { | ||
| 1899 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); | 3021 | dev_err(&pdev->dev, "failed to allocate code buffer\n"); |
| 1900 | return; | 3022 | return; |
| 1901 | } | 3023 | } |
| @@ -2032,11 +3154,6 @@ static int coda_probe(struct platform_device *pdev) | |||
| 2032 | 3154 | ||
| 2033 | /* Get memory for physical registers */ | 3155 | /* Get memory for physical registers */ |
| 2034 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 3156 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2035 | if (res == NULL) { | ||
| 2036 | dev_err(&pdev->dev, "failed to get memory region resource\n"); | ||
| 2037 | return -ENOENT; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); | 3157 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); |
| 2041 | if (IS_ERR(dev->regs_base)) | 3158 | if (IS_ERR(dev->regs_base)) |
| 2042 | return PTR_ERR(dev->regs_base); | 3159 | return PTR_ERR(dev->regs_base); |
| @@ -2048,8 +3165,8 @@ static int coda_probe(struct platform_device *pdev) | |||
| 2048 | return -ENOENT; | 3165 | return -ENOENT; |
| 2049 | } | 3166 | } |
| 2050 | 3167 | ||
| 2051 | if (devm_request_irq(&pdev->dev, irq, coda_irq_handler, | 3168 | if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler, |
| 2052 | 0, CODA_NAME, dev) < 0) { | 3169 | IRQF_ONESHOT, CODA_NAME, dev) < 0) { |
| 2053 | dev_err(&pdev->dev, "failed to request irq\n"); | 3170 | dev_err(&pdev->dev, "failed to request irq\n"); |
| 2054 | return -ENOENT; | 3171 | return -ENOENT; |
| 2055 | } | 3172 | } |
| @@ -2085,24 +3202,36 @@ static int coda_probe(struct platform_device *pdev) | |||
| 2085 | /* allocate auxiliary per-device buffers for the BIT processor */ | 3202 | /* allocate auxiliary per-device buffers for the BIT processor */ |
| 2086 | switch (dev->devtype->product) { | 3203 | switch (dev->devtype->product) { |
| 2087 | case CODA_DX6: | 3204 | case CODA_DX6: |
| 2088 | dev->workbuf.size = CODADX6_WORK_BUF_SIZE; | 3205 | ret = coda_alloc_aux_buf(dev, &dev->workbuf, |
| 3206 | CODADX6_WORK_BUF_SIZE); | ||
| 3207 | if (ret < 0) { | ||
| 3208 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); | ||
| 3209 | v4l2_device_unregister(&dev->v4l2_dev); | ||
| 3210 | return ret; | ||
| 3211 | } | ||
| 3212 | break; | ||
| 3213 | case CODA_7541: | ||
| 3214 | dev->tempbuf.size = CODA7_TEMP_BUF_SIZE; | ||
| 2089 | break; | 3215 | break; |
| 2090 | default: | ||
| 2091 | dev->workbuf.size = CODA7_WORK_BUF_SIZE; | ||
| 2092 | } | 3216 | } |
| 2093 | dev->workbuf.vaddr = dma_alloc_coherent(&pdev->dev, dev->workbuf.size, | 3217 | if (dev->tempbuf.size) { |
| 2094 | &dev->workbuf.paddr, | 3218 | ret = coda_alloc_aux_buf(dev, &dev->tempbuf, |
| 2095 | GFP_KERNEL); | 3219 | dev->tempbuf.size); |
| 2096 | if (!dev->workbuf.vaddr) { | 3220 | if (ret < 0) { |
| 2097 | dev_err(&pdev->dev, "failed to allocate work buffer\n"); | 3221 | dev_err(&pdev->dev, "failed to allocate temp buffer\n"); |
| 2098 | v4l2_device_unregister(&dev->v4l2_dev); | 3222 | v4l2_device_unregister(&dev->v4l2_dev); |
| 2099 | return -ENOMEM; | 3223 | return ret; |
| 3224 | } | ||
| 2100 | } | 3225 | } |
| 2101 | 3226 | ||
| 2102 | if (dev->devtype->product == CODA_DX6) | 3227 | switch (dev->devtype->product) { |
| 3228 | case CODA_DX6: | ||
| 2103 | dev->iram_size = CODADX6_IRAM_SIZE; | 3229 | dev->iram_size = CODADX6_IRAM_SIZE; |
| 2104 | else | 3230 | break; |
| 3231 | case CODA_7541: | ||
| 2105 | dev->iram_size = CODA7_IRAM_SIZE; | 3232 | dev->iram_size = CODA7_IRAM_SIZE; |
| 3233 | break; | ||
| 3234 | } | ||
| 2106 | dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size); | 3235 | dev->iram_vaddr = gen_pool_alloc(dev->iram_pool, dev->iram_size); |
| 2107 | if (!dev->iram_vaddr) { | 3236 | if (!dev->iram_vaddr) { |
| 2108 | dev_err(&pdev->dev, "unable to alloc iram\n"); | 3237 | dev_err(&pdev->dev, "unable to alloc iram\n"); |
| @@ -2128,12 +3257,9 @@ static int coda_remove(struct platform_device *pdev) | |||
| 2128 | v4l2_device_unregister(&dev->v4l2_dev); | 3257 | v4l2_device_unregister(&dev->v4l2_dev); |
| 2129 | if (dev->iram_vaddr) | 3258 | if (dev->iram_vaddr) |
| 2130 | gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size); | 3259 | gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size); |
| 2131 | if (dev->codebuf.vaddr) | 3260 | coda_free_aux_buf(dev, &dev->codebuf); |
| 2132 | dma_free_coherent(&pdev->dev, dev->codebuf.size, | 3261 | coda_free_aux_buf(dev, &dev->tempbuf); |
| 2133 | &dev->codebuf.vaddr, dev->codebuf.paddr); | 3262 | coda_free_aux_buf(dev, &dev->workbuf); |
| 2134 | if (dev->workbuf.vaddr) | ||
| 2135 | dma_free_coherent(&pdev->dev, dev->workbuf.size, &dev->workbuf.vaddr, | ||
| 2136 | dev->workbuf.paddr); | ||
| 2137 | return 0; | 3263 | return 0; |
| 2138 | } | 3264 | } |
| 2139 | 3265 | ||
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index ace0bf0a3b9c..4e32e2edea62 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h | |||
| @@ -43,14 +43,26 @@ | |||
| 43 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) | 43 | #define CODA_STREAM_ENDIAN_SELECT (1 << 0) |
| 44 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 | 44 | #define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 |
| 45 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) | 45 | #define CODA_IMAGE_ENDIAN_SELECT (1 << 0) |
| 46 | #define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 | ||
| 47 | #define CODA_BIT_STREAM_END_FLAG (1 << 2) | ||
| 48 | #define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0) | ||
| 49 | #define CODA_REG_BIT_TEMP_BUF_ADDR 0x118 | ||
| 46 | #define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) | 50 | #define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) |
| 47 | #define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) | 51 | #define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) |
| 52 | #define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) | ||
| 48 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 | 53 | #define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 |
| 49 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 | 54 | #define CODA7_REG_BIT_AXI_SRAM_USE 0x140 |
| 50 | #define CODA7_USE_BIT_ENABLE (1 << 0) | 55 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) |
| 56 | #define CODA7_USE_HOST_OVL_ENABLE (1 << 10) | ||
| 57 | #define CODA7_USE_HOST_DBK_ENABLE (1 << 9) | ||
| 58 | #define CODA7_USE_HOST_IP_ENABLE (1 << 8) | ||
| 51 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) | 59 | #define CODA7_USE_HOST_BIT_ENABLE (1 << 7) |
| 52 | #define CODA7_USE_ME_ENABLE (1 << 4) | 60 | #define CODA7_USE_ME_ENABLE (1 << 4) |
| 53 | #define CODA7_USE_HOST_ME_ENABLE (1 << 11) | 61 | #define CODA7_USE_OVL_ENABLE (1 << 3) |
| 62 | #define CODA7_USE_DBK_ENABLE (1 << 2) | ||
| 63 | #define CODA7_USE_IP_ENABLE (1 << 1) | ||
| 64 | #define CODA7_USE_BIT_ENABLE (1 << 0) | ||
| 65 | |||
| 54 | #define CODA_REG_BIT_BUSY 0x160 | 66 | #define CODA_REG_BIT_BUSY 0x160 |
| 55 | #define CODA_REG_BIT_BUSY_FLAG 1 | 67 | #define CODA_REG_BIT_BUSY_FLAG 1 |
| 56 | #define CODA_REG_BIT_RUN_COMMAND 0x164 | 68 | #define CODA_REG_BIT_RUN_COMMAND 0x164 |
| @@ -84,6 +96,15 @@ | |||
| 84 | #define CODA_MODE_INVALID 0xffff | 96 | #define CODA_MODE_INVALID 0xffff |
| 85 | #define CODA_REG_BIT_INT_ENABLE 0x170 | 97 | #define CODA_REG_BIT_INT_ENABLE 0x170 |
| 86 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) | 98 | #define CODA_INT_INTERRUPT_ENABLE (1 << 3) |
| 99 | #define CODA_REG_BIT_INT_REASON 0x174 | ||
| 100 | #define CODA7_REG_BIT_RUN_AUX_STD 0x178 | ||
| 101 | #define CODA_MP4_AUX_MPEG4 0 | ||
| 102 | #define CODA_MP4_AUX_DIVX3 1 | ||
| 103 | #define CODA_VPX_AUX_THO 0 | ||
| 104 | #define CODA_VPX_AUX_VP6 1 | ||
| 105 | #define CODA_VPX_AUX_VP8 2 | ||
| 106 | #define CODA_H264_AUX_AVC 0 | ||
| 107 | #define CODA_H264_AUX_MVC 1 | ||
| 87 | 108 | ||
| 88 | /* | 109 | /* |
| 89 | * Commands' mailbox: | 110 | * Commands' mailbox: |
| @@ -92,15 +113,89 @@ | |||
| 92 | * issued. | 113 | * issued. |
| 93 | */ | 114 | */ |
| 94 | 115 | ||
| 116 | /* Decoder Sequence Initialization */ | ||
| 117 | #define CODA_CMD_DEC_SEQ_BB_START 0x180 | ||
| 118 | #define CODA_CMD_DEC_SEQ_BB_SIZE 0x184 | ||
| 119 | #define CODA_CMD_DEC_SEQ_OPTION 0x188 | ||
| 120 | #define CODA_REORDER_ENABLE (1 << 1) | ||
| 121 | #define CODADX6_QP_REPORT (1 << 0) | ||
| 122 | #define CODA7_MP4_DEBLK_ENABLE (1 << 0) | ||
| 123 | #define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c | ||
| 124 | #define CODA_CMD_DEC_SEQ_START_BYTE 0x190 | ||
| 125 | #define CODA_CMD_DEC_SEQ_PS_BB_START 0x194 | ||
| 126 | #define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198 | ||
| 127 | #define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c | ||
| 128 | #define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c | ||
| 129 | #define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 | ||
| 130 | |||
| 131 | #define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 | ||
| 132 | #define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 | ||
| 133 | #define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ | ||
| 134 | #define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 | ||
| 135 | #define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8 | ||
| 136 | #define CODA9_RET_DEC_SEQ_ASPECT 0x1c8 | ||
| 137 | #define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc | ||
| 138 | #define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0 | ||
| 139 | #define CODA_RET_DEC_SEQ_INFO 0x1d4 | ||
| 140 | #define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8 | ||
| 141 | #define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc | ||
| 142 | #define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0 | ||
| 143 | #define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0 | ||
| 144 | #define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4 | ||
| 145 | #define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 | ||
| 146 | #define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 | ||
| 147 | #define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 | ||
| 148 | |||
| 149 | /* Decoder Picture Run */ | ||
| 150 | #define CODA_CMD_DEC_PIC_ROT_MODE 0x180 | ||
| 151 | #define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 | ||
| 152 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 | ||
| 153 | #define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c | ||
| 154 | #define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 | ||
| 155 | |||
| 156 | #define CODA_CMD_DEC_PIC_OPTION 0x194 | ||
| 157 | #define CODA_PRE_SCAN_EN (1 << 0) | ||
| 158 | #define CODA_PRE_SCAN_MODE_DECODE (0 << 1) | ||
| 159 | #define CODA_PRE_SCAN_MODE_RETURN (1 << 1) | ||
| 160 | #define CODA_IFRAME_SEARCH_EN (1 << 2) | ||
| 161 | #define CODA_SKIP_FRAME_MODE (0x3 << 3) | ||
| 162 | #define CODA_CMD_DEC_PIC_SKIP_NUM 0x198 | ||
| 163 | #define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c | ||
| 164 | #define CODA_CMD_DEC_PIC_BB_START 0x1a0 | ||
| 165 | #define CODA_CMD_DEC_PIC_START_BYTE 0x1a4 | ||
| 166 | #define CODA_RET_DEC_PIC_SIZE 0x1bc | ||
| 167 | #define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0 | ||
| 168 | #define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4 | ||
| 169 | #define CODA_RET_DEC_PIC_ERR_MB 0x1c8 | ||
| 170 | #define CODA_RET_DEC_PIC_TYPE 0x1cc | ||
| 171 | #define CODA_PIC_TYPE_MASK 0x7 | ||
| 172 | #define CODA_PIC_TYPE_MASK_VC1 0x3f | ||
| 173 | #define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3) | ||
| 174 | #define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6) | ||
| 175 | #define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16) | ||
| 176 | #define CODA7_PIC_TYPE_INTERLACED (1 << 18) | ||
| 177 | #define CODA_RET_DEC_PIC_POST 0x1d0 | ||
| 178 | #define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0 | ||
| 179 | #define CODA_RET_DEC_PIC_OPTION 0x1d4 | ||
| 180 | #define CODA_RET_DEC_PIC_SUCCESS 0x1d8 | ||
| 181 | #define CODA_RET_DEC_PIC_CUR_IDX 0x1dc | ||
| 182 | #define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0 | ||
| 183 | #define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 | ||
| 184 | #define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec | ||
| 185 | |||
| 95 | /* Encoder Sequence Initialization */ | 186 | /* Encoder Sequence Initialization */ |
| 96 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 | 187 | #define CODA_CMD_ENC_SEQ_BB_START 0x180 |
| 97 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 | 188 | #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 |
| 98 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 | 189 | #define CODA_CMD_ENC_SEQ_OPTION 0x188 |
| 190 | #define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 | ||
| 99 | #define CODA7_OPTION_GAMMA_OFFSET 8 | 191 | #define CODA7_OPTION_GAMMA_OFFSET 8 |
| 192 | #define CODA7_OPTION_RCQPMAX_OFFSET 7 | ||
| 100 | #define CODADX6_OPTION_GAMMA_OFFSET 7 | 193 | #define CODADX6_OPTION_GAMMA_OFFSET 7 |
| 194 | #define CODA7_OPTION_RCQPMIN_OFFSET 6 | ||
| 101 | #define CODA_OPTION_LIMITQP_OFFSET 6 | 195 | #define CODA_OPTION_LIMITQP_OFFSET 6 |
| 102 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 | 196 | #define CODA_OPTION_RCINTRAQP_OFFSET 5 |
| 103 | #define CODA_OPTION_FMO_OFFSET 4 | 197 | #define CODA_OPTION_FMO_OFFSET 4 |
| 198 | #define CODA_OPTION_AVC_AUD_OFFSET 2 | ||
| 104 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 | 199 | #define CODA_OPTION_SLICEREPORT_OFFSET 1 |
| 105 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c | 200 | #define CODA_CMD_ENC_SEQ_COD_STD 0x18c |
| 106 | #define CODA_STD_MPEG4 0 | 201 | #define CODA_STD_MPEG4 0 |
| @@ -169,8 +264,10 @@ | |||
| 169 | #define CODA_FMOPARAM_TYPE_MASK 1 | 264 | #define CODA_FMOPARAM_TYPE_MASK 1 |
| 170 | #define CODA_FMOPARAM_SLICENUM_OFFSET 0 | 265 | #define CODA_FMOPARAM_SLICENUM_OFFSET 0 |
| 171 | #define CODA_FMOPARAM_SLICENUM_MASK 0x0f | 266 | #define CODA_FMOPARAM_SLICENUM_MASK 0x0f |
| 267 | #define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc | ||
| 172 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 | 268 | #define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 |
| 173 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc | 269 | #define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc |
| 270 | #define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 | ||
| 174 | #define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 | 271 | #define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 |
| 175 | #define CODA_QPMAX_OFFSET 0 | 272 | #define CODA_QPMAX_OFFSET 0 |
| 176 | #define CODA_QPMAX_MASK 0x3f | 273 | #define CODA_QPMAX_MASK 0x3f |
| @@ -197,18 +294,24 @@ | |||
| 197 | #define CODA_CMD_ENC_PIC_OPTION 0x194 | 294 | #define CODA_CMD_ENC_PIC_OPTION 0x194 |
| 198 | #define CODA_CMD_ENC_PIC_BB_START 0x198 | 295 | #define CODA_CMD_ENC_PIC_BB_START 0x198 |
| 199 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c | 296 | #define CODA_CMD_ENC_PIC_BB_SIZE 0x19c |
| 297 | #define CODA_RET_ENC_FRAME_NUM 0x1c0 | ||
| 200 | #define CODA_RET_ENC_PIC_TYPE 0x1c4 | 298 | #define CODA_RET_ENC_PIC_TYPE 0x1c4 |
| 299 | #define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8 | ||
| 201 | #define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc | 300 | #define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc |
| 202 | #define CODA_RET_ENC_PIC_FLAG 0x1d0 | 301 | #define CODA_RET_ENC_PIC_FLAG 0x1d0 |
| 302 | #define CODA_RET_ENC_PIC_SUCCESS 0x1d8 | ||
| 203 | 303 | ||
| 204 | /* Set Frame Buffer */ | 304 | /* Set Frame Buffer */ |
| 205 | #define CODA_CMD_SET_FRAME_BUF_NUM 0x180 | 305 | #define CODA_CMD_SET_FRAME_BUF_NUM 0x180 |
| 206 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 | 306 | #define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 |
| 307 | #define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 | ||
| 308 | #define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c | ||
| 207 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 | 309 | #define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 |
| 208 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 | 310 | #define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 |
| 209 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 | 311 | #define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 |
| 210 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c | 312 | #define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c |
| 211 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 | 313 | #define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 |
| 314 | #define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 | ||
| 212 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 | 315 | #define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 |
| 213 | 316 | ||
| 214 | /* Encoder Header */ | 317 | /* Encoder Header */ |
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index e180ff7282d9..04609cc6eba7 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c | |||
| @@ -1743,11 +1743,10 @@ static int vpbe_display_probe(struct platform_device *pdev) | |||
| 1743 | 1743 | ||
| 1744 | printk(KERN_DEBUG "vpbe_display_probe\n"); | 1744 | printk(KERN_DEBUG "vpbe_display_probe\n"); |
| 1745 | /* Allocate memory for vpbe_display */ | 1745 | /* Allocate memory for vpbe_display */ |
| 1746 | disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL); | 1746 | disp_dev = devm_kzalloc(&pdev->dev, sizeof(struct vpbe_display), |
| 1747 | if (!disp_dev) { | 1747 | GFP_KERNEL); |
| 1748 | printk(KERN_ERR "ran out of memory\n"); | 1748 | if (!disp_dev) |
| 1749 | return -ENOMEM; | 1749 | return -ENOMEM; |
| 1750 | } | ||
| 1751 | 1750 | ||
| 1752 | spin_lock_init(&disp_dev->dma_queue_lock); | 1751 | spin_lock_init(&disp_dev->dma_queue_lock); |
| 1753 | /* | 1752 | /* |
| @@ -1786,26 +1785,24 @@ static int vpbe_display_probe(struct platform_device *pdev) | |||
| 1786 | } | 1785 | } |
| 1787 | 1786 | ||
| 1788 | irq = res->start; | 1787 | irq = res->start; |
| 1789 | if (request_irq(irq, venc_isr, IRQF_DISABLED, VPBE_DISPLAY_DRIVER, | 1788 | err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED, |
| 1790 | disp_dev)) { | 1789 | VPBE_DISPLAY_DRIVER, disp_dev); |
| 1790 | if (err) { | ||
| 1791 | v4l2_err(&disp_dev->vpbe_dev->v4l2_dev, | 1791 | v4l2_err(&disp_dev->vpbe_dev->v4l2_dev, |
| 1792 | "Unable to request interrupt\n"); | 1792 | "Unable to request interrupt\n"); |
| 1793 | err = -ENODEV; | ||
| 1794 | goto probe_out; | 1793 | goto probe_out; |
| 1795 | } | 1794 | } |
| 1796 | 1795 | ||
| 1797 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { | 1796 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { |
| 1798 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { | 1797 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { |
| 1799 | err = -ENODEV; | 1798 | err = -ENODEV; |
| 1800 | goto probe_out_irq; | 1799 | goto probe_out; |
| 1801 | } | 1800 | } |
| 1802 | } | 1801 | } |
| 1803 | 1802 | ||
| 1804 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); | 1803 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); |
| 1805 | return 0; | 1804 | return 0; |
| 1806 | 1805 | ||
| 1807 | probe_out_irq: | ||
| 1808 | free_irq(res->start, disp_dev); | ||
| 1809 | probe_out: | 1806 | probe_out: |
| 1810 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { | 1807 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { |
| 1811 | /* Get the pointer to the layer object */ | 1808 | /* Get the pointer to the layer object */ |
| @@ -1817,7 +1814,6 @@ probe_out: | |||
| 1817 | kfree(disp_dev->dev[k]); | 1814 | kfree(disp_dev->dev[k]); |
| 1818 | } | 1815 | } |
| 1819 | } | 1816 | } |
| 1820 | kfree(disp_dev); | ||
| 1821 | return err; | 1817 | return err; |
| 1822 | } | 1818 | } |
| 1823 | 1819 | ||
| @@ -1830,15 +1826,10 @@ static int vpbe_display_remove(struct platform_device *pdev) | |||
| 1830 | struct vpbe_layer *vpbe_display_layer; | 1826 | struct vpbe_layer *vpbe_display_layer; |
| 1831 | struct vpbe_display *disp_dev = platform_get_drvdata(pdev); | 1827 | struct vpbe_display *disp_dev = platform_get_drvdata(pdev); |
| 1832 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; | 1828 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; |
| 1833 | struct resource *res; | ||
| 1834 | int i; | 1829 | int i; |
| 1835 | 1830 | ||
| 1836 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n"); | 1831 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n"); |
| 1837 | 1832 | ||
| 1838 | /* unregister irq */ | ||
| 1839 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 1840 | free_irq(res->start, disp_dev); | ||
| 1841 | |||
| 1842 | /* deinitialize the vpbe display controller */ | 1833 | /* deinitialize the vpbe display controller */ |
| 1843 | if (NULL != vpbe_dev->ops.deinitialize) | 1834 | if (NULL != vpbe_dev->ops.deinitialize) |
| 1844 | vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev); | 1835 | vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev); |
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 6ed82e8b297b..d053c2669c1f 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c | |||
| @@ -1547,61 +1547,36 @@ static int osd_probe(struct platform_device *pdev) | |||
| 1547 | const struct platform_device_id *pdev_id; | 1547 | const struct platform_device_id *pdev_id; |
| 1548 | struct osd_state *osd; | 1548 | struct osd_state *osd; |
| 1549 | struct resource *res; | 1549 | struct resource *res; |
| 1550 | int ret = 0; | ||
| 1551 | 1550 | ||
| 1552 | osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL); | 1551 | pdev_id = platform_get_device_id(pdev); |
| 1552 | if (!pdev_id) | ||
| 1553 | return -EINVAL; | ||
| 1554 | |||
| 1555 | osd = devm_kzalloc(&pdev->dev, sizeof(struct osd_state), GFP_KERNEL); | ||
| 1553 | if (osd == NULL) | 1556 | if (osd == NULL) |
| 1554 | return -ENOMEM; | 1557 | return -ENOMEM; |
| 1555 | 1558 | ||
| 1556 | pdev_id = platform_get_device_id(pdev); | ||
| 1557 | if (!pdev_id) { | ||
| 1558 | ret = -EINVAL; | ||
| 1559 | goto free_mem; | ||
| 1560 | } | ||
| 1561 | 1559 | ||
| 1562 | osd->dev = &pdev->dev; | 1560 | osd->dev = &pdev->dev; |
| 1563 | osd->vpbe_type = pdev_id->driver_data; | 1561 | osd->vpbe_type = pdev_id->driver_data; |
| 1564 | 1562 | ||
| 1565 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1563 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1566 | if (!res) { | 1564 | osd->osd_base = devm_ioremap_resource(&pdev->dev, res); |
| 1567 | dev_err(osd->dev, "Unable to get OSD register address map\n"); | 1565 | if (IS_ERR(osd->osd_base)) |
| 1568 | ret = -ENODEV; | 1566 | return PTR_ERR(osd->osd_base); |
| 1569 | goto free_mem; | 1567 | |
| 1570 | } | ||
| 1571 | osd->osd_base_phys = res->start; | 1568 | osd->osd_base_phys = res->start; |
| 1572 | osd->osd_size = resource_size(res); | 1569 | osd->osd_size = resource_size(res); |
| 1573 | if (!request_mem_region(osd->osd_base_phys, osd->osd_size, | ||
| 1574 | MODULE_NAME)) { | ||
| 1575 | dev_err(osd->dev, "Unable to reserve OSD MMIO region\n"); | ||
| 1576 | ret = -ENODEV; | ||
| 1577 | goto free_mem; | ||
| 1578 | } | ||
| 1579 | osd->osd_base = ioremap_nocache(res->start, osd->osd_size); | ||
| 1580 | if (!osd->osd_base) { | ||
| 1581 | dev_err(osd->dev, "Unable to map the OSD region\n"); | ||
| 1582 | ret = -ENODEV; | ||
| 1583 | goto release_mem_region; | ||
| 1584 | } | ||
| 1585 | spin_lock_init(&osd->lock); | 1570 | spin_lock_init(&osd->lock); |
| 1586 | osd->ops = osd_ops; | 1571 | osd->ops = osd_ops; |
| 1587 | platform_set_drvdata(pdev, osd); | 1572 | platform_set_drvdata(pdev, osd); |
| 1588 | dev_notice(osd->dev, "OSD sub device probe success\n"); | 1573 | dev_notice(osd->dev, "OSD sub device probe success\n"); |
| 1589 | return ret; | ||
| 1590 | 1574 | ||
| 1591 | release_mem_region: | 1575 | return 0; |
| 1592 | release_mem_region(osd->osd_base_phys, osd->osd_size); | ||
| 1593 | free_mem: | ||
| 1594 | kfree(osd); | ||
| 1595 | return ret; | ||
| 1596 | } | 1576 | } |
| 1597 | 1577 | ||
| 1598 | static int osd_remove(struct platform_device *pdev) | 1578 | static int osd_remove(struct platform_device *pdev) |
| 1599 | { | 1579 | { |
| 1600 | struct osd_state *osd = platform_get_drvdata(pdev); | ||
| 1601 | |||
| 1602 | iounmap((void *)osd->osd_base); | ||
| 1603 | release_mem_region(osd->osd_base_phys, osd->osd_size); | ||
| 1604 | kfree(osd); | ||
| 1605 | return 0; | 1580 | return 0; |
| 1606 | } | 1581 | } |
| 1607 | 1582 | ||
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 87eef9be08ed..14a023a75d2d 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c | |||
| @@ -639,105 +639,46 @@ static int venc_probe(struct platform_device *pdev) | |||
| 639 | const struct platform_device_id *pdev_id; | 639 | const struct platform_device_id *pdev_id; |
| 640 | struct venc_state *venc; | 640 | struct venc_state *venc; |
| 641 | struct resource *res; | 641 | struct resource *res; |
| 642 | int ret; | ||
| 643 | 642 | ||
| 644 | venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL); | 643 | if (!pdev->dev.platform_data) { |
| 644 | dev_err(&pdev->dev, "No platform data for VENC sub device"); | ||
| 645 | return -EINVAL; | ||
| 646 | } | ||
| 647 | |||
| 648 | pdev_id = platform_get_device_id(pdev); | ||
| 649 | if (!pdev_id) | ||
| 650 | return -EINVAL; | ||
| 651 | |||
| 652 | venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL); | ||
| 645 | if (venc == NULL) | 653 | if (venc == NULL) |
| 646 | return -ENOMEM; | 654 | return -ENOMEM; |
| 647 | 655 | ||
| 648 | pdev_id = platform_get_device_id(pdev); | ||
| 649 | if (!pdev_id) { | ||
| 650 | ret = -EINVAL; | ||
| 651 | goto free_mem; | ||
| 652 | } | ||
| 653 | venc->venc_type = pdev_id->driver_data; | 656 | venc->venc_type = pdev_id->driver_data; |
| 654 | venc->pdev = &pdev->dev; | 657 | venc->pdev = &pdev->dev; |
| 655 | venc->pdata = pdev->dev.platform_data; | 658 | venc->pdata = pdev->dev.platform_data; |
| 656 | if (NULL == venc->pdata) { | 659 | |
| 657 | dev_err(venc->pdev, "Unable to get platform data for" | ||
| 658 | " VENC sub device"); | ||
| 659 | ret = -ENOENT; | ||
| 660 | goto free_mem; | ||
| 661 | } | ||
| 662 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 660 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 663 | if (!res) { | ||
| 664 | dev_err(venc->pdev, | ||
| 665 | "Unable to get VENC register address map\n"); | ||
| 666 | ret = -ENODEV; | ||
| 667 | goto free_mem; | ||
| 668 | } | ||
| 669 | 661 | ||
| 670 | if (!request_mem_region(res->start, resource_size(res), "venc")) { | 662 | venc->venc_base = devm_ioremap_resource(&pdev->dev, res); |
| 671 | dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n"); | 663 | if (IS_ERR(venc->venc_base)) |
| 672 | ret = -ENODEV; | 664 | return PTR_ERR(venc->venc_base); |
| 673 | goto free_mem; | ||
| 674 | } | ||
| 675 | |||
| 676 | venc->venc_base = ioremap_nocache(res->start, resource_size(res)); | ||
| 677 | if (!venc->venc_base) { | ||
| 678 | dev_err(venc->pdev, "Unable to map VENC IO space\n"); | ||
| 679 | ret = -ENODEV; | ||
| 680 | goto release_venc_mem_region; | ||
| 681 | } | ||
| 682 | 665 | ||
| 683 | if (venc->venc_type != VPBE_VERSION_1) { | 666 | if (venc->venc_type != VPBE_VERSION_1) { |
| 684 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 667 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| 685 | if (!res) { | 668 | |
| 686 | dev_err(venc->pdev, | 669 | venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res); |
| 687 | "Unable to get VDAC_CONFIG address map\n"); | 670 | if (IS_ERR(venc->vdaccfg_reg)) |
| 688 | ret = -ENODEV; | 671 | return PTR_ERR(venc->vdaccfg_reg); |
| 689 | goto unmap_venc_io; | ||
| 690 | } | ||
| 691 | |||
| 692 | if (!request_mem_region(res->start, | ||
| 693 | resource_size(res), "venc")) { | ||
| 694 | dev_err(venc->pdev, | ||
| 695 | "Unable to reserve VDAC_CONFIG MMIO region\n"); | ||
| 696 | ret = -ENODEV; | ||
| 697 | goto unmap_venc_io; | ||
| 698 | } | ||
| 699 | |||
| 700 | venc->vdaccfg_reg = ioremap_nocache(res->start, | ||
| 701 | resource_size(res)); | ||
| 702 | if (!venc->vdaccfg_reg) { | ||
| 703 | dev_err(venc->pdev, | ||
| 704 | "Unable to map VDAC_CONFIG IO space\n"); | ||
| 705 | ret = -ENODEV; | ||
| 706 | goto release_vdaccfg_mem_region; | ||
| 707 | } | ||
| 708 | } | 672 | } |
| 709 | spin_lock_init(&venc->lock); | 673 | spin_lock_init(&venc->lock); |
| 710 | platform_set_drvdata(pdev, venc); | 674 | platform_set_drvdata(pdev, venc); |
| 711 | dev_notice(venc->pdev, "VENC sub device probe success\n"); | 675 | dev_notice(venc->pdev, "VENC sub device probe success\n"); |
| 712 | return 0; | ||
| 713 | 676 | ||
| 714 | release_vdaccfg_mem_region: | 677 | return 0; |
| 715 | release_mem_region(res->start, resource_size(res)); | ||
| 716 | unmap_venc_io: | ||
| 717 | iounmap(venc->venc_base); | ||
| 718 | release_venc_mem_region: | ||
| 719 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 720 | release_mem_region(res->start, resource_size(res)); | ||
| 721 | free_mem: | ||
| 722 | kfree(venc); | ||
| 723 | return ret; | ||
| 724 | } | 678 | } |
| 725 | 679 | ||
| 726 | static int venc_remove(struct platform_device *pdev) | 680 | static int venc_remove(struct platform_device *pdev) |
| 727 | { | 681 | { |
| 728 | struct venc_state *venc = platform_get_drvdata(pdev); | ||
| 729 | struct resource *res; | ||
| 730 | |||
| 731 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 732 | iounmap((void *)venc->venc_base); | ||
| 733 | release_mem_region(res->start, resource_size(res)); | ||
| 734 | if (venc->venc_type != VPBE_VERSION_1) { | ||
| 735 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 736 | iounmap((void *)venc->vdaccfg_reg); | ||
| 737 | release_mem_region(res->start, resource_size(res)); | ||
| 738 | } | ||
| 739 | kfree(venc); | ||
| 740 | |||
| 741 | return 0; | 682 | return 0; |
| 742 | } | 683 | } |
| 743 | 684 | ||
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 5514175bbd07..1089834a4efe 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c | |||
| @@ -1799,19 +1799,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
| 1799 | 1799 | ||
| 1800 | /* Configure video port timings */ | 1800 | /* Configure video port timings */ |
| 1801 | 1801 | ||
| 1802 | std_info->eav2sav = bt->hbackporch + bt->hfrontporch + | 1802 | std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8; |
| 1803 | bt->hsync - 8; | ||
| 1804 | std_info->sav2eav = bt->width; | 1803 | std_info->sav2eav = bt->width; |
| 1805 | 1804 | ||
| 1806 | std_info->l1 = 1; | 1805 | std_info->l1 = 1; |
| 1807 | std_info->l3 = bt->vsync + bt->vbackporch + 1; | 1806 | std_info->l3 = bt->vsync + bt->vbackporch + 1; |
| 1808 | 1807 | ||
| 1808 | std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
| 1809 | if (bt->interlaced) { | 1809 | if (bt->interlaced) { |
| 1810 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { | 1810 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { |
| 1811 | std_info->vsize = bt->height * 2 + | ||
| 1812 | bt->vfrontporch + bt->vsync + bt->vbackporch + | ||
| 1813 | bt->il_vfrontporch + bt->il_vsync + | ||
| 1814 | bt->il_vbackporch; | ||
| 1815 | std_info->l5 = std_info->vsize/2 - | 1811 | std_info->l5 = std_info->vsize/2 - |
| 1816 | (bt->vfrontporch - 1); | 1812 | (bt->vfrontporch - 1); |
| 1817 | std_info->l7 = std_info->vsize/2 + 1; | 1813 | std_info->l7 = std_info->vsize/2 + 1; |
| @@ -1825,8 +1821,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
| 1825 | return -EINVAL; | 1821 | return -EINVAL; |
| 1826 | } | 1822 | } |
| 1827 | } else { | 1823 | } else { |
| 1828 | std_info->vsize = bt->height + bt->vfrontporch + | ||
| 1829 | bt->vsync + bt->vbackporch; | ||
| 1830 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); | 1824 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); |
| 1831 | } | 1825 | } |
| 1832 | strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); | 1826 | strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); |
| @@ -1979,6 +1973,76 @@ vpif_init_free_channel_objects: | |||
| 1979 | return err; | 1973 | return err; |
| 1980 | } | 1974 | } |
| 1981 | 1975 | ||
| 1976 | static int vpif_async_bound(struct v4l2_async_notifier *notifier, | ||
| 1977 | struct v4l2_subdev *subdev, | ||
| 1978 | struct v4l2_async_subdev *asd) | ||
| 1979 | { | ||
| 1980 | int i; | ||
| 1981 | |||
| 1982 | for (i = 0; i < vpif_obj.config->subdev_count; i++) | ||
| 1983 | if (!strcmp(vpif_obj.config->subdev_info[i].name, | ||
| 1984 | subdev->name)) { | ||
| 1985 | vpif_obj.sd[i] = subdev; | ||
| 1986 | return 0; | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | return -EINVAL; | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | static int vpif_probe_complete(void) | ||
| 1993 | { | ||
| 1994 | struct common_obj *common; | ||
| 1995 | struct channel_obj *ch; | ||
| 1996 | int i, j, err, k; | ||
| 1997 | |||
| 1998 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
| 1999 | ch = vpif_obj.dev[j]; | ||
| 2000 | ch->channel_id = j; | ||
| 2001 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
| 2002 | spin_lock_init(&common->irqlock); | ||
| 2003 | mutex_init(&common->lock); | ||
| 2004 | ch->video_dev->lock = &common->lock; | ||
| 2005 | /* Initialize prio member of channel object */ | ||
| 2006 | v4l2_prio_init(&ch->prio); | ||
| 2007 | video_set_drvdata(ch->video_dev, ch); | ||
| 2008 | |||
| 2009 | /* select input 0 */ | ||
| 2010 | err = vpif_set_input(vpif_obj.config, ch, 0); | ||
| 2011 | if (err) | ||
| 2012 | goto probe_out; | ||
| 2013 | |||
| 2014 | err = video_register_device(ch->video_dev, | ||
| 2015 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
| 2016 | if (err) | ||
| 2017 | goto probe_out; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); | ||
| 2021 | return 0; | ||
| 2022 | |||
| 2023 | probe_out: | ||
| 2024 | for (k = 0; k < j; k++) { | ||
| 2025 | /* Get the pointer to the channel object */ | ||
| 2026 | ch = vpif_obj.dev[k]; | ||
| 2027 | /* Unregister video device */ | ||
| 2028 | video_unregister_device(ch->video_dev); | ||
| 2029 | } | ||
| 2030 | kfree(vpif_obj.sd); | ||
| 2031 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { | ||
| 2032 | ch = vpif_obj.dev[i]; | ||
| 2033 | /* Note: does nothing if ch->video_dev == NULL */ | ||
| 2034 | video_device_release(ch->video_dev); | ||
| 2035 | } | ||
| 2036 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | ||
| 2037 | |||
| 2038 | return err; | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | static int vpif_async_complete(struct v4l2_async_notifier *notifier) | ||
| 2042 | { | ||
| 2043 | return vpif_probe_complete(); | ||
| 2044 | } | ||
| 2045 | |||
| 1982 | /** | 2046 | /** |
| 1983 | * vpif_probe : This function probes the vpif capture driver | 2047 | * vpif_probe : This function probes the vpif capture driver |
| 1984 | * @pdev: platform device pointer | 2048 | * @pdev: platform device pointer |
| @@ -1989,12 +2053,10 @@ vpif_init_free_channel_objects: | |||
| 1989 | static __init int vpif_probe(struct platform_device *pdev) | 2053 | static __init int vpif_probe(struct platform_device *pdev) |
| 1990 | { | 2054 | { |
| 1991 | struct vpif_subdev_info *subdevdata; | 2055 | struct vpif_subdev_info *subdevdata; |
| 1992 | struct vpif_capture_config *config; | 2056 | int i, j, err; |
| 1993 | int i, j, k, err; | ||
| 1994 | int res_idx = 0; | 2057 | int res_idx = 0; |
| 1995 | struct i2c_adapter *i2c_adap; | 2058 | struct i2c_adapter *i2c_adap; |
| 1996 | struct channel_obj *ch; | 2059 | struct channel_obj *ch; |
| 1997 | struct common_obj *common; | ||
| 1998 | struct video_device *vfd; | 2060 | struct video_device *vfd; |
| 1999 | struct resource *res; | 2061 | struct resource *res; |
| 2000 | int subdev_count; | 2062 | int subdev_count; |
| @@ -2068,10 +2130,9 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
| 2068 | } | 2130 | } |
| 2069 | } | 2131 | } |
| 2070 | 2132 | ||
| 2071 | i2c_adap = i2c_get_adapter(1); | 2133 | vpif_obj.config = pdev->dev.platform_data; |
| 2072 | config = pdev->dev.platform_data; | ||
| 2073 | 2134 | ||
| 2074 | subdev_count = config->subdev_count; | 2135 | subdev_count = vpif_obj.config->subdev_count; |
| 2075 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | 2136 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, |
| 2076 | GFP_KERNEL); | 2137 | GFP_KERNEL); |
| 2077 | if (vpif_obj.sd == NULL) { | 2138 | if (vpif_obj.sd == NULL) { |
| @@ -2080,54 +2141,43 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
| 2080 | goto vpif_sd_error; | 2141 | goto vpif_sd_error; |
| 2081 | } | 2142 | } |
| 2082 | 2143 | ||
| 2083 | for (i = 0; i < subdev_count; i++) { | 2144 | if (!vpif_obj.config->asd_sizes) { |
| 2084 | subdevdata = &config->subdev_info[i]; | 2145 | i2c_adap = i2c_get_adapter(1); |
| 2085 | vpif_obj.sd[i] = | 2146 | for (i = 0; i < subdev_count; i++) { |
| 2086 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | 2147 | subdevdata = &vpif_obj.config->subdev_info[i]; |
| 2087 | i2c_adap, | 2148 | vpif_obj.sd[i] = |
| 2088 | &subdevdata->board_info, | 2149 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, |
| 2089 | NULL); | 2150 | i2c_adap, |
| 2090 | 2151 | &subdevdata-> | |
| 2091 | if (!vpif_obj.sd[i]) { | 2152 | board_info, |
| 2092 | vpif_err("Error registering v4l2 subdevice\n"); | 2153 | NULL); |
| 2093 | err = -ENODEV; | 2154 | |
| 2155 | if (!vpif_obj.sd[i]) { | ||
| 2156 | vpif_err("Error registering v4l2 subdevice\n"); | ||
| 2157 | err = -ENOMEM; | ||
| 2158 | goto probe_subdev_out; | ||
| 2159 | } | ||
| 2160 | v4l2_info(&vpif_obj.v4l2_dev, | ||
| 2161 | "registered sub device %s\n", | ||
| 2162 | subdevdata->name); | ||
| 2163 | } | ||
| 2164 | vpif_probe_complete(); | ||
| 2165 | } else { | ||
| 2166 | vpif_obj.notifier.subdevs = vpif_obj.config->asd; | ||
| 2167 | vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; | ||
| 2168 | vpif_obj.notifier.bound = vpif_async_bound; | ||
| 2169 | vpif_obj.notifier.complete = vpif_async_complete; | ||
| 2170 | err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, | ||
| 2171 | &vpif_obj.notifier); | ||
| 2172 | if (err) { | ||
| 2173 | vpif_err("Error registering async notifier\n"); | ||
| 2174 | err = -EINVAL; | ||
| 2094 | goto probe_subdev_out; | 2175 | goto probe_subdev_out; |
| 2095 | } | 2176 | } |
| 2096 | v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", | ||
| 2097 | subdevdata->name); | ||
| 2098 | } | 2177 | } |
| 2099 | 2178 | ||
| 2100 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | ||
| 2101 | ch = vpif_obj.dev[j]; | ||
| 2102 | ch->channel_id = j; | ||
| 2103 | common = &(ch->common[VPIF_VIDEO_INDEX]); | ||
| 2104 | spin_lock_init(&common->irqlock); | ||
| 2105 | mutex_init(&common->lock); | ||
| 2106 | ch->video_dev->lock = &common->lock; | ||
| 2107 | /* Initialize prio member of channel object */ | ||
| 2108 | v4l2_prio_init(&ch->prio); | ||
| 2109 | video_set_drvdata(ch->video_dev, ch); | ||
| 2110 | |||
| 2111 | /* select input 0 */ | ||
| 2112 | err = vpif_set_input(config, ch, 0); | ||
| 2113 | if (err) | ||
| 2114 | goto probe_out; | ||
| 2115 | |||
| 2116 | err = video_register_device(ch->video_dev, | ||
| 2117 | VFL_TYPE_GRABBER, (j ? 1 : 0)); | ||
| 2118 | if (err) | ||
| 2119 | goto probe_out; | ||
| 2120 | } | ||
| 2121 | v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); | ||
| 2122 | return 0; | 2179 | return 0; |
| 2123 | 2180 | ||
| 2124 | probe_out: | ||
| 2125 | for (k = 0; k < j; k++) { | ||
| 2126 | /* Get the pointer to the channel object */ | ||
| 2127 | ch = vpif_obj.dev[k]; | ||
| 2128 | /* Unregister video device */ | ||
| 2129 | video_unregister_device(ch->video_dev); | ||
| 2130 | } | ||
| 2131 | probe_subdev_out: | 2181 | probe_subdev_out: |
| 2132 | /* free sub devices memory */ | 2182 | /* free sub devices memory */ |
| 2133 | kfree(vpif_obj.sd); | 2183 | kfree(vpif_obj.sd); |
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 0ebb31260369..5a29d9a0cae1 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h | |||
| @@ -142,6 +142,8 @@ struct vpif_device { | |||
| 142 | struct v4l2_device v4l2_dev; | 142 | struct v4l2_device v4l2_dev; |
| 143 | struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; | 143 | struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; |
| 144 | struct v4l2_subdev **sd; | 144 | struct v4l2_subdev **sd; |
| 145 | struct v4l2_async_notifier notifier; | ||
| 146 | struct vpif_capture_config *config; | ||
| 145 | }; | 147 | }; |
| 146 | 148 | ||
| 147 | struct vpif_config_params { | 149 | struct vpif_config_params { |
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index e6e573650250..c31bcf129a5d 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c | |||
| @@ -1436,19 +1436,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
| 1436 | 1436 | ||
| 1437 | /* Configure video port timings */ | 1437 | /* Configure video port timings */ |
| 1438 | 1438 | ||
| 1439 | std_info->eav2sav = bt->hbackporch + bt->hfrontporch + | 1439 | std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8; |
| 1440 | bt->hsync - 8; | ||
| 1441 | std_info->sav2eav = bt->width; | 1440 | std_info->sav2eav = bt->width; |
| 1442 | 1441 | ||
| 1443 | std_info->l1 = 1; | 1442 | std_info->l1 = 1; |
| 1444 | std_info->l3 = bt->vsync + bt->vbackporch + 1; | 1443 | std_info->l3 = bt->vsync + bt->vbackporch + 1; |
| 1445 | 1444 | ||
| 1445 | std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
| 1446 | if (bt->interlaced) { | 1446 | if (bt->interlaced) { |
| 1447 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { | 1447 | if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { |
| 1448 | std_info->vsize = bt->height * 2 + | ||
| 1449 | bt->vfrontporch + bt->vsync + bt->vbackporch + | ||
| 1450 | bt->il_vfrontporch + bt->il_vsync + | ||
| 1451 | bt->il_vbackporch; | ||
| 1452 | std_info->l5 = std_info->vsize/2 - | 1448 | std_info->l5 = std_info->vsize/2 - |
| 1453 | (bt->vfrontporch - 1); | 1449 | (bt->vfrontporch - 1); |
| 1454 | std_info->l7 = std_info->vsize/2 + 1; | 1450 | std_info->l7 = std_info->vsize/2 + 1; |
| @@ -1462,8 +1458,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv, | |||
| 1462 | return -EINVAL; | 1458 | return -EINVAL; |
| 1463 | } | 1459 | } |
| 1464 | } else { | 1460 | } else { |
| 1465 | std_info->vsize = bt->height + bt->vfrontporch + | ||
| 1466 | bt->vsync + bt->vbackporch; | ||
| 1467 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); | 1461 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); |
| 1468 | } | 1462 | } |
| 1469 | strncpy(std_info->name, "Custom timings BT656/1120", | 1463 | strncpy(std_info->name, "Custom timings BT656/1120", |
| @@ -1618,6 +1612,102 @@ vpif_init_free_channel_objects: | |||
| 1618 | return err; | 1612 | return err; |
| 1619 | } | 1613 | } |
| 1620 | 1614 | ||
| 1615 | static int vpif_async_bound(struct v4l2_async_notifier *notifier, | ||
| 1616 | struct v4l2_subdev *subdev, | ||
| 1617 | struct v4l2_async_subdev *asd) | ||
| 1618 | { | ||
| 1619 | int i; | ||
| 1620 | |||
| 1621 | for (i = 0; i < vpif_obj.config->subdev_count; i++) | ||
| 1622 | if (!strcmp(vpif_obj.config->subdevinfo[i].name, | ||
| 1623 | subdev->name)) { | ||
| 1624 | vpif_obj.sd[i] = subdev; | ||
| 1625 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
| 1626 | return 0; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | return -EINVAL; | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | static int vpif_probe_complete(void) | ||
| 1633 | { | ||
| 1634 | struct common_obj *common; | ||
| 1635 | struct channel_obj *ch; | ||
| 1636 | int j, err, k; | ||
| 1637 | |||
| 1638 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | ||
| 1639 | ch = vpif_obj.dev[j]; | ||
| 1640 | /* Initialize field of the channel objects */ | ||
| 1641 | atomic_set(&ch->usrs, 0); | ||
| 1642 | for (k = 0; k < VPIF_NUMOBJECTS; k++) { | ||
| 1643 | ch->common[k].numbuffers = 0; | ||
| 1644 | common = &ch->common[k]; | ||
| 1645 | common->io_usrs = 0; | ||
| 1646 | common->started = 0; | ||
| 1647 | spin_lock_init(&common->irqlock); | ||
| 1648 | mutex_init(&common->lock); | ||
| 1649 | common->numbuffers = 0; | ||
| 1650 | common->set_addr = NULL; | ||
| 1651 | common->ytop_off = 0; | ||
| 1652 | common->ybtm_off = 0; | ||
| 1653 | common->ctop_off = 0; | ||
| 1654 | common->cbtm_off = 0; | ||
| 1655 | common->cur_frm = NULL; | ||
| 1656 | common->next_frm = NULL; | ||
| 1657 | memset(&common->fmt, 0, sizeof(common->fmt)); | ||
| 1658 | common->numbuffers = config_params.numbuffers[k]; | ||
| 1659 | } | ||
| 1660 | ch->initialized = 0; | ||
| 1661 | if (vpif_obj.config->subdev_count) | ||
| 1662 | ch->sd = vpif_obj.sd[0]; | ||
| 1663 | ch->channel_id = j; | ||
| 1664 | if (j < 2) | ||
| 1665 | ch->common[VPIF_VIDEO_INDEX].numbuffers = | ||
| 1666 | config_params.numbuffers[ch->channel_id]; | ||
| 1667 | else | ||
| 1668 | ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; | ||
| 1669 | |||
| 1670 | memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); | ||
| 1671 | |||
| 1672 | /* Initialize prio member of channel object */ | ||
| 1673 | v4l2_prio_init(&ch->prio); | ||
| 1674 | ch->common[VPIF_VIDEO_INDEX].fmt.type = | ||
| 1675 | V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
| 1676 | ch->video_dev->lock = &common->lock; | ||
| 1677 | video_set_drvdata(ch->video_dev, ch); | ||
| 1678 | |||
| 1679 | /* select output 0 */ | ||
| 1680 | err = vpif_set_output(vpif_obj.config, ch, 0); | ||
| 1681 | if (err) | ||
| 1682 | goto probe_out; | ||
| 1683 | |||
| 1684 | /* register video device */ | ||
| 1685 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", | ||
| 1686 | (int)ch, (int)&ch->video_dev); | ||
| 1687 | |||
| 1688 | err = video_register_device(ch->video_dev, | ||
| 1689 | VFL_TYPE_GRABBER, (j ? 3 : 2)); | ||
| 1690 | if (err < 0) | ||
| 1691 | goto probe_out; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | return 0; | ||
| 1695 | |||
| 1696 | probe_out: | ||
| 1697 | for (k = 0; k < j; k++) { | ||
| 1698 | ch = vpif_obj.dev[k]; | ||
| 1699 | video_unregister_device(ch->video_dev); | ||
| 1700 | video_device_release(ch->video_dev); | ||
| 1701 | ch->video_dev = NULL; | ||
| 1702 | } | ||
| 1703 | return err; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | static int vpif_async_complete(struct v4l2_async_notifier *notifier) | ||
| 1707 | { | ||
| 1708 | return vpif_probe_complete(); | ||
| 1709 | } | ||
| 1710 | |||
| 1621 | /* | 1711 | /* |
| 1622 | * vpif_probe: This function creates device entries by register itself to the | 1712 | * vpif_probe: This function creates device entries by register itself to the |
| 1623 | * V4L2 driver and initializes fields of each channel objects | 1713 | * V4L2 driver and initializes fields of each channel objects |
| @@ -1625,11 +1715,9 @@ vpif_init_free_channel_objects: | |||
| 1625 | static __init int vpif_probe(struct platform_device *pdev) | 1715 | static __init int vpif_probe(struct platform_device *pdev) |
| 1626 | { | 1716 | { |
| 1627 | struct vpif_subdev_info *subdevdata; | 1717 | struct vpif_subdev_info *subdevdata; |
| 1628 | struct vpif_display_config *config; | 1718 | int i, j = 0, err = 0; |
| 1629 | int i, j = 0, k, err = 0; | ||
| 1630 | int res_idx = 0; | 1719 | int res_idx = 0; |
| 1631 | struct i2c_adapter *i2c_adap; | 1720 | struct i2c_adapter *i2c_adap; |
| 1632 | struct common_obj *common; | ||
| 1633 | struct channel_obj *ch; | 1721 | struct channel_obj *ch; |
| 1634 | struct video_device *vfd; | 1722 | struct video_device *vfd; |
| 1635 | struct resource *res; | 1723 | struct resource *res; |
| @@ -1708,11 +1796,9 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
| 1708 | size/2; | 1796 | size/2; |
| 1709 | } | 1797 | } |
| 1710 | } | 1798 | } |
| 1711 | 1799 | vpif_obj.config = pdev->dev.platform_data; | |
| 1712 | i2c_adap = i2c_get_adapter(1); | 1800 | subdev_count = vpif_obj.config->subdev_count; |
| 1713 | config = pdev->dev.platform_data; | 1801 | subdevdata = vpif_obj.config->subdevinfo; |
| 1714 | subdev_count = config->subdev_count; | ||
| 1715 | subdevdata = config->subdevinfo; | ||
| 1716 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, | 1802 | vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, |
| 1717 | GFP_KERNEL); | 1803 | GFP_KERNEL); |
| 1718 | if (vpif_obj.sd == NULL) { | 1804 | if (vpif_obj.sd == NULL) { |
| @@ -1721,86 +1807,41 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
| 1721 | goto vpif_sd_error; | 1807 | goto vpif_sd_error; |
| 1722 | } | 1808 | } |
| 1723 | 1809 | ||
| 1724 | for (i = 0; i < subdev_count; i++) { | 1810 | if (!vpif_obj.config->asd_sizes) { |
| 1725 | vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, | 1811 | i2c_adap = i2c_get_adapter(1); |
| 1726 | i2c_adap, | 1812 | for (i = 0; i < subdev_count; i++) { |
| 1727 | &subdevdata[i].board_info, | 1813 | vpif_obj.sd[i] = |
| 1728 | NULL); | 1814 | v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, |
| 1729 | if (!vpif_obj.sd[i]) { | 1815 | i2c_adap, |
| 1730 | vpif_err("Error registering v4l2 subdevice\n"); | 1816 | &subdevdata[i]. |
| 1731 | err = -ENODEV; | 1817 | board_info, |
| 1732 | goto probe_subdev_out; | 1818 | NULL); |
| 1733 | } | 1819 | if (!vpif_obj.sd[i]) { |
| 1734 | 1820 | vpif_err("Error registering v4l2 subdevice\n"); | |
| 1735 | if (vpif_obj.sd[i]) | 1821 | err = -ENODEV; |
| 1736 | vpif_obj.sd[i]->grp_id = 1 << i; | 1822 | goto probe_subdev_out; |
| 1737 | } | 1823 | } |
| 1738 | |||
| 1739 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | ||
| 1740 | ch = vpif_obj.dev[j]; | ||
| 1741 | /* Initialize field of the channel objects */ | ||
| 1742 | atomic_set(&ch->usrs, 0); | ||
| 1743 | for (k = 0; k < VPIF_NUMOBJECTS; k++) { | ||
| 1744 | ch->common[k].numbuffers = 0; | ||
| 1745 | common = &ch->common[k]; | ||
| 1746 | common->io_usrs = 0; | ||
| 1747 | common->started = 0; | ||
| 1748 | spin_lock_init(&common->irqlock); | ||
| 1749 | mutex_init(&common->lock); | ||
| 1750 | common->numbuffers = 0; | ||
| 1751 | common->set_addr = NULL; | ||
| 1752 | common->ytop_off = common->ybtm_off = 0; | ||
| 1753 | common->ctop_off = common->cbtm_off = 0; | ||
| 1754 | common->cur_frm = common->next_frm = NULL; | ||
| 1755 | memset(&common->fmt, 0, sizeof(common->fmt)); | ||
| 1756 | common->numbuffers = config_params.numbuffers[k]; | ||
| 1757 | 1824 | ||
| 1825 | if (vpif_obj.sd[i]) | ||
| 1826 | vpif_obj.sd[i]->grp_id = 1 << i; | ||
| 1827 | } | ||
| 1828 | vpif_probe_complete(); | ||
| 1829 | } else { | ||
| 1830 | vpif_obj.notifier.subdevs = vpif_obj.config->asd; | ||
| 1831 | vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; | ||
| 1832 | vpif_obj.notifier.bound = vpif_async_bound; | ||
| 1833 | vpif_obj.notifier.complete = vpif_async_complete; | ||
| 1834 | err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, | ||
| 1835 | &vpif_obj.notifier); | ||
| 1836 | if (err) { | ||
| 1837 | vpif_err("Error registering async notifier\n"); | ||
| 1838 | err = -EINVAL; | ||
| 1839 | goto probe_subdev_out; | ||
| 1758 | } | 1840 | } |
| 1759 | ch->initialized = 0; | ||
| 1760 | if (subdev_count) | ||
| 1761 | ch->sd = vpif_obj.sd[0]; | ||
| 1762 | ch->channel_id = j; | ||
| 1763 | if (j < 2) | ||
| 1764 | ch->common[VPIF_VIDEO_INDEX].numbuffers = | ||
| 1765 | config_params.numbuffers[ch->channel_id]; | ||
| 1766 | else | ||
| 1767 | ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; | ||
| 1768 | |||
| 1769 | memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); | ||
| 1770 | |||
| 1771 | /* Initialize prio member of channel object */ | ||
| 1772 | v4l2_prio_init(&ch->prio); | ||
| 1773 | ch->common[VPIF_VIDEO_INDEX].fmt.type = | ||
| 1774 | V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
| 1775 | ch->video_dev->lock = &common->lock; | ||
| 1776 | video_set_drvdata(ch->video_dev, ch); | ||
| 1777 | |||
| 1778 | /* select output 0 */ | ||
| 1779 | err = vpif_set_output(config, ch, 0); | ||
| 1780 | if (err) | ||
| 1781 | goto probe_out; | ||
| 1782 | |||
| 1783 | /* register video device */ | ||
| 1784 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", | ||
| 1785 | (int)ch, (int)&ch->video_dev); | ||
| 1786 | |||
| 1787 | err = video_register_device(ch->video_dev, | ||
| 1788 | VFL_TYPE_GRABBER, (j ? 3 : 2)); | ||
| 1789 | if (err < 0) | ||
| 1790 | goto probe_out; | ||
| 1791 | } | 1841 | } |
| 1792 | 1842 | ||
| 1793 | v4l2_info(&vpif_obj.v4l2_dev, | ||
| 1794 | " VPIF display driver initialized\n"); | ||
| 1795 | return 0; | 1843 | return 0; |
| 1796 | 1844 | ||
| 1797 | probe_out: | ||
| 1798 | for (k = 0; k < j; k++) { | ||
| 1799 | ch = vpif_obj.dev[k]; | ||
| 1800 | video_unregister_device(ch->video_dev); | ||
| 1801 | video_device_release(ch->video_dev); | ||
| 1802 | ch->video_dev = NULL; | ||
| 1803 | } | ||
| 1804 | probe_subdev_out: | 1845 | probe_subdev_out: |
| 1805 | kfree(vpif_obj.sd); | 1846 | kfree(vpif_obj.sd); |
| 1806 | vpif_sd_error: | 1847 | vpif_sd_error: |
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index 5d87fc86e580..4d0485b99a80 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h | |||
| @@ -148,7 +148,8 @@ struct vpif_device { | |||
| 148 | struct v4l2_device v4l2_dev; | 148 | struct v4l2_device v4l2_dev; |
| 149 | struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; | 149 | struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; |
| 150 | struct v4l2_subdev **sd; | 150 | struct v4l2_subdev **sd; |
| 151 | 151 | struct v4l2_async_notifier notifier; | |
| 152 | struct vpif_display_config *config; | ||
| 152 | }; | 153 | }; |
| 153 | 154 | ||
| 154 | struct vpif_config_params { | 155 | struct vpif_config_params { |
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c index 8a2f01e344ee..31120b4a4a33 100644 --- a/drivers/media/platform/davinci/vpss.c +++ b/drivers/media/platform/davinci/vpss.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 23 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
| 24 | #include <linux/err.h> | ||
| 24 | 25 | ||
| 25 | #include <media/davinci/vpss.h> | 26 | #include <media/davinci/vpss.h> |
| 26 | 27 | ||
| @@ -404,9 +405,8 @@ EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); | |||
| 404 | 405 | ||
| 405 | static int vpss_probe(struct platform_device *pdev) | 406 | static int vpss_probe(struct platform_device *pdev) |
| 406 | { | 407 | { |
| 407 | struct resource *r1, *r2; | 408 | struct resource *res; |
| 408 | char *platform_name; | 409 | char *platform_name; |
| 409 | int status; | ||
| 410 | 410 | ||
| 411 | if (!pdev->dev.platform_data) { | 411 | if (!pdev->dev.platform_data) { |
| 412 | dev_err(&pdev->dev, "no platform data\n"); | 412 | dev_err(&pdev->dev, "no platform data\n"); |
| @@ -427,38 +427,19 @@ static int vpss_probe(struct platform_device *pdev) | |||
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); | 429 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); |
| 430 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 430 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 431 | if (!r1) | ||
| 432 | return -ENOENT; | ||
| 433 | 431 | ||
| 434 | r1 = request_mem_region(r1->start, resource_size(r1), r1->name); | 432 | oper_cfg.vpss_regs_base0 = devm_ioremap_resource(&pdev->dev, res); |
| 435 | if (!r1) | 433 | if (IS_ERR(oper_cfg.vpss_regs_base0)) |
| 436 | return -EBUSY; | 434 | return PTR_ERR(oper_cfg.vpss_regs_base0); |
| 437 | |||
| 438 | oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1)); | ||
| 439 | if (!oper_cfg.vpss_regs_base0) { | ||
| 440 | status = -EBUSY; | ||
| 441 | goto fail1; | ||
| 442 | } | ||
| 443 | 435 | ||
| 444 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | 436 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { |
| 445 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 437 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| 446 | if (!r2) { | 438 | |
| 447 | status = -ENOENT; | 439 | oper_cfg.vpss_regs_base1 = devm_ioremap_resource(&pdev->dev, |
| 448 | goto fail2; | 440 | res); |
| 449 | } | 441 | if (IS_ERR(oper_cfg.vpss_regs_base1)) |
| 450 | r2 = request_mem_region(r2->start, resource_size(r2), r2->name); | 442 | return PTR_ERR(oper_cfg.vpss_regs_base1); |
| 451 | if (!r2) { | ||
| 452 | status = -EBUSY; | ||
| 453 | goto fail2; | ||
| 454 | } | ||
| 455 | |||
| 456 | oper_cfg.vpss_regs_base1 = ioremap(r2->start, | ||
| 457 | resource_size(r2)); | ||
| 458 | if (!oper_cfg.vpss_regs_base1) { | ||
| 459 | status = -EBUSY; | ||
| 460 | goto fail3; | ||
| 461 | } | ||
| 462 | } | 443 | } |
| 463 | 444 | ||
| 464 | if (oper_cfg.platform == DM355) { | 445 | if (oper_cfg.platform == DM355) { |
| @@ -493,30 +474,13 @@ static int vpss_probe(struct platform_device *pdev) | |||
| 493 | 474 | ||
| 494 | spin_lock_init(&oper_cfg.vpss_lock); | 475 | spin_lock_init(&oper_cfg.vpss_lock); |
| 495 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); | 476 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); |
| 496 | return 0; | ||
| 497 | 477 | ||
| 498 | fail3: | 478 | return 0; |
| 499 | release_mem_region(r2->start, resource_size(r2)); | ||
| 500 | fail2: | ||
| 501 | iounmap(oper_cfg.vpss_regs_base0); | ||
| 502 | fail1: | ||
| 503 | release_mem_region(r1->start, resource_size(r1)); | ||
| 504 | return status; | ||
| 505 | } | 479 | } |
| 506 | 480 | ||
| 507 | static int vpss_remove(struct platform_device *pdev) | 481 | static int vpss_remove(struct platform_device *pdev) |
| 508 | { | 482 | { |
| 509 | struct resource *res; | ||
| 510 | |||
| 511 | pm_runtime_disable(&pdev->dev); | 483 | pm_runtime_disable(&pdev->dev); |
| 512 | iounmap(oper_cfg.vpss_regs_base0); | ||
| 513 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 514 | release_mem_region(res->start, resource_size(res)); | ||
| 515 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | ||
| 516 | iounmap(oper_cfg.vpss_regs_base1); | ||
| 517 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 518 | release_mem_region(res->start, resource_size(res)); | ||
| 519 | } | ||
| 520 | return 0; | 484 | return 0; |
| 521 | } | 485 | } |
| 522 | 486 | ||
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 559fab2a2d67..9d0cc04d7ab7 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c | |||
| @@ -1122,10 +1122,14 @@ static int gsc_probe(struct platform_device *pdev) | |||
| 1122 | goto err_clk; | 1122 | goto err_clk; |
| 1123 | } | 1123 | } |
| 1124 | 1124 | ||
| 1125 | ret = gsc_register_m2m_device(gsc); | 1125 | ret = v4l2_device_register(dev, &gsc->v4l2_dev); |
| 1126 | if (ret) | 1126 | if (ret) |
| 1127 | goto err_clk; | 1127 | goto err_clk; |
| 1128 | 1128 | ||
| 1129 | ret = gsc_register_m2m_device(gsc); | ||
| 1130 | if (ret) | ||
| 1131 | goto err_v4l2; | ||
| 1132 | |||
| 1129 | platform_set_drvdata(pdev, gsc); | 1133 | platform_set_drvdata(pdev, gsc); |
| 1130 | pm_runtime_enable(dev); | 1134 | pm_runtime_enable(dev); |
| 1131 | ret = pm_runtime_get_sync(&pdev->dev); | 1135 | ret = pm_runtime_get_sync(&pdev->dev); |
| @@ -1147,6 +1151,8 @@ err_pm: | |||
| 1147 | pm_runtime_put(dev); | 1151 | pm_runtime_put(dev); |
| 1148 | err_m2m: | 1152 | err_m2m: |
| 1149 | gsc_unregister_m2m_device(gsc); | 1153 | gsc_unregister_m2m_device(gsc); |
| 1154 | err_v4l2: | ||
| 1155 | v4l2_device_unregister(&gsc->v4l2_dev); | ||
| 1150 | err_clk: | 1156 | err_clk: |
| 1151 | gsc_clk_put(gsc); | 1157 | gsc_clk_put(gsc); |
| 1152 | return ret; | 1158 | return ret; |
| @@ -1157,6 +1163,7 @@ static int gsc_remove(struct platform_device *pdev) | |||
| 1157 | struct gsc_dev *gsc = platform_get_drvdata(pdev); | 1163 | struct gsc_dev *gsc = platform_get_drvdata(pdev); |
| 1158 | 1164 | ||
| 1159 | gsc_unregister_m2m_device(gsc); | 1165 | gsc_unregister_m2m_device(gsc); |
| 1166 | v4l2_device_unregister(&gsc->v4l2_dev); | ||
| 1160 | 1167 | ||
| 1161 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); | 1168 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); |
| 1162 | pm_runtime_disable(&pdev->dev); | 1169 | pm_runtime_disable(&pdev->dev); |
| @@ -1210,12 +1217,12 @@ static int gsc_resume(struct device *dev) | |||
| 1210 | spin_unlock_irqrestore(&gsc->slock, flags); | 1217 | spin_unlock_irqrestore(&gsc->slock, flags); |
| 1211 | return 0; | 1218 | return 0; |
| 1212 | } | 1219 | } |
| 1213 | gsc_hw_set_sw_reset(gsc); | ||
| 1214 | gsc_wait_reset(gsc); | ||
| 1215 | |||
| 1216 | spin_unlock_irqrestore(&gsc->slock, flags); | 1220 | spin_unlock_irqrestore(&gsc->slock, flags); |
| 1217 | 1221 | ||
| 1218 | return gsc_m2m_resume(gsc); | 1222 | if (!pm_runtime_suspended(dev)) |
| 1223 | return gsc_runtime_resume(dev); | ||
| 1224 | |||
| 1225 | return 0; | ||
| 1219 | } | 1226 | } |
| 1220 | 1227 | ||
| 1221 | static int gsc_suspend(struct device *dev) | 1228 | static int gsc_suspend(struct device *dev) |
| @@ -1227,7 +1234,10 @@ static int gsc_suspend(struct device *dev) | |||
| 1227 | if (test_and_set_bit(ST_SUSPEND, &gsc->state)) | 1234 | if (test_and_set_bit(ST_SUSPEND, &gsc->state)) |
| 1228 | return 0; | 1235 | return 0; |
| 1229 | 1236 | ||
| 1230 | return gsc_m2m_suspend(gsc); | 1237 | if (!pm_runtime_suspended(dev)) |
| 1238 | return gsc_runtime_suspend(dev); | ||
| 1239 | |||
| 1240 | return 0; | ||
| 1231 | } | 1241 | } |
| 1232 | 1242 | ||
| 1233 | static const struct dev_pm_ops gsc_pm_ops = { | 1243 | static const struct dev_pm_ops gsc_pm_ops = { |
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h index cc19bba09bd1..76435d3bf62d 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.h +++ b/drivers/media/platform/exynos-gsc/gsc-core.h | |||
| @@ -343,6 +343,7 @@ struct gsc_dev { | |||
| 343 | unsigned long state; | 343 | unsigned long state; |
| 344 | struct vb2_alloc_ctx *alloc_ctx; | 344 | struct vb2_alloc_ctx *alloc_ctx; |
| 345 | struct video_device vdev; | 345 | struct video_device vdev; |
| 346 | struct v4l2_device v4l2_dev; | ||
| 346 | }; | 347 | }; |
| 347 | 348 | ||
| 348 | /** | 349 | /** |
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 40a73f7d20da..e576ff2de3de 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c | |||
| @@ -751,6 +751,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc) | |||
| 751 | gsc->vdev.release = video_device_release_empty; | 751 | gsc->vdev.release = video_device_release_empty; |
| 752 | gsc->vdev.lock = &gsc->lock; | 752 | gsc->vdev.lock = &gsc->lock; |
| 753 | gsc->vdev.vfl_dir = VFL_DIR_M2M; | 753 | gsc->vdev.vfl_dir = VFL_DIR_M2M; |
| 754 | gsc->vdev.v4l2_dev = &gsc->v4l2_dev; | ||
| 754 | snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", | 755 | snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", |
| 755 | GSC_MODULE_NAME, gsc->id); | 756 | GSC_MODULE_NAME, gsc->id); |
| 756 | 757 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 6489c5160ee8..3d66d88ea3a1 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c | |||
| @@ -1110,6 +1110,8 @@ static int fimc_remove(struct platform_device *pdev) | |||
| 1110 | struct fimc_dev *fimc = platform_get_drvdata(pdev); | 1110 | struct fimc_dev *fimc = platform_get_drvdata(pdev); |
| 1111 | 1111 | ||
| 1112 | pm_runtime_disable(&pdev->dev); | 1112 | pm_runtime_disable(&pdev->dev); |
| 1113 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
| 1114 | clk_disable(fimc->clock[CLK_GATE]); | ||
| 1113 | pm_runtime_set_suspended(&pdev->dev); | 1115 | pm_runtime_set_suspended(&pdev->dev); |
| 1114 | 1116 | ||
| 1115 | fimc_unregister_capture_subdev(fimc); | 1117 | fimc_unregister_capture_subdev(fimc); |
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index 993055605214..371cad4fcce9 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c | |||
| @@ -81,21 +81,46 @@ static int fimc_is_i2c_remove(struct platform_device *pdev) | |||
| 81 | return 0; | 81 | return 0; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static int fimc_is_i2c_suspend(struct device *dev) | 84 | #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP) |
| 85 | static int fimc_is_i2c_runtime_suspend(struct device *dev) | ||
| 85 | { | 86 | { |
| 86 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); | 87 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); |
| 88 | |||
| 87 | clk_disable_unprepare(isp_i2c->clock); | 89 | clk_disable_unprepare(isp_i2c->clock); |
| 88 | return 0; | 90 | return 0; |
| 89 | } | 91 | } |
| 90 | 92 | ||
| 91 | static int fimc_is_i2c_resume(struct device *dev) | 93 | static int fimc_is_i2c_runtime_resume(struct device *dev) |
| 92 | { | 94 | { |
| 93 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); | 95 | struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev); |
| 96 | |||
| 94 | return clk_prepare_enable(isp_i2c->clock); | 97 | return clk_prepare_enable(isp_i2c->clock); |
| 95 | } | 98 | } |
| 99 | #endif | ||
| 96 | 100 | ||
| 97 | static UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, | 101 | #ifdef CONFIG_PM_SLEEP |
| 98 | fimc_is_i2c_resume, NULL); | 102 | static int fimc_is_i2c_suspend(struct device *dev) |
| 103 | { | ||
| 104 | if (pm_runtime_suspended(dev)) | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | return fimc_is_i2c_runtime_suspend(dev); | ||
| 108 | } | ||
| 109 | |||
| 110 | static int fimc_is_i2c_resume(struct device *dev) | ||
| 111 | { | ||
| 112 | if (pm_runtime_suspended(dev)) | ||
| 113 | return 0; | ||
| 114 | |||
| 115 | return fimc_is_i2c_runtime_resume(dev); | ||
| 116 | } | ||
| 117 | #endif | ||
| 118 | |||
| 119 | static struct dev_pm_ops fimc_is_i2c_pm_ops = { | ||
| 120 | SET_RUNTIME_PM_OPS(fimc_is_i2c_runtime_suspend, | ||
| 121 | fimc_is_i2c_runtime_resume, NULL) | ||
| 122 | SET_SYSTEM_SLEEP_PM_OPS(fimc_is_i2c_suspend, fimc_is_i2c_resume) | ||
| 123 | }; | ||
| 99 | 124 | ||
| 100 | static const struct of_device_id fimc_is_i2c_of_match[] = { | 125 | static const struct of_device_id fimc_is_i2c_of_match[] = { |
| 101 | { .compatible = FIMC_IS_I2C_COMPATIBLE }, | 126 | { .compatible = FIMC_IS_I2C_COMPATIBLE }, |
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c index c7e7f694c6ed..9bf3ddd9e028 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ b/drivers/media/platform/exynos4-is/fimc-is-param.c | |||
| @@ -56,7 +56,7 @@ static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) | |||
| 56 | __hw_param_copy(dst, src); | 56 | __hw_param_copy(dst, src); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) | 59 | static int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) |
| 60 | { | 60 | { |
| 61 | struct is_param_region *par = &is->is_p_region->parameter; | 61 | struct is_param_region *par = &is->is_p_region->parameter; |
| 62 | struct chain_config *cfg = &is->config[is->config_index]; | 62 | struct chain_config *cfg = &is->config[is->config_index]; |
| @@ -287,7 +287,7 @@ void __is_set_sensor(struct fimc_is *is, int fps) | |||
| 287 | fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); | 287 | fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | void __is_set_init_isp_aa(struct fimc_is *is) | 290 | static void __maybe_unused __is_set_init_isp_aa(struct fimc_is *is) |
| 291 | { | 291 | { |
| 292 | struct isp_param *isp; | 292 | struct isp_param *isp; |
| 293 | 293 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index 63c68ec7cfa4..f758e2694fa3 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c | |||
| @@ -96,7 +96,7 @@ int fimc_is_hw_set_param(struct fimc_is *is) | |||
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | int fimc_is_hw_set_tune(struct fimc_is *is) | 99 | static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is) |
| 100 | { | 100 | { |
| 101 | fimc_is_hw_wait_intmsr0_intmsd0(is); | 101 | fimc_is_hw_wait_intmsr0_intmsd0(is); |
| 102 | 102 | ||
| @@ -236,7 +236,7 @@ int fimc_is_itf_mode_change(struct fimc_is *is) | |||
| 236 | fimc_is_hw_change_mode(is); | 236 | fimc_is_hw_change_mode(is); |
| 237 | ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, | 237 | ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, |
| 238 | FIMC_IS_CONFIG_TIMEOUT); | 238 | FIMC_IS_CONFIG_TIMEOUT); |
| 239 | if (!ret < 0) | 239 | if (ret < 0) |
| 240 | dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", | 240 | dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", |
| 241 | __func__, is->config_index); | 241 | __func__, is->config_index); |
| 242 | return ret; | 242 | return ret; |
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 2276fdc213c5..9770fa98d6a1 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c | |||
| @@ -993,3 +993,4 @@ module_exit(fimc_is_module_exit); | |||
| 993 | MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); | 993 | MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); |
| 994 | MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>"); | 994 | MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>"); |
| 995 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 995 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
| 996 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index cf520a7d7f71..d2e6cba3566d 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c | |||
| @@ -672,6 +672,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp) | |||
| 672 | mutex_init(&isp->subdev_lock); | 672 | mutex_init(&isp->subdev_lock); |
| 673 | 673 | ||
| 674 | v4l2_subdev_init(sd, &fimc_is_subdev_ops); | 674 | v4l2_subdev_init(sd, &fimc_is_subdev_ops); |
| 675 | |||
| 676 | sd->owner = THIS_MODULE; | ||
| 675 | sd->grp_id = GRP_ID_FIMC_IS; | 677 | sd->grp_id = GRP_ID_FIMC_IS; |
| 676 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 678 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 677 | snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); | 679 | snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); |
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 08fbfedea90f..e5798f70d149 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c | |||
| @@ -90,7 +90,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { | |||
| 90 | .name = "RAW10 (GRBG)", | 90 | .name = "RAW10 (GRBG)", |
| 91 | .fourcc = V4L2_PIX_FMT_SGRBG10, | 91 | .fourcc = V4L2_PIX_FMT_SGRBG10, |
| 92 | .colorspace = V4L2_COLORSPACE_SRGB, | 92 | .colorspace = V4L2_COLORSPACE_SRGB, |
| 93 | .depth = { 10 }, | 93 | .depth = { 16 }, |
| 94 | .color = FIMC_FMT_RAW10, | 94 | .color = FIMC_FMT_RAW10, |
| 95 | .memplanes = 1, | 95 | .memplanes = 1, |
| 96 | .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, | 96 | .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, |
| @@ -99,7 +99,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { | |||
| 99 | .name = "RAW12 (GRBG)", | 99 | .name = "RAW12 (GRBG)", |
| 100 | .fourcc = V4L2_PIX_FMT_SGRBG12, | 100 | .fourcc = V4L2_PIX_FMT_SGRBG12, |
| 101 | .colorspace = V4L2_COLORSPACE_SRGB, | 101 | .colorspace = V4L2_COLORSPACE_SRGB, |
| 102 | .depth = { 12 }, | 102 | .depth = { 16 }, |
| 103 | .color = FIMC_FMT_RAW12, | 103 | .color = FIMC_FMT_RAW12, |
| 104 | .memplanes = 1, | 104 | .memplanes = 1, |
| 105 | .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, | 105 | .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, |
| @@ -1504,16 +1504,17 @@ static int fimc_lite_probe(struct platform_device *pdev) | |||
| 1504 | struct resource *res; | 1504 | struct resource *res; |
| 1505 | int ret; | 1505 | int ret; |
| 1506 | 1506 | ||
| 1507 | if (!dev->of_node) | ||
| 1508 | return -ENODEV; | ||
| 1509 | |||
| 1507 | fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); | 1510 | fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL); |
| 1508 | if (!fimc) | 1511 | if (!fimc) |
| 1509 | return -ENOMEM; | 1512 | return -ENOMEM; |
| 1510 | 1513 | ||
| 1511 | if (dev->of_node) { | 1514 | of_id = of_match_node(flite_of_match, dev->of_node); |
| 1512 | of_id = of_match_node(flite_of_match, dev->of_node); | 1515 | if (of_id) |
| 1513 | if (of_id) | 1516 | drv_data = (struct flite_drvdata *)of_id->data; |
| 1514 | drv_data = (struct flite_drvdata *)of_id->data; | 1517 | fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); |
| 1515 | fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); | ||
| 1516 | } | ||
| 1517 | 1518 | ||
| 1518 | if (!drv_data || fimc->index >= drv_data->num_instances || | 1519 | if (!drv_data || fimc->index >= drv_data->num_instances || |
| 1519 | fimc->index < 0) { | 1520 | fimc->index < 0) { |
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f8c66b434fd6..a83511278317 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c | |||
| @@ -1149,7 +1149,6 @@ static void fimc_md_put_clocks(struct fimc_md *fmd) | |||
| 1149 | while (--i >= 0) { | 1149 | while (--i >= 0) { |
| 1150 | if (IS_ERR(fmd->camclk[i].clock)) | 1150 | if (IS_ERR(fmd->camclk[i].clock)) |
| 1151 | continue; | 1151 | continue; |
| 1152 | clk_unprepare(fmd->camclk[i].clock); | ||
| 1153 | clk_put(fmd->camclk[i].clock); | 1152 | clk_put(fmd->camclk[i].clock); |
| 1154 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | 1153 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); |
| 1155 | } | 1154 | } |
| @@ -1168,7 +1167,7 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) | |||
| 1168 | struct device *dev = NULL; | 1167 | struct device *dev = NULL; |
| 1169 | char clk_name[32]; | 1168 | char clk_name[32]; |
| 1170 | struct clk *clock; | 1169 | struct clk *clock; |
| 1171 | int ret, i; | 1170 | int i, ret = 0; |
| 1172 | 1171 | ||
| 1173 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) | 1172 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) |
| 1174 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | 1173 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); |
| @@ -1186,12 +1185,6 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) | |||
| 1186 | ret = PTR_ERR(clock); | 1185 | ret = PTR_ERR(clock); |
| 1187 | break; | 1186 | break; |
| 1188 | } | 1187 | } |
| 1189 | ret = clk_prepare(clock); | ||
| 1190 | if (ret < 0) { | ||
| 1191 | clk_put(clock); | ||
| 1192 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); | ||
| 1193 | break; | ||
| 1194 | } | ||
| 1195 | fmd->camclk[i].clock = clock; | 1188 | fmd->camclk[i].clock = clock; |
| 1196 | } | 1189 | } |
| 1197 | if (ret) | 1190 | if (ret) |
| @@ -1248,7 +1241,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, | |||
| 1248 | ret = pm_runtime_get_sync(fmd->pmf); | 1241 | ret = pm_runtime_get_sync(fmd->pmf); |
| 1249 | if (ret < 0) | 1242 | if (ret < 0) |
| 1250 | return ret; | 1243 | return ret; |
| 1251 | ret = clk_enable(camclk->clock); | 1244 | ret = clk_prepare_enable(camclk->clock); |
| 1252 | dbg("Enabled camclk %d: f: %lu", si->clk_id, | 1245 | dbg("Enabled camclk %d: f: %lu", si->clk_id, |
| 1253 | clk_get_rate(camclk->clock)); | 1246 | clk_get_rate(camclk->clock)); |
| 1254 | } | 1247 | } |
| @@ -1259,7 +1252,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, | |||
| 1259 | return 0; | 1252 | return 0; |
| 1260 | 1253 | ||
| 1261 | if (--camclk->use_count == 0) { | 1254 | if (--camclk->use_count == 0) { |
| 1262 | clk_disable(camclk->clock); | 1255 | clk_disable_unprepare(camclk->clock); |
| 1263 | pm_runtime_put(fmd->pmf); | 1256 | pm_runtime_put(fmd->pmf); |
| 1264 | dbg("Disabled camclk %d", si->clk_id); | 1257 | dbg("Disabled camclk %d", si->clk_id); |
| 1265 | } | 1258 | } |
| @@ -1529,9 +1522,9 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
| 1529 | err_unlock: | 1522 | err_unlock: |
| 1530 | mutex_unlock(&fmd->media_dev.graph_mutex); | 1523 | mutex_unlock(&fmd->media_dev.graph_mutex); |
| 1531 | err_clk: | 1524 | err_clk: |
| 1532 | media_device_unregister(&fmd->media_dev); | ||
| 1533 | fimc_md_put_clocks(fmd); | 1525 | fimc_md_put_clocks(fmd); |
| 1534 | fimc_md_unregister_entities(fmd); | 1526 | fimc_md_unregister_entities(fmd); |
| 1527 | media_device_unregister(&fmd->media_dev); | ||
| 1535 | err_md: | 1528 | err_md: |
| 1536 | v4l2_device_unregister(&fmd->v4l2_dev); | 1529 | v4l2_device_unregister(&fmd->v4l2_dev); |
| 1537 | return ret; | 1530 | return ret; |
| @@ -1543,6 +1536,8 @@ static int fimc_md_remove(struct platform_device *pdev) | |||
| 1543 | 1536 | ||
| 1544 | if (!fmd) | 1537 | if (!fmd) |
| 1545 | return 0; | 1538 | return 0; |
| 1539 | |||
| 1540 | v4l2_device_unregister(&fmd->v4l2_dev); | ||
| 1546 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); | 1541 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); |
| 1547 | fimc_md_unregister_entities(fmd); | 1542 | fimc_md_unregister_entities(fmd); |
| 1548 | fimc_md_pipelines_free(fmd); | 1543 | fimc_md_pipelines_free(fmd); |
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index 1f079ff33d4b..562845361246 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c | |||
| @@ -399,7 +399,7 @@ static void cafe_ctlr_init(struct mcam_camera *mcam) | |||
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | 401 | ||
| 402 | static void cafe_ctlr_power_up(struct mcam_camera *mcam) | 402 | static int cafe_ctlr_power_up(struct mcam_camera *mcam) |
| 403 | { | 403 | { |
| 404 | /* | 404 | /* |
| 405 | * Part one of the sensor dance: turn the global | 405 | * Part one of the sensor dance: turn the global |
| @@ -414,6 +414,8 @@ static void cafe_ctlr_power_up(struct mcam_camera *mcam) | |||
| 414 | */ | 414 | */ |
| 415 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ | 415 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ |
| 416 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); | 416 | mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); |
| 417 | |||
| 418 | return 0; | ||
| 417 | } | 419 | } |
| 418 | 420 | ||
| 419 | static void cafe_ctlr_power_down(struct mcam_camera *mcam) | 421 | static void cafe_ctlr_power_down(struct mcam_camera *mcam) |
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 0821ed08c122..5184887b155c 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <linux/clk.h> | ||
| 22 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
| 23 | #include <media/v4l2-device.h> | 24 | #include <media/v4l2-device.h> |
| 24 | #include <media/v4l2-ioctl.h> | 25 | #include <media/v4l2-ioctl.h> |
| @@ -93,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode, | |||
| 93 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | 94 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ |
| 94 | #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ | 95 | #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ |
| 95 | #define CF_SG_RESTART 6 /* SG restart needed */ | 96 | #define CF_SG_RESTART 6 /* SG restart needed */ |
| 97 | #define CF_FRAME_SOF0 7 /* Frame 0 started */ | ||
| 98 | #define CF_FRAME_SOF1 8 | ||
| 99 | #define CF_FRAME_SOF2 9 | ||
| 96 | 100 | ||
| 97 | #define sensor_call(cam, o, f, args...) \ | 101 | #define sensor_call(cam, o, f, args...) \ |
| 98 | v4l2_subdev_call(cam->sensor, o, f, ##args) | 102 | v4l2_subdev_call(cam->sensor, o, f, ##args) |
| @@ -101,6 +105,7 @@ static struct mcam_format_struct { | |||
| 101 | __u8 *desc; | 105 | __u8 *desc; |
| 102 | __u32 pixelformat; | 106 | __u32 pixelformat; |
| 103 | int bpp; /* Bytes per pixel */ | 107 | int bpp; /* Bytes per pixel */ |
| 108 | bool planar; | ||
| 104 | enum v4l2_mbus_pixelcode mbus_code; | 109 | enum v4l2_mbus_pixelcode mbus_code; |
| 105 | } mcam_formats[] = { | 110 | } mcam_formats[] = { |
| 106 | { | 111 | { |
| @@ -108,24 +113,56 @@ static struct mcam_format_struct { | |||
| 108 | .pixelformat = V4L2_PIX_FMT_YUYV, | 113 | .pixelformat = V4L2_PIX_FMT_YUYV, |
| 109 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | 114 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, |
| 110 | .bpp = 2, | 115 | .bpp = 2, |
| 116 | .planar = false, | ||
| 117 | }, | ||
| 118 | { | ||
| 119 | .desc = "UYVY 4:2:2", | ||
| 120 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
| 121 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
| 122 | .bpp = 2, | ||
| 123 | .planar = false, | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | .desc = "YUV 4:2:2 PLANAR", | ||
| 127 | .pixelformat = V4L2_PIX_FMT_YUV422P, | ||
| 128 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
| 129 | .bpp = 2, | ||
| 130 | .planar = true, | ||
| 131 | }, | ||
| 132 | { | ||
| 133 | .desc = "YUV 4:2:0 PLANAR", | ||
| 134 | .pixelformat = V4L2_PIX_FMT_YUV420, | ||
| 135 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
| 136 | .bpp = 2, | ||
| 137 | .planar = true, | ||
| 138 | }, | ||
| 139 | { | ||
| 140 | .desc = "YVU 4:2:0 PLANAR", | ||
| 141 | .pixelformat = V4L2_PIX_FMT_YVU420, | ||
| 142 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
| 143 | .bpp = 2, | ||
| 144 | .planar = true, | ||
| 111 | }, | 145 | }, |
| 112 | { | 146 | { |
| 113 | .desc = "RGB 444", | 147 | .desc = "RGB 444", |
| 114 | .pixelformat = V4L2_PIX_FMT_RGB444, | 148 | .pixelformat = V4L2_PIX_FMT_RGB444, |
| 115 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | 149 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, |
| 116 | .bpp = 2, | 150 | .bpp = 2, |
| 151 | .planar = false, | ||
| 117 | }, | 152 | }, |
| 118 | { | 153 | { |
| 119 | .desc = "RGB 565", | 154 | .desc = "RGB 565", |
| 120 | .pixelformat = V4L2_PIX_FMT_RGB565, | 155 | .pixelformat = V4L2_PIX_FMT_RGB565, |
| 121 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | 156 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, |
| 122 | .bpp = 2, | 157 | .bpp = 2, |
| 158 | .planar = false, | ||
| 123 | }, | 159 | }, |
| 124 | { | 160 | { |
| 125 | .desc = "Raw RGB Bayer", | 161 | .desc = "Raw RGB Bayer", |
| 126 | .pixelformat = V4L2_PIX_FMT_SBGGR8, | 162 | .pixelformat = V4L2_PIX_FMT_SBGGR8, |
| 127 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, | 163 | .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, |
| 128 | .bpp = 1 | 164 | .bpp = 1, |
| 165 | .planar = false, | ||
| 129 | }, | 166 | }, |
| 130 | }; | 167 | }; |
| 131 | #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats) | 168 | #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats) |
| @@ -168,6 +205,12 @@ struct mcam_dma_desc { | |||
| 168 | u32 segment_len; | 205 | u32 segment_len; |
| 169 | }; | 206 | }; |
| 170 | 207 | ||
| 208 | struct yuv_pointer_t { | ||
| 209 | dma_addr_t y; | ||
| 210 | dma_addr_t u; | ||
| 211 | dma_addr_t v; | ||
| 212 | }; | ||
| 213 | |||
| 171 | /* | 214 | /* |
| 172 | * Our buffer type for working with videobuf2. Note that the vb2 | 215 | * Our buffer type for working with videobuf2. Note that the vb2 |
| 173 | * developers have decreed that struct vb2_buffer must be at the | 216 | * developers have decreed that struct vb2_buffer must be at the |
| @@ -179,6 +222,7 @@ struct mcam_vb_buffer { | |||
| 179 | struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ | 222 | struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ |
| 180 | dma_addr_t dma_desc_pa; /* Descriptor physical address */ | 223 | dma_addr_t dma_desc_pa; /* Descriptor physical address */ |
| 181 | int dma_desc_nent; /* Number of mapped descriptors */ | 224 | int dma_desc_nent; /* Number of mapped descriptors */ |
| 225 | struct yuv_pointer_t yuv_p; | ||
| 182 | }; | 226 | }; |
| 183 | 227 | ||
| 184 | static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) | 228 | static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) |
| @@ -219,8 +263,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam) | |||
| 219 | int i; | 263 | int i; |
| 220 | 264 | ||
| 221 | cam->next_buf = -1; | 265 | cam->next_buf = -1; |
| 222 | for (i = 0; i < cam->nbufs; i++) | 266 | for (i = 0; i < cam->nbufs; i++) { |
| 223 | clear_bit(i, &cam->flags); | 267 | clear_bit(i, &cam->flags); |
| 268 | clear_bit(CF_FRAME_SOF0 + i, &cam->flags); | ||
| 269 | } | ||
| 224 | } | 270 | } |
| 225 | 271 | ||
| 226 | static inline int mcam_needs_config(struct mcam_camera *cam) | 272 | static inline int mcam_needs_config(struct mcam_camera *cam) |
| @@ -253,6 +299,45 @@ static void mcam_ctlr_stop(struct mcam_camera *cam) | |||
| 253 | mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); | 299 | mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); |
| 254 | } | 300 | } |
| 255 | 301 | ||
| 302 | static void mcam_enable_mipi(struct mcam_camera *mcam) | ||
| 303 | { | ||
| 304 | /* Using MIPI mode and enable MIPI */ | ||
| 305 | cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n", | ||
| 306 | mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]); | ||
| 307 | mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]); | ||
| 308 | mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]); | ||
| 309 | mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]); | ||
| 310 | |||
| 311 | if (!mcam->mipi_enabled) { | ||
| 312 | if (mcam->lane > 4 || mcam->lane <= 0) { | ||
| 313 | cam_warn(mcam, "lane number error\n"); | ||
| 314 | mcam->lane = 1; /* set the default value */ | ||
| 315 | } | ||
| 316 | /* | ||
| 317 | * 0x41 actives 1 lane | ||
| 318 | * 0x43 actives 2 lanes | ||
| 319 | * 0x45 actives 3 lanes (never happen) | ||
| 320 | * 0x47 actives 4 lanes | ||
| 321 | */ | ||
| 322 | mcam_reg_write(mcam, REG_CSI2_CTRL0, | ||
| 323 | CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane)); | ||
| 324 | mcam_reg_write(mcam, REG_CLKCTRL, | ||
| 325 | (mcam->mclk_src << 29) | mcam->mclk_div); | ||
| 326 | |||
| 327 | mcam->mipi_enabled = true; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | static void mcam_disable_mipi(struct mcam_camera *mcam) | ||
| 332 | { | ||
| 333 | /* Using Parallel mode or disable MIPI */ | ||
| 334 | mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0); | ||
| 335 | mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0); | ||
| 336 | mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0); | ||
| 337 | mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0); | ||
| 338 | mcam->mipi_enabled = false; | ||
| 339 | } | ||
| 340 | |||
| 256 | /* ------------------------------------------------------------------- */ | 341 | /* ------------------------------------------------------------------- */ |
| 257 | 342 | ||
| 258 | #ifdef MCAM_MODE_VMALLOC | 343 | #ifdef MCAM_MODE_VMALLOC |
| @@ -425,6 +510,15 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam) | |||
| 425 | /* | 510 | /* |
| 426 | * DMA-contiguous code. | 511 | * DMA-contiguous code. |
| 427 | */ | 512 | */ |
| 513 | |||
| 514 | static bool mcam_fmt_is_planar(__u32 pfmt) | ||
| 515 | { | ||
| 516 | struct mcam_format_struct *f; | ||
| 517 | |||
| 518 | f = mcam_find_format(pfmt); | ||
| 519 | return f->planar; | ||
| 520 | } | ||
| 521 | |||
| 428 | /* | 522 | /* |
| 429 | * Set up a contiguous buffer for the given frame. Here also is where | 523 | * Set up a contiguous buffer for the given frame. Here also is where |
| 430 | * the underrun strategy is set: if there is no buffer available, reuse | 524 | * the underrun strategy is set: if there is no buffer available, reuse |
| @@ -436,27 +530,58 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam) | |||
| 436 | static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) | 530 | static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) |
| 437 | { | 531 | { |
| 438 | struct mcam_vb_buffer *buf; | 532 | struct mcam_vb_buffer *buf; |
| 533 | struct v4l2_pix_format *fmt = &cam->pix_format; | ||
| 534 | dma_addr_t dma_handle; | ||
| 535 | u32 pixel_count = fmt->width * fmt->height; | ||
| 536 | struct vb2_buffer *vb; | ||
| 537 | |||
| 439 | /* | 538 | /* |
| 440 | * If there are no available buffers, go into single mode | 539 | * If there are no available buffers, go into single mode |
| 441 | */ | 540 | */ |
| 442 | if (list_empty(&cam->buffers)) { | 541 | if (list_empty(&cam->buffers)) { |
| 443 | buf = cam->vb_bufs[frame ^ 0x1]; | 542 | buf = cam->vb_bufs[frame ^ 0x1]; |
| 444 | cam->vb_bufs[frame] = buf; | ||
| 445 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
| 446 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); | ||
| 447 | set_bit(CF_SINGLE_BUFFER, &cam->flags); | 543 | set_bit(CF_SINGLE_BUFFER, &cam->flags); |
| 448 | cam->frame_state.singles++; | 544 | cam->frame_state.singles++; |
| 449 | return; | 545 | } else { |
| 546 | /* | ||
| 547 | * OK, we have a buffer we can use. | ||
| 548 | */ | ||
| 549 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, | ||
| 550 | queue); | ||
| 551 | list_del_init(&buf->queue); | ||
| 552 | clear_bit(CF_SINGLE_BUFFER, &cam->flags); | ||
| 450 | } | 553 | } |
| 451 | /* | 554 | |
| 452 | * OK, we have a buffer we can use. | ||
| 453 | */ | ||
| 454 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); | ||
| 455 | list_del_init(&buf->queue); | ||
| 456 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
| 457 | vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); | ||
| 458 | cam->vb_bufs[frame] = buf; | 555 | cam->vb_bufs[frame] = buf; |
| 459 | clear_bit(CF_SINGLE_BUFFER, &cam->flags); | 556 | vb = &buf->vb_buf; |
| 557 | |||
| 558 | dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
| 559 | buf->yuv_p.y = dma_handle; | ||
| 560 | |||
| 561 | switch (cam->pix_format.pixelformat) { | ||
| 562 | case V4L2_PIX_FMT_YUV422P: | ||
| 563 | buf->yuv_p.u = buf->yuv_p.y + pixel_count; | ||
| 564 | buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2; | ||
| 565 | break; | ||
| 566 | case V4L2_PIX_FMT_YUV420: | ||
| 567 | buf->yuv_p.u = buf->yuv_p.y + pixel_count; | ||
| 568 | buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4; | ||
| 569 | break; | ||
| 570 | case V4L2_PIX_FMT_YVU420: | ||
| 571 | buf->yuv_p.v = buf->yuv_p.y + pixel_count; | ||
| 572 | buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4; | ||
| 573 | break; | ||
| 574 | default: | ||
| 575 | break; | ||
| 576 | } | ||
| 577 | |||
| 578 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y); | ||
| 579 | if (mcam_fmt_is_planar(fmt->pixelformat)) { | ||
| 580 | mcam_reg_write(cam, frame == 0 ? | ||
| 581 | REG_U0BAR : REG_U1BAR, buf->yuv_p.u); | ||
| 582 | mcam_reg_write(cam, frame == 0 ? | ||
| 583 | REG_V0BAR : REG_V1BAR, buf->yuv_p.v); | ||
| 584 | } | ||
| 460 | } | 585 | } |
| 461 | 586 | ||
| 462 | /* | 587 | /* |
| @@ -614,48 +739,90 @@ static inline void mcam_sg_restart(struct mcam_camera *cam) | |||
| 614 | */ | 739 | */ |
| 615 | static void mcam_ctlr_image(struct mcam_camera *cam) | 740 | static void mcam_ctlr_image(struct mcam_camera *cam) |
| 616 | { | 741 | { |
| 617 | int imgsz; | ||
| 618 | struct v4l2_pix_format *fmt = &cam->pix_format; | 742 | struct v4l2_pix_format *fmt = &cam->pix_format; |
| 743 | u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w; | ||
| 744 | |||
| 745 | cam_dbg(cam, "camera: bytesperline = %d; height = %d\n", | ||
| 746 | fmt->bytesperline, fmt->sizeimage / fmt->bytesperline); | ||
| 747 | imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK; | ||
| 748 | imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK; | ||
| 749 | |||
| 750 | switch (fmt->pixelformat) { | ||
| 751 | case V4L2_PIX_FMT_YUYV: | ||
| 752 | case V4L2_PIX_FMT_UYVY: | ||
| 753 | widthy = fmt->width * 2; | ||
| 754 | widthuv = 0; | ||
| 755 | break; | ||
| 756 | case V4L2_PIX_FMT_JPEG: | ||
| 757 | imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT; | ||
| 758 | widthy = fmt->bytesperline; | ||
| 759 | widthuv = 0; | ||
| 760 | break; | ||
| 761 | case V4L2_PIX_FMT_YUV422P: | ||
| 762 | case V4L2_PIX_FMT_YUV420: | ||
| 763 | case V4L2_PIX_FMT_YVU420: | ||
| 764 | widthy = fmt->width; | ||
| 765 | widthuv = fmt->width / 2; | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | widthy = fmt->bytesperline; | ||
| 769 | widthuv = 0; | ||
| 770 | } | ||
| 771 | |||
| 772 | mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy, | ||
| 773 | IMGP_YP_MASK | IMGP_UVP_MASK); | ||
| 774 | mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w); | ||
| 775 | mcam_reg_write(cam, REG_IMGOFFSET, 0x0); | ||
| 619 | 776 | ||
| 620 | imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | | ||
| 621 | (fmt->bytesperline & IMGSZ_H_MASK); | ||
| 622 | mcam_reg_write(cam, REG_IMGSIZE, imgsz); | ||
| 623 | mcam_reg_write(cam, REG_IMGOFFSET, 0); | ||
| 624 | /* YPITCH just drops the last two bits */ | ||
| 625 | mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, | ||
| 626 | IMGP_YP_MASK); | ||
| 627 | /* | 777 | /* |
| 628 | * Tell the controller about the image format we are using. | 778 | * Tell the controller about the image format we are using. |
| 629 | */ | 779 | */ |
| 630 | switch (cam->pix_format.pixelformat) { | 780 | switch (fmt->pixelformat) { |
| 781 | case V4L2_PIX_FMT_YUV422P: | ||
| 782 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
| 783 | C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK); | ||
| 784 | break; | ||
| 785 | case V4L2_PIX_FMT_YUV420: | ||
| 786 | case V4L2_PIX_FMT_YVU420: | ||
| 787 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
| 788 | C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK); | ||
| 789 | break; | ||
| 631 | case V4L2_PIX_FMT_YUYV: | 790 | case V4L2_PIX_FMT_YUYV: |
| 632 | mcam_reg_write_mask(cam, REG_CTRL0, | 791 | mcam_reg_write_mask(cam, REG_CTRL0, |
| 633 | C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, | 792 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK); |
| 634 | C0_DF_MASK); | 793 | break; |
| 635 | break; | 794 | case V4L2_PIX_FMT_UYVY: |
| 636 | 795 | mcam_reg_write_mask(cam, REG_CTRL0, | |
| 796 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK); | ||
| 797 | break; | ||
| 798 | case V4L2_PIX_FMT_JPEG: | ||
| 799 | mcam_reg_write_mask(cam, REG_CTRL0, | ||
| 800 | C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK); | ||
| 801 | break; | ||
| 637 | case V4L2_PIX_FMT_RGB444: | 802 | case V4L2_PIX_FMT_RGB444: |
| 638 | mcam_reg_write_mask(cam, REG_CTRL0, | 803 | mcam_reg_write_mask(cam, REG_CTRL0, |
| 639 | C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, | 804 | C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK); |
| 640 | C0_DF_MASK); | ||
| 641 | /* Alpha value? */ | 805 | /* Alpha value? */ |
| 642 | break; | 806 | break; |
| 643 | |||
| 644 | case V4L2_PIX_FMT_RGB565: | 807 | case V4L2_PIX_FMT_RGB565: |
| 645 | mcam_reg_write_mask(cam, REG_CTRL0, | 808 | mcam_reg_write_mask(cam, REG_CTRL0, |
| 646 | C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, | 809 | C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK); |
| 647 | C0_DF_MASK); | 810 | break; |
| 648 | break; | ||
| 649 | |||
| 650 | default: | 811 | default: |
| 651 | cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); | 812 | cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat); |
| 652 | break; | 813 | break; |
| 653 | } | 814 | } |
| 815 | |||
| 654 | /* | 816 | /* |
| 655 | * Make sure it knows we want to use hsync/vsync. | 817 | * Make sure it knows we want to use hsync/vsync. |
| 656 | */ | 818 | */ |
| 657 | mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, | 819 | mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK); |
| 658 | C0_SIFM_MASK); | 820 | /* |
| 821 | * This field controls the generation of EOF(DVP only) | ||
| 822 | */ | ||
| 823 | if (cam->bus_type != V4L2_MBUS_CSI2) | ||
| 824 | mcam_reg_set_bit(cam, REG_CTRL0, | ||
| 825 | C0_EOF_VSYNC | C0_VEDGE_CTRL); | ||
| 659 | } | 826 | } |
| 660 | 827 | ||
| 661 | 828 | ||
| @@ -753,15 +920,21 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam) | |||
| 753 | /* | 920 | /* |
| 754 | * Power up and down. | 921 | * Power up and down. |
| 755 | */ | 922 | */ |
| 756 | static void mcam_ctlr_power_up(struct mcam_camera *cam) | 923 | static int mcam_ctlr_power_up(struct mcam_camera *cam) |
| 757 | { | 924 | { |
| 758 | unsigned long flags; | 925 | unsigned long flags; |
| 926 | int ret; | ||
| 759 | 927 | ||
| 760 | spin_lock_irqsave(&cam->dev_lock, flags); | 928 | spin_lock_irqsave(&cam->dev_lock, flags); |
| 761 | cam->plat_power_up(cam); | 929 | ret = cam->plat_power_up(cam); |
| 930 | if (ret) { | ||
| 931 | spin_unlock_irqrestore(&cam->dev_lock, flags); | ||
| 932 | return ret; | ||
| 933 | } | ||
| 762 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); | 934 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); |
| 763 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 935 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
| 764 | msleep(5); /* Just to be sure */ | 936 | msleep(5); /* Just to be sure */ |
| 937 | return 0; | ||
| 765 | } | 938 | } |
| 766 | 939 | ||
| 767 | static void mcam_ctlr_power_down(struct mcam_camera *cam) | 940 | static void mcam_ctlr_power_down(struct mcam_camera *cam) |
| @@ -869,6 +1042,17 @@ static int mcam_read_setup(struct mcam_camera *cam) | |||
| 869 | spin_lock_irqsave(&cam->dev_lock, flags); | 1042 | spin_lock_irqsave(&cam->dev_lock, flags); |
| 870 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | 1043 | clear_bit(CF_DMA_ACTIVE, &cam->flags); |
| 871 | mcam_reset_buffers(cam); | 1044 | mcam_reset_buffers(cam); |
| 1045 | /* | ||
| 1046 | * Update CSI2_DPHY value | ||
| 1047 | */ | ||
| 1048 | if (cam->calc_dphy) | ||
| 1049 | cam->calc_dphy(cam); | ||
| 1050 | cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", | ||
| 1051 | cam->dphy[0], cam->dphy[1], cam->dphy[2]); | ||
| 1052 | if (cam->bus_type == V4L2_MBUS_CSI2) | ||
| 1053 | mcam_enable_mipi(cam); | ||
| 1054 | else | ||
| 1055 | mcam_disable_mipi(cam); | ||
| 872 | mcam_ctlr_irq_enable(cam); | 1056 | mcam_ctlr_irq_enable(cam); |
| 873 | cam->state = S_STREAMING; | 1057 | cam->state = S_STREAMING; |
| 874 | if (!test_bit(CF_SG_RESTART, &cam->flags)) | 1058 | if (!test_bit(CF_SG_RESTART, &cam->flags)) |
| @@ -943,6 +1127,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq) | |||
| 943 | static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) | 1127 | static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) |
| 944 | { | 1128 | { |
| 945 | struct mcam_camera *cam = vb2_get_drv_priv(vq); | 1129 | struct mcam_camera *cam = vb2_get_drv_priv(vq); |
| 1130 | unsigned int frame; | ||
| 946 | 1131 | ||
| 947 | if (cam->state != S_IDLE) { | 1132 | if (cam->state != S_IDLE) { |
| 948 | INIT_LIST_HEAD(&cam->buffers); | 1133 | INIT_LIST_HEAD(&cam->buffers); |
| @@ -960,6 +1145,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) | |||
| 960 | cam->state = S_BUFWAIT; | 1145 | cam->state = S_BUFWAIT; |
| 961 | return 0; | 1146 | return 0; |
| 962 | } | 1147 | } |
| 1148 | |||
| 1149 | /* | ||
| 1150 | * Ensure clear the left over frame flags | ||
| 1151 | * before every really start streaming | ||
| 1152 | */ | ||
| 1153 | for (frame = 0; frame < cam->nbufs; frame++) | ||
| 1154 | clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
| 1155 | |||
| 963 | return mcam_read_setup(cam); | 1156 | return mcam_read_setup(cam); |
| 964 | } | 1157 | } |
| 965 | 1158 | ||
| @@ -977,6 +1170,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq) | |||
| 977 | return -EINVAL; | 1170 | return -EINVAL; |
| 978 | mcam_ctlr_stop_dma(cam); | 1171 | mcam_ctlr_stop_dma(cam); |
| 979 | /* | 1172 | /* |
| 1173 | * Reset the CCIC PHY after stopping streaming, | ||
| 1174 | * otherwise, the CCIC may be unstable. | ||
| 1175 | */ | ||
| 1176 | if (cam->ctlr_reset) | ||
| 1177 | cam->ctlr_reset(cam); | ||
| 1178 | /* | ||
| 980 | * VB2 reclaims the buffers, so we need to forget | 1179 | * VB2 reclaims the buffers, so we need to forget |
| 981 | * about them. | 1180 | * about them. |
| 982 | */ | 1181 | */ |
| @@ -1087,6 +1286,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
| 1087 | #ifdef MCAM_MODE_DMA_CONTIG | 1286 | #ifdef MCAM_MODE_DMA_CONTIG |
| 1088 | vq->ops = &mcam_vb2_ops; | 1287 | vq->ops = &mcam_vb2_ops; |
| 1089 | vq->mem_ops = &vb2_dma_contig_memops; | 1288 | vq->mem_ops = &vb2_dma_contig_memops; |
| 1289 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); | ||
| 1090 | cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); | 1290 | cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); |
| 1091 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | 1291 | vq->io_modes = VB2_MMAP | VB2_USERPTR; |
| 1092 | cam->dma_setup = mcam_ctlr_dma_contig; | 1292 | cam->dma_setup = mcam_ctlr_dma_contig; |
| @@ -1097,6 +1297,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
| 1097 | #ifdef MCAM_MODE_DMA_SG | 1297 | #ifdef MCAM_MODE_DMA_SG |
| 1098 | vq->ops = &mcam_vb2_sg_ops; | 1298 | vq->ops = &mcam_vb2_sg_ops; |
| 1099 | vq->mem_ops = &vb2_dma_sg_memops; | 1299 | vq->mem_ops = &vb2_dma_sg_memops; |
| 1300 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); | ||
| 1100 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | 1301 | vq->io_modes = VB2_MMAP | VB2_USERPTR; |
| 1101 | cam->dma_setup = mcam_ctlr_dma_sg; | 1302 | cam->dma_setup = mcam_ctlr_dma_sg; |
| 1102 | cam->frame_complete = mcam_dma_sg_done; | 1303 | cam->frame_complete = mcam_dma_sg_done; |
| @@ -1247,7 +1448,15 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, | |||
| 1247 | ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); | 1448 | ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); |
| 1248 | mutex_unlock(&cam->s_mutex); | 1449 | mutex_unlock(&cam->s_mutex); |
| 1249 | v4l2_fill_pix_format(pix, &mbus_fmt); | 1450 | v4l2_fill_pix_format(pix, &mbus_fmt); |
| 1250 | pix->bytesperline = pix->width * f->bpp; | 1451 | switch (f->pixelformat) { |
| 1452 | case V4L2_PIX_FMT_YUV420: | ||
| 1453 | case V4L2_PIX_FMT_YVU420: | ||
| 1454 | pix->bytesperline = pix->width * 3 / 2; | ||
| 1455 | break; | ||
| 1456 | default: | ||
| 1457 | pix->bytesperline = pix->width * f->bpp; | ||
| 1458 | break; | ||
| 1459 | } | ||
| 1251 | pix->sizeimage = pix->height * pix->bytesperline; | 1460 | pix->sizeimage = pix->height * pix->bytesperline; |
| 1252 | return ret; | 1461 | return ret; |
| 1253 | } | 1462 | } |
| @@ -1475,7 +1684,9 @@ static int mcam_v4l_open(struct file *filp) | |||
| 1475 | ret = mcam_setup_vb2(cam); | 1684 | ret = mcam_setup_vb2(cam); |
| 1476 | if (ret) | 1685 | if (ret) |
| 1477 | goto out; | 1686 | goto out; |
| 1478 | mcam_ctlr_power_up(cam); | 1687 | ret = mcam_ctlr_power_up(cam); |
| 1688 | if (ret) | ||
| 1689 | goto out; | ||
| 1479 | __mcam_cam_reset(cam); | 1690 | __mcam_cam_reset(cam); |
| 1480 | mcam_set_config_needed(cam, 1); | 1691 | mcam_set_config_needed(cam, 1); |
| 1481 | } | 1692 | } |
| @@ -1498,10 +1709,12 @@ static int mcam_v4l_release(struct file *filp) | |||
| 1498 | if (cam->users == 0) { | 1709 | if (cam->users == 0) { |
| 1499 | mcam_ctlr_stop_dma(cam); | 1710 | mcam_ctlr_stop_dma(cam); |
| 1500 | mcam_cleanup_vb2(cam); | 1711 | mcam_cleanup_vb2(cam); |
| 1712 | mcam_disable_mipi(cam); | ||
| 1501 | mcam_ctlr_power_down(cam); | 1713 | mcam_ctlr_power_down(cam); |
| 1502 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) | 1714 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) |
| 1503 | mcam_free_dma_bufs(cam); | 1715 | mcam_free_dma_bufs(cam); |
| 1504 | } | 1716 | } |
| 1717 | |||
| 1505 | mutex_unlock(&cam->s_mutex); | 1718 | mutex_unlock(&cam->s_mutex); |
| 1506 | return 0; | 1719 | return 0; |
| 1507 | } | 1720 | } |
| @@ -1617,9 +1830,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) | |||
| 1617 | * each time. | 1830 | * each time. |
| 1618 | */ | 1831 | */ |
| 1619 | for (frame = 0; frame < cam->nbufs; frame++) | 1832 | for (frame = 0; frame < cam->nbufs; frame++) |
| 1620 | if (irqs & (IRQ_EOF0 << frame)) { | 1833 | if (irqs & (IRQ_EOF0 << frame) && |
| 1834 | test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) { | ||
| 1621 | mcam_frame_complete(cam, frame); | 1835 | mcam_frame_complete(cam, frame); |
| 1622 | handled = 1; | 1836 | handled = 1; |
| 1837 | clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
| 1623 | if (cam->buffer_mode == B_DMA_sg) | 1838 | if (cam->buffer_mode == B_DMA_sg) |
| 1624 | break; | 1839 | break; |
| 1625 | } | 1840 | } |
| @@ -1628,9 +1843,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) | |||
| 1628 | * code assumes that we won't get multiple frame interrupts | 1843 | * code assumes that we won't get multiple frame interrupts |
| 1629 | * at once; may want to rethink that. | 1844 | * at once; may want to rethink that. |
| 1630 | */ | 1845 | */ |
| 1631 | if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) { | 1846 | for (frame = 0; frame < cam->nbufs; frame++) { |
| 1847 | if (irqs & (IRQ_SOF0 << frame)) { | ||
| 1848 | set_bit(CF_FRAME_SOF0 + frame, &cam->flags); | ||
| 1849 | handled = IRQ_HANDLED; | ||
| 1850 | } | ||
| 1851 | } | ||
| 1852 | |||
| 1853 | if (handled == IRQ_HANDLED) { | ||
| 1632 | set_bit(CF_DMA_ACTIVE, &cam->flags); | 1854 | set_bit(CF_DMA_ACTIVE, &cam->flags); |
| 1633 | handled = 1; | ||
| 1634 | if (cam->buffer_mode == B_DMA_sg) | 1855 | if (cam->buffer_mode == B_DMA_sg) |
| 1635 | mcam_ctlr_stop(cam); | 1856 | mcam_ctlr_stop(cam); |
| 1636 | } | 1857 | } |
| @@ -1787,7 +2008,11 @@ int mccic_resume(struct mcam_camera *cam) | |||
| 1787 | 2008 | ||
| 1788 | mutex_lock(&cam->s_mutex); | 2009 | mutex_lock(&cam->s_mutex); |
| 1789 | if (cam->users > 0) { | 2010 | if (cam->users > 0) { |
| 1790 | mcam_ctlr_power_up(cam); | 2011 | ret = mcam_ctlr_power_up(cam); |
| 2012 | if (ret) { | ||
| 2013 | mutex_unlock(&cam->s_mutex); | ||
| 2014 | return ret; | ||
| 2015 | } | ||
| 1791 | __mcam_cam_reset(cam); | 2016 | __mcam_cam_reset(cam); |
| 1792 | } else { | 2017 | } else { |
| 1793 | mcam_ctlr_power_down(cam); | 2018 | mcam_ctlr_power_down(cam); |
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 520c8ded9443..e0e628cb98f9 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h | |||
| @@ -88,6 +88,8 @@ struct mcam_frame_state { | |||
| 88 | unsigned int delivered; | 88 | unsigned int delivered; |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | #define NR_MCAM_CLK 3 | ||
| 92 | |||
| 91 | /* | 93 | /* |
| 92 | * A description of one of our devices. | 94 | * A description of one of our devices. |
| 93 | * Locking: controlled by s_mutex. Certain fields, however, require | 95 | * Locking: controlled by s_mutex. Certain fields, however, require |
| @@ -108,11 +110,33 @@ struct mcam_camera { | |||
| 108 | short int clock_speed; /* Sensor clock speed, default 30 */ | 110 | short int clock_speed; /* Sensor clock speed, default 30 */ |
| 109 | short int use_smbus; /* SMBUS or straight I2c? */ | 111 | short int use_smbus; /* SMBUS or straight I2c? */ |
| 110 | enum mcam_buffer_mode buffer_mode; | 112 | enum mcam_buffer_mode buffer_mode; |
| 113 | |||
| 114 | int mclk_min; /* The minimal value of mclk */ | ||
| 115 | int mclk_src; /* which clock source the mclk derives from */ | ||
| 116 | int mclk_div; /* Clock Divider Value for MCLK */ | ||
| 117 | |||
| 118 | int ccic_id; | ||
| 119 | enum v4l2_mbus_type bus_type; | ||
| 120 | /* MIPI support */ | ||
| 121 | /* The dphy config value, allocated in board file | ||
| 122 | * dphy[0]: DPHY3 | ||
| 123 | * dphy[1]: DPHY5 | ||
| 124 | * dphy[2]: DPHY6 | ||
| 125 | */ | ||
| 126 | int *dphy; | ||
| 127 | bool mipi_enabled; /* flag whether mipi is enabled already */ | ||
| 128 | int lane; /* lane number */ | ||
| 129 | |||
| 130 | /* clock tree support */ | ||
| 131 | struct clk *clk[NR_MCAM_CLK]; | ||
| 132 | |||
| 111 | /* | 133 | /* |
| 112 | * Callbacks from the core to the platform code. | 134 | * Callbacks from the core to the platform code. |
| 113 | */ | 135 | */ |
| 114 | void (*plat_power_up) (struct mcam_camera *cam); | 136 | int (*plat_power_up) (struct mcam_camera *cam); |
| 115 | void (*plat_power_down) (struct mcam_camera *cam); | 137 | void (*plat_power_down) (struct mcam_camera *cam); |
| 138 | void (*calc_dphy) (struct mcam_camera *cam); | ||
| 139 | void (*ctlr_reset) (struct mcam_camera *cam); | ||
| 116 | 140 | ||
| 117 | /* | 141 | /* |
| 118 | * Everything below here is private to the mcam core and | 142 | * Everything below here is private to the mcam core and |
| @@ -225,6 +249,23 @@ int mccic_resume(struct mcam_camera *cam); | |||
| 225 | #define REG_Y0BAR 0x00 | 249 | #define REG_Y0BAR 0x00 |
| 226 | #define REG_Y1BAR 0x04 | 250 | #define REG_Y1BAR 0x04 |
| 227 | #define REG_Y2BAR 0x08 | 251 | #define REG_Y2BAR 0x08 |
| 252 | #define REG_U0BAR 0x0c | ||
| 253 | #define REG_U1BAR 0x10 | ||
| 254 | #define REG_U2BAR 0x14 | ||
| 255 | #define REG_V0BAR 0x18 | ||
| 256 | #define REG_V1BAR 0x1C | ||
| 257 | #define REG_V2BAR 0x20 | ||
| 258 | |||
| 259 | /* | ||
| 260 | * register definitions for MIPI support | ||
| 261 | */ | ||
| 262 | #define REG_CSI2_CTRL0 0x100 | ||
| 263 | #define CSI2_C0_MIPI_EN (0x1 << 0) | ||
| 264 | #define CSI2_C0_ACT_LANE(n) ((n-1) << 1) | ||
| 265 | #define REG_CSI2_DPHY3 0x12c | ||
| 266 | #define REG_CSI2_DPHY5 0x134 | ||
| 267 | #define REG_CSI2_DPHY6 0x138 | ||
| 268 | |||
| 228 | /* ... */ | 269 | /* ... */ |
| 229 | 270 | ||
| 230 | #define REG_IMGPITCH 0x24 /* Image pitch register */ | 271 | #define REG_IMGPITCH 0x24 /* Image pitch register */ |
| @@ -293,13 +334,16 @@ int mccic_resume(struct mcam_camera *cam); | |||
| 293 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ | 334 | #define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */ |
| 294 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ | 335 | #define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */ |
| 295 | /* Bayer bits 18,19 if needed */ | 336 | /* Bayer bits 18,19 if needed */ |
| 337 | #define C0_EOF_VSYNC 0x00400000 /* Generate EOF by VSYNC */ | ||
| 338 | #define C0_VEDGE_CTRL 0x00800000 /* Detect falling edge of VSYNC */ | ||
| 296 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ | 339 | #define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */ |
| 297 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ | 340 | #define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */ |
| 298 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ | 341 | #define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */ |
| 299 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ | 342 | #define C0_DOWNSCALE 0x08000000 /* Enable downscaler */ |
| 300 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | 343 | /* SIFMODE */ |
| 301 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ | 344 | #define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */ |
| 302 | #define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ | 345 | #define C0_SOF_NOSYNC 0x40000000 /* Use inband active signaling */ |
| 346 | #define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */ | ||
| 303 | 347 | ||
| 304 | /* Bits below C1_444ALPHA are not present in Cafe */ | 348 | /* Bits below C1_444ALPHA are not present in Cafe */ |
| 305 | #define REG_CTRL1 0x40 /* Control 1 */ | 349 | #define REG_CTRL1 0x40 /* Control 1 */ |
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index a634888271cd..b5a19af5c587 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 27 | #include <linux/list.h> | 27 | #include <linux/list.h> |
| 28 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
| 29 | #include <linux/clk.h> | ||
| 29 | 30 | ||
| 30 | #include "mcam-core.h" | 31 | #include "mcam-core.h" |
| 31 | 32 | ||
| @@ -33,11 +34,14 @@ MODULE_ALIAS("platform:mmp-camera"); | |||
| 33 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | 34 | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); |
| 34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
| 35 | 36 | ||
| 37 | static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"}; | ||
| 38 | |||
| 36 | struct mmp_camera { | 39 | struct mmp_camera { |
| 37 | void *power_regs; | 40 | void *power_regs; |
| 38 | struct platform_device *pdev; | 41 | struct platform_device *pdev; |
| 39 | struct mcam_camera mcam; | 42 | struct mcam_camera mcam; |
| 40 | struct list_head devlist; | 43 | struct list_head devlist; |
| 44 | struct clk *mipi_clk; | ||
| 41 | int irq; | 45 | int irq; |
| 42 | }; | 46 | }; |
| 43 | 47 | ||
| @@ -101,6 +105,27 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) | |||
| 101 | #define CPU_SUBSYS_PMU_BASE 0xd4282800 | 105 | #define CPU_SUBSYS_PMU_BASE 0xd4282800 |
| 102 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ | 106 | #define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ |
| 103 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ | 107 | #define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ |
| 108 | #define REG_CCIC2_CRCR 0xf4 /* CCIC2 clk reset ctrl reg */ | ||
| 109 | |||
| 110 | static void mcam_clk_enable(struct mcam_camera *mcam) | ||
| 111 | { | ||
| 112 | unsigned int i; | ||
| 113 | |||
| 114 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
| 115 | if (!IS_ERR(mcam->clk[i])) | ||
| 116 | clk_prepare_enable(mcam->clk[i]); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | static void mcam_clk_disable(struct mcam_camera *mcam) | ||
| 121 | { | ||
| 122 | int i; | ||
| 123 | |||
| 124 | for (i = NR_MCAM_CLK - 1; i >= 0; i--) { | ||
| 125 | if (!IS_ERR(mcam->clk[i])) | ||
| 126 | clk_disable_unprepare(mcam->clk[i]); | ||
| 127 | } | ||
| 128 | } | ||
| 104 | 129 | ||
| 105 | /* | 130 | /* |
| 106 | * Power control. | 131 | * Power control. |
| @@ -112,10 +137,17 @@ static void mmpcam_power_up_ctlr(struct mmp_camera *cam) | |||
| 112 | mdelay(1); | 137 | mdelay(1); |
| 113 | } | 138 | } |
| 114 | 139 | ||
| 115 | static void mmpcam_power_up(struct mcam_camera *mcam) | 140 | static int mmpcam_power_up(struct mcam_camera *mcam) |
| 116 | { | 141 | { |
| 117 | struct mmp_camera *cam = mcam_to_cam(mcam); | 142 | struct mmp_camera *cam = mcam_to_cam(mcam); |
| 118 | struct mmp_camera_platform_data *pdata; | 143 | struct mmp_camera_platform_data *pdata; |
| 144 | |||
| 145 | if (mcam->bus_type == V4L2_MBUS_CSI2) { | ||
| 146 | cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); | ||
| 147 | if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) | ||
| 148 | return PTR_ERR(cam->mipi_clk); | ||
| 149 | } | ||
| 150 | |||
| 119 | /* | 151 | /* |
| 120 | * Turn on power and clocks to the controller. | 152 | * Turn on power and clocks to the controller. |
| 121 | */ | 153 | */ |
| @@ -132,6 +164,10 @@ static void mmpcam_power_up(struct mcam_camera *mcam) | |||
| 132 | mdelay(5); | 164 | mdelay(5); |
| 133 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ | 165 | gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ |
| 134 | mdelay(5); | 166 | mdelay(5); |
| 167 | |||
| 168 | mcam_clk_enable(mcam); | ||
| 169 | |||
| 170 | return 0; | ||
| 135 | } | 171 | } |
| 136 | 172 | ||
| 137 | static void mmpcam_power_down(struct mcam_camera *mcam) | 173 | static void mmpcam_power_down(struct mcam_camera *mcam) |
| @@ -149,8 +185,133 @@ static void mmpcam_power_down(struct mcam_camera *mcam) | |||
| 149 | pdata = cam->pdev->dev.platform_data; | 185 | pdata = cam->pdev->dev.platform_data; |
| 150 | gpio_set_value(pdata->sensor_power_gpio, 0); | 186 | gpio_set_value(pdata->sensor_power_gpio, 0); |
| 151 | gpio_set_value(pdata->sensor_reset_gpio, 0); | 187 | gpio_set_value(pdata->sensor_reset_gpio, 0); |
| 188 | |||
| 189 | if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) { | ||
| 190 | if (cam->mipi_clk) | ||
| 191 | devm_clk_put(mcam->dev, cam->mipi_clk); | ||
| 192 | cam->mipi_clk = NULL; | ||
| 193 | } | ||
| 194 | |||
| 195 | mcam_clk_disable(mcam); | ||
| 152 | } | 196 | } |
| 153 | 197 | ||
| 198 | void mcam_ctlr_reset(struct mcam_camera *mcam) | ||
| 199 | { | ||
| 200 | unsigned long val; | ||
| 201 | struct mmp_camera *cam = mcam_to_cam(mcam); | ||
| 202 | |||
| 203 | if (mcam->ccic_id) { | ||
| 204 | /* | ||
| 205 | * Using CCIC2 | ||
| 206 | */ | ||
| 207 | val = ioread32(cam->power_regs + REG_CCIC2_CRCR); | ||
| 208 | iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR); | ||
| 209 | iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR); | ||
| 210 | } else { | ||
| 211 | /* | ||
| 212 | * Using CCIC1 | ||
| 213 | */ | ||
| 214 | val = ioread32(cam->power_regs + REG_CCIC_CRCR); | ||
| 215 | iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR); | ||
| 216 | iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /* | ||
| 221 | * calc the dphy register values | ||
| 222 | * There are three dphy registers being used. | ||
| 223 | * dphy[0] - CSI2_DPHY3 | ||
| 224 | * dphy[1] - CSI2_DPHY5 | ||
| 225 | * dphy[2] - CSI2_DPHY6 | ||
| 226 | * CSI2_DPHY3 and CSI2_DPHY6 can be set with a default value | ||
| 227 | * or be calculated dynamically | ||
| 228 | */ | ||
| 229 | void mmpcam_calc_dphy(struct mcam_camera *mcam) | ||
| 230 | { | ||
| 231 | struct mmp_camera *cam = mcam_to_cam(mcam); | ||
| 232 | struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data; | ||
| 233 | struct device *dev = &cam->pdev->dev; | ||
| 234 | unsigned long tx_clk_esc; | ||
| 235 | |||
| 236 | /* | ||
| 237 | * If CSI2_DPHY3 is calculated dynamically, | ||
| 238 | * pdata->lane_clk should be already set | ||
| 239 | * either in the board driver statically | ||
| 240 | * or in the sensor driver dynamically. | ||
| 241 | */ | ||
| 242 | /* | ||
| 243 | * dphy[0] - CSI2_DPHY3: | ||
| 244 | * bit 0 ~ bit 7: HS Term Enable. | ||
| 245 | * defines the time that the DPHY | ||
| 246 | * wait before enabling the data | ||
| 247 | * lane termination after detecting | ||
| 248 | * that the sensor has driven the data | ||
| 249 | * lanes to the LP00 bridge state. | ||
| 250 | * The value is calculated by: | ||
| 251 | * (Max T(D_TERM_EN)/Period(DDR)) - 1 | ||
| 252 | * bit 8 ~ bit 15: HS_SETTLE | ||
| 253 | * Time interval during which the HS | ||
| 254 | * receiver shall ignore any Data Lane | ||
| 255 | * HS transistions. | ||
| 256 | * The vaule has been calibrated on | ||
| 257 | * different boards. It seems to work well. | ||
| 258 | * | ||
| 259 | * More detail please refer | ||
| 260 | * MIPI Alliance Spectification for D-PHY | ||
| 261 | * document for explanation of HS-SETTLE | ||
| 262 | * and D-TERM-EN. | ||
| 263 | */ | ||
| 264 | switch (pdata->dphy3_algo) { | ||
| 265 | case DPHY3_ALGO_PXA910: | ||
| 266 | /* | ||
| 267 | * Calculate CSI2_DPHY3 algo for PXA910 | ||
| 268 | */ | ||
| 269 | pdata->dphy[0] = | ||
| 270 | (((1 + (pdata->lane_clk * 80) / 1000) & 0xff) << 8) | ||
| 271 | | (1 + pdata->lane_clk * 35 / 1000); | ||
| 272 | break; | ||
| 273 | case DPHY3_ALGO_PXA2128: | ||
| 274 | /* | ||
| 275 | * Calculate CSI2_DPHY3 algo for PXA2128 | ||
| 276 | */ | ||
| 277 | pdata->dphy[0] = | ||
| 278 | (((2 + (pdata->lane_clk * 110) / 1000) & 0xff) << 8) | ||
| 279 | | (1 + pdata->lane_clk * 35 / 1000); | ||
| 280 | break; | ||
| 281 | default: | ||
| 282 | /* | ||
| 283 | * Use default CSI2_DPHY3 value for PXA688/PXA988 | ||
| 284 | */ | ||
| 285 | dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n"); | ||
| 286 | } | ||
| 287 | |||
| 288 | /* | ||
| 289 | * mipi_clk will never be changed, it is a fixed value on MMP | ||
| 290 | */ | ||
| 291 | if (IS_ERR(cam->mipi_clk)) | ||
| 292 | return; | ||
| 293 | |||
| 294 | /* get the escape clk, this is hard coded */ | ||
| 295 | tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12; | ||
| 296 | |||
| 297 | /* | ||
| 298 | * dphy[2] - CSI2_DPHY6: | ||
| 299 | * bit 0 ~ bit 7: CK Term Enable | ||
| 300 | * Time for the Clock Lane receiver to enable the HS line | ||
| 301 | * termination. The value is calculated similarly with | ||
| 302 | * HS Term Enable | ||
| 303 | * bit 8 ~ bit 15: CK Settle | ||
| 304 | * Time interval during which the HS receiver shall ignore | ||
| 305 | * any Clock Lane HS transitions. | ||
| 306 | * The value is calibrated on the boards. | ||
| 307 | */ | ||
| 308 | pdata->dphy[2] = | ||
| 309 | ((((534 * tx_clk_esc) / 2000 - 1) & 0xff) << 8) | ||
| 310 | | (((38 * tx_clk_esc) / 1000 - 1) & 0xff); | ||
| 311 | |||
| 312 | dev_dbg(dev, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", | ||
| 313 | pdata->dphy[0], pdata->dphy[1], pdata->dphy[2]); | ||
| 314 | } | ||
| 154 | 315 | ||
| 155 | static irqreturn_t mmpcam_irq(int irq, void *data) | 316 | static irqreturn_t mmpcam_irq(int irq, void *data) |
| 156 | { | 317 | { |
| @@ -164,6 +325,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data) | |||
| 164 | return IRQ_RETVAL(handled); | 325 | return IRQ_RETVAL(handled); |
| 165 | } | 326 | } |
| 166 | 327 | ||
| 328 | static void mcam_deinit_clk(struct mcam_camera *mcam) | ||
| 329 | { | ||
| 330 | unsigned int i; | ||
| 331 | |||
| 332 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
| 333 | if (!IS_ERR(mcam->clk[i])) { | ||
| 334 | if (mcam->clk[i]) | ||
| 335 | devm_clk_put(mcam->dev, mcam->clk[i]); | ||
| 336 | } | ||
| 337 | mcam->clk[i] = NULL; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | static void mcam_init_clk(struct mcam_camera *mcam) | ||
| 342 | { | ||
| 343 | unsigned int i; | ||
| 344 | |||
| 345 | for (i = 0; i < NR_MCAM_CLK; i++) { | ||
| 346 | if (mcam_clks[i] != NULL) { | ||
| 347 | /* Some clks are not necessary on some boards | ||
| 348 | * We still try to run even it fails getting clk | ||
| 349 | */ | ||
| 350 | mcam->clk[i] = devm_clk_get(mcam->dev, mcam_clks[i]); | ||
| 351 | if (IS_ERR(mcam->clk[i])) | ||
| 352 | dev_warn(mcam->dev, "Could not get clk: %s\n", | ||
| 353 | mcam_clks[i]); | ||
| 354 | } | ||
| 355 | } | ||
| 356 | } | ||
| 167 | 357 | ||
| 168 | static int mmpcam_probe(struct platform_device *pdev) | 358 | static int mmpcam_probe(struct platform_device *pdev) |
| 169 | { | 359 | { |
| @@ -173,17 +363,32 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
| 173 | struct mmp_camera_platform_data *pdata; | 363 | struct mmp_camera_platform_data *pdata; |
| 174 | int ret; | 364 | int ret; |
| 175 | 365 | ||
| 176 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); | 366 | pdata = pdev->dev.platform_data; |
| 367 | if (!pdata) | ||
| 368 | return -ENODEV; | ||
| 369 | |||
| 370 | cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL); | ||
| 177 | if (cam == NULL) | 371 | if (cam == NULL) |
| 178 | return -ENOMEM; | 372 | return -ENOMEM; |
| 179 | cam->pdev = pdev; | 373 | cam->pdev = pdev; |
| 374 | cam->mipi_clk = NULL; | ||
| 180 | INIT_LIST_HEAD(&cam->devlist); | 375 | INIT_LIST_HEAD(&cam->devlist); |
| 181 | 376 | ||
| 182 | mcam = &cam->mcam; | 377 | mcam = &cam->mcam; |
| 183 | mcam->plat_power_up = mmpcam_power_up; | 378 | mcam->plat_power_up = mmpcam_power_up; |
| 184 | mcam->plat_power_down = mmpcam_power_down; | 379 | mcam->plat_power_down = mmpcam_power_down; |
| 380 | mcam->ctlr_reset = mcam_ctlr_reset; | ||
| 381 | mcam->calc_dphy = mmpcam_calc_dphy; | ||
| 185 | mcam->dev = &pdev->dev; | 382 | mcam->dev = &pdev->dev; |
| 186 | mcam->use_smbus = 0; | 383 | mcam->use_smbus = 0; |
| 384 | mcam->ccic_id = pdev->id; | ||
| 385 | mcam->mclk_min = pdata->mclk_min; | ||
| 386 | mcam->mclk_src = pdata->mclk_src; | ||
| 387 | mcam->mclk_div = pdata->mclk_div; | ||
| 388 | mcam->bus_type = pdata->bus_type; | ||
| 389 | mcam->dphy = pdata->dphy; | ||
| 390 | mcam->mipi_enabled = false; | ||
| 391 | mcam->lane = pdata->lane; | ||
| 187 | mcam->chip_id = MCAM_ARMADA610; | 392 | mcam->chip_id = MCAM_ARMADA610; |
| 188 | mcam->buffer_mode = B_DMA_sg; | 393 | mcam->buffer_mode = B_DMA_sg; |
| 189 | spin_lock_init(&mcam->dev_lock); | 394 | spin_lock_init(&mcam->dev_lock); |
| @@ -191,69 +396,58 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
| 191 | * Get our I/O memory. | 396 | * Get our I/O memory. |
| 192 | */ | 397 | */ |
| 193 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 398 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 194 | if (res == NULL) { | 399 | mcam->regs = devm_ioremap_resource(&pdev->dev, res); |
| 195 | dev_err(&pdev->dev, "no iomem resource!\n"); | 400 | if (IS_ERR(mcam->regs)) |
| 196 | ret = -ENODEV; | 401 | return PTR_ERR(mcam->regs); |
| 197 | goto out_free; | ||
| 198 | } | ||
| 199 | mcam->regs = ioremap(res->start, resource_size(res)); | ||
| 200 | if (mcam->regs == NULL) { | ||
| 201 | dev_err(&pdev->dev, "MMIO ioremap fail\n"); | ||
| 202 | ret = -ENODEV; | ||
| 203 | goto out_free; | ||
| 204 | } | ||
| 205 | mcam->regs_size = resource_size(res); | 402 | mcam->regs_size = resource_size(res); |
| 206 | /* | 403 | /* |
| 207 | * Power/clock memory is elsewhere; get it too. Perhaps this | 404 | * Power/clock memory is elsewhere; get it too. Perhaps this |
| 208 | * should really be managed outside of this driver? | 405 | * should really be managed outside of this driver? |
| 209 | */ | 406 | */ |
| 210 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 407 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| 211 | if (res == NULL) { | 408 | cam->power_regs = devm_ioremap_resource(&pdev->dev, res); |
| 212 | dev_err(&pdev->dev, "no power resource!\n"); | 409 | if (IS_ERR(cam->power_regs)) |
| 213 | ret = -ENODEV; | 410 | return PTR_ERR(cam->power_regs); |
| 214 | goto out_unmap1; | ||
| 215 | } | ||
| 216 | cam->power_regs = ioremap(res->start, resource_size(res)); | ||
| 217 | if (cam->power_regs == NULL) { | ||
| 218 | dev_err(&pdev->dev, "power MMIO ioremap fail\n"); | ||
| 219 | ret = -ENODEV; | ||
| 220 | goto out_unmap1; | ||
| 221 | } | ||
| 222 | /* | 411 | /* |
| 223 | * Find the i2c adapter. This assumes, of course, that the | 412 | * Find the i2c adapter. This assumes, of course, that the |
| 224 | * i2c bus is already up and functioning. | 413 | * i2c bus is already up and functioning. |
| 225 | */ | 414 | */ |
| 226 | pdata = pdev->dev.platform_data; | ||
| 227 | mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device); | 415 | mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device); |
| 228 | if (mcam->i2c_adapter == NULL) { | 416 | if (mcam->i2c_adapter == NULL) { |
| 229 | ret = -ENODEV; | ||
| 230 | dev_err(&pdev->dev, "No i2c adapter\n"); | 417 | dev_err(&pdev->dev, "No i2c adapter\n"); |
| 231 | goto out_unmap2; | 418 | return -ENODEV; |
| 232 | } | 419 | } |
| 233 | /* | 420 | /* |
| 234 | * Sensor GPIO pins. | 421 | * Sensor GPIO pins. |
| 235 | */ | 422 | */ |
| 236 | ret = gpio_request(pdata->sensor_power_gpio, "cam-power"); | 423 | ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio, |
| 424 | "cam-power"); | ||
| 237 | if (ret) { | 425 | if (ret) { |
| 238 | dev_err(&pdev->dev, "Can't get sensor power gpio %d", | 426 | dev_err(&pdev->dev, "Can't get sensor power gpio %d", |
| 239 | pdata->sensor_power_gpio); | 427 | pdata->sensor_power_gpio); |
| 240 | goto out_unmap2; | 428 | return ret; |
| 241 | } | 429 | } |
| 242 | gpio_direction_output(pdata->sensor_power_gpio, 0); | 430 | gpio_direction_output(pdata->sensor_power_gpio, 0); |
| 243 | ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset"); | 431 | ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio, |
| 432 | "cam-reset"); | ||
| 244 | if (ret) { | 433 | if (ret) { |
| 245 | dev_err(&pdev->dev, "Can't get sensor reset gpio %d", | 434 | dev_err(&pdev->dev, "Can't get sensor reset gpio %d", |
| 246 | pdata->sensor_reset_gpio); | 435 | pdata->sensor_reset_gpio); |
| 247 | goto out_gpio; | 436 | return ret; |
| 248 | } | 437 | } |
| 249 | gpio_direction_output(pdata->sensor_reset_gpio, 0); | 438 | gpio_direction_output(pdata->sensor_reset_gpio, 0); |
| 439 | |||
| 440 | mcam_init_clk(mcam); | ||
| 441 | |||
| 250 | /* | 442 | /* |
| 251 | * Power the device up and hand it off to the core. | 443 | * Power the device up and hand it off to the core. |
| 252 | */ | 444 | */ |
| 253 | mmpcam_power_up(mcam); | 445 | ret = mmpcam_power_up(mcam); |
| 446 | if (ret) | ||
| 447 | goto out_deinit_clk; | ||
| 254 | ret = mccic_register(mcam); | 448 | ret = mccic_register(mcam); |
| 255 | if (ret) | 449 | if (ret) |
| 256 | goto out_gpio2; | 450 | goto out_power_down; |
| 257 | /* | 451 | /* |
| 258 | * Finally, set up our IRQ now that the core is ready to | 452 | * Finally, set up our IRQ now that the core is ready to |
| 259 | * deal with it. | 453 | * deal with it. |
| @@ -264,8 +458,8 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
| 264 | goto out_unregister; | 458 | goto out_unregister; |
| 265 | } | 459 | } |
| 266 | cam->irq = res->start; | 460 | cam->irq = res->start; |
| 267 | ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED, | 461 | ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED, |
| 268 | "mmp-camera", mcam); | 462 | "mmp-camera", mcam); |
| 269 | if (ret == 0) { | 463 | if (ret == 0) { |
| 270 | mmpcam_add_device(cam); | 464 | mmpcam_add_device(cam); |
| 271 | return 0; | 465 | return 0; |
| @@ -273,17 +467,10 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
| 273 | 467 | ||
| 274 | out_unregister: | 468 | out_unregister: |
| 275 | mccic_shutdown(mcam); | 469 | mccic_shutdown(mcam); |
| 276 | out_gpio2: | 470 | out_power_down: |
| 277 | mmpcam_power_down(mcam); | 471 | mmpcam_power_down(mcam); |
| 278 | gpio_free(pdata->sensor_reset_gpio); | 472 | out_deinit_clk: |
| 279 | out_gpio: | 473 | mcam_deinit_clk(mcam); |
| 280 | gpio_free(pdata->sensor_power_gpio); | ||
| 281 | out_unmap2: | ||
| 282 | iounmap(cam->power_regs); | ||
| 283 | out_unmap1: | ||
| 284 | iounmap(mcam->regs); | ||
| 285 | out_free: | ||
| 286 | kfree(cam); | ||
| 287 | return ret; | 474 | return ret; |
| 288 | } | 475 | } |
| 289 | 476 | ||
| @@ -300,6 +487,7 @@ static int mmpcam_remove(struct mmp_camera *cam) | |||
| 300 | pdata = cam->pdev->dev.platform_data; | 487 | pdata = cam->pdev->dev.platform_data; |
| 301 | gpio_free(pdata->sensor_reset_gpio); | 488 | gpio_free(pdata->sensor_reset_gpio); |
| 302 | gpio_free(pdata->sensor_power_gpio); | 489 | gpio_free(pdata->sensor_power_gpio); |
| 490 | mcam_deinit_clk(mcam); | ||
| 303 | iounmap(cam->power_regs); | 491 | iounmap(cam->power_regs); |
| 304 | iounmap(mcam->regs); | 492 | iounmap(mcam->regs); |
| 305 | kfree(cam); | 493 | kfree(cam); |
diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c index a9e3b16460b8..ebf5b184cce4 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.c +++ b/drivers/media/platform/s3c-camif/camif-regs.c | |||
| @@ -106,15 +106,15 @@ static const u32 src_pixfmt_map[8][2] = { | |||
| 106 | void camif_hw_set_source_format(struct camif_dev *camif) | 106 | void camif_hw_set_source_format(struct camif_dev *camif) |
| 107 | { | 107 | { |
| 108 | struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt; | 108 | struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt; |
| 109 | unsigned int i = ARRAY_SIZE(src_pixfmt_map); | 109 | int i; |
| 110 | u32 cfg; | 110 | u32 cfg; |
| 111 | 111 | ||
| 112 | while (i-- >= 0) { | 112 | for (i = ARRAY_SIZE(src_pixfmt_map) - 1; i >= 0; i--) { |
| 113 | if (src_pixfmt_map[i][0] == mf->code) | 113 | if (src_pixfmt_map[i][0] == mf->code) |
| 114 | break; | 114 | break; |
| 115 | } | 115 | } |
| 116 | 116 | if (i < 0) { | |
| 117 | if (i == 0 && src_pixfmt_map[i][0] != mf->code) { | 117 | i = 0; |
| 118 | dev_err(camif->dev, | 118 | dev_err(camif->dev, |
| 119 | "Unsupported pixel code, falling back to %#08x\n", | 119 | "Unsupported pixel code, falling back to %#08x\n", |
| 120 | src_pixfmt_map[i][0]); | 120 | src_pixfmt_map[i][0]); |
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h index 363a97cc7681..2398cdf61341 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h | |||
| @@ -374,9 +374,9 @@ | |||
| 374 | #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 | 374 | #define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16 |
| 375 | 375 | ||
| 376 | /* Buffer size requirements defined by hardware */ | 376 | /* Buffer size requirements defined by hardware */ |
| 377 | #define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8) | 377 | #define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 3) * 8) |
| 378 | #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ | 378 | #define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \ |
| 379 | ((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \ | 379 | (((((imw + 127) / 64) * 16) * DIV_ROUND_UP(imh, 64) * 256) + \ |
| 380 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) | 380 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) |
| 381 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) | 381 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) |
| 382 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ | 382 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ |
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h new file mode 100644 index 000000000000..ea5ec2a711af --- /dev/null +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * Register definition file for Samsung MFC V7.x Interface (FIMV) driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
| 5 | * http://www.samsung.com/ | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _REGS_MFC_V7_H | ||
| 13 | #define _REGS_MFC_V7_H | ||
| 14 | |||
| 15 | #include "regs-mfc-v6.h" | ||
| 16 | |||
| 17 | /* Additional features of v7 */ | ||
| 18 | #define S5P_FIMV_CODEC_VP8_ENC_V7 25 | ||
| 19 | |||
| 20 | /* Additional registers for v7 */ | ||
| 21 | #define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7 0xf47c | ||
| 22 | |||
| 23 | #define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0 | ||
| 24 | #define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4 | ||
| 25 | #define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8 | ||
| 26 | #define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7 0xf9ec | ||
| 27 | #define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7 0xf9f0 | ||
| 28 | #define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7 0xf9f4 | ||
| 29 | |||
| 30 | #define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7 0xfa70 | ||
| 31 | #define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7 0xfa74 | ||
| 32 | |||
| 33 | #define S5P_FIMV_E_VP8_OPTIONS_V7 0xfdb0 | ||
| 34 | #define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7 0xfdb4 | ||
| 35 | #define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7 0xfdb8 | ||
| 36 | #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4 | ||
| 37 | |||
| 38 | /* MFCv7 variant defines */ | ||
| 39 | #define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */ | ||
| 40 | #define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */ | ||
| 41 | #define MFC_VERSION_V7 0x72 | ||
| 42 | #define MFC_NUM_PORTS_V7 1 | ||
| 43 | |||
| 44 | #define MFC_LUMA_PAD_BYTES_V7 256 | ||
| 45 | #define MFC_CHROMA_PAD_BYTES_V7 128 | ||
| 46 | |||
| 47 | /* MFCv7 Context buffer sizes */ | ||
| 48 | #define MFC_CTX_BUF_SIZE_V7 (30 * SZ_1K) /* 30KB */ | ||
| 49 | #define MFC_H264_DEC_CTX_BUF_SIZE_V7 (2 * SZ_1M) /* 2MB */ | ||
| 50 | #define MFC_OTHER_DEC_CTX_BUF_SIZE_V7 (20 * SZ_1K) /* 20KB */ | ||
| 51 | #define MFC_H264_ENC_CTX_BUF_SIZE_V7 (100 * SZ_1K) /* 100KB */ | ||
| 52 | #define MFC_OTHER_ENC_CTX_BUF_SIZE_V7 (10 * SZ_1K) /* 10KB */ | ||
| 53 | |||
| 54 | /* Buffer size defines */ | ||
| 55 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \ | ||
| 56 | (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216) | ||
| 57 | |||
| 58 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \ | ||
| 59 | (((w) * 48) + (((w) + 1) / 2 * 128) + 144 + 8192) | ||
| 60 | |||
| 61 | #endif /*_REGS_MFC_V7_H*/ | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index a130dcdb7206..084263dd126f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
| @@ -1391,6 +1391,32 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = { | |||
| 1391 | .fw_name = "s5p-mfc-v6.fw", | 1391 | .fw_name = "s5p-mfc-v6.fw", |
| 1392 | }; | 1392 | }; |
| 1393 | 1393 | ||
| 1394 | struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = { | ||
| 1395 | .dev_ctx = MFC_CTX_BUF_SIZE_V7, | ||
| 1396 | .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V7, | ||
| 1397 | .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V7, | ||
| 1398 | .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V7, | ||
| 1399 | .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V7, | ||
| 1400 | }; | ||
| 1401 | |||
| 1402 | struct s5p_mfc_buf_size buf_size_v7 = { | ||
| 1403 | .fw = MAX_FW_SIZE_V7, | ||
| 1404 | .cpb = MAX_CPB_SIZE_V7, | ||
| 1405 | .priv = &mfc_buf_size_v7, | ||
| 1406 | }; | ||
| 1407 | |||
| 1408 | struct s5p_mfc_buf_align mfc_buf_align_v7 = { | ||
| 1409 | .base = 0, | ||
| 1410 | }; | ||
| 1411 | |||
| 1412 | static struct s5p_mfc_variant mfc_drvdata_v7 = { | ||
| 1413 | .version = MFC_VERSION_V7, | ||
| 1414 | .port_num = MFC_NUM_PORTS_V7, | ||
| 1415 | .buf_size = &buf_size_v7, | ||
| 1416 | .buf_align = &mfc_buf_align_v7, | ||
| 1417 | .fw_name = "s5p-mfc-v7.fw", | ||
| 1418 | }; | ||
| 1419 | |||
| 1394 | static struct platform_device_id mfc_driver_ids[] = { | 1420 | static struct platform_device_id mfc_driver_ids[] = { |
| 1395 | { | 1421 | { |
| 1396 | .name = "s5p-mfc", | 1422 | .name = "s5p-mfc", |
| @@ -1401,6 +1427,9 @@ static struct platform_device_id mfc_driver_ids[] = { | |||
| 1401 | }, { | 1427 | }, { |
| 1402 | .name = "s5p-mfc-v6", | 1428 | .name = "s5p-mfc-v6", |
| 1403 | .driver_data = (unsigned long)&mfc_drvdata_v6, | 1429 | .driver_data = (unsigned long)&mfc_drvdata_v6, |
| 1430 | }, { | ||
| 1431 | .name = "s5p-mfc-v7", | ||
| 1432 | .driver_data = (unsigned long)&mfc_drvdata_v7, | ||
| 1404 | }, | 1433 | }, |
| 1405 | {}, | 1434 | {}, |
| 1406 | }; | 1435 | }; |
| @@ -1413,6 +1442,9 @@ static const struct of_device_id exynos_mfc_match[] = { | |||
| 1413 | }, { | 1442 | }, { |
| 1414 | .compatible = "samsung,mfc-v6", | 1443 | .compatible = "samsung,mfc-v6", |
| 1415 | .data = &mfc_drvdata_v6, | 1444 | .data = &mfc_drvdata_v6, |
| 1445 | }, { | ||
| 1446 | .compatible = "samsung,mfc-v7", | ||
| 1447 | .data = &mfc_drvdata_v7, | ||
| 1416 | }, | 1448 | }, |
| 1417 | {}, | 1449 | {}, |
| 1418 | }; | 1450 | }; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c index f0a41c95df84..242c033cf8bb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c | |||
| @@ -20,7 +20,7 @@ static struct s5p_mfc_hw_cmds *s5p_mfc_cmds; | |||
| 20 | 20 | ||
| 21 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) | 21 | void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) |
| 22 | { | 22 | { |
| 23 | if (IS_MFCV6(dev)) | 23 | if (IS_MFCV6_PLUS(dev)) |
| 24 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); | 24 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); |
| 25 | else | 25 | else |
| 26 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); | 26 | s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c index 5708fc3d9b4d..db796c8e7874 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c | |||
| @@ -108,6 +108,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx) | |||
| 108 | case S5P_MFC_CODEC_H263_ENC: | 108 | case S5P_MFC_CODEC_H263_ENC: |
| 109 | codec_type = S5P_FIMV_CODEC_H263_ENC_V6; | 109 | codec_type = S5P_FIMV_CODEC_H263_ENC_V6; |
| 110 | break; | 110 | break; |
| 111 | case S5P_MFC_CODEC_VP8_ENC: | ||
| 112 | codec_type = S5P_FIMV_CODEC_VP8_ENC_V7; | ||
| 113 | break; | ||
| 111 | default: | 114 | default: |
| 112 | codec_type = S5P_FIMV_CODEC_NONE_V6; | 115 | codec_type = S5P_FIMV_CODEC_NONE_V6; |
| 113 | }; | 116 | }; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index ef4074cd5316..6920b546181a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <media/videobuf2-core.h> | 24 | #include <media/videobuf2-core.h> |
| 25 | #include "regs-mfc.h" | 25 | #include "regs-mfc.h" |
| 26 | #include "regs-mfc-v6.h" | 26 | #include "regs-mfc-v6.h" |
| 27 | #include "regs-mfc-v7.h" | ||
| 27 | 28 | ||
| 28 | /* Definitions related to MFC memory */ | 29 | /* Definitions related to MFC memory */ |
| 29 | 30 | ||
| @@ -64,7 +65,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | |||
| 64 | #define MFC_ENC_CAP_PLANE_COUNT 1 | 65 | #define MFC_ENC_CAP_PLANE_COUNT 1 |
| 65 | #define MFC_ENC_OUT_PLANE_COUNT 2 | 66 | #define MFC_ENC_OUT_PLANE_COUNT 2 |
| 66 | #define STUFF_BYTE 4 | 67 | #define STUFF_BYTE 4 |
| 67 | #define MFC_MAX_CTRLS 70 | 68 | #define MFC_MAX_CTRLS 77 |
| 68 | 69 | ||
| 69 | #define S5P_MFC_CODEC_NONE -1 | 70 | #define S5P_MFC_CODEC_NONE -1 |
| 70 | #define S5P_MFC_CODEC_H264_DEC 0 | 71 | #define S5P_MFC_CODEC_H264_DEC 0 |
| @@ -80,6 +81,7 @@ static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) | |||
| 80 | #define S5P_MFC_CODEC_H264_MVC_ENC 21 | 81 | #define S5P_MFC_CODEC_H264_MVC_ENC 21 |
| 81 | #define S5P_MFC_CODEC_MPEG4_ENC 22 | 82 | #define S5P_MFC_CODEC_MPEG4_ENC 22 |
| 82 | #define S5P_MFC_CODEC_H263_ENC 23 | 83 | #define S5P_MFC_CODEC_H263_ENC 23 |
| 84 | #define S5P_MFC_CODEC_VP8_ENC 24 | ||
| 83 | 85 | ||
| 84 | #define S5P_MFC_R2H_CMD_EMPTY 0 | 86 | #define S5P_MFC_R2H_CMD_EMPTY 0 |
| 85 | #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 | 87 | #define S5P_MFC_R2H_CMD_SYS_INIT_RET 1 |
| @@ -408,6 +410,21 @@ struct s5p_mfc_mpeg4_enc_params { | |||
| 408 | }; | 410 | }; |
| 409 | 411 | ||
| 410 | /** | 412 | /** |
| 413 | * struct s5p_mfc_vp8_enc_params - encoding parameters for vp8 | ||
| 414 | */ | ||
| 415 | struct s5p_mfc_vp8_enc_params { | ||
| 416 | u8 imd_4x4; | ||
| 417 | enum v4l2_vp8_num_partitions num_partitions; | ||
| 418 | enum v4l2_vp8_num_ref_frames num_ref; | ||
| 419 | u8 filter_level; | ||
| 420 | u8 filter_sharpness; | ||
| 421 | u32 golden_frame_ref_period; | ||
| 422 | enum v4l2_vp8_golden_frame_sel golden_frame_sel; | ||
| 423 | u8 hier_layer; | ||
| 424 | u8 hier_layer_qp[3]; | ||
| 425 | }; | ||
| 426 | |||
| 427 | /** | ||
| 411 | * struct s5p_mfc_enc_params - general encoding parameters | 428 | * struct s5p_mfc_enc_params - general encoding parameters |
| 412 | */ | 429 | */ |
| 413 | struct s5p_mfc_enc_params { | 430 | struct s5p_mfc_enc_params { |
| @@ -441,6 +458,7 @@ struct s5p_mfc_enc_params { | |||
| 441 | struct { | 458 | struct { |
| 442 | struct s5p_mfc_h264_enc_params h264; | 459 | struct s5p_mfc_h264_enc_params h264; |
| 443 | struct s5p_mfc_mpeg4_enc_params mpeg4; | 460 | struct s5p_mfc_mpeg4_enc_params mpeg4; |
| 461 | struct s5p_mfc_vp8_enc_params vp8; | ||
| 444 | } codec; | 462 | } codec; |
| 445 | 463 | ||
| 446 | }; | 464 | }; |
| @@ -683,6 +701,7 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); | |||
| 683 | #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ | 701 | #define HAS_PORTNUM(dev) (dev ? (dev->variant ? \ |
| 684 | (dev->variant->port_num ? 1 : 0) : 0) : 0) | 702 | (dev->variant->port_num ? 1 : 0) : 0) : 0) |
| 685 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) | 703 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) |
| 686 | #define IS_MFCV6(dev) (dev->variant->version >= 0x60 ? 1 : 0) | 704 | #define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0) |
| 705 | #define IS_MFCV7(dev) (dev->variant->version >= 0x70 ? 1 : 0) | ||
| 687 | 706 | ||
| 688 | #endif /* S5P_MFC_COMMON_H_ */ | 707 | #endif /* S5P_MFC_COMMON_H_ */ |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index dc1fc94a488d..7cab6849fb5b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | |||
| @@ -164,7 +164,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) | |||
| 164 | 164 | ||
| 165 | mfc_debug_enter(); | 165 | mfc_debug_enter(); |
| 166 | 166 | ||
| 167 | if (IS_MFCV6(dev)) { | 167 | if (IS_MFCV6_PLUS(dev)) { |
| 168 | /* Reset IP */ | 168 | /* Reset IP */ |
| 169 | /* except RISC, reset */ | 169 | /* except RISC, reset */ |
| 170 | mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); | 170 | mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6); |
| @@ -213,7 +213,7 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) | |||
| 213 | 213 | ||
| 214 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) | 214 | static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) |
| 215 | { | 215 | { |
| 216 | if (IS_MFCV6(dev)) { | 216 | if (IS_MFCV6_PLUS(dev)) { |
| 217 | mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); | 217 | mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); |
| 218 | mfc_debug(2, "Base Address : %08x\n", dev->bank1); | 218 | mfc_debug(2, "Base Address : %08x\n", dev->bank1); |
| 219 | } else { | 219 | } else { |
| @@ -226,7 +226,7 @@ static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) | |||
| 226 | 226 | ||
| 227 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) | 227 | static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) |
| 228 | { | 228 | { |
| 229 | if (IS_MFCV6(dev)) { | 229 | if (IS_MFCV6_PLUS(dev)) { |
| 230 | /* Zero initialization should be done before RESET. | 230 | /* Zero initialization should be done before RESET. |
| 231 | * Nothing to do here. */ | 231 | * Nothing to do here. */ |
| 232 | } else { | 232 | } else { |
| @@ -264,7 +264,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
| 264 | s5p_mfc_clear_cmds(dev); | 264 | s5p_mfc_clear_cmds(dev); |
| 265 | /* 3. Release reset signal to the RISC */ | 265 | /* 3. Release reset signal to the RISC */ |
| 266 | s5p_mfc_clean_dev_int_flags(dev); | 266 | s5p_mfc_clean_dev_int_flags(dev); |
| 267 | if (IS_MFCV6(dev)) | 267 | if (IS_MFCV6_PLUS(dev)) |
| 268 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | 268 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); |
| 269 | else | 269 | else |
| 270 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 270 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); |
| @@ -301,7 +301,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) | |||
| 301 | s5p_mfc_clock_off(); | 301 | s5p_mfc_clock_off(); |
| 302 | return -EIO; | 302 | return -EIO; |
| 303 | } | 303 | } |
| 304 | if (IS_MFCV6(dev)) | 304 | if (IS_MFCV6_PLUS(dev)) |
| 305 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); | 305 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6); |
| 306 | else | 306 | else |
| 307 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); | 307 | ver = mfc_read(dev, S5P_FIMV_FW_VERSION); |
| @@ -380,7 +380,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) | |||
| 380 | return ret; | 380 | return ret; |
| 381 | } | 381 | } |
| 382 | /* 4. Release reset signal to the RISC */ | 382 | /* 4. Release reset signal to the RISC */ |
| 383 | if (IS_MFCV6(dev)) | 383 | if (IS_MFCV6_PLUS(dev)) |
| 384 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); | 384 | mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6); |
| 385 | else | 385 | else |
| 386 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); | 386 | mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 4f6dd42c9adb..8faf9691712d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | |||
| @@ -386,7 +386,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 386 | mfc_err("Unknown codec\n"); | 386 | mfc_err("Unknown codec\n"); |
| 387 | return -EINVAL; | 387 | return -EINVAL; |
| 388 | } | 388 | } |
| 389 | if (!IS_MFCV6(dev)) { | 389 | if (!IS_MFCV6_PLUS(dev)) { |
| 390 | if (fmt->fourcc == V4L2_PIX_FMT_VP8) { | 390 | if (fmt->fourcc == V4L2_PIX_FMT_VP8) { |
| 391 | mfc_err("Not supported format.\n"); | 391 | mfc_err("Not supported format.\n"); |
| 392 | return -EINVAL; | 392 | return -EINVAL; |
| @@ -398,10 +398,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 398 | mfc_err("Unsupported format for destination.\n"); | 398 | mfc_err("Unsupported format for destination.\n"); |
| 399 | return -EINVAL; | 399 | return -EINVAL; |
| 400 | } | 400 | } |
| 401 | if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | 401 | if (IS_MFCV6_PLUS(dev) && |
| 402 | (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | ||
| 402 | mfc_err("Not supported format.\n"); | 403 | mfc_err("Not supported format.\n"); |
| 403 | return -EINVAL; | 404 | return -EINVAL; |
| 404 | } else if (!IS_MFCV6(dev) && | 405 | } else if (!IS_MFCV6_PLUS(dev) && |
| 405 | (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | 406 | (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { |
| 406 | mfc_err("Not supported format.\n"); | 407 | mfc_err("Not supported format.\n"); |
| 407 | return -EINVAL; | 408 | return -EINVAL; |
| @@ -925,7 +926,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
| 925 | psize[0] = ctx->luma_size; | 926 | psize[0] = ctx->luma_size; |
| 926 | psize[1] = ctx->chroma_size; | 927 | psize[1] = ctx->chroma_size; |
| 927 | 928 | ||
| 928 | if (IS_MFCV6(dev)) | 929 | if (IS_MFCV6_PLUS(dev)) |
| 929 | allocators[0] = | 930 | allocators[0] = |
| 930 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | 931 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
| 931 | else | 932 | else |
| @@ -1050,7 +1051,7 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |||
| 1050 | ctx->dpb_flush_flag = 1; | 1051 | ctx->dpb_flush_flag = 1; |
| 1051 | ctx->dec_dst_flag = 0; | 1052 | ctx->dec_dst_flag = 0; |
| 1052 | spin_unlock_irqrestore(&dev->irqlock, flags); | 1053 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 1053 | if (IS_MFCV6(dev) && (ctx->state == MFCINST_RUNNING)) { | 1054 | if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { |
| 1054 | ctx->state = MFCINST_FLUSH; | 1055 | ctx->state = MFCINST_FLUSH; |
| 1055 | set_work_bit_irqsave(ctx); | 1056 | set_work_bit_irqsave(ctx); |
| 1056 | s5p_mfc_clean_ctx_int_flags(ctx); | 1057 | s5p_mfc_clean_ctx_int_flags(ctx); |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 59e56f4c8ce3..41f5a3c10dbd 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
| @@ -84,6 +84,13 @@ static struct s5p_mfc_fmt formats[] = { | |||
| 84 | .type = MFC_FMT_ENC, | 84 | .type = MFC_FMT_ENC, |
| 85 | .num_planes = 1, | 85 | .num_planes = 1, |
| 86 | }, | 86 | }, |
| 87 | { | ||
| 88 | .name = "VP8 Encoded Stream", | ||
| 89 | .fourcc = V4L2_PIX_FMT_VP8, | ||
| 90 | .codec_mode = S5P_MFC_CODEC_VP8_ENC, | ||
| 91 | .type = MFC_FMT_ENC, | ||
| 92 | .num_planes = 1, | ||
| 93 | }, | ||
| 87 | }; | 94 | }; |
| 88 | 95 | ||
| 89 | #define NUM_FORMATS ARRAY_SIZE(formats) | 96 | #define NUM_FORMATS ARRAY_SIZE(formats) |
| @@ -557,6 +564,60 @@ static struct mfc_control controls[] = { | |||
| 557 | .step = 1, | 564 | .step = 1, |
| 558 | .default_value = 0, | 565 | .default_value = 0, |
| 559 | }, | 566 | }, |
| 567 | { | ||
| 568 | .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS, | ||
| 569 | .type = V4L2_CTRL_TYPE_INTEGER_MENU, | ||
| 570 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS, | ||
| 571 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION, | ||
| 572 | .menu_skip_mask = 0, | ||
| 573 | }, | ||
| 574 | { | ||
| 575 | .id = V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4, | ||
| 576 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 577 | .minimum = 0, | ||
| 578 | .maximum = 1, | ||
| 579 | .step = 1, | ||
| 580 | .default_value = 0, | ||
| 581 | }, | ||
| 582 | { | ||
| 583 | .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES, | ||
| 584 | .type = V4L2_CTRL_TYPE_INTEGER_MENU, | ||
| 585 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME, | ||
| 586 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME, | ||
| 587 | .menu_skip_mask = 0, | ||
| 588 | }, | ||
| 589 | { | ||
| 590 | .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL, | ||
| 591 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 592 | .minimum = 0, | ||
| 593 | .maximum = 63, | ||
| 594 | .step = 1, | ||
| 595 | .default_value = 0, | ||
| 596 | }, | ||
| 597 | { | ||
| 598 | .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS, | ||
| 599 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 600 | .minimum = 0, | ||
| 601 | .maximum = 7, | ||
| 602 | .step = 1, | ||
| 603 | .default_value = 0, | ||
| 604 | }, | ||
| 605 | { | ||
| 606 | .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD, | ||
| 607 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 608 | .minimum = 0, | ||
| 609 | .maximum = (1 << 16) - 1, | ||
| 610 | .step = 1, | ||
| 611 | .default_value = 0, | ||
| 612 | }, | ||
| 613 | { | ||
| 614 | .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL, | ||
| 615 | .type = V4L2_CTRL_TYPE_MENU, | ||
| 616 | .minimum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, | ||
| 617 | .maximum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD, | ||
| 618 | .default_value = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV, | ||
| 619 | .menu_skip_mask = 0, | ||
| 620 | }, | ||
| 560 | }; | 621 | }; |
| 561 | 622 | ||
| 562 | #define NUM_CTRLS ARRAY_SIZE(controls) | 623 | #define NUM_CTRLS ARRAY_SIZE(controls) |
| @@ -663,7 +724,7 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) | |||
| 663 | spin_unlock_irqrestore(&dev->irqlock, flags); | 724 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 664 | } | 725 | } |
| 665 | 726 | ||
| 666 | if (!IS_MFCV6(dev)) { | 727 | if (!IS_MFCV6_PLUS(dev)) { |
| 667 | ctx->state = MFCINST_RUNNING; | 728 | ctx->state = MFCINST_RUNNING; |
| 668 | if (s5p_mfc_ctx_ready(ctx)) | 729 | if (s5p_mfc_ctx_ready(ctx)) |
| 669 | set_work_bit_irqsave(ctx); | 730 | set_work_bit_irqsave(ctx); |
| @@ -917,6 +978,11 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 917 | return -EINVAL; | 978 | return -EINVAL; |
| 918 | } | 979 | } |
| 919 | 980 | ||
| 981 | if (!IS_MFCV7(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | ||
| 982 | mfc_err("VP8 is supported only in MFC v7\n"); | ||
| 983 | return -EINVAL; | ||
| 984 | } | ||
| 985 | |||
| 920 | if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { | 986 | if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { |
| 921 | mfc_err("must be set encoding output size\n"); | 987 | mfc_err("must be set encoding output size\n"); |
| 922 | return -EINVAL; | 988 | return -EINVAL; |
| @@ -931,12 +997,12 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
| 931 | return -EINVAL; | 997 | return -EINVAL; |
| 932 | } | 998 | } |
| 933 | 999 | ||
| 934 | if (!IS_MFCV6(dev)) { | 1000 | if (!IS_MFCV6_PLUS(dev)) { |
| 935 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { | 1001 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { |
| 936 | mfc_err("Not supported format.\n"); | 1002 | mfc_err("Not supported format.\n"); |
| 937 | return -EINVAL; | 1003 | return -EINVAL; |
| 938 | } | 1004 | } |
| 939 | } else if (IS_MFCV6(dev)) { | 1005 | } else if (IS_MFCV6_PLUS(dev)) { |
| 940 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | 1006 | if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { |
| 941 | mfc_err("Not supported format.\n"); | 1007 | mfc_err("Not supported format.\n"); |
| 942 | return -EINVAL; | 1008 | return -EINVAL; |
| @@ -1060,7 +1126,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
| 1060 | return -EINVAL; | 1126 | return -EINVAL; |
| 1061 | } | 1127 | } |
| 1062 | 1128 | ||
| 1063 | if (IS_MFCV6(dev)) { | 1129 | if (IS_MFCV6_PLUS(dev)) { |
| 1064 | /* Check for min encoder buffers */ | 1130 | /* Check for min encoder buffers */ |
| 1065 | if (ctx->pb_count && | 1131 | if (ctx->pb_count && |
| 1066 | (reqbufs->count < ctx->pb_count)) { | 1132 | (reqbufs->count < ctx->pb_count)) { |
| @@ -1341,7 +1407,7 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
| 1341 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; | 1407 | S5P_FIMV_ENC_PROFILE_H264_BASELINE; |
| 1342 | break; | 1408 | break; |
| 1343 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: | 1409 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: |
| 1344 | if (IS_MFCV6(dev)) | 1410 | if (IS_MFCV6_PLUS(dev)) |
| 1345 | p->codec.h264.profile = | 1411 | p->codec.h264.profile = |
| 1346 | S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; | 1412 | S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE; |
| 1347 | else | 1413 | else |
| @@ -1470,6 +1536,27 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
| 1470 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: | 1536 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: |
| 1471 | p->codec.mpeg4.quarter_pixel = ctrl->val; | 1537 | p->codec.mpeg4.quarter_pixel = ctrl->val; |
| 1472 | break; | 1538 | break; |
| 1539 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
| 1540 | p->codec.vp8.num_partitions = ctrl->val; | ||
| 1541 | break; | ||
| 1542 | case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: | ||
| 1543 | p->codec.vp8.imd_4x4 = ctrl->val; | ||
| 1544 | break; | ||
| 1545 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
| 1546 | p->codec.vp8.num_ref = ctrl->val; | ||
| 1547 | break; | ||
| 1548 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: | ||
| 1549 | p->codec.vp8.filter_level = ctrl->val; | ||
| 1550 | break; | ||
| 1551 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: | ||
| 1552 | p->codec.vp8.filter_sharpness = ctrl->val; | ||
| 1553 | break; | ||
| 1554 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: | ||
| 1555 | p->codec.vp8.golden_frame_ref_period = ctrl->val; | ||
| 1556 | break; | ||
| 1557 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
| 1558 | p->codec.vp8.golden_frame_sel = ctrl->val; | ||
| 1559 | break; | ||
| 1473 | default: | 1560 | default: |
| 1474 | v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n", | 1561 | v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n", |
| 1475 | ctrl->id, ctrl->val); | 1562 | ctrl->id, ctrl->val); |
| @@ -1650,9 +1737,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, | |||
| 1650 | *buf_count = 1; | 1737 | *buf_count = 1; |
| 1651 | if (*buf_count > MFC_MAX_BUFFERS) | 1738 | if (*buf_count > MFC_MAX_BUFFERS) |
| 1652 | *buf_count = MFC_MAX_BUFFERS; | 1739 | *buf_count = MFC_MAX_BUFFERS; |
| 1740 | |||
| 1653 | psize[0] = ctx->luma_size; | 1741 | psize[0] = ctx->luma_size; |
| 1654 | psize[1] = ctx->chroma_size; | 1742 | psize[1] = ctx->chroma_size; |
| 1655 | if (IS_MFCV6(dev)) { | 1743 | |
| 1744 | if (IS_MFCV6_PLUS(dev)) { | ||
| 1656 | allocators[0] = | 1745 | allocators[0] = |
| 1657 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | 1746 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
| 1658 | allocators[1] = | 1747 | allocators[1] = |
| @@ -1761,7 +1850,8 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) | |||
| 1761 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | 1850 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); |
| 1762 | struct s5p_mfc_dev *dev = ctx->dev; | 1851 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1763 | 1852 | ||
| 1764 | if (IS_MFCV6(dev) && (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { | 1853 | if (IS_MFCV6_PLUS(dev) && |
| 1854 | (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { | ||
| 1765 | 1855 | ||
| 1766 | if ((ctx->state == MFCINST_GOT_INST) && | 1856 | if ((ctx->state == MFCINST_GOT_INST) && |
| 1767 | (dev->curr_ctx == ctx->num) && dev->hw_lock) { | 1857 | (dev->curr_ctx == ctx->num) && dev->hw_lock) { |
| @@ -1915,7 +2005,9 @@ int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx) | |||
| 1915 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, | 2005 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, |
| 1916 | &cfg, NULL); | 2006 | &cfg, NULL); |
| 1917 | } else { | 2007 | } else { |
| 1918 | if (controls[i].type == V4L2_CTRL_TYPE_MENU) { | 2008 | if ((controls[i].type == V4L2_CTRL_TYPE_MENU) || |
| 2009 | (controls[i].type == | ||
| 2010 | V4L2_CTRL_TYPE_INTEGER_MENU)) { | ||
| 1919 | ctx->ctrls[i] = v4l2_ctrl_new_std_menu( | 2011 | ctx->ctrls[i] = v4l2_ctrl_new_std_menu( |
| 1920 | &ctx->ctrl_handler, | 2012 | &ctx->ctrl_handler, |
| 1921 | &s5p_mfc_enc_ctrl_ops, controls[i].id, | 2013 | &s5p_mfc_enc_ctrl_ops, controls[i].id, |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 10f8ac37cecd..3c01c339d696 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | |||
| @@ -21,7 +21,7 @@ static struct s5p_mfc_hw_ops *s5p_mfc_ops; | |||
| 21 | 21 | ||
| 22 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) | 22 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) |
| 23 | { | 23 | { |
| 24 | if (IS_MFCV6(dev)) { | 24 | if (IS_MFCV6_PLUS(dev)) { |
| 25 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); | 25 | s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); |
| 26 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; | 26 | dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; |
| 27 | } else { | 27 | } else { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 66f0d042357f..461358c4a790 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | |||
| @@ -80,6 +80,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 80 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | 80 | ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * |
| 81 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), | 81 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), |
| 82 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); | 82 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); |
| 83 | |||
| 83 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * | 84 | ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * |
| 84 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, | 85 | S5P_FIMV_LUMA_MB_TO_PIXEL_V6, |
| 85 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); | 86 | S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6); |
| @@ -112,10 +113,18 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 112 | (ctx->mv_count * ctx->mv_size); | 113 | (ctx->mv_count * ctx->mv_size); |
| 113 | break; | 114 | break; |
| 114 | case S5P_MFC_CODEC_MPEG4_DEC: | 115 | case S5P_MFC_CODEC_MPEG4_DEC: |
| 115 | ctx->scratch_buf_size = | 116 | if (IS_MFCV7(dev)) { |
| 116 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | 117 | ctx->scratch_buf_size = |
| 117 | mb_width, | 118 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7( |
| 118 | mb_height); | 119 | mb_width, |
| 120 | mb_height); | ||
| 121 | } else { | ||
| 122 | ctx->scratch_buf_size = | ||
| 123 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6( | ||
| 124 | mb_width, | ||
| 125 | mb_height); | ||
| 126 | } | ||
| 127 | |||
| 119 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | 128 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
| 120 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | 129 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 121 | ctx->bank1.size = ctx->scratch_buf_size; | 130 | ctx->bank1.size = ctx->scratch_buf_size; |
| @@ -179,6 +188,19 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) | |||
| 179 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | 188 | ctx->chroma_dpb_size + ctx->me_buffer_size)); |
| 180 | ctx->bank2.size = 0; | 189 | ctx->bank2.size = 0; |
| 181 | break; | 190 | break; |
| 191 | case S5P_MFC_CODEC_VP8_ENC: | ||
| 192 | ctx->scratch_buf_size = | ||
| 193 | S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( | ||
| 194 | mb_width, | ||
| 195 | mb_height); | ||
| 196 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, | ||
| 197 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); | ||
| 198 | ctx->bank1.size = | ||
| 199 | ctx->scratch_buf_size + ctx->tmv_buffer_size + | ||
| 200 | (ctx->pb_count * (ctx->luma_dpb_size + | ||
| 201 | ctx->chroma_dpb_size + ctx->me_buffer_size)); | ||
| 202 | ctx->bank2.size = 0; | ||
| 203 | break; | ||
| 182 | default: | 204 | default: |
| 183 | break; | 205 | break; |
| 184 | } | 206 | } |
| @@ -228,6 +250,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) | |||
| 228 | break; | 250 | break; |
| 229 | case S5P_MFC_CODEC_MPEG4_ENC: | 251 | case S5P_MFC_CODEC_MPEG4_ENC: |
| 230 | case S5P_MFC_CODEC_H263_ENC: | 252 | case S5P_MFC_CODEC_H263_ENC: |
| 253 | case S5P_MFC_CODEC_VP8_ENC: | ||
| 231 | ctx->ctx.size = buf_size->other_enc_ctx; | 254 | ctx->ctx.size = buf_size->other_enc_ctx; |
| 232 | break; | 255 | break; |
| 233 | default: | 256 | default: |
| @@ -329,6 +352,12 @@ static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) | |||
| 329 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); | 352 | ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6); |
| 330 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); | 353 | ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256); |
| 331 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); | 354 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); |
| 355 | |||
| 356 | /* MFCv7 needs pad bytes for Luma and Chroma */ | ||
| 357 | if (IS_MFCV7(ctx->dev)) { | ||
| 358 | ctx->luma_size += MFC_LUMA_PAD_BYTES_V7; | ||
| 359 | ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7; | ||
| 360 | } | ||
| 332 | } | 361 | } |
| 333 | 362 | ||
| 334 | /* Set registers for decoding stream buffer */ | 363 | /* Set registers for decoding stream buffer */ |
| @@ -453,8 +482,13 @@ static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
| 453 | { | 482 | { |
| 454 | struct s5p_mfc_dev *dev = ctx->dev; | 483 | struct s5p_mfc_dev *dev = ctx->dev; |
| 455 | 484 | ||
| 456 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); /* 256B align */ | 485 | if (IS_MFCV7(dev)) { |
| 457 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | 486 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); |
| 487 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); | ||
| 488 | } else { | ||
| 489 | WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); | ||
| 490 | WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | ||
| 491 | } | ||
| 458 | 492 | ||
| 459 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); | 493 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); |
| 460 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); | 494 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); |
| @@ -466,8 +500,13 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, | |||
| 466 | struct s5p_mfc_dev *dev = ctx->dev; | 500 | struct s5p_mfc_dev *dev = ctx->dev; |
| 467 | unsigned long enc_recon_y_addr, enc_recon_c_addr; | 501 | unsigned long enc_recon_y_addr, enc_recon_c_addr; |
| 468 | 502 | ||
| 469 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | 503 | if (IS_MFCV7(dev)) { |
| 470 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | 504 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); |
| 505 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); | ||
| 506 | } else { | ||
| 507 | *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | ||
| 508 | *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | ||
| 509 | } | ||
| 471 | 510 | ||
| 472 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | 511 | enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); |
| 473 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | 512 | enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); |
| @@ -1140,6 +1179,80 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) | |||
| 1140 | return 0; | 1179 | return 0; |
| 1141 | } | 1180 | } |
| 1142 | 1181 | ||
| 1182 | static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) | ||
| 1183 | { | ||
| 1184 | struct s5p_mfc_dev *dev = ctx->dev; | ||
| 1185 | struct s5p_mfc_enc_params *p = &ctx->enc_params; | ||
| 1186 | struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8; | ||
| 1187 | unsigned int reg = 0; | ||
| 1188 | unsigned int val = 0; | ||
| 1189 | |||
| 1190 | mfc_debug_enter(); | ||
| 1191 | |||
| 1192 | s5p_mfc_set_enc_params(ctx); | ||
| 1193 | |||
| 1194 | /* pictype : number of B */ | ||
| 1195 | reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | ||
| 1196 | reg &= ~(0x3 << 16); | ||
| 1197 | reg |= ((p->num_b_frame & 0x3) << 16); | ||
| 1198 | WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | ||
| 1199 | |||
| 1200 | /* profile & level */ | ||
| 1201 | reg = 0; | ||
| 1202 | /** profile */ | ||
| 1203 | reg |= (0x1 << 4); | ||
| 1204 | WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | ||
| 1205 | |||
| 1206 | /* rate control config. */ | ||
| 1207 | reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | ||
| 1208 | /** macroblock level rate control */ | ||
| 1209 | reg &= ~(0x1 << 8); | ||
| 1210 | reg |= ((p->rc_mb & 0x1) << 8); | ||
| 1211 | WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | ||
| 1212 | |||
| 1213 | /* frame rate */ | ||
| 1214 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { | ||
| 1215 | reg = 0; | ||
| 1216 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); | ||
| 1217 | reg |= p->rc_framerate_denom & 0xFFFF; | ||
| 1218 | WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* vbv buffer size */ | ||
| 1222 | if (p->frame_skip_mode == | ||
| 1223 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { | ||
| 1224 | WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | ||
| 1225 | |||
| 1226 | if (p->rc_frame) | ||
| 1227 | WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /* VP8 specific params */ | ||
| 1231 | reg = 0; | ||
| 1232 | reg |= (p_vp8->imd_4x4 & 0x1) << 10; | ||
| 1233 | switch (p_vp8->num_partitions) { | ||
| 1234 | case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION: | ||
| 1235 | val = 0; | ||
| 1236 | break; | ||
| 1237 | case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS: | ||
| 1238 | val = 2; | ||
| 1239 | break; | ||
| 1240 | case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS: | ||
| 1241 | val = 4; | ||
| 1242 | break; | ||
| 1243 | case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS: | ||
| 1244 | val = 8; | ||
| 1245 | break; | ||
| 1246 | } | ||
| 1247 | reg |= (val & 0xF) << 3; | ||
| 1248 | reg |= (p_vp8->num_ref & 0x2); | ||
| 1249 | WRITEL(reg, S5P_FIMV_E_VP8_OPTIONS_V7); | ||
| 1250 | |||
| 1251 | mfc_debug_leave(); | ||
| 1252 | |||
| 1253 | return 0; | ||
| 1254 | } | ||
| 1255 | |||
| 1143 | /* Initialize decoding */ | 1256 | /* Initialize decoding */ |
| 1144 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | 1257 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) |
| 1145 | { | 1258 | { |
| @@ -1166,6 +1279,12 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
| 1166 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); | 1279 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); |
| 1167 | WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | 1280 | WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); |
| 1168 | } | 1281 | } |
| 1282 | |||
| 1283 | if (IS_MFCV7(dev)) { | ||
| 1284 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | ||
| 1285 | reg = 0; | ||
| 1286 | } | ||
| 1287 | |||
| 1169 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ | 1288 | /* Setup loop filter, for decoding this is only valid for MPEG4 */ |
| 1170 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { | 1289 | if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) { |
| 1171 | mfc_debug(2, "Set loop filter to: %d\n", | 1290 | mfc_debug(2, "Set loop filter to: %d\n", |
| @@ -1176,7 +1295,10 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
| 1176 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) | 1295 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) |
| 1177 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); | 1296 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); |
| 1178 | 1297 | ||
| 1179 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | 1298 | if (IS_MFCV7(dev)) |
| 1299 | WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7); | ||
| 1300 | else | ||
| 1301 | WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | ||
| 1180 | 1302 | ||
| 1181 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ | 1303 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
| 1182 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) | 1304 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) |
| @@ -1184,6 +1306,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) | |||
| 1184 | else | 1306 | else |
| 1185 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | 1307 | WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); |
| 1186 | 1308 | ||
| 1309 | |||
| 1187 | /* sei parse */ | 1310 | /* sei parse */ |
| 1188 | WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); | 1311 | WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); |
| 1189 | 1312 | ||
| @@ -1248,12 +1371,20 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) | |||
| 1248 | s5p_mfc_set_enc_params_mpeg4(ctx); | 1371 | s5p_mfc_set_enc_params_mpeg4(ctx); |
| 1249 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) | 1372 | else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC) |
| 1250 | s5p_mfc_set_enc_params_h263(ctx); | 1373 | s5p_mfc_set_enc_params_h263(ctx); |
| 1374 | else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC) | ||
| 1375 | s5p_mfc_set_enc_params_vp8(ctx); | ||
| 1251 | else { | 1376 | else { |
| 1252 | mfc_err("Unknown codec for encoding (%x).\n", | 1377 | mfc_err("Unknown codec for encoding (%x).\n", |
| 1253 | ctx->codec_mode); | 1378 | ctx->codec_mode); |
| 1254 | return -EINVAL; | 1379 | return -EINVAL; |
| 1255 | } | 1380 | } |
| 1256 | 1381 | ||
| 1382 | /* Set stride lengths */ | ||
| 1383 | if (IS_MFCV7(dev)) { | ||
| 1384 | WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); | ||
| 1385 | WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); | ||
| 1386 | } | ||
| 1387 | |||
| 1257 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | 1388 | WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); |
| 1258 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, | 1389 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 1259 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); | 1390 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); |
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 1b34c3629858..534722c04ec5 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
| 38 | #include <media/v4l2-dev.h> | 38 | #include <media/v4l2-dev.h> |
| 39 | #include <media/v4l2-device.h> | 39 | #include <media/v4l2-device.h> |
| 40 | #include <media/v4l2-dv-timings.h> | ||
| 40 | 41 | ||
| 41 | #include "regs-hdmi.h" | 42 | #include "regs-hdmi.h" |
| 42 | 43 | ||
| @@ -625,7 +626,7 @@ static int hdmi_s_dv_timings(struct v4l2_subdev *sd, | |||
| 625 | int i; | 626 | int i; |
| 626 | 627 | ||
| 627 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) | 628 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) |
| 628 | if (v4l_match_dv_timings(&hdmi_timings[i].dv_timings, | 629 | if (v4l2_match_dv_timings(&hdmi_timings[i].dv_timings, |
| 629 | timings, 0)) | 630 | timings, 0)) |
| 630 | break; | 631 | break; |
| 631 | if (i == ARRAY_SIZE(hdmi_timings)) { | 632 | if (i == ARRAY_SIZE(hdmi_timings)) { |
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 626dcccc37da..af39c4665554 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig | |||
| @@ -44,6 +44,14 @@ config VIDEO_PXA27x | |||
| 44 | ---help--- | 44 | ---help--- |
| 45 | This is a v4l2 driver for the PXA27x Quick Capture Interface | 45 | This is a v4l2 driver for the PXA27x Quick Capture Interface |
| 46 | 46 | ||
| 47 | config VIDEO_RCAR_VIN | ||
| 48 | tristate "R-Car Video Input (VIN) support" | ||
| 49 | depends on VIDEO_DEV && SOC_CAMERA | ||
| 50 | select VIDEOBUF2_DMA_CONTIG | ||
| 51 | select SOC_CAMERA_SCALE_CROP | ||
| 52 | ---help--- | ||
| 53 | This is a v4l2 driver for the R-Car VIN Interface | ||
| 54 | |||
| 47 | config VIDEO_SH_MOBILE_CSI2 | 55 | config VIDEO_SH_MOBILE_CSI2 |
| 48 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" | 56 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" |
| 49 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK | 57 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK |
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 39186224c16a..8aed26d7a64d 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile | |||
| @@ -14,3 +14,4 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | |||
| 14 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | 14 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o |
| 15 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 15 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
| 16 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o | 16 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o |
| 17 | obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar_vin.o | ||
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 1047e3e8db77..8f9f6211c52e 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c | |||
| @@ -672,7 +672,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
| 672 | fmt = soc_mbus_get_fmtdesc(code); | 672 | fmt = soc_mbus_get_fmtdesc(code); |
| 673 | if (!fmt) { | 673 | if (!fmt) { |
| 674 | dev_warn(icd->parent, | 674 | dev_warn(icd->parent, |
| 675 | "Unsupported format code #%u: %d\n", idx, code); | 675 | "Unsupported format code #%u: 0x%x\n", idx, code); |
| 676 | return 0; | 676 | return 0; |
| 677 | } | 677 | } |
| 678 | 678 | ||
| @@ -688,7 +688,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
| 688 | xlate->host_fmt = &mx3_camera_formats[0]; | 688 | xlate->host_fmt = &mx3_camera_formats[0]; |
| 689 | xlate->code = code; | 689 | xlate->code = code; |
| 690 | xlate++; | 690 | xlate++; |
| 691 | dev_dbg(dev, "Providing format %s using code %d\n", | 691 | dev_dbg(dev, "Providing format %s using code 0x%x\n", |
| 692 | mx3_camera_formats[0].name, code); | 692 | mx3_camera_formats[0].name, code); |
| 693 | } | 693 | } |
| 694 | break; | 694 | break; |
| @@ -698,7 +698,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
| 698 | xlate->host_fmt = &mx3_camera_formats[1]; | 698 | xlate->host_fmt = &mx3_camera_formats[1]; |
| 699 | xlate->code = code; | 699 | xlate->code = code; |
| 700 | xlate++; | 700 | xlate++; |
| 701 | dev_dbg(dev, "Providing format %s using code %d\n", | 701 | dev_dbg(dev, "Providing format %s using code 0x%x\n", |
| 702 | mx3_camera_formats[1].name, code); | 702 | mx3_camera_formats[1].name, code); |
| 703 | } | 703 | } |
| 704 | break; | 704 | break; |
| @@ -1144,6 +1144,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { | |||
| 1144 | 1144 | ||
| 1145 | static int mx3_camera_probe(struct platform_device *pdev) | 1145 | static int mx3_camera_probe(struct platform_device *pdev) |
| 1146 | { | 1146 | { |
| 1147 | struct mx3_camera_pdata *pdata = pdev->dev.platform_data; | ||
| 1147 | struct mx3_camera_dev *mx3_cam; | 1148 | struct mx3_camera_dev *mx3_cam; |
| 1148 | struct resource *res; | 1149 | struct resource *res; |
| 1149 | void __iomem *base; | 1150 | void __iomem *base; |
| @@ -1151,26 +1152,25 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
| 1151 | struct soc_camera_host *soc_host; | 1152 | struct soc_camera_host *soc_host; |
| 1152 | 1153 | ||
| 1153 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1154 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1154 | if (!res) { | 1155 | base = devm_ioremap_resource(&pdev->dev, res); |
| 1155 | err = -ENODEV; | 1156 | if (IS_ERR(base)) |
| 1156 | goto egetres; | 1157 | return PTR_ERR(base); |
| 1157 | } | 1158 | |
| 1159 | if (!pdata) | ||
| 1160 | return -EINVAL; | ||
| 1158 | 1161 | ||
| 1159 | mx3_cam = vzalloc(sizeof(*mx3_cam)); | 1162 | mx3_cam = devm_kzalloc(&pdev->dev, sizeof(*mx3_cam), GFP_KERNEL); |
| 1160 | if (!mx3_cam) { | 1163 | if (!mx3_cam) { |
| 1161 | dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); | 1164 | dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); |
| 1162 | err = -ENOMEM; | 1165 | return -ENOMEM; |
| 1163 | goto ealloc; | ||
| 1164 | } | 1166 | } |
| 1165 | 1167 | ||
| 1166 | mx3_cam->clk = clk_get(&pdev->dev, NULL); | 1168 | mx3_cam->clk = devm_clk_get(&pdev->dev, NULL); |
| 1167 | if (IS_ERR(mx3_cam->clk)) { | 1169 | if (IS_ERR(mx3_cam->clk)) |
| 1168 | err = PTR_ERR(mx3_cam->clk); | 1170 | return PTR_ERR(mx3_cam->clk); |
| 1169 | goto eclkget; | ||
| 1170 | } | ||
| 1171 | 1171 | ||
| 1172 | mx3_cam->pdata = pdev->dev.platform_data; | 1172 | mx3_cam->pdata = pdata; |
| 1173 | mx3_cam->platform_flags = mx3_cam->pdata->flags; | 1173 | mx3_cam->platform_flags = pdata->flags; |
| 1174 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { | 1174 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { |
| 1175 | /* | 1175 | /* |
| 1176 | * Platform hasn't set available data widths. This is bad. | 1176 | * Platform hasn't set available data widths. This is bad. |
| @@ -1189,7 +1189,7 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
| 1189 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) | 1189 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) |
| 1190 | mx3_cam->width_flags |= 1 << 14; | 1190 | mx3_cam->width_flags |= 1 << 14; |
| 1191 | 1191 | ||
| 1192 | mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000; | 1192 | mx3_cam->mclk = pdata->mclk_10khz * 10000; |
| 1193 | if (!mx3_cam->mclk) { | 1193 | if (!mx3_cam->mclk) { |
| 1194 | dev_warn(&pdev->dev, | 1194 | dev_warn(&pdev->dev, |
| 1195 | "mclk_10khz == 0! Please, fix your platform data. " | 1195 | "mclk_10khz == 0! Please, fix your platform data. " |
| @@ -1201,13 +1201,6 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
| 1201 | INIT_LIST_HEAD(&mx3_cam->capture); | 1201 | INIT_LIST_HEAD(&mx3_cam->capture); |
| 1202 | spin_lock_init(&mx3_cam->lock); | 1202 | spin_lock_init(&mx3_cam->lock); |
| 1203 | 1203 | ||
| 1204 | base = ioremap(res->start, resource_size(res)); | ||
| 1205 | if (!base) { | ||
| 1206 | pr_err("Couldn't map %x@%x\n", resource_size(res), res->start); | ||
| 1207 | err = -ENOMEM; | ||
| 1208 | goto eioremap; | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | mx3_cam->base = base; | 1204 | mx3_cam->base = base; |
| 1212 | 1205 | ||
| 1213 | soc_host = &mx3_cam->soc_host; | 1206 | soc_host = &mx3_cam->soc_host; |
| @@ -1218,9 +1211,12 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
| 1218 | soc_host->nr = pdev->id; | 1211 | soc_host->nr = pdev->id; |
| 1219 | 1212 | ||
| 1220 | mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 1213 | mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
| 1221 | if (IS_ERR(mx3_cam->alloc_ctx)) { | 1214 | if (IS_ERR(mx3_cam->alloc_ctx)) |
| 1222 | err = PTR_ERR(mx3_cam->alloc_ctx); | 1215 | return PTR_ERR(mx3_cam->alloc_ctx); |
| 1223 | goto eallocctx; | 1216 | |
| 1217 | if (pdata->asd_sizes) { | ||
| 1218 | soc_host->asd = pdata->asd; | ||
| 1219 | soc_host->asd_sizes = pdata->asd_sizes; | ||
| 1224 | } | 1220 | } |
| 1225 | 1221 | ||
| 1226 | err = soc_camera_host_register(soc_host); | 1222 | err = soc_camera_host_register(soc_host); |
| @@ -1234,14 +1230,6 @@ static int mx3_camera_probe(struct platform_device *pdev) | |||
| 1234 | 1230 | ||
| 1235 | ecamhostreg: | 1231 | ecamhostreg: |
| 1236 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | 1232 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); |
| 1237 | eallocctx: | ||
| 1238 | iounmap(base); | ||
| 1239 | eioremap: | ||
| 1240 | clk_put(mx3_cam->clk); | ||
| 1241 | eclkget: | ||
| 1242 | vfree(mx3_cam); | ||
| 1243 | ealloc: | ||
| 1244 | egetres: | ||
| 1245 | return err; | 1233 | return err; |
| 1246 | } | 1234 | } |
| 1247 | 1235 | ||
| @@ -1251,12 +1239,8 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
| 1251 | struct mx3_camera_dev *mx3_cam = container_of(soc_host, | 1239 | struct mx3_camera_dev *mx3_cam = container_of(soc_host, |
| 1252 | struct mx3_camera_dev, soc_host); | 1240 | struct mx3_camera_dev, soc_host); |
| 1253 | 1241 | ||
| 1254 | clk_put(mx3_cam->clk); | ||
| 1255 | |||
| 1256 | soc_camera_host_unregister(soc_host); | 1242 | soc_camera_host_unregister(soc_host); |
| 1257 | 1243 | ||
| 1258 | iounmap(mx3_cam->base); | ||
| 1259 | |||
| 1260 | /* | 1244 | /* |
| 1261 | * The channel has either not been allocated, | 1245 | * The channel has either not been allocated, |
| 1262 | * or should have been released | 1246 | * or should have been released |
| @@ -1266,8 +1250,6 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
| 1266 | 1250 | ||
| 1267 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); | 1251 | vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); |
| 1268 | 1252 | ||
| 1269 | vfree(mx3_cam); | ||
| 1270 | |||
| 1271 | dmaengine_put(); | 1253 | dmaengine_put(); |
| 1272 | 1254 | ||
| 1273 | return 0; | 1255 | return 0; |
| @@ -1276,6 +1258,7 @@ static int mx3_camera_remove(struct platform_device *pdev) | |||
| 1276 | static struct platform_driver mx3_camera_driver = { | 1258 | static struct platform_driver mx3_camera_driver = { |
| 1277 | .driver = { | 1259 | .driver = { |
| 1278 | .name = MX3_CAM_DRV_NAME, | 1260 | .name = MX3_CAM_DRV_NAME, |
| 1261 | .owner = THIS_MODULE, | ||
| 1279 | }, | 1262 | }, |
| 1280 | .probe = mx3_camera_probe, | 1263 | .probe = mx3_camera_probe, |
| 1281 | .remove = mx3_camera_remove, | 1264 | .remove = mx3_camera_remove, |
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c new file mode 100644 index 000000000000..d02a7e0b773f --- /dev/null +++ b/drivers/media/platform/soc_camera/rcar_vin.c | |||
| @@ -0,0 +1,1486 @@ | |||
| 1 | /* | ||
| 2 | * SoC-camera host driver for Renesas R-Car VIN unit | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011-2013 Renesas Solutions Corp. | ||
| 5 | * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com> | ||
| 6 | * | ||
| 7 | * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c" | ||
| 8 | * | ||
| 9 | * Copyright (C) 2008 Magnus Damm | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the | ||
| 13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 14 | * option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/platform_data/camera-rcar.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/videodev2.h> | ||
| 26 | |||
| 27 | #include <media/soc_camera.h> | ||
| 28 | #include <media/soc_mediabus.h> | ||
| 29 | #include <media/v4l2-common.h> | ||
| 30 | #include <media/v4l2-dev.h> | ||
| 31 | #include <media/v4l2-device.h> | ||
| 32 | #include <media/v4l2-mediabus.h> | ||
| 33 | #include <media/v4l2-subdev.h> | ||
| 34 | #include <media/videobuf2-dma-contig.h> | ||
| 35 | |||
| 36 | #include "soc_scale_crop.h" | ||
| 37 | |||
| 38 | #define DRV_NAME "rcar_vin" | ||
| 39 | |||
| 40 | /* Register offsets for R-Car VIN */ | ||
| 41 | #define VNMC_REG 0x00 /* Video n Main Control Register */ | ||
| 42 | #define VNMS_REG 0x04 /* Video n Module Status Register */ | ||
| 43 | #define VNFC_REG 0x08 /* Video n Frame Capture Register */ | ||
| 44 | #define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */ | ||
| 45 | #define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */ | ||
| 46 | #define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */ | ||
| 47 | #define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */ | ||
| 48 | #define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */ | ||
| 49 | #define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */ | ||
| 50 | #define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */ | ||
| 51 | #define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */ | ||
| 52 | #define VNIS_REG 0x2C /* Video n Image Stride Register */ | ||
| 53 | #define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */ | ||
| 54 | #define VNIE_REG 0x40 /* Video n Interrupt Enable Register */ | ||
| 55 | #define VNINTS_REG 0x44 /* Video n Interrupt Status Register */ | ||
| 56 | #define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */ | ||
| 57 | #define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */ | ||
| 58 | #define VNYS_REG 0x50 /* Video n Y Scale Register */ | ||
| 59 | #define VNXS_REG 0x54 /* Video n X Scale Register */ | ||
| 60 | #define VNDMR_REG 0x58 /* Video n Data Mode Register */ | ||
| 61 | #define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */ | ||
| 62 | #define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */ | ||
| 63 | |||
| 64 | /* Register bit fields for R-Car VIN */ | ||
| 65 | /* Video n Main Control Register bits */ | ||
| 66 | #define VNMC_FOC (1 << 21) | ||
| 67 | #define VNMC_YCAL (1 << 19) | ||
| 68 | #define VNMC_INF_YUV8_BT656 (0 << 16) | ||
| 69 | #define VNMC_INF_YUV8_BT601 (1 << 16) | ||
| 70 | #define VNMC_INF_YUV16 (5 << 16) | ||
| 71 | #define VNMC_VUP (1 << 10) | ||
| 72 | #define VNMC_IM_ODD (0 << 3) | ||
| 73 | #define VNMC_IM_ODD_EVEN (1 << 3) | ||
| 74 | #define VNMC_IM_EVEN (2 << 3) | ||
| 75 | #define VNMC_IM_FULL (3 << 3) | ||
| 76 | #define VNMC_BPS (1 << 1) | ||
| 77 | #define VNMC_ME (1 << 0) | ||
| 78 | |||
| 79 | /* Video n Module Status Register bits */ | ||
| 80 | #define VNMS_FBS_MASK (3 << 3) | ||
| 81 | #define VNMS_FBS_SHIFT 3 | ||
| 82 | #define VNMS_AV (1 << 1) | ||
| 83 | #define VNMS_CA (1 << 0) | ||
| 84 | |||
| 85 | /* Video n Frame Capture Register bits */ | ||
| 86 | #define VNFC_C_FRAME (1 << 1) | ||
| 87 | #define VNFC_S_FRAME (1 << 0) | ||
| 88 | |||
| 89 | /* Video n Interrupt Enable Register bits */ | ||
| 90 | #define VNIE_FIE (1 << 4) | ||
| 91 | #define VNIE_EFE (1 << 1) | ||
| 92 | |||
| 93 | /* Video n Data Mode Register bits */ | ||
| 94 | #define VNDMR_EXRGB (1 << 8) | ||
| 95 | #define VNDMR_BPSM (1 << 4) | ||
| 96 | #define VNDMR_DTMD_YCSEP (1 << 1) | ||
| 97 | #define VNDMR_DTMD_ARGB1555 (1 << 0) | ||
| 98 | |||
| 99 | /* Video n Data Mode Register 2 bits */ | ||
| 100 | #define VNDMR2_VPS (1 << 30) | ||
| 101 | #define VNDMR2_HPS (1 << 29) | ||
| 102 | #define VNDMR2_FTEV (1 << 17) | ||
| 103 | |||
| 104 | #define VIN_MAX_WIDTH 2048 | ||
| 105 | #define VIN_MAX_HEIGHT 2048 | ||
| 106 | |||
| 107 | enum chip_id { | ||
| 108 | RCAR_H1, | ||
| 109 | RCAR_M1, | ||
| 110 | RCAR_E1, | ||
| 111 | }; | ||
| 112 | |||
| 113 | enum rcar_vin_state { | ||
| 114 | STOPPED = 0, | ||
| 115 | RUNNING, | ||
| 116 | STOPPING, | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct rcar_vin_priv { | ||
| 120 | void __iomem *base; | ||
| 121 | spinlock_t lock; | ||
| 122 | int sequence; | ||
| 123 | /* State of the VIN module in capturing mode */ | ||
| 124 | enum rcar_vin_state state; | ||
| 125 | struct rcar_vin_platform_data *pdata; | ||
| 126 | struct soc_camera_host ici; | ||
| 127 | struct list_head capture; | ||
| 128 | #define MAX_BUFFER_NUM 3 | ||
| 129 | struct vb2_buffer *queue_buf[MAX_BUFFER_NUM]; | ||
| 130 | struct vb2_alloc_ctx *alloc_ctx; | ||
| 131 | enum v4l2_field field; | ||
| 132 | unsigned int vb_count; | ||
| 133 | unsigned int nr_hw_slots; | ||
| 134 | bool request_to_stop; | ||
| 135 | struct completion capture_stop; | ||
| 136 | enum chip_id chip; | ||
| 137 | }; | ||
| 138 | |||
| 139 | #define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM) | ||
| 140 | |||
| 141 | struct rcar_vin_buffer { | ||
| 142 | struct vb2_buffer vb; | ||
| 143 | struct list_head list; | ||
| 144 | }; | ||
| 145 | |||
| 146 | #define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ | ||
| 147 | struct rcar_vin_buffer, \ | ||
| 148 | vb)->list) | ||
| 149 | |||
| 150 | struct rcar_vin_cam { | ||
| 151 | /* VIN offsets within the camera output, before the VIN scaler */ | ||
| 152 | unsigned int vin_left; | ||
| 153 | unsigned int vin_top; | ||
| 154 | /* Client output, as seen by the VIN */ | ||
| 155 | unsigned int width; | ||
| 156 | unsigned int height; | ||
| 157 | /* | ||
| 158 | * User window from S_CROP / G_CROP, produced by client cropping and | ||
| 159 | * scaling, VIN scaling and VIN cropping, mapped back onto the client | ||
| 160 | * input window | ||
| 161 | */ | ||
| 162 | struct v4l2_rect subrect; | ||
| 163 | /* Camera cropping rectangle */ | ||
| 164 | struct v4l2_rect rect; | ||
| 165 | const struct soc_mbus_pixelfmt *extra_fmt; | ||
| 166 | }; | ||
| 167 | |||
| 168 | /* | ||
| 169 | * .queue_setup() is called to check whether the driver can accept the requested | ||
| 170 | * number of buffers and to fill in plane sizes for the current frame format if | ||
| 171 | * required | ||
| 172 | */ | ||
| 173 | static int rcar_vin_videobuf_setup(struct vb2_queue *vq, | ||
| 174 | const struct v4l2_format *fmt, | ||
| 175 | unsigned int *count, | ||
| 176 | unsigned int *num_planes, | ||
| 177 | unsigned int sizes[], void *alloc_ctxs[]) | ||
| 178 | { | ||
| 179 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); | ||
| 180 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 181 | struct rcar_vin_priv *priv = ici->priv; | ||
| 182 | |||
| 183 | if (fmt) { | ||
| 184 | const struct soc_camera_format_xlate *xlate; | ||
| 185 | unsigned int bytes_per_line; | ||
| 186 | int ret; | ||
| 187 | |||
| 188 | xlate = soc_camera_xlate_by_fourcc(icd, | ||
| 189 | fmt->fmt.pix.pixelformat); | ||
| 190 | if (!xlate) | ||
| 191 | return -EINVAL; | ||
| 192 | ret = soc_mbus_bytes_per_line(fmt->fmt.pix.width, | ||
| 193 | xlate->host_fmt); | ||
| 194 | if (ret < 0) | ||
| 195 | return ret; | ||
| 196 | |||
| 197 | bytes_per_line = max_t(u32, fmt->fmt.pix.bytesperline, ret); | ||
| 198 | |||
| 199 | ret = soc_mbus_image_size(xlate->host_fmt, bytes_per_line, | ||
| 200 | fmt->fmt.pix.height); | ||
| 201 | if (ret < 0) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | sizes[0] = max_t(u32, fmt->fmt.pix.sizeimage, ret); | ||
| 205 | } else { | ||
| 206 | /* Called from VIDIOC_REQBUFS or in compatibility mode */ | ||
| 207 | sizes[0] = icd->sizeimage; | ||
| 208 | } | ||
| 209 | |||
| 210 | alloc_ctxs[0] = priv->alloc_ctx; | ||
| 211 | |||
| 212 | if (!vq->num_buffers) | ||
| 213 | priv->sequence = 0; | ||
| 214 | |||
| 215 | if (!*count) | ||
| 216 | *count = 2; | ||
| 217 | priv->vb_count = *count; | ||
| 218 | |||
| 219 | *num_planes = 1; | ||
| 220 | |||
| 221 | /* Number of hardware slots */ | ||
| 222 | if (is_continuous_transfer(priv)) | ||
| 223 | priv->nr_hw_slots = MAX_BUFFER_NUM; | ||
| 224 | else | ||
| 225 | priv->nr_hw_slots = 1; | ||
| 226 | |||
| 227 | dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int rcar_vin_setup(struct rcar_vin_priv *priv) | ||
| 233 | { | ||
| 234 | struct soc_camera_device *icd = priv->ici.icd; | ||
| 235 | struct rcar_vin_cam *cam = icd->host_priv; | ||
| 236 | u32 vnmc, dmr, interrupts; | ||
| 237 | bool progressive = false, output_is_yuv = false; | ||
| 238 | |||
| 239 | switch (priv->field) { | ||
| 240 | case V4L2_FIELD_TOP: | ||
| 241 | vnmc = VNMC_IM_ODD; | ||
| 242 | break; | ||
| 243 | case V4L2_FIELD_BOTTOM: | ||
| 244 | vnmc = VNMC_IM_EVEN; | ||
| 245 | break; | ||
| 246 | case V4L2_FIELD_INTERLACED: | ||
| 247 | case V4L2_FIELD_INTERLACED_TB: | ||
| 248 | vnmc = VNMC_IM_FULL; | ||
| 249 | break; | ||
| 250 | case V4L2_FIELD_INTERLACED_BT: | ||
| 251 | vnmc = VNMC_IM_FULL | VNMC_FOC; | ||
| 252 | break; | ||
| 253 | case V4L2_FIELD_NONE: | ||
| 254 | if (is_continuous_transfer(priv)) { | ||
| 255 | vnmc = VNMC_IM_ODD_EVEN; | ||
| 256 | progressive = true; | ||
| 257 | } else { | ||
| 258 | vnmc = VNMC_IM_ODD; | ||
| 259 | } | ||
| 260 | break; | ||
| 261 | default: | ||
| 262 | vnmc = VNMC_IM_ODD; | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | |||
| 266 | /* input interface */ | ||
| 267 | switch (icd->current_fmt->code) { | ||
| 268 | case V4L2_MBUS_FMT_YUYV8_1X16: | ||
| 269 | /* BT.601/BT.1358 16bit YCbCr422 */ | ||
| 270 | vnmc |= VNMC_INF_YUV16; | ||
| 271 | break; | ||
| 272 | case V4L2_MBUS_FMT_YUYV8_2X8: | ||
| 273 | /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ | ||
| 274 | vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ? | ||
| 275 | VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; | ||
| 276 | default: | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* output format */ | ||
| 281 | switch (icd->current_fmt->host_fmt->fourcc) { | ||
| 282 | case V4L2_PIX_FMT_NV16: | ||
| 283 | iowrite32(ALIGN(cam->width * cam->height, 0x80), | ||
| 284 | priv->base + VNUVAOF_REG); | ||
| 285 | dmr = VNDMR_DTMD_YCSEP; | ||
| 286 | output_is_yuv = true; | ||
| 287 | break; | ||
| 288 | case V4L2_PIX_FMT_YUYV: | ||
| 289 | dmr = VNDMR_BPSM; | ||
| 290 | output_is_yuv = true; | ||
| 291 | break; | ||
| 292 | case V4L2_PIX_FMT_UYVY: | ||
| 293 | dmr = 0; | ||
| 294 | output_is_yuv = true; | ||
| 295 | break; | ||
| 296 | case V4L2_PIX_FMT_RGB555X: | ||
| 297 | dmr = VNDMR_DTMD_ARGB1555; | ||
| 298 | break; | ||
| 299 | case V4L2_PIX_FMT_RGB565: | ||
| 300 | dmr = 0; | ||
| 301 | break; | ||
| 302 | case V4L2_PIX_FMT_RGB32: | ||
| 303 | if (priv->chip == RCAR_H1 || priv->chip == RCAR_E1) { | ||
| 304 | dmr = VNDMR_EXRGB; | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | default: | ||
| 308 | dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", | ||
| 309 | icd->current_fmt->host_fmt->fourcc); | ||
| 310 | return -EINVAL; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Always update on field change */ | ||
| 314 | vnmc |= VNMC_VUP; | ||
| 315 | |||
| 316 | /* If input and output use the same colorspace, use bypass mode */ | ||
| 317 | if (output_is_yuv) | ||
| 318 | vnmc |= VNMC_BPS; | ||
| 319 | |||
| 320 | /* progressive or interlaced mode */ | ||
| 321 | interrupts = progressive ? VNIE_FIE | VNIE_EFE : VNIE_EFE; | ||
| 322 | |||
| 323 | /* ack interrupts */ | ||
| 324 | iowrite32(interrupts, priv->base + VNINTS_REG); | ||
| 325 | /* enable interrupts */ | ||
| 326 | iowrite32(interrupts, priv->base + VNIE_REG); | ||
| 327 | /* start capturing */ | ||
| 328 | iowrite32(dmr, priv->base + VNDMR_REG); | ||
| 329 | iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG); | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | static void rcar_vin_capture(struct rcar_vin_priv *priv) | ||
| 335 | { | ||
| 336 | if (is_continuous_transfer(priv)) | ||
| 337 | /* Continuous Frame Capture Mode */ | ||
| 338 | iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG); | ||
| 339 | else | ||
| 340 | /* Single Frame Capture Mode */ | ||
| 341 | iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG); | ||
| 342 | } | ||
| 343 | |||
| 344 | static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv) | ||
| 345 | { | ||
| 346 | priv->state = STOPPING; | ||
| 347 | |||
| 348 | /* set continuous & single transfer off */ | ||
| 349 | iowrite32(0, priv->base + VNFC_REG); | ||
| 350 | /* disable capture (release DMA buffer), reset */ | ||
| 351 | iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, | ||
| 352 | priv->base + VNMC_REG); | ||
| 353 | |||
| 354 | /* update the status if stopped already */ | ||
| 355 | if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA)) | ||
| 356 | priv->state = STOPPED; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv) | ||
| 360 | { | ||
| 361 | int slot; | ||
| 362 | |||
| 363 | for (slot = 0; slot < priv->nr_hw_slots; slot++) | ||
| 364 | if (priv->queue_buf[slot] == NULL) | ||
| 365 | return slot; | ||
| 366 | |||
| 367 | return -1; | ||
| 368 | } | ||
| 369 | |||
| 370 | static int rcar_vin_hw_ready(struct rcar_vin_priv *priv) | ||
| 371 | { | ||
| 372 | /* Ensure all HW slots are filled */ | ||
| 373 | return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | /* Moves a buffer from the queue to the HW slots */ | ||
| 377 | static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) | ||
| 378 | { | ||
| 379 | struct vb2_buffer *vb; | ||
| 380 | dma_addr_t phys_addr_top; | ||
| 381 | int slot; | ||
| 382 | |||
| 383 | if (list_empty(&priv->capture)) | ||
| 384 | return 0; | ||
| 385 | |||
| 386 | /* Find a free HW slot */ | ||
| 387 | slot = rcar_vin_get_free_hw_slot(priv); | ||
| 388 | if (slot < 0) | ||
| 389 | return 0; | ||
| 390 | |||
| 391 | vb = &list_entry(priv->capture.next, struct rcar_vin_buffer, list)->vb; | ||
| 392 | list_del_init(to_buf_list(vb)); | ||
| 393 | priv->queue_buf[slot] = vb; | ||
| 394 | phys_addr_top = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
| 395 | iowrite32(phys_addr_top, priv->base + VNMB_REG(slot)); | ||
| 396 | |||
| 397 | return 1; | ||
| 398 | } | ||
| 399 | |||
| 400 | static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) | ||
| 401 | { | ||
| 402 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); | ||
| 403 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 404 | struct rcar_vin_priv *priv = ici->priv; | ||
| 405 | unsigned long size; | ||
| 406 | |||
| 407 | size = icd->sizeimage; | ||
| 408 | |||
| 409 | if (vb2_plane_size(vb, 0) < size) { | ||
| 410 | dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", | ||
| 411 | vb->v4l2_buf.index, vb2_plane_size(vb, 0), size); | ||
| 412 | goto error; | ||
| 413 | } | ||
| 414 | |||
| 415 | vb2_set_plane_payload(vb, 0, size); | ||
| 416 | |||
| 417 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, | ||
| 418 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); | ||
| 419 | |||
| 420 | spin_lock_irq(&priv->lock); | ||
| 421 | |||
| 422 | list_add_tail(to_buf_list(vb), &priv->capture); | ||
| 423 | rcar_vin_fill_hw_slot(priv); | ||
| 424 | |||
| 425 | /* If we weren't running, and have enough buffers, start capturing! */ | ||
| 426 | if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) { | ||
| 427 | if (rcar_vin_setup(priv)) { | ||
| 428 | /* Submit error */ | ||
| 429 | list_del_init(to_buf_list(vb)); | ||
| 430 | spin_unlock_irq(&priv->lock); | ||
| 431 | goto error; | ||
| 432 | } | ||
| 433 | priv->request_to_stop = false; | ||
| 434 | init_completion(&priv->capture_stop); | ||
| 435 | priv->state = RUNNING; | ||
| 436 | rcar_vin_capture(priv); | ||
| 437 | } | ||
| 438 | |||
| 439 | spin_unlock_irq(&priv->lock); | ||
| 440 | |||
| 441 | return; | ||
| 442 | |||
| 443 | error: | ||
| 444 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
| 445 | } | ||
| 446 | |||
| 447 | static void rcar_vin_videobuf_release(struct vb2_buffer *vb) | ||
| 448 | { | ||
| 449 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); | ||
| 450 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 451 | struct rcar_vin_priv *priv = ici->priv; | ||
| 452 | unsigned int i; | ||
| 453 | int buf_in_use = 0; | ||
| 454 | |||
| 455 | spin_lock_irq(&priv->lock); | ||
| 456 | |||
| 457 | /* Is the buffer in use by the VIN hardware? */ | ||
| 458 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
| 459 | if (priv->queue_buf[i] == vb) { | ||
| 460 | buf_in_use = 1; | ||
| 461 | break; | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | if (buf_in_use) { | ||
| 466 | while (priv->state != STOPPED) { | ||
| 467 | |||
| 468 | /* issue stop if running */ | ||
| 469 | if (priv->state == RUNNING) | ||
| 470 | rcar_vin_request_capture_stop(priv); | ||
| 471 | |||
| 472 | /* wait until capturing has been stopped */ | ||
| 473 | if (priv->state == STOPPING) { | ||
| 474 | priv->request_to_stop = true; | ||
| 475 | spin_unlock_irq(&priv->lock); | ||
| 476 | wait_for_completion(&priv->capture_stop); | ||
| 477 | spin_lock_irq(&priv->lock); | ||
| 478 | } | ||
| 479 | } | ||
| 480 | /* | ||
| 481 | * Capturing has now stopped. The buffer we have been asked | ||
| 482 | * to release could be any of the current buffers in use, so | ||
| 483 | * release all buffers that are in use by HW | ||
| 484 | */ | ||
| 485 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
| 486 | if (priv->queue_buf[i]) { | ||
| 487 | vb2_buffer_done(priv->queue_buf[i], | ||
| 488 | VB2_BUF_STATE_ERROR); | ||
| 489 | priv->queue_buf[i] = NULL; | ||
| 490 | } | ||
| 491 | } | ||
| 492 | } else { | ||
| 493 | list_del_init(to_buf_list(vb)); | ||
| 494 | } | ||
| 495 | |||
| 496 | spin_unlock_irq(&priv->lock); | ||
| 497 | } | ||
| 498 | |||
| 499 | static int rcar_vin_videobuf_init(struct vb2_buffer *vb) | ||
| 500 | { | ||
| 501 | INIT_LIST_HEAD(to_buf_list(vb)); | ||
| 502 | return 0; | ||
| 503 | } | ||
| 504 | |||
| 505 | static int rcar_vin_stop_streaming(struct vb2_queue *vq) | ||
| 506 | { | ||
| 507 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); | ||
| 508 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 509 | struct rcar_vin_priv *priv = ici->priv; | ||
| 510 | struct list_head *buf_head, *tmp; | ||
| 511 | |||
| 512 | spin_lock_irq(&priv->lock); | ||
| 513 | list_for_each_safe(buf_head, tmp, &priv->capture) | ||
| 514 | list_del_init(buf_head); | ||
| 515 | spin_unlock_irq(&priv->lock); | ||
| 516 | |||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | |||
| 520 | static struct vb2_ops rcar_vin_vb2_ops = { | ||
| 521 | .queue_setup = rcar_vin_videobuf_setup, | ||
| 522 | .buf_init = rcar_vin_videobuf_init, | ||
| 523 | .buf_cleanup = rcar_vin_videobuf_release, | ||
| 524 | .buf_queue = rcar_vin_videobuf_queue, | ||
| 525 | .stop_streaming = rcar_vin_stop_streaming, | ||
| 526 | .wait_prepare = soc_camera_unlock, | ||
| 527 | .wait_finish = soc_camera_lock, | ||
| 528 | }; | ||
| 529 | |||
| 530 | static irqreturn_t rcar_vin_irq(int irq, void *data) | ||
| 531 | { | ||
| 532 | struct rcar_vin_priv *priv = data; | ||
| 533 | u32 int_status; | ||
| 534 | bool can_run = false, hw_stopped; | ||
| 535 | int slot; | ||
| 536 | unsigned int handled = 0; | ||
| 537 | |||
| 538 | spin_lock(&priv->lock); | ||
| 539 | |||
| 540 | int_status = ioread32(priv->base + VNINTS_REG); | ||
| 541 | if (!int_status) | ||
| 542 | goto done; | ||
| 543 | /* ack interrupts */ | ||
| 544 | iowrite32(int_status, priv->base + VNINTS_REG); | ||
| 545 | handled = 1; | ||
| 546 | |||
| 547 | /* nothing to do if capture status is 'STOPPED' */ | ||
| 548 | if (priv->state == STOPPED) | ||
| 549 | goto done; | ||
| 550 | |||
| 551 | hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA); | ||
| 552 | |||
| 553 | if (!priv->request_to_stop) { | ||
| 554 | if (is_continuous_transfer(priv)) | ||
| 555 | slot = (ioread32(priv->base + VNMS_REG) & | ||
| 556 | VNMS_FBS_MASK) >> VNMS_FBS_SHIFT; | ||
| 557 | else | ||
| 558 | slot = 0; | ||
| 559 | |||
| 560 | priv->queue_buf[slot]->v4l2_buf.field = priv->field; | ||
| 561 | priv->queue_buf[slot]->v4l2_buf.sequence = priv->sequence++; | ||
| 562 | do_gettimeofday(&priv->queue_buf[slot]->v4l2_buf.timestamp); | ||
| 563 | vb2_buffer_done(priv->queue_buf[slot], VB2_BUF_STATE_DONE); | ||
| 564 | priv->queue_buf[slot] = NULL; | ||
| 565 | |||
| 566 | if (priv->state != STOPPING) | ||
| 567 | can_run = rcar_vin_fill_hw_slot(priv); | ||
| 568 | |||
| 569 | if (hw_stopped || !can_run) { | ||
| 570 | priv->state = STOPPED; | ||
| 571 | } else if (is_continuous_transfer(priv) && | ||
| 572 | list_empty(&priv->capture) && | ||
| 573 | priv->state == RUNNING) { | ||
| 574 | /* | ||
| 575 | * The continuous capturing requires an explicit stop | ||
| 576 | * operation when there is no buffer to be set into | ||
| 577 | * the VnMBm registers. | ||
| 578 | */ | ||
| 579 | rcar_vin_request_capture_stop(priv); | ||
| 580 | } else { | ||
| 581 | rcar_vin_capture(priv); | ||
| 582 | } | ||
| 583 | |||
| 584 | } else if (hw_stopped) { | ||
| 585 | priv->state = STOPPED; | ||
| 586 | priv->request_to_stop = false; | ||
| 587 | complete(&priv->capture_stop); | ||
| 588 | } | ||
| 589 | |||
| 590 | done: | ||
| 591 | spin_unlock(&priv->lock); | ||
| 592 | |||
| 593 | return IRQ_RETVAL(handled); | ||
| 594 | } | ||
| 595 | |||
| 596 | static int rcar_vin_add_device(struct soc_camera_device *icd) | ||
| 597 | { | ||
| 598 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 599 | struct rcar_vin_priv *priv = ici->priv; | ||
| 600 | int i; | ||
| 601 | |||
| 602 | for (i = 0; i < MAX_BUFFER_NUM; i++) | ||
| 603 | priv->queue_buf[i] = NULL; | ||
| 604 | |||
| 605 | pm_runtime_get_sync(ici->v4l2_dev.dev); | ||
| 606 | |||
| 607 | dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n", | ||
| 608 | icd->devnum); | ||
| 609 | |||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | |||
| 613 | static void rcar_vin_remove_device(struct soc_camera_device *icd) | ||
| 614 | { | ||
| 615 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 616 | struct rcar_vin_priv *priv = ici->priv; | ||
| 617 | struct vb2_buffer *vb; | ||
| 618 | int i; | ||
| 619 | |||
| 620 | /* disable capture, disable interrupts */ | ||
| 621 | iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, | ||
| 622 | priv->base + VNMC_REG); | ||
| 623 | iowrite32(0, priv->base + VNIE_REG); | ||
| 624 | |||
| 625 | priv->state = STOPPED; | ||
| 626 | priv->request_to_stop = false; | ||
| 627 | |||
| 628 | /* make sure active buffer is cancelled */ | ||
| 629 | spin_lock_irq(&priv->lock); | ||
| 630 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
| 631 | vb = priv->queue_buf[i]; | ||
| 632 | if (vb) { | ||
| 633 | list_del_init(to_buf_list(vb)); | ||
| 634 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
| 635 | } | ||
| 636 | } | ||
| 637 | spin_unlock_irq(&priv->lock); | ||
| 638 | |||
| 639 | pm_runtime_put(ici->v4l2_dev.dev); | ||
| 640 | |||
| 641 | dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", | ||
| 642 | icd->devnum); | ||
| 643 | } | ||
| 644 | |||
| 645 | /* Called with .host_lock held */ | ||
| 646 | static int rcar_vin_clock_start(struct soc_camera_host *ici) | ||
| 647 | { | ||
| 648 | /* VIN does not have "mclk" */ | ||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | /* Called with .host_lock held */ | ||
| 653 | static void rcar_vin_clock_stop(struct soc_camera_host *ici) | ||
| 654 | { | ||
| 655 | /* VIN does not have "mclk" */ | ||
| 656 | } | ||
| 657 | |||
| 658 | /* rect is guaranteed to not exceed the scaled camera rectangle */ | ||
| 659 | static int rcar_vin_set_rect(struct soc_camera_device *icd) | ||
| 660 | { | ||
| 661 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 662 | struct rcar_vin_cam *cam = icd->host_priv; | ||
| 663 | struct rcar_vin_priv *priv = ici->priv; | ||
| 664 | unsigned int left_offset, top_offset; | ||
| 665 | unsigned char dsize = 0; | ||
| 666 | struct v4l2_rect *cam_subrect = &cam->subrect; | ||
| 667 | |||
| 668 | dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", | ||
| 669 | icd->user_width, icd->user_height, cam->vin_left, cam->vin_top); | ||
| 670 | |||
| 671 | left_offset = cam->vin_left; | ||
| 672 | top_offset = cam->vin_top; | ||
| 673 | |||
| 674 | if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB32 && | ||
| 675 | priv->chip == RCAR_E1) | ||
| 676 | dsize = 1; | ||
| 677 | |||
| 678 | dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n", | ||
| 679 | cam->width, cam->height, cam->vin_left, cam->vin_top); | ||
| 680 | dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n", | ||
| 681 | cam_subrect->width, cam_subrect->height, | ||
| 682 | cam_subrect->left, cam_subrect->top); | ||
| 683 | |||
| 684 | /* Set Start/End Pixel/Line Pre-Clip */ | ||
| 685 | iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG); | ||
| 686 | iowrite32((left_offset + cam->width - 1) << dsize, | ||
| 687 | priv->base + VNEPPRC_REG); | ||
| 688 | switch (priv->field) { | ||
| 689 | case V4L2_FIELD_INTERLACED: | ||
| 690 | case V4L2_FIELD_INTERLACED_TB: | ||
| 691 | case V4L2_FIELD_INTERLACED_BT: | ||
| 692 | iowrite32(top_offset / 2, priv->base + VNSLPRC_REG); | ||
| 693 | iowrite32((top_offset + cam->height) / 2 - 1, | ||
| 694 | priv->base + VNELPRC_REG); | ||
| 695 | break; | ||
| 696 | default: | ||
| 697 | iowrite32(top_offset, priv->base + VNSLPRC_REG); | ||
| 698 | iowrite32(top_offset + cam->height - 1, | ||
| 699 | priv->base + VNELPRC_REG); | ||
| 700 | break; | ||
| 701 | } | ||
| 702 | |||
| 703 | /* Set Start/End Pixel/Line Post-Clip */ | ||
| 704 | iowrite32(0, priv->base + VNSPPOC_REG); | ||
| 705 | iowrite32(0, priv->base + VNSLPOC_REG); | ||
| 706 | iowrite32((cam_subrect->width - 1) << dsize, priv->base + VNEPPOC_REG); | ||
| 707 | switch (priv->field) { | ||
| 708 | case V4L2_FIELD_INTERLACED: | ||
| 709 | case V4L2_FIELD_INTERLACED_TB: | ||
| 710 | case V4L2_FIELD_INTERLACED_BT: | ||
| 711 | iowrite32(cam_subrect->height / 2 - 1, | ||
| 712 | priv->base + VNELPOC_REG); | ||
| 713 | break; | ||
| 714 | default: | ||
| 715 | iowrite32(cam_subrect->height - 1, priv->base + VNELPOC_REG); | ||
| 716 | break; | ||
| 717 | } | ||
| 718 | |||
| 719 | iowrite32(ALIGN(cam->width, 0x10), priv->base + VNIS_REG); | ||
| 720 | |||
| 721 | return 0; | ||
| 722 | } | ||
| 723 | |||
| 724 | static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc) | ||
| 725 | { | ||
| 726 | *vnmc = ioread32(priv->base + VNMC_REG); | ||
| 727 | /* module disable */ | ||
| 728 | iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG); | ||
| 729 | } | ||
| 730 | |||
| 731 | static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc) | ||
| 732 | { | ||
| 733 | unsigned long timeout = jiffies + 10 * HZ; | ||
| 734 | |||
| 735 | /* | ||
| 736 | * Wait until the end of the current frame. It can take a long time, | ||
| 737 | * but if it has been aborted by a MRST1 reset, it should exit sooner. | ||
| 738 | */ | ||
| 739 | while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) && | ||
| 740 | time_before(jiffies, timeout)) | ||
| 741 | msleep(1); | ||
| 742 | |||
| 743 | if (time_after(jiffies, timeout)) { | ||
| 744 | dev_err(priv->ici.v4l2_dev.dev, | ||
| 745 | "Timeout waiting for frame end! Interface problem?\n"); | ||
| 746 | return; | ||
| 747 | } | ||
| 748 | |||
| 749 | iowrite32(vnmc, priv->base + VNMC_REG); | ||
| 750 | } | ||
| 751 | |||
| 752 | #define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \ | ||
| 753 | V4L2_MBUS_PCLK_SAMPLE_RISING | \ | ||
| 754 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ | ||
| 755 | V4L2_MBUS_HSYNC_ACTIVE_LOW | \ | ||
| 756 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ | ||
| 757 | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ | ||
| 758 | V4L2_MBUS_DATA_ACTIVE_HIGH) | ||
| 759 | |||
| 760 | static int rcar_vin_set_bus_param(struct soc_camera_device *icd) | ||
| 761 | { | ||
| 762 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 763 | struct rcar_vin_priv *priv = ici->priv; | ||
| 764 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 765 | struct v4l2_mbus_config cfg; | ||
| 766 | unsigned long common_flags; | ||
| 767 | u32 vnmc; | ||
| 768 | u32 val; | ||
| 769 | int ret; | ||
| 770 | |||
| 771 | capture_stop_preserve(priv, &vnmc); | ||
| 772 | |||
| 773 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); | ||
| 774 | if (!ret) { | ||
| 775 | common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); | ||
| 776 | if (!common_flags) { | ||
| 777 | dev_warn(icd->parent, | ||
| 778 | "MBUS flags incompatible: camera 0x%x, host 0x%x\n", | ||
| 779 | cfg.flags, VIN_MBUS_FLAGS); | ||
| 780 | return -EINVAL; | ||
| 781 | } | ||
| 782 | } else if (ret != -ENOIOCTLCMD) { | ||
| 783 | return ret; | ||
| 784 | } else { | ||
| 785 | common_flags = VIN_MBUS_FLAGS; | ||
| 786 | } | ||
| 787 | |||
| 788 | /* Make choises, based on platform preferences */ | ||
| 789 | if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && | ||
| 790 | (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { | ||
| 791 | if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW) | ||
| 792 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; | ||
| 793 | else | ||
| 794 | common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; | ||
| 795 | } | ||
| 796 | |||
| 797 | if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && | ||
| 798 | (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { | ||
| 799 | if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW) | ||
| 800 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; | ||
| 801 | else | ||
| 802 | common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; | ||
| 803 | } | ||
| 804 | |||
| 805 | cfg.flags = common_flags; | ||
| 806 | ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); | ||
| 807 | if (ret < 0 && ret != -ENOIOCTLCMD) | ||
| 808 | return ret; | ||
| 809 | |||
| 810 | val = priv->field == V4L2_FIELD_NONE ? VNDMR2_FTEV : 0; | ||
| 811 | if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) | ||
| 812 | val |= VNDMR2_VPS; | ||
| 813 | if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) | ||
| 814 | val |= VNDMR2_HPS; | ||
| 815 | iowrite32(val, priv->base + VNDMR2_REG); | ||
| 816 | |||
| 817 | ret = rcar_vin_set_rect(icd); | ||
| 818 | if (ret < 0) | ||
| 819 | return ret; | ||
| 820 | |||
| 821 | capture_restore(priv, vnmc); | ||
| 822 | |||
| 823 | return 0; | ||
| 824 | } | ||
| 825 | |||
| 826 | static int rcar_vin_try_bus_param(struct soc_camera_device *icd, | ||
| 827 | unsigned char buswidth) | ||
| 828 | { | ||
| 829 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 830 | struct v4l2_mbus_config cfg; | ||
| 831 | int ret; | ||
| 832 | |||
| 833 | ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); | ||
| 834 | if (ret == -ENOIOCTLCMD) | ||
| 835 | return 0; | ||
| 836 | else if (ret) | ||
| 837 | return ret; | ||
| 838 | |||
| 839 | if (buswidth > 24) | ||
| 840 | return -EINVAL; | ||
| 841 | |||
| 842 | /* check is there common mbus flags */ | ||
| 843 | ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); | ||
| 844 | if (ret) | ||
| 845 | return 0; | ||
| 846 | |||
| 847 | dev_warn(icd->parent, | ||
| 848 | "MBUS flags incompatible: camera 0x%x, host 0x%x\n", | ||
| 849 | cfg.flags, VIN_MBUS_FLAGS); | ||
| 850 | |||
| 851 | return -EINVAL; | ||
| 852 | } | ||
| 853 | |||
| 854 | static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
| 855 | { | ||
| 856 | return fmt->packing == SOC_MBUS_PACKING_NONE || | ||
| 857 | (fmt->bits_per_sample > 8 && | ||
| 858 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); | ||
| 859 | } | ||
| 860 | |||
| 861 | static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { | ||
| 862 | { | ||
| 863 | .fourcc = V4L2_PIX_FMT_NV16, | ||
| 864 | .name = "NV16", | ||
| 865 | .bits_per_sample = 8, | ||
| 866 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
| 867 | .order = SOC_MBUS_ORDER_LE, | ||
| 868 | .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C, | ||
| 869 | }, | ||
| 870 | { | ||
| 871 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
| 872 | .name = "UYVY", | ||
| 873 | .bits_per_sample = 16, | ||
| 874 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 875 | .order = SOC_MBUS_ORDER_LE, | ||
| 876 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
| 877 | }, | ||
| 878 | { | ||
| 879 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
| 880 | .name = "RGB565", | ||
| 881 | .bits_per_sample = 16, | ||
| 882 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 883 | .order = SOC_MBUS_ORDER_LE, | ||
| 884 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
| 885 | }, | ||
| 886 | { | ||
| 887 | .fourcc = V4L2_PIX_FMT_RGB555X, | ||
| 888 | .name = "ARGB1555", | ||
| 889 | .bits_per_sample = 16, | ||
| 890 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 891 | .order = SOC_MBUS_ORDER_LE, | ||
| 892 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
| 893 | }, | ||
| 894 | { | ||
| 895 | .fourcc = V4L2_PIX_FMT_RGB32, | ||
| 896 | .name = "RGB888", | ||
| 897 | .bits_per_sample = 32, | ||
| 898 | .packing = SOC_MBUS_PACKING_NONE, | ||
| 899 | .order = SOC_MBUS_ORDER_LE, | ||
| 900 | .layout = SOC_MBUS_LAYOUT_PACKED, | ||
| 901 | }, | ||
| 902 | }; | ||
| 903 | |||
| 904 | static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, | ||
| 905 | struct soc_camera_format_xlate *xlate) | ||
| 906 | { | ||
| 907 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 908 | struct device *dev = icd->parent; | ||
| 909 | int ret, k, n; | ||
| 910 | int formats = 0; | ||
| 911 | struct rcar_vin_cam *cam; | ||
| 912 | enum v4l2_mbus_pixelcode code; | ||
| 913 | const struct soc_mbus_pixelfmt *fmt; | ||
| 914 | |||
| 915 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); | ||
| 916 | if (ret < 0) | ||
| 917 | return 0; | ||
| 918 | |||
| 919 | fmt = soc_mbus_get_fmtdesc(code); | ||
| 920 | if (!fmt) { | ||
| 921 | dev_warn(dev, "unsupported format code #%u: %d\n", idx, code); | ||
| 922 | return 0; | ||
| 923 | } | ||
| 924 | |||
| 925 | ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample); | ||
| 926 | if (ret < 0) | ||
| 927 | return 0; | ||
| 928 | |||
| 929 | if (!icd->host_priv) { | ||
| 930 | struct v4l2_mbus_framefmt mf; | ||
| 931 | struct v4l2_rect rect; | ||
| 932 | struct device *dev = icd->parent; | ||
| 933 | int shift; | ||
| 934 | |||
| 935 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
| 936 | if (ret < 0) | ||
| 937 | return ret; | ||
| 938 | |||
| 939 | /* Cache current client geometry */ | ||
| 940 | ret = soc_camera_client_g_rect(sd, &rect); | ||
| 941 | if (ret == -ENOIOCTLCMD) { | ||
| 942 | /* Sensor driver doesn't support cropping */ | ||
| 943 | rect.left = 0; | ||
| 944 | rect.top = 0; | ||
| 945 | rect.width = mf.width; | ||
| 946 | rect.height = mf.height; | ||
| 947 | } else if (ret < 0) { | ||
| 948 | return ret; | ||
| 949 | } | ||
| 950 | |||
| 951 | /* | ||
| 952 | * If sensor proposes too large format then try smaller ones: | ||
| 953 | * 1280x960, 640x480, 320x240 | ||
| 954 | */ | ||
| 955 | for (shift = 0; shift < 3; shift++) { | ||
| 956 | if (mf.width <= VIN_MAX_WIDTH && | ||
| 957 | mf.height <= VIN_MAX_HEIGHT) | ||
| 958 | break; | ||
| 959 | |||
| 960 | mf.width = 1280 >> shift; | ||
| 961 | mf.height = 960 >> shift; | ||
| 962 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | ||
| 963 | soc_camera_grp_id(icd), | ||
| 964 | video, s_mbus_fmt, | ||
| 965 | &mf); | ||
| 966 | if (ret < 0) | ||
| 967 | return ret; | ||
| 968 | } | ||
| 969 | |||
| 970 | if (shift == 3) { | ||
| 971 | dev_err(dev, | ||
| 972 | "Failed to configure the client below %ux%x\n", | ||
| 973 | mf.width, mf.height); | ||
| 974 | return -EIO; | ||
| 975 | } | ||
| 976 | |||
| 977 | dev_dbg(dev, "camera fmt %ux%u\n", mf.width, mf.height); | ||
| 978 | |||
| 979 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); | ||
| 980 | if (!cam) | ||
| 981 | return -ENOMEM; | ||
| 982 | /* | ||
| 983 | * We are called with current camera crop, | ||
| 984 | * initialise subrect with it | ||
| 985 | */ | ||
| 986 | cam->rect = rect; | ||
| 987 | cam->subrect = rect; | ||
| 988 | cam->width = mf.width; | ||
| 989 | cam->height = mf.height; | ||
| 990 | |||
| 991 | icd->host_priv = cam; | ||
| 992 | } else { | ||
| 993 | cam = icd->host_priv; | ||
| 994 | } | ||
| 995 | |||
| 996 | /* Beginning of a pass */ | ||
| 997 | if (!idx) | ||
| 998 | cam->extra_fmt = NULL; | ||
| 999 | |||
| 1000 | switch (code) { | ||
| 1001 | case V4L2_MBUS_FMT_YUYV8_1X16: | ||
| 1002 | case V4L2_MBUS_FMT_YUYV8_2X8: | ||
| 1003 | if (cam->extra_fmt) | ||
| 1004 | break; | ||
| 1005 | |||
| 1006 | /* Add all our formats that can be generated by VIN */ | ||
| 1007 | cam->extra_fmt = rcar_vin_formats; | ||
| 1008 | |||
| 1009 | n = ARRAY_SIZE(rcar_vin_formats); | ||
| 1010 | formats += n; | ||
| 1011 | for (k = 0; xlate && k < n; k++, xlate++) { | ||
| 1012 | xlate->host_fmt = &rcar_vin_formats[k]; | ||
| 1013 | xlate->code = code; | ||
| 1014 | dev_dbg(dev, "Providing format %s using code %d\n", | ||
| 1015 | rcar_vin_formats[k].name, code); | ||
| 1016 | } | ||
| 1017 | break; | ||
| 1018 | default: | ||
| 1019 | if (!rcar_vin_packing_supported(fmt)) | ||
| 1020 | return 0; | ||
| 1021 | |||
| 1022 | dev_dbg(dev, "Providing format %s in pass-through mode\n", | ||
| 1023 | fmt->name); | ||
| 1024 | break; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | /* Generic pass-through */ | ||
| 1028 | formats++; | ||
| 1029 | if (xlate) { | ||
| 1030 | xlate->host_fmt = fmt; | ||
| 1031 | xlate->code = code; | ||
| 1032 | xlate++; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | return formats; | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static void rcar_vin_put_formats(struct soc_camera_device *icd) | ||
| 1039 | { | ||
| 1040 | kfree(icd->host_priv); | ||
| 1041 | icd->host_priv = NULL; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static int rcar_vin_set_crop(struct soc_camera_device *icd, | ||
| 1045 | const struct v4l2_crop *a) | ||
| 1046 | { | ||
| 1047 | struct v4l2_crop a_writable = *a; | ||
| 1048 | const struct v4l2_rect *rect = &a_writable.c; | ||
| 1049 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 1050 | struct rcar_vin_priv *priv = ici->priv; | ||
| 1051 | struct v4l2_crop cam_crop; | ||
| 1052 | struct rcar_vin_cam *cam = icd->host_priv; | ||
| 1053 | struct v4l2_rect *cam_rect = &cam_crop.c; | ||
| 1054 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 1055 | struct device *dev = icd->parent; | ||
| 1056 | struct v4l2_mbus_framefmt mf; | ||
| 1057 | u32 vnmc; | ||
| 1058 | int ret, i; | ||
| 1059 | |||
| 1060 | dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, | ||
| 1061 | rect->left, rect->top); | ||
| 1062 | |||
| 1063 | /* During camera cropping its output window can change too, stop VIN */ | ||
| 1064 | capture_stop_preserve(priv, &vnmc); | ||
| 1065 | dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc); | ||
| 1066 | |||
| 1067 | /* Apply iterative camera S_CROP for new input window. */ | ||
| 1068 | ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, | ||
| 1069 | &cam->rect, &cam->subrect); | ||
| 1070 | if (ret < 0) | ||
| 1071 | return ret; | ||
| 1072 | |||
| 1073 | dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n", | ||
| 1074 | cam_rect->width, cam_rect->height, | ||
| 1075 | cam_rect->left, cam_rect->top); | ||
| 1076 | |||
| 1077 | /* On success cam_crop contains current camera crop */ | ||
| 1078 | |||
| 1079 | /* Retrieve camera output window */ | ||
| 1080 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
| 1081 | if (ret < 0) | ||
| 1082 | return ret; | ||
| 1083 | |||
| 1084 | if (mf.width > VIN_MAX_WIDTH || mf.height > VIN_MAX_HEIGHT) | ||
| 1085 | return -EINVAL; | ||
| 1086 | |||
| 1087 | /* Cache camera output window */ | ||
| 1088 | cam->width = mf.width; | ||
| 1089 | cam->height = mf.height; | ||
| 1090 | |||
| 1091 | icd->user_width = cam->width; | ||
| 1092 | icd->user_height = cam->height; | ||
| 1093 | |||
| 1094 | cam->vin_left = rect->left & ~1; | ||
| 1095 | cam->vin_top = rect->top & ~1; | ||
| 1096 | |||
| 1097 | /* Use VIN cropping to crop to the new window. */ | ||
| 1098 | ret = rcar_vin_set_rect(icd); | ||
| 1099 | if (ret < 0) | ||
| 1100 | return ret; | ||
| 1101 | |||
| 1102 | cam->subrect = *rect; | ||
| 1103 | |||
| 1104 | dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n", | ||
| 1105 | icd->user_width, icd->user_height, | ||
| 1106 | cam->vin_left, cam->vin_top); | ||
| 1107 | |||
| 1108 | /* Restore capture */ | ||
| 1109 | for (i = 0; i < MAX_BUFFER_NUM; i++) { | ||
| 1110 | if (priv->queue_buf[i] && priv->state == STOPPED) { | ||
| 1111 | vnmc |= VNMC_ME; | ||
| 1112 | break; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | capture_restore(priv, vnmc); | ||
| 1116 | |||
| 1117 | /* Even if only camera cropping succeeded */ | ||
| 1118 | return ret; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | static int rcar_vin_get_crop(struct soc_camera_device *icd, | ||
| 1122 | struct v4l2_crop *a) | ||
| 1123 | { | ||
| 1124 | struct rcar_vin_cam *cam = icd->host_priv; | ||
| 1125 | |||
| 1126 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 1127 | a->c = cam->subrect; | ||
| 1128 | |||
| 1129 | return 0; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | /* Similar to set_crop multistage iterative algorithm */ | ||
| 1133 | static int rcar_vin_set_fmt(struct soc_camera_device *icd, | ||
| 1134 | struct v4l2_format *f) | ||
| 1135 | { | ||
| 1136 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
| 1137 | struct rcar_vin_priv *priv = ici->priv; | ||
| 1138 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 1139 | struct rcar_vin_cam *cam = icd->host_priv; | ||
| 1140 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
| 1141 | struct v4l2_mbus_framefmt mf; | ||
| 1142 | struct device *dev = icd->parent; | ||
| 1143 | __u32 pixfmt = pix->pixelformat; | ||
| 1144 | const struct soc_camera_format_xlate *xlate; | ||
| 1145 | unsigned int vin_sub_width = 0, vin_sub_height = 0; | ||
| 1146 | int ret; | ||
| 1147 | bool can_scale; | ||
| 1148 | enum v4l2_field field; | ||
| 1149 | v4l2_std_id std; | ||
| 1150 | |||
| 1151 | dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n", | ||
| 1152 | pixfmt, pix->width, pix->height); | ||
| 1153 | |||
| 1154 | switch (pix->field) { | ||
| 1155 | default: | ||
| 1156 | pix->field = V4L2_FIELD_NONE; | ||
| 1157 | /* fall-through */ | ||
| 1158 | case V4L2_FIELD_NONE: | ||
| 1159 | case V4L2_FIELD_TOP: | ||
| 1160 | case V4L2_FIELD_BOTTOM: | ||
| 1161 | case V4L2_FIELD_INTERLACED_TB: | ||
| 1162 | case V4L2_FIELD_INTERLACED_BT: | ||
| 1163 | field = pix->field; | ||
| 1164 | break; | ||
| 1165 | case V4L2_FIELD_INTERLACED: | ||
| 1166 | /* Query for standard if not explicitly mentioned _TB/_BT */ | ||
| 1167 | ret = v4l2_subdev_call(sd, video, querystd, &std); | ||
| 1168 | if (ret < 0) | ||
| 1169 | std = V4L2_STD_625_50; | ||
| 1170 | |||
| 1171 | field = std & V4L2_STD_625_50 ? V4L2_FIELD_INTERLACED_TB : | ||
| 1172 | V4L2_FIELD_INTERLACED_BT; | ||
| 1173 | break; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | ||
| 1177 | if (!xlate) { | ||
| 1178 | dev_warn(dev, "Format %x not found\n", pixfmt); | ||
| 1179 | return -EINVAL; | ||
| 1180 | } | ||
| 1181 | /* Calculate client output geometry */ | ||
| 1182 | soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, | ||
| 1183 | 12); | ||
| 1184 | mf.field = pix->field; | ||
| 1185 | mf.colorspace = pix->colorspace; | ||
| 1186 | mf.code = xlate->code; | ||
| 1187 | |||
| 1188 | switch (pixfmt) { | ||
| 1189 | case V4L2_PIX_FMT_RGB32: | ||
| 1190 | can_scale = priv->chip != RCAR_E1; | ||
| 1191 | break; | ||
| 1192 | case V4L2_PIX_FMT_UYVY: | ||
| 1193 | case V4L2_PIX_FMT_YUYV: | ||
| 1194 | case V4L2_PIX_FMT_RGB565: | ||
| 1195 | case V4L2_PIX_FMT_RGB555X: | ||
| 1196 | can_scale = true; | ||
| 1197 | break; | ||
| 1198 | default: | ||
| 1199 | can_scale = false; | ||
| 1200 | break; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height); | ||
| 1204 | |||
| 1205 | ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, | ||
| 1206 | &mf, &vin_sub_width, &vin_sub_height, | ||
| 1207 | can_scale, 12); | ||
| 1208 | |||
| 1209 | /* Done with the camera. Now see if we can improve the result */ | ||
| 1210 | dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", | ||
| 1211 | ret, mf.width, mf.height, pix->width, pix->height); | ||
| 1212 | |||
| 1213 | if (ret == -ENOIOCTLCMD) | ||
| 1214 | dev_dbg(dev, "Sensor doesn't support scaling\n"); | ||
| 1215 | else if (ret < 0) | ||
| 1216 | return ret; | ||
| 1217 | |||
| 1218 | if (mf.code != xlate->code) | ||
| 1219 | return -EINVAL; | ||
| 1220 | |||
| 1221 | /* Prepare VIN crop */ | ||
| 1222 | cam->width = mf.width; | ||
| 1223 | cam->height = mf.height; | ||
| 1224 | |||
| 1225 | /* Use VIN scaling to scale to the requested user window. */ | ||
| 1226 | |||
| 1227 | /* We cannot scale up */ | ||
| 1228 | if (pix->width > vin_sub_width) | ||
| 1229 | vin_sub_width = pix->width; | ||
| 1230 | |||
| 1231 | if (pix->height > vin_sub_height) | ||
| 1232 | vin_sub_height = pix->height; | ||
| 1233 | |||
| 1234 | pix->colorspace = mf.colorspace; | ||
| 1235 | |||
| 1236 | if (!can_scale) { | ||
| 1237 | pix->width = vin_sub_width; | ||
| 1238 | pix->height = vin_sub_height; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | /* | ||
| 1242 | * We have calculated CFLCR, the actual configuration will be performed | ||
| 1243 | * in rcar_vin_set_bus_param() | ||
| 1244 | */ | ||
| 1245 | |||
| 1246 | dev_dbg(dev, "W: %u : %u, H: %u : %u\n", | ||
| 1247 | vin_sub_width, pix->width, vin_sub_height, pix->height); | ||
| 1248 | |||
| 1249 | icd->current_fmt = xlate; | ||
| 1250 | |||
| 1251 | priv->field = field; | ||
| 1252 | |||
| 1253 | return 0; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | static int rcar_vin_try_fmt(struct soc_camera_device *icd, | ||
| 1257 | struct v4l2_format *f) | ||
| 1258 | { | ||
| 1259 | const struct soc_camera_format_xlate *xlate; | ||
| 1260 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
| 1261 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
| 1262 | struct v4l2_mbus_framefmt mf; | ||
| 1263 | __u32 pixfmt = pix->pixelformat; | ||
| 1264 | int width, height; | ||
| 1265 | int ret; | ||
| 1266 | |||
| 1267 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | ||
| 1268 | if (!xlate) { | ||
| 1269 | xlate = icd->current_fmt; | ||
| 1270 | dev_dbg(icd->parent, "Format %x not found, keeping %x\n", | ||
| 1271 | pixfmt, xlate->host_fmt->fourcc); | ||
| 1272 | pixfmt = xlate->host_fmt->fourcc; | ||
| 1273 | pix->pixelformat = pixfmt; | ||
| 1274 | pix->colorspace = icd->colorspace; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | /* FIXME: calculate using depth and bus width */ | ||
| 1278 | v4l_bound_align_image(&pix->width, 2, VIN_MAX_WIDTH, 1, | ||
| 1279 | &pix->height, 4, VIN_MAX_HEIGHT, 2, 0); | ||
| 1280 | |||
| 1281 | width = pix->width; | ||
| 1282 | height = pix->height; | ||
| 1283 | |||
| 1284 | /* let soc-camera calculate these values */ | ||
| 1285 | pix->bytesperline = 0; | ||
| 1286 | pix->sizeimage = 0; | ||
| 1287 | |||
| 1288 | /* limit to sensor capabilities */ | ||
| 1289 | mf.width = pix->width; | ||
| 1290 | mf.height = pix->height; | ||
| 1291 | mf.field = pix->field; | ||
| 1292 | mf.code = xlate->code; | ||
| 1293 | mf.colorspace = pix->colorspace; | ||
| 1294 | |||
| 1295 | ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), | ||
| 1296 | video, try_mbus_fmt, &mf); | ||
| 1297 | if (ret < 0) | ||
| 1298 | return ret; | ||
| 1299 | |||
| 1300 | pix->width = mf.width; | ||
| 1301 | pix->height = mf.height; | ||
| 1302 | pix->field = mf.field; | ||
| 1303 | pix->colorspace = mf.colorspace; | ||
| 1304 | |||
| 1305 | if (pixfmt == V4L2_PIX_FMT_NV16) { | ||
| 1306 | /* FIXME: check against rect_max after converting soc-camera */ | ||
| 1307 | /* We can scale precisely, need a bigger image from camera */ | ||
| 1308 | if (pix->width < width || pix->height < height) { | ||
| 1309 | /* | ||
| 1310 | * We presume, the sensor behaves sanely, i.e. if | ||
| 1311 | * requested a bigger rectangle, it will not return a | ||
| 1312 | * smaller one. | ||
| 1313 | */ | ||
| 1314 | mf.width = VIN_MAX_WIDTH; | ||
| 1315 | mf.height = VIN_MAX_HEIGHT; | ||
| 1316 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | ||
| 1317 | soc_camera_grp_id(icd), | ||
| 1318 | video, try_mbus_fmt, | ||
| 1319 | &mf); | ||
| 1320 | if (ret < 0) { | ||
| 1321 | dev_err(icd->parent, | ||
| 1322 | "client try_fmt() = %d\n", ret); | ||
| 1323 | return ret; | ||
| 1324 | } | ||
| 1325 | } | ||
| 1326 | /* We will scale exactly */ | ||
| 1327 | if (mf.width > width) | ||
| 1328 | pix->width = width; | ||
| 1329 | if (mf.height > height) | ||
| 1330 | pix->height = height; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | return ret; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | static unsigned int rcar_vin_poll(struct file *file, poll_table *pt) | ||
| 1337 | { | ||
| 1338 | struct soc_camera_device *icd = file->private_data; | ||
| 1339 | |||
| 1340 | return vb2_poll(&icd->vb2_vidq, file, pt); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | static int rcar_vin_querycap(struct soc_camera_host *ici, | ||
| 1344 | struct v4l2_capability *cap) | ||
| 1345 | { | ||
| 1346 | strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card)); | ||
| 1347 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | ||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static int rcar_vin_init_videobuf2(struct vb2_queue *vq, | ||
| 1352 | struct soc_camera_device *icd) | ||
| 1353 | { | ||
| 1354 | vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 1355 | vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
| 1356 | vq->drv_priv = icd; | ||
| 1357 | vq->ops = &rcar_vin_vb2_ops; | ||
| 1358 | vq->mem_ops = &vb2_dma_contig_memops; | ||
| 1359 | vq->buf_struct_size = sizeof(struct rcar_vin_buffer); | ||
| 1360 | vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
| 1361 | |||
| 1362 | return vb2_queue_init(vq); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static struct soc_camera_host_ops rcar_vin_host_ops = { | ||
| 1366 | .owner = THIS_MODULE, | ||
| 1367 | .add = rcar_vin_add_device, | ||
| 1368 | .remove = rcar_vin_remove_device, | ||
| 1369 | .clock_start = rcar_vin_clock_start, | ||
| 1370 | .clock_stop = rcar_vin_clock_stop, | ||
| 1371 | .get_formats = rcar_vin_get_formats, | ||
| 1372 | .put_formats = rcar_vin_put_formats, | ||
| 1373 | .get_crop = rcar_vin_get_crop, | ||
| 1374 | .set_crop = rcar_vin_set_crop, | ||
| 1375 | .try_fmt = rcar_vin_try_fmt, | ||
| 1376 | .set_fmt = rcar_vin_set_fmt, | ||
| 1377 | .poll = rcar_vin_poll, | ||
| 1378 | .querycap = rcar_vin_querycap, | ||
| 1379 | .set_bus_param = rcar_vin_set_bus_param, | ||
| 1380 | .init_videobuf2 = rcar_vin_init_videobuf2, | ||
| 1381 | }; | ||
| 1382 | |||
| 1383 | static struct platform_device_id rcar_vin_id_table[] = { | ||
| 1384 | { "r8a7779-vin", RCAR_H1 }, | ||
| 1385 | { "r8a7778-vin", RCAR_M1 }, | ||
| 1386 | { "uPD35004-vin", RCAR_E1 }, | ||
| 1387 | {}, | ||
| 1388 | }; | ||
| 1389 | MODULE_DEVICE_TABLE(platform, rcar_vin_id_table); | ||
| 1390 | |||
| 1391 | static int rcar_vin_probe(struct platform_device *pdev) | ||
| 1392 | { | ||
| 1393 | struct rcar_vin_priv *priv; | ||
| 1394 | struct resource *mem; | ||
| 1395 | struct rcar_vin_platform_data *pdata; | ||
| 1396 | int irq, ret; | ||
| 1397 | |||
| 1398 | pdata = pdev->dev.platform_data; | ||
| 1399 | if (!pdata || !pdata->flags) { | ||
| 1400 | dev_err(&pdev->dev, "platform data not set\n"); | ||
| 1401 | return -EINVAL; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1405 | if (mem == NULL) | ||
| 1406 | return -EINVAL; | ||
| 1407 | |||
| 1408 | irq = platform_get_irq(pdev, 0); | ||
| 1409 | if (irq <= 0) | ||
| 1410 | return -EINVAL; | ||
| 1411 | |||
| 1412 | priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv), | ||
| 1413 | GFP_KERNEL); | ||
| 1414 | if (!priv) | ||
| 1415 | return -ENOMEM; | ||
| 1416 | |||
| 1417 | priv->base = devm_ioremap_resource(&pdev->dev, mem); | ||
| 1418 | if (IS_ERR(priv->base)) | ||
| 1419 | return PTR_ERR(priv->base); | ||
| 1420 | |||
| 1421 | ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, | ||
| 1422 | dev_name(&pdev->dev), priv); | ||
| 1423 | if (ret) | ||
| 1424 | return ret; | ||
| 1425 | |||
| 1426 | priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
| 1427 | if (IS_ERR(priv->alloc_ctx)) | ||
| 1428 | return PTR_ERR(priv->alloc_ctx); | ||
| 1429 | |||
| 1430 | priv->ici.priv = priv; | ||
| 1431 | priv->ici.v4l2_dev.dev = &pdev->dev; | ||
| 1432 | priv->ici.nr = pdev->id; | ||
| 1433 | priv->ici.drv_name = dev_name(&pdev->dev); | ||
| 1434 | priv->ici.ops = &rcar_vin_host_ops; | ||
| 1435 | |||
| 1436 | priv->pdata = pdata; | ||
| 1437 | priv->chip = pdev->id_entry->driver_data; | ||
| 1438 | spin_lock_init(&priv->lock); | ||
| 1439 | INIT_LIST_HEAD(&priv->capture); | ||
| 1440 | |||
| 1441 | priv->state = STOPPED; | ||
| 1442 | |||
| 1443 | pm_suspend_ignore_children(&pdev->dev, true); | ||
| 1444 | pm_runtime_enable(&pdev->dev); | ||
| 1445 | |||
| 1446 | ret = soc_camera_host_register(&priv->ici); | ||
| 1447 | if (ret) | ||
| 1448 | goto cleanup; | ||
| 1449 | |||
| 1450 | return 0; | ||
| 1451 | |||
| 1452 | cleanup: | ||
| 1453 | pm_runtime_disable(&pdev->dev); | ||
| 1454 | vb2_dma_contig_cleanup_ctx(priv->alloc_ctx); | ||
| 1455 | |||
| 1456 | return ret; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | static int rcar_vin_remove(struct platform_device *pdev) | ||
| 1460 | { | ||
| 1461 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); | ||
| 1462 | struct rcar_vin_priv *priv = container_of(soc_host, | ||
| 1463 | struct rcar_vin_priv, ici); | ||
| 1464 | |||
| 1465 | soc_camera_host_unregister(soc_host); | ||
| 1466 | pm_runtime_disable(&pdev->dev); | ||
| 1467 | vb2_dma_contig_cleanup_ctx(priv->alloc_ctx); | ||
| 1468 | |||
| 1469 | return 0; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static struct platform_driver rcar_vin_driver = { | ||
| 1473 | .probe = rcar_vin_probe, | ||
| 1474 | .remove = rcar_vin_remove, | ||
| 1475 | .driver = { | ||
| 1476 | .name = DRV_NAME, | ||
| 1477 | .owner = THIS_MODULE, | ||
| 1478 | }, | ||
| 1479 | .id_table = rcar_vin_id_table, | ||
| 1480 | }; | ||
| 1481 | |||
| 1482 | module_platform_driver(rcar_vin_driver); | ||
| 1483 | |||
| 1484 | MODULE_LICENSE("GPL"); | ||
| 1485 | MODULE_ALIAS("platform:rcar_vin"); | ||
| 1486 | MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver"); | ||
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index f2de0066089a..8df22f779175 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | |||
| @@ -610,13 +610,12 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
| 610 | static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) | 610 | static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) |
| 611 | { | 611 | { |
| 612 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 612 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 613 | int ret; | ||
| 614 | 613 | ||
| 615 | pm_runtime_get_sync(ici->v4l2_dev.dev); | 614 | pm_runtime_get_sync(ici->v4l2_dev.dev); |
| 616 | 615 | ||
| 617 | pcdev->buf_total = 0; | 616 | pcdev->buf_total = 0; |
| 618 | 617 | ||
| 619 | ret = sh_mobile_ceu_soft_reset(pcdev); | 618 | sh_mobile_ceu_soft_reset(pcdev); |
| 620 | 619 | ||
| 621 | return 0; | 620 | return 0; |
| 622 | } | 621 | } |
| @@ -1837,9 +1836,9 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) | |||
| 1837 | for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { | 1836 | for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { |
| 1838 | for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { | 1837 | for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { |
| 1839 | dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", | 1838 | dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", |
| 1840 | __func__, i, (*asd)->bus_type); | 1839 | __func__, i, (*asd)->match_type); |
| 1841 | if ((*asd)->bus_type == V4L2_ASYNC_BUS_PLATFORM && | 1840 | if ((*asd)->match_type == V4L2_ASYNC_MATCH_DEVNAME && |
| 1842 | !strncmp(name, (*asd)->match.platform.name, | 1841 | !strncmp(name, (*asd)->match.device_name.name, |
| 1843 | sizeof(name) - 1)) { | 1842 | sizeof(name) - 1)) { |
| 1844 | pcdev->csi2_asd = *asd; | 1843 | pcdev->csi2_asd = *asd; |
| 1845 | break; | 1844 | break; |
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 2dd0e5272941..387a232d95a4 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
| @@ -136,7 +136,7 @@ EXPORT_SYMBOL(soc_camera_power_off); | |||
| 136 | 136 | ||
| 137 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) | 137 | int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) |
| 138 | { | 138 | { |
| 139 | 139 | /* Should not have any effect in synchronous case */ | |
| 140 | return devm_regulator_bulk_get(dev, ssdd->num_regulators, | 140 | return devm_regulator_bulk_get(dev, ssdd->num_regulators, |
| 141 | ssdd->regulators); | 141 | ssdd->regulators); |
| 142 | } | 142 | } |
| @@ -1311,6 +1311,7 @@ eusrfmt: | |||
| 1311 | static int soc_camera_i2c_init(struct soc_camera_device *icd, | 1311 | static int soc_camera_i2c_init(struct soc_camera_device *icd, |
| 1312 | struct soc_camera_desc *sdesc) | 1312 | struct soc_camera_desc *sdesc) |
| 1313 | { | 1313 | { |
| 1314 | struct soc_camera_subdev_desc *ssdd; | ||
| 1314 | struct i2c_client *client; | 1315 | struct i2c_client *client; |
| 1315 | struct soc_camera_host *ici; | 1316 | struct soc_camera_host *ici; |
| 1316 | struct soc_camera_host_desc *shd = &sdesc->host_desc; | 1317 | struct soc_camera_host_desc *shd = &sdesc->host_desc; |
| @@ -1333,7 +1334,21 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, | |||
| 1333 | return -ENODEV; | 1334 | return -ENODEV; |
| 1334 | } | 1335 | } |
| 1335 | 1336 | ||
| 1336 | shd->board_info->platform_data = &sdesc->subdev_desc; | 1337 | ssdd = kzalloc(sizeof(*ssdd), GFP_KERNEL); |
| 1338 | if (!ssdd) { | ||
| 1339 | ret = -ENOMEM; | ||
| 1340 | goto ealloc; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | memcpy(ssdd, &sdesc->subdev_desc, sizeof(*ssdd)); | ||
| 1344 | /* | ||
| 1345 | * In synchronous case we request regulators ourselves in | ||
| 1346 | * soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try | ||
| 1347 | * to allocate them again. | ||
| 1348 | */ | ||
| 1349 | ssdd->num_regulators = 0; | ||
| 1350 | ssdd->regulators = NULL; | ||
| 1351 | shd->board_info->platform_data = ssdd; | ||
| 1337 | 1352 | ||
| 1338 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", | 1353 | snprintf(clk_name, sizeof(clk_name), "%d-%04x", |
| 1339 | shd->i2c_adapter_id, shd->board_info->addr); | 1354 | shd->i2c_adapter_id, shd->board_info->addr); |
| @@ -1359,8 +1374,10 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, | |||
| 1359 | return 0; | 1374 | return 0; |
| 1360 | ei2cnd: | 1375 | ei2cnd: |
| 1361 | v4l2_clk_unregister(icd->clk); | 1376 | v4l2_clk_unregister(icd->clk); |
| 1362 | eclkreg: | ||
| 1363 | icd->clk = NULL; | 1377 | icd->clk = NULL; |
| 1378 | eclkreg: | ||
| 1379 | kfree(ssdd); | ||
| 1380 | ealloc: | ||
| 1364 | i2c_put_adapter(adap); | 1381 | i2c_put_adapter(adap); |
| 1365 | return ret; | 1382 | return ret; |
| 1366 | } | 1383 | } |
| @@ -1370,15 +1387,18 @@ static void soc_camera_i2c_free(struct soc_camera_device *icd) | |||
| 1370 | struct i2c_client *client = | 1387 | struct i2c_client *client = |
| 1371 | to_i2c_client(to_soc_camera_control(icd)); | 1388 | to_i2c_client(to_soc_camera_control(icd)); |
| 1372 | struct i2c_adapter *adap; | 1389 | struct i2c_adapter *adap; |
| 1390 | struct soc_camera_subdev_desc *ssdd; | ||
| 1373 | 1391 | ||
| 1374 | icd->control = NULL; | 1392 | icd->control = NULL; |
| 1375 | if (icd->sasc) | 1393 | if (icd->sasc) |
| 1376 | return; | 1394 | return; |
| 1377 | 1395 | ||
| 1378 | adap = client->adapter; | 1396 | adap = client->adapter; |
| 1397 | ssdd = client->dev.platform_data; | ||
| 1379 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); | 1398 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); |
| 1380 | i2c_unregister_device(client); | 1399 | i2c_unregister_device(client); |
| 1381 | i2c_put_adapter(adap); | 1400 | i2c_put_adapter(adap); |
| 1401 | kfree(ssdd); | ||
| 1382 | v4l2_clk_unregister(icd->clk); | 1402 | v4l2_clk_unregister(icd->clk); |
| 1383 | icd->clk = NULL; | 1403 | icd->clk = NULL; |
| 1384 | } | 1404 | } |
| @@ -1466,7 +1486,8 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
| 1466 | struct soc_camera_device *icd; | 1486 | struct soc_camera_device *icd; |
| 1467 | struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; | 1487 | struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; |
| 1468 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; | 1488 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; |
| 1469 | int ret, i; | 1489 | unsigned int i; |
| 1490 | int ret; | ||
| 1470 | 1491 | ||
| 1471 | /* First look for a sensor */ | 1492 | /* First look for a sensor */ |
| 1472 | for (i = 0; i < size; i++) { | 1493 | for (i = 0; i < size; i++) { |
| @@ -1475,7 +1496,7 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
| 1475 | break; | 1496 | break; |
| 1476 | } | 1497 | } |
| 1477 | 1498 | ||
| 1478 | if (i == size || asd[i]->bus_type != V4L2_ASYNC_BUS_I2C) { | 1499 | if (i >= size || asd[i]->match_type != V4L2_ASYNC_MATCH_I2C) { |
| 1479 | /* All useless */ | 1500 | /* All useless */ |
| 1480 | dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); | 1501 | dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); |
| 1481 | return -ENODEV; | 1502 | return -ENODEV; |
| @@ -1501,7 +1522,7 @@ static int scan_async_group(struct soc_camera_host *ici, | |||
| 1501 | return -ENOMEM; | 1522 | return -ENOMEM; |
| 1502 | } | 1523 | } |
| 1503 | 1524 | ||
| 1504 | sasc->notifier.subdev = asd; | 1525 | sasc->notifier.subdevs = asd; |
| 1505 | sasc->notifier.num_subdevs = size; | 1526 | sasc->notifier.num_subdevs = size; |
| 1506 | sasc->notifier.bound = soc_camera_async_bound; | 1527 | sasc->notifier.bound = soc_camera_async_bound; |
| 1507 | sasc->notifier.unbind = soc_camera_async_unbind; | 1528 | sasc->notifier.unbind = soc_camera_async_unbind; |
| @@ -1994,9 +2015,10 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) | |||
| 1994 | 2015 | ||
| 1995 | /* | 2016 | /* |
| 1996 | * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below | 2017 | * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below |
| 1997 | * regulator allocation is a dummy. They will be really requested later | 2018 | * regulator allocation is a dummy. They are actually requested by the |
| 1998 | * in soc_camera_async_bind(). Also note, that in that case regulators | 2019 | * subdevice driver, using soc_camera_power_init(). Also note, that in |
| 1999 | * are attached to the I2C device and not to the camera platform device. | 2020 | * that case regulators are attached to the I2C device and not to the |
| 2021 | * camera platform device. | ||
| 2000 | */ | 2022 | */ |
| 2001 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, | 2023 | ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, |
| 2002 | ssdd->regulators); | 2024 | ssdd->regulators); |
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile new file mode 100644 index 000000000000..4da226169e15 --- /dev/null +++ b/drivers/media/platform/vsp1/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o | ||
| 2 | vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o | ||
| 3 | vsp1-y += vsp1_lif.o vsp1_uds.o | ||
| 4 | |||
| 5 | obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o | ||
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h new file mode 100644 index 000000000000..d6c6ecd039ff --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1.h | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | /* | ||
| 2 | * vsp1.h -- R-Car VSP1 Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_H__ | ||
| 14 | #define __VSP1_H__ | ||
| 15 | |||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/list.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/platform_data/vsp1.h> | ||
| 20 | |||
| 21 | #include <media/media-device.h> | ||
| 22 | #include <media/v4l2-device.h> | ||
| 23 | #include <media/v4l2-subdev.h> | ||
| 24 | |||
| 25 | #include "vsp1_regs.h" | ||
| 26 | |||
| 27 | struct clk; | ||
| 28 | struct device; | ||
| 29 | |||
| 30 | struct vsp1_platform_data; | ||
| 31 | struct vsp1_lif; | ||
| 32 | struct vsp1_rwpf; | ||
| 33 | struct vsp1_uds; | ||
| 34 | |||
| 35 | #define VPS1_MAX_RPF 5 | ||
| 36 | #define VPS1_MAX_UDS 3 | ||
| 37 | #define VPS1_MAX_WPF 4 | ||
| 38 | |||
| 39 | struct vsp1_device { | ||
| 40 | struct device *dev; | ||
| 41 | struct vsp1_platform_data *pdata; | ||
| 42 | |||
| 43 | void __iomem *mmio; | ||
| 44 | struct clk *clock; | ||
| 45 | struct clk *rt_clock; | ||
| 46 | |||
| 47 | struct mutex lock; | ||
| 48 | int ref_count; | ||
| 49 | |||
| 50 | struct vsp1_lif *lif; | ||
| 51 | struct vsp1_rwpf *rpf[VPS1_MAX_RPF]; | ||
| 52 | struct vsp1_uds *uds[VPS1_MAX_UDS]; | ||
| 53 | struct vsp1_rwpf *wpf[VPS1_MAX_WPF]; | ||
| 54 | |||
| 55 | struct list_head entities; | ||
| 56 | |||
| 57 | struct v4l2_device v4l2_dev; | ||
| 58 | struct media_device media_dev; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1); | ||
| 62 | void vsp1_device_put(struct vsp1_device *vsp1); | ||
| 63 | |||
| 64 | static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg) | ||
| 65 | { | ||
| 66 | return ioread32(vsp1->mmio + reg); | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data) | ||
| 70 | { | ||
| 71 | iowrite32(data, vsp1->mmio + reg); | ||
| 72 | } | ||
| 73 | |||
| 74 | #endif /* __VSP1_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c new file mode 100644 index 000000000000..1c9e771aa15c --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_drv.c | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_drv.c -- R-Car VSP1 Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/videodev2.h> | ||
| 21 | |||
| 22 | #include "vsp1.h" | ||
| 23 | #include "vsp1_lif.h" | ||
| 24 | #include "vsp1_rwpf.h" | ||
| 25 | #include "vsp1_uds.h" | ||
| 26 | |||
| 27 | /* ----------------------------------------------------------------------------- | ||
| 28 | * Interrupt Handling | ||
| 29 | */ | ||
| 30 | |||
| 31 | static irqreturn_t vsp1_irq_handler(int irq, void *data) | ||
| 32 | { | ||
| 33 | u32 mask = VI6_WFP_IRQ_STA_DFE | VI6_WFP_IRQ_STA_FRE; | ||
| 34 | struct vsp1_device *vsp1 = data; | ||
| 35 | irqreturn_t ret = IRQ_NONE; | ||
| 36 | unsigned int i; | ||
| 37 | |||
| 38 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
| 39 | struct vsp1_rwpf *wpf = vsp1->wpf[i]; | ||
| 40 | struct vsp1_pipeline *pipe; | ||
| 41 | u32 status; | ||
| 42 | |||
| 43 | if (wpf == NULL) | ||
| 44 | continue; | ||
| 45 | |||
| 46 | pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); | ||
| 47 | status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i)); | ||
| 48 | vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask); | ||
| 49 | |||
| 50 | if (status & VI6_WFP_IRQ_STA_FRE) { | ||
| 51 | vsp1_pipeline_frame_end(pipe); | ||
| 52 | ret = IRQ_HANDLED; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* ----------------------------------------------------------------------------- | ||
| 60 | * Entities | ||
| 61 | */ | ||
| 62 | |||
| 63 | /* | ||
| 64 | * vsp1_create_links - Create links from all sources to the given sink | ||
| 65 | * | ||
| 66 | * This function creates media links from all valid sources to the given sink | ||
| 67 | * pad. Links that would be invalid according to the VSP1 hardware capabilities | ||
| 68 | * are skipped. Those include all links | ||
| 69 | * | ||
| 70 | * - from a UDS to a UDS (UDS entities can't be chained) | ||
| 71 | * - from an entity to itself (no loops are allowed) | ||
| 72 | */ | ||
| 73 | static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink) | ||
| 74 | { | ||
| 75 | struct media_entity *entity = &sink->subdev.entity; | ||
| 76 | struct vsp1_entity *source; | ||
| 77 | unsigned int pad; | ||
| 78 | int ret; | ||
| 79 | |||
| 80 | list_for_each_entry(source, &vsp1->entities, list_dev) { | ||
| 81 | u32 flags; | ||
| 82 | |||
| 83 | if (source->type == sink->type) | ||
| 84 | continue; | ||
| 85 | |||
| 86 | if (source->type == VSP1_ENTITY_LIF || | ||
| 87 | source->type == VSP1_ENTITY_WPF) | ||
| 88 | continue; | ||
| 89 | |||
| 90 | flags = source->type == VSP1_ENTITY_RPF && | ||
| 91 | sink->type == VSP1_ENTITY_WPF && | ||
| 92 | source->index == sink->index | ||
| 93 | ? MEDIA_LNK_FL_ENABLED : 0; | ||
| 94 | |||
| 95 | for (pad = 0; pad < entity->num_pads; ++pad) { | ||
| 96 | if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK)) | ||
| 97 | continue; | ||
| 98 | |||
| 99 | ret = media_entity_create_link(&source->subdev.entity, | ||
| 100 | source->source_pad, | ||
| 101 | entity, pad, flags); | ||
| 102 | if (ret < 0) | ||
| 103 | return ret; | ||
| 104 | |||
| 105 | if (flags & MEDIA_LNK_FL_ENABLED) | ||
| 106 | source->sink = entity; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static void vsp1_destroy_entities(struct vsp1_device *vsp1) | ||
| 114 | { | ||
| 115 | struct vsp1_entity *entity; | ||
| 116 | struct vsp1_entity *next; | ||
| 117 | |||
| 118 | list_for_each_entry_safe(entity, next, &vsp1->entities, list_dev) { | ||
| 119 | list_del(&entity->list_dev); | ||
| 120 | vsp1_entity_destroy(entity); | ||
| 121 | } | ||
| 122 | |||
| 123 | v4l2_device_unregister(&vsp1->v4l2_dev); | ||
| 124 | media_device_unregister(&vsp1->media_dev); | ||
| 125 | } | ||
| 126 | |||
| 127 | static int vsp1_create_entities(struct vsp1_device *vsp1) | ||
| 128 | { | ||
| 129 | struct media_device *mdev = &vsp1->media_dev; | ||
| 130 | struct v4l2_device *vdev = &vsp1->v4l2_dev; | ||
| 131 | struct vsp1_entity *entity; | ||
| 132 | unsigned int i; | ||
| 133 | int ret; | ||
| 134 | |||
| 135 | mdev->dev = vsp1->dev; | ||
| 136 | strlcpy(mdev->model, "VSP1", sizeof(mdev->model)); | ||
| 137 | snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", | ||
| 138 | dev_name(mdev->dev)); | ||
| 139 | ret = media_device_register(mdev); | ||
| 140 | if (ret < 0) { | ||
| 141 | dev_err(vsp1->dev, "media device registration failed (%d)\n", | ||
| 142 | ret); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | vdev->mdev = mdev; | ||
| 147 | ret = v4l2_device_register(vsp1->dev, vdev); | ||
| 148 | if (ret < 0) { | ||
| 149 | dev_err(vsp1->dev, "V4L2 device registration failed (%d)\n", | ||
| 150 | ret); | ||
| 151 | goto done; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* Instantiate all the entities. */ | ||
| 155 | if (vsp1->pdata->features & VSP1_HAS_LIF) { | ||
| 156 | vsp1->lif = vsp1_lif_create(vsp1); | ||
| 157 | if (IS_ERR(vsp1->lif)) { | ||
| 158 | ret = PTR_ERR(vsp1->lif); | ||
| 159 | goto done; | ||
| 160 | } | ||
| 161 | |||
| 162 | list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities); | ||
| 163 | } | ||
| 164 | |||
| 165 | for (i = 0; i < vsp1->pdata->rpf_count; ++i) { | ||
| 166 | struct vsp1_rwpf *rpf; | ||
| 167 | |||
| 168 | rpf = vsp1_rpf_create(vsp1, i); | ||
| 169 | if (IS_ERR(rpf)) { | ||
| 170 | ret = PTR_ERR(rpf); | ||
| 171 | goto done; | ||
| 172 | } | ||
| 173 | |||
| 174 | vsp1->rpf[i] = rpf; | ||
| 175 | list_add_tail(&rpf->entity.list_dev, &vsp1->entities); | ||
| 176 | } | ||
| 177 | |||
| 178 | for (i = 0; i < vsp1->pdata->uds_count; ++i) { | ||
| 179 | struct vsp1_uds *uds; | ||
| 180 | |||
| 181 | uds = vsp1_uds_create(vsp1, i); | ||
| 182 | if (IS_ERR(uds)) { | ||
| 183 | ret = PTR_ERR(uds); | ||
| 184 | goto done; | ||
| 185 | } | ||
| 186 | |||
| 187 | vsp1->uds[i] = uds; | ||
| 188 | list_add_tail(&uds->entity.list_dev, &vsp1->entities); | ||
| 189 | } | ||
| 190 | |||
| 191 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
| 192 | struct vsp1_rwpf *wpf; | ||
| 193 | |||
| 194 | wpf = vsp1_wpf_create(vsp1, i); | ||
| 195 | if (IS_ERR(wpf)) { | ||
| 196 | ret = PTR_ERR(wpf); | ||
| 197 | goto done; | ||
| 198 | } | ||
| 199 | |||
| 200 | vsp1->wpf[i] = wpf; | ||
| 201 | list_add_tail(&wpf->entity.list_dev, &vsp1->entities); | ||
| 202 | } | ||
| 203 | |||
| 204 | /* Create links. */ | ||
| 205 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
| 206 | if (entity->type == VSP1_ENTITY_LIF || | ||
| 207 | entity->type == VSP1_ENTITY_RPF) | ||
| 208 | continue; | ||
| 209 | |||
| 210 | ret = vsp1_create_links(vsp1, entity); | ||
| 211 | if (ret < 0) | ||
| 212 | goto done; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (vsp1->pdata->features & VSP1_HAS_LIF) { | ||
| 216 | ret = media_entity_create_link( | ||
| 217 | &vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE, | ||
| 218 | &vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0); | ||
| 219 | if (ret < 0) | ||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* Register all subdevs. */ | ||
| 224 | list_for_each_entry(entity, &vsp1->entities, list_dev) { | ||
| 225 | ret = v4l2_device_register_subdev(&vsp1->v4l2_dev, | ||
| 226 | &entity->subdev); | ||
| 227 | if (ret < 0) | ||
| 228 | goto done; | ||
| 229 | } | ||
| 230 | |||
| 231 | ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); | ||
| 232 | |||
| 233 | done: | ||
| 234 | if (ret < 0) | ||
| 235 | vsp1_destroy_entities(vsp1); | ||
| 236 | |||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int vsp1_device_init(struct vsp1_device *vsp1) | ||
| 241 | { | ||
| 242 | unsigned int i; | ||
| 243 | u32 status; | ||
| 244 | |||
| 245 | /* Reset any channel that might be running. */ | ||
| 246 | status = vsp1_read(vsp1, VI6_STATUS); | ||
| 247 | |||
| 248 | for (i = 0; i < vsp1->pdata->wpf_count; ++i) { | ||
| 249 | unsigned int timeout; | ||
| 250 | |||
| 251 | if (!(status & VI6_STATUS_SYS_ACT(i))) | ||
| 252 | continue; | ||
| 253 | |||
| 254 | vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(i)); | ||
| 255 | for (timeout = 10; timeout > 0; --timeout) { | ||
| 256 | status = vsp1_read(vsp1, VI6_STATUS); | ||
| 257 | if (!(status & VI6_STATUS_SYS_ACT(i))) | ||
| 258 | break; | ||
| 259 | |||
| 260 | usleep_range(1000, 2000); | ||
| 261 | } | ||
| 262 | |||
| 263 | if (!timeout) { | ||
| 264 | dev_err(vsp1->dev, "failed to reset wpf.%u\n", i); | ||
| 265 | return -ETIMEDOUT; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) | | ||
| 270 | (8 << VI6_CLK_DCSWT_CSTRW_SHIFT)); | ||
| 271 | |||
| 272 | for (i = 0; i < vsp1->pdata->rpf_count; ++i) | ||
| 273 | vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED); | ||
| 274 | |||
| 275 | for (i = 0; i < vsp1->pdata->uds_count; ++i) | ||
| 276 | vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED); | ||
| 277 | |||
| 278 | vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 279 | vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 280 | vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 281 | vsp1_write(vsp1, VI6_DPR_HST_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 282 | vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 283 | vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED); | ||
| 284 | |||
| 285 | vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | | ||
| 286 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); | ||
| 287 | vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | | ||
| 288 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); | ||
| 289 | |||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | static int vsp1_clocks_enable(struct vsp1_device *vsp1) | ||
| 294 | { | ||
| 295 | int ret; | ||
| 296 | |||
| 297 | ret = clk_prepare_enable(vsp1->clock); | ||
| 298 | if (ret < 0) | ||
| 299 | return ret; | ||
| 300 | |||
| 301 | if (IS_ERR(vsp1->rt_clock)) | ||
| 302 | return 0; | ||
| 303 | |||
| 304 | ret = clk_prepare_enable(vsp1->rt_clock); | ||
| 305 | if (ret < 0) { | ||
| 306 | clk_disable_unprepare(vsp1->clock); | ||
| 307 | return ret; | ||
| 308 | } | ||
| 309 | |||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static void vsp1_clocks_disable(struct vsp1_device *vsp1) | ||
| 314 | { | ||
| 315 | if (!IS_ERR(vsp1->rt_clock)) | ||
| 316 | clk_disable_unprepare(vsp1->rt_clock); | ||
| 317 | clk_disable_unprepare(vsp1->clock); | ||
| 318 | } | ||
| 319 | |||
| 320 | /* | ||
| 321 | * vsp1_device_get - Acquire the VSP1 device | ||
| 322 | * | ||
| 323 | * Increment the VSP1 reference count and initialize the device if the first | ||
| 324 | * reference is taken. | ||
| 325 | * | ||
| 326 | * Return a pointer to the VSP1 device or NULL if an error occured. | ||
| 327 | */ | ||
| 328 | struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) | ||
| 329 | { | ||
| 330 | struct vsp1_device *__vsp1 = vsp1; | ||
| 331 | int ret; | ||
| 332 | |||
| 333 | mutex_lock(&vsp1->lock); | ||
| 334 | if (vsp1->ref_count > 0) | ||
| 335 | goto done; | ||
| 336 | |||
| 337 | ret = vsp1_clocks_enable(vsp1); | ||
| 338 | if (ret < 0) { | ||
| 339 | __vsp1 = NULL; | ||
| 340 | goto done; | ||
| 341 | } | ||
| 342 | |||
| 343 | ret = vsp1_device_init(vsp1); | ||
| 344 | if (ret < 0) { | ||
| 345 | vsp1_clocks_disable(vsp1); | ||
| 346 | __vsp1 = NULL; | ||
| 347 | goto done; | ||
| 348 | } | ||
| 349 | |||
| 350 | done: | ||
| 351 | if (__vsp1) | ||
| 352 | vsp1->ref_count++; | ||
| 353 | |||
| 354 | mutex_unlock(&vsp1->lock); | ||
| 355 | return __vsp1; | ||
| 356 | } | ||
| 357 | |||
| 358 | /* | ||
| 359 | * vsp1_device_put - Release the VSP1 device | ||
| 360 | * | ||
| 361 | * Decrement the VSP1 reference count and cleanup the device if the last | ||
| 362 | * reference is released. | ||
| 363 | */ | ||
| 364 | void vsp1_device_put(struct vsp1_device *vsp1) | ||
| 365 | { | ||
| 366 | mutex_lock(&vsp1->lock); | ||
| 367 | |||
| 368 | if (--vsp1->ref_count == 0) | ||
| 369 | vsp1_clocks_disable(vsp1); | ||
| 370 | |||
| 371 | mutex_unlock(&vsp1->lock); | ||
| 372 | } | ||
| 373 | |||
| 374 | /* ----------------------------------------------------------------------------- | ||
| 375 | * Power Management | ||
| 376 | */ | ||
| 377 | |||
| 378 | #ifdef CONFIG_PM_SLEEP | ||
| 379 | static int vsp1_pm_suspend(struct device *dev) | ||
| 380 | { | ||
| 381 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); | ||
| 382 | |||
| 383 | WARN_ON(mutex_is_locked(&vsp1->lock)); | ||
| 384 | |||
| 385 | if (vsp1->ref_count == 0) | ||
| 386 | return 0; | ||
| 387 | |||
| 388 | vsp1_clocks_disable(vsp1); | ||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static int vsp1_pm_resume(struct device *dev) | ||
| 393 | { | ||
| 394 | struct vsp1_device *vsp1 = dev_get_drvdata(dev); | ||
| 395 | |||
| 396 | WARN_ON(mutex_is_locked(&vsp1->lock)); | ||
| 397 | |||
| 398 | if (vsp1->ref_count) | ||
| 399 | return 0; | ||
| 400 | |||
| 401 | return vsp1_clocks_enable(vsp1); | ||
| 402 | } | ||
| 403 | #endif | ||
| 404 | |||
| 405 | static const struct dev_pm_ops vsp1_pm_ops = { | ||
| 406 | SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume) | ||
| 407 | }; | ||
| 408 | |||
| 409 | /* ----------------------------------------------------------------------------- | ||
| 410 | * Platform Driver | ||
| 411 | */ | ||
| 412 | |||
| 413 | static struct vsp1_platform_data * | ||
| 414 | vsp1_get_platform_data(struct platform_device *pdev) | ||
| 415 | { | ||
| 416 | struct vsp1_platform_data *pdata = pdev->dev.platform_data; | ||
| 417 | |||
| 418 | if (pdata == NULL) { | ||
| 419 | dev_err(&pdev->dev, "missing platform data\n"); | ||
| 420 | return NULL; | ||
| 421 | } | ||
| 422 | |||
| 423 | if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) { | ||
| 424 | dev_err(&pdev->dev, "invalid number of RPF (%u)\n", | ||
| 425 | pdata->rpf_count); | ||
| 426 | return NULL; | ||
| 427 | } | ||
| 428 | |||
| 429 | if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) { | ||
| 430 | dev_err(&pdev->dev, "invalid number of UDS (%u)\n", | ||
| 431 | pdata->uds_count); | ||
| 432 | return NULL; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) { | ||
| 436 | dev_err(&pdev->dev, "invalid number of WPF (%u)\n", | ||
| 437 | pdata->wpf_count); | ||
| 438 | return NULL; | ||
| 439 | } | ||
| 440 | |||
| 441 | return pdata; | ||
| 442 | } | ||
| 443 | |||
| 444 | static int vsp1_probe(struct platform_device *pdev) | ||
| 445 | { | ||
| 446 | struct vsp1_device *vsp1; | ||
| 447 | struct resource *irq; | ||
| 448 | struct resource *io; | ||
| 449 | int ret; | ||
| 450 | |||
| 451 | vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL); | ||
| 452 | if (vsp1 == NULL) | ||
| 453 | return -ENOMEM; | ||
| 454 | |||
| 455 | vsp1->dev = &pdev->dev; | ||
| 456 | mutex_init(&vsp1->lock); | ||
| 457 | INIT_LIST_HEAD(&vsp1->entities); | ||
| 458 | |||
| 459 | vsp1->pdata = vsp1_get_platform_data(pdev); | ||
| 460 | if (vsp1->pdata == NULL) | ||
| 461 | return -ENODEV; | ||
| 462 | |||
| 463 | /* I/O, IRQ and clock resources */ | ||
| 464 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 465 | vsp1->mmio = devm_ioremap_resource(&pdev->dev, io); | ||
| 466 | if (IS_ERR(vsp1->mmio)) | ||
| 467 | return PTR_ERR(vsp1->mmio); | ||
| 468 | |||
| 469 | vsp1->clock = devm_clk_get(&pdev->dev, NULL); | ||
| 470 | if (IS_ERR(vsp1->clock)) { | ||
| 471 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
| 472 | return PTR_ERR(vsp1->clock); | ||
| 473 | } | ||
| 474 | |||
| 475 | /* The RT clock is optional */ | ||
| 476 | vsp1->rt_clock = devm_clk_get(&pdev->dev, "rt"); | ||
| 477 | |||
| 478 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 479 | if (!irq) { | ||
| 480 | dev_err(&pdev->dev, "missing IRQ\n"); | ||
| 481 | return -EINVAL; | ||
| 482 | } | ||
| 483 | |||
| 484 | ret = devm_request_irq(&pdev->dev, irq->start, vsp1_irq_handler, | ||
| 485 | IRQF_SHARED, dev_name(&pdev->dev), vsp1); | ||
| 486 | if (ret < 0) { | ||
| 487 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 488 | return ret; | ||
| 489 | } | ||
| 490 | |||
| 491 | /* Instanciate entities */ | ||
| 492 | ret = vsp1_create_entities(vsp1); | ||
| 493 | if (ret < 0) { | ||
| 494 | dev_err(&pdev->dev, "failed to create entities\n"); | ||
| 495 | return ret; | ||
| 496 | } | ||
| 497 | |||
| 498 | platform_set_drvdata(pdev, vsp1); | ||
| 499 | |||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | static int vsp1_remove(struct platform_device *pdev) | ||
| 504 | { | ||
| 505 | struct vsp1_device *vsp1 = platform_get_drvdata(pdev); | ||
| 506 | |||
| 507 | vsp1_destroy_entities(vsp1); | ||
| 508 | |||
| 509 | return 0; | ||
| 510 | } | ||
| 511 | |||
| 512 | static struct platform_driver vsp1_platform_driver = { | ||
| 513 | .probe = vsp1_probe, | ||
| 514 | .remove = vsp1_remove, | ||
| 515 | .driver = { | ||
| 516 | .owner = THIS_MODULE, | ||
| 517 | .name = "vsp1", | ||
| 518 | .pm = &vsp1_pm_ops, | ||
| 519 | }, | ||
| 520 | }; | ||
| 521 | |||
| 522 | module_platform_driver(vsp1_platform_driver); | ||
| 523 | |||
| 524 | MODULE_ALIAS("vsp1"); | ||
| 525 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
| 526 | MODULE_DESCRIPTION("Renesas VSP1 Driver"); | ||
| 527 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c new file mode 100644 index 000000000000..9028f9d524f4 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_entity.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_entity.c -- R-Car VSP1 Base Entity | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/gfp.h> | ||
| 16 | |||
| 17 | #include <media/media-entity.h> | ||
| 18 | #include <media/v4l2-subdev.h> | ||
| 19 | |||
| 20 | #include "vsp1.h" | ||
| 21 | #include "vsp1_entity.h" | ||
| 22 | |||
| 23 | /* ----------------------------------------------------------------------------- | ||
| 24 | * V4L2 Subdevice Operations | ||
| 25 | */ | ||
| 26 | |||
| 27 | struct v4l2_mbus_framefmt * | ||
| 28 | vsp1_entity_get_pad_format(struct vsp1_entity *entity, | ||
| 29 | struct v4l2_subdev_fh *fh, | ||
| 30 | unsigned int pad, u32 which) | ||
| 31 | { | ||
| 32 | switch (which) { | ||
| 33 | case V4L2_SUBDEV_FORMAT_TRY: | ||
| 34 | return v4l2_subdev_get_try_format(fh, pad); | ||
| 35 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
| 36 | return &entity->formats[pad]; | ||
| 37 | default: | ||
| 38 | return NULL; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | /* | ||
| 43 | * vsp1_entity_init_formats - Initialize formats on all pads | ||
| 44 | * @subdev: V4L2 subdevice | ||
| 45 | * @fh: V4L2 subdev file handle | ||
| 46 | * | ||
| 47 | * Initialize all pad formats with default values. If fh is not NULL, try | ||
| 48 | * formats are initialized on the file handle. Otherwise active formats are | ||
| 49 | * initialized on the device. | ||
| 50 | */ | ||
| 51 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, | ||
| 52 | struct v4l2_subdev_fh *fh) | ||
| 53 | { | ||
| 54 | struct v4l2_subdev_format format; | ||
| 55 | unsigned int pad; | ||
| 56 | |||
| 57 | for (pad = 0; pad < subdev->entity.num_pads - 1; ++pad) { | ||
| 58 | memset(&format, 0, sizeof(format)); | ||
| 59 | |||
| 60 | format.pad = pad; | ||
| 61 | format.which = fh ? V4L2_SUBDEV_FORMAT_TRY | ||
| 62 | : V4L2_SUBDEV_FORMAT_ACTIVE; | ||
| 63 | |||
| 64 | v4l2_subdev_call(subdev, pad, set_fmt, fh, &format); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | static int vsp1_entity_open(struct v4l2_subdev *subdev, | ||
| 69 | struct v4l2_subdev_fh *fh) | ||
| 70 | { | ||
| 71 | vsp1_entity_init_formats(subdev, fh); | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = { | ||
| 77 | .open = vsp1_entity_open, | ||
| 78 | }; | ||
| 79 | |||
| 80 | /* ----------------------------------------------------------------------------- | ||
| 81 | * Media Operations | ||
| 82 | */ | ||
| 83 | |||
| 84 | static int vsp1_entity_link_setup(struct media_entity *entity, | ||
| 85 | const struct media_pad *local, | ||
| 86 | const struct media_pad *remote, u32 flags) | ||
| 87 | { | ||
| 88 | struct vsp1_entity *source; | ||
| 89 | |||
| 90 | if (!(local->flags & MEDIA_PAD_FL_SOURCE)) | ||
| 91 | return 0; | ||
| 92 | |||
| 93 | source = container_of(local->entity, struct vsp1_entity, subdev.entity); | ||
| 94 | |||
| 95 | if (!source->route) | ||
| 96 | return 0; | ||
| 97 | |||
| 98 | if (flags & MEDIA_LNK_FL_ENABLED) { | ||
| 99 | if (source->sink) | ||
| 100 | return -EBUSY; | ||
| 101 | source->sink = remote->entity; | ||
| 102 | } else { | ||
| 103 | source->sink = NULL; | ||
| 104 | } | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | const struct media_entity_operations vsp1_media_ops = { | ||
| 110 | .link_setup = vsp1_entity_link_setup, | ||
| 111 | .link_validate = v4l2_subdev_link_validate, | ||
| 112 | }; | ||
| 113 | |||
| 114 | /* ----------------------------------------------------------------------------- | ||
| 115 | * Initialization | ||
| 116 | */ | ||
| 117 | |||
| 118 | int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | ||
| 119 | unsigned int num_pads) | ||
| 120 | { | ||
| 121 | static const struct { | ||
| 122 | unsigned int id; | ||
| 123 | unsigned int reg; | ||
| 124 | } routes[] = { | ||
| 125 | { VI6_DPR_NODE_LIF, 0 }, | ||
| 126 | { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) }, | ||
| 127 | { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) }, | ||
| 128 | { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) }, | ||
| 129 | { VI6_DPR_NODE_RPF(3), VI6_DPR_RPF_ROUTE(3) }, | ||
| 130 | { VI6_DPR_NODE_RPF(4), VI6_DPR_RPF_ROUTE(4) }, | ||
| 131 | { VI6_DPR_NODE_UDS(0), VI6_DPR_UDS_ROUTE(0) }, | ||
| 132 | { VI6_DPR_NODE_UDS(1), VI6_DPR_UDS_ROUTE(1) }, | ||
| 133 | { VI6_DPR_NODE_UDS(2), VI6_DPR_UDS_ROUTE(2) }, | ||
| 134 | { VI6_DPR_NODE_WPF(0), 0 }, | ||
| 135 | { VI6_DPR_NODE_WPF(1), 0 }, | ||
| 136 | { VI6_DPR_NODE_WPF(2), 0 }, | ||
| 137 | { VI6_DPR_NODE_WPF(3), 0 }, | ||
| 138 | }; | ||
| 139 | |||
| 140 | unsigned int i; | ||
| 141 | |||
| 142 | for (i = 0; i < ARRAY_SIZE(routes); ++i) { | ||
| 143 | if (routes[i].id == entity->id) { | ||
| 144 | entity->route = routes[i].reg; | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | if (i == ARRAY_SIZE(routes)) | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | entity->vsp1 = vsp1; | ||
| 153 | entity->source_pad = num_pads - 1; | ||
| 154 | |||
| 155 | /* Allocate formats and pads. */ | ||
| 156 | entity->formats = devm_kzalloc(vsp1->dev, | ||
| 157 | num_pads * sizeof(*entity->formats), | ||
| 158 | GFP_KERNEL); | ||
| 159 | if (entity->formats == NULL) | ||
| 160 | return -ENOMEM; | ||
| 161 | |||
| 162 | entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads), | ||
| 163 | GFP_KERNEL); | ||
| 164 | if (entity->pads == NULL) | ||
| 165 | return -ENOMEM; | ||
| 166 | |||
| 167 | /* Initialize pads. */ | ||
| 168 | for (i = 0; i < num_pads - 1; ++i) | ||
| 169 | entity->pads[i].flags = MEDIA_PAD_FL_SINK; | ||
| 170 | |||
| 171 | entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; | ||
| 172 | |||
| 173 | /* Initialize the media entity. */ | ||
| 174 | return media_entity_init(&entity->subdev.entity, num_pads, | ||
| 175 | entity->pads, 0); | ||
| 176 | } | ||
| 177 | |||
| 178 | void vsp1_entity_destroy(struct vsp1_entity *entity) | ||
| 179 | { | ||
| 180 | media_entity_cleanup(&entity->subdev.entity); | ||
| 181 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h new file mode 100644 index 000000000000..c4feab2cbb81 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_entity.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_entity.h -- R-Car VSP1 Base Entity | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_ENTITY_H__ | ||
| 14 | #define __VSP1_ENTITY_H__ | ||
| 15 | |||
| 16 | #include <linux/list.h> | ||
| 17 | |||
| 18 | #include <media/v4l2-subdev.h> | ||
| 19 | |||
| 20 | struct vsp1_device; | ||
| 21 | |||
| 22 | enum vsp1_entity_type { | ||
| 23 | VSP1_ENTITY_LIF, | ||
| 24 | VSP1_ENTITY_RPF, | ||
| 25 | VSP1_ENTITY_UDS, | ||
| 26 | VSP1_ENTITY_WPF, | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct vsp1_entity { | ||
| 30 | struct vsp1_device *vsp1; | ||
| 31 | |||
| 32 | enum vsp1_entity_type type; | ||
| 33 | unsigned int index; | ||
| 34 | unsigned int id; | ||
| 35 | unsigned int route; | ||
| 36 | |||
| 37 | struct list_head list_dev; | ||
| 38 | struct list_head list_pipe; | ||
| 39 | |||
| 40 | struct media_pad *pads; | ||
| 41 | unsigned int source_pad; | ||
| 42 | |||
| 43 | struct media_entity *sink; | ||
| 44 | |||
| 45 | struct v4l2_subdev subdev; | ||
| 46 | struct v4l2_mbus_framefmt *formats; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) | ||
| 50 | { | ||
| 51 | return container_of(subdev, struct vsp1_entity, subdev); | ||
| 52 | } | ||
| 53 | |||
| 54 | int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, | ||
| 55 | unsigned int num_pads); | ||
| 56 | void vsp1_entity_destroy(struct vsp1_entity *entity); | ||
| 57 | |||
| 58 | extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops; | ||
| 59 | extern const struct media_entity_operations vsp1_media_ops; | ||
| 60 | |||
| 61 | struct v4l2_mbus_framefmt * | ||
| 62 | vsp1_entity_get_pad_format(struct vsp1_entity *entity, | ||
| 63 | struct v4l2_subdev_fh *fh, | ||
| 64 | unsigned int pad, u32 which); | ||
| 65 | void vsp1_entity_init_formats(struct v4l2_subdev *subdev, | ||
| 66 | struct v4l2_subdev_fh *fh); | ||
| 67 | |||
| 68 | #endif /* __VSP1_ENTITY_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c new file mode 100644 index 000000000000..74a32e69ef10 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lif.c | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_lif.c -- R-Car VSP1 LCD Controller Interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/gfp.h> | ||
| 16 | |||
| 17 | #include <media/v4l2-subdev.h> | ||
| 18 | |||
| 19 | #include "vsp1.h" | ||
| 20 | #include "vsp1_lif.h" | ||
| 21 | |||
| 22 | #define LIF_MIN_SIZE 2U | ||
| 23 | #define LIF_MAX_SIZE 2048U | ||
| 24 | |||
| 25 | /* ----------------------------------------------------------------------------- | ||
| 26 | * Device Access | ||
| 27 | */ | ||
| 28 | |||
| 29 | static inline u32 vsp1_lif_read(struct vsp1_lif *lif, u32 reg) | ||
| 30 | { | ||
| 31 | return vsp1_read(lif->entity.vsp1, reg); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) | ||
| 35 | { | ||
| 36 | vsp1_write(lif->entity.vsp1, reg, data); | ||
| 37 | } | ||
| 38 | |||
| 39 | /* ----------------------------------------------------------------------------- | ||
| 40 | * V4L2 Subdevice Core Operations | ||
| 41 | */ | ||
| 42 | |||
| 43 | static int lif_s_stream(struct v4l2_subdev *subdev, int enable) | ||
| 44 | { | ||
| 45 | const struct v4l2_mbus_framefmt *format; | ||
| 46 | struct vsp1_lif *lif = to_lif(subdev); | ||
| 47 | unsigned int hbth = 1300; | ||
| 48 | unsigned int obth = 400; | ||
| 49 | unsigned int lbth = 200; | ||
| 50 | |||
| 51 | if (!enable) { | ||
| 52 | vsp1_lif_write(lif, VI6_LIF_CTRL, 0); | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | format = &lif->entity.formats[LIF_PAD_SOURCE]; | ||
| 57 | |||
| 58 | obth = min(obth, (format->width + 1) / 2 * format->height - 4); | ||
| 59 | |||
| 60 | vsp1_lif_write(lif, VI6_LIF_CSBTH, | ||
| 61 | (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | | ||
| 62 | (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); | ||
| 63 | |||
| 64 | vsp1_lif_write(lif, VI6_LIF_CTRL, | ||
| 65 | (obth << VI6_LIF_CTRL_OBTH_SHIFT) | | ||
| 66 | (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | | ||
| 67 | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* ----------------------------------------------------------------------------- | ||
| 73 | * V4L2 Subdevice Pad Operations | ||
| 74 | */ | ||
| 75 | |||
| 76 | static int lif_enum_mbus_code(struct v4l2_subdev *subdev, | ||
| 77 | struct v4l2_subdev_fh *fh, | ||
| 78 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 79 | { | ||
| 80 | static const unsigned int codes[] = { | ||
| 81 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 82 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 83 | }; | ||
| 84 | |||
| 85 | if (code->pad == LIF_PAD_SINK) { | ||
| 86 | if (code->index >= ARRAY_SIZE(codes)) | ||
| 87 | return -EINVAL; | ||
| 88 | |||
| 89 | code->code = codes[code->index]; | ||
| 90 | } else { | ||
| 91 | struct v4l2_mbus_framefmt *format; | ||
| 92 | |||
| 93 | /* The LIF can't perform format conversion, the sink format is | ||
| 94 | * always identical to the source format. | ||
| 95 | */ | ||
| 96 | if (code->index) | ||
| 97 | return -EINVAL; | ||
| 98 | |||
| 99 | format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK); | ||
| 100 | code->code = format->code; | ||
| 101 | } | ||
| 102 | |||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int lif_enum_frame_size(struct v4l2_subdev *subdev, | ||
| 107 | struct v4l2_subdev_fh *fh, | ||
| 108 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 109 | { | ||
| 110 | struct v4l2_mbus_framefmt *format; | ||
| 111 | |||
| 112 | format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK); | ||
| 113 | |||
| 114 | if (fse->index || fse->code != format->code) | ||
| 115 | return -EINVAL; | ||
| 116 | |||
| 117 | if (fse->pad == LIF_PAD_SINK) { | ||
| 118 | fse->min_width = LIF_MIN_SIZE; | ||
| 119 | fse->max_width = LIF_MAX_SIZE; | ||
| 120 | fse->min_height = LIF_MIN_SIZE; | ||
| 121 | fse->max_height = LIF_MAX_SIZE; | ||
| 122 | } else { | ||
| 123 | fse->min_width = format->width; | ||
| 124 | fse->max_width = format->width; | ||
| 125 | fse->min_height = format->height; | ||
| 126 | fse->max_height = format->height; | ||
| 127 | } | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 133 | struct v4l2_subdev_format *fmt) | ||
| 134 | { | ||
| 135 | struct vsp1_lif *lif = to_lif(subdev); | ||
| 136 | |||
| 137 | fmt->format = *vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad, | ||
| 138 | fmt->which); | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 144 | struct v4l2_subdev_format *fmt) | ||
| 145 | { | ||
| 146 | struct vsp1_lif *lif = to_lif(subdev); | ||
| 147 | struct v4l2_mbus_framefmt *format; | ||
| 148 | |||
| 149 | /* Default to YUV if the requested format is not supported. */ | ||
| 150 | if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
| 151 | fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
| 152 | fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
| 153 | |||
| 154 | format = vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad, | ||
| 155 | fmt->which); | ||
| 156 | |||
| 157 | if (fmt->pad == LIF_PAD_SOURCE) { | ||
| 158 | /* The LIF source format is always identical to its sink | ||
| 159 | * format. | ||
| 160 | */ | ||
| 161 | fmt->format = *format; | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | format->code = fmt->format.code; | ||
| 166 | format->width = clamp_t(unsigned int, fmt->format.width, | ||
| 167 | LIF_MIN_SIZE, LIF_MAX_SIZE); | ||
| 168 | format->height = clamp_t(unsigned int, fmt->format.height, | ||
| 169 | LIF_MIN_SIZE, LIF_MAX_SIZE); | ||
| 170 | format->field = V4L2_FIELD_NONE; | ||
| 171 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 172 | |||
| 173 | fmt->format = *format; | ||
| 174 | |||
| 175 | /* Propagate the format to the source pad. */ | ||
| 176 | format = vsp1_entity_get_pad_format(&lif->entity, fh, LIF_PAD_SOURCE, | ||
| 177 | fmt->which); | ||
| 178 | *format = fmt->format; | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | /* ----------------------------------------------------------------------------- | ||
| 184 | * V4L2 Subdevice Operations | ||
| 185 | */ | ||
| 186 | |||
| 187 | static struct v4l2_subdev_video_ops lif_video_ops = { | ||
| 188 | .s_stream = lif_s_stream, | ||
| 189 | }; | ||
| 190 | |||
| 191 | static struct v4l2_subdev_pad_ops lif_pad_ops = { | ||
| 192 | .enum_mbus_code = lif_enum_mbus_code, | ||
| 193 | .enum_frame_size = lif_enum_frame_size, | ||
| 194 | .get_fmt = lif_get_format, | ||
| 195 | .set_fmt = lif_set_format, | ||
| 196 | }; | ||
| 197 | |||
| 198 | static struct v4l2_subdev_ops lif_ops = { | ||
| 199 | .video = &lif_video_ops, | ||
| 200 | .pad = &lif_pad_ops, | ||
| 201 | }; | ||
| 202 | |||
| 203 | /* ----------------------------------------------------------------------------- | ||
| 204 | * Initialization and Cleanup | ||
| 205 | */ | ||
| 206 | |||
| 207 | struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) | ||
| 208 | { | ||
| 209 | struct v4l2_subdev *subdev; | ||
| 210 | struct vsp1_lif *lif; | ||
| 211 | int ret; | ||
| 212 | |||
| 213 | lif = devm_kzalloc(vsp1->dev, sizeof(*lif), GFP_KERNEL); | ||
| 214 | if (lif == NULL) | ||
| 215 | return ERR_PTR(-ENOMEM); | ||
| 216 | |||
| 217 | lif->entity.type = VSP1_ENTITY_LIF; | ||
| 218 | lif->entity.id = VI6_DPR_NODE_LIF; | ||
| 219 | |||
| 220 | ret = vsp1_entity_init(vsp1, &lif->entity, 2); | ||
| 221 | if (ret < 0) | ||
| 222 | return ERR_PTR(ret); | ||
| 223 | |||
| 224 | /* Initialize the V4L2 subdev. */ | ||
| 225 | subdev = &lif->entity.subdev; | ||
| 226 | v4l2_subdev_init(subdev, &lif_ops); | ||
| 227 | |||
| 228 | subdev->entity.ops = &vsp1_media_ops; | ||
| 229 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
| 230 | snprintf(subdev->name, sizeof(subdev->name), "%s lif", | ||
| 231 | dev_name(vsp1->dev)); | ||
| 232 | v4l2_set_subdevdata(subdev, lif); | ||
| 233 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 234 | |||
| 235 | vsp1_entity_init_formats(subdev, NULL); | ||
| 236 | |||
| 237 | return lif; | ||
| 238 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_lif.h b/drivers/media/platform/vsp1/vsp1_lif.h new file mode 100644 index 000000000000..89b93af56fdc --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_lif.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_lif.h -- R-Car VSP1 LCD Controller Interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_LIF_H__ | ||
| 14 | #define __VSP1_LIF_H__ | ||
| 15 | |||
| 16 | #include <media/media-entity.h> | ||
| 17 | #include <media/v4l2-subdev.h> | ||
| 18 | |||
| 19 | #include "vsp1_entity.h" | ||
| 20 | |||
| 21 | struct vsp1_device; | ||
| 22 | |||
| 23 | #define LIF_PAD_SINK 0 | ||
| 24 | #define LIF_PAD_SOURCE 1 | ||
| 25 | |||
| 26 | struct vsp1_lif { | ||
| 27 | struct vsp1_entity entity; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static inline struct vsp1_lif *to_lif(struct v4l2_subdev *subdev) | ||
| 31 | { | ||
| 32 | return container_of(subdev, struct vsp1_lif, entity.subdev); | ||
| 33 | } | ||
| 34 | |||
| 35 | struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1); | ||
| 36 | |||
| 37 | #endif /* __VSP1_LIF_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h new file mode 100644 index 000000000000..1d3304f1365b --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_regs.h | |||
| @@ -0,0 +1,581 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_regs.h -- R-Car VSP1 Registers Definitions | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Electronics Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 | ||
| 10 | * as published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __VSP1_REGS_H__ | ||
| 14 | #define __VSP1_REGS_H__ | ||
| 15 | |||
| 16 | /* ----------------------------------------------------------------------------- | ||
| 17 | * General Control Registers | ||
| 18 | */ | ||
| 19 | |||
| 20 | #define VI6_CMD(n) (0x0000 + (n) * 4) | ||
| 21 | #define VI6_CMD_STRCMD (1 << 0) | ||
| 22 | |||
| 23 | #define VI6_CLK_DCSWT 0x0018 | ||
| 24 | #define VI6_CLK_DCSWT_CSTPW_MASK (0xff << 8) | ||
| 25 | #define VI6_CLK_DCSWT_CSTPW_SHIFT 8 | ||
| 26 | #define VI6_CLK_DCSWT_CSTRW_MASK (0xff << 0) | ||
| 27 | #define VI6_CLK_DCSWT_CSTRW_SHIFT 0 | ||
| 28 | |||
| 29 | #define VI6_SRESET 0x0028 | ||
| 30 | #define VI6_SRESET_SRTS(n) (1 << (n)) | ||
| 31 | |||
| 32 | #define VI6_STATUS 0x0038 | ||
| 33 | #define VI6_STATUS_SYS_ACT(n) (1 << ((n) + 8)) | ||
| 34 | |||
| 35 | #define VI6_WPF_IRQ_ENB(n) (0x0048 + (n) * 12) | ||
| 36 | #define VI6_WFP_IRQ_ENB_DFEE (1 << 1) | ||
| 37 | #define VI6_WFP_IRQ_ENB_FREE (1 << 0) | ||
| 38 | |||
| 39 | #define VI6_WPF_IRQ_STA(n) (0x004c + (n) * 12) | ||
| 40 | #define VI6_WFP_IRQ_STA_DFE (1 << 1) | ||
| 41 | #define VI6_WFP_IRQ_STA_FRE (1 << 0) | ||
| 42 | |||
| 43 | #define VI6_DISP_IRQ_ENB 0x0078 | ||
| 44 | #define VI6_DISP_IRQ_ENB_DSTE (1 << 8) | ||
| 45 | #define VI6_DISP_IRQ_ENB_MAEE (1 << 5) | ||
| 46 | #define VI6_DISP_IRQ_ENB_LNEE(n) (1 << ((n) + 4)) | ||
| 47 | |||
| 48 | #define VI6_DISP_IRQ_STA 0x007c | ||
| 49 | #define VI6_DISP_IRQ_STA_DSE (1 << 8) | ||
| 50 | #define VI6_DISP_IRQ_STA_MAE (1 << 5) | ||
| 51 | #define VI6_DISP_IRQ_STA_LNE(n) (1 << ((n) + 4)) | ||
| 52 | |||
| 53 | #define VI6_WPF_LINE_COUNT(n) (0x0084 + (n) * 4) | ||
| 54 | #define VI6_WPF_LINE_COUNT_MASK (0x1fffff << 0) | ||
| 55 | |||
| 56 | /* ----------------------------------------------------------------------------- | ||
| 57 | * Display List Control Registers | ||
| 58 | */ | ||
| 59 | |||
| 60 | #define VI6_DL_CTRL 0x0100 | ||
| 61 | #define VI6_DL_CTRL_AR_WAIT_MASK (0xffff << 16) | ||
| 62 | #define VI6_DL_CTRL_AR_WAIT_SHIFT 16 | ||
| 63 | #define VI6_DL_CTRL_DC2 (1 << 12) | ||
| 64 | #define VI6_DL_CTRL_DC1 (1 << 8) | ||
| 65 | #define VI6_DL_CTRL_DC0 (1 << 4) | ||
| 66 | #define VI6_DL_CTRL_CFM0 (1 << 2) | ||
| 67 | #define VI6_DL_CTRL_NH0 (1 << 1) | ||
| 68 | #define VI6_DL_CTRL_DLE (1 << 0) | ||
| 69 | |||
| 70 | #define VI6_DL_HDR_ADDR(n) (0x0104 + (n) * 4) | ||
| 71 | |||
| 72 | #define VI6_DL_SWAP 0x0114 | ||
| 73 | #define VI6_DL_SWAP_LWS (1 << 2) | ||
| 74 | #define VI6_DL_SWAP_WDS (1 << 1) | ||
| 75 | #define VI6_DL_SWAP_BTS (1 << 0) | ||
| 76 | |||
| 77 | #define VI6_DL_EXT_CTRL 0x011c | ||
| 78 | #define VI6_DL_EXT_CTRL_NWE (1 << 16) | ||
| 79 | #define VI6_DL_EXT_CTRL_POLINT_MASK (0x3f << 8) | ||
| 80 | #define VI6_DL_EXT_CTRL_POLINT_SHIFT 8 | ||
| 81 | #define VI6_DL_EXT_CTRL_DLPRI (1 << 5) | ||
| 82 | #define VI6_DL_EXT_CTRL_EXPRI (1 << 4) | ||
| 83 | #define VI6_DL_EXT_CTRL_EXT (1 << 0) | ||
| 84 | |||
| 85 | #define VI6_DL_BODY_SIZE 0x0120 | ||
| 86 | #define VI6_DL_BODY_SIZE_UPD (1 << 24) | ||
| 87 | #define VI6_DL_BODY_SIZE_BS_MASK (0x1ffff << 0) | ||
| 88 | #define VI6_DL_BODY_SIZE_BS_SHIFT 0 | ||
| 89 | |||
| 90 | /* ----------------------------------------------------------------------------- | ||
| 91 | * RPF Control Registers | ||
| 92 | */ | ||
| 93 | |||
| 94 | #define VI6_RPF_OFFSET 0x100 | ||
| 95 | |||
| 96 | #define VI6_RPF_SRC_BSIZE 0x0300 | ||
| 97 | #define VI6_RPF_SRC_BSIZE_BHSIZE_MASK (0x1fff << 16) | ||
| 98 | #define VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT 16 | ||
| 99 | #define VI6_RPF_SRC_BSIZE_BVSIZE_MASK (0x1fff << 0) | ||
| 100 | #define VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT 0 | ||
| 101 | |||
| 102 | #define VI6_RPF_SRC_ESIZE 0x0304 | ||
| 103 | #define VI6_RPF_SRC_ESIZE_EHSIZE_MASK (0x1fff << 16) | ||
| 104 | #define VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT 16 | ||
| 105 | #define VI6_RPF_SRC_ESIZE_EVSIZE_MASK (0x1fff << 0) | ||
| 106 | #define VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT 0 | ||
| 107 | |||
| 108 | #define VI6_RPF_INFMT 0x0308 | ||
| 109 | #define VI6_RPF_INFMT_VIR (1 << 28) | ||
| 110 | #define VI6_RPF_INFMT_CIPM (1 << 16) | ||
| 111 | #define VI6_RPF_INFMT_SPYCS (1 << 15) | ||
| 112 | #define VI6_RPF_INFMT_SPUVS (1 << 14) | ||
| 113 | #define VI6_RPF_INFMT_CEXT_ZERO (0 << 12) | ||
| 114 | #define VI6_RPF_INFMT_CEXT_EXT (1 << 12) | ||
| 115 | #define VI6_RPF_INFMT_CEXT_ONE (2 << 12) | ||
| 116 | #define VI6_RPF_INFMT_CEXT_MASK (3 << 12) | ||
| 117 | #define VI6_RPF_INFMT_RDTM_BT601 (0 << 9) | ||
| 118 | #define VI6_RPF_INFMT_RDTM_BT601_EXT (1 << 9) | ||
| 119 | #define VI6_RPF_INFMT_RDTM_BT709 (2 << 9) | ||
| 120 | #define VI6_RPF_INFMT_RDTM_BT709_EXT (3 << 9) | ||
| 121 | #define VI6_RPF_INFMT_RDTM_MASK (7 << 9) | ||
| 122 | #define VI6_RPF_INFMT_CSC (1 << 8) | ||
| 123 | #define VI6_RPF_INFMT_RDFMT_MASK (0x7f << 0) | ||
| 124 | #define VI6_RPF_INFMT_RDFMT_SHIFT 0 | ||
| 125 | |||
| 126 | #define VI6_RPF_DSWAP 0x030c | ||
| 127 | #define VI6_RPF_DSWAP_A_LLS (1 << 11) | ||
| 128 | #define VI6_RPF_DSWAP_A_LWS (1 << 10) | ||
| 129 | #define VI6_RPF_DSWAP_A_WDS (1 << 9) | ||
| 130 | #define VI6_RPF_DSWAP_A_BTS (1 << 8) | ||
| 131 | #define VI6_RPF_DSWAP_P_LLS (1 << 3) | ||
| 132 | #define VI6_RPF_DSWAP_P_LWS (1 << 2) | ||
| 133 | #define VI6_RPF_DSWAP_P_WDS (1 << 1) | ||
| 134 | #define VI6_RPF_DSWAP_P_BTS (1 << 0) | ||
| 135 | |||
| 136 | #define VI6_RPF_LOC 0x0310 | ||
| 137 | #define VI6_RPF_LOC_HCOORD_MASK (0x1fff << 16) | ||
| 138 | #define VI6_RPF_LOC_HCOORD_SHIFT 16 | ||
| 139 | #define VI6_RPF_LOC_VCOORD_MASK (0x1fff << 0) | ||
| 140 | #define VI6_RPF_LOC_VCOORD_SHIFT 0 | ||
| 141 | |||
| 142 | #define VI6_RPF_ALPH_SEL 0x0314 | ||
| 143 | #define VI6_RPF_ALPH_SEL_ASEL_PACKED (0 << 28) | ||
| 144 | #define VI6_RPF_ALPH_SEL_ASEL_8B_PLANE (1 << 28) | ||
| 145 | #define VI6_RPF_ALPH_SEL_ASEL_SELECT (2 << 28) | ||
| 146 | #define VI6_RPF_ALPH_SEL_ASEL_1B_PLANE (3 << 28) | ||
| 147 | #define VI6_RPF_ALPH_SEL_ASEL_FIXED (4 << 28) | ||
| 148 | #define VI6_RPF_ALPH_SEL_ASEL_MASK (7 << 28) | ||
| 149 | #define VI6_RPF_ALPH_SEL_ASEL_SHIFT 28 | ||
| 150 | #define VI6_RPF_ALPH_SEL_IROP_MASK (0xf << 24) | ||
| 151 | #define VI6_RPF_ALPH_SEL_IROP_SHIFT 24 | ||
| 152 | #define VI6_RPF_ALPH_SEL_BSEL (1 << 23) | ||
| 153 | #define VI6_RPF_ALPH_SEL_AEXT_ZERO (0 << 18) | ||
| 154 | #define VI6_RPF_ALPH_SEL_AEXT_EXT (1 << 18) | ||
| 155 | #define VI6_RPF_ALPH_SEL_AEXT_ONE (2 << 18) | ||
| 156 | #define VI6_RPF_ALPH_SEL_AEXT_MASK (3 << 18) | ||
| 157 | #define VI6_RPF_ALPH_SEL_ALPHA0_MASK (0xff << 8) | ||
| 158 | #define VI6_RPF_ALPH_SEL_ALPHA0_SHIFT 8 | ||
| 159 | #define VI6_RPF_ALPH_SEL_ALPHA1_MASK (0xff << 0) | ||
| 160 | #define VI6_RPF_ALPH_SEL_ALPHA1_SHIFT 0 | ||
| 161 | |||
| 162 | #define VI6_RPF_VRTCOL_SET 0x0318 | ||
| 163 | #define VI6_RPF_VRTCOL_SET_LAYA_MASK (0xff << 24) | ||
| 164 | #define VI6_RPF_VRTCOL_SET_LAYA_SHIFT 24 | ||
| 165 | #define VI6_RPF_VRTCOL_SET_LAYR_MASK (0xff << 16) | ||
| 166 | #define VI6_RPF_VRTCOL_SET_LAYR_SHIFT 16 | ||
| 167 | #define VI6_RPF_VRTCOL_SET_LAYG_MASK (0xff << 8) | ||
| 168 | #define VI6_RPF_VRTCOL_SET_LAYG_SHIFT 8 | ||
| 169 | #define VI6_RPF_VRTCOL_SET_LAYB_MASK (0xff << 0) | ||
| 170 | #define VI6_RPF_VRTCOL_SET_LAYB_SHIFT 0 | ||
| 171 | |||
| 172 | #define VI6_RPF_MSK_CTRL 0x031c | ||
| 173 | #define VI6_RPF_MSK_CTRL_MSK_EN (1 << 24) | ||
| 174 | #define VI6_RPF_MSK_CTRL_MGR_MASK (0xff << 16) | ||
| 175 | #define VI6_RPF_MSK_CTRL_MGR_SHIFT 16 | ||
| 176 | #define VI6_RPF_MSK_CTRL_MGG_MASK (0xff << 8) | ||
| 177 | #define VI6_RPF_MSK_CTRL_MGG_SHIFT 8 | ||
| 178 | #define VI6_RPF_MSK_CTRL_MGB_MASK (0xff << 0) | ||
| 179 | #define VI6_RPF_MSK_CTRL_MGB_SHIFT 0 | ||
| 180 | |||
| 181 | #define VI6_RPF_MSK_SET0 0x0320 | ||
| 182 | #define VI6_RPF_MSK_SET1 0x0324 | ||
| 183 | #define VI6_RPF_MSK_SET_MSA_MASK (0xff << 24) | ||
| 184 | #define VI6_RPF_MSK_SET_MSA_SHIFT 24 | ||
| 185 | #define VI6_RPF_MSK_SET_MSR_MASK (0xff << 16) | ||
| 186 | #define VI6_RPF_MSK_SET_MSR_SHIFT 16 | ||
| 187 | #define VI6_RPF_MSK_SET_MSG_MASK (0xff << 8) | ||
| 188 | #define VI6_RPF_MSK_SET_MSG_SHIFT 8 | ||
| 189 | #define VI6_RPF_MSK_SET_MSB_MASK (0xff << 0) | ||
| 190 | #define VI6_RPF_MSK_SET_MSB_SHIFT 0 | ||
| 191 | |||
| 192 | #define VI6_RPF_CKEY_CTRL 0x0328 | ||
| 193 | #define VI6_RPF_CKEY_CTRL_CV (1 << 4) | ||
| 194 | #define VI6_RPF_CKEY_CTRL_SAPE1 (1 << 1) | ||
| 195 | #define VI6_RPF_CKEY_CTRL_SAPE0 (1 << 0) | ||
| 196 | |||
| 197 | #define VI6_RPF_CKEY_SET0 0x032c | ||
| 198 | #define VI6_RPF_CKEY_SET1 0x0330 | ||
| 199 | #define VI6_RPF_CKEY_SET_AP_MASK (0xff << 24) | ||
| 200 | #define VI6_RPF_CKEY_SET_AP_SHIFT 24 | ||
| 201 | #define VI6_RPF_CKEY_SET_R_MASK (0xff << 16) | ||
| 202 | #define VI6_RPF_CKEY_SET_R_SHIFT 16 | ||
| 203 | #define VI6_RPF_CKEY_SET_GY_MASK (0xff << 8) | ||
| 204 | #define VI6_RPF_CKEY_SET_GY_SHIFT 8 | ||
| 205 | #define VI6_RPF_CKEY_SET_B_MASK (0xff << 0) | ||
| 206 | #define VI6_RPF_CKEY_SET_B_SHIFT 0 | ||
| 207 | |||
| 208 | #define VI6_RPF_SRCM_PSTRIDE 0x0334 | ||
| 209 | #define VI6_RPF_SRCM_PSTRIDE_Y_SHIFT 16 | ||
| 210 | #define VI6_RPF_SRCM_PSTRIDE_C_SHIFT 0 | ||
| 211 | |||
| 212 | #define VI6_RPF_SRCM_ASTRIDE 0x0338 | ||
| 213 | #define VI6_RPF_SRCM_PSTRIDE_A_SHIFT 0 | ||
| 214 | |||
| 215 | #define VI6_RPF_SRCM_ADDR_Y 0x033c | ||
| 216 | #define VI6_RPF_SRCM_ADDR_C0 0x0340 | ||
| 217 | #define VI6_RPF_SRCM_ADDR_C1 0x0344 | ||
| 218 | #define VI6_RPF_SRCM_ADDR_AI 0x0348 | ||
| 219 | |||
| 220 | /* ----------------------------------------------------------------------------- | ||
| 221 | * WPF Control Registers | ||
| 222 | */ | ||
| 223 | |||
| 224 | #define VI6_WPF_OFFSET 0x100 | ||
| 225 | |||
| 226 | #define VI6_WPF_SRCRPF 0x1000 | ||
| 227 | #define VI6_WPF_SRCRPF_VIRACT_DIS (0 << 28) | ||
| 228 | #define VI6_WPF_SRCRPF_VIRACT_SUB (1 << 28) | ||
| 229 | #define VI6_WPF_SRCRPF_VIRACT_MST (2 << 28) | ||
| 230 | #define VI6_WPF_SRCRPF_VIRACT_MASK (3 << 28) | ||
| 231 | #define VI6_WPF_SRCRPF_RPF_ACT_DIS(n) (0 << ((n) * 2)) | ||
| 232 | #define VI6_WPF_SRCRPF_RPF_ACT_SUB(n) (1 << ((n) * 2)) | ||
| 233 | #define VI6_WPF_SRCRPF_RPF_ACT_MST(n) (2 << ((n) * 2)) | ||
| 234 | #define VI6_WPF_SRCRPF_RPF_ACT_MASK(n) (3 << ((n) * 2)) | ||
| 235 | |||
| 236 | #define VI6_WPF_HSZCLIP 0x1004 | ||
| 237 | #define VI6_WPF_VSZCLIP 0x1008 | ||
| 238 | #define VI6_WPF_SZCLIP_EN (1 << 28) | ||
| 239 | #define VI6_WPF_SZCLIP_OFST_MASK (0xff << 16) | ||
| 240 | #define VI6_WPF_SZCLIP_OFST_SHIFT 16 | ||
| 241 | #define VI6_WPF_SZCLIP_SIZE_MASK (0x1fff << 0) | ||
| 242 | #define VI6_WPF_SZCLIP_SIZE_SHIFT 0 | ||
| 243 | |||
| 244 | #define VI6_WPF_OUTFMT 0x100c | ||
| 245 | #define VI6_WPF_OUTFMT_PDV_MASK (0xff << 24) | ||
| 246 | #define VI6_WPF_OUTFMT_PDV_SHIFT 24 | ||
| 247 | #define VI6_WPF_OUTFMT_PXA (1 << 23) | ||
| 248 | #define VI6_WPF_OUTFMT_FLP (1 << 16) | ||
| 249 | #define VI6_WPF_OUTFMT_SPYCS (1 << 15) | ||
| 250 | #define VI6_WPF_OUTFMT_SPUVS (1 << 14) | ||
| 251 | #define VI6_WPF_OUTFMT_DITH_DIS (0 << 12) | ||
| 252 | #define VI6_WPF_OUTFMT_DITH_EN (3 << 12) | ||
| 253 | #define VI6_WPF_OUTFMT_DITH_MASK (3 << 12) | ||
| 254 | #define VI6_WPF_OUTFMT_WRTM_BT601 (0 << 9) | ||
| 255 | #define VI6_WPF_OUTFMT_WRTM_BT601_EXT (1 << 9) | ||
| 256 | #define VI6_WPF_OUTFMT_WRTM_BT709 (2 << 9) | ||
| 257 | #define VI6_WPF_OUTFMT_WRTM_BT709_EXT (3 << 9) | ||
| 258 | #define VI6_WPF_OUTFMT_WRTM_MASK (7 << 9) | ||
| 259 | #define VI6_WPF_OUTFMT_CSC (1 << 8) | ||
| 260 | #define VI6_WPF_OUTFMT_WRFMT_MASK (0x7f << 0) | ||
| 261 | #define VI6_WPF_OUTFMT_WRFMT_SHIFT 0 | ||
| 262 | |||
| 263 | #define VI6_WPF_DSWAP 0x1010 | ||
| 264 | #define VI6_WPF_DSWAP_P_LLS (1 << 3) | ||
| 265 | #define VI6_WPF_DSWAP_P_LWS (1 << 2) | ||
| 266 | #define VI6_WPF_DSWAP_P_WDS (1 << 1) | ||
| 267 | #define VI6_WPF_DSWAP_P_BTS (1 << 0) | ||
| 268 | |||
| 269 | #define VI6_WPF_RNDCTRL 0x1014 | ||
| 270 | #define VI6_WPF_RNDCTRL_CBRM (1 << 28) | ||
| 271 | #define VI6_WPF_RNDCTRL_ABRM_TRUNC (0 << 24) | ||
| 272 | #define VI6_WPF_RNDCTRL_ABRM_ROUND (1 << 24) | ||
| 273 | #define VI6_WPF_RNDCTRL_ABRM_THRESH (2 << 24) | ||
| 274 | #define VI6_WPF_RNDCTRL_ABRM_MASK (3 << 24) | ||
| 275 | #define VI6_WPF_RNDCTRL_ATHRESH_MASK (0xff << 16) | ||
| 276 | #define VI6_WPF_RNDCTRL_ATHRESH_SHIFT 16 | ||
| 277 | #define VI6_WPF_RNDCTRL_CLMD_FULL (0 << 12) | ||
| 278 | #define VI6_WPF_RNDCTRL_CLMD_CLIP (1 << 12) | ||
| 279 | #define VI6_WPF_RNDCTRL_CLMD_EXT (2 << 12) | ||
| 280 | #define VI6_WPF_RNDCTRL_CLMD_MASK (3 << 12) | ||
| 281 | |||
| 282 | #define VI6_WPF_DSTM_STRIDE_Y 0x101c | ||
| 283 | #define VI6_WPF_DSTM_STRIDE_C 0x1020 | ||
| 284 | #define VI6_WPF_DSTM_ADDR_Y 0x1024 | ||
| 285 | #define VI6_WPF_DSTM_ADDR_C0 0x1028 | ||
| 286 | #define VI6_WPF_DSTM_ADDR_C1 0x102c | ||
| 287 | |||
| 288 | #define VI6_WPF_WRBCK_CTRL 0x1034 | ||
| 289 | #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0) | ||
| 290 | |||
| 291 | /* ----------------------------------------------------------------------------- | ||
| 292 | * DPR Control Registers | ||
| 293 | */ | ||
| 294 | |||
| 295 | #define VI6_DPR_RPF_ROUTE(n) (0x2000 + (n) * 4) | ||
| 296 | |||
| 297 | #define VI6_DPR_WPF_FPORCH(n) (0x2014 + (n) * 4) | ||
| 298 | #define VI6_DPR_WPF_FPORCH_FP_WPFN (5 << 8) | ||
| 299 | |||
| 300 | #define VI6_DPR_SRU_ROUTE 0x2024 | ||
| 301 | #define VI6_DPR_UDS_ROUTE(n) (0x2028 + (n) * 4) | ||
| 302 | #define VI6_DPR_LUT_ROUTE 0x203c | ||
| 303 | #define VI6_DPR_CLU_ROUTE 0x2040 | ||
| 304 | #define VI6_DPR_HST_ROUTE 0x2044 | ||
| 305 | #define VI6_DPR_HSI_ROUTE 0x2048 | ||
| 306 | #define VI6_DPR_BRU_ROUTE 0x204c | ||
| 307 | #define VI6_DPR_ROUTE_FXA_MASK (0xff << 8) | ||
| 308 | #define VI6_DPR_ROUTE_FXA_SHIFT 16 | ||
| 309 | #define VI6_DPR_ROUTE_FP_MASK (0xff << 8) | ||
| 310 | #define VI6_DPR_ROUTE_FP_SHIFT 8 | ||
| 311 | #define VI6_DPR_ROUTE_RT_MASK (0x3f << 0) | ||
| 312 | #define VI6_DPR_ROUTE_RT_SHIFT 0 | ||
| 313 | |||
| 314 | #define VI6_DPR_HGO_SMPPT 0x2050 | ||
| 315 | #define VI6_DPR_HGT_SMPPT 0x2054 | ||
| 316 | #define VI6_DPR_SMPPT_TGW_MASK (7 << 8) | ||
| 317 | #define VI6_DPR_SMPPT_TGW_SHIFT 8 | ||
| 318 | #define VI6_DPR_SMPPT_PT_MASK (0x3f << 0) | ||
| 319 | #define VI6_DPR_SMPPT_PT_SHIFT 0 | ||
| 320 | |||
| 321 | #define VI6_DPR_NODE_RPF(n) (n) | ||
| 322 | #define VI6_DPR_NODE_SRU 16 | ||
| 323 | #define VI6_DPR_NODE_UDS(n) (17 + (n)) | ||
| 324 | #define VI6_DPR_NODE_LUT 22 | ||
| 325 | #define VI6_DPR_NODE_BRU_IN(n) (23 + (n)) | ||
| 326 | #define VI6_DPR_NODE_BRU_OUT 27 | ||
| 327 | #define VI6_DPR_NODE_CLU 29 | ||
| 328 | #define VI6_DPR_NODE_HST 30 | ||
| 329 | #define VI6_DPR_NODE_HSI 31 | ||
| 330 | #define VI6_DPR_NODE_LIF 55 | ||
| 331 | #define VI6_DPR_NODE_WPF(n) (56 + (n)) | ||
| 332 | #define VI6_DPR_NODE_UNUSED 63 | ||
| 333 | |||
| 334 | /* ----------------------------------------------------------------------------- | ||
| 335 | * SRU Control Registers | ||
| 336 | */ | ||
| 337 | |||
| 338 | #define VI6_SRU_CTRL0 0x2200 | ||
| 339 | #define VI6_SRU_CTRL1 0x2204 | ||
| 340 | #define VI6_SRU_CTRL2 0x2208 | ||
| 341 | |||
| 342 | /* ----------------------------------------------------------------------------- | ||
| 343 | * UDS Control Registers | ||
| 344 | */ | ||
| 345 | |||
| 346 | #define VI6_UDS_OFFSET 0x100 | ||
| 347 | |||
| 348 | #define VI6_UDS_CTRL 0x2300 | ||
| 349 | #define VI6_UDS_CTRL_AMD (1 << 30) | ||
| 350 | #define VI6_UDS_CTRL_FMD (1 << 29) | ||
| 351 | #define VI6_UDS_CTRL_BLADV (1 << 28) | ||
| 352 | #define VI6_UDS_CTRL_AON (1 << 25) | ||
| 353 | #define VI6_UDS_CTRL_ATHON (1 << 24) | ||
| 354 | #define VI6_UDS_CTRL_BC (1 << 20) | ||
| 355 | #define VI6_UDS_CTRL_NE_A (1 << 19) | ||
| 356 | #define VI6_UDS_CTRL_NE_RCR (1 << 18) | ||
| 357 | #define VI6_UDS_CTRL_NE_GY (1 << 17) | ||
| 358 | #define VI6_UDS_CTRL_NE_BCB (1 << 16) | ||
| 359 | #define VI6_UDS_CTRL_TDIPC (1 << 1) | ||
| 360 | |||
| 361 | #define VI6_UDS_SCALE 0x2304 | ||
| 362 | #define VI6_UDS_SCALE_HMANT_MASK (0xf << 28) | ||
| 363 | #define VI6_UDS_SCALE_HMANT_SHIFT 28 | ||
| 364 | #define VI6_UDS_SCALE_HFRAC_MASK (0xfff << 16) | ||
| 365 | #define VI6_UDS_SCALE_HFRAC_SHIFT 16 | ||
| 366 | #define VI6_UDS_SCALE_VMANT_MASK (0xf << 12) | ||
| 367 | #define VI6_UDS_SCALE_VMANT_SHIFT 12 | ||
| 368 | #define VI6_UDS_SCALE_VFRAC_MASK (0xfff << 0) | ||
| 369 | #define VI6_UDS_SCALE_VFRAC_SHIFT 0 | ||
| 370 | |||
| 371 | #define VI6_UDS_ALPTH 0x2308 | ||
| 372 | #define VI6_UDS_ALPTH_TH1_MASK (0xff << 8) | ||
| 373 | #define VI6_UDS_ALPTH_TH1_SHIFT 8 | ||
| 374 | #define VI6_UDS_ALPTH_TH0_MASK (0xff << 0) | ||
| 375 | #define VI6_UDS_ALPTH_TH0_SHIFT 0 | ||
| 376 | |||
| 377 | #define VI6_UDS_ALPVAL 0x230c | ||
| 378 | #define VI6_UDS_ALPVAL_VAL2_MASK (0xff << 16) | ||
| 379 | #define VI6_UDS_ALPVAL_VAL2_SHIFT 16 | ||
| 380 | #define VI6_UDS_ALPVAL_VAL1_MASK (0xff << 8) | ||
| 381 | #define VI6_UDS_ALPVAL_VAL1_SHIFT 8 | ||
| 382 | #define VI6_UDS_ALPVAL_VAL0_MASK (0xff << 0) | ||
| 383 | #define VI6_UDS_ALPVAL_VAL0_SHIFT 0 | ||
| 384 | |||
| 385 | #define VI6_UDS_PASS_BWIDTH 0x2310 | ||
| 386 | #define VI6_UDS_PASS_BWIDTH_H_MASK (0x7f << 16) | ||
| 387 | #define VI6_UDS_PASS_BWIDTH_H_SHIFT 16 | ||
| 388 | #define VI6_UDS_PASS_BWIDTH_V_MASK (0x7f << 0) | ||
| 389 | #define VI6_UDS_PASS_BWIDTH_V_SHIFT 0 | ||
| 390 | |||
| 391 | #define VI6_UDS_IPC 0x2318 | ||
| 392 | #define VI6_UDS_IPC_FIELD (1 << 27) | ||
| 393 | #define VI6_UDS_IPC_VEDP_MASK (0xfff << 0) | ||
| 394 | #define VI6_UDS_IPC_VEDP_SHIFT 0 | ||
| 395 | |||
| 396 | #define VI6_UDS_CLIP_SIZE 0x2324 | ||
| 397 | #define VI6_UDS_CLIP_SIZE_HSIZE_MASK (0x1fff << 16) | ||
| 398 | #define VI6_UDS_CLIP_SIZE_HSIZE_SHIFT 16 | ||
| 399 | #define VI6_UDS_CLIP_SIZE_VSIZE_MASK (0x1fff << 0) | ||
| 400 | #define VI6_UDS_CLIP_SIZE_VSIZE_SHIFT 0 | ||
| 401 | |||
| 402 | #define VI6_UDS_FILL_COLOR 0x2328 | ||
| 403 | #define VI6_UDS_FILL_COLOR_RFILC_MASK (0xff << 16) | ||
| 404 | #define VI6_UDS_FILL_COLOR_RFILC_SHIFT 16 | ||
| 405 | #define VI6_UDS_FILL_COLOR_GFILC_MASK (0xff << 8) | ||
| 406 | #define VI6_UDS_FILL_COLOR_GFILC_SHIFT 8 | ||
| 407 | #define VI6_UDS_FILL_COLOR_BFILC_MASK (0xff << 0) | ||
| 408 | #define VI6_UDS_FILL_COLOR_BFILC_SHIFT 0 | ||
| 409 | |||
| 410 | /* ----------------------------------------------------------------------------- | ||
| 411 | * LUT Control Registers | ||
| 412 | */ | ||
| 413 | |||
| 414 | #define VI6_LUT_CTRL 0x2800 | ||
| 415 | |||
| 416 | /* ----------------------------------------------------------------------------- | ||
| 417 | * CLU Control Registers | ||
| 418 | */ | ||
| 419 | |||
| 420 | #define VI6_CLU_CTRL 0x2900 | ||
| 421 | |||
| 422 | /* ----------------------------------------------------------------------------- | ||
| 423 | * HST Control Registers | ||
| 424 | */ | ||
| 425 | |||
| 426 | #define VI6_HST_CTRL 0x2a00 | ||
| 427 | |||
| 428 | /* ----------------------------------------------------------------------------- | ||
| 429 | * HSI Control Registers | ||
| 430 | */ | ||
| 431 | |||
| 432 | #define VI6_HSI_CTRL 0x2b00 | ||
| 433 | |||
| 434 | /* ----------------------------------------------------------------------------- | ||
| 435 | * BRU Control Registers | ||
| 436 | */ | ||
| 437 | |||
| 438 | #define VI6_BRU_INCTRL 0x2c00 | ||
| 439 | #define VI6_BRU_VIRRPF_SIZE 0x2c04 | ||
| 440 | #define VI6_BRU_VIRRPF_LOC 0x2c08 | ||
| 441 | #define VI6_BRU_VIRRPF_COL 0x2c0c | ||
| 442 | #define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8) | ||
| 443 | #define VI6_BRU_BLD(n) (0x2c14 + (n) * 8) | ||
| 444 | #define VI6_BRU_ROP 0x2c30 | ||
| 445 | |||
| 446 | /* ----------------------------------------------------------------------------- | ||
| 447 | * HGO Control Registers | ||
| 448 | */ | ||
| 449 | |||
| 450 | #define VI6_HGO_OFFSET 0x3000 | ||
| 451 | #define VI6_HGO_SIZE 0x3004 | ||
| 452 | #define VI6_HGO_MODE 0x3008 | ||
| 453 | #define VI6_HGO_LB_TH 0x300c | ||
| 454 | #define VI6_HGO_LBn_H(n) (0x3010 + (n) * 8) | ||
| 455 | #define VI6_HGO_LBn_V(n) (0x3014 + (n) * 8) | ||
| 456 | #define VI6_HGO_R_HISTO 0x3030 | ||
| 457 | #define VI6_HGO_R_MAXMIN 0x3130 | ||
| 458 | #define VI6_HGO_R_SUM 0x3134 | ||
| 459 | #define VI6_HGO_R_LB_DET 0x3138 | ||
| 460 | #define VI6_HGO_G_HISTO 0x3140 | ||
| 461 | #define VI6_HGO_G_MAXMIN 0x3240 | ||
| 462 | #define VI6_HGO_G_SUM 0x3244 | ||
| 463 | #define VI6_HGO_G_LB_DET 0x3248 | ||
| 464 | #define VI6_HGO_B_HISTO 0x3250 | ||
| 465 | #define VI6_HGO_B_MAXMIN 0x3350 | ||
| 466 | #define VI6_HGO_B_SUM 0x3354 | ||
| 467 | #define VI6_HGO_B_LB_DET 0x3358 | ||
| 468 | #define VI6_HGO_REGRST 0x33fc | ||
| 469 | |||
| 470 | /* ----------------------------------------------------------------------------- | ||
| 471 | * HGT Control Registers | ||
| 472 | */ | ||
| 473 | |||
| 474 | #define VI6_HGT_OFFSET 0x3400 | ||
| 475 | #define VI6_HGT_SIZE 0x3404 | ||
| 476 | #define VI6_HGT_MODE 0x3408 | ||
| 477 | #define VI6_HGT_HUE_AREA(n) (0x340c + (n) * 4) | ||
| 478 | #define VI6_HGT_LB_TH 0x3424 | ||
| 479 | #define VI6_HGT_LBn_H(n) (0x3438 + (n) * 8) | ||
| 480 | #define VI6_HGT_LBn_V(n) (0x342c + (n) * 8) | ||
| 481 | #define VI6_HGT_HISTO(m, n) (0x3450 + (m) * 128 + (n) * 4) | ||
| 482 | #define VI6_HGT_MAXMIN 0x3750 | ||
| 483 | #define VI6_HGT_SUM 0x3754 | ||
| 484 | #define VI6_HGT_LB_DET 0x3758 | ||
| 485 | #define VI6_HGT_REGRST 0x37fc | ||
| 486 | |||
| 487 | /* ----------------------------------------------------------------------------- | ||
| 488 | * LIF Control Registers | ||
| 489 | */ | ||
| 490 | |||
| 491 | #define VI6_LIF_CTRL 0x3b00 | ||
| 492 | #define VI6_LIF_CTRL_OBTH_MASK (0x7ff << 16) | ||
| 493 | #define VI6_LIF_CTRL_OBTH_SHIFT 16 | ||
| 494 | #define VI6_LIF_CTRL_CFMT (1 << 4) | ||
| 495 | #define VI6_LIF_CTRL_REQSEL (1 << 1) | ||
| 496 | #define VI6_LIF_CTRL_LIF_EN (1 << 0) | ||
| 497 | |||
| 498 | #define VI6_LIF_CSBTH 0x3b04 | ||
| 499 | #define VI6_LIF_CSBTH_HBTH_MASK (0x7ff << 16) | ||
| 500 | #define VI6_LIF_CSBTH_HBTH_SHIFT 16 | ||
| 501 | #define VI6_LIF_CSBTH_LBTH_MASK (0x7ff << 0) | ||
| 502 | #define VI6_LIF_CSBTH_LBTH_SHIFT 0 | ||
| 503 | |||
| 504 | /* ----------------------------------------------------------------------------- | ||
| 505 | * Security Control Registers | ||
| 506 | */ | ||
| 507 | |||
| 508 | #define VI6_SECURITY_CTRL0 0x3d00 | ||
| 509 | #define VI6_SECURITY_CTRL1 0x3d04 | ||
| 510 | |||
| 511 | /* ----------------------------------------------------------------------------- | ||
| 512 | * RPF CLUT Registers | ||
| 513 | */ | ||
| 514 | |||
| 515 | #define VI6_CLUT_TABLE 0x4000 | ||
| 516 | |||
| 517 | /* ----------------------------------------------------------------------------- | ||
| 518 | * 1D LUT Registers | ||
| 519 | */ | ||
| 520 | |||
| 521 | #define VI6_LUT_TABLE 0x7000 | ||
| 522 | |||
| 523 | /* ----------------------------------------------------------------------------- | ||
| 524 | * 3D LUT Registers | ||
| 525 | */ | ||
| 526 | |||
| 527 | #define VI6_CLU_ADDR 0x7400 | ||
| 528 | #define VI6_CLU_DATA 0x7404 | ||
| 529 | |||
| 530 | /* ----------------------------------------------------------------------------- | ||
| 531 | * Formats | ||
| 532 | */ | ||
| 533 | |||
| 534 | #define VI6_FMT_RGB_332 0x00 | ||
| 535 | #define VI6_FMT_XRGB_4444 0x01 | ||
| 536 | #define VI6_FMT_RGBX_4444 0x02 | ||
| 537 | #define VI6_FMT_XRGB_1555 0x04 | ||
| 538 | #define VI6_FMT_RGBX_5551 0x05 | ||
| 539 | #define VI6_FMT_RGB_565 0x06 | ||
| 540 | #define VI6_FMT_AXRGB_86666 0x07 | ||
| 541 | #define VI6_FMT_RGBXA_66668 0x08 | ||
| 542 | #define VI6_FMT_XRGBA_66668 0x09 | ||
| 543 | #define VI6_FMT_ARGBX_86666 0x0a | ||
| 544 | #define VI6_FMT_AXRXGXB_8262626 0x0b | ||
| 545 | #define VI6_FMT_XRXGXBA_2626268 0x0c | ||
| 546 | #define VI6_FMT_ARXGXBX_8626262 0x0d | ||
| 547 | #define VI6_FMT_RXGXBXA_6262628 0x0e | ||
| 548 | #define VI6_FMT_XRGB_6666 0x0f | ||
| 549 | #define VI6_FMT_RGBX_6666 0x10 | ||
| 550 | #define VI6_FMT_XRXGXB_262626 0x11 | ||
| 551 | #define VI6_FMT_RXGXBX_626262 0x12 | ||
| 552 | #define VI6_FMT_ARGB_8888 0x13 | ||
| 553 | #define VI6_FMT_RGBA_8888 0x14 | ||
| 554 | #define VI6_FMT_RGB_888 0x15 | ||
| 555 | #define VI6_FMT_XRGXGB_763763 0x16 | ||
| 556 | #define VI6_FMT_XXRGB_86666 0x17 | ||
| 557 | #define VI6_FMT_BGR_888 0x18 | ||
| 558 | #define VI6_FMT_ARGB_4444 0x19 | ||
| 559 | #define VI6_FMT_RGBA_4444 0x1a | ||
| 560 | #define VI6_FMT_ARGB_1555 0x1b | ||
| 561 | #define VI6_FMT_RGBA_5551 0x1c | ||
| 562 | #define VI6_FMT_ABGR_4444 0x1d | ||
| 563 | #define VI6_FMT_BGRA_4444 0x1e | ||
| 564 | #define VI6_FMT_ABGR_1555 0x1f | ||
| 565 | #define VI6_FMT_BGRA_5551 0x20 | ||
| 566 | #define VI6_FMT_XBXGXR_262626 0x21 | ||
| 567 | #define VI6_FMT_ABGR_8888 0x22 | ||
| 568 | #define VI6_FMT_XXRGB_88565 0x23 | ||
| 569 | |||
| 570 | #define VI6_FMT_Y_UV_444 0x40 | ||
| 571 | #define VI6_FMT_Y_UV_422 0x41 | ||
| 572 | #define VI6_FMT_Y_UV_420 0x42 | ||
| 573 | #define VI6_FMT_YUV_444 0x46 | ||
| 574 | #define VI6_FMT_YUYV_422 0x47 | ||
| 575 | #define VI6_FMT_YYUV_422 0x48 | ||
| 576 | #define VI6_FMT_YUV_420 0x49 | ||
| 577 | #define VI6_FMT_Y_U_V_444 0x4a | ||
| 578 | #define VI6_FMT_Y_U_V_422 0x4b | ||
| 579 | #define VI6_FMT_Y_U_V_420 0x4c | ||
| 580 | |||
| 581 | #endif /* __VSP1_REGS_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c new file mode 100644 index 000000000000..254871d3423e --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rpf.c | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_rpf.c -- R-Car VSP1 Read Pixel Formatter | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | |||
| 16 | #include <media/v4l2-subdev.h> | ||
| 17 | |||
| 18 | #include "vsp1.h" | ||
| 19 | #include "vsp1_rwpf.h" | ||
| 20 | #include "vsp1_video.h" | ||
| 21 | |||
| 22 | #define RPF_MAX_WIDTH 8190 | ||
| 23 | #define RPF_MAX_HEIGHT 8190 | ||
| 24 | |||
| 25 | /* ----------------------------------------------------------------------------- | ||
| 26 | * Device Access | ||
| 27 | */ | ||
| 28 | |||
| 29 | static inline u32 vsp1_rpf_read(struct vsp1_rwpf *rpf, u32 reg) | ||
| 30 | { | ||
| 31 | return vsp1_read(rpf->entity.vsp1, | ||
| 32 | reg + rpf->entity.index * VI6_RPF_OFFSET); | ||
| 33 | } | ||
| 34 | |||
| 35 | static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) | ||
| 36 | { | ||
| 37 | vsp1_write(rpf->entity.vsp1, | ||
| 38 | reg + rpf->entity.index * VI6_RPF_OFFSET, data); | ||
| 39 | } | ||
| 40 | |||
| 41 | /* ----------------------------------------------------------------------------- | ||
| 42 | * V4L2 Subdevice Core Operations | ||
| 43 | */ | ||
| 44 | |||
| 45 | static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) | ||
| 46 | { | ||
| 47 | struct vsp1_rwpf *rpf = to_rwpf(subdev); | ||
| 48 | const struct vsp1_format_info *fmtinfo = rpf->video.fmtinfo; | ||
| 49 | const struct v4l2_pix_format_mplane *format = &rpf->video.format; | ||
| 50 | u32 pstride; | ||
| 51 | u32 infmt; | ||
| 52 | |||
| 53 | if (!enable) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | /* Source size and stride. Cropping isn't supported yet. */ | ||
| 57 | vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, | ||
| 58 | (format->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | | ||
| 59 | (format->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); | ||
| 60 | vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, | ||
| 61 | (format->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | | ||
| 62 | (format->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); | ||
| 63 | |||
| 64 | pstride = format->plane_fmt[0].bytesperline | ||
| 65 | << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; | ||
| 66 | if (format->num_planes > 1) | ||
| 67 | pstride |= format->plane_fmt[1].bytesperline | ||
| 68 | << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; | ||
| 69 | |||
| 70 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); | ||
| 71 | |||
| 72 | /* Format */ | ||
| 73 | infmt = VI6_RPF_INFMT_CIPM | ||
| 74 | | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); | ||
| 75 | |||
| 76 | if (fmtinfo->swap_yc) | ||
| 77 | infmt |= VI6_RPF_INFMT_SPYCS; | ||
| 78 | if (fmtinfo->swap_uv) | ||
| 79 | infmt |= VI6_RPF_INFMT_SPUVS; | ||
| 80 | |||
| 81 | if (rpf->entity.formats[RWPF_PAD_SINK].code != | ||
| 82 | rpf->entity.formats[RWPF_PAD_SOURCE].code) | ||
| 83 | infmt |= VI6_RPF_INFMT_CSC; | ||
| 84 | |||
| 85 | vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); | ||
| 86 | vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); | ||
| 87 | |||
| 88 | /* Output location. Composing isn't supported yet. */ | ||
| 89 | vsp1_rpf_write(rpf, VI6_RPF_LOC, 0); | ||
| 90 | |||
| 91 | /* Disable alpha, mask and color key. Set the alpha channel to a fixed | ||
| 92 | * value of 255. | ||
| 93 | */ | ||
| 94 | vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED); | ||
| 95 | vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, | ||
| 96 | 255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); | ||
| 97 | vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); | ||
| 98 | vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* ----------------------------------------------------------------------------- | ||
| 104 | * V4L2 Subdevice Operations | ||
| 105 | */ | ||
| 106 | |||
| 107 | static struct v4l2_subdev_video_ops rpf_video_ops = { | ||
| 108 | .s_stream = rpf_s_stream, | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct v4l2_subdev_pad_ops rpf_pad_ops = { | ||
| 112 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, | ||
| 113 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | ||
| 114 | .get_fmt = vsp1_rwpf_get_format, | ||
| 115 | .set_fmt = vsp1_rwpf_set_format, | ||
| 116 | }; | ||
| 117 | |||
| 118 | static struct v4l2_subdev_ops rpf_ops = { | ||
| 119 | .video = &rpf_video_ops, | ||
| 120 | .pad = &rpf_pad_ops, | ||
| 121 | }; | ||
| 122 | |||
| 123 | /* ----------------------------------------------------------------------------- | ||
| 124 | * Video Device Operations | ||
| 125 | */ | ||
| 126 | |||
| 127 | static void rpf_vdev_queue(struct vsp1_video *video, | ||
| 128 | struct vsp1_video_buffer *buf) | ||
| 129 | { | ||
| 130 | struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video); | ||
| 131 | |||
| 132 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, buf->addr[0]); | ||
| 133 | if (buf->buf.num_planes > 1) | ||
| 134 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, buf->addr[1]); | ||
| 135 | if (buf->buf.num_planes > 2) | ||
| 136 | vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, buf->addr[2]); | ||
| 137 | } | ||
| 138 | |||
| 139 | static const struct vsp1_video_operations rpf_vdev_ops = { | ||
| 140 | .queue = rpf_vdev_queue, | ||
| 141 | }; | ||
| 142 | |||
| 143 | /* ----------------------------------------------------------------------------- | ||
| 144 | * Initialization and Cleanup | ||
| 145 | */ | ||
| 146 | |||
| 147 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) | ||
| 148 | { | ||
| 149 | struct v4l2_subdev *subdev; | ||
| 150 | struct vsp1_video *video; | ||
| 151 | struct vsp1_rwpf *rpf; | ||
| 152 | int ret; | ||
| 153 | |||
| 154 | rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL); | ||
| 155 | if (rpf == NULL) | ||
| 156 | return ERR_PTR(-ENOMEM); | ||
| 157 | |||
| 158 | rpf->max_width = RPF_MAX_WIDTH; | ||
| 159 | rpf->max_height = RPF_MAX_HEIGHT; | ||
| 160 | |||
| 161 | rpf->entity.type = VSP1_ENTITY_RPF; | ||
| 162 | rpf->entity.index = index; | ||
| 163 | rpf->entity.id = VI6_DPR_NODE_RPF(index); | ||
| 164 | |||
| 165 | ret = vsp1_entity_init(vsp1, &rpf->entity, 2); | ||
| 166 | if (ret < 0) | ||
| 167 | return ERR_PTR(ret); | ||
| 168 | |||
| 169 | /* Initialize the V4L2 subdev. */ | ||
| 170 | subdev = &rpf->entity.subdev; | ||
| 171 | v4l2_subdev_init(subdev, &rpf_ops); | ||
| 172 | |||
| 173 | subdev->entity.ops = &vsp1_media_ops; | ||
| 174 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
| 175 | snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u", | ||
| 176 | dev_name(vsp1->dev), index); | ||
| 177 | v4l2_set_subdevdata(subdev, rpf); | ||
| 178 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 179 | |||
| 180 | vsp1_entity_init_formats(subdev, NULL); | ||
| 181 | |||
| 182 | /* Initialize the video device. */ | ||
| 183 | video = &rpf->video; | ||
| 184 | |||
| 185 | video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | ||
| 186 | video->vsp1 = vsp1; | ||
| 187 | video->ops = &rpf_vdev_ops; | ||
| 188 | |||
| 189 | ret = vsp1_video_init(video, &rpf->entity); | ||
| 190 | if (ret < 0) | ||
| 191 | goto error_video; | ||
| 192 | |||
| 193 | /* Connect the video device to the RPF. */ | ||
| 194 | ret = media_entity_create_link(&rpf->video.video.entity, 0, | ||
| 195 | &rpf->entity.subdev.entity, | ||
| 196 | RWPF_PAD_SINK, | ||
| 197 | MEDIA_LNK_FL_ENABLED | | ||
| 198 | MEDIA_LNK_FL_IMMUTABLE); | ||
| 199 | if (ret < 0) | ||
| 200 | goto error_link; | ||
| 201 | |||
| 202 | return rpf; | ||
| 203 | |||
| 204 | error_link: | ||
| 205 | vsp1_video_cleanup(video); | ||
| 206 | error_video: | ||
| 207 | media_entity_cleanup(&rpf->entity.subdev.entity); | ||
| 208 | return ERR_PTR(ret); | ||
| 209 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c new file mode 100644 index 000000000000..9752d5516ceb --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_rwpf.c -- R-Car VSP1 Read and Write Pixel Formatters | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <media/v4l2-subdev.h> | ||
| 15 | |||
| 16 | #include "vsp1.h" | ||
| 17 | #include "vsp1_rwpf.h" | ||
| 18 | #include "vsp1_video.h" | ||
| 19 | |||
| 20 | #define RWPF_MIN_WIDTH 1 | ||
| 21 | #define RWPF_MIN_HEIGHT 1 | ||
| 22 | |||
| 23 | /* ----------------------------------------------------------------------------- | ||
| 24 | * V4L2 Subdevice Pad Operations | ||
| 25 | */ | ||
| 26 | |||
| 27 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | ||
| 28 | struct v4l2_subdev_fh *fh, | ||
| 29 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 30 | { | ||
| 31 | static const unsigned int codes[] = { | ||
| 32 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 33 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 34 | }; | ||
| 35 | |||
| 36 | if (code->index >= ARRAY_SIZE(codes)) | ||
| 37 | return -EINVAL; | ||
| 38 | |||
| 39 | code->code = codes[code->index]; | ||
| 40 | |||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, | ||
| 45 | struct v4l2_subdev_fh *fh, | ||
| 46 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 47 | { | ||
| 48 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
| 49 | struct v4l2_mbus_framefmt *format; | ||
| 50 | |||
| 51 | format = v4l2_subdev_get_try_format(fh, fse->pad); | ||
| 52 | |||
| 53 | if (fse->index || fse->code != format->code) | ||
| 54 | return -EINVAL; | ||
| 55 | |||
| 56 | if (fse->pad == RWPF_PAD_SINK) { | ||
| 57 | fse->min_width = RWPF_MIN_WIDTH; | ||
| 58 | fse->max_width = rwpf->max_width; | ||
| 59 | fse->min_height = RWPF_MIN_HEIGHT; | ||
| 60 | fse->max_height = rwpf->max_height; | ||
| 61 | } else { | ||
| 62 | /* The size on the source pad are fixed and always identical to | ||
| 63 | * the size on the sink pad. | ||
| 64 | */ | ||
| 65 | fse->min_width = format->width; | ||
| 66 | fse->max_width = format->width; | ||
| 67 | fse->min_height = format->height; | ||
| 68 | fse->max_height = format->height; | ||
| 69 | } | ||
| 70 | |||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 75 | struct v4l2_subdev_format *fmt) | ||
| 76 | { | ||
| 77 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
| 78 | |||
| 79 | fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad, | ||
| 80 | fmt->which); | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 86 | struct v4l2_subdev_format *fmt) | ||
| 87 | { | ||
| 88 | struct vsp1_rwpf *rwpf = to_rwpf(subdev); | ||
| 89 | struct v4l2_mbus_framefmt *format; | ||
| 90 | |||
| 91 | /* Default to YUV if the requested format is not supported. */ | ||
| 92 | if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
| 93 | fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
| 94 | fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
| 95 | |||
| 96 | format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad, | ||
| 97 | fmt->which); | ||
| 98 | |||
| 99 | if (fmt->pad == RWPF_PAD_SOURCE) { | ||
| 100 | /* The RWPF performs format conversion but can't scale, only the | ||
| 101 | * format code can be changed on the source pad. | ||
| 102 | */ | ||
| 103 | format->code = fmt->format.code; | ||
| 104 | fmt->format = *format; | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | format->code = fmt->format.code; | ||
| 109 | format->width = clamp_t(unsigned int, fmt->format.width, | ||
| 110 | RWPF_MIN_WIDTH, rwpf->max_width); | ||
| 111 | format->height = clamp_t(unsigned int, fmt->format.height, | ||
| 112 | RWPF_MIN_HEIGHT, rwpf->max_height); | ||
| 113 | format->field = V4L2_FIELD_NONE; | ||
| 114 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 115 | |||
| 116 | fmt->format = *format; | ||
| 117 | |||
| 118 | /* Propagate the format to the source pad. */ | ||
| 119 | format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE, | ||
| 120 | fmt->which); | ||
| 121 | *format = fmt->format; | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h new file mode 100644 index 000000000000..c182d85f36b3 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_rwpf.h -- R-Car VSP1 Read and Write Pixel Formatters | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_RWPF_H__ | ||
| 14 | #define __VSP1_RWPF_H__ | ||
| 15 | |||
| 16 | #include <media/media-entity.h> | ||
| 17 | #include <media/v4l2-subdev.h> | ||
| 18 | |||
| 19 | #include "vsp1.h" | ||
| 20 | #include "vsp1_entity.h" | ||
| 21 | #include "vsp1_video.h" | ||
| 22 | |||
| 23 | #define RWPF_PAD_SINK 0 | ||
| 24 | #define RWPF_PAD_SOURCE 1 | ||
| 25 | |||
| 26 | struct vsp1_rwpf { | ||
| 27 | struct vsp1_entity entity; | ||
| 28 | struct vsp1_video video; | ||
| 29 | |||
| 30 | unsigned int max_width; | ||
| 31 | unsigned int max_height; | ||
| 32 | }; | ||
| 33 | |||
| 34 | static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) | ||
| 35 | { | ||
| 36 | return container_of(subdev, struct vsp1_rwpf, entity.subdev); | ||
| 37 | } | ||
| 38 | |||
| 39 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); | ||
| 40 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); | ||
| 41 | |||
| 42 | int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | ||
| 43 | struct v4l2_subdev_fh *fh, | ||
| 44 | struct v4l2_subdev_mbus_code_enum *code); | ||
| 45 | int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, | ||
| 46 | struct v4l2_subdev_fh *fh, | ||
| 47 | struct v4l2_subdev_frame_size_enum *fse); | ||
| 48 | int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 49 | struct v4l2_subdev_format *fmt); | ||
| 50 | int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 51 | struct v4l2_subdev_format *fmt); | ||
| 52 | |||
| 53 | #endif /* __VSP1_RWPF_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c new file mode 100644 index 000000000000..0e50b37f060d --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uds.c | |||
| @@ -0,0 +1,346 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_uds.c -- R-Car VSP1 Up and Down Scaler | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/gfp.h> | ||
| 16 | |||
| 17 | #include <media/v4l2-subdev.h> | ||
| 18 | |||
| 19 | #include "vsp1.h" | ||
| 20 | #include "vsp1_uds.h" | ||
| 21 | |||
| 22 | #define UDS_MIN_SIZE 4U | ||
| 23 | #define UDS_MAX_SIZE 8190U | ||
| 24 | |||
| 25 | #define UDS_MIN_FACTOR 0x0100 | ||
| 26 | #define UDS_MAX_FACTOR 0xffff | ||
| 27 | |||
| 28 | /* ----------------------------------------------------------------------------- | ||
| 29 | * Device Access | ||
| 30 | */ | ||
| 31 | |||
| 32 | static inline u32 vsp1_uds_read(struct vsp1_uds *uds, u32 reg) | ||
| 33 | { | ||
| 34 | return vsp1_read(uds->entity.vsp1, | ||
| 35 | reg + uds->entity.index * VI6_UDS_OFFSET); | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) | ||
| 39 | { | ||
| 40 | vsp1_write(uds->entity.vsp1, | ||
| 41 | reg + uds->entity.index * VI6_UDS_OFFSET, data); | ||
| 42 | } | ||
| 43 | |||
| 44 | /* ----------------------------------------------------------------------------- | ||
| 45 | * Scaling Computation | ||
| 46 | */ | ||
| 47 | |||
| 48 | /* | ||
| 49 | * uds_output_size - Return the output size for an input size and scaling ratio | ||
| 50 | * @input: input size in pixels | ||
| 51 | * @ratio: scaling ratio in U4.12 fixed-point format | ||
| 52 | */ | ||
| 53 | static unsigned int uds_output_size(unsigned int input, unsigned int ratio) | ||
| 54 | { | ||
| 55 | if (ratio > 4096) { | ||
| 56 | /* Down-scaling */ | ||
| 57 | unsigned int mp; | ||
| 58 | |||
| 59 | mp = ratio / 4096; | ||
| 60 | mp = mp < 4 ? 1 : (mp < 8 ? 2 : 4); | ||
| 61 | |||
| 62 | return (input - 1) / mp * mp * 4096 / ratio + 1; | ||
| 63 | } else { | ||
| 64 | /* Up-scaling */ | ||
| 65 | return (input - 1) * 4096 / ratio + 1; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | /* | ||
| 70 | * uds_output_limits - Return the min and max output sizes for an input size | ||
| 71 | * @input: input size in pixels | ||
| 72 | * @minimum: minimum output size (returned) | ||
| 73 | * @maximum: maximum output size (returned) | ||
| 74 | */ | ||
| 75 | static void uds_output_limits(unsigned int input, | ||
| 76 | unsigned int *minimum, unsigned int *maximum) | ||
| 77 | { | ||
| 78 | *minimum = max(uds_output_size(input, UDS_MAX_FACTOR), UDS_MIN_SIZE); | ||
| 79 | *maximum = min(uds_output_size(input, UDS_MIN_FACTOR), UDS_MAX_SIZE); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 83 | * uds_passband_width - Return the passband filter width for a scaling ratio | ||
| 84 | * @ratio: scaling ratio in U4.12 fixed-point format | ||
| 85 | */ | ||
| 86 | static unsigned int uds_passband_width(unsigned int ratio) | ||
| 87 | { | ||
| 88 | if (ratio >= 4096) { | ||
| 89 | /* Down-scaling */ | ||
| 90 | unsigned int mp; | ||
| 91 | |||
| 92 | mp = ratio / 4096; | ||
| 93 | mp = mp < 4 ? 1 : (mp < 8 ? 2 : 4); | ||
| 94 | |||
| 95 | return 64 * 4096 * mp / ratio; | ||
| 96 | } else { | ||
| 97 | /* Up-scaling */ | ||
| 98 | return 64; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | static unsigned int uds_compute_ratio(unsigned int input, unsigned int output) | ||
| 103 | { | ||
| 104 | /* TODO: This is an approximation that will need to be refined. */ | ||
| 105 | return (input - 1) * 4096 / (output - 1); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void uds_compute_ratios(struct vsp1_uds *uds) | ||
| 109 | { | ||
| 110 | struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK]; | ||
| 111 | struct v4l2_mbus_framefmt *output = | ||
| 112 | &uds->entity.formats[UDS_PAD_SOURCE]; | ||
| 113 | |||
| 114 | uds->hscale = uds_compute_ratio(input->width, output->width); | ||
| 115 | uds->vscale = uds_compute_ratio(input->height, output->height); | ||
| 116 | |||
| 117 | dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", | ||
| 118 | uds->hscale, uds->vscale); | ||
| 119 | } | ||
| 120 | |||
| 121 | /* ----------------------------------------------------------------------------- | ||
| 122 | * V4L2 Subdevice Core Operations | ||
| 123 | */ | ||
| 124 | |||
| 125 | static int uds_s_stream(struct v4l2_subdev *subdev, int enable) | ||
| 126 | { | ||
| 127 | const struct v4l2_mbus_framefmt *format; | ||
| 128 | struct vsp1_uds *uds = to_uds(subdev); | ||
| 129 | |||
| 130 | if (!enable) | ||
| 131 | return 0; | ||
| 132 | |||
| 133 | /* Enable multi-tap scaling. */ | ||
| 134 | vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_BC); | ||
| 135 | |||
| 136 | vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH, | ||
| 137 | (uds_passband_width(uds->hscale) | ||
| 138 | << VI6_UDS_PASS_BWIDTH_H_SHIFT) | | ||
| 139 | (uds_passband_width(uds->vscale) | ||
| 140 | << VI6_UDS_PASS_BWIDTH_V_SHIFT)); | ||
| 141 | |||
| 142 | |||
| 143 | /* Set the scaling ratios and the output size. */ | ||
| 144 | format = &uds->entity.formats[UDS_PAD_SOURCE]; | ||
| 145 | |||
| 146 | vsp1_uds_write(uds, VI6_UDS_SCALE, | ||
| 147 | (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) | | ||
| 148 | (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); | ||
| 149 | vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE, | ||
| 150 | (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | | ||
| 151 | (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* ----------------------------------------------------------------------------- | ||
| 157 | * V4L2 Subdevice Pad Operations | ||
| 158 | */ | ||
| 159 | |||
| 160 | static int uds_enum_mbus_code(struct v4l2_subdev *subdev, | ||
| 161 | struct v4l2_subdev_fh *fh, | ||
| 162 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 163 | { | ||
| 164 | static const unsigned int codes[] = { | ||
| 165 | V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 166 | V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 167 | }; | ||
| 168 | |||
| 169 | if (code->pad == UDS_PAD_SINK) { | ||
| 170 | if (code->index >= ARRAY_SIZE(codes)) | ||
| 171 | return -EINVAL; | ||
| 172 | |||
| 173 | code->code = codes[code->index]; | ||
| 174 | } else { | ||
| 175 | struct v4l2_mbus_framefmt *format; | ||
| 176 | |||
| 177 | /* The UDS can't perform format conversion, the sink format is | ||
| 178 | * always identical to the source format. | ||
| 179 | */ | ||
| 180 | if (code->index) | ||
| 181 | return -EINVAL; | ||
| 182 | |||
| 183 | format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK); | ||
| 184 | code->code = format->code; | ||
| 185 | } | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int uds_enum_frame_size(struct v4l2_subdev *subdev, | ||
| 191 | struct v4l2_subdev_fh *fh, | ||
| 192 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 193 | { | ||
| 194 | struct v4l2_mbus_framefmt *format; | ||
| 195 | |||
| 196 | format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK); | ||
| 197 | |||
| 198 | if (fse->index || fse->code != format->code) | ||
| 199 | return -EINVAL; | ||
| 200 | |||
| 201 | if (fse->pad == UDS_PAD_SINK) { | ||
| 202 | fse->min_width = UDS_MIN_SIZE; | ||
| 203 | fse->max_width = UDS_MAX_SIZE; | ||
| 204 | fse->min_height = UDS_MIN_SIZE; | ||
| 205 | fse->max_height = UDS_MAX_SIZE; | ||
| 206 | } else { | ||
| 207 | uds_output_limits(format->width, &fse->min_width, | ||
| 208 | &fse->max_width); | ||
| 209 | uds_output_limits(format->height, &fse->min_height, | ||
| 210 | &fse->max_height); | ||
| 211 | } | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 217 | struct v4l2_subdev_format *fmt) | ||
| 218 | { | ||
| 219 | struct vsp1_uds *uds = to_uds(subdev); | ||
| 220 | |||
| 221 | fmt->format = *vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad, | ||
| 222 | fmt->which); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_fh *fh, | ||
| 228 | unsigned int pad, struct v4l2_mbus_framefmt *fmt, | ||
| 229 | enum v4l2_subdev_format_whence which) | ||
| 230 | { | ||
| 231 | struct v4l2_mbus_framefmt *format; | ||
| 232 | unsigned int minimum; | ||
| 233 | unsigned int maximum; | ||
| 234 | |||
| 235 | switch (pad) { | ||
| 236 | case UDS_PAD_SINK: | ||
| 237 | /* Default to YUV if the requested format is not supported. */ | ||
| 238 | if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 && | ||
| 239 | fmt->code != V4L2_MBUS_FMT_AYUV8_1X32) | ||
| 240 | fmt->code = V4L2_MBUS_FMT_AYUV8_1X32; | ||
| 241 | |||
| 242 | fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE); | ||
| 243 | fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE); | ||
| 244 | break; | ||
| 245 | |||
| 246 | case UDS_PAD_SOURCE: | ||
| 247 | /* The UDS scales but can't perform format conversion. */ | ||
| 248 | format = vsp1_entity_get_pad_format(&uds->entity, fh, | ||
| 249 | UDS_PAD_SINK, which); | ||
| 250 | fmt->code = format->code; | ||
| 251 | |||
| 252 | uds_output_limits(format->width, &minimum, &maximum); | ||
| 253 | fmt->width = clamp(fmt->width, minimum, maximum); | ||
| 254 | uds_output_limits(format->height, &minimum, &maximum); | ||
| 255 | fmt->height = clamp(fmt->height, minimum, maximum); | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | fmt->field = V4L2_FIELD_NONE; | ||
| 260 | fmt->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, | ||
| 264 | struct v4l2_subdev_format *fmt) | ||
| 265 | { | ||
| 266 | struct vsp1_uds *uds = to_uds(subdev); | ||
| 267 | struct v4l2_mbus_framefmt *format; | ||
| 268 | |||
| 269 | uds_try_format(uds, fh, fmt->pad, &fmt->format, fmt->which); | ||
| 270 | |||
| 271 | format = vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad, | ||
| 272 | fmt->which); | ||
| 273 | *format = fmt->format; | ||
| 274 | |||
| 275 | if (fmt->pad == UDS_PAD_SINK) { | ||
| 276 | /* Propagate the format to the source pad. */ | ||
| 277 | format = vsp1_entity_get_pad_format(&uds->entity, fh, | ||
| 278 | UDS_PAD_SOURCE, fmt->which); | ||
| 279 | *format = fmt->format; | ||
| 280 | |||
| 281 | uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
| 285 | uds_compute_ratios(uds); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* ----------------------------------------------------------------------------- | ||
| 291 | * V4L2 Subdevice Operations | ||
| 292 | */ | ||
| 293 | |||
| 294 | static struct v4l2_subdev_video_ops uds_video_ops = { | ||
| 295 | .s_stream = uds_s_stream, | ||
| 296 | }; | ||
| 297 | |||
| 298 | static struct v4l2_subdev_pad_ops uds_pad_ops = { | ||
| 299 | .enum_mbus_code = uds_enum_mbus_code, | ||
| 300 | .enum_frame_size = uds_enum_frame_size, | ||
| 301 | .get_fmt = uds_get_format, | ||
| 302 | .set_fmt = uds_set_format, | ||
| 303 | }; | ||
| 304 | |||
| 305 | static struct v4l2_subdev_ops uds_ops = { | ||
| 306 | .video = &uds_video_ops, | ||
| 307 | .pad = &uds_pad_ops, | ||
| 308 | }; | ||
| 309 | |||
| 310 | /* ----------------------------------------------------------------------------- | ||
| 311 | * Initialization and Cleanup | ||
| 312 | */ | ||
| 313 | |||
| 314 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) | ||
| 315 | { | ||
| 316 | struct v4l2_subdev *subdev; | ||
| 317 | struct vsp1_uds *uds; | ||
| 318 | int ret; | ||
| 319 | |||
| 320 | uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL); | ||
| 321 | if (uds == NULL) | ||
| 322 | return ERR_PTR(-ENOMEM); | ||
| 323 | |||
| 324 | uds->entity.type = VSP1_ENTITY_UDS; | ||
| 325 | uds->entity.index = index; | ||
| 326 | uds->entity.id = VI6_DPR_NODE_UDS(index); | ||
| 327 | |||
| 328 | ret = vsp1_entity_init(vsp1, &uds->entity, 2); | ||
| 329 | if (ret < 0) | ||
| 330 | return ERR_PTR(ret); | ||
| 331 | |||
| 332 | /* Initialize the V4L2 subdev. */ | ||
| 333 | subdev = &uds->entity.subdev; | ||
| 334 | v4l2_subdev_init(subdev, &uds_ops); | ||
| 335 | |||
| 336 | subdev->entity.ops = &vsp1_media_ops; | ||
| 337 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
| 338 | snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u", | ||
| 339 | dev_name(vsp1->dev), index); | ||
| 340 | v4l2_set_subdevdata(subdev, uds); | ||
| 341 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 342 | |||
| 343 | vsp1_entity_init_formats(subdev, NULL); | ||
| 344 | |||
| 345 | return uds; | ||
| 346 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h new file mode 100644 index 000000000000..972a285abdb9 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uds.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_uds.h -- R-Car VSP1 Up and Down Scaler | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_UDS_H__ | ||
| 14 | #define __VSP1_UDS_H__ | ||
| 15 | |||
| 16 | #include <media/media-entity.h> | ||
| 17 | #include <media/v4l2-subdev.h> | ||
| 18 | |||
| 19 | #include "vsp1_entity.h" | ||
| 20 | |||
| 21 | struct vsp1_device; | ||
| 22 | |||
| 23 | #define UDS_PAD_SINK 0 | ||
| 24 | #define UDS_PAD_SOURCE 1 | ||
| 25 | |||
| 26 | struct vsp1_uds { | ||
| 27 | struct vsp1_entity entity; | ||
| 28 | |||
| 29 | unsigned int hscale; | ||
| 30 | unsigned int vscale; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev) | ||
| 34 | { | ||
| 35 | return container_of(subdev, struct vsp1_uds, entity.subdev); | ||
| 36 | } | ||
| 37 | |||
| 38 | struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); | ||
| 39 | |||
| 40 | #endif /* __VSP1_UDS_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c new file mode 100644 index 000000000000..714c53ef6c11 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_video.c | |||
| @@ -0,0 +1,1069 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_video.c -- R-Car VSP1 Video Node | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/list.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/v4l2-mediabus.h> | ||
| 20 | #include <linux/videodev2.h> | ||
| 21 | |||
| 22 | #include <media/media-entity.h> | ||
| 23 | #include <media/v4l2-dev.h> | ||
| 24 | #include <media/v4l2-fh.h> | ||
| 25 | #include <media/v4l2-ioctl.h> | ||
| 26 | #include <media/v4l2-subdev.h> | ||
| 27 | #include <media/videobuf2-core.h> | ||
| 28 | #include <media/videobuf2-dma-contig.h> | ||
| 29 | |||
| 30 | #include "vsp1.h" | ||
| 31 | #include "vsp1_entity.h" | ||
| 32 | #include "vsp1_rwpf.h" | ||
| 33 | #include "vsp1_video.h" | ||
| 34 | |||
| 35 | #define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV | ||
| 36 | #define VSP1_VIDEO_DEF_WIDTH 1024 | ||
| 37 | #define VSP1_VIDEO_DEF_HEIGHT 768 | ||
| 38 | |||
| 39 | #define VSP1_VIDEO_MIN_WIDTH 2U | ||
| 40 | #define VSP1_VIDEO_MAX_WIDTH 8190U | ||
| 41 | #define VSP1_VIDEO_MIN_HEIGHT 2U | ||
| 42 | #define VSP1_VIDEO_MAX_HEIGHT 8190U | ||
| 43 | |||
| 44 | /* ----------------------------------------------------------------------------- | ||
| 45 | * Helper functions | ||
| 46 | */ | ||
| 47 | |||
| 48 | static const struct vsp1_format_info vsp1_video_formats[] = { | ||
| 49 | { V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 50 | VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 51 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 52 | 1, { 8, 0, 0 }, false, false, 1, 1 }, | ||
| 53 | { V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 54 | VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 55 | VI6_RPF_DSWAP_P_WDS, | ||
| 56 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
| 57 | { V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 58 | VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 59 | VI6_RPF_DSWAP_P_WDS, | ||
| 60 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
| 61 | { V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 62 | VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 63 | VI6_RPF_DSWAP_P_WDS, | ||
| 64 | 1, { 16, 0, 0 }, false, false, 1, 1 }, | ||
| 65 | { V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 66 | VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 67 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 68 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | ||
| 69 | { V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 70 | VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 71 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 72 | 1, { 24, 0, 0 }, false, false, 1, 1 }, | ||
| 73 | { V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 74 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, | ||
| 75 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | ||
| 76 | { V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32, | ||
| 77 | VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 78 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 79 | 1, { 32, 0, 0 }, false, false, 1, 1 }, | ||
| 80 | { V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 81 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 82 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 83 | 1, { 16, 0, 0 }, false, false, 2, 1 }, | ||
| 84 | { V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 85 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 86 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 87 | 1, { 16, 0, 0 }, false, true, 2, 1 }, | ||
| 88 | { V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 89 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 90 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 91 | 1, { 16, 0, 0 }, true, false, 2, 1 }, | ||
| 92 | { V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 93 | VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 94 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 95 | 1, { 16, 0, 0 }, true, true, 2, 1 }, | ||
| 96 | { V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 97 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 98 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 99 | 2, { 8, 16, 0 }, false, false, 2, 2 }, | ||
| 100 | { V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 101 | VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 102 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 103 | 2, { 8, 16, 0 }, false, true, 2, 2 }, | ||
| 104 | { V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 105 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 106 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 107 | 2, { 8, 16, 0 }, false, false, 2, 1 }, | ||
| 108 | { V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 109 | VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 110 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 111 | 2, { 8, 16, 0 }, false, true, 2, 1 }, | ||
| 112 | { V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32, | ||
| 113 | VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | | ||
| 114 | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, | ||
| 115 | 3, { 8, 8, 8 }, false, false, 2, 2 }, | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * vsp1_get_format_info - Retrieve format information for a 4CC | ||
| 120 | * @fourcc: the format 4CC | ||
| 121 | * | ||
| 122 | * Return a pointer to the format information structure corresponding to the | ||
| 123 | * given V4L2 format 4CC, or NULL if no corresponding format can be found. | ||
| 124 | */ | ||
| 125 | static const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc) | ||
| 126 | { | ||
| 127 | unsigned int i; | ||
| 128 | |||
| 129 | for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) { | ||
| 130 | const struct vsp1_format_info *info = &vsp1_video_formats[i]; | ||
| 131 | |||
| 132 | if (info->fourcc == fourcc) | ||
| 133 | return info; | ||
| 134 | } | ||
| 135 | |||
| 136 | return NULL; | ||
| 137 | } | ||
| 138 | |||
| 139 | |||
| 140 | static struct v4l2_subdev * | ||
| 141 | vsp1_video_remote_subdev(struct media_pad *local, u32 *pad) | ||
| 142 | { | ||
| 143 | struct media_pad *remote; | ||
| 144 | |||
| 145 | remote = media_entity_remote_pad(local); | ||
| 146 | if (remote == NULL || | ||
| 147 | media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
| 148 | return NULL; | ||
| 149 | |||
| 150 | if (pad) | ||
| 151 | *pad = remote->index; | ||
| 152 | |||
| 153 | return media_entity_to_v4l2_subdev(remote->entity); | ||
| 154 | } | ||
| 155 | |||
| 156 | static int vsp1_video_verify_format(struct vsp1_video *video) | ||
| 157 | { | ||
| 158 | struct v4l2_subdev_format fmt; | ||
| 159 | struct v4l2_subdev *subdev; | ||
| 160 | int ret; | ||
| 161 | |||
| 162 | subdev = vsp1_video_remote_subdev(&video->pad, &fmt.pad); | ||
| 163 | if (subdev == NULL) | ||
| 164 | return -EINVAL; | ||
| 165 | |||
| 166 | fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; | ||
| 167 | ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); | ||
| 168 | if (ret < 0) | ||
| 169 | return ret == -ENOIOCTLCMD ? -EINVAL : ret; | ||
| 170 | |||
| 171 | if (video->fmtinfo->mbus != fmt.format.code || | ||
| 172 | video->format.height != fmt.format.height || | ||
| 173 | video->format.width != fmt.format.width) | ||
| 174 | return -EINVAL; | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int __vsp1_video_try_format(struct vsp1_video *video, | ||
| 180 | struct v4l2_pix_format_mplane *pix, | ||
| 181 | const struct vsp1_format_info **fmtinfo) | ||
| 182 | { | ||
| 183 | const struct vsp1_format_info *info; | ||
| 184 | unsigned int width = pix->width; | ||
| 185 | unsigned int height = pix->height; | ||
| 186 | unsigned int i; | ||
| 187 | |||
| 188 | /* Retrieve format information and select the default format if the | ||
| 189 | * requested format isn't supported. | ||
| 190 | */ | ||
| 191 | info = vsp1_get_format_info(pix->pixelformat); | ||
| 192 | if (info == NULL) | ||
| 193 | info = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); | ||
| 194 | |||
| 195 | pix->pixelformat = info->fourcc; | ||
| 196 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 197 | pix->field = V4L2_FIELD_NONE; | ||
| 198 | memset(pix->reserved, 0, sizeof(pix->reserved)); | ||
| 199 | |||
| 200 | /* Align the width and height for YUV 4:2:2 and 4:2:0 formats. */ | ||
| 201 | width = round_down(width, info->hsub); | ||
| 202 | height = round_down(height, info->vsub); | ||
| 203 | |||
| 204 | /* Clamp the width and height. */ | ||
| 205 | pix->width = clamp(width, VSP1_VIDEO_MIN_WIDTH, VSP1_VIDEO_MAX_WIDTH); | ||
| 206 | pix->height = clamp(height, VSP1_VIDEO_MIN_HEIGHT, | ||
| 207 | VSP1_VIDEO_MAX_HEIGHT); | ||
| 208 | |||
| 209 | /* Compute and clamp the stride and image size. While not documented in | ||
| 210 | * the datasheet, strides not aligned to a multiple of 128 bytes result | ||
| 211 | * in image corruption. | ||
| 212 | */ | ||
| 213 | for (i = 0; i < max(info->planes, 2U); ++i) { | ||
| 214 | unsigned int hsub = i > 0 ? info->hsub : 1; | ||
| 215 | unsigned int vsub = i > 0 ? info->vsub : 1; | ||
| 216 | unsigned int align = 128; | ||
| 217 | unsigned int bpl; | ||
| 218 | |||
| 219 | bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline, | ||
| 220 | pix->width / hsub * info->bpp[i] / 8, | ||
| 221 | round_down(65535U, align)); | ||
| 222 | |||
| 223 | pix->plane_fmt[i].bytesperline = round_up(bpl, align); | ||
| 224 | pix->plane_fmt[i].sizeimage = pix->plane_fmt[i].bytesperline | ||
| 225 | * pix->height / vsub; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (info->planes == 3) { | ||
| 229 | /* The second and third planes must have the same stride. */ | ||
| 230 | pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline; | ||
| 231 | pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage; | ||
| 232 | } | ||
| 233 | |||
| 234 | pix->num_planes = info->planes; | ||
| 235 | |||
| 236 | if (fmtinfo) | ||
| 237 | *fmtinfo = info; | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static bool | ||
| 243 | vsp1_video_format_adjust(struct vsp1_video *video, | ||
| 244 | const struct v4l2_pix_format_mplane *format, | ||
| 245 | struct v4l2_pix_format_mplane *adjust) | ||
| 246 | { | ||
| 247 | unsigned int i; | ||
| 248 | |||
| 249 | *adjust = *format; | ||
| 250 | __vsp1_video_try_format(video, adjust, NULL); | ||
| 251 | |||
| 252 | if (format->width != adjust->width || | ||
| 253 | format->height != adjust->height || | ||
| 254 | format->pixelformat != adjust->pixelformat || | ||
| 255 | format->num_planes != adjust->num_planes) | ||
| 256 | return false; | ||
| 257 | |||
| 258 | for (i = 0; i < format->num_planes; ++i) { | ||
| 259 | if (format->plane_fmt[i].bytesperline != | ||
| 260 | adjust->plane_fmt[i].bytesperline) | ||
| 261 | return false; | ||
| 262 | |||
| 263 | adjust->plane_fmt[i].sizeimage = | ||
| 264 | max(adjust->plane_fmt[i].sizeimage, | ||
| 265 | format->plane_fmt[i].sizeimage); | ||
| 266 | } | ||
| 267 | |||
| 268 | return true; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* ----------------------------------------------------------------------------- | ||
| 272 | * Pipeline Management | ||
| 273 | */ | ||
| 274 | |||
| 275 | static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, | ||
| 276 | struct vsp1_rwpf *output) | ||
| 277 | { | ||
| 278 | struct vsp1_entity *entity; | ||
| 279 | unsigned int entities = 0; | ||
| 280 | struct media_pad *pad; | ||
| 281 | bool uds_found = false; | ||
| 282 | |||
| 283 | pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); | ||
| 284 | |||
| 285 | while (1) { | ||
| 286 | if (pad == NULL) | ||
| 287 | return -EPIPE; | ||
| 288 | |||
| 289 | /* We've reached a video node, that shouldn't have happened. */ | ||
| 290 | if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | ||
| 291 | return -EPIPE; | ||
| 292 | |||
| 293 | entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity)); | ||
| 294 | |||
| 295 | /* We've reached the WPF, we're done. */ | ||
| 296 | if (entity->type == VSP1_ENTITY_WPF) | ||
| 297 | break; | ||
| 298 | |||
| 299 | /* Ensure the branch has no loop. */ | ||
| 300 | if (entities & (1 << entity->subdev.entity.id)) | ||
| 301 | return -EPIPE; | ||
| 302 | |||
| 303 | entities |= 1 << entity->subdev.entity.id; | ||
| 304 | |||
| 305 | /* UDS can't be chained. */ | ||
| 306 | if (entity->type == VSP1_ENTITY_UDS) { | ||
| 307 | if (uds_found) | ||
| 308 | return -EPIPE; | ||
| 309 | uds_found = true; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* Follow the source link. The link setup operations ensure | ||
| 313 | * that the output fan-out can't be more than one, there is thus | ||
| 314 | * no need to verify here that only a single source link is | ||
| 315 | * activated. | ||
| 316 | */ | ||
| 317 | pad = &entity->pads[entity->source_pad]; | ||
| 318 | pad = media_entity_remote_pad(pad); | ||
| 319 | } | ||
| 320 | |||
| 321 | /* The last entity must be the output WPF. */ | ||
| 322 | if (entity != &output->entity) | ||
| 323 | return -EPIPE; | ||
| 324 | |||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, | ||
| 329 | struct vsp1_video *video) | ||
| 330 | { | ||
| 331 | struct media_entity_graph graph; | ||
| 332 | struct media_entity *entity = &video->video.entity; | ||
| 333 | struct media_device *mdev = entity->parent; | ||
| 334 | unsigned int i; | ||
| 335 | int ret; | ||
| 336 | |||
| 337 | mutex_lock(&mdev->graph_mutex); | ||
| 338 | |||
| 339 | /* Walk the graph to locate the entities and video nodes. */ | ||
| 340 | media_entity_graph_walk_start(&graph, entity); | ||
| 341 | |||
| 342 | while ((entity = media_entity_graph_walk_next(&graph))) { | ||
| 343 | struct v4l2_subdev *subdev; | ||
| 344 | struct vsp1_rwpf *rwpf; | ||
| 345 | struct vsp1_entity *e; | ||
| 346 | |||
| 347 | if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) { | ||
| 348 | pipe->num_video++; | ||
| 349 | continue; | ||
| 350 | } | ||
| 351 | |||
| 352 | subdev = media_entity_to_v4l2_subdev(entity); | ||
| 353 | e = to_vsp1_entity(subdev); | ||
| 354 | list_add_tail(&e->list_pipe, &pipe->entities); | ||
| 355 | |||
| 356 | if (e->type == VSP1_ENTITY_RPF) { | ||
| 357 | rwpf = to_rwpf(subdev); | ||
| 358 | pipe->inputs[pipe->num_inputs++] = rwpf; | ||
| 359 | rwpf->video.pipe_index = pipe->num_inputs; | ||
| 360 | } else if (e->type == VSP1_ENTITY_WPF) { | ||
| 361 | rwpf = to_rwpf(subdev); | ||
| 362 | pipe->output = to_rwpf(subdev); | ||
| 363 | rwpf->video.pipe_index = 0; | ||
| 364 | } else if (e->type == VSP1_ENTITY_LIF) { | ||
| 365 | pipe->lif = e; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | mutex_unlock(&mdev->graph_mutex); | ||
| 370 | |||
| 371 | /* We need one output and at least one input. */ | ||
| 372 | if (pipe->num_inputs == 0 || !pipe->output) { | ||
| 373 | ret = -EPIPE; | ||
| 374 | goto error; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Follow links downstream for each input and make sure the graph | ||
| 378 | * contains no loop and that all branches end at the output WPF. | ||
| 379 | */ | ||
| 380 | for (i = 0; i < pipe->num_inputs; ++i) { | ||
| 381 | ret = vsp1_pipeline_validate_branch(pipe->inputs[i], | ||
| 382 | pipe->output); | ||
| 383 | if (ret < 0) | ||
| 384 | goto error; | ||
| 385 | } | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | |||
| 389 | error: | ||
| 390 | INIT_LIST_HEAD(&pipe->entities); | ||
| 391 | pipe->buffers_ready = 0; | ||
| 392 | pipe->num_video = 0; | ||
| 393 | pipe->num_inputs = 0; | ||
| 394 | pipe->output = NULL; | ||
| 395 | pipe->lif = NULL; | ||
| 396 | return ret; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int vsp1_pipeline_init(struct vsp1_pipeline *pipe, | ||
| 400 | struct vsp1_video *video) | ||
| 401 | { | ||
| 402 | int ret; | ||
| 403 | |||
| 404 | mutex_lock(&pipe->lock); | ||
| 405 | |||
| 406 | /* If we're the first user validate and initialize the pipeline. */ | ||
| 407 | if (pipe->use_count == 0) { | ||
| 408 | ret = vsp1_pipeline_validate(pipe, video); | ||
| 409 | if (ret < 0) | ||
| 410 | goto done; | ||
| 411 | } | ||
| 412 | |||
| 413 | pipe->use_count++; | ||
| 414 | ret = 0; | ||
| 415 | |||
| 416 | done: | ||
| 417 | mutex_unlock(&pipe->lock); | ||
| 418 | return ret; | ||
| 419 | } | ||
| 420 | |||
| 421 | static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) | ||
| 422 | { | ||
| 423 | mutex_lock(&pipe->lock); | ||
| 424 | |||
| 425 | /* If we're the last user clean up the pipeline. */ | ||
| 426 | if (--pipe->use_count == 0) { | ||
| 427 | INIT_LIST_HEAD(&pipe->entities); | ||
| 428 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
| 429 | pipe->buffers_ready = 0; | ||
| 430 | pipe->num_video = 0; | ||
| 431 | pipe->num_inputs = 0; | ||
| 432 | pipe->output = NULL; | ||
| 433 | pipe->lif = NULL; | ||
| 434 | } | ||
| 435 | |||
| 436 | mutex_unlock(&pipe->lock); | ||
| 437 | } | ||
| 438 | |||
| 439 | static void vsp1_pipeline_run(struct vsp1_pipeline *pipe) | ||
| 440 | { | ||
| 441 | struct vsp1_device *vsp1 = pipe->output->entity.vsp1; | ||
| 442 | |||
| 443 | vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD); | ||
| 444 | pipe->state = VSP1_PIPELINE_RUNNING; | ||
| 445 | pipe->buffers_ready = 0; | ||
| 446 | } | ||
| 447 | |||
| 448 | static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) | ||
| 449 | { | ||
| 450 | struct vsp1_entity *entity; | ||
| 451 | unsigned long flags; | ||
| 452 | int ret; | ||
| 453 | |||
| 454 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
| 455 | pipe->state = VSP1_PIPELINE_STOPPING; | ||
| 456 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
| 457 | |||
| 458 | ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED, | ||
| 459 | msecs_to_jiffies(500)); | ||
| 460 | ret = ret == 0 ? -ETIMEDOUT : 0; | ||
| 461 | |||
| 462 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | ||
| 463 | if (entity->route) | ||
| 464 | vsp1_write(entity->vsp1, entity->route, | ||
| 465 | VI6_DPR_NODE_UNUSED); | ||
| 466 | |||
| 467 | v4l2_subdev_call(&entity->subdev, video, s_stream, 0); | ||
| 468 | } | ||
| 469 | |||
| 470 | return ret; | ||
| 471 | } | ||
| 472 | |||
| 473 | static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) | ||
| 474 | { | ||
| 475 | unsigned int mask; | ||
| 476 | |||
| 477 | mask = ((1 << pipe->num_inputs) - 1) << 1; | ||
| 478 | if (!pipe->lif) | ||
| 479 | mask |= 1 << 0; | ||
| 480 | |||
| 481 | return pipe->buffers_ready == mask; | ||
| 482 | } | ||
| 483 | |||
| 484 | /* | ||
| 485 | * vsp1_video_complete_buffer - Complete the current buffer | ||
| 486 | * @video: the video node | ||
| 487 | * | ||
| 488 | * This function completes the current buffer by filling its sequence number, | ||
| 489 | * time stamp and payload size, and hands it back to the videobuf core. | ||
| 490 | * | ||
| 491 | * Return the next queued buffer or NULL if the queue is empty. | ||
| 492 | */ | ||
| 493 | static struct vsp1_video_buffer * | ||
| 494 | vsp1_video_complete_buffer(struct vsp1_video *video) | ||
| 495 | { | ||
| 496 | struct vsp1_video_buffer *next = NULL; | ||
| 497 | struct vsp1_video_buffer *done; | ||
| 498 | unsigned long flags; | ||
| 499 | unsigned int i; | ||
| 500 | |||
| 501 | spin_lock_irqsave(&video->irqlock, flags); | ||
| 502 | |||
| 503 | if (list_empty(&video->irqqueue)) { | ||
| 504 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
| 505 | return NULL; | ||
| 506 | } | ||
| 507 | |||
| 508 | done = list_first_entry(&video->irqqueue, | ||
| 509 | struct vsp1_video_buffer, queue); | ||
| 510 | list_del(&done->queue); | ||
| 511 | |||
| 512 | if (!list_empty(&video->irqqueue)) | ||
| 513 | next = list_first_entry(&video->irqqueue, | ||
| 514 | struct vsp1_video_buffer, queue); | ||
| 515 | |||
| 516 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
| 517 | |||
| 518 | done->buf.v4l2_buf.sequence = video->sequence++; | ||
| 519 | v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp); | ||
| 520 | for (i = 0; i < done->buf.num_planes; ++i) | ||
| 521 | vb2_set_plane_payload(&done->buf, i, done->length[i]); | ||
| 522 | vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE); | ||
| 523 | |||
| 524 | return next; | ||
| 525 | } | ||
| 526 | |||
| 527 | static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, | ||
| 528 | struct vsp1_video *video) | ||
| 529 | { | ||
| 530 | struct vsp1_video_buffer *buf; | ||
| 531 | unsigned long flags; | ||
| 532 | |||
| 533 | buf = vsp1_video_complete_buffer(video); | ||
| 534 | if (buf == NULL) | ||
| 535 | return; | ||
| 536 | |||
| 537 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
| 538 | |||
| 539 | video->ops->queue(video, buf); | ||
| 540 | pipe->buffers_ready |= 1 << video->pipe_index; | ||
| 541 | |||
| 542 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
| 543 | } | ||
| 544 | |||
| 545 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) | ||
| 546 | { | ||
| 547 | unsigned long flags; | ||
| 548 | unsigned int i; | ||
| 549 | |||
| 550 | if (pipe == NULL) | ||
| 551 | return; | ||
| 552 | |||
| 553 | /* Complete buffers on all video nodes. */ | ||
| 554 | for (i = 0; i < pipe->num_inputs; ++i) | ||
| 555 | vsp1_video_frame_end(pipe, &pipe->inputs[i]->video); | ||
| 556 | |||
| 557 | if (!pipe->lif) | ||
| 558 | vsp1_video_frame_end(pipe, &pipe->output->video); | ||
| 559 | |||
| 560 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
| 561 | |||
| 562 | /* If a stop has been requested, mark the pipeline as stopped and | ||
| 563 | * return. | ||
| 564 | */ | ||
| 565 | if (pipe->state == VSP1_PIPELINE_STOPPING) { | ||
| 566 | pipe->state = VSP1_PIPELINE_STOPPED; | ||
| 567 | wake_up(&pipe->wq); | ||
| 568 | goto done; | ||
| 569 | } | ||
| 570 | |||
| 571 | /* Restart the pipeline if ready. */ | ||
| 572 | if (vsp1_pipeline_ready(pipe)) | ||
| 573 | vsp1_pipeline_run(pipe); | ||
| 574 | |||
| 575 | done: | ||
| 576 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
| 577 | } | ||
| 578 | |||
| 579 | /* ----------------------------------------------------------------------------- | ||
| 580 | * videobuf2 Queue Operations | ||
| 581 | */ | ||
| 582 | |||
| 583 | static int | ||
| 584 | vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | ||
| 585 | unsigned int *nbuffers, unsigned int *nplanes, | ||
| 586 | unsigned int sizes[], void *alloc_ctxs[]) | ||
| 587 | { | ||
| 588 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
| 589 | const struct v4l2_pix_format_mplane *format; | ||
| 590 | struct v4l2_pix_format_mplane pix_mp; | ||
| 591 | unsigned int i; | ||
| 592 | |||
| 593 | if (fmt) { | ||
| 594 | /* Make sure the format is valid and adjust the sizeimage field | ||
| 595 | * if needed. | ||
| 596 | */ | ||
| 597 | if (!vsp1_video_format_adjust(video, &fmt->fmt.pix_mp, &pix_mp)) | ||
| 598 | return -EINVAL; | ||
| 599 | |||
| 600 | format = &pix_mp; | ||
| 601 | } else { | ||
| 602 | format = &video->format; | ||
| 603 | } | ||
| 604 | |||
| 605 | *nplanes = format->num_planes; | ||
| 606 | |||
| 607 | for (i = 0; i < format->num_planes; ++i) { | ||
| 608 | sizes[i] = format->plane_fmt[i].sizeimage; | ||
| 609 | alloc_ctxs[i] = video->alloc_ctx; | ||
| 610 | } | ||
| 611 | |||
| 612 | return 0; | ||
| 613 | } | ||
| 614 | |||
| 615 | static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) | ||
| 616 | { | ||
| 617 | struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); | ||
| 618 | struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); | ||
| 619 | const struct v4l2_pix_format_mplane *format = &video->format; | ||
| 620 | unsigned int i; | ||
| 621 | |||
| 622 | if (vb->num_planes < format->num_planes) | ||
| 623 | return -EINVAL; | ||
| 624 | |||
| 625 | buf->video = video; | ||
| 626 | |||
| 627 | for (i = 0; i < vb->num_planes; ++i) { | ||
| 628 | buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); | ||
| 629 | buf->length[i] = vb2_plane_size(vb, i); | ||
| 630 | |||
| 631 | if (buf->length[i] < format->plane_fmt[i].sizeimage) | ||
| 632 | return -EINVAL; | ||
| 633 | } | ||
| 634 | |||
| 635 | return 0; | ||
| 636 | } | ||
| 637 | |||
| 638 | static void vsp1_video_buffer_queue(struct vb2_buffer *vb) | ||
| 639 | { | ||
| 640 | struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); | ||
| 641 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
| 642 | struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb); | ||
| 643 | unsigned long flags; | ||
| 644 | bool empty; | ||
| 645 | |||
| 646 | spin_lock_irqsave(&video->irqlock, flags); | ||
| 647 | empty = list_empty(&video->irqqueue); | ||
| 648 | list_add_tail(&buf->queue, &video->irqqueue); | ||
| 649 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
| 650 | |||
| 651 | if (!empty) | ||
| 652 | return; | ||
| 653 | |||
| 654 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
| 655 | |||
| 656 | video->ops->queue(video, buf); | ||
| 657 | pipe->buffers_ready |= 1 << video->pipe_index; | ||
| 658 | |||
| 659 | if (vb2_is_streaming(&video->queue) && | ||
| 660 | vsp1_pipeline_ready(pipe)) | ||
| 661 | vsp1_pipeline_run(pipe); | ||
| 662 | |||
| 663 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
| 664 | } | ||
| 665 | |||
| 666 | static void vsp1_entity_route_setup(struct vsp1_entity *source) | ||
| 667 | { | ||
| 668 | struct vsp1_entity *sink; | ||
| 669 | |||
| 670 | if (source->route == 0) | ||
| 671 | return; | ||
| 672 | |||
| 673 | sink = container_of(source->sink, struct vsp1_entity, subdev.entity); | ||
| 674 | vsp1_write(source->vsp1, source->route, sink->id); | ||
| 675 | } | ||
| 676 | |||
| 677 | static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
| 678 | { | ||
| 679 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
| 680 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
| 681 | struct vsp1_entity *entity; | ||
| 682 | unsigned long flags; | ||
| 683 | int ret; | ||
| 684 | |||
| 685 | mutex_lock(&pipe->lock); | ||
| 686 | if (pipe->stream_count == pipe->num_video - 1) { | ||
| 687 | list_for_each_entry(entity, &pipe->entities, list_pipe) { | ||
| 688 | vsp1_entity_route_setup(entity); | ||
| 689 | |||
| 690 | ret = v4l2_subdev_call(&entity->subdev, video, | ||
| 691 | s_stream, 1); | ||
| 692 | if (ret < 0) { | ||
| 693 | mutex_unlock(&pipe->lock); | ||
| 694 | return ret; | ||
| 695 | } | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 699 | pipe->stream_count++; | ||
| 700 | mutex_unlock(&pipe->lock); | ||
| 701 | |||
| 702 | spin_lock_irqsave(&pipe->irqlock, flags); | ||
| 703 | if (vsp1_pipeline_ready(pipe)) | ||
| 704 | vsp1_pipeline_run(pipe); | ||
| 705 | spin_unlock_irqrestore(&pipe->irqlock, flags); | ||
| 706 | |||
| 707 | return 0; | ||
| 708 | } | ||
| 709 | |||
| 710 | static int vsp1_video_stop_streaming(struct vb2_queue *vq) | ||
| 711 | { | ||
| 712 | struct vsp1_video *video = vb2_get_drv_priv(vq); | ||
| 713 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); | ||
| 714 | unsigned long flags; | ||
| 715 | int ret; | ||
| 716 | |||
| 717 | mutex_lock(&pipe->lock); | ||
| 718 | if (--pipe->stream_count == 0) { | ||
| 719 | /* Stop the pipeline. */ | ||
| 720 | ret = vsp1_pipeline_stop(pipe); | ||
| 721 | if (ret == -ETIMEDOUT) | ||
| 722 | dev_err(video->vsp1->dev, "pipeline stop timeout\n"); | ||
| 723 | } | ||
| 724 | mutex_unlock(&pipe->lock); | ||
| 725 | |||
| 726 | vsp1_pipeline_cleanup(pipe); | ||
| 727 | media_entity_pipeline_stop(&video->video.entity); | ||
| 728 | |||
| 729 | /* Remove all buffers from the IRQ queue. */ | ||
| 730 | spin_lock_irqsave(&video->irqlock, flags); | ||
| 731 | INIT_LIST_HEAD(&video->irqqueue); | ||
| 732 | spin_unlock_irqrestore(&video->irqlock, flags); | ||
| 733 | |||
| 734 | return 0; | ||
| 735 | } | ||
| 736 | |||
| 737 | static struct vb2_ops vsp1_video_queue_qops = { | ||
| 738 | .queue_setup = vsp1_video_queue_setup, | ||
| 739 | .buf_prepare = vsp1_video_buffer_prepare, | ||
| 740 | .buf_queue = vsp1_video_buffer_queue, | ||
| 741 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 742 | .wait_finish = vb2_ops_wait_finish, | ||
| 743 | .start_streaming = vsp1_video_start_streaming, | ||
| 744 | .stop_streaming = vsp1_video_stop_streaming, | ||
| 745 | }; | ||
| 746 | |||
| 747 | /* ----------------------------------------------------------------------------- | ||
| 748 | * V4L2 ioctls | ||
| 749 | */ | ||
| 750 | |||
| 751 | static int | ||
| 752 | vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) | ||
| 753 | { | ||
| 754 | struct v4l2_fh *vfh = file->private_data; | ||
| 755 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
| 756 | |||
| 757 | cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING | ||
| 758 | | V4L2_CAP_VIDEO_CAPTURE_MPLANE | ||
| 759 | | V4L2_CAP_VIDEO_OUTPUT_MPLANE; | ||
| 760 | |||
| 761 | if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
| 762 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | ||
| 763 | | V4L2_CAP_STREAMING; | ||
| 764 | else | ||
| 765 | cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | ||
| 766 | | V4L2_CAP_STREAMING; | ||
| 767 | |||
| 768 | strlcpy(cap->driver, "vsp1", sizeof(cap->driver)); | ||
| 769 | strlcpy(cap->card, video->video.name, sizeof(cap->card)); | ||
| 770 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | ||
| 771 | dev_name(video->vsp1->dev)); | ||
| 772 | |||
| 773 | return 0; | ||
| 774 | } | ||
| 775 | |||
| 776 | static int | ||
| 777 | vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format) | ||
| 778 | { | ||
| 779 | struct v4l2_fh *vfh = file->private_data; | ||
| 780 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
| 781 | |||
| 782 | if (format->type != video->queue.type) | ||
| 783 | return -EINVAL; | ||
| 784 | |||
| 785 | mutex_lock(&video->lock); | ||
| 786 | format->fmt.pix_mp = video->format; | ||
| 787 | mutex_unlock(&video->lock); | ||
| 788 | |||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | static int | ||
| 793 | vsp1_video_try_format(struct file *file, void *fh, struct v4l2_format *format) | ||
| 794 | { | ||
| 795 | struct v4l2_fh *vfh = file->private_data; | ||
| 796 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
| 797 | |||
| 798 | if (format->type != video->queue.type) | ||
| 799 | return -EINVAL; | ||
| 800 | |||
| 801 | return __vsp1_video_try_format(video, &format->fmt.pix_mp, NULL); | ||
| 802 | } | ||
| 803 | |||
| 804 | static int | ||
| 805 | vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format) | ||
| 806 | { | ||
| 807 | struct v4l2_fh *vfh = file->private_data; | ||
| 808 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
| 809 | const struct vsp1_format_info *info; | ||
| 810 | int ret; | ||
| 811 | |||
| 812 | if (format->type != video->queue.type) | ||
| 813 | return -EINVAL; | ||
| 814 | |||
| 815 | ret = __vsp1_video_try_format(video, &format->fmt.pix_mp, &info); | ||
| 816 | if (ret < 0) | ||
| 817 | return ret; | ||
| 818 | |||
| 819 | mutex_lock(&video->lock); | ||
| 820 | |||
| 821 | if (vb2_is_busy(&video->queue)) { | ||
| 822 | ret = -EBUSY; | ||
| 823 | goto done; | ||
| 824 | } | ||
| 825 | |||
| 826 | video->format = format->fmt.pix_mp; | ||
| 827 | video->fmtinfo = info; | ||
| 828 | |||
| 829 | done: | ||
| 830 | mutex_unlock(&video->lock); | ||
| 831 | return ret; | ||
| 832 | } | ||
| 833 | |||
| 834 | static int | ||
| 835 | vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | ||
| 836 | { | ||
| 837 | struct v4l2_fh *vfh = file->private_data; | ||
| 838 | struct vsp1_video *video = to_vsp1_video(vfh->vdev); | ||
| 839 | struct vsp1_pipeline *pipe; | ||
| 840 | int ret; | ||
| 841 | |||
| 842 | if (video->queue.owner && video->queue.owner != file->private_data) | ||
| 843 | return -EBUSY; | ||
| 844 | |||
| 845 | video->sequence = 0; | ||
| 846 | |||
| 847 | /* Start streaming on the pipeline. No link touching an entity in the | ||
| 848 | * pipeline can be activated or deactivated once streaming is started. | ||
| 849 | * | ||
| 850 | * Use the VSP1 pipeline object embedded in the first video object that | ||
| 851 | * starts streaming. | ||
| 852 | */ | ||
| 853 | pipe = video->video.entity.pipe | ||
| 854 | ? to_vsp1_pipeline(&video->video.entity) : &video->pipe; | ||
| 855 | |||
| 856 | ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); | ||
| 857 | if (ret < 0) | ||
| 858 | return ret; | ||
| 859 | |||
| 860 | /* Verify that the configured format matches the output of the connected | ||
| 861 | * subdev. | ||
| 862 | */ | ||
| 863 | ret = vsp1_video_verify_format(video); | ||
| 864 | if (ret < 0) | ||
| 865 | goto err_stop; | ||
| 866 | |||
| 867 | ret = vsp1_pipeline_init(pipe, video); | ||
| 868 | if (ret < 0) | ||
| 869 | goto err_stop; | ||
| 870 | |||
| 871 | /* Start the queue. */ | ||
| 872 | ret = vb2_streamon(&video->queue, type); | ||
| 873 | if (ret < 0) | ||
| 874 | goto err_cleanup; | ||
| 875 | |||
| 876 | return 0; | ||
| 877 | |||
| 878 | err_cleanup: | ||
| 879 | vsp1_pipeline_cleanup(pipe); | ||
| 880 | err_stop: | ||
| 881 | media_entity_pipeline_stop(&video->video.entity); | ||
| 882 | return ret; | ||
| 883 | } | ||
| 884 | |||
| 885 | static const struct v4l2_ioctl_ops vsp1_video_ioctl_ops = { | ||
| 886 | .vidioc_querycap = vsp1_video_querycap, | ||
| 887 | .vidioc_g_fmt_vid_cap_mplane = vsp1_video_get_format, | ||
| 888 | .vidioc_s_fmt_vid_cap_mplane = vsp1_video_set_format, | ||
| 889 | .vidioc_try_fmt_vid_cap_mplane = vsp1_video_try_format, | ||
| 890 | .vidioc_g_fmt_vid_out_mplane = vsp1_video_get_format, | ||
| 891 | .vidioc_s_fmt_vid_out_mplane = vsp1_video_set_format, | ||
| 892 | .vidioc_try_fmt_vid_out_mplane = vsp1_video_try_format, | ||
| 893 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
| 894 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
| 895 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
| 896 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
| 897 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | ||
| 898 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | ||
| 899 | .vidioc_streamon = vsp1_video_streamon, | ||
| 900 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
| 901 | }; | ||
| 902 | |||
| 903 | /* ----------------------------------------------------------------------------- | ||
| 904 | * V4L2 File Operations | ||
| 905 | */ | ||
| 906 | |||
| 907 | static int vsp1_video_open(struct file *file) | ||
| 908 | { | ||
| 909 | struct vsp1_video *video = video_drvdata(file); | ||
| 910 | struct v4l2_fh *vfh; | ||
| 911 | int ret = 0; | ||
| 912 | |||
| 913 | vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); | ||
| 914 | if (vfh == NULL) | ||
| 915 | return -ENOMEM; | ||
| 916 | |||
| 917 | v4l2_fh_init(vfh, &video->video); | ||
| 918 | v4l2_fh_add(vfh); | ||
| 919 | |||
| 920 | file->private_data = vfh; | ||
| 921 | |||
| 922 | if (!vsp1_device_get(video->vsp1)) { | ||
| 923 | ret = -EBUSY; | ||
| 924 | v4l2_fh_del(vfh); | ||
| 925 | kfree(vfh); | ||
| 926 | } | ||
| 927 | |||
| 928 | return ret; | ||
| 929 | } | ||
| 930 | |||
| 931 | static int vsp1_video_release(struct file *file) | ||
| 932 | { | ||
| 933 | struct vsp1_video *video = video_drvdata(file); | ||
| 934 | struct v4l2_fh *vfh = file->private_data; | ||
| 935 | |||
| 936 | mutex_lock(&video->lock); | ||
| 937 | if (video->queue.owner == vfh) { | ||
| 938 | vb2_queue_release(&video->queue); | ||
| 939 | video->queue.owner = NULL; | ||
| 940 | } | ||
| 941 | mutex_unlock(&video->lock); | ||
| 942 | |||
| 943 | vsp1_device_put(video->vsp1); | ||
| 944 | |||
| 945 | v4l2_fh_release(file); | ||
| 946 | |||
| 947 | file->private_data = NULL; | ||
| 948 | |||
| 949 | return 0; | ||
| 950 | } | ||
| 951 | |||
| 952 | static struct v4l2_file_operations vsp1_video_fops = { | ||
| 953 | .owner = THIS_MODULE, | ||
| 954 | .unlocked_ioctl = video_ioctl2, | ||
| 955 | .open = vsp1_video_open, | ||
| 956 | .release = vsp1_video_release, | ||
| 957 | .poll = vb2_fop_poll, | ||
| 958 | .mmap = vb2_fop_mmap, | ||
| 959 | }; | ||
| 960 | |||
| 961 | /* ----------------------------------------------------------------------------- | ||
| 962 | * Initialization and Cleanup | ||
| 963 | */ | ||
| 964 | |||
| 965 | int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf) | ||
| 966 | { | ||
| 967 | const char *direction; | ||
| 968 | int ret; | ||
| 969 | |||
| 970 | switch (video->type) { | ||
| 971 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: | ||
| 972 | direction = "output"; | ||
| 973 | video->pad.flags = MEDIA_PAD_FL_SINK; | ||
| 974 | break; | ||
| 975 | |||
| 976 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | ||
| 977 | direction = "input"; | ||
| 978 | video->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
| 979 | video->video.vfl_dir = VFL_DIR_TX; | ||
| 980 | break; | ||
| 981 | |||
| 982 | default: | ||
| 983 | return -EINVAL; | ||
| 984 | } | ||
| 985 | |||
| 986 | video->rwpf = rwpf; | ||
| 987 | |||
| 988 | mutex_init(&video->lock); | ||
| 989 | spin_lock_init(&video->irqlock); | ||
| 990 | INIT_LIST_HEAD(&video->irqqueue); | ||
| 991 | |||
| 992 | mutex_init(&video->pipe.lock); | ||
| 993 | spin_lock_init(&video->pipe.irqlock); | ||
| 994 | INIT_LIST_HEAD(&video->pipe.entities); | ||
| 995 | init_waitqueue_head(&video->pipe.wq); | ||
| 996 | video->pipe.state = VSP1_PIPELINE_STOPPED; | ||
| 997 | |||
| 998 | /* Initialize the media entity... */ | ||
| 999 | ret = media_entity_init(&video->video.entity, 1, &video->pad, 0); | ||
| 1000 | if (ret < 0) | ||
| 1001 | return ret; | ||
| 1002 | |||
| 1003 | /* ... and the format ... */ | ||
| 1004 | video->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); | ||
| 1005 | video->format.pixelformat = video->fmtinfo->fourcc; | ||
| 1006 | video->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
| 1007 | video->format.field = V4L2_FIELD_NONE; | ||
| 1008 | video->format.width = VSP1_VIDEO_DEF_WIDTH; | ||
| 1009 | video->format.height = VSP1_VIDEO_DEF_HEIGHT; | ||
| 1010 | video->format.num_planes = 1; | ||
| 1011 | video->format.plane_fmt[0].bytesperline = | ||
| 1012 | video->format.width * video->fmtinfo->bpp[0] / 8; | ||
| 1013 | video->format.plane_fmt[0].sizeimage = | ||
| 1014 | video->format.plane_fmt[0].bytesperline * video->format.height; | ||
| 1015 | |||
| 1016 | /* ... and the video node... */ | ||
| 1017 | video->video.v4l2_dev = &video->vsp1->v4l2_dev; | ||
| 1018 | video->video.fops = &vsp1_video_fops; | ||
| 1019 | snprintf(video->video.name, sizeof(video->video.name), "%s %s", | ||
| 1020 | rwpf->subdev.name, direction); | ||
| 1021 | video->video.vfl_type = VFL_TYPE_GRABBER; | ||
| 1022 | video->video.release = video_device_release_empty; | ||
| 1023 | video->video.ioctl_ops = &vsp1_video_ioctl_ops; | ||
| 1024 | |||
| 1025 | video_set_drvdata(&video->video, video); | ||
| 1026 | |||
| 1027 | /* ... and the buffers queue... */ | ||
| 1028 | video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev); | ||
| 1029 | if (IS_ERR(video->alloc_ctx)) | ||
| 1030 | goto error; | ||
| 1031 | |||
| 1032 | video->queue.type = video->type; | ||
| 1033 | video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; | ||
| 1034 | video->queue.lock = &video->lock; | ||
| 1035 | video->queue.drv_priv = video; | ||
| 1036 | video->queue.buf_struct_size = sizeof(struct vsp1_video_buffer); | ||
| 1037 | video->queue.ops = &vsp1_video_queue_qops; | ||
| 1038 | video->queue.mem_ops = &vb2_dma_contig_memops; | ||
| 1039 | video->queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; | ||
| 1040 | ret = vb2_queue_init(&video->queue); | ||
| 1041 | if (ret < 0) { | ||
| 1042 | dev_err(video->vsp1->dev, "failed to initialize vb2 queue\n"); | ||
| 1043 | goto error; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* ... and register the video device. */ | ||
| 1047 | video->video.queue = &video->queue; | ||
| 1048 | ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1); | ||
| 1049 | if (ret < 0) { | ||
| 1050 | dev_err(video->vsp1->dev, "failed to register video device\n"); | ||
| 1051 | goto error; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | return 0; | ||
| 1055 | |||
| 1056 | error: | ||
| 1057 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); | ||
| 1058 | vsp1_video_cleanup(video); | ||
| 1059 | return ret; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | void vsp1_video_cleanup(struct vsp1_video *video) | ||
| 1063 | { | ||
| 1064 | if (video_is_registered(&video->video)) | ||
| 1065 | video_unregister_device(&video->video); | ||
| 1066 | |||
| 1067 | vb2_dma_contig_cleanup_ctx(video->alloc_ctx); | ||
| 1068 | media_entity_cleanup(&video->video.entity); | ||
| 1069 | } | ||
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h new file mode 100644 index 000000000000..d8612a378345 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_video.h | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_video.h -- R-Car VSP1 Video Node | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __VSP1_VIDEO_H__ | ||
| 14 | #define __VSP1_VIDEO_H__ | ||
| 15 | |||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/wait.h> | ||
| 19 | |||
| 20 | #include <media/media-entity.h> | ||
| 21 | #include <media/videobuf2-core.h> | ||
| 22 | |||
| 23 | struct vsp1_video; | ||
| 24 | |||
| 25 | /* | ||
| 26 | * struct vsp1_format_info - VSP1 video format description | ||
| 27 | * @mbus: media bus format code | ||
| 28 | * @fourcc: V4L2 pixel format FCC identifier | ||
| 29 | * @planes: number of planes | ||
| 30 | * @bpp: bits per pixel | ||
| 31 | * @hwfmt: VSP1 hardware format | ||
| 32 | * @swap_yc: the Y and C components are swapped (Y comes before C) | ||
| 33 | * @swap_uv: the U and V components are swapped (V comes before U) | ||
| 34 | * @hsub: horizontal subsampling factor | ||
| 35 | * @vsub: vertical subsampling factor | ||
| 36 | */ | ||
| 37 | struct vsp1_format_info { | ||
| 38 | u32 fourcc; | ||
| 39 | unsigned int mbus; | ||
| 40 | unsigned int hwfmt; | ||
| 41 | unsigned int swap; | ||
| 42 | unsigned int planes; | ||
| 43 | unsigned int bpp[3]; | ||
| 44 | bool swap_yc; | ||
| 45 | bool swap_uv; | ||
| 46 | unsigned int hsub; | ||
| 47 | unsigned int vsub; | ||
| 48 | }; | ||
| 49 | |||
| 50 | enum vsp1_pipeline_state { | ||
| 51 | VSP1_PIPELINE_STOPPED, | ||
| 52 | VSP1_PIPELINE_RUNNING, | ||
| 53 | VSP1_PIPELINE_STOPPING, | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * struct vsp1_pipeline - A VSP1 hardware pipeline | ||
| 58 | * @media: the media pipeline | ||
| 59 | * @irqlock: protects the pipeline state | ||
| 60 | * @lock: protects the pipeline use count and stream count | ||
| 61 | */ | ||
| 62 | struct vsp1_pipeline { | ||
| 63 | struct media_pipeline pipe; | ||
| 64 | |||
| 65 | spinlock_t irqlock; | ||
| 66 | enum vsp1_pipeline_state state; | ||
| 67 | wait_queue_head_t wq; | ||
| 68 | |||
| 69 | struct mutex lock; | ||
| 70 | unsigned int use_count; | ||
| 71 | unsigned int stream_count; | ||
| 72 | unsigned int buffers_ready; | ||
| 73 | |||
| 74 | unsigned int num_video; | ||
| 75 | unsigned int num_inputs; | ||
| 76 | struct vsp1_rwpf *inputs[VPS1_MAX_RPF]; | ||
| 77 | struct vsp1_rwpf *output; | ||
| 78 | struct vsp1_entity *lif; | ||
| 79 | |||
| 80 | struct list_head entities; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) | ||
| 84 | { | ||
| 85 | if (likely(e->pipe)) | ||
| 86 | return container_of(e->pipe, struct vsp1_pipeline, pipe); | ||
| 87 | else | ||
| 88 | return NULL; | ||
| 89 | } | ||
| 90 | |||
| 91 | struct vsp1_video_buffer { | ||
| 92 | struct vsp1_video *video; | ||
| 93 | struct vb2_buffer buf; | ||
| 94 | struct list_head queue; | ||
| 95 | |||
| 96 | dma_addr_t addr[3]; | ||
| 97 | unsigned int length[3]; | ||
| 98 | }; | ||
| 99 | |||
| 100 | static inline struct vsp1_video_buffer * | ||
| 101 | to_vsp1_video_buffer(struct vb2_buffer *vb) | ||
| 102 | { | ||
| 103 | return container_of(vb, struct vsp1_video_buffer, buf); | ||
| 104 | } | ||
| 105 | |||
| 106 | struct vsp1_video_operations { | ||
| 107 | void (*queue)(struct vsp1_video *video, struct vsp1_video_buffer *buf); | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct vsp1_video { | ||
| 111 | struct vsp1_device *vsp1; | ||
| 112 | struct vsp1_entity *rwpf; | ||
| 113 | |||
| 114 | const struct vsp1_video_operations *ops; | ||
| 115 | |||
| 116 | struct video_device video; | ||
| 117 | enum v4l2_buf_type type; | ||
| 118 | struct media_pad pad; | ||
| 119 | |||
| 120 | struct mutex lock; | ||
| 121 | struct v4l2_pix_format_mplane format; | ||
| 122 | const struct vsp1_format_info *fmtinfo; | ||
| 123 | |||
| 124 | struct vsp1_pipeline pipe; | ||
| 125 | unsigned int pipe_index; | ||
| 126 | |||
| 127 | struct vb2_queue queue; | ||
| 128 | void *alloc_ctx; | ||
| 129 | spinlock_t irqlock; | ||
| 130 | struct list_head irqqueue; | ||
| 131 | unsigned int sequence; | ||
| 132 | }; | ||
| 133 | |||
| 134 | static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev) | ||
| 135 | { | ||
| 136 | return container_of(vdev, struct vsp1_video, video); | ||
| 137 | } | ||
| 138 | |||
| 139 | int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf); | ||
| 140 | void vsp1_video_cleanup(struct vsp1_video *video); | ||
| 141 | |||
| 142 | void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); | ||
| 143 | |||
| 144 | #endif /* __VSP1_VIDEO_H__ */ | ||
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c new file mode 100644 index 000000000000..db4b85ee05fc --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_wpf.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | |||
| 16 | #include <media/v4l2-subdev.h> | ||
| 17 | |||
| 18 | #include "vsp1.h" | ||
| 19 | #include "vsp1_rwpf.h" | ||
| 20 | #include "vsp1_video.h" | ||
| 21 | |||
| 22 | #define WPF_MAX_WIDTH 2048 | ||
| 23 | #define WPF_MAX_HEIGHT 2048 | ||
| 24 | |||
| 25 | /* ----------------------------------------------------------------------------- | ||
| 26 | * Device Access | ||
| 27 | */ | ||
| 28 | |||
| 29 | static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg) | ||
| 30 | { | ||
| 31 | return vsp1_read(wpf->entity.vsp1, | ||
| 32 | reg + wpf->entity.index * VI6_WPF_OFFSET); | ||
| 33 | } | ||
| 34 | |||
| 35 | static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data) | ||
| 36 | { | ||
| 37 | vsp1_write(wpf->entity.vsp1, | ||
| 38 | reg + wpf->entity.index * VI6_WPF_OFFSET, data); | ||
| 39 | } | ||
| 40 | |||
| 41 | /* ----------------------------------------------------------------------------- | ||
| 42 | * V4L2 Subdevice Core Operations | ||
| 43 | */ | ||
| 44 | |||
| 45 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | ||
| 46 | { | ||
| 47 | struct vsp1_rwpf *wpf = to_rwpf(subdev); | ||
| 48 | struct vsp1_pipeline *pipe = | ||
| 49 | to_vsp1_pipeline(&wpf->entity.subdev.entity); | ||
| 50 | struct vsp1_device *vsp1 = wpf->entity.vsp1; | ||
| 51 | const struct v4l2_mbus_framefmt *format = | ||
| 52 | &wpf->entity.formats[RWPF_PAD_SOURCE]; | ||
| 53 | unsigned int i; | ||
| 54 | u32 srcrpf = 0; | ||
| 55 | u32 outfmt = 0; | ||
| 56 | |||
| 57 | if (!enable) { | ||
| 58 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Sources */ | ||
| 63 | for (i = 0; i < pipe->num_inputs; ++i) { | ||
| 64 | struct vsp1_rwpf *input = pipe->inputs[i]; | ||
| 65 | |||
| 66 | srcrpf |= VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index); | ||
| 67 | } | ||
| 68 | |||
| 69 | vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); | ||
| 70 | |||
| 71 | /* Destination stride. Cropping isn't supported yet. */ | ||
| 72 | if (!pipe->lif) { | ||
| 73 | struct v4l2_pix_format_mplane *format = &wpf->video.format; | ||
| 74 | |||
| 75 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, | ||
| 76 | format->plane_fmt[0].bytesperline); | ||
| 77 | if (format->num_planes > 1) | ||
| 78 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C, | ||
| 79 | format->plane_fmt[1].bytesperline); | ||
| 80 | } | ||
| 81 | |||
| 82 | vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, | ||
| 83 | format->width << VI6_WPF_SZCLIP_SIZE_SHIFT); | ||
| 84 | vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, | ||
| 85 | format->height << VI6_WPF_SZCLIP_SIZE_SHIFT); | ||
| 86 | |||
| 87 | /* Format */ | ||
| 88 | if (!pipe->lif) { | ||
| 89 | const struct vsp1_format_info *fmtinfo = wpf->video.fmtinfo; | ||
| 90 | |||
| 91 | outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; | ||
| 92 | |||
| 93 | if (fmtinfo->swap_yc) | ||
| 94 | outfmt |= VI6_WPF_OUTFMT_SPYCS; | ||
| 95 | if (fmtinfo->swap_uv) | ||
| 96 | outfmt |= VI6_WPF_OUTFMT_SPUVS; | ||
| 97 | |||
| 98 | vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); | ||
| 99 | } | ||
| 100 | |||
| 101 | if (wpf->entity.formats[RWPF_PAD_SINK].code != | ||
| 102 | wpf->entity.formats[RWPF_PAD_SOURCE].code) | ||
| 103 | outfmt |= VI6_WPF_OUTFMT_CSC; | ||
| 104 | |||
| 105 | vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt); | ||
| 106 | |||
| 107 | vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index), | ||
| 108 | VI6_DPR_WPF_FPORCH_FP_WPFN); | ||
| 109 | |||
| 110 | vsp1_write(vsp1, VI6_WPF_WRBCK_CTRL, 0); | ||
| 111 | |||
| 112 | /* Enable interrupts */ | ||
| 113 | vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0); | ||
| 114 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), | ||
| 115 | VI6_WFP_IRQ_ENB_FREE); | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | /* ----------------------------------------------------------------------------- | ||
| 121 | * V4L2 Subdevice Operations | ||
| 122 | */ | ||
| 123 | |||
| 124 | static struct v4l2_subdev_video_ops wpf_video_ops = { | ||
| 125 | .s_stream = wpf_s_stream, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct v4l2_subdev_pad_ops wpf_pad_ops = { | ||
| 129 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, | ||
| 130 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | ||
| 131 | .get_fmt = vsp1_rwpf_get_format, | ||
| 132 | .set_fmt = vsp1_rwpf_set_format, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static struct v4l2_subdev_ops wpf_ops = { | ||
| 136 | .video = &wpf_video_ops, | ||
| 137 | .pad = &wpf_pad_ops, | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* ----------------------------------------------------------------------------- | ||
| 141 | * Video Device Operations | ||
| 142 | */ | ||
| 143 | |||
| 144 | static void wpf_vdev_queue(struct vsp1_video *video, | ||
| 145 | struct vsp1_video_buffer *buf) | ||
| 146 | { | ||
| 147 | struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video); | ||
| 148 | |||
| 149 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]); | ||
| 150 | if (buf->buf.num_planes > 1) | ||
| 151 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]); | ||
| 152 | if (buf->buf.num_planes > 2) | ||
| 153 | vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]); | ||
| 154 | } | ||
| 155 | |||
| 156 | static const struct vsp1_video_operations wpf_vdev_ops = { | ||
| 157 | .queue = wpf_vdev_queue, | ||
| 158 | }; | ||
| 159 | |||
| 160 | /* ----------------------------------------------------------------------------- | ||
| 161 | * Initialization and Cleanup | ||
| 162 | */ | ||
| 163 | |||
| 164 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) | ||
| 165 | { | ||
| 166 | struct v4l2_subdev *subdev; | ||
| 167 | struct vsp1_video *video; | ||
| 168 | struct vsp1_rwpf *wpf; | ||
| 169 | unsigned int flags; | ||
| 170 | int ret; | ||
| 171 | |||
| 172 | wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); | ||
| 173 | if (wpf == NULL) | ||
| 174 | return ERR_PTR(-ENOMEM); | ||
| 175 | |||
| 176 | wpf->max_width = WPF_MAX_WIDTH; | ||
| 177 | wpf->max_height = WPF_MAX_HEIGHT; | ||
| 178 | |||
| 179 | wpf->entity.type = VSP1_ENTITY_WPF; | ||
| 180 | wpf->entity.index = index; | ||
| 181 | wpf->entity.id = VI6_DPR_NODE_WPF(index); | ||
| 182 | |||
| 183 | ret = vsp1_entity_init(vsp1, &wpf->entity, 2); | ||
| 184 | if (ret < 0) | ||
| 185 | return ERR_PTR(ret); | ||
| 186 | |||
| 187 | /* Initialize the V4L2 subdev. */ | ||
| 188 | subdev = &wpf->entity.subdev; | ||
| 189 | v4l2_subdev_init(subdev, &wpf_ops); | ||
| 190 | |||
| 191 | subdev->entity.ops = &vsp1_media_ops; | ||
| 192 | subdev->internal_ops = &vsp1_subdev_internal_ops; | ||
| 193 | snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u", | ||
| 194 | dev_name(vsp1->dev), index); | ||
| 195 | v4l2_set_subdevdata(subdev, wpf); | ||
| 196 | subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 197 | |||
| 198 | vsp1_entity_init_formats(subdev, NULL); | ||
| 199 | |||
| 200 | /* Initialize the video device. */ | ||
| 201 | video = &wpf->video; | ||
| 202 | |||
| 203 | video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | ||
| 204 | video->vsp1 = vsp1; | ||
| 205 | video->ops = &wpf_vdev_ops; | ||
| 206 | |||
| 207 | ret = vsp1_video_init(video, &wpf->entity); | ||
| 208 | if (ret < 0) | ||
| 209 | goto error_video; | ||
| 210 | |||
| 211 | /* Connect the video device to the WPF. All connections are immutable | ||
| 212 | * except for the WPF0 source link if a LIF is present. | ||
| 213 | */ | ||
| 214 | flags = MEDIA_LNK_FL_ENABLED; | ||
| 215 | if (!(vsp1->pdata->features & VSP1_HAS_LIF) || index != 0) | ||
| 216 | flags |= MEDIA_LNK_FL_IMMUTABLE; | ||
| 217 | |||
| 218 | ret = media_entity_create_link(&wpf->entity.subdev.entity, | ||
| 219 | RWPF_PAD_SOURCE, | ||
| 220 | &wpf->video.video.entity, 0, flags); | ||
| 221 | if (ret < 0) | ||
| 222 | goto error_link; | ||
| 223 | |||
| 224 | wpf->entity.sink = &wpf->video.video.entity; | ||
| 225 | |||
| 226 | return wpf; | ||
| 227 | |||
| 228 | error_link: | ||
| 229 | vsp1_video_cleanup(video); | ||
| 230 | error_video: | ||
| 231 | media_entity_cleanup(&wpf->entity.subdev.entity); | ||
| 232 | return ERR_PTR(ret); | ||
| 233 | } | ||
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d529ba788f41..39882ddd2594 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
| @@ -12,6 +12,9 @@ menuconfig RADIO_ADAPTERS | |||
| 12 | 12 | ||
| 13 | if RADIO_ADAPTERS && VIDEO_V4L2 | 13 | if RADIO_ADAPTERS && VIDEO_V4L2 |
| 14 | 14 | ||
| 15 | config RADIO_TEA575X | ||
| 16 | tristate | ||
| 17 | |||
| 15 | config RADIO_SI470X | 18 | config RADIO_SI470X |
| 16 | bool "Silicon Labs Si470x FM Radio Receiver support" | 19 | bool "Silicon Labs Si470x FM Radio Receiver support" |
| 17 | depends on VIDEO_V4L2 | 20 | depends on VIDEO_V4L2 |
| @@ -61,7 +64,8 @@ config USB_DSBR | |||
| 61 | 64 | ||
| 62 | config RADIO_MAXIRADIO | 65 | config RADIO_MAXIRADIO |
| 63 | tristate "Guillemot MAXI Radio FM 2000 radio" | 66 | tristate "Guillemot MAXI Radio FM 2000 radio" |
| 64 | depends on VIDEO_V4L2 && PCI && SND | 67 | depends on VIDEO_V4L2 && PCI |
| 68 | select RADIO_TEA575X | ||
| 65 | ---help--- | 69 | ---help--- |
| 66 | Choose Y here if you have this radio card. This card may also be | 70 | Choose Y here if you have this radio card. This card may also be |
| 67 | found as Gemtek PCI FM. | 71 | found as Gemtek PCI FM. |
| @@ -76,7 +80,8 @@ config RADIO_MAXIRADIO | |||
| 76 | 80 | ||
| 77 | config RADIO_SHARK | 81 | config RADIO_SHARK |
| 78 | tristate "Griffin radioSHARK USB radio receiver" | 82 | tristate "Griffin radioSHARK USB radio receiver" |
| 79 | depends on USB && SND | 83 | depends on USB |
| 84 | select RADIO_TEA575X | ||
| 80 | ---help--- | 85 | ---help--- |
| 81 | Choose Y here if you have this radio receiver. | 86 | Choose Y here if you have this radio receiver. |
| 82 | 87 | ||
| @@ -393,7 +398,8 @@ config RADIO_SF16FMI | |||
| 393 | 398 | ||
| 394 | config RADIO_SF16FMR2 | 399 | config RADIO_SF16FMR2 |
| 395 | tristate "SF16-FMR2/SF16-FMD2 Radio" | 400 | tristate "SF16-FMR2/SF16-FMD2 Radio" |
| 396 | depends on ISA && VIDEO_V4L2 && SND | 401 | depends on ISA && VIDEO_V4L2 |
| 402 | select RADIO_TEA575X | ||
| 397 | ---help--- | 403 | ---help--- |
| 398 | Choose Y here if you have one of these FM radio cards. | 404 | Choose Y here if you have one of these FM radio cards. |
| 399 | 405 | ||
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 0dcdb320cfc7..3b645601800d 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
| @@ -32,6 +32,7 @@ obj-$(CONFIG_RADIO_TEF6862) += tef6862.o | |||
| 32 | obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o | 32 | obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o |
| 33 | obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o | 33 | obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o |
| 34 | obj-$(CONFIG_RADIO_WL128X) += wl128x/ | 34 | obj-$(CONFIG_RADIO_WL128X) += wl128x/ |
| 35 | obj-$(CONFIG_RADIO_TEA575X) += tea575x.o | ||
| 35 | 36 | ||
| 36 | shark2-objs := radio-shark2.o radio-tea5777.o | 37 | shark2-objs := radio-shark2.o radio-tea5777.o |
| 37 | 38 | ||
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 177bcbd7a7c1..705dd6f9162c 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <media/v4l2-ioctl.h> | 26 | #include <media/v4l2-ioctl.h> |
| 27 | #include <media/v4l2-ctrls.h> | 27 | #include <media/v4l2-ctrls.h> |
| 28 | #include "radio-isa.h" | 28 | #include "radio-isa.h" |
| 29 | #include "lm7000.h" | ||
| 29 | 30 | ||
| 30 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); | 31 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); |
| 31 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); | 32 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); |
| @@ -54,18 +55,29 @@ struct aztech { | |||
| 54 | int curvol; | 55 | int curvol; |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | static void send_0_byte(struct aztech *az) | 58 | /* bit definitions for register read */ |
| 58 | { | 59 | #define AZTECH_BIT_NOT_TUNED (1 << 0) |
| 59 | udelay(radio_wait_time); | 60 | #define AZTECH_BIT_MONO (1 << 1) |
| 60 | outb_p(2 + az->curvol, az->isa.io); | 61 | /* bit definitions for register write */ |
| 61 | outb_p(64 + 2 + az->curvol, az->isa.io); | 62 | #define AZTECH_BIT_TUN_CE (1 << 1) |
| 62 | } | 63 | #define AZTECH_BIT_TUN_CLK (1 << 6) |
| 64 | #define AZTECH_BIT_TUN_DATA (1 << 7) | ||
| 65 | /* bits 0 and 2 are volume control, bits 3..5 are not connected */ | ||
| 63 | 66 | ||
| 64 | static void send_1_byte(struct aztech *az) | 67 | static void aztech_set_pins(void *handle, u8 pins) |
| 65 | { | 68 | { |
| 66 | udelay(radio_wait_time); | 69 | struct radio_isa_card *isa = handle; |
| 67 | outb_p(128 + 2 + az->curvol, az->isa.io); | 70 | struct aztech *az = container_of(isa, struct aztech, isa); |
| 68 | outb_p(128 + 64 + 2 + az->curvol, az->isa.io); | 71 | u8 bits = az->curvol; |
| 72 | |||
| 73 | if (pins & LM7000_DATA) | ||
| 74 | bits |= AZTECH_BIT_TUN_DATA; | ||
| 75 | if (pins & LM7000_CLK) | ||
| 76 | bits |= AZTECH_BIT_TUN_CLK; | ||
| 77 | if (pins & LM7000_CE) | ||
| 78 | bits |= AZTECH_BIT_TUN_CE; | ||
| 79 | |||
| 80 | outb_p(bits, az->isa.io); | ||
| 69 | } | 81 | } |
| 70 | 82 | ||
| 71 | static struct radio_isa_card *aztech_alloc(void) | 83 | static struct radio_isa_card *aztech_alloc(void) |
| @@ -77,58 +89,21 @@ static struct radio_isa_card *aztech_alloc(void) | |||
| 77 | 89 | ||
| 78 | static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) | 90 | static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) |
| 79 | { | 91 | { |
| 80 | struct aztech *az = container_of(isa, struct aztech, isa); | 92 | lm7000_set_freq(freq, isa, aztech_set_pins); |
| 81 | int i; | ||
| 82 | |||
| 83 | freq += 171200; /* Add 10.7 MHz IF */ | ||
| 84 | freq /= 800; /* Convert to 50 kHz units */ | ||
| 85 | |||
| 86 | send_0_byte(az); /* 0: LSB of frequency */ | ||
| 87 | |||
| 88 | for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ | ||
| 89 | if (freq & (1 << i)) | ||
| 90 | send_1_byte(az); | ||
| 91 | else | ||
| 92 | send_0_byte(az); | ||
| 93 | |||
| 94 | send_0_byte(az); /* 14: test bit - always 0 */ | ||
| 95 | send_0_byte(az); /* 15: test bit - always 0 */ | ||
| 96 | send_0_byte(az); /* 16: band data 0 - always 0 */ | ||
| 97 | if (isa->stereo) /* 17: stereo (1 to enable) */ | ||
| 98 | send_1_byte(az); | ||
| 99 | else | ||
| 100 | send_0_byte(az); | ||
| 101 | |||
| 102 | send_1_byte(az); /* 18: band data 1 - unknown */ | ||
| 103 | send_0_byte(az); /* 19: time base - always 0 */ | ||
| 104 | send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ | ||
| 105 | send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ | ||
| 106 | send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ | ||
| 107 | send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ | ||
| 108 | |||
| 109 | /* latch frequency */ | ||
| 110 | |||
| 111 | udelay(radio_wait_time); | ||
| 112 | outb_p(128 + 64 + az->curvol, az->isa.io); | ||
| 113 | 93 | ||
| 114 | return 0; | 94 | return 0; |
| 115 | } | 95 | } |
| 116 | 96 | ||
| 117 | /* thanks to Michael Dwyer for giving me a dose of clues in | ||
| 118 | * the signal strength department.. | ||
| 119 | * | ||
| 120 | * This card has a stereo bit - bit 0 set = mono, not set = stereo | ||
| 121 | */ | ||
| 122 | static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) | 97 | static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) |
| 123 | { | 98 | { |
| 124 | if (inb(isa->io) & 1) | 99 | if (inb(isa->io) & AZTECH_BIT_MONO) |
| 125 | return V4L2_TUNER_SUB_MONO; | 100 | return V4L2_TUNER_SUB_MONO; |
| 126 | return V4L2_TUNER_SUB_STEREO; | 101 | return V4L2_TUNER_SUB_STEREO; |
| 127 | } | 102 | } |
| 128 | 103 | ||
| 129 | static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo) | 104 | static u32 aztech_g_signal(struct radio_isa_card *isa) |
| 130 | { | 105 | { |
| 131 | return aztech_s_frequency(isa, isa->freq); | 106 | return (inb(isa->io) & AZTECH_BIT_NOT_TUNED) ? 0 : 0xffff; |
| 132 | } | 107 | } |
| 133 | 108 | ||
| 134 | static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) | 109 | static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) |
| @@ -146,8 +121,8 @@ static const struct radio_isa_ops aztech_ops = { | |||
| 146 | .alloc = aztech_alloc, | 121 | .alloc = aztech_alloc, |
| 147 | .s_mute_volume = aztech_s_mute_volume, | 122 | .s_mute_volume = aztech_s_mute_volume, |
| 148 | .s_frequency = aztech_s_frequency, | 123 | .s_frequency = aztech_s_frequency, |
| 149 | .s_stereo = aztech_s_stereo, | ||
| 150 | .g_rxsubchans = aztech_g_rxsubchans, | 124 | .g_rxsubchans = aztech_g_rxsubchans, |
| 125 | .g_signal = aztech_g_signal, | ||
| 151 | }; | 126 | }; |
| 152 | 127 | ||
| 153 | static const int aztech_ioports[] = { 0x350, 0x358 }; | 128 | static const int aztech_ioports[] = { 0x350, 0x358 }; |
| @@ -165,7 +140,7 @@ static struct radio_isa_driver aztech_driver = { | |||
| 165 | .radio_nr_params = radio_nr, | 140 | .radio_nr_params = radio_nr, |
| 166 | .io_ports = aztech_ioports, | 141 | .io_ports = aztech_ioports, |
| 167 | .num_of_io_ports = ARRAY_SIZE(aztech_ioports), | 142 | .num_of_io_ports = ARRAY_SIZE(aztech_ioports), |
| 168 | .region_size = 2, | 143 | .region_size = 8, |
| 169 | .card = "Aztech Radio", | 144 | .card = "Aztech Radio", |
| 170 | .ops = &aztech_ops, | 145 | .ops = &aztech_ops, |
| 171 | .has_stereo = true, | 146 | .has_stereo = true, |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index bd4d3a7cdadd..5236035f0f2a 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include <linux/videodev2.h> | 42 | #include <linux/videodev2.h> |
| 43 | #include <linux/io.h> | 43 | #include <linux/io.h> |
| 44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
| 45 | #include <sound/tea575x-tuner.h> | 45 | #include <media/tea575x.h> |
| 46 | #include <media/v4l2-device.h> | 46 | #include <media/v4l2-device.h> |
| 47 | #include <media/v4l2-ioctl.h> | 47 | #include <media/v4l2-ioctl.h> |
| 48 | #include <media/v4l2-fh.h> | 48 | #include <media/v4l2-fh.h> |
| @@ -200,15 +200,4 @@ static struct pci_driver maxiradio_driver = { | |||
| 200 | .remove = maxiradio_remove, | 200 | .remove = maxiradio_remove, |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | static int __init maxiradio_init(void) | 203 | module_pci_driver(maxiradio_driver); |
| 204 | { | ||
| 205 | return pci_register_driver(&maxiradio_driver); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void __exit maxiradio_exit(void) | ||
| 209 | { | ||
| 210 | pci_unregister_driver(&maxiradio_driver); | ||
| 211 | } | ||
| 212 | |||
| 213 | module_init(maxiradio_init); | ||
| 214 | module_exit(maxiradio_exit); | ||
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9c0990457a7c..f1e3714b5f16 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #include <linux/io.h> /* outb, outb_p */ | 14 | #include <linux/io.h> /* outb, outb_p */ |
| 15 | #include <linux/isa.h> | 15 | #include <linux/isa.h> |
| 16 | #include <linux/pnp.h> | 16 | #include <linux/pnp.h> |
| 17 | #include <sound/tea575x-tuner.h> | 17 | #include <media/tea575x.h> |
| 18 | 18 | ||
| 19 | MODULE_AUTHOR("Ondrej Zary"); | 19 | MODULE_AUTHOR("Ondrej Zary"); |
| 20 | MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); | 20 | MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); |
diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 8fa18ab5b725..b91477212413 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
| 34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
| 35 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
| 36 | #include <sound/tea575x-tuner.h> | 36 | #include <media/tea575x.h> |
| 37 | 37 | ||
| 38 | #if defined(CONFIG_LEDS_CLASS) || \ | 38 | #if defined(CONFIG_LEDS_CLASS) || \ |
| 39 | (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) | 39 | (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) |
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 62f3edec39bc..d6d4d60261d5 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c | |||
| @@ -142,8 +142,6 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); | |||
| 142 | /************************************************************************** | 142 | /************************************************************************** |
| 143 | * Software/Hardware Versions from Scratch Page | 143 | * Software/Hardware Versions from Scratch Page |
| 144 | **************************************************************************/ | 144 | **************************************************************************/ |
| 145 | #define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 | ||
| 146 | #define RADIO_SW_VERSION 1 | ||
| 147 | #define RADIO_HW_VERSION 1 | 145 | #define RADIO_HW_VERSION 1 |
| 148 | 146 | ||
| 149 | 147 | ||
| @@ -682,15 +680,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, | |||
| 682 | } | 680 | } |
| 683 | dev_info(&intf->dev, "software version %d, hardware version %d\n", | 681 | dev_info(&intf->dev, "software version %d, hardware version %d\n", |
| 684 | radio->software_version, radio->hardware_version); | 682 | radio->software_version, radio->hardware_version); |
| 685 | if (radio->software_version < RADIO_SW_VERSION) { | ||
| 686 | dev_warn(&intf->dev, | ||
| 687 | "This driver is known to work with " | ||
| 688 | "software version %hu,\n", RADIO_SW_VERSION); | ||
| 689 | dev_warn(&intf->dev, | ||
| 690 | "but the device has software version %hu.\n", | ||
| 691 | radio->software_version); | ||
| 692 | version_warning = 1; | ||
| 693 | } | ||
| 694 | if (radio->hardware_version < RADIO_HW_VERSION) { | 683 | if (radio->hardware_version < RADIO_HW_VERSION) { |
| 695 | dev_warn(&intf->dev, | 684 | dev_warn(&intf->dev, |
| 696 | "This driver is known to work with " | 685 | "This driver is known to work with " |
diff --git a/sound/i2c/other/tea575x-tuner.c b/drivers/media/radio/tea575x.c index 8a36a1d9803f..cef06981b7c9 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/drivers/media/radio/tea575x.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <media/v4l2-fh.h> | 31 | #include <media/v4l2-fh.h> |
| 32 | #include <media/v4l2-ioctl.h> | 32 | #include <media/v4l2-ioctl.h> |
| 33 | #include <media/v4l2-event.h> | 33 | #include <media/v4l2-event.h> |
| 34 | #include <sound/tea575x-tuner.h> | 34 | #include <media/tea575x.h> |
| 35 | 35 | ||
| 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
| 37 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); | 37 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); |
| @@ -486,13 +486,9 @@ static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { | |||
| 486 | .s_ctrl = tea575x_s_ctrl, | 486 | .s_ctrl = tea575x_s_ctrl, |
| 487 | }; | 487 | }; |
| 488 | 488 | ||
| 489 | /* | ||
| 490 | * initialize all the tea575x chips | ||
| 491 | */ | ||
| 492 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) | ||
| 493 | { | ||
| 494 | int retval; | ||
| 495 | 489 | ||
| 490 | int snd_tea575x_hw_init(struct snd_tea575x *tea) | ||
| 491 | { | ||
| 496 | tea->mute = true; | 492 | tea->mute = true; |
| 497 | 493 | ||
| 498 | /* Not all devices can or know how to read the data back. | 494 | /* Not all devices can or know how to read the data back. |
| @@ -507,6 +503,17 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) | |||
| 507 | tea->freq = 90500 * 16; /* 90.5Mhz default */ | 503 | tea->freq = 90500 * 16; /* 90.5Mhz default */ |
| 508 | snd_tea575x_set_freq(tea); | 504 | snd_tea575x_set_freq(tea); |
| 509 | 505 | ||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | EXPORT_SYMBOL(snd_tea575x_hw_init); | ||
| 509 | |||
| 510 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) | ||
| 511 | { | ||
| 512 | int retval = snd_tea575x_hw_init(tea); | ||
| 513 | |||
| 514 | if (retval) | ||
| 515 | return retval; | ||
| 516 | |||
| 510 | tea->vd = tea575x_radio; | 517 | tea->vd = tea575x_radio; |
| 511 | video_set_drvdata(&tea->vd, tea); | 518 | video_set_drvdata(&tea->vd, tea); |
| 512 | mutex_init(&tea->mutex); | 519 | mutex_init(&tea->mutex); |
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5a79c333d45e..11e84bcc23a1 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
| @@ -223,6 +223,8 @@ config IR_REDRAT3 | |||
| 223 | tristate "RedRat3 IR Transceiver" | 223 | tristate "RedRat3 IR Transceiver" |
| 224 | depends on USB_ARCH_HAS_HCD | 224 | depends on USB_ARCH_HAS_HCD |
| 225 | depends on RC_CORE | 225 | depends on RC_CORE |
| 226 | select NEW_LEDS | ||
| 227 | select LEDS_CLASS | ||
| 226 | select USB | 228 | select USB |
| 227 | ---help--- | 229 | ---help--- |
| 228 | Say Y here if you want to use a RedRat3 Infrared Transceiver. | 230 | Say Y here if you want to use a RedRat3 Infrared Transceiver. |
| @@ -248,7 +250,6 @@ config IR_WINBOND_CIR | |||
| 248 | depends on RC_CORE | 250 | depends on RC_CORE |
| 249 | select NEW_LEDS | 251 | select NEW_LEDS |
| 250 | select LEDS_CLASS | 252 | select LEDS_CLASS |
| 251 | select LEDS_TRIGGERS | ||
| 252 | select BITREVERSE | 253 | select BITREVERSE |
| 253 | ---help--- | 254 | ---help--- |
| 254 | Say Y here if you want to use the IR remote functionality found | 255 | Say Y here if you want to use the IR remote functionality found |
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index ed184f68c17c..c1444f84717d 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c | |||
| @@ -476,7 +476,7 @@ select_timeout: | |||
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | /* Enable the device for receive */ | 478 | /* Enable the device for receive */ |
| 479 | static void ene_rx_enable(struct ene_device *dev) | 479 | static void ene_rx_enable_hw(struct ene_device *dev) |
| 480 | { | 480 | { |
| 481 | u8 reg_value; | 481 | u8 reg_value; |
| 482 | 482 | ||
| @@ -504,11 +504,17 @@ static void ene_rx_enable(struct ene_device *dev) | |||
| 504 | 504 | ||
| 505 | /* enter idle mode */ | 505 | /* enter idle mode */ |
| 506 | ir_raw_event_set_idle(dev->rdev, true); | 506 | ir_raw_event_set_idle(dev->rdev, true); |
| 507 | } | ||
| 508 | |||
| 509 | /* Enable the device for receive - wrapper to track the state*/ | ||
| 510 | static void ene_rx_enable(struct ene_device *dev) | ||
| 511 | { | ||
| 512 | ene_rx_enable_hw(dev); | ||
| 507 | dev->rx_enabled = true; | 513 | dev->rx_enabled = true; |
| 508 | } | 514 | } |
| 509 | 515 | ||
| 510 | /* Disable the device receiver */ | 516 | /* Disable the device receiver */ |
| 511 | static void ene_rx_disable(struct ene_device *dev) | 517 | static void ene_rx_disable_hw(struct ene_device *dev) |
| 512 | { | 518 | { |
| 513 | /* disable inputs */ | 519 | /* disable inputs */ |
| 514 | ene_rx_enable_cir_engine(dev, false); | 520 | ene_rx_enable_cir_engine(dev, false); |
| @@ -516,8 +522,13 @@ static void ene_rx_disable(struct ene_device *dev) | |||
| 516 | 522 | ||
| 517 | /* disable hardware IRQ and firmware flag */ | 523 | /* disable hardware IRQ and firmware flag */ |
| 518 | ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); | 524 | ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); |
| 519 | |||
| 520 | ir_raw_event_set_idle(dev->rdev, true); | 525 | ir_raw_event_set_idle(dev->rdev, true); |
| 526 | } | ||
| 527 | |||
| 528 | /* Disable the device receiver - wrapper to track the state */ | ||
| 529 | static void ene_rx_disable(struct ene_device *dev) | ||
| 530 | { | ||
| 531 | ene_rx_disable_hw(dev); | ||
| 521 | dev->rx_enabled = false; | 532 | dev->rx_enabled = false; |
| 522 | } | 533 | } |
| 523 | 534 | ||
| @@ -1022,6 +1033,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
| 1022 | spin_lock_init(&dev->hw_lock); | 1033 | spin_lock_init(&dev->hw_lock); |
| 1023 | 1034 | ||
| 1024 | dev->hw_io = pnp_port_start(pnp_dev, 0); | 1035 | dev->hw_io = pnp_port_start(pnp_dev, 0); |
| 1036 | dev->irq = pnp_irq(pnp_dev, 0); | ||
| 1037 | |||
| 1025 | 1038 | ||
| 1026 | pnp_set_drvdata(pnp_dev, dev); | 1039 | pnp_set_drvdata(pnp_dev, dev); |
| 1027 | dev->pnp_dev = pnp_dev; | 1040 | dev->pnp_dev = pnp_dev; |
| @@ -1085,7 +1098,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
| 1085 | goto exit_unregister_device; | 1098 | goto exit_unregister_device; |
| 1086 | } | 1099 | } |
| 1087 | 1100 | ||
| 1088 | dev->irq = pnp_irq(pnp_dev, 0); | ||
| 1089 | if (request_irq(dev->irq, ene_isr, | 1101 | if (request_irq(dev->irq, ene_isr, |
| 1090 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { | 1102 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { |
| 1091 | goto exit_release_hw_io; | 1103 | goto exit_release_hw_io; |
| @@ -1123,9 +1135,8 @@ static void ene_remove(struct pnp_dev *pnp_dev) | |||
| 1123 | } | 1135 | } |
| 1124 | 1136 | ||
| 1125 | /* enable wake on IR (wakes on specific button on original remote) */ | 1137 | /* enable wake on IR (wakes on specific button on original remote) */ |
| 1126 | static void ene_enable_wake(struct ene_device *dev, int enable) | 1138 | static void ene_enable_wake(struct ene_device *dev, bool enable) |
| 1127 | { | 1139 | { |
| 1128 | enable = enable && device_may_wakeup(&dev->pnp_dev->dev); | ||
| 1129 | dbg("wake on IR %s", enable ? "enabled" : "disabled"); | 1140 | dbg("wake on IR %s", enable ? "enabled" : "disabled"); |
| 1130 | ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); | 1141 | ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); |
| 1131 | } | 1142 | } |
| @@ -1134,9 +1145,12 @@ static void ene_enable_wake(struct ene_device *dev, int enable) | |||
| 1134 | static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) | 1145 | static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) |
| 1135 | { | 1146 | { |
| 1136 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | 1147 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); |
| 1137 | ene_enable_wake(dev, true); | 1148 | bool wake = device_may_wakeup(&dev->pnp_dev->dev); |
| 1149 | |||
| 1150 | if (!wake && dev->rx_enabled) | ||
| 1151 | ene_rx_disable_hw(dev); | ||
| 1138 | 1152 | ||
| 1139 | /* TODO: add support for wake pattern */ | 1153 | ene_enable_wake(dev, wake); |
| 1140 | return 0; | 1154 | return 0; |
| 1141 | } | 1155 | } |
| 1142 | 1156 | ||
diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h index 6f978e85db8c..a7911e3b9bc0 100644 --- a/drivers/media/rc/ene_ir.h +++ b/drivers/media/rc/ene_ir.h | |||
| @@ -185,7 +185,7 @@ | |||
| 185 | #define __dbg(level, format, ...) \ | 185 | #define __dbg(level, format, ...) \ |
| 186 | do { \ | 186 | do { \ |
| 187 | if (debug >= level) \ | 187 | if (debug >= level) \ |
| 188 | pr_debug(format "\n", ## __VA_ARGS__); \ | 188 | pr_info(format "\n", ## __VA_ARGS__); \ |
| 189 | } while (0) | 189 | } while (0) |
| 190 | 190 | ||
| 191 | #define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) | 191 | #define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) |
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index a4ab2e6b3f82..19632b1c2190 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c | |||
| @@ -364,8 +364,8 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) | |||
| 364 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); | 364 | periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); |
| 365 | bytes = DIV_ROUND_UP(periods, 127); | 365 | bytes = DIV_ROUND_UP(periods, 127); |
| 366 | if (size + bytes > ir->bufsize) { | 366 | if (size + bytes > ir->bufsize) { |
| 367 | count = i; | 367 | rc = -EINVAL; |
| 368 | break; | 368 | goto out; |
| 369 | } | 369 | } |
| 370 | while (periods > 127) { | 370 | while (periods > 127) { |
| 371 | ir->packet->payload[size++] = 127 | space; | 371 | ir->packet->payload[size++] = 127 | space; |
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index e4561264e124..ed2c8a1ed8ca 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c | |||
| @@ -140,11 +140,20 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, | |||
| 140 | goto out; | 140 | goto out; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | for (i = 0; i < count; i++) { | ||
| 144 | if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { | ||
| 145 | ret = -EINVAL; | ||
| 146 | goto out; | ||
| 147 | } | ||
| 148 | |||
| 149 | duration += txbuf[i]; | ||
| 150 | } | ||
| 151 | |||
| 143 | ret = dev->tx_ir(dev, txbuf, count); | 152 | ret = dev->tx_ir(dev, txbuf, count); |
| 144 | if (ret < 0) | 153 | if (ret < 0) |
| 145 | goto out; | 154 | goto out; |
| 146 | 155 | ||
| 147 | for (i = 0; i < ret; i++) | 156 | for (duration = i = 0; i < ret; i++) |
| 148 | duration += txbuf[i]; | 157 | duration += txbuf[i]; |
| 149 | 158 | ||
| 150 | ret *= sizeof(unsigned int); | 159 | ret *= sizeof(unsigned int); |
| @@ -375,6 +384,7 @@ static int ir_lirc_register(struct rc_dev *dev) | |||
| 375 | drv->code_length = sizeof(struct ir_raw_event) * 8; | 384 | drv->code_length = sizeof(struct ir_raw_event) * 8; |
| 376 | drv->fops = &lirc_fops; | 385 | drv->fops = &lirc_fops; |
| 377 | drv->dev = &dev->dev; | 386 | drv->dev = &dev->dev; |
| 387 | drv->rdev = dev; | ||
| 378 | drv->owner = THIS_MODULE; | 388 | drv->owner = THIS_MODULE; |
| 379 | 389 | ||
| 380 | drv->minor = lirc_register_driver(drv); | 390 | drv->minor = lirc_register_driver(drv); |
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 8dc057b273f2..dc5cbffcd5a2 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/device.h> | 35 | #include <linux/device.h> |
| 36 | #include <linux/cdev.h> | 36 | #include <linux/cdev.h> |
| 37 | 37 | ||
| 38 | #include <media/rc-core.h> | ||
| 38 | #include <media/lirc.h> | 39 | #include <media/lirc.h> |
| 39 | #include <media/lirc_dev.h> | 40 | #include <media/lirc_dev.h> |
| 40 | 41 | ||
| @@ -467,6 +468,12 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) | |||
| 467 | goto error; | 468 | goto error; |
| 468 | } | 469 | } |
| 469 | 470 | ||
| 471 | if (ir->d.rdev) { | ||
| 472 | retval = rc_open(ir->d.rdev); | ||
| 473 | if (retval) | ||
| 474 | goto error; | ||
| 475 | } | ||
| 476 | |||
| 470 | cdev = ir->cdev; | 477 | cdev = ir->cdev; |
| 471 | if (try_module_get(cdev->owner)) { | 478 | if (try_module_get(cdev->owner)) { |
| 472 | ir->open++; | 479 | ir->open++; |
| @@ -511,6 +518,9 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file) | |||
| 511 | 518 | ||
| 512 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); | 519 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); |
| 513 | 520 | ||
| 521 | if (ir->d.rdev) | ||
| 522 | rc_close(ir->d.rdev); | ||
| 523 | |||
| 514 | ir->open--; | 524 | ir->open--; |
| 515 | if (ir->attached) { | 525 | if (ir->attached) { |
| 516 | ir->d.set_use_dec(ir->d.data); | 526 | ir->d.set_use_dec(ir->d.data); |
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1cf382a0b277..46da365c9c84 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 19 | #include <linux/leds.h> | ||
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| @@ -31,6 +32,7 @@ | |||
| 31 | /* Used to keep track of known keymaps */ | 32 | /* Used to keep track of known keymaps */ |
| 32 | static LIST_HEAD(rc_map_list); | 33 | static LIST_HEAD(rc_map_list); |
| 33 | static DEFINE_SPINLOCK(rc_map_lock); | 34 | static DEFINE_SPINLOCK(rc_map_lock); |
| 35 | static struct led_trigger *led_feedback; | ||
| 34 | 36 | ||
| 35 | static struct rc_map_list *seek_rc_map(const char *name) | 37 | static struct rc_map_list *seek_rc_map(const char *name) |
| 36 | { | 38 | { |
| @@ -535,6 +537,7 @@ static void ir_do_keyup(struct rc_dev *dev, bool sync) | |||
| 535 | 537 | ||
| 536 | IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); | 538 | IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); |
| 537 | input_report_key(dev->input_dev, dev->last_keycode, 0); | 539 | input_report_key(dev->input_dev, dev->last_keycode, 0); |
| 540 | led_trigger_event(led_feedback, LED_OFF); | ||
| 538 | if (sync) | 541 | if (sync) |
| 539 | input_sync(dev->input_dev); | 542 | input_sync(dev->input_dev); |
| 540 | dev->keypressed = false; | 543 | dev->keypressed = false; |
| @@ -648,6 +651,7 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode, | |||
| 648 | input_report_key(dev->input_dev, keycode, 1); | 651 | input_report_key(dev->input_dev, keycode, 1); |
| 649 | } | 652 | } |
| 650 | 653 | ||
| 654 | led_trigger_event(led_feedback, LED_FULL); | ||
| 651 | input_sync(dev->input_dev); | 655 | input_sync(dev->input_dev); |
| 652 | } | 656 | } |
| 653 | 657 | ||
| @@ -699,19 +703,50 @@ void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) | |||
| 699 | } | 703 | } |
| 700 | EXPORT_SYMBOL_GPL(rc_keydown_notimeout); | 704 | EXPORT_SYMBOL_GPL(rc_keydown_notimeout); |
| 701 | 705 | ||
| 706 | int rc_open(struct rc_dev *rdev) | ||
| 707 | { | ||
| 708 | int rval = 0; | ||
| 709 | |||
| 710 | if (!rdev) | ||
| 711 | return -EINVAL; | ||
| 712 | |||
| 713 | mutex_lock(&rdev->lock); | ||
| 714 | if (!rdev->users++ && rdev->open != NULL) | ||
| 715 | rval = rdev->open(rdev); | ||
| 716 | |||
| 717 | if (rval) | ||
| 718 | rdev->users--; | ||
| 719 | |||
| 720 | mutex_unlock(&rdev->lock); | ||
| 721 | |||
| 722 | return rval; | ||
| 723 | } | ||
| 724 | EXPORT_SYMBOL_GPL(rc_open); | ||
| 725 | |||
| 702 | static int ir_open(struct input_dev *idev) | 726 | static int ir_open(struct input_dev *idev) |
| 703 | { | 727 | { |
| 704 | struct rc_dev *rdev = input_get_drvdata(idev); | 728 | struct rc_dev *rdev = input_get_drvdata(idev); |
| 705 | 729 | ||
| 706 | return rdev->open(rdev); | 730 | return rc_open(rdev); |
| 731 | } | ||
| 732 | |||
| 733 | void rc_close(struct rc_dev *rdev) | ||
| 734 | { | ||
| 735 | if (rdev) { | ||
| 736 | mutex_lock(&rdev->lock); | ||
| 737 | |||
| 738 | if (!--rdev->users && rdev->close != NULL) | ||
| 739 | rdev->close(rdev); | ||
| 740 | |||
| 741 | mutex_unlock(&rdev->lock); | ||
| 742 | } | ||
| 707 | } | 743 | } |
| 744 | EXPORT_SYMBOL_GPL(rc_close); | ||
| 708 | 745 | ||
| 709 | static void ir_close(struct input_dev *idev) | 746 | static void ir_close(struct input_dev *idev) |
| 710 | { | 747 | { |
| 711 | struct rc_dev *rdev = input_get_drvdata(idev); | 748 | struct rc_dev *rdev = input_get_drvdata(idev); |
| 712 | 749 | rc_close(rdev); | |
| 713 | if (rdev) | ||
| 714 | rdev->close(rdev); | ||
| 715 | } | 750 | } |
| 716 | 751 | ||
| 717 | /* class for /sys/class/rc */ | 752 | /* class for /sys/class/rc */ |
| @@ -1076,7 +1111,14 @@ int rc_register_device(struct rc_dev *dev) | |||
| 1076 | memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); | 1111 | memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); |
| 1077 | dev->input_dev->phys = dev->input_phys; | 1112 | dev->input_dev->phys = dev->input_phys; |
| 1078 | dev->input_dev->name = dev->input_name; | 1113 | dev->input_dev->name = dev->input_name; |
| 1114 | |||
| 1115 | /* input_register_device can call ir_open, so unlock mutex here */ | ||
| 1116 | mutex_unlock(&dev->lock); | ||
| 1117 | |||
| 1079 | rc = input_register_device(dev->input_dev); | 1118 | rc = input_register_device(dev->input_dev); |
| 1119 | |||
| 1120 | mutex_lock(&dev->lock); | ||
| 1121 | |||
| 1080 | if (rc) | 1122 | if (rc) |
| 1081 | goto out_table; | 1123 | goto out_table; |
| 1082 | 1124 | ||
| @@ -1184,6 +1226,7 @@ static int __init rc_core_init(void) | |||
| 1184 | return rc; | 1226 | return rc; |
| 1185 | } | 1227 | } |
| 1186 | 1228 | ||
| 1229 | led_trigger_register_simple("rc-feedback", &led_feedback); | ||
| 1187 | rc_map_register(&empty_map); | 1230 | rc_map_register(&empty_map); |
| 1188 | 1231 | ||
| 1189 | return 0; | 1232 | return 0; |
| @@ -1192,6 +1235,7 @@ static int __init rc_core_init(void) | |||
| 1192 | static void __exit rc_core_exit(void) | 1235 | static void __exit rc_core_exit(void) |
| 1193 | { | 1236 | { |
| 1194 | class_unregister(&rc_class); | 1237 | class_unregister(&rc_class); |
| 1238 | led_trigger_unregister_simple(led_feedback); | ||
| 1195 | rc_map_unregister(&empty_map); | 1239 | rc_map_unregister(&empty_map); |
| 1196 | } | 1240 | } |
| 1197 | 1241 | ||
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 12167a6b5472..094484fac94c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | #include <asm/unaligned.h> | 48 | #include <asm/unaligned.h> |
| 49 | #include <linux/device.h> | 49 | #include <linux/device.h> |
| 50 | #include <linux/leds.h> | ||
| 50 | #include <linux/module.h> | 51 | #include <linux/module.h> |
| 51 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 52 | #include <linux/usb.h> | 53 | #include <linux/usb.h> |
| @@ -186,6 +187,13 @@ struct redrat3_dev { | |||
| 186 | struct rc_dev *rc; | 187 | struct rc_dev *rc; |
| 187 | struct device *dev; | 188 | struct device *dev; |
| 188 | 189 | ||
| 190 | /* led control */ | ||
| 191 | struct led_classdev led; | ||
| 192 | atomic_t flash; | ||
| 193 | struct usb_ctrlrequest flash_control; | ||
| 194 | struct urb *flash_urb; | ||
| 195 | u8 flash_in_buf; | ||
| 196 | |||
| 189 | /* save off the usb device pointer */ | 197 | /* save off the usb device pointer */ |
| 190 | struct usb_device *udev; | 198 | struct usb_device *udev; |
| 191 | 199 | ||
| @@ -206,8 +214,6 @@ struct redrat3_dev { | |||
| 206 | struct timer_list rx_timeout; | 214 | struct timer_list rx_timeout; |
| 207 | u32 hw_timeout; | 215 | u32 hw_timeout; |
| 208 | 216 | ||
| 209 | /* is the detector enabled*/ | ||
| 210 | bool det_enabled; | ||
| 211 | /* Is the device currently transmitting?*/ | 217 | /* Is the device currently transmitting?*/ |
| 212 | bool transmitting; | 218 | bool transmitting; |
| 213 | 219 | ||
| @@ -472,40 +478,19 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3) | |||
| 472 | return -EIO; | 478 | return -EIO; |
| 473 | } | 479 | } |
| 474 | 480 | ||
| 475 | rr3->det_enabled = true; | ||
| 476 | redrat3_issue_async(rr3); | 481 | redrat3_issue_async(rr3); |
| 477 | 482 | ||
| 478 | return 0; | 483 | return 0; |
| 479 | } | 484 | } |
| 480 | 485 | ||
| 481 | /* Disables the rr3 long range detector */ | ||
| 482 | static void redrat3_disable_detector(struct redrat3_dev *rr3) | ||
| 483 | { | ||
| 484 | struct device *dev = rr3->dev; | ||
| 485 | u8 ret; | ||
| 486 | |||
| 487 | rr3_ftr(dev, "Entering %s\n", __func__); | ||
| 488 | |||
| 489 | ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3); | ||
| 490 | if (ret != 0) | ||
| 491 | dev_err(dev, "%s: failure!\n", __func__); | ||
| 492 | |||
| 493 | ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | ||
| 494 | if (ret != 0) | ||
| 495 | dev_warn(dev, "%s: detector status: %d, should be 0\n", | ||
| 496 | __func__, ret); | ||
| 497 | |||
| 498 | rr3->det_enabled = false; | ||
| 499 | } | ||
| 500 | |||
| 501 | static inline void redrat3_delete(struct redrat3_dev *rr3, | 486 | static inline void redrat3_delete(struct redrat3_dev *rr3, |
| 502 | struct usb_device *udev) | 487 | struct usb_device *udev) |
| 503 | { | 488 | { |
| 504 | rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); | 489 | rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); |
| 505 | usb_kill_urb(rr3->read_urb); | 490 | usb_kill_urb(rr3->read_urb); |
| 506 | 491 | usb_kill_urb(rr3->flash_urb); | |
| 507 | usb_free_urb(rr3->read_urb); | 492 | usb_free_urb(rr3->read_urb); |
| 508 | 493 | usb_free_urb(rr3->flash_urb); | |
| 509 | usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), | 494 | usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize), |
| 510 | rr3->bulk_in_buf, rr3->dma_in); | 495 | rr3->bulk_in_buf, rr3->dma_in); |
| 511 | 496 | ||
| @@ -686,7 +671,8 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len) | |||
| 686 | goto out; | 671 | goto out; |
| 687 | } | 672 | } |
| 688 | 673 | ||
| 689 | if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length)) | 674 | if (rr3->bytes_read < be16_to_cpu(rr3->irdata.header.length) + |
| 675 | sizeof(struct redrat3_header)) | ||
| 690 | /* we're still accumulating data */ | 676 | /* we're still accumulating data */ |
| 691 | return 0; | 677 | return 0; |
| 692 | 678 | ||
| @@ -785,10 +771,10 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, | |||
| 785 | return -EAGAIN; | 771 | return -EAGAIN; |
| 786 | } | 772 | } |
| 787 | 773 | ||
| 788 | count = min_t(unsigned, count, RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN); | 774 | if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN) |
| 775 | return -EINVAL; | ||
| 789 | 776 | ||
| 790 | /* rr3 will disable rc detector on transmit */ | 777 | /* rr3 will disable rc detector on transmit */ |
| 791 | rr3->det_enabled = false; | ||
| 792 | rr3->transmitting = true; | 778 | rr3->transmitting = true; |
| 793 | 779 | ||
| 794 | sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); | 780 | sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); |
| @@ -825,8 +811,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, | |||
| 825 | &irdata->lens[curlencheck]); | 811 | &irdata->lens[curlencheck]); |
| 826 | curlencheck++; | 812 | curlencheck++; |
| 827 | } else { | 813 | } else { |
| 828 | count = i - 1; | 814 | ret = -EINVAL; |
| 829 | break; | 815 | goto out; |
| 830 | } | 816 | } |
| 831 | } | 817 | } |
| 832 | irdata->sigdata[i] = lencheck; | 818 | irdata->sigdata[i] = lencheck; |
| @@ -868,11 +854,48 @@ out: | |||
| 868 | 854 | ||
| 869 | rr3->transmitting = false; | 855 | rr3->transmitting = false; |
| 870 | /* rr3 re-enables rc detector because it was enabled before */ | 856 | /* rr3 re-enables rc detector because it was enabled before */ |
| 871 | rr3->det_enabled = true; | ||
| 872 | 857 | ||
| 873 | return ret; | 858 | return ret; |
| 874 | } | 859 | } |
| 875 | 860 | ||
| 861 | static void redrat3_brightness_set(struct led_classdev *led_dev, enum | ||
| 862 | led_brightness brightness) | ||
| 863 | { | ||
| 864 | struct redrat3_dev *rr3 = container_of(led_dev, struct redrat3_dev, | ||
| 865 | led); | ||
| 866 | |||
| 867 | if (brightness != LED_OFF && atomic_cmpxchg(&rr3->flash, 0, 1) == 0) { | ||
| 868 | int ret = usb_submit_urb(rr3->flash_urb, GFP_ATOMIC); | ||
| 869 | if (ret != 0) { | ||
| 870 | dev_dbg(rr3->dev, "%s: unexpected ret of %d\n", | ||
| 871 | __func__, ret); | ||
| 872 | atomic_set(&rr3->flash, 0); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | } | ||
| 876 | |||
| 877 | static void redrat3_led_complete(struct urb *urb) | ||
| 878 | { | ||
| 879 | struct redrat3_dev *rr3 = urb->context; | ||
| 880 | |||
| 881 | switch (urb->status) { | ||
| 882 | case 0: | ||
| 883 | break; | ||
| 884 | case -ECONNRESET: | ||
| 885 | case -ENOENT: | ||
| 886 | case -ESHUTDOWN: | ||
| 887 | usb_unlink_urb(urb); | ||
| 888 | return; | ||
| 889 | case -EPIPE: | ||
| 890 | default: | ||
| 891 | dev_dbg(rr3->dev, "Error: urb status = %d\n", urb->status); | ||
| 892 | break; | ||
| 893 | } | ||
| 894 | |||
| 895 | rr3->led.brightness = LED_OFF; | ||
| 896 | atomic_dec(&rr3->flash); | ||
| 897 | } | ||
| 898 | |||
| 876 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) | 899 | static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) |
| 877 | { | 900 | { |
| 878 | struct device *dev = rr3->dev; | 901 | struct device *dev = rr3->dev; |
| @@ -1016,10 +1039,35 @@ static int redrat3_dev_probe(struct usb_interface *intf, | |||
| 1016 | /* default.. will get overridden by any sends with a freq defined */ | 1039 | /* default.. will get overridden by any sends with a freq defined */ |
| 1017 | rr3->carrier = 38000; | 1040 | rr3->carrier = 38000; |
| 1018 | 1041 | ||
| 1042 | /* led control */ | ||
| 1043 | rr3->led.name = "redrat3:red:feedback"; | ||
| 1044 | rr3->led.default_trigger = "rc-feedback"; | ||
| 1045 | rr3->led.brightness_set = redrat3_brightness_set; | ||
| 1046 | retval = led_classdev_register(&intf->dev, &rr3->led); | ||
| 1047 | if (retval) | ||
| 1048 | goto error; | ||
| 1049 | |||
| 1050 | atomic_set(&rr3->flash, 0); | ||
| 1051 | rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1052 | if (!rr3->flash_urb) { | ||
| 1053 | retval = -ENOMEM; | ||
| 1054 | goto led_free_error; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | /* setup packet is 'c0 b9 0000 0000 0001' */ | ||
| 1058 | rr3->flash_control.bRequestType = 0xc0; | ||
| 1059 | rr3->flash_control.bRequest = RR3_BLINK_LED; | ||
| 1060 | rr3->flash_control.wLength = cpu_to_le16(1); | ||
| 1061 | |||
| 1062 | usb_fill_control_urb(rr3->flash_urb, udev, usb_rcvctrlpipe(udev, 0), | ||
| 1063 | (unsigned char *)&rr3->flash_control, | ||
| 1064 | &rr3->flash_in_buf, sizeof(rr3->flash_in_buf), | ||
| 1065 | redrat3_led_complete, rr3); | ||
| 1066 | |||
| 1019 | rr3->rc = redrat3_init_rc_dev(rr3); | 1067 | rr3->rc = redrat3_init_rc_dev(rr3); |
| 1020 | if (!rr3->rc) { | 1068 | if (!rr3->rc) { |
| 1021 | retval = -ENOMEM; | 1069 | retval = -ENOMEM; |
| 1022 | goto error; | 1070 | goto led_free_error; |
| 1023 | } | 1071 | } |
| 1024 | setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); | 1072 | setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); |
| 1025 | 1073 | ||
| @@ -1029,6 +1077,8 @@ static int redrat3_dev_probe(struct usb_interface *intf, | |||
| 1029 | rr3_ftr(dev, "Exiting %s\n", __func__); | 1077 | rr3_ftr(dev, "Exiting %s\n", __func__); |
| 1030 | return 0; | 1078 | return 0; |
| 1031 | 1079 | ||
| 1080 | led_free_error: | ||
| 1081 | led_classdev_unregister(&rr3->led); | ||
| 1032 | error: | 1082 | error: |
| 1033 | redrat3_delete(rr3, rr3->udev); | 1083 | redrat3_delete(rr3, rr3->udev); |
| 1034 | 1084 | ||
| @@ -1048,10 +1098,9 @@ static void redrat3_dev_disconnect(struct usb_interface *intf) | |||
| 1048 | if (!rr3) | 1098 | if (!rr3) |
| 1049 | return; | 1099 | return; |
| 1050 | 1100 | ||
| 1051 | redrat3_disable_detector(rr3); | ||
| 1052 | |||
| 1053 | usb_set_intfdata(intf, NULL); | 1101 | usb_set_intfdata(intf, NULL); |
| 1054 | rc_unregister_device(rr3->rc); | 1102 | rc_unregister_device(rr3->rc); |
| 1103 | led_classdev_unregister(&rr3->led); | ||
| 1055 | del_timer_sync(&rr3->rx_timeout); | 1104 | del_timer_sync(&rr3->rx_timeout); |
| 1056 | redrat3_delete(rr3, udev); | 1105 | redrat3_delete(rr3, udev); |
| 1057 | 1106 | ||
| @@ -1062,7 +1111,9 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1062 | { | 1111 | { |
| 1063 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); | 1112 | struct redrat3_dev *rr3 = usb_get_intfdata(intf); |
| 1064 | rr3_ftr(rr3->dev, "suspend\n"); | 1113 | rr3_ftr(rr3->dev, "suspend\n"); |
| 1114 | led_classdev_suspend(&rr3->led); | ||
| 1065 | usb_kill_urb(rr3->read_urb); | 1115 | usb_kill_urb(rr3->read_urb); |
| 1116 | usb_kill_urb(rr3->flash_urb); | ||
| 1066 | return 0; | 1117 | return 0; |
| 1067 | } | 1118 | } |
| 1068 | 1119 | ||
| @@ -1072,6 +1123,7 @@ static int redrat3_dev_resume(struct usb_interface *intf) | |||
| 1072 | rr3_ftr(rr3->dev, "resume\n"); | 1123 | rr3_ftr(rr3->dev, "resume\n"); |
| 1073 | if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) | 1124 | if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) |
| 1074 | return -EIO; | 1125 | return -EIO; |
| 1126 | led_classdev_resume(&rr3->led); | ||
| 1075 | return 0; | 1127 | return 0; |
| 1076 | } | 1128 | } |
| 1077 | 1129 | ||
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c index 891762d167ed..d8de2056a4f6 100644 --- a/drivers/media/rc/ttusbir.c +++ b/drivers/media/rc/ttusbir.c | |||
| @@ -302,6 +302,7 @@ static int ttusbir_probe(struct usb_interface *intf, | |||
| 302 | ttusbir_bulk_complete, tt); | 302 | ttusbir_bulk_complete, tt); |
| 303 | 303 | ||
| 304 | tt->led.name = "ttusbir:green:power"; | 304 | tt->led.name = "ttusbir:green:power"; |
| 305 | tt->led.default_trigger = "rc-feedback"; | ||
| 305 | tt->led.brightness_set = ttusbir_brightness_set; | 306 | tt->led.brightness_set = ttusbir_brightness_set; |
| 306 | tt->led.brightness_get = ttusbir_brightness_get; | 307 | tt->led.brightness_get = ttusbir_brightness_get; |
| 307 | tt->is_led_on = tt->led_on = true; | 308 | tt->is_led_on = tt->led_on = true; |
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 87af2d3ba601..98bd4960c75e 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c | |||
| @@ -213,13 +213,11 @@ struct wbcir_data { | |||
| 213 | 213 | ||
| 214 | /* RX state */ | 214 | /* RX state */ |
| 215 | enum wbcir_rxstate rxstate; | 215 | enum wbcir_rxstate rxstate; |
| 216 | struct led_trigger *rxtrigger; | ||
| 217 | int carrier_report_enabled; | 216 | int carrier_report_enabled; |
| 218 | u32 pulse_duration; | 217 | u32 pulse_duration; |
| 219 | 218 | ||
| 220 | /* TX state */ | 219 | /* TX state */ |
| 221 | enum wbcir_txstate txstate; | 220 | enum wbcir_txstate txstate; |
| 222 | struct led_trigger *txtrigger; | ||
| 223 | u32 txlen; | 221 | u32 txlen; |
| 224 | u32 txoff; | 222 | u32 txoff; |
| 225 | u32 *txbuf; | 223 | u32 *txbuf; |
| @@ -366,14 +364,11 @@ wbcir_idle_rx(struct rc_dev *dev, bool idle) | |||
| 366 | { | 364 | { |
| 367 | struct wbcir_data *data = dev->priv; | 365 | struct wbcir_data *data = dev->priv; |
| 368 | 366 | ||
| 369 | if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) { | 367 | if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) |
| 370 | data->rxstate = WBCIR_RXSTATE_ACTIVE; | 368 | data->rxstate = WBCIR_RXSTATE_ACTIVE; |
| 371 | led_trigger_event(data->rxtrigger, LED_FULL); | ||
| 372 | } | ||
| 373 | 369 | ||
| 374 | if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) { | 370 | if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) { |
| 375 | data->rxstate = WBCIR_RXSTATE_INACTIVE; | 371 | data->rxstate = WBCIR_RXSTATE_INACTIVE; |
| 376 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
| 377 | 372 | ||
| 378 | if (data->carrier_report_enabled) | 373 | if (data->carrier_report_enabled) |
| 379 | wbcir_carrier_report(data); | 374 | wbcir_carrier_report(data); |
| @@ -425,7 +420,6 @@ wbcir_irq_tx(struct wbcir_data *data) | |||
| 425 | case WBCIR_TXSTATE_INACTIVE: | 420 | case WBCIR_TXSTATE_INACTIVE: |
| 426 | /* TX FIFO empty */ | 421 | /* TX FIFO empty */ |
| 427 | space = 16; | 422 | space = 16; |
| 428 | led_trigger_event(data->txtrigger, LED_FULL); | ||
| 429 | break; | 423 | break; |
| 430 | case WBCIR_TXSTATE_ACTIVE: | 424 | case WBCIR_TXSTATE_ACTIVE: |
| 431 | /* TX FIFO low (3 bytes or less) */ | 425 | /* TX FIFO low (3 bytes or less) */ |
| @@ -464,7 +458,6 @@ wbcir_irq_tx(struct wbcir_data *data) | |||
| 464 | /* Clear TX underrun bit */ | 458 | /* Clear TX underrun bit */ |
| 465 | outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); | 459 | outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); |
| 466 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); | 460 | wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); |
| 467 | led_trigger_event(data->txtrigger, LED_OFF); | ||
| 468 | kfree(data->txbuf); | 461 | kfree(data->txbuf); |
| 469 | data->txbuf = NULL; | 462 | data->txbuf = NULL; |
| 470 | data->txstate = WBCIR_TXSTATE_INACTIVE; | 463 | data->txstate = WBCIR_TXSTATE_INACTIVE; |
| @@ -878,15 +871,13 @@ finish: | |||
| 878 | */ | 871 | */ |
| 879 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | 872 | wbcir_set_irqmask(data, WBCIR_IRQ_NONE); |
| 880 | disable_irq(data->irq); | 873 | disable_irq(data->irq); |
| 881 | |||
| 882 | /* Disable LED */ | ||
| 883 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
| 884 | led_trigger_event(data->txtrigger, LED_OFF); | ||
| 885 | } | 874 | } |
| 886 | 875 | ||
| 887 | static int | 876 | static int |
| 888 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) | 877 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) |
| 889 | { | 878 | { |
| 879 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
| 880 | led_classdev_suspend(&data->led); | ||
| 890 | wbcir_shutdown(device); | 881 | wbcir_shutdown(device); |
| 891 | return 0; | 882 | return 0; |
| 892 | } | 883 | } |
| @@ -1015,6 +1006,7 @@ wbcir_resume(struct pnp_dev *device) | |||
| 1015 | 1006 | ||
| 1016 | wbcir_init_hw(data); | 1007 | wbcir_init_hw(data); |
| 1017 | enable_irq(data->irq); | 1008 | enable_irq(data->irq); |
| 1009 | led_classdev_resume(&data->led); | ||
| 1018 | 1010 | ||
| 1019 | return 0; | 1011 | return 0; |
| 1020 | } | 1012 | } |
| @@ -1058,25 +1050,13 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
| 1058 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", | 1050 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", |
| 1059 | data->wbase, data->ebase, data->sbase, data->irq); | 1051 | data->wbase, data->ebase, data->sbase, data->irq); |
| 1060 | 1052 | ||
| 1061 | led_trigger_register_simple("cir-tx", &data->txtrigger); | ||
| 1062 | if (!data->txtrigger) { | ||
| 1063 | err = -ENOMEM; | ||
| 1064 | goto exit_free_data; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | led_trigger_register_simple("cir-rx", &data->rxtrigger); | ||
| 1068 | if (!data->rxtrigger) { | ||
| 1069 | err = -ENOMEM; | ||
| 1070 | goto exit_unregister_txtrigger; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | data->led.name = "cir::activity"; | 1053 | data->led.name = "cir::activity"; |
| 1074 | data->led.default_trigger = "cir-rx"; | 1054 | data->led.default_trigger = "rc-feedback"; |
| 1075 | data->led.brightness_set = wbcir_led_brightness_set; | 1055 | data->led.brightness_set = wbcir_led_brightness_set; |
| 1076 | data->led.brightness_get = wbcir_led_brightness_get; | 1056 | data->led.brightness_get = wbcir_led_brightness_get; |
| 1077 | err = led_classdev_register(&device->dev, &data->led); | 1057 | err = led_classdev_register(&device->dev, &data->led); |
| 1078 | if (err) | 1058 | if (err) |
| 1079 | goto exit_unregister_rxtrigger; | 1059 | goto exit_free_data; |
| 1080 | 1060 | ||
| 1081 | data->dev = rc_allocate_device(); | 1061 | data->dev = rc_allocate_device(); |
| 1082 | if (!data->dev) { | 1062 | if (!data->dev) { |
| @@ -1156,10 +1136,6 @@ exit_free_rc: | |||
| 1156 | rc_free_device(data->dev); | 1136 | rc_free_device(data->dev); |
| 1157 | exit_unregister_led: | 1137 | exit_unregister_led: |
| 1158 | led_classdev_unregister(&data->led); | 1138 | led_classdev_unregister(&data->led); |
| 1159 | exit_unregister_rxtrigger: | ||
| 1160 | led_trigger_unregister_simple(data->rxtrigger); | ||
| 1161 | exit_unregister_txtrigger: | ||
| 1162 | led_trigger_unregister_simple(data->txtrigger); | ||
| 1163 | exit_free_data: | 1139 | exit_free_data: |
| 1164 | kfree(data); | 1140 | kfree(data); |
| 1165 | pnp_set_drvdata(device, NULL); | 1141 | pnp_set_drvdata(device, NULL); |
| @@ -1187,8 +1163,6 @@ wbcir_remove(struct pnp_dev *device) | |||
| 1187 | 1163 | ||
| 1188 | rc_unregister_device(data->dev); | 1164 | rc_unregister_device(data->dev); |
| 1189 | 1165 | ||
| 1190 | led_trigger_unregister_simple(data->rxtrigger); | ||
| 1191 | led_trigger_unregister_simple(data->txtrigger); | ||
| 1192 | led_classdev_unregister(&data->led); | 1166 | led_classdev_unregister(&data->led); |
| 1193 | 1167 | ||
| 1194 | /* This is ok since &data->led isn't actually used */ | 1168 | /* This is ok since &data->led isn't actually used */ |
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index 1b33ed368abe..ad9309da4a91 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c | |||
| @@ -41,8 +41,9 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) | |||
| 41 | if (ret == 1) { | 41 | if (ret == 1) { |
| 42 | ret = 0; | 42 | ret = 0; |
| 43 | } else { | 43 | } else { |
| 44 | dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ | 44 | dev_warn(&priv->i2c->dev, |
| 45 | "len=%d\n", KBUILD_MODNAME, ret, reg, len); | 45 | "%s: i2c wr failed=%d reg=%02x len=%d\n", |
| 46 | KBUILD_MODNAME, ret, reg, len); | ||
| 46 | ret = -EREMOTEIO; | 47 | ret = -EREMOTEIO; |
| 47 | } | 48 | } |
| 48 | return ret; | 49 | return ret; |
| @@ -72,8 +73,9 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) | |||
| 72 | memcpy(val, buf, len); | 73 | memcpy(val, buf, len); |
| 73 | ret = 0; | 74 | ret = 0; |
| 74 | } else { | 75 | } else { |
| 75 | dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ | 76 | dev_warn(&priv->i2c->dev, |
| 76 | "len=%d\n", KBUILD_MODNAME, ret, reg, len); | 77 | "%s: i2c rd failed=%d reg=%02x len=%d\n", |
| 78 | KBUILD_MODNAME, ret, reg, len); | ||
| 77 | ret = -EREMOTEIO; | 79 | ret = -EREMOTEIO; |
| 78 | } | 80 | } |
| 79 | 81 | ||
| @@ -140,14 +142,12 @@ static int e4000_init(struct dvb_frontend *fe) | |||
| 140 | if (ret < 0) | 142 | if (ret < 0) |
| 141 | goto err; | 143 | goto err; |
| 142 | 144 | ||
| 143 | /* | ||
| 144 | * TODO: Implement DC offset control correctly. | ||
| 145 | * DC offsets has quite much effect for received signal quality in case | ||
| 146 | * of direct conversion tuners (Zero-IF). Surely we will now lose few | ||
| 147 | * decimals or even decibels from SNR... | ||
| 148 | */ | ||
| 149 | /* DC offset control */ | 145 | /* DC offset control */ |
| 150 | ret = e4000_wr_reg(priv, 0x2d, 0x0c); | 146 | ret = e4000_wr_reg(priv, 0x2d, 0x1f); |
| 147 | if (ret < 0) | ||
| 148 | goto err; | ||
| 149 | |||
| 150 | ret = e4000_wr_regs(priv, 0x70, "\x01\x01", 2); | ||
| 151 | if (ret < 0) | 151 | if (ret < 0) |
| 152 | goto err; | 152 | goto err; |
| 153 | 153 | ||
| @@ -203,12 +203,13 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
| 203 | struct e4000_priv *priv = fe->tuner_priv; | 203 | struct e4000_priv *priv = fe->tuner_priv; |
| 204 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 204 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 205 | int ret, i, sigma_delta; | 205 | int ret, i, sigma_delta; |
| 206 | unsigned int f_VCO; | 206 | unsigned int f_vco; |
| 207 | u8 buf[5]; | 207 | u8 buf[5], i_data[4], q_data[4]; |
| 208 | 208 | ||
| 209 | dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ | 209 | dev_dbg(&priv->i2c->dev, |
| 210 | "bandwidth_hz=%d\n", __func__, | 210 | "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", |
| 211 | c->delivery_system, c->frequency, c->bandwidth_hz); | 211 | __func__, c->delivery_system, c->frequency, |
| 212 | c->bandwidth_hz); | ||
| 212 | 213 | ||
| 213 | if (fe->ops.i2c_gate_ctrl) | 214 | if (fe->ops.i2c_gate_ctrl) |
| 214 | fe->ops.i2c_gate_ctrl(fe, 1); | 215 | fe->ops.i2c_gate_ctrl(fe, 1); |
| @@ -228,19 +229,19 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
| 228 | goto err; | 229 | goto err; |
| 229 | 230 | ||
| 230 | /* | 231 | /* |
| 231 | * Note: Currently f_VCO overflows when c->frequency is 1 073 741 824 Hz | 232 | * Note: Currently f_vco overflows when c->frequency is 1 073 741 824 Hz |
| 232 | * or more. | 233 | * or more. |
| 233 | */ | 234 | */ |
| 234 | f_VCO = c->frequency * e4000_pll_lut[i].mul; | 235 | f_vco = c->frequency * e4000_pll_lut[i].mul; |
| 235 | sigma_delta = 0x10000UL * (f_VCO % priv->cfg->clock) / priv->cfg->clock; | 236 | sigma_delta = 0x10000UL * (f_vco % priv->cfg->clock) / priv->cfg->clock; |
| 236 | buf[0] = f_VCO / priv->cfg->clock; | 237 | buf[0] = f_vco / priv->cfg->clock; |
| 237 | buf[1] = (sigma_delta >> 0) & 0xff; | 238 | buf[1] = (sigma_delta >> 0) & 0xff; |
| 238 | buf[2] = (sigma_delta >> 8) & 0xff; | 239 | buf[2] = (sigma_delta >> 8) & 0xff; |
| 239 | buf[3] = 0x00; | 240 | buf[3] = 0x00; |
| 240 | buf[4] = e4000_pll_lut[i].div; | 241 | buf[4] = e4000_pll_lut[i].div; |
| 241 | 242 | ||
| 242 | dev_dbg(&priv->i2c->dev, "%s: f_VCO=%u pll div=%d sigma_delta=%04x\n", | 243 | dev_dbg(&priv->i2c->dev, "%s: f_vco=%u pll div=%d sigma_delta=%04x\n", |
| 243 | __func__, f_VCO, buf[0], sigma_delta); | 244 | __func__, f_vco, buf[0], sigma_delta); |
| 244 | 245 | ||
| 245 | ret = e4000_wr_regs(priv, 0x09, buf, 5); | 246 | ret = e4000_wr_regs(priv, 0x09, buf, 5); |
| 246 | if (ret < 0) | 247 | if (ret < 0) |
| @@ -292,6 +293,43 @@ static int e4000_set_params(struct dvb_frontend *fe) | |||
| 292 | if (ret < 0) | 293 | if (ret < 0) |
| 293 | goto err; | 294 | goto err; |
| 294 | 295 | ||
| 296 | /* DC offset */ | ||
| 297 | for (i = 0; i < 4; i++) { | ||
| 298 | if (i == 0) | ||
| 299 | ret = e4000_wr_regs(priv, 0x15, "\x00\x7e\x24", 3); | ||
| 300 | else if (i == 1) | ||
| 301 | ret = e4000_wr_regs(priv, 0x15, "\x00\x7f", 2); | ||
| 302 | else if (i == 2) | ||
| 303 | ret = e4000_wr_regs(priv, 0x15, "\x01", 1); | ||
| 304 | else | ||
| 305 | ret = e4000_wr_regs(priv, 0x16, "\x7e", 1); | ||
| 306 | |||
| 307 | if (ret < 0) | ||
| 308 | goto err; | ||
| 309 | |||
| 310 | ret = e4000_wr_reg(priv, 0x29, 0x01); | ||
| 311 | if (ret < 0) | ||
| 312 | goto err; | ||
| 313 | |||
| 314 | ret = e4000_rd_regs(priv, 0x2a, buf, 3); | ||
| 315 | if (ret < 0) | ||
| 316 | goto err; | ||
| 317 | |||
| 318 | i_data[i] = (((buf[2] >> 0) & 0x3) << 6) | (buf[0] & 0x3f); | ||
| 319 | q_data[i] = (((buf[2] >> 4) & 0x3) << 6) | (buf[1] & 0x3f); | ||
| 320 | } | ||
| 321 | |||
| 322 | swap(q_data[2], q_data[3]); | ||
| 323 | swap(i_data[2], i_data[3]); | ||
| 324 | |||
| 325 | ret = e4000_wr_regs(priv, 0x50, q_data, 4); | ||
| 326 | if (ret < 0) | ||
| 327 | goto err; | ||
| 328 | |||
| 329 | ret = e4000_wr_regs(priv, 0x60, i_data, 4); | ||
| 330 | if (ret < 0) | ||
| 331 | goto err; | ||
| 332 | |||
| 295 | /* gain control auto */ | 333 | /* gain control auto */ |
| 296 | ret = e4000_wr_reg(priv, 0x1a, 0x17); | 334 | ret = e4000_wr_reg(priv, 0x1a, 0x17); |
| 297 | if (ret < 0) | 335 | if (ret < 0) |
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h index 3783a0bdf855..25ee7c07abff 100644 --- a/drivers/media/tuners/e4000.h +++ b/drivers/media/tuners/e4000.h | |||
| @@ -44,7 +44,7 @@ extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, | |||
| 44 | static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, | 44 | static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, |
| 45 | struct i2c_adapter *i2c, const struct e4000_config *cfg) | 45 | struct i2c_adapter *i2c, const struct e4000_config *cfg) |
| 46 | { | 46 | { |
| 47 | pr_warn("%s: driver disabled by Kconfig\n", __func__); | 47 | dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); |
| 48 | return NULL; | 48 | return NULL; |
| 49 | } | 49 | } |
| 50 | #endif | 50 | #endif |
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 27948e1798eb..a384f80f595e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c | |||
| @@ -443,6 +443,44 @@ struct cx231xx_board cx231xx_boards[] = { | |||
| 443 | .gpio = NULL, | 443 | .gpio = NULL, |
| 444 | } }, | 444 | } }, |
| 445 | }, | 445 | }, |
| 446 | [CX231XX_BOARD_KWORLD_UB445_USB_HYBRID] = { | ||
| 447 | .name = "Kworld UB445 USB Hybrid", | ||
| 448 | .tuner_type = TUNER_NXP_TDA18271, | ||
| 449 | .tuner_addr = 0x60, | ||
| 450 | .decoder = CX231XX_AVDECODER, | ||
| 451 | .output_mode = OUT_MODE_VIP11, | ||
| 452 | .demod_xfer_mode = 0, | ||
| 453 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
| 454 | .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */ | ||
| 455 | .tuner_sif_gpio = -1, | ||
| 456 | .tuner_scl_gpio = -1, | ||
| 457 | .tuner_sda_gpio = -1, | ||
| 458 | .gpio_pin_status_mask = 0x4001000, | ||
| 459 | .tuner_i2c_master = 2, | ||
| 460 | .demod_i2c_master = 1, | ||
| 461 | .ir_i2c_master = 2, | ||
| 462 | .has_dvb = 1, | ||
| 463 | .demod_addr = 0x10, | ||
| 464 | .norm = V4L2_STD_NTSC_M, | ||
| 465 | .input = {{ | ||
| 466 | .type = CX231XX_VMUX_TELEVISION, | ||
| 467 | .vmux = CX231XX_VIN_3_1, | ||
| 468 | .amux = CX231XX_AMUX_VIDEO, | ||
| 469 | .gpio = NULL, | ||
| 470 | }, { | ||
| 471 | .type = CX231XX_VMUX_COMPOSITE1, | ||
| 472 | .vmux = CX231XX_VIN_2_1, | ||
| 473 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 474 | .gpio = NULL, | ||
| 475 | }, { | ||
| 476 | .type = CX231XX_VMUX_SVIDEO, | ||
| 477 | .vmux = CX231XX_VIN_1_1 | | ||
| 478 | (CX231XX_VIN_1_2 << 8) | | ||
| 479 | CX25840_SVIDEO_ON, | ||
| 480 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 481 | .gpio = NULL, | ||
| 482 | } }, | ||
| 483 | }, | ||
| 446 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { | 484 | [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { |
| 447 | .name = "Pixelview PlayTV USB Hybrid", | 485 | .name = "Pixelview PlayTV USB Hybrid", |
| 448 | .tuner_type = TUNER_NXP_TDA18271, | 486 | .tuner_type = TUNER_NXP_TDA18271, |
| @@ -703,6 +741,8 @@ struct usb_device_id cx231xx_id_table[] = { | |||
| 703 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, | 741 | .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, |
| 704 | {USB_DEVICE(0x1b80, 0xe424), | 742 | {USB_DEVICE(0x1b80, 0xe424), |
| 705 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, | 743 | .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, |
| 744 | {USB_DEVICE(0x1b80, 0xe421), | ||
| 745 | .driver_info = CX231XX_BOARD_KWORLD_UB445_USB_HYBRID}, | ||
| 706 | {USB_DEVICE(0x1f4d, 0x0237), | 746 | {USB_DEVICE(0x1f4d, 0x0237), |
| 707 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, | 747 | .driver_info = CX231XX_BOARD_ICONBIT_U100}, |
| 708 | {USB_DEVICE(0x0fd9, 0x0037), | 748 | {USB_DEVICE(0x0fd9, 0x0037), |
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 14e26106fd72..4504bc6a700b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c | |||
| @@ -657,6 +657,7 @@ static int dvb_init(struct cx231xx *dev) | |||
| 657 | } | 657 | } |
| 658 | break; | 658 | break; |
| 659 | case CX231XX_BOARD_CNXT_RDU_253S: | 659 | case CX231XX_BOARD_CNXT_RDU_253S: |
| 660 | case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID: | ||
| 660 | 661 | ||
| 661 | dev->dvb->frontend = dvb_attach(s5h1411_attach, | 662 | dev->dvb->frontend = dvb_attach(s5h1411_attach, |
| 662 | &tda18271_s5h1411_config, | 663 | &tda18271_s5h1411_config, |
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index e812119ea7a8..babca7fb85e2 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15 | 72 | #define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15 |
| 73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 | 73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 |
| 74 | #define CX231XX_BOARD_OTG102 17 | 74 | #define CX231XX_BOARD_OTG102 17 |
| 75 | #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 | ||
| 75 | 76 | ||
| 76 | /* Limits minimum and default number of buffers */ | 77 | /* Limits minimum and default number of buffers */ |
| 77 | #define CX231XX_MIN_BUF 4 | 78 | #define CX231XX_MIN_BUF 4 |
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index a3c8ecf22078..2059d0c86ad3 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config DVB_USB_V2 | 1 | config DVB_USB_V2 |
| 2 | tristate "Support for various USB DVB devices v2" | 2 | tristate "Support for various USB DVB devices v2" |
| 3 | depends on DVB_CORE && USB && I2C | 3 | depends on DVB_CORE && USB && I2C && (RC_CORE || RC_CORE=n) |
| 4 | help | 4 | help |
| 5 | By enabling this you will be able to choose the various supported | 5 | By enabling this you will be able to choose the various supported |
| 6 | USB1.1 and USB2.0 DVB devices. | 6 | USB1.1 and USB2.0 DVB devices. |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 399916bd588f..124b4baa7e97 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h | |||
| @@ -352,9 +352,7 @@ struct dvb_usb_adapter { | |||
| 352 | * @rc_map: name of rc codes table | 352 | * @rc_map: name of rc codes table |
| 353 | * @rc_polling_active: set when RC polling is active | 353 | * @rc_polling_active: set when RC polling is active |
| 354 | * @udev: pointer to the device's struct usb_device | 354 | * @udev: pointer to the device's struct usb_device |
| 355 | * @intf: pointer to the device's usb interface | ||
| 356 | * @rc: remote controller configuration | 355 | * @rc: remote controller configuration |
| 357 | * @probe_work: work to defer .probe() | ||
| 358 | * @powered: indicated whether the device is power or not | 356 | * @powered: indicated whether the device is power or not |
| 359 | * @usb_mutex: mutex for usb control messages | 357 | * @usb_mutex: mutex for usb control messages |
| 360 | * @i2c_mutex: mutex for i2c-transfers | 358 | * @i2c_mutex: mutex for i2c-transfers |
| @@ -370,10 +368,7 @@ struct dvb_usb_device { | |||
| 370 | const char *rc_map; | 368 | const char *rc_map; |
| 371 | bool rc_polling_active; | 369 | bool rc_polling_active; |
| 372 | struct usb_device *udev; | 370 | struct usb_device *udev; |
| 373 | struct usb_interface *intf; | ||
| 374 | struct dvb_usb_rc rc; | 371 | struct dvb_usb_rc rc; |
| 375 | struct work_struct probe_work; | ||
| 376 | pid_t work_pid; | ||
| 377 | int powered; | 372 | int powered; |
| 378 | 373 | ||
| 379 | /* locking */ | 374 | /* locking */ |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 19f6737d9817..8a054d66e708 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | |||
| @@ -833,20 +833,44 @@ err: | |||
| 833 | return ret; | 833 | return ret; |
| 834 | } | 834 | } |
| 835 | 835 | ||
| 836 | /* | 836 | int dvb_usbv2_probe(struct usb_interface *intf, |
| 837 | * udev, which is used for the firmware downloading, requires we cannot | 837 | const struct usb_device_id *id) |
| 838 | * block during module_init(). module_init() calls USB probe() which | ||
| 839 | * is this routine. Due to that we delay actual operation using workqueue | ||
| 840 | * and return always success here. | ||
| 841 | */ | ||
| 842 | static void dvb_usbv2_init_work(struct work_struct *work) | ||
| 843 | { | 838 | { |
| 844 | int ret; | 839 | int ret; |
| 845 | struct dvb_usb_device *d = | 840 | struct dvb_usb_device *d; |
| 846 | container_of(work, struct dvb_usb_device, probe_work); | 841 | struct usb_device *udev = interface_to_usbdev(intf); |
| 842 | struct dvb_usb_driver_info *driver_info = | ||
| 843 | (struct dvb_usb_driver_info *) id->driver_info; | ||
| 844 | |||
| 845 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | ||
| 846 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 847 | |||
| 848 | if (!id->driver_info) { | ||
| 849 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | ||
| 850 | ret = -ENODEV; | ||
| 851 | goto err; | ||
| 852 | } | ||
| 853 | |||
| 854 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
| 855 | if (!d) { | ||
| 856 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
| 857 | ret = -ENOMEM; | ||
| 858 | goto err; | ||
| 859 | } | ||
| 847 | 860 | ||
| 848 | d->work_pid = current->pid; | 861 | d->name = driver_info->name; |
| 849 | dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); | 862 | d->rc_map = driver_info->rc_map; |
| 863 | d->udev = udev; | ||
| 864 | d->props = driver_info->props; | ||
| 865 | |||
| 866 | if (intf->cur_altsetting->desc.bInterfaceNumber != | ||
| 867 | d->props->bInterfaceNumber) { | ||
| 868 | ret = -ENODEV; | ||
| 869 | goto err_free_all; | ||
| 870 | } | ||
| 871 | |||
| 872 | mutex_init(&d->usb_mutex); | ||
| 873 | mutex_init(&d->i2c_mutex); | ||
| 850 | 874 | ||
| 851 | if (d->props->size_of_priv) { | 875 | if (d->props->size_of_priv) { |
| 852 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | 876 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); |
| @@ -854,7 +878,7 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
| 854 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", | 878 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", |
| 855 | KBUILD_MODNAME); | 879 | KBUILD_MODNAME); |
| 856 | ret = -ENOMEM; | 880 | ret = -ENOMEM; |
| 857 | goto err_usb_driver_release_interface; | 881 | goto err_free_all; |
| 858 | } | 882 | } |
| 859 | } | 883 | } |
| 860 | 884 | ||
| @@ -884,20 +908,12 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
| 884 | * device. As 'new' device is warm we should | 908 | * device. As 'new' device is warm we should |
| 885 | * never go here again. | 909 | * never go here again. |
| 886 | */ | 910 | */ |
| 887 | return; | 911 | goto exit; |
| 888 | } else { | 912 | } else { |
| 889 | /* | 913 | goto err_free_all; |
| 890 | * Unexpected error. We must unregister driver | ||
| 891 | * manually from the device, because device is | ||
| 892 | * already register by returning from probe() | ||
| 893 | * with success. usb_driver_release_interface() | ||
| 894 | * finally calls disconnect() in order to free | ||
| 895 | * resources. | ||
| 896 | */ | ||
| 897 | goto err_usb_driver_release_interface; | ||
| 898 | } | 914 | } |
| 899 | } else { | 915 | } else { |
| 900 | goto err_usb_driver_release_interface; | 916 | goto err_free_all; |
| 901 | } | 917 | } |
| 902 | } | 918 | } |
| 903 | 919 | ||
| @@ -906,73 +922,17 @@ static void dvb_usbv2_init_work(struct work_struct *work) | |||
| 906 | 922 | ||
| 907 | ret = dvb_usbv2_init(d); | 923 | ret = dvb_usbv2_init(d); |
| 908 | if (ret < 0) | 924 | if (ret < 0) |
| 909 | goto err_usb_driver_release_interface; | 925 | goto err_free_all; |
| 910 | 926 | ||
| 911 | dev_info(&d->udev->dev, | 927 | dev_info(&d->udev->dev, |
| 912 | "%s: '%s' successfully initialized and connected\n", | 928 | "%s: '%s' successfully initialized and connected\n", |
| 913 | KBUILD_MODNAME, d->name); | 929 | KBUILD_MODNAME, d->name); |
| 914 | 930 | exit: | |
| 915 | return; | ||
| 916 | err_usb_driver_release_interface: | ||
| 917 | dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n", | ||
| 918 | KBUILD_MODNAME, d->name, ret); | ||
| 919 | usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), | ||
| 920 | d->intf); | ||
| 921 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
| 922 | return; | ||
| 923 | } | ||
| 924 | |||
| 925 | int dvb_usbv2_probe(struct usb_interface *intf, | ||
| 926 | const struct usb_device_id *id) | ||
| 927 | { | ||
| 928 | int ret; | ||
| 929 | struct dvb_usb_device *d; | ||
| 930 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 931 | struct dvb_usb_driver_info *driver_info = | ||
| 932 | (struct dvb_usb_driver_info *) id->driver_info; | ||
| 933 | |||
| 934 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | ||
| 935 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 936 | |||
| 937 | if (!id->driver_info) { | ||
| 938 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | ||
| 939 | ret = -ENODEV; | ||
| 940 | goto err; | ||
| 941 | } | ||
| 942 | |||
| 943 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
| 944 | if (!d) { | ||
| 945 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
| 946 | ret = -ENOMEM; | ||
| 947 | goto err; | ||
| 948 | } | ||
| 949 | |||
| 950 | d->name = driver_info->name; | ||
| 951 | d->rc_map = driver_info->rc_map; | ||
| 952 | d->udev = udev; | ||
| 953 | d->intf = intf; | ||
| 954 | d->props = driver_info->props; | ||
| 955 | |||
| 956 | if (d->intf->cur_altsetting->desc.bInterfaceNumber != | ||
| 957 | d->props->bInterfaceNumber) { | ||
| 958 | ret = -ENODEV; | ||
| 959 | goto err_kfree; | ||
| 960 | } | ||
| 961 | |||
| 962 | mutex_init(&d->usb_mutex); | ||
| 963 | mutex_init(&d->i2c_mutex); | ||
| 964 | INIT_WORK(&d->probe_work, dvb_usbv2_init_work); | ||
| 965 | usb_set_intfdata(intf, d); | 931 | usb_set_intfdata(intf, d); |
| 966 | ret = schedule_work(&d->probe_work); | ||
| 967 | if (ret < 0) { | ||
| 968 | dev_err(&d->udev->dev, "%s: schedule_work() failed\n", | ||
| 969 | KBUILD_MODNAME); | ||
| 970 | goto err_kfree; | ||
| 971 | } | ||
| 972 | 932 | ||
| 973 | return 0; | 933 | return 0; |
| 974 | err_kfree: | 934 | err_free_all: |
| 975 | kfree(d); | 935 | dvb_usbv2_exit(d); |
| 976 | err: | 936 | err: |
| 977 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); | 937 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); |
| 978 | return ret; | 938 | return ret; |
| @@ -984,12 +944,8 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) | |||
| 984 | struct dvb_usb_device *d = usb_get_intfdata(intf); | 944 | struct dvb_usb_device *d = usb_get_intfdata(intf); |
| 985 | const char *name = d->name; | 945 | const char *name = d->name; |
| 986 | struct device dev = d->udev->dev; | 946 | struct device dev = d->udev->dev; |
| 987 | dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, | 947 | dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, |
| 988 | current->pid, d->work_pid); | 948 | intf->cur_altsetting->desc.bInterfaceNumber); |
| 989 | |||
| 990 | /* ensure initialization work is finished until release resources */ | ||
| 991 | if (d->work_pid != current->pid) | ||
| 992 | cancel_work_sync(&d->probe_work); | ||
| 993 | 949 | ||
| 994 | if (d->props->exit) | 950 | if (d->props->exit) |
| 995 | d->props->exit(d); | 951 | d->props->exit(d); |
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index b3fd0ffa3c3f..f674dc024d06 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c | |||
| @@ -1225,7 +1225,7 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) | |||
| 1225 | usb_reset_configuration(d->udev); | 1225 | usb_reset_configuration(d->udev); |
| 1226 | 1226 | ||
| 1227 | usb_set_interface(d->udev, | 1227 | usb_set_interface(d->udev, |
| 1228 | d->intf->cur_altsetting->desc.bInterfaceNumber, 1); | 1228 | d->props->bInterfaceNumber, 1); |
| 1229 | 1229 | ||
| 1230 | st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; | 1230 | st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; |
| 1231 | 1231 | ||
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index f08136052f9c..829323e42ca0 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c | |||
| @@ -3589,6 +3589,8 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
| 3589 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790P) }, | 3589 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790P) }, |
| 3590 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) }, | 3590 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) }, |
| 3591 | /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, | 3591 | /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, |
| 3592 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, | ||
| 3593 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, | ||
| 3592 | { 0 } /* Terminating entry */ | 3594 | { 0 } /* Terminating entry */ |
| 3593 | }; | 3595 | }; |
| 3594 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 3596 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
| @@ -3993,12 +3995,20 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 3993 | } | 3995 | } |
| 3994 | }, | 3996 | }, |
| 3995 | 3997 | ||
| 3996 | .num_device_descs = 1, | 3998 | .num_device_descs = 3, |
| 3997 | .devices = { | 3999 | .devices = { |
| 3998 | { "Hauppauge Nova-TD Stick (52009)", | 4000 | { "Hauppauge Nova-TD Stick (52009)", |
| 3999 | { &dib0700_usb_id_table[35], NULL }, | 4001 | { &dib0700_usb_id_table[35], NULL }, |
| 4000 | { NULL }, | 4002 | { NULL }, |
| 4001 | }, | 4003 | }, |
| 4004 | { "PCTV 2002e", | ||
| 4005 | { &dib0700_usb_id_table[81], NULL }, | ||
| 4006 | { NULL }, | ||
| 4007 | }, | ||
| 4008 | { "PCTV 2002e SE", | ||
| 4009 | { &dib0700_usb_id_table[82], NULL }, | ||
| 4010 | { NULL }, | ||
| 4011 | }, | ||
| 4002 | }, | 4012 | }, |
| 4003 | 4013 | ||
| 4004 | .rc.core = { | 4014 | .rc.core = { |
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index c2b635d6a17a..0306cb778df4 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c | |||
| @@ -1212,7 +1212,7 @@ static struct dvb_usb_device_properties vp7049_properties = { | |||
| 1212 | .rc_interval = 150, | 1212 | .rc_interval = 150, |
| 1213 | .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, | 1213 | .rc_codes = RC_MAP_TWINHAN_VP1027_DVBS, |
| 1214 | .rc_query = m920x_rc_core_query, | 1214 | .rc_query = m920x_rc_core_query, |
| 1215 | .allowed_protos = RC_TYPE_UNKNOWN, | 1215 | .allowed_protos = RC_BIT_UNKNOWN, |
| 1216 | }, | 1216 | }, |
| 1217 | 1217 | ||
| 1218 | .size_of_priv = sizeof(struct m920x_state), | 1218 | .size_of_priv = sizeof(struct m920x_state), |
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 1a577ed8ea0c..9d103344f34a 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c | |||
| @@ -1008,6 +1008,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 1008 | else | 1008 | else |
| 1009 | f->fmt.pix.field = dev->interlaced ? | 1009 | f->fmt.pix.field = dev->interlaced ? |
| 1010 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; | 1010 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; |
| 1011 | f->fmt.pix.priv = 0; | ||
| 1011 | 1012 | ||
| 1012 | return 0; | 1013 | return 0; |
| 1013 | } | 1014 | } |
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index 6345f9331e7f..4f0c6d566c85 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig | |||
| @@ -338,6 +338,15 @@ config USB_GSPCA_STK014 | |||
| 338 | To compile this driver as a module, choose M here: the | 338 | To compile this driver as a module, choose M here: the |
| 339 | module will be called gspca_stk014. | 339 | module will be called gspca_stk014. |
| 340 | 340 | ||
| 341 | config USB_GSPCA_STK1135 | ||
| 342 | tristate "Syntek STK1135 USB Camera Driver" | ||
| 343 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 344 | help | ||
| 345 | Say Y here if you want support for cameras based on the STK1135 chip. | ||
| 346 | |||
| 347 | To compile this driver as a module, choose M here: the | ||
| 348 | module will be called gspca_stk1135. | ||
| 349 | |||
| 341 | config USB_GSPCA_STV0680 | 350 | config USB_GSPCA_STV0680 |
| 342 | tristate "STV0680 USB Camera Driver" | 351 | tristate "STV0680 USB Camera Driver" |
| 343 | depends on VIDEO_V4L2 && USB_GSPCA | 352 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile index c901da0bd657..5855131ab8b6 100644 --- a/drivers/media/usb/gspca/Makefile +++ b/drivers/media/usb/gspca/Makefile | |||
| @@ -34,6 +34,7 @@ obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o | |||
| 34 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o | 34 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o |
| 35 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | 35 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o |
| 36 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | 36 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o |
| 37 | obj-$(CONFIG_USB_GSPCA_STK1135) += gspca_stk1135.o | ||
| 37 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o | 38 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o |
| 38 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | 39 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o |
| 39 | obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o | 40 | obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o |
| @@ -78,6 +79,7 @@ gspca_sq905-objs := sq905.o | |||
| 78 | gspca_sq905c-objs := sq905c.o | 79 | gspca_sq905c-objs := sq905c.o |
| 79 | gspca_sq930x-objs := sq930x.o | 80 | gspca_sq930x-objs := sq930x.o |
| 80 | gspca_stk014-objs := stk014.o | 81 | gspca_stk014-objs := stk014.o |
| 82 | gspca_stk1135-objs := stk1135.o | ||
| 81 | gspca_stv0680-objs := stv0680.o | 83 | gspca_stv0680-objs := stv0680.o |
| 82 | gspca_sunplus-objs := sunplus.o | 84 | gspca_sunplus-objs := sunplus.o |
| 83 | gspca_t613-objs := t613.o | 85 | gspca_t613-objs := t613.o |
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index b7ae8721b847..048507b27bb2 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c | |||
| @@ -1266,6 +1266,7 @@ static void gspca_release(struct v4l2_device *v4l2_device) | |||
| 1266 | static int dev_open(struct file *file) | 1266 | static int dev_open(struct file *file) |
| 1267 | { | 1267 | { |
| 1268 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1268 | struct gspca_dev *gspca_dev = video_drvdata(file); |
| 1269 | int ret; | ||
| 1269 | 1270 | ||
| 1270 | PDEBUG(D_STREAM, "[%s] open", current->comm); | 1271 | PDEBUG(D_STREAM, "[%s] open", current->comm); |
| 1271 | 1272 | ||
| @@ -1273,7 +1274,10 @@ static int dev_open(struct file *file) | |||
| 1273 | if (!try_module_get(gspca_dev->module)) | 1274 | if (!try_module_get(gspca_dev->module)) |
| 1274 | return -ENODEV; | 1275 | return -ENODEV; |
| 1275 | 1276 | ||
| 1276 | return v4l2_fh_open(file); | 1277 | ret = v4l2_fh_open(file); |
| 1278 | if (ret) | ||
| 1279 | module_put(gspca_dev->module); | ||
| 1280 | return ret; | ||
| 1277 | } | 1281 | } |
| 1278 | 1282 | ||
| 1279 | static int dev_close(struct file *file) | 1283 | static int dev_close(struct file *file) |
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index a3958ee86816..8937d79fd176 100644 --- a/drivers/media/usb/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c | |||
| @@ -75,6 +75,8 @@ struct sd { | |||
| 75 | struct v4l2_ctrl *brightness; | 75 | struct v4l2_ctrl *brightness; |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | u8 revision; | ||
| 79 | |||
| 78 | u8 packet_nr; | 80 | u8 packet_nr; |
| 79 | 81 | ||
| 80 | char bridge; | 82 | char bridge; |
| @@ -3080,8 +3082,8 @@ static void ov518_configure(struct gspca_dev *gspca_dev) | |||
| 3080 | }; | 3082 | }; |
| 3081 | 3083 | ||
| 3082 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | 3084 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ |
| 3083 | PDEBUG(D_PROBE, "Device revision %d", | 3085 | sd->revision = reg_r(sd, R51x_SYS_CUST_ID) & 0x1f; |
| 3084 | 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); | 3086 | PDEBUG(D_PROBE, "Device revision %d", sd->revision); |
| 3085 | 3087 | ||
| 3086 | write_regvals(sd, init_518, ARRAY_SIZE(init_518)); | 3088 | write_regvals(sd, init_518, ARRAY_SIZE(init_518)); |
| 3087 | 3089 | ||
| @@ -3657,7 +3659,11 @@ static void ov518_mode_init_regs(struct sd *sd) | |||
| 3657 | reg_w(sd, 0x2f, 0x80); | 3659 | reg_w(sd, 0x2f, 0x80); |
| 3658 | 3660 | ||
| 3659 | /******** Set the framerate ********/ | 3661 | /******** Set the framerate ********/ |
| 3660 | sd->clockdiv = 1; | 3662 | if (sd->bridge == BRIDGE_OV518PLUS && sd->revision == 0 && |
| 3663 | sd->sensor == SEN_OV7620AE) | ||
| 3664 | sd->clockdiv = 0; | ||
| 3665 | else | ||
| 3666 | sd->clockdiv = 1; | ||
| 3661 | 3667 | ||
| 3662 | /* Mode independent, but framerate dependent, regs */ | 3668 | /* Mode independent, but framerate dependent, regs */ |
| 3663 | /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ | 3669 | /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ |
| @@ -3668,12 +3674,24 @@ static void ov518_mode_init_regs(struct sd *sd) | |||
| 3668 | if (sd->bridge == BRIDGE_OV518PLUS) { | 3674 | if (sd->bridge == BRIDGE_OV518PLUS) { |
| 3669 | switch (sd->sensor) { | 3675 | switch (sd->sensor) { |
| 3670 | case SEN_OV7620AE: | 3676 | case SEN_OV7620AE: |
| 3671 | if (sd->gspca_dev.width == 320) { | 3677 | /* |
| 3672 | reg_w(sd, 0x20, 0x00); | 3678 | * HdG: 640x480 needs special handling on device |
| 3673 | reg_w(sd, 0x21, 0x19); | 3679 | * revision 2, we check for device revison > 0 to |
| 3674 | } else { | 3680 | * avoid regressions, as we don't know the correct |
| 3681 | * thing todo for revision 1. | ||
| 3682 | * | ||
| 3683 | * Also this likely means we don't need to | ||
| 3684 | * differentiate between the OV7620 and OV7620AE, | ||
| 3685 | * earlier testing hitting this same problem likely | ||
| 3686 | * happened to be with revision < 2 cams using an | ||
| 3687 | * OV7620 and revision 2 cams using an OV7620AE. | ||
| 3688 | */ | ||
| 3689 | if (sd->revision > 0 && sd->gspca_dev.width == 640) { | ||
| 3675 | reg_w(sd, 0x20, 0x60); | 3690 | reg_w(sd, 0x20, 0x60); |
| 3676 | reg_w(sd, 0x21, 0x1f); | 3691 | reg_w(sd, 0x21, 0x1f); |
| 3692 | } else { | ||
| 3693 | reg_w(sd, 0x20, 0x00); | ||
| 3694 | reg_w(sd, 0x21, 0x19); | ||
| 3677 | } | 3695 | } |
| 3678 | break; | 3696 | break; |
| 3679 | case SEN_OV7620: | 3697 | case SEN_OV7620: |
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index 2e28c81a03ab..03a33c46ca2c 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c | |||
| @@ -1305,8 +1305,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 1305 | ov534_set_led(gspca_dev, 1); | 1305 | ov534_set_led(gspca_dev, 1); |
| 1306 | sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, | 1306 | sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, |
| 1307 | sensor_init[sd->sensor].len); | 1307 | sensor_init[sd->sensor].len); |
| 1308 | if (sd->sensor == SENSOR_OV767x) | 1308 | |
| 1309 | sd_start(gspca_dev); | ||
| 1310 | sd_stopN(gspca_dev); | 1309 | sd_stopN(gspca_dev); |
| 1311 | /* set_frame_rate(gspca_dev); */ | 1310 | /* set_frame_rate(gspca_dev); */ |
| 1312 | 1311 | ||
diff --git a/drivers/media/usb/gspca/stk1135.c b/drivers/media/usb/gspca/stk1135.c new file mode 100644 index 000000000000..585868835ace --- /dev/null +++ b/drivers/media/usb/gspca/stk1135.c | |||
| @@ -0,0 +1,685 @@ | |||
| 1 | /* | ||
| 2 | * Syntek STK1135 subdriver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2013 Ondrej Zary | ||
| 5 | * | ||
| 6 | * Based on Syntekdriver (stk11xx) by Nicolas VIVIEN: | ||
| 7 | * http://syntekdriver.sourceforge.net | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 25 | |||
| 26 | #define MODULE_NAME "stk1135" | ||
| 27 | |||
| 28 | #include "gspca.h" | ||
| 29 | #include "stk1135.h" | ||
| 30 | |||
| 31 | MODULE_AUTHOR("Ondrej Zary"); | ||
| 32 | MODULE_DESCRIPTION("Syntek STK1135 USB Camera Driver"); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | |||
| 35 | |||
| 36 | /* specific webcam descriptor */ | ||
| 37 | struct sd { | ||
| 38 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
| 39 | |||
| 40 | u8 pkt_seq; | ||
| 41 | u8 sensor_page; | ||
| 42 | |||
| 43 | bool flip_status; | ||
| 44 | u8 flip_debounce; | ||
| 45 | |||
| 46 | struct v4l2_ctrl *hflip; | ||
| 47 | struct v4l2_ctrl *vflip; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static const struct v4l2_pix_format stk1135_modes[] = { | ||
| 51 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 52 | .bytesperline = 160, | ||
| 53 | .sizeimage = 160 * 120, | ||
| 54 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 55 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 56 | .bytesperline = 176, | ||
| 57 | .sizeimage = 176 * 144, | ||
| 58 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 59 | {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 60 | .bytesperline = 320, | ||
| 61 | .sizeimage = 320 * 240, | ||
| 62 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 63 | {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 64 | .bytesperline = 352, | ||
| 65 | .sizeimage = 352 * 288, | ||
| 66 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 67 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 68 | .bytesperline = 640, | ||
| 69 | .sizeimage = 640 * 480, | ||
| 70 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 71 | {720, 576, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 72 | .bytesperline = 720, | ||
| 73 | .sizeimage = 720 * 576, | ||
| 74 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 75 | {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 76 | .bytesperline = 800, | ||
| 77 | .sizeimage = 800 * 600, | ||
| 78 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 79 | {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 80 | .bytesperline = 1024, | ||
| 81 | .sizeimage = 1024 * 768, | ||
| 82 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 83 | {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
| 84 | .bytesperline = 1280, | ||
| 85 | .sizeimage = 1280 * 1024, | ||
| 86 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* -- read a register -- */ | ||
| 90 | static u8 reg_r(struct gspca_dev *gspca_dev, u16 index) | ||
| 91 | { | ||
| 92 | struct usb_device *dev = gspca_dev->dev; | ||
| 93 | int ret; | ||
| 94 | |||
| 95 | if (gspca_dev->usb_err < 0) | ||
| 96 | return 0; | ||
| 97 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 98 | 0x00, | ||
| 99 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 100 | 0x00, | ||
| 101 | index, | ||
| 102 | gspca_dev->usb_buf, 1, | ||
| 103 | 500); | ||
| 104 | |||
| 105 | PDEBUG(D_USBI, "reg_r 0x%x=0x%02x", index, gspca_dev->usb_buf[0]); | ||
| 106 | if (ret < 0) { | ||
| 107 | pr_err("reg_r 0x%x err %d\n", index, ret); | ||
| 108 | gspca_dev->usb_err = ret; | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | return gspca_dev->usb_buf[0]; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* -- write a register -- */ | ||
| 116 | static void reg_w(struct gspca_dev *gspca_dev, u16 index, u8 val) | ||
| 117 | { | ||
| 118 | int ret; | ||
| 119 | struct usb_device *dev = gspca_dev->dev; | ||
| 120 | |||
| 121 | if (gspca_dev->usb_err < 0) | ||
| 122 | return; | ||
| 123 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
| 124 | 0x01, | ||
| 125 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 126 | val, | ||
| 127 | index, | ||
| 128 | NULL, | ||
| 129 | 0, | ||
| 130 | 500); | ||
| 131 | PDEBUG(D_USBO, "reg_w 0x%x:=0x%02x", index, val); | ||
| 132 | if (ret < 0) { | ||
| 133 | pr_err("reg_w 0x%x err %d\n", index, ret); | ||
| 134 | gspca_dev->usb_err = ret; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | static void reg_w_mask(struct gspca_dev *gspca_dev, u16 index, u8 val, u8 mask) | ||
| 139 | { | ||
| 140 | val = (reg_r(gspca_dev, index) & ~mask) | (val & mask); | ||
| 141 | reg_w(gspca_dev, index, val); | ||
| 142 | } | ||
| 143 | |||
| 144 | /* this function is called at probe time */ | ||
| 145 | static int sd_config(struct gspca_dev *gspca_dev, | ||
| 146 | const struct usb_device_id *id) | ||
| 147 | { | ||
| 148 | gspca_dev->cam.cam_mode = stk1135_modes; | ||
| 149 | gspca_dev->cam.nmodes = ARRAY_SIZE(stk1135_modes); | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int stk1135_serial_wait_ready(struct gspca_dev *gspca_dev) | ||
| 154 | { | ||
| 155 | int i = 0; | ||
| 156 | u8 val; | ||
| 157 | |||
| 158 | do { | ||
| 159 | val = reg_r(gspca_dev, STK1135_REG_SICTL + 1); | ||
| 160 | if (i++ > 500) { /* maximum retry count */ | ||
| 161 | pr_err("serial bus timeout: status=0x%02x\n", val); | ||
| 162 | return -1; | ||
| 163 | } | ||
| 164 | /* repeat if BUSY or WRITE/READ not finished */ | ||
| 165 | } while ((val & 0x10) || !(val & 0x05)); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static u8 sensor_read_8(struct gspca_dev *gspca_dev, u8 addr) | ||
| 171 | { | ||
| 172 | reg_w(gspca_dev, STK1135_REG_SBUSR, addr); | ||
| 173 | /* begin read */ | ||
| 174 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x20); | ||
| 175 | /* wait until finished */ | ||
| 176 | if (stk1135_serial_wait_ready(gspca_dev)) { | ||
| 177 | pr_err("Sensor read failed\n"); | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | return reg_r(gspca_dev, STK1135_REG_SBUSR + 1); | ||
| 182 | } | ||
| 183 | |||
| 184 | static u16 sensor_read_16(struct gspca_dev *gspca_dev, u8 addr) | ||
| 185 | { | ||
| 186 | return (sensor_read_8(gspca_dev, addr) << 8) | | ||
| 187 | sensor_read_8(gspca_dev, 0xf1); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void sensor_write_8(struct gspca_dev *gspca_dev, u8 addr, u8 data) | ||
| 191 | { | ||
| 192 | /* load address and data registers */ | ||
| 193 | reg_w(gspca_dev, STK1135_REG_SBUSW, addr); | ||
| 194 | reg_w(gspca_dev, STK1135_REG_SBUSW + 1, data); | ||
| 195 | /* begin write */ | ||
| 196 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x01); | ||
| 197 | /* wait until finished */ | ||
| 198 | if (stk1135_serial_wait_ready(gspca_dev)) { | ||
| 199 | pr_err("Sensor write failed\n"); | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | static void sensor_write_16(struct gspca_dev *gspca_dev, u8 addr, u16 data) | ||
| 205 | { | ||
| 206 | sensor_write_8(gspca_dev, addr, data >> 8); | ||
| 207 | sensor_write_8(gspca_dev, 0xf1, data & 0xff); | ||
| 208 | } | ||
| 209 | |||
| 210 | static void sensor_set_page(struct gspca_dev *gspca_dev, u8 page) | ||
| 211 | { | ||
| 212 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 213 | |||
| 214 | if (page != sd->sensor_page) { | ||
| 215 | sensor_write_16(gspca_dev, 0xf0, page); | ||
| 216 | sd->sensor_page = page; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | static u16 sensor_read(struct gspca_dev *gspca_dev, u16 reg) | ||
| 221 | { | ||
| 222 | sensor_set_page(gspca_dev, reg >> 8); | ||
| 223 | return sensor_read_16(gspca_dev, reg & 0xff); | ||
| 224 | } | ||
| 225 | |||
| 226 | static void sensor_write(struct gspca_dev *gspca_dev, u16 reg, u16 val) | ||
| 227 | { | ||
| 228 | sensor_set_page(gspca_dev, reg >> 8); | ||
| 229 | sensor_write_16(gspca_dev, reg & 0xff, val); | ||
| 230 | } | ||
| 231 | |||
| 232 | static void sensor_write_mask(struct gspca_dev *gspca_dev, | ||
| 233 | u16 reg, u16 val, u16 mask) | ||
| 234 | { | ||
| 235 | val = (sensor_read(gspca_dev, reg) & ~mask) | (val & mask); | ||
| 236 | sensor_write(gspca_dev, reg, val); | ||
| 237 | } | ||
| 238 | |||
| 239 | struct sensor_val { | ||
| 240 | u16 reg; | ||
| 241 | u16 val; | ||
| 242 | }; | ||
| 243 | |||
| 244 | /* configure MT9M112 sensor */ | ||
| 245 | static void stk1135_configure_mt9m112(struct gspca_dev *gspca_dev) | ||
| 246 | { | ||
| 247 | static const struct sensor_val cfg[] = { | ||
| 248 | /* restart&reset, chip enable, reserved */ | ||
| 249 | { 0x00d, 0x000b }, { 0x00d, 0x0008 }, { 0x035, 0x0022 }, | ||
| 250 | /* mode ctl: AWB on, AE both, clip aper corr, defect corr, AE */ | ||
| 251 | { 0x106, 0x700e }, | ||
| 252 | |||
| 253 | { 0x2dd, 0x18e0 }, /* B-R thresholds, */ | ||
| 254 | |||
| 255 | /* AWB */ | ||
| 256 | { 0x21f, 0x0180 }, /* Cb and Cr limits */ | ||
| 257 | { 0x220, 0xc814 }, { 0x221, 0x8080 }, /* lum limits, RGB gain */ | ||
| 258 | { 0x222, 0xa078 }, { 0x223, 0xa078 }, /* R, B limit */ | ||
| 259 | { 0x224, 0x5f20 }, { 0x228, 0xea02 }, /* mtx adj lim, adv ctl */ | ||
| 260 | { 0x229, 0x867a }, /* wide gates */ | ||
| 261 | |||
| 262 | /* Color correction */ | ||
| 263 | /* imager gains base, delta, delta signs */ | ||
| 264 | { 0x25e, 0x594c }, { 0x25f, 0x4d51 }, { 0x260, 0x0002 }, | ||
| 265 | /* AWB adv ctl 2, gain offs */ | ||
| 266 | { 0x2ef, 0x0008 }, { 0x2f2, 0x0000 }, | ||
| 267 | /* base matrix signs, scale K1-5, K6-9 */ | ||
| 268 | { 0x202, 0x00ee }, { 0x203, 0x3923 }, { 0x204, 0x0724 }, | ||
| 269 | /* base matrix coef */ | ||
| 270 | { 0x209, 0x00cd }, { 0x20a, 0x0093 }, { 0x20b, 0x0004 },/*K1-3*/ | ||
| 271 | { 0x20c, 0x005c }, { 0x20d, 0x00d9 }, { 0x20e, 0x0053 },/*K4-6*/ | ||
| 272 | { 0x20f, 0x0008 }, { 0x210, 0x0091 }, { 0x211, 0x00cf },/*K7-9*/ | ||
| 273 | { 0x215, 0x0000 }, /* delta mtx signs */ | ||
| 274 | /* delta matrix coef */ | ||
| 275 | { 0x216, 0x0000 }, { 0x217, 0x0000 }, { 0x218, 0x0000 },/*D1-3*/ | ||
| 276 | { 0x219, 0x0000 }, { 0x21a, 0x0000 }, { 0x21b, 0x0000 },/*D4-6*/ | ||
| 277 | { 0x21c, 0x0000 }, { 0x21d, 0x0000 }, { 0x21e, 0x0000 },/*D7-9*/ | ||
| 278 | /* enable & disable manual WB to apply color corr. settings */ | ||
| 279 | { 0x106, 0xf00e }, { 0x106, 0x700e }, | ||
| 280 | |||
| 281 | /* Lens shading correction */ | ||
| 282 | { 0x180, 0x0007 }, /* control */ | ||
| 283 | /* vertical knee 0, 2+1, 4+3 */ | ||
| 284 | { 0x181, 0xde13 }, { 0x182, 0xebe2 }, { 0x183, 0x00f6 }, /* R */ | ||
| 285 | { 0x184, 0xe114 }, { 0x185, 0xeadd }, { 0x186, 0xfdf6 }, /* G */ | ||
| 286 | { 0x187, 0xe511 }, { 0x188, 0xede6 }, { 0x189, 0xfbf7 }, /* B */ | ||
| 287 | /* horizontal knee 0, 2+1, 4+3, 5 */ | ||
| 288 | { 0x18a, 0xd613 }, { 0x18b, 0xedec }, /* R .. */ | ||
| 289 | { 0x18c, 0xf9f2 }, { 0x18d, 0x0000 }, /* .. R */ | ||
| 290 | { 0x18e, 0xd815 }, { 0x18f, 0xe9ea }, /* G .. */ | ||
| 291 | { 0x190, 0xf9f1 }, { 0x191, 0x0002 }, /* .. G */ | ||
| 292 | { 0x192, 0xde10 }, { 0x193, 0xefef }, /* B .. */ | ||
| 293 | { 0x194, 0xfbf4 }, { 0x195, 0x0002 }, /* .. B */ | ||
| 294 | /* vertical knee 6+5, 8+7 */ | ||
| 295 | { 0x1b6, 0x0e06 }, { 0x1b7, 0x2713 }, /* R */ | ||
| 296 | { 0x1b8, 0x1106 }, { 0x1b9, 0x2713 }, /* G */ | ||
| 297 | { 0x1ba, 0x0c03 }, { 0x1bb, 0x2a0f }, /* B */ | ||
| 298 | /* horizontal knee 7+6, 9+8, 10 */ | ||
| 299 | { 0x1bc, 0x1208 }, { 0x1bd, 0x1a16 }, { 0x1be, 0x0022 }, /* R */ | ||
| 300 | { 0x1bf, 0x150a }, { 0x1c0, 0x1c1a }, { 0x1c1, 0x002d }, /* G */ | ||
| 301 | { 0x1c2, 0x1109 }, { 0x1c3, 0x1414 }, { 0x1c4, 0x002a }, /* B */ | ||
| 302 | { 0x106, 0x740e }, /* enable lens shading correction */ | ||
| 303 | |||
| 304 | /* Gamma correction - context A */ | ||
| 305 | { 0x153, 0x0b03 }, { 0x154, 0x4722 }, { 0x155, 0xac82 }, | ||
| 306 | { 0x156, 0xdac7 }, { 0x157, 0xf5e9 }, { 0x158, 0xff00 }, | ||
| 307 | /* Gamma correction - context B */ | ||
| 308 | { 0x1dc, 0x0b03 }, { 0x1dd, 0x4722 }, { 0x1de, 0xac82 }, | ||
| 309 | { 0x1df, 0xdac7 }, { 0x1e0, 0xf5e9 }, { 0x1e1, 0xff00 }, | ||
| 310 | |||
| 311 | /* output format: RGB, invert output pixclock, output bayer */ | ||
| 312 | { 0x13a, 0x4300 }, { 0x19b, 0x4300 }, /* for context A, B */ | ||
| 313 | { 0x108, 0x0180 }, /* format control - enable bayer row flip */ | ||
| 314 | |||
| 315 | { 0x22f, 0xd100 }, { 0x29c, 0xd100 }, /* AE A, B */ | ||
| 316 | |||
| 317 | /* default prg conf, prg ctl - by 0x2d2, prg advance - PA1 */ | ||
| 318 | { 0x2d2, 0x0000 }, { 0x2cc, 0x0004 }, { 0x2cb, 0x0001 }, | ||
| 319 | |||
| 320 | { 0x22e, 0x0c3c }, { 0x267, 0x1010 }, /* AE tgt ctl, gain lim */ | ||
| 321 | |||
| 322 | /* PLL */ | ||
| 323 | { 0x065, 0xa000 }, /* clk ctl - enable PLL (clear bit 14) */ | ||
| 324 | { 0x066, 0x2003 }, { 0x067, 0x0501 }, /* PLL M=128, N=3, P=1 */ | ||
| 325 | { 0x065, 0x2000 }, /* disable PLL bypass (clear bit 15) */ | ||
| 326 | |||
| 327 | { 0x005, 0x01b8 }, { 0x007, 0x00d8 }, /* horiz blanking B, A */ | ||
| 328 | |||
| 329 | /* AE line size, shutter delay limit */ | ||
| 330 | { 0x239, 0x06c0 }, { 0x23b, 0x040e }, /* for context A */ | ||
| 331 | { 0x23a, 0x06c0 }, { 0x23c, 0x0564 }, /* for context B */ | ||
| 332 | /* shutter width basis 60Hz, 50Hz */ | ||
| 333 | { 0x257, 0x0208 }, { 0x258, 0x0271 }, /* for context A */ | ||
| 334 | { 0x259, 0x0209 }, { 0x25a, 0x0271 }, /* for context B */ | ||
| 335 | |||
| 336 | { 0x25c, 0x120d }, { 0x25d, 0x1712 }, /* flicker 60Hz, 50Hz */ | ||
| 337 | { 0x264, 0x5e1c }, /* reserved */ | ||
| 338 | /* flicker, AE gain limits, gain zone limits */ | ||
| 339 | { 0x25b, 0x0003 }, { 0x236, 0x7810 }, { 0x237, 0x8304 }, | ||
| 340 | |||
| 341 | { 0x008, 0x0021 }, /* vert blanking A */ | ||
| 342 | }; | ||
| 343 | int i; | ||
| 344 | u16 width, height; | ||
| 345 | |||
| 346 | for (i = 0; i < ARRAY_SIZE(cfg); i++) | ||
| 347 | sensor_write(gspca_dev, cfg[i].reg, cfg[i].val); | ||
| 348 | |||
| 349 | /* set output size */ | ||
| 350 | width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width; | ||
| 351 | height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height; | ||
| 352 | if (width <= 640) { /* use context A (half readout speed by default) */ | ||
| 353 | sensor_write(gspca_dev, 0x1a7, width); | ||
| 354 | sensor_write(gspca_dev, 0x1aa, height); | ||
| 355 | /* set read mode context A */ | ||
| 356 | sensor_write(gspca_dev, 0x0c8, 0x0000); | ||
| 357 | /* set resize, read mode, vblank, hblank context A */ | ||
| 358 | sensor_write(gspca_dev, 0x2c8, 0x0000); | ||
| 359 | } else { /* use context B (full readout speed by default) */ | ||
| 360 | sensor_write(gspca_dev, 0x1a1, width); | ||
| 361 | sensor_write(gspca_dev, 0x1a4, height); | ||
| 362 | /* set read mode context B */ | ||
| 363 | sensor_write(gspca_dev, 0x0c8, 0x0008); | ||
| 364 | /* set resize, read mode, vblank, hblank context B */ | ||
| 365 | sensor_write(gspca_dev, 0x2c8, 0x040b); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | static void stk1135_configure_clock(struct gspca_dev *gspca_dev) | ||
| 370 | { | ||
| 371 | /* configure SCLKOUT */ | ||
| 372 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x12); | ||
| 373 | /* set 1 clock per pixel */ | ||
| 374 | /* and positive edge clocked pulse high when pixel counter = 0 */ | ||
| 375 | reg_w(gspca_dev, STK1135_REG_TCP1 + 0, 0x41); | ||
| 376 | reg_w(gspca_dev, STK1135_REG_TCP1 + 1, 0x00); | ||
| 377 | reg_w(gspca_dev, STK1135_REG_TCP1 + 2, 0x00); | ||
| 378 | reg_w(gspca_dev, STK1135_REG_TCP1 + 3, 0x00); | ||
| 379 | |||
| 380 | /* enable CLKOUT for sensor */ | ||
| 381 | reg_w(gspca_dev, STK1135_REG_SENSO + 0, 0x10); | ||
| 382 | /* disable STOP clock */ | ||
| 383 | reg_w(gspca_dev, STK1135_REG_SENSO + 1, 0x00); | ||
| 384 | /* set lower 8 bits of PLL feedback divider */ | ||
| 385 | reg_w(gspca_dev, STK1135_REG_SENSO + 3, 0x07); | ||
| 386 | /* set other PLL parameters */ | ||
| 387 | reg_w(gspca_dev, STK1135_REG_PLLFD, 0x06); | ||
| 388 | /* enable timing generator */ | ||
| 389 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x80); | ||
| 390 | /* enable PLL */ | ||
| 391 | reg_w(gspca_dev, STK1135_REG_SENSO + 2, 0x04); | ||
| 392 | |||
| 393 | /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */ | ||
| 394 | reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f); | ||
| 395 | } | ||
| 396 | |||
| 397 | static void stk1135_camera_disable(struct gspca_dev *gspca_dev) | ||
| 398 | { | ||
| 399 | /* set capture end Y position to 0 */ | ||
| 400 | reg_w(gspca_dev, STK1135_REG_CIEPO + 2, 0x00); | ||
| 401 | reg_w(gspca_dev, STK1135_REG_CIEPO + 3, 0x00); | ||
| 402 | /* disable capture */ | ||
| 403 | reg_w_mask(gspca_dev, STK1135_REG_SCTRL, 0x00, 0x80); | ||
| 404 | |||
| 405 | /* enable sensor standby and diasble chip enable */ | ||
| 406 | sensor_write_mask(gspca_dev, 0x00d, 0x0004, 0x000c); | ||
| 407 | |||
| 408 | /* disable PLL */ | ||
| 409 | reg_w_mask(gspca_dev, STK1135_REG_SENSO + 2, 0x00, 0x01); | ||
| 410 | /* disable timing generator */ | ||
| 411 | reg_w(gspca_dev, STK1135_REG_TMGEN, 0x00); | ||
| 412 | /* enable STOP clock */ | ||
| 413 | reg_w(gspca_dev, STK1135_REG_SENSO + 1, 0x20); | ||
| 414 | /* disable CLKOUT for sensor */ | ||
| 415 | reg_w(gspca_dev, STK1135_REG_SENSO, 0x00); | ||
| 416 | |||
| 417 | /* disable sensor (GPIO5) and enable GPIO0,3,6 (?) - sensor standby? */ | ||
| 418 | reg_w(gspca_dev, STK1135_REG_GCTRL, 0x49); | ||
| 419 | } | ||
| 420 | |||
| 421 | /* this function is called at probe and resume time */ | ||
| 422 | static int sd_init(struct gspca_dev *gspca_dev) | ||
| 423 | { | ||
| 424 | u16 sensor_id; | ||
| 425 | char *sensor_name; | ||
| 426 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 427 | |||
| 428 | /* set GPIO3,4,5,6 direction to output */ | ||
| 429 | reg_w(gspca_dev, STK1135_REG_GCTRL + 2, 0x78); | ||
| 430 | /* enable sensor (GPIO5) */ | ||
| 431 | reg_w(gspca_dev, STK1135_REG_GCTRL, (1 << 5)); | ||
| 432 | /* disable ROM interface */ | ||
| 433 | reg_w(gspca_dev, STK1135_REG_GCTRL + 3, 0x80); | ||
| 434 | /* enable interrupts from GPIO8 (flip sensor) and GPIO9 (???) */ | ||
| 435 | reg_w(gspca_dev, STK1135_REG_ICTRL + 1, 0x00); | ||
| 436 | reg_w(gspca_dev, STK1135_REG_ICTRL + 3, 0x03); | ||
| 437 | /* enable remote wakeup from GPIO9 (???) */ | ||
| 438 | reg_w(gspca_dev, STK1135_REG_RMCTL + 1, 0x00); | ||
| 439 | reg_w(gspca_dev, STK1135_REG_RMCTL + 3, 0x02); | ||
| 440 | |||
| 441 | /* reset serial interface */ | ||
| 442 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x80); | ||
| 443 | reg_w(gspca_dev, STK1135_REG_SICTL, 0x00); | ||
| 444 | /* set sensor address */ | ||
| 445 | reg_w(gspca_dev, STK1135_REG_SICTL + 3, 0xba); | ||
| 446 | /* disable alt 2-wire serial interface */ | ||
| 447 | reg_w(gspca_dev, STK1135_REG_ASIC + 3, 0x00); | ||
| 448 | |||
| 449 | stk1135_configure_clock(gspca_dev); | ||
| 450 | |||
| 451 | /* read sensor ID */ | ||
| 452 | sd->sensor_page = 0xff; | ||
| 453 | sensor_id = sensor_read(gspca_dev, 0x000); | ||
| 454 | |||
| 455 | switch (sensor_id) { | ||
| 456 | case 0x148c: | ||
| 457 | sensor_name = "MT9M112"; | ||
| 458 | break; | ||
| 459 | default: | ||
| 460 | sensor_name = "unknown"; | ||
| 461 | } | ||
| 462 | pr_info("Detected sensor type %s (0x%x)\n", sensor_name, sensor_id); | ||
| 463 | |||
| 464 | stk1135_camera_disable(gspca_dev); | ||
| 465 | |||
| 466 | return gspca_dev->usb_err; | ||
| 467 | } | ||
| 468 | |||
| 469 | /* -- start the camera -- */ | ||
| 470 | static int sd_start(struct gspca_dev *gspca_dev) | ||
| 471 | { | ||
| 472 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 473 | u16 width, height; | ||
| 474 | |||
| 475 | /* enable sensor (GPIO5) */ | ||
| 476 | reg_w(gspca_dev, STK1135_REG_GCTRL, (1 << 5)); | ||
| 477 | |||
| 478 | stk1135_configure_clock(gspca_dev); | ||
| 479 | |||
| 480 | /* set capture start position X = 0, Y = 0 */ | ||
| 481 | reg_w(gspca_dev, STK1135_REG_CISPO + 0, 0x00); | ||
| 482 | reg_w(gspca_dev, STK1135_REG_CISPO + 1, 0x00); | ||
| 483 | reg_w(gspca_dev, STK1135_REG_CISPO + 2, 0x00); | ||
| 484 | reg_w(gspca_dev, STK1135_REG_CISPO + 3, 0x00); | ||
| 485 | |||
| 486 | /* set capture end position */ | ||
| 487 | width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width; | ||
| 488 | height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height; | ||
| 489 | reg_w(gspca_dev, STK1135_REG_CIEPO + 0, width & 0xff); | ||
| 490 | reg_w(gspca_dev, STK1135_REG_CIEPO + 1, width >> 8); | ||
| 491 | reg_w(gspca_dev, STK1135_REG_CIEPO + 2, height & 0xff); | ||
| 492 | reg_w(gspca_dev, STK1135_REG_CIEPO + 3, height >> 8); | ||
| 493 | |||
| 494 | /* set 8-bit mode */ | ||
| 495 | reg_w(gspca_dev, STK1135_REG_SCTRL, 0x20); | ||
| 496 | |||
| 497 | stk1135_configure_mt9m112(gspca_dev); | ||
| 498 | |||
| 499 | /* enable capture */ | ||
| 500 | reg_w_mask(gspca_dev, STK1135_REG_SCTRL, 0x80, 0x80); | ||
| 501 | |||
| 502 | if (gspca_dev->usb_err >= 0) | ||
| 503 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", | ||
| 504 | gspca_dev->alt); | ||
| 505 | |||
| 506 | sd->pkt_seq = 0; | ||
| 507 | |||
| 508 | return gspca_dev->usb_err; | ||
| 509 | } | ||
| 510 | |||
| 511 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
| 512 | { | ||
| 513 | struct usb_device *dev = gspca_dev->dev; | ||
| 514 | |||
| 515 | usb_set_interface(dev, gspca_dev->iface, 0); | ||
| 516 | |||
| 517 | stk1135_camera_disable(gspca_dev); | ||
| 518 | |||
| 519 | PDEBUG(D_STREAM, "camera stopped"); | ||
| 520 | } | ||
| 521 | |||
| 522 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
| 523 | u8 *data, /* isoc packet */ | ||
| 524 | int len) /* iso packet length */ | ||
| 525 | { | ||
| 526 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 527 | int skip = sizeof(struct stk1135_pkt_header); | ||
| 528 | bool flip; | ||
| 529 | enum gspca_packet_type pkt_type = INTER_PACKET; | ||
| 530 | struct stk1135_pkt_header *hdr = (void *)data; | ||
| 531 | u8 seq; | ||
| 532 | |||
| 533 | if (len < 4) { | ||
| 534 | PDEBUG(D_PACK, "received short packet (less than 4 bytes)"); | ||
| 535 | return; | ||
| 536 | } | ||
| 537 | |||
| 538 | /* GPIO 8 is flip sensor (1 = normal position, 0 = flipped to back) */ | ||
| 539 | flip = !(le16_to_cpu(hdr->gpio) & (1 << 8)); | ||
| 540 | /* it's a switch, needs software debounce */ | ||
| 541 | if (sd->flip_status != flip) | ||
| 542 | sd->flip_debounce++; | ||
| 543 | else | ||
| 544 | sd->flip_debounce = 0; | ||
| 545 | |||
| 546 | /* check sequence number (not present in new frame packets) */ | ||
| 547 | if (!(hdr->flags & STK1135_HDR_FRAME_START)) { | ||
| 548 | seq = hdr->seq & STK1135_HDR_SEQ_MASK; | ||
| 549 | if (seq != sd->pkt_seq) { | ||
| 550 | PDEBUG(D_PACK, "received out-of-sequence packet"); | ||
| 551 | /* resync sequence and discard packet */ | ||
| 552 | sd->pkt_seq = seq; | ||
| 553 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
| 554 | return; | ||
| 555 | } | ||
| 556 | } | ||
| 557 | sd->pkt_seq++; | ||
| 558 | if (sd->pkt_seq > STK1135_HDR_SEQ_MASK) | ||
| 559 | sd->pkt_seq = 0; | ||
| 560 | |||
| 561 | if (len == sizeof(struct stk1135_pkt_header)) | ||
| 562 | return; | ||
| 563 | |||
| 564 | if (hdr->flags & STK1135_HDR_FRAME_START) { /* new frame */ | ||
| 565 | skip = 8; /* the header is longer */ | ||
| 566 | gspca_frame_add(gspca_dev, LAST_PACKET, data, 0); | ||
| 567 | pkt_type = FIRST_PACKET; | ||
| 568 | } | ||
| 569 | gspca_frame_add(gspca_dev, pkt_type, data + skip, len - skip); | ||
| 570 | } | ||
| 571 | |||
| 572 | static void sethflip(struct gspca_dev *gspca_dev, s32 val) | ||
| 573 | { | ||
| 574 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 575 | |||
| 576 | if (sd->flip_status) | ||
| 577 | val = !val; | ||
| 578 | sensor_write_mask(gspca_dev, 0x020, val ? 0x0002 : 0x0000 , 0x0002); | ||
| 579 | } | ||
| 580 | |||
| 581 | static void setvflip(struct gspca_dev *gspca_dev, s32 val) | ||
| 582 | { | ||
| 583 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 584 | |||
| 585 | if (sd->flip_status) | ||
| 586 | val = !val; | ||
| 587 | sensor_write_mask(gspca_dev, 0x020, val ? 0x0001 : 0x0000 , 0x0001); | ||
| 588 | } | ||
| 589 | |||
| 590 | static void stk1135_dq_callback(struct gspca_dev *gspca_dev) | ||
| 591 | { | ||
| 592 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 593 | |||
| 594 | if (sd->flip_debounce > 100) { | ||
| 595 | sd->flip_status = !sd->flip_status; | ||
| 596 | sethflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip)); | ||
| 597 | setvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->vflip)); | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 602 | { | ||
| 603 | struct gspca_dev *gspca_dev = | ||
| 604 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
| 605 | |||
| 606 | gspca_dev->usb_err = 0; | ||
| 607 | |||
| 608 | if (!gspca_dev->streaming) | ||
| 609 | return 0; | ||
| 610 | |||
| 611 | switch (ctrl->id) { | ||
| 612 | case V4L2_CID_HFLIP: | ||
| 613 | sethflip(gspca_dev, ctrl->val); | ||
| 614 | break; | ||
| 615 | case V4L2_CID_VFLIP: | ||
| 616 | setvflip(gspca_dev, ctrl->val); | ||
| 617 | break; | ||
| 618 | } | ||
| 619 | |||
| 620 | return gspca_dev->usb_err; | ||
| 621 | } | ||
| 622 | |||
| 623 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
| 624 | .s_ctrl = sd_s_ctrl, | ||
| 625 | }; | ||
| 626 | |||
| 627 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
| 628 | { | ||
| 629 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 630 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
| 631 | |||
| 632 | gspca_dev->vdev.ctrl_handler = hdl; | ||
| 633 | v4l2_ctrl_handler_init(hdl, 2); | ||
| 634 | sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
| 635 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
| 636 | sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
| 637 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
| 638 | |||
| 639 | if (hdl->error) { | ||
| 640 | pr_err("Could not initialize controls\n"); | ||
| 641 | return hdl->error; | ||
| 642 | } | ||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* sub-driver description */ | ||
| 647 | static const struct sd_desc sd_desc = { | ||
| 648 | .name = MODULE_NAME, | ||
| 649 | .config = sd_config, | ||
| 650 | .init = sd_init, | ||
| 651 | .init_controls = sd_init_controls, | ||
| 652 | .start = sd_start, | ||
| 653 | .stopN = sd_stopN, | ||
| 654 | .pkt_scan = sd_pkt_scan, | ||
| 655 | .dq_callback = stk1135_dq_callback, | ||
| 656 | }; | ||
| 657 | |||
| 658 | /* -- module initialisation -- */ | ||
| 659 | static const struct usb_device_id device_table[] = { | ||
| 660 | {USB_DEVICE(0x174f, 0x6a31)}, /* ASUS laptop, MT9M112 sensor */ | ||
| 661 | {} | ||
| 662 | }; | ||
| 663 | MODULE_DEVICE_TABLE(usb, device_table); | ||
| 664 | |||
| 665 | /* -- device connect -- */ | ||
| 666 | static int sd_probe(struct usb_interface *intf, | ||
| 667 | const struct usb_device_id *id) | ||
| 668 | { | ||
| 669 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
| 670 | THIS_MODULE); | ||
| 671 | } | ||
| 672 | |||
| 673 | static struct usb_driver sd_driver = { | ||
| 674 | .name = MODULE_NAME, | ||
| 675 | .id_table = device_table, | ||
| 676 | .probe = sd_probe, | ||
| 677 | .disconnect = gspca_disconnect, | ||
| 678 | #ifdef CONFIG_PM | ||
| 679 | .suspend = gspca_suspend, | ||
| 680 | .resume = gspca_resume, | ||
| 681 | .reset_resume = gspca_resume, | ||
| 682 | #endif | ||
| 683 | }; | ||
| 684 | |||
| 685 | module_usb_driver(sd_driver); | ||
diff --git a/drivers/media/usb/gspca/stk1135.h b/drivers/media/usb/gspca/stk1135.h new file mode 100644 index 000000000000..e1dd92ab49bb --- /dev/null +++ b/drivers/media/usb/gspca/stk1135.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * STK1135 registers | ||
| 3 | * | ||
| 4 | * Copyright (c) 2013 Ondrej Zary | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define STK1135_REG_GCTRL 0x000 /* GPIO control */ | ||
| 22 | #define STK1135_REG_ICTRL 0x004 /* Interrupt control */ | ||
| 23 | #define STK1135_REG_IDATA 0x008 /* Interrupt data */ | ||
| 24 | #define STK1135_REG_RMCTL 0x00c /* Remote wakeup control */ | ||
| 25 | #define STK1135_REG_POSVA 0x010 /* Power-on strapping data */ | ||
| 26 | |||
| 27 | #define STK1135_REG_SENSO 0x018 /* Sensor select options */ | ||
| 28 | #define STK1135_REG_PLLFD 0x01c /* PLL frequency divider */ | ||
| 29 | |||
| 30 | #define STK1135_REG_SCTRL 0x100 /* Sensor control register */ | ||
| 31 | #define STK1135_REG_DCTRL 0x104 /* Decimation control register */ | ||
| 32 | #define STK1135_REG_CISPO 0x110 /* Capture image starting position */ | ||
| 33 | #define STK1135_REG_CIEPO 0x114 /* Capture image ending position */ | ||
| 34 | #define STK1135_REG_TCTRL 0x120 /* Test data control */ | ||
| 35 | |||
| 36 | #define STK1135_REG_SICTL 0x200 /* Serial interface control register */ | ||
| 37 | #define STK1135_REG_SBUSW 0x204 /* Serial bus write */ | ||
| 38 | #define STK1135_REG_SBUSR 0x208 /* Serial bus read */ | ||
| 39 | #define STK1135_REG_SCSI 0x20c /* Software control serial interface */ | ||
| 40 | #define STK1135_REG_GSBWP 0x210 /* General serial bus write port */ | ||
| 41 | #define STK1135_REG_GSBRP 0x214 /* General serial bus read port */ | ||
| 42 | #define STK1135_REG_ASIC 0x2fc /* Alternate serial interface control */ | ||
| 43 | |||
| 44 | #define STK1135_REG_TMGEN 0x300 /* Timing generator */ | ||
| 45 | #define STK1135_REG_TCP1 0x350 /* Timing control parameter 1 */ | ||
| 46 | |||
| 47 | struct stk1135_pkt_header { | ||
| 48 | u8 flags; | ||
| 49 | u8 seq; | ||
| 50 | __le16 gpio; | ||
| 51 | } __packed; | ||
| 52 | |||
| 53 | #define STK1135_HDR_FRAME_START (1 << 7) | ||
| 54 | #define STK1135_HDR_ODD (1 << 6) | ||
| 55 | #define STK1135_HDR_I2C_VBLANK (1 << 5) | ||
| 56 | |||
| 57 | #define STK1135_HDR_SEQ_MASK 0x3f | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 4f8567aa99d8..0500c4175d5f 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/v4l2-dv-timings.h> | 24 | #include <linux/v4l2-dv-timings.h> |
| 25 | #include <media/v4l2-dev.h> | 25 | #include <media/v4l2-dev.h> |
| 26 | #include <media/v4l2-common.h> | 26 | #include <media/v4l2-common.h> |
| 27 | #include <media/v4l2-dv-timings.h> | ||
| 27 | #include <media/v4l2-ioctl.h> | 28 | #include <media/v4l2-ioctl.h> |
| 28 | #include <media/v4l2-event.h> | 29 | #include <media/v4l2-event.h> |
| 29 | #include "hdpvr.h" | 30 | #include "hdpvr.h" |
| @@ -641,7 +642,7 @@ static int vidioc_s_dv_timings(struct file *file, void *_fh, | |||
| 641 | if (dev->status != STATUS_IDLE) | 642 | if (dev->status != STATUS_IDLE) |
| 642 | return -EBUSY; | 643 | return -EBUSY; |
| 643 | for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) | 644 | for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) |
| 644 | if (v4l_match_dv_timings(timings, hdpvr_dv_timings + i, 0)) | 645 | if (v4l2_match_dv_timings(timings, hdpvr_dv_timings + i, 0)) |
| 645 | break; | 646 | break; |
| 646 | if (i == ARRAY_SIZE(hdpvr_dv_timings)) | 647 | if (i == ARRAY_SIZE(hdpvr_dv_timings)) |
| 647 | return -EINVAL; | 648 | return -EINVAL; |
| @@ -689,10 +690,8 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, | |||
| 689 | unsigned vsize; | 690 | unsigned vsize; |
| 690 | unsigned fps; | 691 | unsigned fps; |
| 691 | 692 | ||
| 692 | hsize = bt->hfrontporch + bt->hsync + bt->hbackporch + bt->width; | 693 | hsize = V4L2_DV_BT_FRAME_WIDTH(bt); |
| 693 | vsize = bt->vfrontporch + bt->vsync + bt->vbackporch + | 694 | vsize = V4L2_DV_BT_FRAME_HEIGHT(bt); |
| 694 | bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch + | ||
| 695 | bt->height; | ||
| 696 | fps = (unsigned)bt->pixelclock / (hsize * vsize); | 695 | fps = (unsigned)bt->pixelclock / (hsize * vsize); |
| 697 | if (bt->width != vid_info.width || | 696 | if (bt->width != vid_info.width || |
| 698 | bt->height != vid_info.height || | 697 | bt->height != vid_info.height || |
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index ab97e7d0b4f2..6bc9b8e19e20 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device | 2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2010 by Sensoray Company Inc. | 4 | * Copyright (C) 2007-2013 by Sensoray Company Inc. |
| 5 | * Dean Anderson | 5 | * Dean Anderson |
| 6 | * | 6 | * |
| 7 | * Some video buffer code based on vivi driver: | 7 | * Some video buffer code based on vivi driver: |
| @@ -52,7 +52,7 @@ | |||
| 52 | #include <media/v4l2-ctrls.h> | 52 | #include <media/v4l2-ctrls.h> |
| 53 | #include <media/v4l2-event.h> | 53 | #include <media/v4l2-event.h> |
| 54 | 54 | ||
| 55 | #define S2255_VERSION "1.22.1" | 55 | #define S2255_VERSION "1.23.1" |
| 56 | #define FIRMWARE_FILE_NAME "f2255usb.bin" | 56 | #define FIRMWARE_FILE_NAME "f2255usb.bin" |
| 57 | 57 | ||
| 58 | /* default JPEG quality */ | 58 | /* default JPEG quality */ |
| @@ -1303,11 +1303,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i) | |||
| 1303 | int ret = 0; | 1303 | int ret = 0; |
| 1304 | 1304 | ||
| 1305 | mutex_lock(&q->vb_lock); | 1305 | mutex_lock(&q->vb_lock); |
| 1306 | if (videobuf_queue_is_busy(q)) { | ||
| 1307 | dprintk(1, "queue busy\n"); | ||
| 1308 | ret = -EBUSY; | ||
| 1309 | goto out_s_std; | ||
| 1310 | } | ||
| 1311 | if (res_locked(fh)) { | 1306 | if (res_locked(fh)) { |
| 1312 | dprintk(1, "can't change standard after started\n"); | 1307 | dprintk(1, "can't change standard after started\n"); |
| 1313 | ret = -EBUSY; | 1308 | ret = -EBUSY; |
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 1c3a1ec00237..95584c15dc5a 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | config VIDEO_STK1160 | 1 | config VIDEO_STK1160_COMMON |
| 2 | tristate "STK1160 USB video capture support" | 2 | tristate "STK1160 USB video capture support" |
| 3 | depends on VIDEO_DEV && I2C | 3 | depends on VIDEO_DEV && I2C |
| 4 | select VIDEOBUF2_VMALLOC | ||
| 5 | select VIDEO_SAA711X | ||
| 6 | 4 | ||
| 7 | ---help--- | 5 | ---help--- |
| 8 | This is a video4linux driver for STK1160 based video capture devices. | 6 | This is a video4linux driver for STK1160 based video capture devices. |
| @@ -12,9 +10,15 @@ config VIDEO_STK1160 | |||
| 12 | 10 | ||
| 13 | config VIDEO_STK1160_AC97 | 11 | config VIDEO_STK1160_AC97 |
| 14 | bool "STK1160 AC97 codec support" | 12 | bool "STK1160 AC97 codec support" |
| 15 | depends on VIDEO_STK1160 && SND | 13 | depends on VIDEO_STK1160_COMMON && SND |
| 16 | select SND_AC97_CODEC | ||
| 17 | 14 | ||
| 18 | ---help--- | 15 | ---help--- |
| 19 | Enables AC97 codec support for stk1160 driver. | 16 | Enables AC97 codec support for stk1160 driver. |
| 20 | . | 17 | |
| 18 | config VIDEO_STK1160 | ||
| 19 | tristate | ||
| 20 | depends on (!VIDEO_STK1160_AC97 || (SND='n') || SND) && VIDEO_STK1160_COMMON | ||
| 21 | default y | ||
| 22 | select VIDEOBUF2_VMALLOC | ||
| 23 | select VIDEO_SAA711X | ||
| 24 | select SND_AC97_CODEC if SND | ||
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 876fc26565e3..c45c9881bb5f 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c | |||
| @@ -379,6 +379,9 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) | |||
| 379 | struct stk1160 *dev = video_drvdata(file); | 379 | struct stk1160 *dev = video_drvdata(file); |
| 380 | struct vb2_queue *q = &dev->vb_vidq; | 380 | struct vb2_queue *q = &dev->vb_vidq; |
| 381 | 381 | ||
| 382 | if (dev->norm == norm) | ||
| 383 | return 0; | ||
| 384 | |||
| 382 | if (vb2_is_busy(q)) | 385 | if (vb2_is_busy(q)) |
| 383 | return -EBUSY; | 386 | return -EBUSY; |
| 384 | 387 | ||
| @@ -440,9 +443,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
| 440 | { | 443 | { |
| 441 | struct stk1160 *dev = video_drvdata(file); | 444 | struct stk1160 *dev = video_drvdata(file); |
| 442 | 445 | ||
| 443 | if (vb2_is_busy(&dev->vb_vidq)) | ||
| 444 | return -EBUSY; | ||
| 445 | |||
| 446 | if (i > STK1160_MAX_INPUT) | 446 | if (i > STK1160_MAX_INPUT) |
| 447 | return -EINVAL; | 447 | return -EINVAL; |
| 448 | 448 | ||
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c index e07e4c699cc2..95f94e5aa66d 100644 --- a/drivers/media/usb/tlg2300/pd-main.c +++ b/drivers/media/usb/tlg2300/pd-main.c | |||
| @@ -375,7 +375,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | |||
| 375 | } | 375 | } |
| 376 | #endif | 376 | #endif |
| 377 | 377 | ||
| 378 | static int check_firmware(struct usb_device *udev, int *down_firmware) | 378 | static int check_firmware(struct usb_device *udev) |
| 379 | { | 379 | { |
| 380 | void *buf; | 380 | void *buf; |
| 381 | int ret; | 381 | int ret; |
| @@ -395,10 +395,8 @@ static int check_firmware(struct usb_device *udev, int *down_firmware) | |||
| 395 | USB_CTRL_GET_TIMEOUT); | 395 | USB_CTRL_GET_TIMEOUT); |
| 396 | kfree(buf); | 396 | kfree(buf); |
| 397 | 397 | ||
| 398 | if (ret < 0) { | 398 | if (ret < 0) |
| 399 | *down_firmware = 1; | ||
| 400 | return firmware_download(udev); | 399 | return firmware_download(udev); |
| 401 | } | ||
| 402 | return 0; | 400 | return 0; |
| 403 | } | 401 | } |
| 404 | 402 | ||
| @@ -411,9 +409,9 @@ static int poseidon_probe(struct usb_interface *interface, | |||
| 411 | int new_one = 0; | 409 | int new_one = 0; |
| 412 | 410 | ||
| 413 | /* download firmware */ | 411 | /* download firmware */ |
| 414 | check_firmware(udev, &ret); | 412 | ret = check_firmware(udev); |
| 415 | if (ret) | 413 | if (ret) |
| 416 | return 0; | 414 | return ret; |
| 417 | 415 | ||
| 418 | /* Do I recovery from the hibernate ? */ | 416 | /* Do I recovery from the hibernate ? */ |
| 419 | pd = find_old_poseidon(udev); | 417 | pd = find_old_poseidon(udev); |
| @@ -436,12 +434,22 @@ static int poseidon_probe(struct usb_interface *interface, | |||
| 436 | 434 | ||
| 437 | /* register v4l2 device */ | 435 | /* register v4l2 device */ |
| 438 | ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev); | 436 | ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev); |
| 437 | if (ret) | ||
| 438 | goto err_v4l2; | ||
| 439 | 439 | ||
| 440 | /* register devices in directory /dev */ | 440 | /* register devices in directory /dev */ |
| 441 | ret = pd_video_init(pd); | 441 | ret = pd_video_init(pd); |
| 442 | poseidon_audio_init(pd); | 442 | if (ret) |
| 443 | poseidon_fm_init(pd); | 443 | goto err_video; |
| 444 | pd_dvb_usb_device_init(pd); | 444 | ret = poseidon_audio_init(pd); |
| 445 | if (ret) | ||
| 446 | goto err_audio; | ||
| 447 | ret = poseidon_fm_init(pd); | ||
| 448 | if (ret) | ||
| 449 | goto err_fm; | ||
| 450 | ret = pd_dvb_usb_device_init(pd); | ||
| 451 | if (ret) | ||
| 452 | goto err_dvb; | ||
| 445 | 453 | ||
| 446 | INIT_LIST_HEAD(&pd->device_list); | 454 | INIT_LIST_HEAD(&pd->device_list); |
| 447 | list_add_tail(&pd->device_list, &pd_device_list); | 455 | list_add_tail(&pd->device_list, &pd_device_list); |
| @@ -459,6 +467,17 @@ static int poseidon_probe(struct usb_interface *interface, | |||
| 459 | } | 467 | } |
| 460 | #endif | 468 | #endif |
| 461 | return 0; | 469 | return 0; |
| 470 | err_dvb: | ||
| 471 | poseidon_fm_exit(pd); | ||
| 472 | err_fm: | ||
| 473 | poseidon_audio_free(pd); | ||
| 474 | err_audio: | ||
| 475 | pd_video_exit(pd); | ||
| 476 | err_video: | ||
| 477 | v4l2_device_unregister(&pd->v4l2_dev); | ||
| 478 | err_v4l2: | ||
| 479 | kfree(pd); | ||
| 480 | return ret; | ||
| 462 | } | 481 | } |
| 463 | 482 | ||
| 464 | static void poseidon_disconnect(struct usb_interface *interface) | 483 | static void poseidon_disconnect(struct usb_interface *interface) |
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 91650173941a..8a505a90d318 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
| 36 | #include <linux/version.h> | ||
| 37 | #include <linux/videodev2.h> | 36 | #include <linux/videodev2.h> |
| 38 | 37 | ||
| 39 | #include <media/v4l2-device.h> | 38 | #include <media/v4l2-device.h> |
| @@ -91,17 +90,78 @@ struct usbtv { | |||
| 91 | u32 frame_id; | 90 | u32 frame_id; |
| 92 | int chunks_done; | 91 | int chunks_done; |
| 93 | 92 | ||
| 93 | enum { | ||
| 94 | USBTV_COMPOSITE_INPUT, | ||
| 95 | USBTV_SVIDEO_INPUT, | ||
| 96 | } input; | ||
| 94 | int iso_size; | 97 | int iso_size; |
| 95 | unsigned int sequence; | 98 | unsigned int sequence; |
| 96 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; | 99 | struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; |
| 97 | }; | 100 | }; |
| 98 | 101 | ||
| 99 | static int usbtv_setup_capture(struct usbtv *usbtv) | 102 | static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) |
| 100 | { | 103 | { |
| 101 | int ret; | 104 | int ret; |
| 102 | int pipe = usb_rcvctrlpipe(usbtv->udev, 0); | 105 | int pipe = usb_rcvctrlpipe(usbtv->udev, 0); |
| 103 | int i; | 106 | int i; |
| 104 | static const u16 protoregs[][2] = { | 107 | |
| 108 | for (i = 0; i < size; i++) { | ||
| 109 | u16 index = regs[i][0]; | ||
| 110 | u16 value = regs[i][1]; | ||
| 111 | |||
| 112 | ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, | ||
| 113 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 114 | value, index, NULL, 0, 0); | ||
| 115 | if (ret < 0) | ||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int usbtv_select_input(struct usbtv *usbtv, int input) | ||
| 123 | { | ||
| 124 | int ret; | ||
| 125 | |||
| 126 | static const u16 composite[][2] = { | ||
| 127 | { USBTV_BASE + 0x0105, 0x0060 }, | ||
| 128 | { USBTV_BASE + 0x011f, 0x00f2 }, | ||
| 129 | { USBTV_BASE + 0x0127, 0x0060 }, | ||
| 130 | { USBTV_BASE + 0x00ae, 0x0010 }, | ||
| 131 | { USBTV_BASE + 0x0284, 0x00aa }, | ||
| 132 | { USBTV_BASE + 0x0239, 0x0060 }, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static const u16 svideo[][2] = { | ||
| 136 | { USBTV_BASE + 0x0105, 0x0010 }, | ||
| 137 | { USBTV_BASE + 0x011f, 0x00ff }, | ||
| 138 | { USBTV_BASE + 0x0127, 0x0060 }, | ||
| 139 | { USBTV_BASE + 0x00ae, 0x0030 }, | ||
| 140 | { USBTV_BASE + 0x0284, 0x0088 }, | ||
| 141 | { USBTV_BASE + 0x0239, 0x0060 }, | ||
| 142 | }; | ||
| 143 | |||
| 144 | switch (input) { | ||
| 145 | case USBTV_COMPOSITE_INPUT: | ||
| 146 | ret = usbtv_set_regs(usbtv, composite, ARRAY_SIZE(composite)); | ||
| 147 | break; | ||
| 148 | case USBTV_SVIDEO_INPUT: | ||
| 149 | ret = usbtv_set_regs(usbtv, svideo, ARRAY_SIZE(svideo)); | ||
| 150 | break; | ||
| 151 | default: | ||
| 152 | ret = -EINVAL; | ||
| 153 | } | ||
| 154 | |||
| 155 | if (!ret) | ||
| 156 | usbtv->input = input; | ||
| 157 | |||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int usbtv_setup_capture(struct usbtv *usbtv) | ||
| 162 | { | ||
| 163 | int ret; | ||
| 164 | static const u16 setup[][2] = { | ||
| 105 | /* These seem to enable the device. */ | 165 | /* These seem to enable the device. */ |
| 106 | { USBTV_BASE + 0x0008, 0x0001 }, | 166 | { USBTV_BASE + 0x0008, 0x0001 }, |
| 107 | { USBTV_BASE + 0x01d0, 0x00ff }, | 167 | { USBTV_BASE + 0x01d0, 0x00ff }, |
| @@ -189,16 +249,13 @@ static int usbtv_setup_capture(struct usbtv *usbtv) | |||
| 189 | { USBTV_BASE + 0x024f, 0x0002 }, | 249 | { USBTV_BASE + 0x024f, 0x0002 }, |
| 190 | }; | 250 | }; |
| 191 | 251 | ||
| 192 | for (i = 0; i < ARRAY_SIZE(protoregs); i++) { | 252 | ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup)); |
| 193 | u16 index = protoregs[i][0]; | 253 | if (ret) |
| 194 | u16 value = protoregs[i][1]; | 254 | return ret; |
| 195 | 255 | ||
| 196 | ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, | 256 | ret = usbtv_select_input(usbtv, usbtv->input); |
| 197 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 257 | if (ret) |
| 198 | value, index, NULL, 0, 0); | 258 | return ret; |
| 199 | if (ret < 0) | ||
| 200 | return ret; | ||
| 201 | } | ||
| 202 | 259 | ||
| 203 | return 0; | 260 | return 0; |
| 204 | } | 261 | } |
| @@ -443,10 +500,17 @@ static int usbtv_querycap(struct file *file, void *priv, | |||
| 443 | static int usbtv_enum_input(struct file *file, void *priv, | 500 | static int usbtv_enum_input(struct file *file, void *priv, |
| 444 | struct v4l2_input *i) | 501 | struct v4l2_input *i) |
| 445 | { | 502 | { |
| 446 | if (i->index > 0) | 503 | switch (i->index) { |
| 504 | case USBTV_COMPOSITE_INPUT: | ||
| 505 | strlcpy(i->name, "Composite", sizeof(i->name)); | ||
| 506 | break; | ||
| 507 | case USBTV_SVIDEO_INPUT: | ||
| 508 | strlcpy(i->name, "S-Video", sizeof(i->name)); | ||
| 509 | break; | ||
| 510 | default: | ||
| 447 | return -EINVAL; | 511 | return -EINVAL; |
| 512 | } | ||
| 448 | 513 | ||
| 449 | strlcpy(i->name, "Composite", sizeof(i->name)); | ||
| 450 | i->type = V4L2_INPUT_TYPE_CAMERA; | 514 | i->type = V4L2_INPUT_TYPE_CAMERA; |
| 451 | i->std = V4L2_STD_525_60; | 515 | i->std = V4L2_STD_525_60; |
| 452 | return 0; | 516 | return 0; |
| @@ -486,15 +550,15 @@ static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) | |||
| 486 | 550 | ||
| 487 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) | 551 | static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) |
| 488 | { | 552 | { |
| 489 | *i = 0; | 553 | struct usbtv *usbtv = video_drvdata(file); |
| 554 | *i = usbtv->input; | ||
| 490 | return 0; | 555 | return 0; |
| 491 | } | 556 | } |
| 492 | 557 | ||
| 493 | static int usbtv_s_input(struct file *file, void *priv, unsigned int i) | 558 | static int usbtv_s_input(struct file *file, void *priv, unsigned int i) |
| 494 | { | 559 | { |
| 495 | if (i > 0) | 560 | struct usbtv *usbtv = video_drvdata(file); |
| 496 | return -EINVAL; | 561 | return usbtv_select_input(usbtv, i); |
| 497 | return 0; | ||
| 498 | } | 562 | } |
| 499 | 563 | ||
| 500 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) | 564 | static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) |
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 4c33b8d6520c..1a85eee581f8 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile | |||
| @@ -17,6 +17,7 @@ endif | |||
| 17 | obj-$(CONFIG_VIDEO_V4L2) += videodev.o | 17 | obj-$(CONFIG_VIDEO_V4L2) += videodev.o |
| 18 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o | 18 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o |
| 19 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o | 19 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o |
| 20 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-dv-timings.o | ||
| 20 | 21 | ||
| 21 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o | 22 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
| 22 | 23 | ||
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index aae241730caa..c85d69da35bd 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c | |||
| @@ -27,7 +27,6 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | |||
| 27 | #if IS_ENABLED(CONFIG_I2C) | 27 | #if IS_ENABLED(CONFIG_I2C) |
| 28 | struct i2c_client *client = i2c_verify_client(dev); | 28 | struct i2c_client *client = i2c_verify_client(dev); |
| 29 | return client && | 29 | return client && |
| 30 | asd->bus_type == V4L2_ASYNC_BUS_I2C && | ||
| 31 | asd->match.i2c.adapter_id == client->adapter->nr && | 30 | asd->match.i2c.adapter_id == client->adapter->nr && |
| 32 | asd->match.i2c.address == client->addr; | 31 | asd->match.i2c.address == client->addr; |
| 33 | #else | 32 | #else |
| @@ -35,10 +34,14 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | |||
| 35 | #endif | 34 | #endif |
| 36 | } | 35 | } |
| 37 | 36 | ||
| 38 | static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd) | 37 | static bool match_devname(struct device *dev, struct v4l2_async_subdev *asd) |
| 39 | { | 38 | { |
| 40 | return asd->bus_type == V4L2_ASYNC_BUS_PLATFORM && | 39 | return !strcmp(asd->match.device_name.name, dev_name(dev)); |
| 41 | !strcmp(asd->match.platform.name, dev_name(dev)); | 40 | } |
| 41 | |||
| 42 | static bool match_of(struct device *dev, struct v4l2_async_subdev *asd) | ||
| 43 | { | ||
| 44 | return dev->of_node == asd->match.of.node; | ||
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | static LIST_HEAD(subdev_list); | 47 | static LIST_HEAD(subdev_list); |
| @@ -46,28 +49,29 @@ static LIST_HEAD(notifier_list); | |||
| 46 | static DEFINE_MUTEX(list_lock); | 49 | static DEFINE_MUTEX(list_lock); |
| 47 | 50 | ||
| 48 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, | 51 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, |
| 49 | struct v4l2_async_subdev_list *asdl) | 52 | struct v4l2_subdev *sd) |
| 50 | { | 53 | { |
| 51 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
| 52 | struct v4l2_async_subdev *asd; | 54 | struct v4l2_async_subdev *asd; |
| 53 | bool (*match)(struct device *, | 55 | bool (*match)(struct device *, struct v4l2_async_subdev *); |
| 54 | struct v4l2_async_subdev *); | ||
| 55 | 56 | ||
| 56 | list_for_each_entry(asd, ¬ifier->waiting, list) { | 57 | list_for_each_entry(asd, ¬ifier->waiting, list) { |
| 57 | /* bus_type has been verified valid before */ | 58 | /* bus_type has been verified valid before */ |
| 58 | switch (asd->bus_type) { | 59 | switch (asd->match_type) { |
| 59 | case V4L2_ASYNC_BUS_CUSTOM: | 60 | case V4L2_ASYNC_MATCH_CUSTOM: |
| 60 | match = asd->match.custom.match; | 61 | match = asd->match.custom.match; |
| 61 | if (!match) | 62 | if (!match) |
| 62 | /* Match always */ | 63 | /* Match always */ |
| 63 | return asd; | 64 | return asd; |
| 64 | break; | 65 | break; |
| 65 | case V4L2_ASYNC_BUS_PLATFORM: | 66 | case V4L2_ASYNC_MATCH_DEVNAME: |
| 66 | match = match_platform; | 67 | match = match_devname; |
| 67 | break; | 68 | break; |
| 68 | case V4L2_ASYNC_BUS_I2C: | 69 | case V4L2_ASYNC_MATCH_I2C: |
| 69 | match = match_i2c; | 70 | match = match_i2c; |
| 70 | break; | 71 | break; |
| 72 | case V4L2_ASYNC_MATCH_OF: | ||
| 73 | match = match_of; | ||
| 74 | break; | ||
| 71 | default: | 75 | default: |
| 72 | /* Cannot happen, unless someone breaks us */ | 76 | /* Cannot happen, unless someone breaks us */ |
| 73 | WARN_ON(true); | 77 | WARN_ON(true); |
| @@ -83,16 +87,15 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * | |||
| 83 | } | 87 | } |
| 84 | 88 | ||
| 85 | static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | 89 | static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, |
| 86 | struct v4l2_async_subdev_list *asdl, | 90 | struct v4l2_subdev *sd, |
| 87 | struct v4l2_async_subdev *asd) | 91 | struct v4l2_async_subdev *asd) |
| 88 | { | 92 | { |
| 89 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
| 90 | int ret; | 93 | int ret; |
| 91 | 94 | ||
| 92 | /* Remove from the waiting list */ | 95 | /* Remove from the waiting list */ |
| 93 | list_del(&asd->list); | 96 | list_del(&asd->list); |
| 94 | asdl->asd = asd; | 97 | sd->asd = asd; |
| 95 | asdl->notifier = notifier; | 98 | sd->notifier = notifier; |
| 96 | 99 | ||
| 97 | if (notifier->bound) { | 100 | if (notifier->bound) { |
| 98 | ret = notifier->bound(notifier, sd, asd); | 101 | ret = notifier->bound(notifier, sd, asd); |
| @@ -100,7 +103,7 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | |||
| 100 | return ret; | 103 | return ret; |
| 101 | } | 104 | } |
| 102 | /* Move from the global subdevice list to notifier's done */ | 105 | /* Move from the global subdevice list to notifier's done */ |
| 103 | list_move(&asdl->list, ¬ifier->done); | 106 | list_move(&sd->async_list, ¬ifier->done); |
| 104 | 107 | ||
| 105 | ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); | 108 | ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); |
| 106 | if (ret < 0) { | 109 | if (ret < 0) { |
| @@ -115,21 +118,19 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, | |||
| 115 | return 0; | 118 | return 0; |
| 116 | } | 119 | } |
| 117 | 120 | ||
| 118 | static void v4l2_async_cleanup(struct v4l2_async_subdev_list *asdl) | 121 | static void v4l2_async_cleanup(struct v4l2_subdev *sd) |
| 119 | { | 122 | { |
| 120 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
| 121 | |||
| 122 | v4l2_device_unregister_subdev(sd); | 123 | v4l2_device_unregister_subdev(sd); |
| 123 | /* Subdevice driver will reprobe and put asdl back onto the list */ | 124 | /* Subdevice driver will reprobe and put the subdev back onto the list */ |
| 124 | list_del_init(&asdl->list); | 125 | list_del_init(&sd->async_list); |
| 125 | asdl->asd = NULL; | 126 | sd->asd = NULL; |
| 126 | sd->dev = NULL; | 127 | sd->dev = NULL; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | 130 | int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, |
| 130 | struct v4l2_async_notifier *notifier) | 131 | struct v4l2_async_notifier *notifier) |
| 131 | { | 132 | { |
| 132 | struct v4l2_async_subdev_list *asdl, *tmp; | 133 | struct v4l2_subdev *sd, *tmp; |
| 133 | struct v4l2_async_subdev *asd; | 134 | struct v4l2_async_subdev *asd; |
| 134 | int i; | 135 | int i; |
| 135 | 136 | ||
| @@ -141,17 +142,18 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | |||
| 141 | INIT_LIST_HEAD(¬ifier->done); | 142 | INIT_LIST_HEAD(¬ifier->done); |
| 142 | 143 | ||
| 143 | for (i = 0; i < notifier->num_subdevs; i++) { | 144 | for (i = 0; i < notifier->num_subdevs; i++) { |
| 144 | asd = notifier->subdev[i]; | 145 | asd = notifier->subdevs[i]; |
| 145 | 146 | ||
| 146 | switch (asd->bus_type) { | 147 | switch (asd->match_type) { |
| 147 | case V4L2_ASYNC_BUS_CUSTOM: | 148 | case V4L2_ASYNC_MATCH_CUSTOM: |
| 148 | case V4L2_ASYNC_BUS_PLATFORM: | 149 | case V4L2_ASYNC_MATCH_DEVNAME: |
| 149 | case V4L2_ASYNC_BUS_I2C: | 150 | case V4L2_ASYNC_MATCH_I2C: |
| 151 | case V4L2_ASYNC_MATCH_OF: | ||
| 150 | break; | 152 | break; |
| 151 | default: | 153 | default: |
| 152 | dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, | 154 | dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, |
| 153 | "Invalid bus-type %u on %p\n", | 155 | "Invalid match type %u on %p\n", |
| 154 | asd->bus_type, asd); | 156 | asd->match_type, asd); |
| 155 | return -EINVAL; | 157 | return -EINVAL; |
| 156 | } | 158 | } |
| 157 | list_add_tail(&asd->list, ¬ifier->waiting); | 159 | list_add_tail(&asd->list, ¬ifier->waiting); |
| @@ -162,14 +164,14 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, | |||
| 162 | /* Keep also completed notifiers on the list */ | 164 | /* Keep also completed notifiers on the list */ |
| 163 | list_add(¬ifier->list, ¬ifier_list); | 165 | list_add(¬ifier->list, ¬ifier_list); |
| 164 | 166 | ||
| 165 | list_for_each_entry_safe(asdl, tmp, &subdev_list, list) { | 167 | list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) { |
| 166 | int ret; | 168 | int ret; |
| 167 | 169 | ||
| 168 | asd = v4l2_async_belongs(notifier, asdl); | 170 | asd = v4l2_async_belongs(notifier, sd); |
| 169 | if (!asd) | 171 | if (!asd) |
| 170 | continue; | 172 | continue; |
| 171 | 173 | ||
| 172 | ret = v4l2_async_test_notify(notifier, asdl, asd); | 174 | ret = v4l2_async_test_notify(notifier, sd, asd); |
| 173 | if (ret < 0) { | 175 | if (ret < 0) { |
| 174 | mutex_unlock(&list_lock); | 176 | mutex_unlock(&list_lock); |
| 175 | return ret; | 177 | return ret; |
| @@ -184,28 +186,29 @@ EXPORT_SYMBOL(v4l2_async_notifier_register); | |||
| 184 | 186 | ||
| 185 | void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) | 187 | void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) |
| 186 | { | 188 | { |
| 187 | struct v4l2_async_subdev_list *asdl, *tmp; | 189 | struct v4l2_subdev *sd, *tmp; |
| 188 | unsigned int notif_n_subdev = notifier->num_subdevs; | 190 | unsigned int notif_n_subdev = notifier->num_subdevs; |
| 189 | unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); | 191 | unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); |
| 190 | struct device *dev[n_subdev]; | 192 | struct device *dev[n_subdev]; |
| 191 | int i = 0; | 193 | int i = 0; |
| 192 | 194 | ||
| 195 | if (!notifier->v4l2_dev) | ||
| 196 | return; | ||
| 197 | |||
| 193 | mutex_lock(&list_lock); | 198 | mutex_lock(&list_lock); |
| 194 | 199 | ||
| 195 | list_del(¬ifier->list); | 200 | list_del(¬ifier->list); |
| 196 | 201 | ||
| 197 | list_for_each_entry_safe(asdl, tmp, ¬ifier->done, list) { | 202 | list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) { |
| 198 | struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); | ||
| 199 | |||
| 200 | dev[i] = get_device(sd->dev); | 203 | dev[i] = get_device(sd->dev); |
| 201 | 204 | ||
| 202 | v4l2_async_cleanup(asdl); | 205 | v4l2_async_cleanup(sd); |
| 203 | 206 | ||
| 204 | /* If we handled USB devices, we'd have to lock the parent too */ | 207 | /* If we handled USB devices, we'd have to lock the parent too */ |
| 205 | device_release_driver(dev[i++]); | 208 | device_release_driver(dev[i++]); |
| 206 | 209 | ||
| 207 | if (notifier->unbind) | 210 | if (notifier->unbind) |
| 208 | notifier->unbind(notifier, sd, sd->asdl.asd); | 211 | notifier->unbind(notifier, sd, sd->asd); |
| 209 | } | 212 | } |
| 210 | 213 | ||
| 211 | mutex_unlock(&list_lock); | 214 | mutex_unlock(&list_lock); |
| @@ -225,6 +228,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) | |||
| 225 | } | 228 | } |
| 226 | put_device(d); | 229 | put_device(d); |
| 227 | } | 230 | } |
| 231 | |||
| 232 | notifier->v4l2_dev = NULL; | ||
| 233 | |||
| 228 | /* | 234 | /* |
| 229 | * Don't care about the waiting list, it is initialised and populated | 235 | * Don't care about the waiting list, it is initialised and populated |
| 230 | * upon notifier registration. | 236 | * upon notifier registration. |
| @@ -234,24 +240,23 @@ EXPORT_SYMBOL(v4l2_async_notifier_unregister); | |||
| 234 | 240 | ||
| 235 | int v4l2_async_register_subdev(struct v4l2_subdev *sd) | 241 | int v4l2_async_register_subdev(struct v4l2_subdev *sd) |
| 236 | { | 242 | { |
| 237 | struct v4l2_async_subdev_list *asdl = &sd->asdl; | ||
| 238 | struct v4l2_async_notifier *notifier; | 243 | struct v4l2_async_notifier *notifier; |
| 239 | 244 | ||
| 240 | mutex_lock(&list_lock); | 245 | mutex_lock(&list_lock); |
| 241 | 246 | ||
| 242 | INIT_LIST_HEAD(&asdl->list); | 247 | INIT_LIST_HEAD(&sd->async_list); |
| 243 | 248 | ||
| 244 | list_for_each_entry(notifier, ¬ifier_list, list) { | 249 | list_for_each_entry(notifier, ¬ifier_list, list) { |
| 245 | struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, asdl); | 250 | struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd); |
| 246 | if (asd) { | 251 | if (asd) { |
| 247 | int ret = v4l2_async_test_notify(notifier, asdl, asd); | 252 | int ret = v4l2_async_test_notify(notifier, sd, asd); |
| 248 | mutex_unlock(&list_lock); | 253 | mutex_unlock(&list_lock); |
| 249 | return ret; | 254 | return ret; |
| 250 | } | 255 | } |
| 251 | } | 256 | } |
| 252 | 257 | ||
| 253 | /* None matched, wait for hot-plugging */ | 258 | /* None matched, wait for hot-plugging */ |
| 254 | list_add(&asdl->list, &subdev_list); | 259 | list_add(&sd->async_list, &subdev_list); |
| 255 | 260 | ||
| 256 | mutex_unlock(&list_lock); | 261 | mutex_unlock(&list_lock); |
| 257 | 262 | ||
| @@ -261,23 +266,22 @@ EXPORT_SYMBOL(v4l2_async_register_subdev); | |||
| 261 | 266 | ||
| 262 | void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) | 267 | void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) |
| 263 | { | 268 | { |
| 264 | struct v4l2_async_subdev_list *asdl = &sd->asdl; | 269 | struct v4l2_async_notifier *notifier = sd->notifier; |
| 265 | struct v4l2_async_notifier *notifier = asdl->notifier; | ||
| 266 | 270 | ||
| 267 | if (!asdl->asd) { | 271 | if (!sd->asd) { |
| 268 | if (!list_empty(&asdl->list)) | 272 | if (!list_empty(&sd->async_list)) |
| 269 | v4l2_async_cleanup(asdl); | 273 | v4l2_async_cleanup(sd); |
| 270 | return; | 274 | return; |
| 271 | } | 275 | } |
| 272 | 276 | ||
| 273 | mutex_lock(&list_lock); | 277 | mutex_lock(&list_lock); |
| 274 | 278 | ||
| 275 | list_add(&asdl->asd->list, ¬ifier->waiting); | 279 | list_add(&sd->asd->list, ¬ifier->waiting); |
| 276 | 280 | ||
| 277 | v4l2_async_cleanup(asdl); | 281 | v4l2_async_cleanup(sd); |
| 278 | 282 | ||
| 279 | if (notifier->unbind) | 283 | if (notifier->unbind) |
| 280 | notifier->unbind(notifier, sd, sd->asdl.asd); | 284 | notifier->unbind(notifier, sd, sd->asd); |
| 281 | 285 | ||
| 282 | mutex_unlock(&list_lock); | 286 | mutex_unlock(&list_lock); |
| 283 | } | 287 | } |
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index a95e5e23403f..037d7a55aa8c 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c | |||
| @@ -495,363 +495,6 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | |||
| 495 | } | 495 | } |
| 496 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | 496 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); |
| 497 | 497 | ||
| 498 | /** | ||
| 499 | * v4l_match_dv_timings - check if two timings match | ||
| 500 | * @t1 - compare this v4l2_dv_timings struct... | ||
| 501 | * @t2 - with this struct. | ||
| 502 | * @pclock_delta - the allowed pixelclock deviation. | ||
| 503 | * | ||
| 504 | * Compare t1 with t2 with a given margin of error for the pixelclock. | ||
| 505 | */ | ||
| 506 | bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1, | ||
| 507 | const struct v4l2_dv_timings *t2, | ||
| 508 | unsigned pclock_delta) | ||
| 509 | { | ||
| 510 | if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) | ||
| 511 | return false; | ||
| 512 | if (t1->bt.width == t2->bt.width && | ||
| 513 | t1->bt.height == t2->bt.height && | ||
| 514 | t1->bt.interlaced == t2->bt.interlaced && | ||
| 515 | t1->bt.polarities == t2->bt.polarities && | ||
| 516 | t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && | ||
| 517 | t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && | ||
| 518 | t1->bt.hfrontporch == t2->bt.hfrontporch && | ||
| 519 | t1->bt.vfrontporch == t2->bt.vfrontporch && | ||
| 520 | t1->bt.vsync == t2->bt.vsync && | ||
| 521 | t1->bt.vbackporch == t2->bt.vbackporch && | ||
| 522 | (!t1->bt.interlaced || | ||
| 523 | (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && | ||
| 524 | t1->bt.il_vsync == t2->bt.il_vsync && | ||
| 525 | t1->bt.il_vbackporch == t2->bt.il_vbackporch))) | ||
| 526 | return true; | ||
| 527 | return false; | ||
| 528 | } | ||
| 529 | EXPORT_SYMBOL_GPL(v4l_match_dv_timings); | ||
| 530 | |||
| 531 | /* | ||
| 532 | * CVT defines | ||
| 533 | * Based on Coordinated Video Timings Standard | ||
| 534 | * version 1.1 September 10, 2003 | ||
| 535 | */ | ||
| 536 | |||
| 537 | #define CVT_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
| 538 | |||
| 539 | /* Normal blanking */ | ||
| 540 | #define CVT_MIN_V_BPORCH 7 /* lines */ | ||
| 541 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ | ||
| 542 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
| 543 | |||
| 544 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ | ||
| 545 | #define CVT_CELL_GRAN 8 /* character cell granularity */ | ||
| 546 | #define CVT_M 600 /* blanking formula gradient */ | ||
| 547 | #define CVT_C 40 /* blanking formula offset */ | ||
| 548 | #define CVT_K 128 /* blanking formula scaling factor */ | ||
| 549 | #define CVT_J 20 /* blanking formula scaling factor */ | ||
| 550 | #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) | ||
| 551 | #define CVT_M_PRIME (CVT_K * CVT_M / 256) | ||
| 552 | |||
| 553 | /* Reduced Blanking */ | ||
| 554 | #define CVT_RB_MIN_V_BPORCH 7 /* lines */ | ||
| 555 | #define CVT_RB_V_FPORCH 3 /* lines */ | ||
| 556 | #define CVT_RB_MIN_V_BLANK 460 /* us */ | ||
| 557 | #define CVT_RB_H_SYNC 32 /* pixels */ | ||
| 558 | #define CVT_RB_H_BPORCH 80 /* pixels */ | ||
| 559 | #define CVT_RB_H_BLANK 160 /* pixels */ | ||
| 560 | |||
| 561 | /** v4l2_detect_cvt - detect if the given timings follow the CVT standard | ||
| 562 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 563 | * @hfreq - the horizontal frequency in Hz. | ||
| 564 | * @vsync - the height of the vertical sync in lines. | ||
| 565 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 566 | * v4l2_bt_timings polarities). | ||
| 567 | * @fmt - the resulting timings. | ||
| 568 | * | ||
| 569 | * This function will attempt to detect if the given values correspond to a | ||
| 570 | * valid CVT format. If so, then it will return true, and fmt will be filled | ||
| 571 | * in with the found CVT timings. | ||
| 572 | */ | ||
| 573 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 574 | u32 polarities, struct v4l2_dv_timings *fmt) | ||
| 575 | { | ||
| 576 | int v_fp, v_bp, h_fp, h_bp, hsync; | ||
| 577 | int frame_width, image_height, image_width; | ||
| 578 | bool reduced_blanking; | ||
| 579 | unsigned pix_clk; | ||
| 580 | |||
| 581 | if (vsync < 4 || vsync > 7) | ||
| 582 | return false; | ||
| 583 | |||
| 584 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
| 585 | reduced_blanking = false; | ||
| 586 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
| 587 | reduced_blanking = true; | ||
| 588 | else | ||
| 589 | return false; | ||
| 590 | |||
| 591 | /* Vertical */ | ||
| 592 | if (reduced_blanking) { | ||
| 593 | v_fp = CVT_RB_V_FPORCH; | ||
| 594 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 999999) / 1000000; | ||
| 595 | v_bp -= vsync + v_fp; | ||
| 596 | |||
| 597 | if (v_bp < CVT_RB_MIN_V_BPORCH) | ||
| 598 | v_bp = CVT_RB_MIN_V_BPORCH; | ||
| 599 | } else { | ||
| 600 | v_fp = CVT_MIN_V_PORCH_RND; | ||
| 601 | v_bp = (CVT_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
| 602 | |||
| 603 | if (v_bp < CVT_MIN_V_BPORCH) | ||
| 604 | v_bp = CVT_MIN_V_BPORCH; | ||
| 605 | } | ||
| 606 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
| 607 | |||
| 608 | /* Aspect ratio based on vsync */ | ||
| 609 | switch (vsync) { | ||
| 610 | case 4: | ||
| 611 | image_width = (image_height * 4) / 3; | ||
| 612 | break; | ||
| 613 | case 5: | ||
| 614 | image_width = (image_height * 16) / 9; | ||
| 615 | break; | ||
| 616 | case 6: | ||
| 617 | image_width = (image_height * 16) / 10; | ||
| 618 | break; | ||
| 619 | case 7: | ||
| 620 | /* special case */ | ||
| 621 | if (image_height == 1024) | ||
| 622 | image_width = (image_height * 5) / 4; | ||
| 623 | else if (image_height == 768) | ||
| 624 | image_width = (image_height * 15) / 9; | ||
| 625 | else | ||
| 626 | return false; | ||
| 627 | break; | ||
| 628 | default: | ||
| 629 | return false; | ||
| 630 | } | ||
| 631 | |||
| 632 | image_width = image_width & ~7; | ||
| 633 | |||
| 634 | /* Horizontal */ | ||
| 635 | if (reduced_blanking) { | ||
| 636 | pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq; | ||
| 637 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
| 638 | |||
| 639 | h_bp = CVT_RB_H_BPORCH; | ||
| 640 | hsync = CVT_RB_H_SYNC; | ||
| 641 | h_fp = CVT_RB_H_BLANK - h_bp - hsync; | ||
| 642 | |||
| 643 | frame_width = image_width + CVT_RB_H_BLANK; | ||
| 644 | } else { | ||
| 645 | int h_blank; | ||
| 646 | unsigned ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * 1000) / hfreq; | ||
| 647 | |||
| 648 | h_blank = (image_width * ideal_duty_cycle + (100 - ideal_duty_cycle) / 2) / | ||
| 649 | (100 - ideal_duty_cycle); | ||
| 650 | h_blank = h_blank - h_blank % (2 * CVT_CELL_GRAN); | ||
| 651 | |||
| 652 | if (h_blank * 100 / image_width < 20) { | ||
| 653 | h_blank = image_width / 5; | ||
| 654 | h_blank = (h_blank + 0x7) & ~0x7; | ||
| 655 | } | ||
| 656 | |||
| 657 | pix_clk = (image_width + h_blank) * hfreq; | ||
| 658 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
| 659 | |||
| 660 | h_bp = h_blank / 2; | ||
| 661 | frame_width = image_width + h_blank; | ||
| 662 | |||
| 663 | hsync = (frame_width * 8 + 50) / 100; | ||
| 664 | hsync = hsync - hsync % CVT_CELL_GRAN; | ||
| 665 | h_fp = h_blank - hsync - h_bp; | ||
| 666 | } | ||
| 667 | |||
| 668 | fmt->bt.polarities = polarities; | ||
| 669 | fmt->bt.width = image_width; | ||
| 670 | fmt->bt.height = image_height; | ||
| 671 | fmt->bt.hfrontporch = h_fp; | ||
| 672 | fmt->bt.vfrontporch = v_fp; | ||
| 673 | fmt->bt.hsync = hsync; | ||
| 674 | fmt->bt.vsync = vsync; | ||
| 675 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
| 676 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
| 677 | fmt->bt.pixelclock = pix_clk; | ||
| 678 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; | ||
| 679 | if (reduced_blanking) | ||
| 680 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
| 681 | return true; | ||
| 682 | } | ||
| 683 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | ||
| 684 | |||
| 685 | /* | ||
| 686 | * GTF defines | ||
| 687 | * Based on Generalized Timing Formula Standard | ||
| 688 | * Version 1.1 September 2, 1999 | ||
| 689 | */ | ||
| 690 | |||
| 691 | #define GTF_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
| 692 | |||
| 693 | #define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
| 694 | #define GTF_V_FP 1 /* vertical front porch (lines) */ | ||
| 695 | #define GTF_CELL_GRAN 8 /* character cell granularity */ | ||
| 696 | |||
| 697 | /* Default */ | ||
| 698 | #define GTF_D_M 600 /* blanking formula gradient */ | ||
| 699 | #define GTF_D_C 40 /* blanking formula offset */ | ||
| 700 | #define GTF_D_K 128 /* blanking formula scaling factor */ | ||
| 701 | #define GTF_D_J 20 /* blanking formula scaling factor */ | ||
| 702 | #define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J) | ||
| 703 | #define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256) | ||
| 704 | |||
| 705 | /* Secondary */ | ||
| 706 | #define GTF_S_M 3600 /* blanking formula gradient */ | ||
| 707 | #define GTF_S_C 40 /* blanking formula offset */ | ||
| 708 | #define GTF_S_K 128 /* blanking formula scaling factor */ | ||
| 709 | #define GTF_S_J 35 /* blanking formula scaling factor */ | ||
| 710 | #define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J) | ||
| 711 | #define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256) | ||
| 712 | |||
| 713 | /** v4l2_detect_gtf - detect if the given timings follow the GTF standard | ||
| 714 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 715 | * @hfreq - the horizontal frequency in Hz. | ||
| 716 | * @vsync - the height of the vertical sync in lines. | ||
| 717 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 718 | * v4l2_bt_timings polarities). | ||
| 719 | * @aspect - preferred aspect ratio. GTF has no method of determining the | ||
| 720 | * aspect ratio in order to derive the image width from the | ||
| 721 | * image height, so it has to be passed explicitly. Usually | ||
| 722 | * the native screen aspect ratio is used for this. If it | ||
| 723 | * is not filled in correctly, then 16:9 will be assumed. | ||
| 724 | * @fmt - the resulting timings. | ||
| 725 | * | ||
| 726 | * This function will attempt to detect if the given values correspond to a | ||
| 727 | * valid GTF format. If so, then it will return true, and fmt will be filled | ||
| 728 | * in with the found GTF timings. | ||
| 729 | */ | ||
| 730 | bool v4l2_detect_gtf(unsigned frame_height, | ||
| 731 | unsigned hfreq, | ||
| 732 | unsigned vsync, | ||
| 733 | u32 polarities, | ||
| 734 | struct v4l2_fract aspect, | ||
| 735 | struct v4l2_dv_timings *fmt) | ||
| 736 | { | ||
| 737 | int pix_clk; | ||
| 738 | int v_fp, v_bp, h_fp, hsync; | ||
| 739 | int frame_width, image_height, image_width; | ||
| 740 | bool default_gtf; | ||
| 741 | int h_blank; | ||
| 742 | |||
| 743 | if (vsync != 3) | ||
| 744 | return false; | ||
| 745 | |||
| 746 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
| 747 | default_gtf = true; | ||
| 748 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
| 749 | default_gtf = false; | ||
| 750 | else | ||
| 751 | return false; | ||
| 752 | |||
| 753 | /* Vertical */ | ||
| 754 | v_fp = GTF_V_FP; | ||
| 755 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
| 756 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
| 757 | |||
| 758 | if (aspect.numerator == 0 || aspect.denominator == 0) { | ||
| 759 | aspect.numerator = 16; | ||
| 760 | aspect.denominator = 9; | ||
| 761 | } | ||
| 762 | image_width = ((image_height * aspect.numerator) / aspect.denominator); | ||
| 763 | |||
| 764 | /* Horizontal */ | ||
| 765 | if (default_gtf) | ||
| 766 | h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - | ||
| 767 | (image_width * GTF_D_M_PRIME * 1000) + | ||
| 768 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / | ||
| 769 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); | ||
| 770 | else | ||
| 771 | h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - | ||
| 772 | (image_width * GTF_S_M_PRIME * 1000) + | ||
| 773 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / | ||
| 774 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); | ||
| 775 | |||
| 776 | h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); | ||
| 777 | frame_width = image_width + h_blank; | ||
| 778 | |||
| 779 | pix_clk = (image_width + h_blank) * hfreq; | ||
| 780 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; | ||
| 781 | |||
| 782 | hsync = (frame_width * 8 + 50) / 100; | ||
| 783 | hsync = hsync - hsync % GTF_CELL_GRAN; | ||
| 784 | |||
| 785 | h_fp = h_blank / 2 - hsync; | ||
| 786 | |||
| 787 | fmt->bt.polarities = polarities; | ||
| 788 | fmt->bt.width = image_width; | ||
| 789 | fmt->bt.height = image_height; | ||
| 790 | fmt->bt.hfrontporch = h_fp; | ||
| 791 | fmt->bt.vfrontporch = v_fp; | ||
| 792 | fmt->bt.hsync = hsync; | ||
| 793 | fmt->bt.vsync = vsync; | ||
| 794 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
| 795 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
| 796 | fmt->bt.pixelclock = pix_clk; | ||
| 797 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; | ||
| 798 | if (!default_gtf) | ||
| 799 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
| 800 | return true; | ||
| 801 | } | ||
| 802 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); | ||
| 803 | |||
| 804 | /** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes | ||
| 805 | * 0x15 and 0x16 from the EDID. | ||
| 806 | * @hor_landscape - byte 0x15 from the EDID. | ||
| 807 | * @vert_portrait - byte 0x16 from the EDID. | ||
| 808 | * | ||
| 809 | * Determines the aspect ratio from the EDID. | ||
| 810 | * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: | ||
| 811 | * "Horizontal and Vertical Screen Size or Aspect Ratio" | ||
| 812 | */ | ||
| 813 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) | ||
| 814 | { | ||
| 815 | struct v4l2_fract aspect = { 16, 9 }; | ||
| 816 | u32 tmp; | ||
| 817 | u8 ratio; | ||
| 818 | |||
| 819 | /* Nothing filled in, fallback to 16:9 */ | ||
| 820 | if (!hor_landscape && !vert_portrait) | ||
| 821 | return aspect; | ||
| 822 | /* Both filled in, so they are interpreted as the screen size in cm */ | ||
| 823 | if (hor_landscape && vert_portrait) { | ||
| 824 | aspect.numerator = hor_landscape; | ||
| 825 | aspect.denominator = vert_portrait; | ||
| 826 | return aspect; | ||
| 827 | } | ||
| 828 | /* Only one is filled in, so interpret them as a ratio: | ||
| 829 | (val + 99) / 100 */ | ||
| 830 | ratio = hor_landscape | vert_portrait; | ||
| 831 | /* Change some rounded values into the exact aspect ratio */ | ||
| 832 | if (ratio == 79) { | ||
| 833 | aspect.numerator = 16; | ||
| 834 | aspect.denominator = 9; | ||
| 835 | } else if (ratio == 34) { | ||
| 836 | aspect.numerator = 4; | ||
| 837 | aspect.numerator = 3; | ||
| 838 | } else if (ratio == 68) { | ||
| 839 | aspect.numerator = 15; | ||
| 840 | aspect.numerator = 9; | ||
| 841 | } else { | ||
| 842 | aspect.numerator = hor_landscape + 99; | ||
| 843 | aspect.denominator = 100; | ||
| 844 | } | ||
| 845 | if (hor_landscape) | ||
| 846 | return aspect; | ||
| 847 | /* The aspect ratio is for portrait, so swap numerator and denominator */ | ||
| 848 | tmp = aspect.denominator; | ||
| 849 | aspect.denominator = aspect.numerator; | ||
| 850 | aspect.numerator = tmp; | ||
| 851 | return aspect; | ||
| 852 | } | ||
| 853 | EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio); | ||
| 854 | |||
| 855 | const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( | 498 | const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( |
| 856 | const struct v4l2_discrete_probe *probe, | 499 | const struct v4l2_discrete_probe *probe, |
| 857 | s32 width, s32 height) | 500 | s32 width, s32 height) |
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index fccd08b66d1a..c3f080388684 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
| @@ -424,6 +424,12 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
| 424 | NULL, | 424 | NULL, |
| 425 | }; | 425 | }; |
| 426 | 426 | ||
| 427 | static const char * const vpx_golden_frame_sel[] = { | ||
| 428 | "Use Previous Frame", | ||
| 429 | "Use Previous Specific Frame", | ||
| 430 | NULL, | ||
| 431 | }; | ||
| 432 | |||
| 427 | static const char * const flash_led_mode[] = { | 433 | static const char * const flash_led_mode[] = { |
| 428 | "Off", | 434 | "Off", |
| 429 | "Flash", | 435 | "Flash", |
| @@ -538,6 +544,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
| 538 | return mpeg_mpeg4_level; | 544 | return mpeg_mpeg4_level; |
| 539 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 545 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
| 540 | return mpeg4_profile; | 546 | return mpeg4_profile; |
| 547 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
| 548 | return vpx_golden_frame_sel; | ||
| 541 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | 549 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
| 542 | return jpeg_chroma_subsampling; | 550 | return jpeg_chroma_subsampling; |
| 543 | case V4L2_CID_DV_TX_MODE: | 551 | case V4L2_CID_DV_TX_MODE: |
| @@ -552,6 +560,33 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
| 552 | } | 560 | } |
| 553 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); | 561 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); |
| 554 | 562 | ||
| 563 | #define __v4l2_qmenu_int_len(arr, len) ({ *(len) = ARRAY_SIZE(arr); arr; }) | ||
| 564 | /* | ||
| 565 | * Returns NULL or an s64 type array containing the menu for given | ||
| 566 | * control ID. The total number of the menu items is returned in @len. | ||
| 567 | */ | ||
| 568 | const s64 const *v4l2_ctrl_get_int_menu(u32 id, u32 *len) | ||
| 569 | { | ||
| 570 | static const s64 const qmenu_int_vpx_num_partitions[] = { | ||
| 571 | 1, 2, 4, 8, | ||
| 572 | }; | ||
| 573 | |||
| 574 | static const s64 const qmenu_int_vpx_num_ref_frames[] = { | ||
| 575 | 1, 2, 3, | ||
| 576 | }; | ||
| 577 | |||
| 578 | switch (id) { | ||
| 579 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
| 580 | return __v4l2_qmenu_int_len(qmenu_int_vpx_num_partitions, len); | ||
| 581 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
| 582 | return __v4l2_qmenu_int_len(qmenu_int_vpx_num_ref_frames, len); | ||
| 583 | default: | ||
| 584 | *len = 0; | ||
| 585 | return NULL; | ||
| 586 | }; | ||
| 587 | } | ||
| 588 | EXPORT_SYMBOL(v4l2_ctrl_get_int_menu); | ||
| 589 | |||
| 555 | /* Return the control name. */ | 590 | /* Return the control name. */ |
| 556 | const char *v4l2_ctrl_get_name(u32 id) | 591 | const char *v4l2_ctrl_get_name(u32 id) |
| 557 | { | 592 | { |
| @@ -600,9 +635,11 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
| 600 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; | 635 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; |
| 601 | case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; | 636 | case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; |
| 602 | 637 | ||
| 603 | /* MPEG controls */ | 638 | /* Codec controls */ |
| 639 | /* The MPEG controls are applicable to all codec controls | ||
| 640 | * and the 'MPEG' part of the define is historical */ | ||
| 604 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 641 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
| 605 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; | 642 | case V4L2_CID_MPEG_CLASS: return "Codec Controls"; |
| 606 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; | 643 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; |
| 607 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; | 644 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; |
| 608 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; | 645 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; |
| @@ -700,6 +737,15 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
| 700 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; | 737 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; |
| 701 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; | 738 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; |
| 702 | 739 | ||
| 740 | /* VPX controls */ | ||
| 741 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; | ||
| 742 | case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: return "VPX Intra Mode Decision Disable"; | ||
| 743 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: return "VPX No. of Refs for P Frame"; | ||
| 744 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: return "VPX Loop Filter Level Range"; | ||
| 745 | case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: return "VPX Deblocking Effect Control"; | ||
| 746 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: return "VPX Golden Frame Refresh Period"; | ||
| 747 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: return "VPX Golden Frame Indicator"; | ||
| 748 | |||
| 703 | /* CAMERA controls */ | 749 | /* CAMERA controls */ |
| 704 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 750 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
| 705 | case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; | 751 | case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; |
| @@ -914,6 +960,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
| 914 | case V4L2_CID_DV_RX_RGB_RANGE: | 960 | case V4L2_CID_DV_RX_RGB_RANGE: |
| 915 | case V4L2_CID_TEST_PATTERN: | 961 | case V4L2_CID_TEST_PATTERN: |
| 916 | case V4L2_CID_TUNE_DEEMPHASIS: | 962 | case V4L2_CID_TUNE_DEEMPHASIS: |
| 963 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: | ||
| 917 | *type = V4L2_CTRL_TYPE_MENU; | 964 | *type = V4L2_CTRL_TYPE_MENU; |
| 918 | break; | 965 | break; |
| 919 | case V4L2_CID_LINK_FREQ: | 966 | case V4L2_CID_LINK_FREQ: |
| @@ -925,6 +972,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
| 925 | break; | 972 | break; |
| 926 | case V4L2_CID_ISO_SENSITIVITY: | 973 | case V4L2_CID_ISO_SENSITIVITY: |
| 927 | case V4L2_CID_AUTO_EXPOSURE_BIAS: | 974 | case V4L2_CID_AUTO_EXPOSURE_BIAS: |
| 975 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: | ||
| 976 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: | ||
| 928 | *type = V4L2_CTRL_TYPE_INTEGER_MENU; | 977 | *type = V4L2_CTRL_TYPE_INTEGER_MENU; |
| 929 | break; | 978 | break; |
| 930 | case V4L2_CID_USER_CLASS: | 979 | case V4L2_CID_USER_CLASS: |
| @@ -1712,7 +1761,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
| 1712 | const struct v4l2_ctrl_ops *ops, | 1761 | const struct v4l2_ctrl_ops *ops, |
| 1713 | u32 id, s32 max, s32 mask, s32 def) | 1762 | u32 id, s32 max, s32 mask, s32 def) |
| 1714 | { | 1763 | { |
| 1715 | const char * const *qmenu = v4l2_ctrl_get_menu(id); | 1764 | const char * const *qmenu = NULL; |
| 1765 | const s64 *qmenu_int = NULL; | ||
| 1766 | unsigned int qmenu_int_len = 0; | ||
| 1716 | const char *name; | 1767 | const char *name; |
| 1717 | enum v4l2_ctrl_type type; | 1768 | enum v4l2_ctrl_type type; |
| 1718 | s32 min; | 1769 | s32 min; |
| @@ -1720,12 +1771,18 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, | |||
| 1720 | u32 flags; | 1771 | u32 flags; |
| 1721 | 1772 | ||
| 1722 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); | 1773 | v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); |
| 1723 | if (type != V4L2_CTRL_TYPE_MENU) { | 1774 | |
| 1775 | if (type == V4L2_CTRL_TYPE_MENU) | ||
| 1776 | qmenu = v4l2_ctrl_get_menu(id); | ||
| 1777 | else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) | ||
| 1778 | qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len); | ||
| 1779 | |||
| 1780 | if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) { | ||
| 1724 | handler_set_err(hdl, -EINVAL); | 1781 | handler_set_err(hdl, -EINVAL); |
| 1725 | return NULL; | 1782 | return NULL; |
| 1726 | } | 1783 | } |
| 1727 | return v4l2_ctrl_new(hdl, ops, id, name, type, | 1784 | return v4l2_ctrl_new(hdl, ops, id, name, type, |
| 1728 | 0, max, mask, def, flags, qmenu, NULL, NULL); | 1785 | 0, max, mask, def, flags, qmenu, qmenu_int, NULL); |
| 1729 | } | 1786 | } |
| 1730 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); | 1787 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); |
| 1731 | 1788 | ||
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index b0f49b014bc5..b5aaaac427ad 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c | |||
| @@ -872,6 +872,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
| 872 | 872 | ||
| 873 | /* Should not happen since we thought this minor was free */ | 873 | /* Should not happen since we thought this minor was free */ |
| 874 | WARN_ON(video_device[vdev->minor] != NULL); | 874 | WARN_ON(video_device[vdev->minor] != NULL); |
| 875 | video_device[vdev->minor] = vdev; | ||
| 875 | vdev->index = get_index(vdev); | 876 | vdev->index = get_index(vdev); |
| 876 | mutex_unlock(&videodev_lock); | 877 | mutex_unlock(&videodev_lock); |
| 877 | 878 | ||
| @@ -934,9 +935,6 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
| 934 | #endif | 935 | #endif |
| 935 | /* Part 6: Activate this minor. The char device can now be used. */ | 936 | /* Part 6: Activate this minor. The char device can now be used. */ |
| 936 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); | 937 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); |
| 937 | mutex_lock(&videodev_lock); | ||
| 938 | video_device[vdev->minor] = vdev; | ||
| 939 | mutex_unlock(&videodev_lock); | ||
| 940 | 938 | ||
| 941 | return 0; | 939 | return 0; |
| 942 | 940 | ||
| @@ -944,6 +942,7 @@ cleanup: | |||
| 944 | mutex_lock(&videodev_lock); | 942 | mutex_lock(&videodev_lock); |
| 945 | if (vdev->cdev) | 943 | if (vdev->cdev) |
| 946 | cdev_del(vdev->cdev); | 944 | cdev_del(vdev->cdev); |
| 945 | video_device[vdev->minor] = NULL; | ||
| 947 | devnode_clear(vdev); | 946 | devnode_clear(vdev); |
| 948 | mutex_unlock(&videodev_lock); | 947 | mutex_unlock(&videodev_lock); |
| 949 | /* Mark this video device as never having been registered. */ | 948 | /* Mark this video device as never having been registered. */ |
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c new file mode 100644 index 000000000000..ee52b9f4a944 --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c | |||
| @@ -0,0 +1,609 @@ | |||
| 1 | /* | ||
| 2 | * v4l2-dv-timings - dv-timings helper functions | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/videodev2.h> | ||
| 26 | #include <linux/v4l2-dv-timings.h> | ||
| 27 | #include <media/v4l2-dv-timings.h> | ||
| 28 | |||
| 29 | const struct v4l2_dv_timings v4l2_dv_timings_presets[] = { | ||
| 30 | V4L2_DV_BT_CEA_640X480P59_94, | ||
| 31 | V4L2_DV_BT_CEA_720X480I59_94, | ||
| 32 | V4L2_DV_BT_CEA_720X480P59_94, | ||
| 33 | V4L2_DV_BT_CEA_720X576I50, | ||
| 34 | V4L2_DV_BT_CEA_720X576P50, | ||
| 35 | V4L2_DV_BT_CEA_1280X720P24, | ||
| 36 | V4L2_DV_BT_CEA_1280X720P25, | ||
| 37 | V4L2_DV_BT_CEA_1280X720P30, | ||
| 38 | V4L2_DV_BT_CEA_1280X720P50, | ||
| 39 | V4L2_DV_BT_CEA_1280X720P60, | ||
| 40 | V4L2_DV_BT_CEA_1920X1080P24, | ||
| 41 | V4L2_DV_BT_CEA_1920X1080P25, | ||
| 42 | V4L2_DV_BT_CEA_1920X1080P30, | ||
| 43 | V4L2_DV_BT_CEA_1920X1080I50, | ||
| 44 | V4L2_DV_BT_CEA_1920X1080P50, | ||
| 45 | V4L2_DV_BT_CEA_1920X1080I60, | ||
| 46 | V4L2_DV_BT_CEA_1920X1080P60, | ||
| 47 | V4L2_DV_BT_DMT_640X350P85, | ||
| 48 | V4L2_DV_BT_DMT_640X400P85, | ||
| 49 | V4L2_DV_BT_DMT_720X400P85, | ||
| 50 | V4L2_DV_BT_DMT_640X480P72, | ||
| 51 | V4L2_DV_BT_DMT_640X480P75, | ||
| 52 | V4L2_DV_BT_DMT_640X480P85, | ||
| 53 | V4L2_DV_BT_DMT_800X600P56, | ||
| 54 | V4L2_DV_BT_DMT_800X600P60, | ||
| 55 | V4L2_DV_BT_DMT_800X600P72, | ||
| 56 | V4L2_DV_BT_DMT_800X600P75, | ||
| 57 | V4L2_DV_BT_DMT_800X600P85, | ||
| 58 | V4L2_DV_BT_DMT_800X600P120_RB, | ||
| 59 | V4L2_DV_BT_DMT_848X480P60, | ||
| 60 | V4L2_DV_BT_DMT_1024X768I43, | ||
| 61 | V4L2_DV_BT_DMT_1024X768P60, | ||
| 62 | V4L2_DV_BT_DMT_1024X768P70, | ||
| 63 | V4L2_DV_BT_DMT_1024X768P75, | ||
| 64 | V4L2_DV_BT_DMT_1024X768P85, | ||
| 65 | V4L2_DV_BT_DMT_1024X768P120_RB, | ||
| 66 | V4L2_DV_BT_DMT_1152X864P75, | ||
| 67 | V4L2_DV_BT_DMT_1280X768P60_RB, | ||
| 68 | V4L2_DV_BT_DMT_1280X768P60, | ||
| 69 | V4L2_DV_BT_DMT_1280X768P75, | ||
| 70 | V4L2_DV_BT_DMT_1280X768P85, | ||
| 71 | V4L2_DV_BT_DMT_1280X768P120_RB, | ||
| 72 | V4L2_DV_BT_DMT_1280X800P60_RB, | ||
| 73 | V4L2_DV_BT_DMT_1280X800P60, | ||
| 74 | V4L2_DV_BT_DMT_1280X800P75, | ||
| 75 | V4L2_DV_BT_DMT_1280X800P85, | ||
| 76 | V4L2_DV_BT_DMT_1280X800P120_RB, | ||
| 77 | V4L2_DV_BT_DMT_1280X960P60, | ||
| 78 | V4L2_DV_BT_DMT_1280X960P85, | ||
| 79 | V4L2_DV_BT_DMT_1280X960P120_RB, | ||
| 80 | V4L2_DV_BT_DMT_1280X1024P60, | ||
| 81 | V4L2_DV_BT_DMT_1280X1024P75, | ||
| 82 | V4L2_DV_BT_DMT_1280X1024P85, | ||
| 83 | V4L2_DV_BT_DMT_1280X1024P120_RB, | ||
| 84 | V4L2_DV_BT_DMT_1360X768P60, | ||
| 85 | V4L2_DV_BT_DMT_1360X768P120_RB, | ||
| 86 | V4L2_DV_BT_DMT_1366X768P60, | ||
| 87 | V4L2_DV_BT_DMT_1366X768P60_RB, | ||
| 88 | V4L2_DV_BT_DMT_1400X1050P60_RB, | ||
| 89 | V4L2_DV_BT_DMT_1400X1050P60, | ||
| 90 | V4L2_DV_BT_DMT_1400X1050P75, | ||
| 91 | V4L2_DV_BT_DMT_1400X1050P85, | ||
| 92 | V4L2_DV_BT_DMT_1400X1050P120_RB, | ||
| 93 | V4L2_DV_BT_DMT_1440X900P60_RB, | ||
| 94 | V4L2_DV_BT_DMT_1440X900P60, | ||
| 95 | V4L2_DV_BT_DMT_1440X900P75, | ||
| 96 | V4L2_DV_BT_DMT_1440X900P85, | ||
| 97 | V4L2_DV_BT_DMT_1440X900P120_RB, | ||
| 98 | V4L2_DV_BT_DMT_1600X900P60_RB, | ||
| 99 | V4L2_DV_BT_DMT_1600X1200P60, | ||
| 100 | V4L2_DV_BT_DMT_1600X1200P65, | ||
| 101 | V4L2_DV_BT_DMT_1600X1200P70, | ||
| 102 | V4L2_DV_BT_DMT_1600X1200P75, | ||
| 103 | V4L2_DV_BT_DMT_1600X1200P85, | ||
| 104 | V4L2_DV_BT_DMT_1600X1200P120_RB, | ||
| 105 | V4L2_DV_BT_DMT_1680X1050P60_RB, | ||
| 106 | V4L2_DV_BT_DMT_1680X1050P60, | ||
| 107 | V4L2_DV_BT_DMT_1680X1050P75, | ||
| 108 | V4L2_DV_BT_DMT_1680X1050P85, | ||
| 109 | V4L2_DV_BT_DMT_1680X1050P120_RB, | ||
| 110 | V4L2_DV_BT_DMT_1792X1344P60, | ||
| 111 | V4L2_DV_BT_DMT_1792X1344P75, | ||
| 112 | V4L2_DV_BT_DMT_1792X1344P120_RB, | ||
| 113 | V4L2_DV_BT_DMT_1856X1392P60, | ||
| 114 | V4L2_DV_BT_DMT_1856X1392P75, | ||
| 115 | V4L2_DV_BT_DMT_1856X1392P120_RB, | ||
| 116 | V4L2_DV_BT_DMT_1920X1200P60_RB, | ||
| 117 | V4L2_DV_BT_DMT_1920X1200P60, | ||
| 118 | V4L2_DV_BT_DMT_1920X1200P75, | ||
| 119 | V4L2_DV_BT_DMT_1920X1200P85, | ||
| 120 | V4L2_DV_BT_DMT_1920X1200P120_RB, | ||
| 121 | V4L2_DV_BT_DMT_1920X1440P60, | ||
| 122 | V4L2_DV_BT_DMT_1920X1440P75, | ||
| 123 | V4L2_DV_BT_DMT_1920X1440P120_RB, | ||
| 124 | V4L2_DV_BT_DMT_2048X1152P60_RB, | ||
| 125 | V4L2_DV_BT_DMT_2560X1600P60_RB, | ||
| 126 | V4L2_DV_BT_DMT_2560X1600P60, | ||
| 127 | V4L2_DV_BT_DMT_2560X1600P75, | ||
| 128 | V4L2_DV_BT_DMT_2560X1600P85, | ||
| 129 | V4L2_DV_BT_DMT_2560X1600P120_RB, | ||
| 130 | { } | ||
| 131 | }; | ||
| 132 | EXPORT_SYMBOL_GPL(v4l2_dv_timings_presets); | ||
| 133 | |||
| 134 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, | ||
| 135 | const struct v4l2_dv_timings_cap *dvcap, | ||
| 136 | v4l2_check_dv_timings_fnc fnc, | ||
| 137 | void *fnc_handle) | ||
| 138 | { | ||
| 139 | const struct v4l2_bt_timings *bt = &t->bt; | ||
| 140 | const struct v4l2_bt_timings_cap *cap = &dvcap->bt; | ||
| 141 | u32 caps = cap->capabilities; | ||
| 142 | |||
| 143 | if (t->type != V4L2_DV_BT_656_1120) | ||
| 144 | return false; | ||
| 145 | if (t->type != dvcap->type || | ||
| 146 | bt->height < cap->min_height || | ||
| 147 | bt->height > cap->max_height || | ||
| 148 | bt->width < cap->min_width || | ||
| 149 | bt->width > cap->max_width || | ||
| 150 | bt->pixelclock < cap->min_pixelclock || | ||
| 151 | bt->pixelclock > cap->max_pixelclock || | ||
| 152 | (cap->standards && !(bt->standards & cap->standards)) || | ||
| 153 | (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || | ||
| 154 | (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) | ||
| 155 | return false; | ||
| 156 | return fnc == NULL || fnc(t, fnc_handle); | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings); | ||
| 159 | |||
| 160 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, | ||
| 161 | const struct v4l2_dv_timings_cap *cap, | ||
| 162 | v4l2_check_dv_timings_fnc fnc, | ||
| 163 | void *fnc_handle) | ||
| 164 | { | ||
| 165 | u32 i, idx; | ||
| 166 | |||
| 167 | memset(t->reserved, 0, sizeof(t->reserved)); | ||
| 168 | for (i = idx = 0; v4l2_dv_timings_presets[i].bt.width; i++) { | ||
| 169 | if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | ||
| 170 | fnc, fnc_handle) && | ||
| 171 | idx++ == t->index) { | ||
| 172 | t->timings = v4l2_dv_timings_presets[i]; | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | EXPORT_SYMBOL_GPL(v4l2_enum_dv_timings_cap); | ||
| 179 | |||
| 180 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, | ||
| 181 | const struct v4l2_dv_timings_cap *cap, | ||
| 182 | unsigned pclock_delta, | ||
| 183 | v4l2_check_dv_timings_fnc fnc, | ||
| 184 | void *fnc_handle) | ||
| 185 | { | ||
| 186 | int i; | ||
| 187 | |||
| 188 | if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle)) | ||
| 189 | return false; | ||
| 190 | |||
| 191 | for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) { | ||
| 192 | if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap, | ||
| 193 | fnc, fnc_handle) && | ||
| 194 | v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i, | ||
| 195 | pclock_delta)) { | ||
| 196 | *t = v4l2_dv_timings_presets[i]; | ||
| 197 | return true; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | return false; | ||
| 201 | } | ||
| 202 | EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap); | ||
| 203 | |||
| 204 | /** | ||
| 205 | * v4l2_match_dv_timings - check if two timings match | ||
| 206 | * @t1 - compare this v4l2_dv_timings struct... | ||
| 207 | * @t2 - with this struct. | ||
| 208 | * @pclock_delta - the allowed pixelclock deviation. | ||
| 209 | * | ||
| 210 | * Compare t1 with t2 with a given margin of error for the pixelclock. | ||
| 211 | */ | ||
| 212 | bool v4l2_match_dv_timings(const struct v4l2_dv_timings *t1, | ||
| 213 | const struct v4l2_dv_timings *t2, | ||
| 214 | unsigned pclock_delta) | ||
| 215 | { | ||
| 216 | if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) | ||
| 217 | return false; | ||
| 218 | if (t1->bt.width == t2->bt.width && | ||
| 219 | t1->bt.height == t2->bt.height && | ||
| 220 | t1->bt.interlaced == t2->bt.interlaced && | ||
| 221 | t1->bt.polarities == t2->bt.polarities && | ||
| 222 | t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && | ||
| 223 | t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && | ||
| 224 | t1->bt.hfrontporch == t2->bt.hfrontporch && | ||
| 225 | t1->bt.vfrontporch == t2->bt.vfrontporch && | ||
| 226 | t1->bt.vsync == t2->bt.vsync && | ||
| 227 | t1->bt.vbackporch == t2->bt.vbackporch && | ||
| 228 | (!t1->bt.interlaced || | ||
| 229 | (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && | ||
| 230 | t1->bt.il_vsync == t2->bt.il_vsync && | ||
| 231 | t1->bt.il_vbackporch == t2->bt.il_vbackporch))) | ||
| 232 | return true; | ||
| 233 | return false; | ||
| 234 | } | ||
| 235 | EXPORT_SYMBOL_GPL(v4l2_match_dv_timings); | ||
| 236 | |||
| 237 | void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix, | ||
| 238 | const struct v4l2_dv_timings *t, bool detailed) | ||
| 239 | { | ||
| 240 | const struct v4l2_bt_timings *bt = &t->bt; | ||
| 241 | u32 htot, vtot; | ||
| 242 | |||
| 243 | if (t->type != V4L2_DV_BT_656_1120) | ||
| 244 | return; | ||
| 245 | |||
| 246 | htot = V4L2_DV_BT_FRAME_WIDTH(bt); | ||
| 247 | vtot = V4L2_DV_BT_FRAME_HEIGHT(bt); | ||
| 248 | |||
| 249 | if (prefix == NULL) | ||
| 250 | prefix = ""; | ||
| 251 | |||
| 252 | pr_info("%s: %s%ux%u%s%u (%ux%u)\n", dev_prefix, prefix, | ||
| 253 | bt->width, bt->height, bt->interlaced ? "i" : "p", | ||
| 254 | (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, | ||
| 255 | htot, vtot); | ||
| 256 | |||
| 257 | if (!detailed) | ||
| 258 | return; | ||
| 259 | |||
| 260 | pr_info("%s: horizontal: fp = %u, %ssync = %u, bp = %u\n", | ||
| 261 | dev_prefix, bt->hfrontporch, | ||
| 262 | (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", | ||
| 263 | bt->hsync, bt->hbackporch); | ||
| 264 | pr_info("%s: vertical: fp = %u, %ssync = %u, bp = %u\n", | ||
| 265 | dev_prefix, bt->vfrontporch, | ||
| 266 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
| 267 | bt->vsync, bt->vbackporch); | ||
| 268 | pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock); | ||
| 269 | pr_info("%s: flags (0x%x):%s%s%s%s\n", dev_prefix, bt->flags, | ||
| 270 | (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ? | ||
| 271 | " REDUCED_BLANKING" : "", | ||
| 272 | (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ? | ||
| 273 | " CAN_REDUCE_FPS" : "", | ||
| 274 | (bt->flags & V4L2_DV_FL_REDUCED_FPS) ? | ||
| 275 | " REDUCED_FPS" : "", | ||
| 276 | (bt->flags & V4L2_DV_FL_HALF_LINE) ? | ||
| 277 | " HALF_LINE" : ""); | ||
| 278 | pr_info("%s: standards (0x%x):%s%s%s%s\n", dev_prefix, bt->standards, | ||
| 279 | (bt->standards & V4L2_DV_BT_STD_CEA861) ? " CEA" : "", | ||
| 280 | (bt->standards & V4L2_DV_BT_STD_DMT) ? " DMT" : "", | ||
| 281 | (bt->standards & V4L2_DV_BT_STD_CVT) ? " CVT" : "", | ||
| 282 | (bt->standards & V4L2_DV_BT_STD_GTF) ? " GTF" : ""); | ||
| 283 | } | ||
| 284 | EXPORT_SYMBOL_GPL(v4l2_print_dv_timings); | ||
| 285 | |||
| 286 | /* | ||
| 287 | * CVT defines | ||
| 288 | * Based on Coordinated Video Timings Standard | ||
| 289 | * version 1.1 September 10, 2003 | ||
| 290 | */ | ||
| 291 | |||
| 292 | #define CVT_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
| 293 | |||
| 294 | /* Normal blanking */ | ||
| 295 | #define CVT_MIN_V_BPORCH 7 /* lines */ | ||
| 296 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ | ||
| 297 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
| 298 | |||
| 299 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ | ||
| 300 | #define CVT_CELL_GRAN 8 /* character cell granularity */ | ||
| 301 | #define CVT_M 600 /* blanking formula gradient */ | ||
| 302 | #define CVT_C 40 /* blanking formula offset */ | ||
| 303 | #define CVT_K 128 /* blanking formula scaling factor */ | ||
| 304 | #define CVT_J 20 /* blanking formula scaling factor */ | ||
| 305 | #define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) | ||
| 306 | #define CVT_M_PRIME (CVT_K * CVT_M / 256) | ||
| 307 | |||
| 308 | /* Reduced Blanking */ | ||
| 309 | #define CVT_RB_MIN_V_BPORCH 7 /* lines */ | ||
| 310 | #define CVT_RB_V_FPORCH 3 /* lines */ | ||
| 311 | #define CVT_RB_MIN_V_BLANK 460 /* us */ | ||
| 312 | #define CVT_RB_H_SYNC 32 /* pixels */ | ||
| 313 | #define CVT_RB_H_BPORCH 80 /* pixels */ | ||
| 314 | #define CVT_RB_H_BLANK 160 /* pixels */ | ||
| 315 | |||
| 316 | /** v4l2_detect_cvt - detect if the given timings follow the CVT standard | ||
| 317 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 318 | * @hfreq - the horizontal frequency in Hz. | ||
| 319 | * @vsync - the height of the vertical sync in lines. | ||
| 320 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 321 | * v4l2_bt_timings polarities). | ||
| 322 | * @fmt - the resulting timings. | ||
| 323 | * | ||
| 324 | * This function will attempt to detect if the given values correspond to a | ||
| 325 | * valid CVT format. If so, then it will return true, and fmt will be filled | ||
| 326 | * in with the found CVT timings. | ||
| 327 | */ | ||
| 328 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 329 | u32 polarities, struct v4l2_dv_timings *fmt) | ||
| 330 | { | ||
| 331 | int v_fp, v_bp, h_fp, h_bp, hsync; | ||
| 332 | int frame_width, image_height, image_width; | ||
| 333 | bool reduced_blanking; | ||
| 334 | unsigned pix_clk; | ||
| 335 | |||
| 336 | if (vsync < 4 || vsync > 7) | ||
| 337 | return false; | ||
| 338 | |||
| 339 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
| 340 | reduced_blanking = false; | ||
| 341 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
| 342 | reduced_blanking = true; | ||
| 343 | else | ||
| 344 | return false; | ||
| 345 | |||
| 346 | /* Vertical */ | ||
| 347 | if (reduced_blanking) { | ||
| 348 | v_fp = CVT_RB_V_FPORCH; | ||
| 349 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 1999999) / 1000000; | ||
| 350 | v_bp -= vsync + v_fp; | ||
| 351 | |||
| 352 | if (v_bp < CVT_RB_MIN_V_BPORCH) | ||
| 353 | v_bp = CVT_RB_MIN_V_BPORCH; | ||
| 354 | } else { | ||
| 355 | v_fp = CVT_MIN_V_PORCH_RND; | ||
| 356 | v_bp = (CVT_MIN_VSYNC_BP * hfreq + 1999999) / 1000000 - vsync; | ||
| 357 | |||
| 358 | if (v_bp < CVT_MIN_V_BPORCH) | ||
| 359 | v_bp = CVT_MIN_V_BPORCH; | ||
| 360 | } | ||
| 361 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
| 362 | |||
| 363 | /* Aspect ratio based on vsync */ | ||
| 364 | switch (vsync) { | ||
| 365 | case 4: | ||
| 366 | image_width = (image_height * 4) / 3; | ||
| 367 | break; | ||
| 368 | case 5: | ||
| 369 | image_width = (image_height * 16) / 9; | ||
| 370 | break; | ||
| 371 | case 6: | ||
| 372 | image_width = (image_height * 16) / 10; | ||
| 373 | break; | ||
| 374 | case 7: | ||
| 375 | /* special case */ | ||
| 376 | if (image_height == 1024) | ||
| 377 | image_width = (image_height * 5) / 4; | ||
| 378 | else if (image_height == 768) | ||
| 379 | image_width = (image_height * 15) / 9; | ||
| 380 | else | ||
| 381 | return false; | ||
| 382 | break; | ||
| 383 | default: | ||
| 384 | return false; | ||
| 385 | } | ||
| 386 | |||
| 387 | image_width = image_width & ~7; | ||
| 388 | |||
| 389 | /* Horizontal */ | ||
| 390 | if (reduced_blanking) { | ||
| 391 | pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq; | ||
| 392 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
| 393 | |||
| 394 | h_bp = CVT_RB_H_BPORCH; | ||
| 395 | hsync = CVT_RB_H_SYNC; | ||
| 396 | h_fp = CVT_RB_H_BLANK - h_bp - hsync; | ||
| 397 | |||
| 398 | frame_width = image_width + CVT_RB_H_BLANK; | ||
| 399 | } else { | ||
| 400 | unsigned ideal_duty_cycle_per_myriad = | ||
| 401 | 100 * CVT_C_PRIME - (CVT_M_PRIME * 100000) / hfreq; | ||
| 402 | int h_blank; | ||
| 403 | |||
| 404 | if (ideal_duty_cycle_per_myriad < 2000) | ||
| 405 | ideal_duty_cycle_per_myriad = 2000; | ||
| 406 | |||
| 407 | h_blank = image_width * ideal_duty_cycle_per_myriad / | ||
| 408 | (10000 - ideal_duty_cycle_per_myriad); | ||
| 409 | h_blank = (h_blank / (2 * CVT_CELL_GRAN)) * 2 * CVT_CELL_GRAN; | ||
| 410 | |||
| 411 | pix_clk = (image_width + h_blank) * hfreq; | ||
| 412 | pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; | ||
| 413 | |||
| 414 | h_bp = h_blank / 2; | ||
| 415 | frame_width = image_width + h_blank; | ||
| 416 | |||
| 417 | hsync = (frame_width * 8 + 50) / 100; | ||
| 418 | hsync = hsync - hsync % CVT_CELL_GRAN; | ||
| 419 | h_fp = h_blank - hsync - h_bp; | ||
| 420 | } | ||
| 421 | |||
| 422 | fmt->type = V4L2_DV_BT_656_1120; | ||
| 423 | fmt->bt.polarities = polarities; | ||
| 424 | fmt->bt.width = image_width; | ||
| 425 | fmt->bt.height = image_height; | ||
| 426 | fmt->bt.hfrontporch = h_fp; | ||
| 427 | fmt->bt.vfrontporch = v_fp; | ||
| 428 | fmt->bt.hsync = hsync; | ||
| 429 | fmt->bt.vsync = vsync; | ||
| 430 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
| 431 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
| 432 | fmt->bt.pixelclock = pix_clk; | ||
| 433 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; | ||
| 434 | if (reduced_blanking) | ||
| 435 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
| 436 | return true; | ||
| 437 | } | ||
| 438 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | ||
| 439 | |||
| 440 | /* | ||
| 441 | * GTF defines | ||
| 442 | * Based on Generalized Timing Formula Standard | ||
| 443 | * Version 1.1 September 2, 1999 | ||
| 444 | */ | ||
| 445 | |||
| 446 | #define GTF_PXL_CLK_GRAN 250000 /* pixel clock granularity */ | ||
| 447 | |||
| 448 | #define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | ||
| 449 | #define GTF_V_FP 1 /* vertical front porch (lines) */ | ||
| 450 | #define GTF_CELL_GRAN 8 /* character cell granularity */ | ||
| 451 | |||
| 452 | /* Default */ | ||
| 453 | #define GTF_D_M 600 /* blanking formula gradient */ | ||
| 454 | #define GTF_D_C 40 /* blanking formula offset */ | ||
| 455 | #define GTF_D_K 128 /* blanking formula scaling factor */ | ||
| 456 | #define GTF_D_J 20 /* blanking formula scaling factor */ | ||
| 457 | #define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J) | ||
| 458 | #define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256) | ||
| 459 | |||
| 460 | /* Secondary */ | ||
| 461 | #define GTF_S_M 3600 /* blanking formula gradient */ | ||
| 462 | #define GTF_S_C 40 /* blanking formula offset */ | ||
| 463 | #define GTF_S_K 128 /* blanking formula scaling factor */ | ||
| 464 | #define GTF_S_J 35 /* blanking formula scaling factor */ | ||
| 465 | #define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J) | ||
| 466 | #define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256) | ||
| 467 | |||
| 468 | /** v4l2_detect_gtf - detect if the given timings follow the GTF standard | ||
| 469 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 470 | * @hfreq - the horizontal frequency in Hz. | ||
| 471 | * @vsync - the height of the vertical sync in lines. | ||
| 472 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 473 | * v4l2_bt_timings polarities). | ||
| 474 | * @aspect - preferred aspect ratio. GTF has no method of determining the | ||
| 475 | * aspect ratio in order to derive the image width from the | ||
| 476 | * image height, so it has to be passed explicitly. Usually | ||
| 477 | * the native screen aspect ratio is used for this. If it | ||
| 478 | * is not filled in correctly, then 16:9 will be assumed. | ||
| 479 | * @fmt - the resulting timings. | ||
| 480 | * | ||
| 481 | * This function will attempt to detect if the given values correspond to a | ||
| 482 | * valid GTF format. If so, then it will return true, and fmt will be filled | ||
| 483 | * in with the found GTF timings. | ||
| 484 | */ | ||
| 485 | bool v4l2_detect_gtf(unsigned frame_height, | ||
| 486 | unsigned hfreq, | ||
| 487 | unsigned vsync, | ||
| 488 | u32 polarities, | ||
| 489 | struct v4l2_fract aspect, | ||
| 490 | struct v4l2_dv_timings *fmt) | ||
| 491 | { | ||
| 492 | int pix_clk; | ||
| 493 | int v_fp, v_bp, h_fp, hsync; | ||
| 494 | int frame_width, image_height, image_width; | ||
| 495 | bool default_gtf; | ||
| 496 | int h_blank; | ||
| 497 | |||
| 498 | if (vsync != 3) | ||
| 499 | return false; | ||
| 500 | |||
| 501 | if (polarities == V4L2_DV_VSYNC_POS_POL) | ||
| 502 | default_gtf = true; | ||
| 503 | else if (polarities == V4L2_DV_HSYNC_POS_POL) | ||
| 504 | default_gtf = false; | ||
| 505 | else | ||
| 506 | return false; | ||
| 507 | |||
| 508 | /* Vertical */ | ||
| 509 | v_fp = GTF_V_FP; | ||
| 510 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | ||
| 511 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
| 512 | |||
| 513 | if (aspect.numerator == 0 || aspect.denominator == 0) { | ||
| 514 | aspect.numerator = 16; | ||
| 515 | aspect.denominator = 9; | ||
| 516 | } | ||
| 517 | image_width = ((image_height * aspect.numerator) / aspect.denominator); | ||
| 518 | |||
| 519 | /* Horizontal */ | ||
| 520 | if (default_gtf) | ||
| 521 | h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - | ||
| 522 | (image_width * GTF_D_M_PRIME * 1000) + | ||
| 523 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / | ||
| 524 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); | ||
| 525 | else | ||
| 526 | h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - | ||
| 527 | (image_width * GTF_S_M_PRIME * 1000) + | ||
| 528 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / | ||
| 529 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); | ||
| 530 | |||
| 531 | h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); | ||
| 532 | frame_width = image_width + h_blank; | ||
| 533 | |||
| 534 | pix_clk = (image_width + h_blank) * hfreq; | ||
| 535 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; | ||
| 536 | |||
| 537 | hsync = (frame_width * 8 + 50) / 100; | ||
| 538 | hsync = hsync - hsync % GTF_CELL_GRAN; | ||
| 539 | |||
| 540 | h_fp = h_blank / 2 - hsync; | ||
| 541 | |||
| 542 | fmt->type = V4L2_DV_BT_656_1120; | ||
| 543 | fmt->bt.polarities = polarities; | ||
| 544 | fmt->bt.width = image_width; | ||
| 545 | fmt->bt.height = image_height; | ||
| 546 | fmt->bt.hfrontporch = h_fp; | ||
| 547 | fmt->bt.vfrontporch = v_fp; | ||
| 548 | fmt->bt.hsync = hsync; | ||
| 549 | fmt->bt.vsync = vsync; | ||
| 550 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | ||
| 551 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
| 552 | fmt->bt.pixelclock = pix_clk; | ||
| 553 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; | ||
| 554 | if (!default_gtf) | ||
| 555 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | ||
| 556 | return true; | ||
| 557 | } | ||
| 558 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); | ||
| 559 | |||
| 560 | /** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes | ||
| 561 | * 0x15 and 0x16 from the EDID. | ||
| 562 | * @hor_landscape - byte 0x15 from the EDID. | ||
| 563 | * @vert_portrait - byte 0x16 from the EDID. | ||
| 564 | * | ||
| 565 | * Determines the aspect ratio from the EDID. | ||
| 566 | * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: | ||
| 567 | * "Horizontal and Vertical Screen Size or Aspect Ratio" | ||
| 568 | */ | ||
| 569 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) | ||
| 570 | { | ||
| 571 | struct v4l2_fract aspect = { 16, 9 }; | ||
| 572 | u32 tmp; | ||
| 573 | u8 ratio; | ||
| 574 | |||
| 575 | /* Nothing filled in, fallback to 16:9 */ | ||
| 576 | if (!hor_landscape && !vert_portrait) | ||
| 577 | return aspect; | ||
| 578 | /* Both filled in, so they are interpreted as the screen size in cm */ | ||
| 579 | if (hor_landscape && vert_portrait) { | ||
| 580 | aspect.numerator = hor_landscape; | ||
| 581 | aspect.denominator = vert_portrait; | ||
| 582 | return aspect; | ||
| 583 | } | ||
| 584 | /* Only one is filled in, so interpret them as a ratio: | ||
| 585 | (val + 99) / 100 */ | ||
| 586 | ratio = hor_landscape | vert_portrait; | ||
| 587 | /* Change some rounded values into the exact aspect ratio */ | ||
| 588 | if (ratio == 79) { | ||
| 589 | aspect.numerator = 16; | ||
| 590 | aspect.denominator = 9; | ||
| 591 | } else if (ratio == 34) { | ||
| 592 | aspect.numerator = 4; | ||
| 593 | aspect.numerator = 3; | ||
| 594 | } else if (ratio == 68) { | ||
| 595 | aspect.numerator = 15; | ||
| 596 | aspect.numerator = 9; | ||
| 597 | } else { | ||
| 598 | aspect.numerator = hor_landscape + 99; | ||
| 599 | aspect.denominator = 100; | ||
| 600 | } | ||
| 601 | if (hor_landscape) | ||
| 602 | return aspect; | ||
| 603 | /* The aspect ratio is for portrait, so swap numerator and denominator */ | ||
| 604 | tmp = aspect.denominator; | ||
| 605 | aspect.denominator = aspect.numerator; | ||
| 606 | aspect.numerator = tmp; | ||
| 607 | return aspect; | ||
| 608 | } | ||
| 609 | EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio); | ||
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index e96497f7c3ed..7c4371288215 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | |||
| @@ -196,6 +196,10 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) | |||
| 196 | * 2) at least one destination buffer has to be queued, | 196 | * 2) at least one destination buffer has to be queued, |
| 197 | * 3) streaming has to be on. | 197 | * 3) streaming has to be on. |
| 198 | * | 198 | * |
| 199 | * If a queue is buffered (for example a decoder hardware ringbuffer that has | ||
| 200 | * to be drained before doing streamoff), allow scheduling without v4l2 buffers | ||
| 201 | * on that queue. | ||
| 202 | * | ||
| 199 | * There may also be additional, custom requirements. In such case the driver | 203 | * There may also be additional, custom requirements. In such case the driver |
| 200 | * should supply a custom callback (job_ready in v4l2_m2m_ops) that should | 204 | * should supply a custom callback (job_ready in v4l2_m2m_ops) that should |
| 201 | * return 1 if the instance is ready. | 205 | * return 1 if the instance is ready. |
| @@ -224,7 +228,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
| 224 | } | 228 | } |
| 225 | 229 | ||
| 226 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); | 230 | spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); |
| 227 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { | 231 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) |
| 232 | && !m2m_ctx->out_q_ctx.buffered) { | ||
| 228 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, | 233 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, |
| 229 | flags_out); | 234 | flags_out); |
| 230 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | 235 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); |
| @@ -232,7 +237,8 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
| 232 | return; | 237 | return; |
| 233 | } | 238 | } |
| 234 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); | 239 | spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); |
| 235 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { | 240 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue) |
| 241 | && !m2m_ctx->cap_q_ctx.buffered) { | ||
| 236 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, | 242 | spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, |
| 237 | flags_cap); | 243 | flags_cap); |
| 238 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, | 244 | spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, |
| @@ -260,6 +266,39 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | |||
| 260 | } | 266 | } |
| 261 | 267 | ||
| 262 | /** | 268 | /** |
| 269 | * v4l2_m2m_cancel_job() - cancel pending jobs for the context | ||
| 270 | * | ||
| 271 | * In case of streamoff or release called on any context, | ||
| 272 | * 1] If the context is currently running, then abort job will be called | ||
| 273 | * 2] If the context is queued, then the context will be removed from | ||
| 274 | * the job_queue | ||
| 275 | */ | ||
| 276 | static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx) | ||
| 277 | { | ||
| 278 | struct v4l2_m2m_dev *m2m_dev; | ||
| 279 | unsigned long flags; | ||
| 280 | |||
| 281 | m2m_dev = m2m_ctx->m2m_dev; | ||
| 282 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
| 283 | if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||
| 284 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 285 | m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||
| 286 | dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); | ||
| 287 | wait_event(m2m_ctx->finished, | ||
| 288 | !(m2m_ctx->job_flags & TRANS_RUNNING)); | ||
| 289 | } else if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
| 290 | list_del(&m2m_ctx->queue); | ||
| 291 | m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
| 292 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 293 | dprintk("m2m_ctx: %p had been on queue and was removed\n", | ||
| 294 | m2m_ctx); | ||
| 295 | } else { | ||
| 296 | /* Do nothing, was not on queue/running */ | ||
| 297 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | /** | ||
| 263 | * v4l2_m2m_job_finish() - inform the framework that a job has been finished | 302 | * v4l2_m2m_job_finish() - inform the framework that a job has been finished |
| 264 | * and have it clean up | 303 | * and have it clean up |
| 265 | * | 304 | * |
| @@ -430,6 +469,9 @@ int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | |||
| 430 | unsigned long flags_job, flags; | 469 | unsigned long flags_job, flags; |
| 431 | int ret; | 470 | int ret; |
| 432 | 471 | ||
| 472 | /* wait until the current context is dequeued from job_queue */ | ||
| 473 | v4l2_m2m_cancel_job(m2m_ctx); | ||
| 474 | |||
| 433 | q_ctx = get_queue_ctx(m2m_ctx, type); | 475 | q_ctx = get_queue_ctx(m2m_ctx, type); |
| 434 | ret = vb2_streamoff(&q_ctx->q, type); | 476 | ret = vb2_streamoff(&q_ctx->q, type); |
| 435 | if (ret) | 477 | if (ret) |
| @@ -652,27 +694,8 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); | |||
| 652 | */ | 694 | */ |
| 653 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) | 695 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) |
| 654 | { | 696 | { |
| 655 | struct v4l2_m2m_dev *m2m_dev; | 697 | /* wait until the current context is dequeued from job_queue */ |
| 656 | unsigned long flags; | 698 | v4l2_m2m_cancel_job(m2m_ctx); |
| 657 | |||
| 658 | m2m_dev = m2m_ctx->m2m_dev; | ||
| 659 | |||
| 660 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
| 661 | if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||
| 662 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 663 | m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||
| 664 | dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); | ||
| 665 | wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING)); | ||
| 666 | } else if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
| 667 | list_del(&m2m_ctx->queue); | ||
| 668 | m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
| 669 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 670 | dprintk("m2m_ctx: %p had been on queue and was removed\n", | ||
| 671 | m2m_ctx); | ||
| 672 | } else { | ||
| 673 | /* Do nothing, was not on queue/running */ | ||
| 674 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
| 675 | } | ||
| 676 | 699 | ||
| 677 | vb2_queue_release(&m2m_ctx->cap_q_ctx.q); | 700 | vb2_queue_release(&m2m_ctx->cap_q_ctx.q); |
| 678 | vb2_queue_release(&m2m_ctx->out_q_ctx.q); | 701 | vb2_queue_release(&m2m_ctx->out_q_ctx.q); |
diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index aa59639d013c..a6478dca0cde 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c | |||
| @@ -100,6 +100,10 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, | |||
| 100 | if (!of_property_read_u32(node, "data-shift", &v)) | 100 | if (!of_property_read_u32(node, "data-shift", &v)) |
| 101 | bus->data_shift = v; | 101 | bus->data_shift = v; |
| 102 | 102 | ||
| 103 | if (!of_property_read_u32(node, "sync-on-green-active", &v)) | ||
| 104 | flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : | ||
| 105 | V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; | ||
| 106 | |||
| 103 | bus->flags = flags; | 107 | bus->flags = flags; |
| 104 | 108 | ||
| 105 | } | 109 | } |
| @@ -173,12 +177,8 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, | |||
| 173 | if (node) | 177 | if (node) |
| 174 | parent = node; | 178 | parent = node; |
| 175 | 179 | ||
| 176 | for_each_child_of_node(parent, node) { | 180 | port = of_get_child_by_name(parent, "port"); |
| 177 | if (!of_node_cmp(node->name, "port")) { | 181 | |
| 178 | port = node; | ||
| 179 | break; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | if (port) { | 182 | if (port) { |
| 183 | /* Found a port, get an endpoint. */ | 183 | /* Found a port, get an endpoint. */ |
| 184 | endpoint = of_get_next_child(port, NULL); | 184 | endpoint = of_get_next_child(port, NULL); |
| @@ -190,6 +190,7 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, | |||
| 190 | if (!endpoint) | 190 | if (!endpoint) |
| 191 | pr_err("%s(): no endpoint nodes specified for %s\n", | 191 | pr_err("%s(): no endpoint nodes specified for %s\n", |
| 192 | __func__, parent->full_name); | 192 | __func__, parent->full_name); |
| 193 | of_node_put(node); | ||
| 193 | } else { | 194 | } else { |
| 194 | port = of_get_parent(prev); | 195 | port = of_get_parent(prev); |
| 195 | if (!port) | 196 | if (!port) |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9fc4bab2da97..594c75eab5a5 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
| @@ -334,6 +334,41 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer | |||
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | /** | 336 | /** |
| 337 | * __verify_length() - Verify that the bytesused value for each plane fits in | ||
| 338 | * the plane length and that the data offset doesn't exceed the bytesused value. | ||
| 339 | */ | ||
| 340 | static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) | ||
| 341 | { | ||
| 342 | unsigned int length; | ||
| 343 | unsigned int plane; | ||
| 344 | |||
| 345 | if (!V4L2_TYPE_IS_OUTPUT(b->type)) | ||
| 346 | return 0; | ||
| 347 | |||
| 348 | if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { | ||
| 349 | for (plane = 0; plane < vb->num_planes; ++plane) { | ||
| 350 | length = (b->memory == V4L2_MEMORY_USERPTR) | ||
| 351 | ? b->m.planes[plane].length | ||
| 352 | : vb->v4l2_planes[plane].length; | ||
| 353 | |||
| 354 | if (b->m.planes[plane].bytesused > length) | ||
| 355 | return -EINVAL; | ||
| 356 | if (b->m.planes[plane].data_offset >= | ||
| 357 | b->m.planes[plane].bytesused) | ||
| 358 | return -EINVAL; | ||
| 359 | } | ||
| 360 | } else { | ||
| 361 | length = (b->memory == V4L2_MEMORY_USERPTR) | ||
| 362 | ? b->length : vb->v4l2_planes[0].length; | ||
| 363 | |||
| 364 | if (b->bytesused > length) | ||
| 365 | return -EINVAL; | ||
| 366 | } | ||
| 367 | |||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | /** | ||
| 337 | * __buffer_in_use() - return true if the buffer is in use and | 372 | * __buffer_in_use() - return true if the buffer is in use and |
| 338 | * the queue cannot be freed (by the means of REQBUFS(0)) call | 373 | * the queue cannot be freed (by the means of REQBUFS(0)) call |
| 339 | */ | 374 | */ |
| @@ -1167,6 +1202,10 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
| 1167 | struct vb2_queue *q = vb->vb2_queue; | 1202 | struct vb2_queue *q = vb->vb2_queue; |
| 1168 | int ret; | 1203 | int ret; |
| 1169 | 1204 | ||
| 1205 | ret = __verify_length(vb, b); | ||
| 1206 | if (ret < 0) | ||
| 1207 | return ret; | ||
| 1208 | |||
| 1170 | switch (q->memory) { | 1209 | switch (q->memory) { |
| 1171 | case V4L2_MEMORY_MMAP: | 1210 | case V4L2_MEMORY_MMAP: |
| 1172 | ret = __qbuf_mmap(vb, b); | 1211 | ret = __qbuf_mmap(vb, b); |
| @@ -1192,108 +1231,31 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
| 1192 | return ret; | 1231 | return ret; |
| 1193 | } | 1232 | } |
| 1194 | 1233 | ||
| 1195 | /** | 1234 | static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, |
| 1196 | * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel | 1235 | const char *opname, |
| 1197 | * @q: videobuf2 queue | 1236 | int (*handler)(struct vb2_queue *, |
| 1198 | * @b: buffer structure passed from userspace to vidioc_prepare_buf | 1237 | struct v4l2_buffer *, |
| 1199 | * handler in driver | 1238 | struct vb2_buffer *)) |
| 1200 | * | ||
| 1201 | * Should be called from vidioc_prepare_buf ioctl handler of a driver. | ||
| 1202 | * This function: | ||
| 1203 | * 1) verifies the passed buffer, | ||
| 1204 | * 2) calls buf_prepare callback in the driver (if provided), in which | ||
| 1205 | * driver-specific buffer initialization can be performed, | ||
| 1206 | * | ||
| 1207 | * The return values from this function are intended to be directly returned | ||
| 1208 | * from vidioc_prepare_buf handler in driver. | ||
| 1209 | */ | ||
| 1210 | int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
| 1211 | { | ||
| 1212 | struct vb2_buffer *vb; | ||
| 1213 | int ret; | ||
| 1214 | |||
| 1215 | if (q->fileio) { | ||
| 1216 | dprintk(1, "%s(): file io in progress\n", __func__); | ||
| 1217 | return -EBUSY; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | if (b->type != q->type) { | ||
| 1221 | dprintk(1, "%s(): invalid buffer type\n", __func__); | ||
| 1222 | return -EINVAL; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | if (b->index >= q->num_buffers) { | ||
| 1226 | dprintk(1, "%s(): buffer index out of range\n", __func__); | ||
| 1227 | return -EINVAL; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | vb = q->bufs[b->index]; | ||
| 1231 | if (NULL == vb) { | ||
| 1232 | /* Should never happen */ | ||
| 1233 | dprintk(1, "%s(): buffer is NULL\n", __func__); | ||
| 1234 | return -EINVAL; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | if (b->memory != q->memory) { | ||
| 1238 | dprintk(1, "%s(): invalid memory type\n", __func__); | ||
| 1239 | return -EINVAL; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | if (vb->state != VB2_BUF_STATE_DEQUEUED) { | ||
| 1243 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state); | ||
| 1244 | return -EINVAL; | ||
| 1245 | } | ||
| 1246 | ret = __verify_planes_array(vb, b); | ||
| 1247 | if (ret < 0) | ||
| 1248 | return ret; | ||
| 1249 | ret = __buf_prepare(vb, b); | ||
| 1250 | if (ret < 0) | ||
| 1251 | return ret; | ||
| 1252 | |||
| 1253 | __fill_v4l2_buffer(vb, b); | ||
| 1254 | |||
| 1255 | return 0; | ||
| 1256 | } | ||
| 1257 | EXPORT_SYMBOL_GPL(vb2_prepare_buf); | ||
| 1258 | |||
| 1259 | /** | ||
| 1260 | * vb2_qbuf() - Queue a buffer from userspace | ||
| 1261 | * @q: videobuf2 queue | ||
| 1262 | * @b: buffer structure passed from userspace to vidioc_qbuf handler | ||
| 1263 | * in driver | ||
| 1264 | * | ||
| 1265 | * Should be called from vidioc_qbuf ioctl handler of a driver. | ||
| 1266 | * This function: | ||
| 1267 | * 1) verifies the passed buffer, | ||
| 1268 | * 2) if necessary, calls buf_prepare callback in the driver (if provided), in | ||
| 1269 | * which driver-specific buffer initialization can be performed, | ||
| 1270 | * 3) if streaming is on, queues the buffer in driver by the means of buf_queue | ||
| 1271 | * callback for processing. | ||
| 1272 | * | ||
| 1273 | * The return values from this function are intended to be directly returned | ||
| 1274 | * from vidioc_qbuf handler in driver. | ||
| 1275 | */ | ||
| 1276 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
| 1277 | { | 1239 | { |
| 1278 | struct rw_semaphore *mmap_sem = NULL; | 1240 | struct rw_semaphore *mmap_sem = NULL; |
| 1279 | struct vb2_buffer *vb; | 1241 | struct vb2_buffer *vb; |
| 1280 | int ret = 0; | 1242 | int ret; |
| 1281 | 1243 | ||
| 1282 | /* | 1244 | /* |
| 1283 | * In case of user pointer buffers vb2 allocator needs to get direct | 1245 | * In case of user pointer buffers vb2 allocators need to get direct |
| 1284 | * access to userspace pages. This requires getting read access on | 1246 | * access to userspace pages. This requires getting the mmap semaphore |
| 1285 | * mmap semaphore in the current process structure. The same | 1247 | * for read access in the current process structure. The same semaphore |
| 1286 | * semaphore is taken before calling mmap operation, while both mmap | 1248 | * is taken before calling mmap operation, while both qbuf/prepare_buf |
| 1287 | * and qbuf are called by the driver or v4l2 core with driver's lock | 1249 | * and mmap are called by the driver or v4l2 core with the driver's lock |
| 1288 | * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in | 1250 | * held. To avoid an AB-BA deadlock (mmap_sem then driver's lock in mmap |
| 1289 | * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core | 1251 | * and driver's lock then mmap_sem in qbuf/prepare_buf) the videobuf2 |
| 1290 | * release driver's lock, takes mmap_sem and then takes again driver's | 1252 | * core releases the driver's lock, takes mmap_sem and then takes the |
| 1291 | * lock. | 1253 | * driver's lock again. |
| 1292 | * | 1254 | * |
| 1293 | * To avoid race with other vb2 calls, which might be called after | 1255 | * To avoid racing with other vb2 calls, which might be called after |
| 1294 | * releasing driver's lock, this operation is performed at the | 1256 | * releasing the driver's lock, this operation is performed at the |
| 1295 | * beggining of qbuf processing. This way the queue status is | 1257 | * beginning of qbuf/prepare_buf processing. This way the queue status |
| 1296 | * consistent after getting driver's lock back. | 1258 | * is consistent after getting the driver's lock back. |
| 1297 | */ | 1259 | */ |
| 1298 | if (q->memory == V4L2_MEMORY_USERPTR) { | 1260 | if (q->memory == V4L2_MEMORY_USERPTR) { |
| 1299 | mmap_sem = ¤t->mm->mmap_sem; | 1261 | mmap_sem = ¤t->mm->mmap_sem; |
| @@ -1303,19 +1265,19 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
| 1303 | } | 1265 | } |
| 1304 | 1266 | ||
| 1305 | if (q->fileio) { | 1267 | if (q->fileio) { |
| 1306 | dprintk(1, "qbuf: file io in progress\n"); | 1268 | dprintk(1, "%s(): file io in progress\n", opname); |
| 1307 | ret = -EBUSY; | 1269 | ret = -EBUSY; |
| 1308 | goto unlock; | 1270 | goto unlock; |
| 1309 | } | 1271 | } |
| 1310 | 1272 | ||
| 1311 | if (b->type != q->type) { | 1273 | if (b->type != q->type) { |
| 1312 | dprintk(1, "qbuf: invalid buffer type\n"); | 1274 | dprintk(1, "%s(): invalid buffer type\n", opname); |
| 1313 | ret = -EINVAL; | 1275 | ret = -EINVAL; |
| 1314 | goto unlock; | 1276 | goto unlock; |
| 1315 | } | 1277 | } |
| 1316 | 1278 | ||
| 1317 | if (b->index >= q->num_buffers) { | 1279 | if (b->index >= q->num_buffers) { |
| 1318 | dprintk(1, "qbuf: buffer index out of range\n"); | 1280 | dprintk(1, "%s(): buffer index out of range\n", opname); |
| 1319 | ret = -EINVAL; | 1281 | ret = -EINVAL; |
| 1320 | goto unlock; | 1282 | goto unlock; |
| 1321 | } | 1283 | } |
| @@ -1323,31 +1285,83 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
| 1323 | vb = q->bufs[b->index]; | 1285 | vb = q->bufs[b->index]; |
| 1324 | if (NULL == vb) { | 1286 | if (NULL == vb) { |
| 1325 | /* Should never happen */ | 1287 | /* Should never happen */ |
| 1326 | dprintk(1, "qbuf: buffer is NULL\n"); | 1288 | dprintk(1, "%s(): buffer is NULL\n", opname); |
| 1327 | ret = -EINVAL; | 1289 | ret = -EINVAL; |
| 1328 | goto unlock; | 1290 | goto unlock; |
| 1329 | } | 1291 | } |
| 1330 | 1292 | ||
| 1331 | if (b->memory != q->memory) { | 1293 | if (b->memory != q->memory) { |
| 1332 | dprintk(1, "qbuf: invalid memory type\n"); | 1294 | dprintk(1, "%s(): invalid memory type\n", opname); |
| 1333 | ret = -EINVAL; | 1295 | ret = -EINVAL; |
| 1334 | goto unlock; | 1296 | goto unlock; |
| 1335 | } | 1297 | } |
| 1298 | |||
| 1336 | ret = __verify_planes_array(vb, b); | 1299 | ret = __verify_planes_array(vb, b); |
| 1337 | if (ret) | 1300 | if (ret) |
| 1338 | goto unlock; | 1301 | goto unlock; |
| 1339 | 1302 | ||
| 1303 | ret = handler(q, b, vb); | ||
| 1304 | if (ret) | ||
| 1305 | goto unlock; | ||
| 1306 | |||
| 1307 | /* Fill buffer information for the userspace */ | ||
| 1308 | __fill_v4l2_buffer(vb, b); | ||
| 1309 | |||
| 1310 | dprintk(1, "%s() of buffer %d succeeded\n", opname, vb->v4l2_buf.index); | ||
| 1311 | unlock: | ||
| 1312 | if (mmap_sem) | ||
| 1313 | up_read(mmap_sem); | ||
| 1314 | return ret; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | static int __vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b, | ||
| 1318 | struct vb2_buffer *vb) | ||
| 1319 | { | ||
| 1320 | if (vb->state != VB2_BUF_STATE_DEQUEUED) { | ||
| 1321 | dprintk(1, "%s(): invalid buffer state %d\n", __func__, | ||
| 1322 | vb->state); | ||
| 1323 | return -EINVAL; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | return __buf_prepare(vb, b); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | /** | ||
| 1330 | * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel | ||
| 1331 | * @q: videobuf2 queue | ||
| 1332 | * @b: buffer structure passed from userspace to vidioc_prepare_buf | ||
| 1333 | * handler in driver | ||
| 1334 | * | ||
| 1335 | * Should be called from vidioc_prepare_buf ioctl handler of a driver. | ||
| 1336 | * This function: | ||
| 1337 | * 1) verifies the passed buffer, | ||
| 1338 | * 2) calls buf_prepare callback in the driver (if provided), in which | ||
| 1339 | * driver-specific buffer initialization can be performed, | ||
| 1340 | * | ||
| 1341 | * The return values from this function are intended to be directly returned | ||
| 1342 | * from vidioc_prepare_buf handler in driver. | ||
| 1343 | */ | ||
| 1344 | int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
| 1345 | { | ||
| 1346 | return vb2_queue_or_prepare_buf(q, b, "prepare_buf", __vb2_prepare_buf); | ||
| 1347 | } | ||
| 1348 | EXPORT_SYMBOL_GPL(vb2_prepare_buf); | ||
| 1349 | |||
| 1350 | static int __vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b, | ||
| 1351 | struct vb2_buffer *vb) | ||
| 1352 | { | ||
| 1353 | int ret; | ||
| 1354 | |||
| 1340 | switch (vb->state) { | 1355 | switch (vb->state) { |
| 1341 | case VB2_BUF_STATE_DEQUEUED: | 1356 | case VB2_BUF_STATE_DEQUEUED: |
| 1342 | ret = __buf_prepare(vb, b); | 1357 | ret = __buf_prepare(vb, b); |
| 1343 | if (ret) | 1358 | if (ret) |
| 1344 | goto unlock; | 1359 | return ret; |
| 1345 | case VB2_BUF_STATE_PREPARED: | 1360 | case VB2_BUF_STATE_PREPARED: |
| 1346 | break; | 1361 | break; |
| 1347 | default: | 1362 | default: |
| 1348 | dprintk(1, "qbuf: buffer already in use\n"); | 1363 | dprintk(1, "qbuf: buffer already in use\n"); |
| 1349 | ret = -EINVAL; | 1364 | return -EINVAL; |
| 1350 | goto unlock; | ||
| 1351 | } | 1365 | } |
| 1352 | 1366 | ||
| 1353 | /* | 1367 | /* |
| @@ -1364,14 +1378,29 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
| 1364 | if (q->streaming) | 1378 | if (q->streaming) |
| 1365 | __enqueue_in_driver(vb); | 1379 | __enqueue_in_driver(vb); |
| 1366 | 1380 | ||
| 1367 | /* Fill buffer information for the userspace */ | 1381 | return 0; |
| 1368 | __fill_v4l2_buffer(vb, b); | 1382 | } |
| 1369 | 1383 | ||
| 1370 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); | 1384 | /** |
| 1371 | unlock: | 1385 | * vb2_qbuf() - Queue a buffer from userspace |
| 1372 | if (mmap_sem) | 1386 | * @q: videobuf2 queue |
| 1373 | up_read(mmap_sem); | 1387 | * @b: buffer structure passed from userspace to vidioc_qbuf handler |
| 1374 | return ret; | 1388 | * in driver |
| 1389 | * | ||
| 1390 | * Should be called from vidioc_qbuf ioctl handler of a driver. | ||
| 1391 | * This function: | ||
| 1392 | * 1) verifies the passed buffer, | ||
| 1393 | * 2) if necessary, calls buf_prepare callback in the driver (if provided), in | ||
| 1394 | * which driver-specific buffer initialization can be performed, | ||
| 1395 | * 3) if streaming is on, queues the buffer in driver by the means of buf_queue | ||
| 1396 | * callback for processing. | ||
| 1397 | * | ||
| 1398 | * The return values from this function are intended to be directly returned | ||
| 1399 | * from vidioc_qbuf handler in driver. | ||
| 1400 | */ | ||
| 1401 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | ||
| 1402 | { | ||
| 1403 | return vb2_queue_or_prepare_buf(q, b, "qbuf", __vb2_qbuf); | ||
| 1375 | } | 1404 | } |
| 1376 | EXPORT_SYMBOL_GPL(vb2_qbuf); | 1405 | EXPORT_SYMBOL_GPL(vb2_qbuf); |
| 1377 | 1406 | ||
| @@ -2578,8 +2607,15 @@ EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); | |||
| 2578 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) | 2607 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) |
| 2579 | { | 2608 | { |
| 2580 | struct video_device *vdev = video_devdata(file); | 2609 | struct video_device *vdev = video_devdata(file); |
| 2610 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
| 2611 | int err; | ||
| 2581 | 2612 | ||
| 2582 | return vb2_mmap(vdev->queue, vma); | 2613 | if (lock && mutex_lock_interruptible(lock)) |
| 2614 | return -ERESTARTSYS; | ||
| 2615 | err = vb2_mmap(vdev->queue, vma); | ||
| 2616 | if (lock) | ||
| 2617 | mutex_unlock(lock); | ||
| 2618 | return err; | ||
| 2583 | } | 2619 | } |
| 2584 | EXPORT_SYMBOL_GPL(vb2_fop_mmap); | 2620 | EXPORT_SYMBOL_GPL(vb2_fop_mmap); |
| 2585 | 2621 | ||
| @@ -2685,8 +2721,15 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 2685 | unsigned long len, unsigned long pgoff, unsigned long flags) | 2721 | unsigned long len, unsigned long pgoff, unsigned long flags) |
| 2686 | { | 2722 | { |
| 2687 | struct video_device *vdev = video_devdata(file); | 2723 | struct video_device *vdev = video_devdata(file); |
| 2724 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
| 2725 | int ret; | ||
| 2688 | 2726 | ||
| 2689 | return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); | 2727 | if (lock && mutex_lock_interruptible(lock)) |
| 2728 | return -ERESTARTSYS; | ||
| 2729 | ret = vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); | ||
| 2730 | if (lock) | ||
| 2731 | mutex_unlock(lock); | ||
| 2732 | return ret; | ||
| 2690 | } | 2733 | } |
| 2691 | EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); | 2734 | EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); |
| 2692 | #endif | 2735 | #endif |
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index ae0abc350e34..46f1e619cbd8 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig | |||
| @@ -29,6 +29,8 @@ source "drivers/staging/media/dt3155v4l/Kconfig" | |||
| 29 | 29 | ||
| 30 | source "drivers/staging/media/go7007/Kconfig" | 30 | source "drivers/staging/media/go7007/Kconfig" |
| 31 | 31 | ||
| 32 | source "drivers/staging/media/msi3101/Kconfig" | ||
| 33 | |||
| 32 | source "drivers/staging/media/solo6x10/Kconfig" | 34 | source "drivers/staging/media/solo6x10/Kconfig" |
| 33 | 35 | ||
| 34 | # Keep LIRC at the end, as it has sub-menus | 36 | # Keep LIRC at the end, as it has sub-menus |
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 2b97cae99499..eb7f30b1ccd8 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile | |||
| @@ -4,4 +4,5 @@ obj-$(CONFIG_LIRC_STAGING) += lirc/ | |||
| 4 | obj-$(CONFIG_SOLO6X10) += solo6x10/ | 4 | obj-$(CONFIG_SOLO6X10) += solo6x10/ |
| 5 | obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ | 5 | obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ |
| 6 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | 6 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
| 7 | obj-$(CONFIG_USB_MSI3101) += msi3101/ | ||
| 7 | obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ | 8 | obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ |
diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c index 2faa391006db..28c8b0bcf5b2 100644 --- a/drivers/staging/media/lirc/lirc_igorplugusb.c +++ b/drivers/staging/media/lirc/lirc_igorplugusb.c | |||
| @@ -240,10 +240,6 @@ static int unregister_from_lirc(struct igorplug *ir) | |||
| 240 | dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum); | 240 | dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum); |
| 241 | lirc_unregister_driver(d->minor); | 241 | lirc_unregister_driver(d->minor); |
| 242 | 242 | ||
| 243 | kfree(d); | ||
| 244 | ir->d = NULL; | ||
| 245 | kfree(ir); | ||
| 246 | |||
| 247 | return devnum; | 243 | return devnum; |
| 248 | } | 244 | } |
| 249 | 245 | ||
| @@ -377,20 +373,16 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf) | |||
| 377 | return -ENODATA; | 373 | return -ENODATA; |
| 378 | } | 374 | } |
| 379 | 375 | ||
| 380 | |||
| 381 | |||
| 382 | static int igorplugusb_remote_probe(struct usb_interface *intf, | 376 | static int igorplugusb_remote_probe(struct usb_interface *intf, |
| 383 | const struct usb_device_id *id) | 377 | const struct usb_device_id *id) |
| 384 | { | 378 | { |
| 385 | struct usb_device *dev = NULL; | 379 | struct usb_device *dev; |
| 386 | struct usb_host_interface *idesc = NULL; | 380 | struct usb_host_interface *idesc = NULL; |
| 387 | struct usb_endpoint_descriptor *ep; | 381 | struct usb_endpoint_descriptor *ep; |
| 388 | struct igorplug *ir = NULL; | 382 | struct igorplug *ir = NULL; |
| 389 | struct lirc_driver *driver = NULL; | 383 | struct lirc_driver *driver = NULL; |
| 390 | int devnum, pipe, maxp; | 384 | int devnum, pipe, maxp; |
| 391 | int minor = 0; | ||
| 392 | char buf[63], name[128] = ""; | 385 | char buf[63], name[128] = ""; |
| 393 | int mem_failure = 0; | ||
| 394 | int ret; | 386 | int ret; |
| 395 | 387 | ||
| 396 | dprintk(DRIVER_NAME ": usb probe called.\n"); | 388 | dprintk(DRIVER_NAME ": usb probe called.\n"); |
| @@ -416,24 +408,18 @@ static int igorplugusb_remote_probe(struct usb_interface *intf, | |||
| 416 | dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n", | 408 | dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n", |
| 417 | devnum, CODE_LENGTH, maxp); | 409 | devnum, CODE_LENGTH, maxp); |
| 418 | 410 | ||
| 419 | mem_failure = 0; | 411 | ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL); |
| 420 | ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); | 412 | if (!ir) |
| 421 | if (!ir) { | 413 | return -ENOMEM; |
| 422 | mem_failure = 1; | 414 | |
| 423 | goto mem_failure_switch; | 415 | driver = devm_kzalloc(&intf->dev, sizeof(*driver), GFP_KERNEL); |
| 424 | } | 416 | if (!driver) |
| 425 | driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); | 417 | return -ENOMEM; |
| 426 | if (!driver) { | ||
| 427 | mem_failure = 2; | ||
| 428 | goto mem_failure_switch; | ||
| 429 | } | ||
| 430 | 418 | ||
| 431 | ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, | 419 | ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, |
| 432 | GFP_ATOMIC, &ir->dma_in); | 420 | GFP_ATOMIC, &ir->dma_in); |
| 433 | if (!ir->buf_in) { | 421 | if (!ir->buf_in) |
| 434 | mem_failure = 3; | 422 | return -ENOMEM; |
| 435 | goto mem_failure_switch; | ||
| 436 | } | ||
| 437 | 423 | ||
| 438 | strcpy(driver->name, DRIVER_NAME " "); | 424 | strcpy(driver->name, DRIVER_NAME " "); |
| 439 | driver->minor = -1; | 425 | driver->minor = -1; |
| @@ -449,27 +435,14 @@ static int igorplugusb_remote_probe(struct usb_interface *intf, | |||
| 449 | driver->dev = &intf->dev; | 435 | driver->dev = &intf->dev; |
| 450 | driver->owner = THIS_MODULE; | 436 | driver->owner = THIS_MODULE; |
| 451 | 437 | ||
| 452 | minor = lirc_register_driver(driver); | 438 | ret = lirc_register_driver(driver); |
| 453 | if (minor < 0) | 439 | if (ret < 0) { |
| 454 | mem_failure = 9; | ||
| 455 | |||
| 456 | mem_failure_switch: | ||
| 457 | |||
| 458 | switch (mem_failure) { | ||
| 459 | case 9: | ||
| 460 | usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, | 440 | usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, |
| 461 | ir->buf_in, ir->dma_in); | 441 | ir->buf_in, ir->dma_in); |
| 462 | case 3: | 442 | return ret; |
| 463 | kfree(driver); | ||
| 464 | case 2: | ||
| 465 | kfree(ir); | ||
| 466 | case 1: | ||
| 467 | printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", | ||
| 468 | devnum, mem_failure); | ||
| 469 | return -ENOMEM; | ||
| 470 | } | 443 | } |
| 471 | 444 | ||
| 472 | driver->minor = minor; | 445 | driver->minor = ret; |
| 473 | ir->d = driver; | 446 | ir->d = driver; |
| 474 | ir->devnum = devnum; | 447 | ir->devnum = devnum; |
| 475 | ir->usbdev = dev; | 448 | ir->usbdev = dev; |
| @@ -502,7 +475,6 @@ mem_failure_switch: | |||
| 502 | return 0; | 475 | return 0; |
| 503 | } | 476 | } |
| 504 | 477 | ||
| 505 | |||
| 506 | static void igorplugusb_remote_disconnect(struct usb_interface *intf) | 478 | static void igorplugusb_remote_disconnect(struct usb_interface *intf) |
| 507 | { | 479 | { |
| 508 | struct usb_device *usbdev = interface_to_usbdev(intf); | 480 | struct usb_device *usbdev = interface_to_usbdev(intf); |
diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig new file mode 100644 index 000000000000..b94a95a597d6 --- /dev/null +++ b/drivers/staging/media/msi3101/Kconfig | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | config USB_MSI3101 | ||
| 2 | tristate "Mirics MSi3101 SDR Dongle" | ||
| 3 | depends on USB && VIDEO_DEV && VIDEO_V4L2 | ||
diff --git a/drivers/staging/media/msi3101/Makefile b/drivers/staging/media/msi3101/Makefile new file mode 100644 index 000000000000..3730654b0eb9 --- /dev/null +++ b/drivers/staging/media/msi3101/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_USB_MSI3101) += sdr-msi3101.o | |||
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c new file mode 100644 index 000000000000..24c7b70a6cbf --- /dev/null +++ b/drivers/staging/media/msi3101/sdr-msi3101.c | |||
| @@ -0,0 +1,1931 @@ | |||
| 1 | /* | ||
| 2 | * Mirics MSi3101 SDR Dongle driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | * | ||
| 20 | * That driver is somehow based of pwc driver: | ||
| 21 | * (C) 1999-2004 Nemosoft Unv. | ||
| 22 | * (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
| 23 | * (C) 2011 Hans de Goede <hdegoede@redhat.com> | ||
| 24 | * | ||
| 25 | * Development tree of that driver will be on: | ||
| 26 | * http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/mirics | ||
| 27 | * | ||
| 28 | * GNU Radio plugin "gr-kernel" for device usage will be on: | ||
| 29 | * http://git.linuxtv.org/anttip/gr-kernel.git | ||
| 30 | * | ||
| 31 | * TODO: | ||
| 32 | * Help is very highly welcome for these + all the others you could imagine: | ||
| 33 | * - split USB ADC interface and RF tuner to own drivers (msi2500 and msi001) | ||
| 34 | * - move controls to V4L2 API | ||
| 35 | * - use libv4l2 for stream format conversions | ||
| 36 | * - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu) | ||
| 37 | * - SDRSharp support | ||
| 38 | */ | ||
| 39 | |||
| 40 | #include <linux/module.h> | ||
| 41 | #include <linux/slab.h> | ||
| 42 | #include <linux/gcd.h> | ||
| 43 | #include <asm/div64.h> | ||
| 44 | #include <media/v4l2-device.h> | ||
| 45 | #include <media/v4l2-ioctl.h> | ||
| 46 | #include <media/v4l2-ctrls.h> | ||
| 47 | #include <media/v4l2-event.h> | ||
| 48 | #include <linux/usb.h> | ||
| 49 | #include <media/videobuf2-vmalloc.h> | ||
| 50 | |||
| 51 | struct msi3101_gain { | ||
| 52 | u8 tot:7; | ||
| 53 | u8 baseband:6; | ||
| 54 | bool lna:1; | ||
| 55 | bool mixer:1; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* 60 – 120 MHz band, lna 24dB, mixer 19dB */ | ||
| 59 | static const struct msi3101_gain msi3101_gain_lut_120[] = { | ||
| 60 | { 0, 0, 0, 0}, | ||
| 61 | { 1, 1, 0, 0}, | ||
| 62 | { 2, 2, 0, 0}, | ||
| 63 | { 3, 3, 0, 0}, | ||
| 64 | { 4, 4, 0, 0}, | ||
| 65 | { 5, 5, 0, 0}, | ||
| 66 | { 6, 6, 0, 0}, | ||
| 67 | { 7, 7, 0, 0}, | ||
| 68 | { 8, 8, 0, 0}, | ||
| 69 | { 9, 9, 0, 0}, | ||
| 70 | { 10, 10, 0, 0}, | ||
| 71 | { 11, 11, 0, 0}, | ||
| 72 | { 12, 12, 0, 0}, | ||
| 73 | { 13, 13, 0, 0}, | ||
| 74 | { 14, 14, 0, 0}, | ||
| 75 | { 15, 15, 0, 0}, | ||
| 76 | { 16, 16, 0, 0}, | ||
| 77 | { 17, 17, 0, 0}, | ||
| 78 | { 18, 18, 0, 0}, | ||
| 79 | { 19, 19, 0, 0}, | ||
| 80 | { 20, 20, 0, 0}, | ||
| 81 | { 21, 21, 0, 0}, | ||
| 82 | { 22, 22, 0, 0}, | ||
| 83 | { 23, 23, 0, 0}, | ||
| 84 | { 24, 24, 0, 0}, | ||
| 85 | { 25, 25, 0, 0}, | ||
| 86 | { 26, 26, 0, 0}, | ||
| 87 | { 27, 27, 0, 0}, | ||
| 88 | { 28, 28, 0, 0}, | ||
| 89 | { 29, 5, 1, 0}, | ||
| 90 | { 30, 6, 1, 0}, | ||
| 91 | { 31, 7, 1, 0}, | ||
| 92 | { 32, 8, 1, 0}, | ||
| 93 | { 33, 9, 1, 0}, | ||
| 94 | { 34, 10, 1, 0}, | ||
| 95 | { 35, 11, 1, 0}, | ||
| 96 | { 36, 12, 1, 0}, | ||
| 97 | { 37, 13, 1, 0}, | ||
| 98 | { 38, 14, 1, 0}, | ||
| 99 | { 39, 15, 1, 0}, | ||
| 100 | { 40, 16, 1, 0}, | ||
| 101 | { 41, 17, 1, 0}, | ||
| 102 | { 42, 18, 1, 0}, | ||
| 103 | { 43, 19, 1, 0}, | ||
| 104 | { 44, 20, 1, 0}, | ||
| 105 | { 45, 21, 1, 0}, | ||
| 106 | { 46, 22, 1, 0}, | ||
| 107 | { 47, 23, 1, 0}, | ||
| 108 | { 48, 24, 1, 0}, | ||
| 109 | { 49, 25, 1, 0}, | ||
| 110 | { 50, 26, 1, 0}, | ||
| 111 | { 51, 27, 1, 0}, | ||
| 112 | { 52, 28, 1, 0}, | ||
| 113 | { 53, 29, 1, 0}, | ||
| 114 | { 54, 30, 1, 0}, | ||
| 115 | { 55, 31, 1, 0}, | ||
| 116 | { 56, 32, 1, 0}, | ||
| 117 | { 57, 33, 1, 0}, | ||
| 118 | { 58, 34, 1, 0}, | ||
| 119 | { 59, 35, 1, 0}, | ||
| 120 | { 60, 36, 1, 0}, | ||
| 121 | { 61, 37, 1, 0}, | ||
| 122 | { 62, 38, 1, 0}, | ||
| 123 | { 63, 39, 1, 0}, | ||
| 124 | { 64, 40, 1, 0}, | ||
| 125 | { 65, 41, 1, 0}, | ||
| 126 | { 66, 42, 1, 0}, | ||
| 127 | { 67, 43, 1, 0}, | ||
| 128 | { 68, 44, 1, 0}, | ||
| 129 | { 69, 45, 1, 0}, | ||
| 130 | { 70, 46, 1, 0}, | ||
| 131 | { 71, 47, 1, 0}, | ||
| 132 | { 72, 48, 1, 0}, | ||
| 133 | { 73, 49, 1, 0}, | ||
| 134 | { 74, 50, 1, 0}, | ||
| 135 | { 75, 51, 1, 0}, | ||
| 136 | { 76, 52, 1, 0}, | ||
| 137 | { 77, 53, 1, 0}, | ||
| 138 | { 78, 54, 1, 0}, | ||
| 139 | { 79, 55, 1, 0}, | ||
| 140 | { 80, 56, 1, 0}, | ||
| 141 | { 81, 57, 1, 0}, | ||
| 142 | { 82, 58, 1, 0}, | ||
| 143 | { 83, 40, 1, 1}, | ||
| 144 | { 84, 41, 1, 1}, | ||
| 145 | { 85, 42, 1, 1}, | ||
| 146 | { 86, 43, 1, 1}, | ||
| 147 | { 87, 44, 1, 1}, | ||
| 148 | { 88, 45, 1, 1}, | ||
| 149 | { 89, 46, 1, 1}, | ||
| 150 | { 90, 47, 1, 1}, | ||
| 151 | { 91, 48, 1, 1}, | ||
| 152 | { 92, 49, 1, 1}, | ||
| 153 | { 93, 50, 1, 1}, | ||
| 154 | { 94, 51, 1, 1}, | ||
| 155 | { 95, 52, 1, 1}, | ||
| 156 | { 96, 53, 1, 1}, | ||
| 157 | { 97, 54, 1, 1}, | ||
| 158 | { 98, 55, 1, 1}, | ||
| 159 | { 99, 56, 1, 1}, | ||
| 160 | {100, 57, 1, 1}, | ||
| 161 | {101, 58, 1, 1}, | ||
| 162 | {102, 59, 1, 1}, | ||
| 163 | }; | ||
| 164 | |||
| 165 | /* 120 – 245 MHz band, lna 24dB, mixer 19dB */ | ||
| 166 | static const struct msi3101_gain msi3101_gain_lut_245[] = { | ||
| 167 | { 0, 0, 0, 0}, | ||
| 168 | { 1, 1, 0, 0}, | ||
| 169 | { 2, 2, 0, 0}, | ||
| 170 | { 3, 3, 0, 0}, | ||
| 171 | { 4, 4, 0, 0}, | ||
| 172 | { 5, 5, 0, 0}, | ||
| 173 | { 6, 6, 0, 0}, | ||
| 174 | { 7, 7, 0, 0}, | ||
| 175 | { 8, 8, 0, 0}, | ||
| 176 | { 9, 9, 0, 0}, | ||
| 177 | { 10, 10, 0, 0}, | ||
| 178 | { 11, 11, 0, 0}, | ||
| 179 | { 12, 12, 0, 0}, | ||
| 180 | { 13, 13, 0, 0}, | ||
| 181 | { 14, 14, 0, 0}, | ||
| 182 | { 15, 15, 0, 0}, | ||
| 183 | { 16, 16, 0, 0}, | ||
| 184 | { 17, 17, 0, 0}, | ||
| 185 | { 18, 18, 0, 0}, | ||
| 186 | { 19, 19, 0, 0}, | ||
| 187 | { 20, 20, 0, 0}, | ||
| 188 | { 21, 21, 0, 0}, | ||
| 189 | { 22, 22, 0, 0}, | ||
| 190 | { 23, 23, 0, 0}, | ||
| 191 | { 24, 24, 0, 0}, | ||
| 192 | { 25, 25, 0, 0}, | ||
| 193 | { 26, 26, 0, 0}, | ||
| 194 | { 27, 27, 0, 0}, | ||
| 195 | { 28, 28, 0, 0}, | ||
| 196 | { 29, 5, 1, 0}, | ||
| 197 | { 30, 6, 1, 0}, | ||
| 198 | { 31, 7, 1, 0}, | ||
| 199 | { 32, 8, 1, 0}, | ||
| 200 | { 33, 9, 1, 0}, | ||
| 201 | { 34, 10, 1, 0}, | ||
| 202 | { 35, 11, 1, 0}, | ||
| 203 | { 36, 12, 1, 0}, | ||
| 204 | { 37, 13, 1, 0}, | ||
| 205 | { 38, 14, 1, 0}, | ||
| 206 | { 39, 15, 1, 0}, | ||
| 207 | { 40, 16, 1, 0}, | ||
| 208 | { 41, 17, 1, 0}, | ||
| 209 | { 42, 18, 1, 0}, | ||
| 210 | { 43, 19, 1, 0}, | ||
| 211 | { 44, 20, 1, 0}, | ||
| 212 | { 45, 21, 1, 0}, | ||
| 213 | { 46, 22, 1, 0}, | ||
| 214 | { 47, 23, 1, 0}, | ||
| 215 | { 48, 24, 1, 0}, | ||
| 216 | { 49, 25, 1, 0}, | ||
| 217 | { 50, 26, 1, 0}, | ||
| 218 | { 51, 27, 1, 0}, | ||
| 219 | { 52, 28, 1, 0}, | ||
| 220 | { 53, 29, 1, 0}, | ||
| 221 | { 54, 30, 1, 0}, | ||
| 222 | { 55, 31, 1, 0}, | ||
| 223 | { 56, 32, 1, 0}, | ||
| 224 | { 57, 33, 1, 0}, | ||
| 225 | { 58, 34, 1, 0}, | ||
| 226 | { 59, 35, 1, 0}, | ||
| 227 | { 60, 36, 1, 0}, | ||
| 228 | { 61, 37, 1, 0}, | ||
| 229 | { 62, 38, 1, 0}, | ||
| 230 | { 63, 39, 1, 0}, | ||
| 231 | { 64, 40, 1, 0}, | ||
| 232 | { 65, 41, 1, 0}, | ||
| 233 | { 66, 42, 1, 0}, | ||
| 234 | { 67, 43, 1, 0}, | ||
| 235 | { 68, 44, 1, 0}, | ||
| 236 | { 69, 45, 1, 0}, | ||
| 237 | { 70, 46, 1, 0}, | ||
| 238 | { 71, 47, 1, 0}, | ||
| 239 | { 72, 48, 1, 0}, | ||
| 240 | { 73, 49, 1, 0}, | ||
| 241 | { 74, 50, 1, 0}, | ||
| 242 | { 75, 51, 1, 0}, | ||
| 243 | { 76, 52, 1, 0}, | ||
| 244 | { 77, 53, 1, 0}, | ||
| 245 | { 78, 54, 1, 0}, | ||
| 246 | { 79, 55, 1, 0}, | ||
| 247 | { 80, 56, 1, 0}, | ||
| 248 | { 81, 57, 1, 0}, | ||
| 249 | { 82, 58, 1, 0}, | ||
| 250 | { 83, 40, 1, 1}, | ||
| 251 | { 84, 41, 1, 1}, | ||
| 252 | { 85, 42, 1, 1}, | ||
| 253 | { 86, 43, 1, 1}, | ||
| 254 | { 87, 44, 1, 1}, | ||
| 255 | { 88, 45, 1, 1}, | ||
| 256 | { 89, 46, 1, 1}, | ||
| 257 | { 90, 47, 1, 1}, | ||
| 258 | { 91, 48, 1, 1}, | ||
| 259 | { 92, 49, 1, 1}, | ||
| 260 | { 93, 50, 1, 1}, | ||
| 261 | { 94, 51, 1, 1}, | ||
| 262 | { 95, 52, 1, 1}, | ||
| 263 | { 96, 53, 1, 1}, | ||
| 264 | { 97, 54, 1, 1}, | ||
| 265 | { 98, 55, 1, 1}, | ||
| 266 | { 99, 56, 1, 1}, | ||
| 267 | {100, 57, 1, 1}, | ||
| 268 | {101, 58, 1, 1}, | ||
| 269 | {102, 59, 1, 1}, | ||
| 270 | }; | ||
| 271 | |||
| 272 | /* 420 – 1000 MHz band, lna 7dB, mixer 19dB */ | ||
| 273 | static const struct msi3101_gain msi3101_gain_lut_1000[] = { | ||
| 274 | { 0, 0, 0, 0}, | ||
| 275 | { 1, 1, 0, 0}, | ||
| 276 | { 2, 2, 0, 0}, | ||
| 277 | { 3, 3, 0, 0}, | ||
| 278 | { 4, 4, 0, 0}, | ||
| 279 | { 5, 5, 0, 0}, | ||
| 280 | { 6, 6, 0, 0}, | ||
| 281 | { 7, 7, 0, 0}, | ||
| 282 | { 8, 8, 0, 0}, | ||
| 283 | { 9, 9, 0, 0}, | ||
| 284 | { 10, 10, 0, 0}, | ||
| 285 | { 11, 11, 0, 0}, | ||
| 286 | { 12, 5, 1, 0}, | ||
| 287 | { 13, 6, 1, 0}, | ||
| 288 | { 14, 7, 1, 0}, | ||
| 289 | { 15, 8, 1, 0}, | ||
| 290 | { 16, 9, 1, 0}, | ||
| 291 | { 17, 10, 1, 0}, | ||
| 292 | { 18, 11, 1, 0}, | ||
| 293 | { 19, 12, 1, 0}, | ||
| 294 | { 20, 13, 1, 0}, | ||
| 295 | { 21, 14, 1, 0}, | ||
| 296 | { 22, 15, 1, 0}, | ||
| 297 | { 23, 16, 1, 0}, | ||
| 298 | { 24, 17, 1, 0}, | ||
| 299 | { 25, 18, 1, 0}, | ||
| 300 | { 26, 19, 1, 0}, | ||
| 301 | { 27, 20, 1, 0}, | ||
| 302 | { 28, 21, 1, 0}, | ||
| 303 | { 29, 22, 1, 0}, | ||
| 304 | { 30, 23, 1, 0}, | ||
| 305 | { 31, 24, 1, 0}, | ||
| 306 | { 32, 25, 1, 0}, | ||
| 307 | { 33, 26, 1, 0}, | ||
| 308 | { 34, 27, 1, 0}, | ||
| 309 | { 35, 28, 1, 0}, | ||
| 310 | { 36, 29, 1, 0}, | ||
| 311 | { 37, 30, 1, 0}, | ||
| 312 | { 38, 31, 1, 0}, | ||
| 313 | { 39, 32, 1, 0}, | ||
| 314 | { 40, 33, 1, 0}, | ||
| 315 | { 41, 34, 1, 0}, | ||
| 316 | { 42, 35, 1, 0}, | ||
| 317 | { 43, 36, 1, 0}, | ||
| 318 | { 44, 37, 1, 0}, | ||
| 319 | { 45, 38, 1, 0}, | ||
| 320 | { 46, 39, 1, 0}, | ||
| 321 | { 47, 40, 1, 0}, | ||
| 322 | { 48, 41, 1, 0}, | ||
| 323 | { 49, 42, 1, 0}, | ||
| 324 | { 50, 43, 1, 0}, | ||
| 325 | { 51, 44, 1, 0}, | ||
| 326 | { 52, 45, 1, 0}, | ||
| 327 | { 53, 46, 1, 0}, | ||
| 328 | { 54, 47, 1, 0}, | ||
| 329 | { 55, 48, 1, 0}, | ||
| 330 | { 56, 49, 1, 0}, | ||
| 331 | { 57, 50, 1, 0}, | ||
| 332 | { 58, 51, 1, 0}, | ||
| 333 | { 59, 52, 1, 0}, | ||
| 334 | { 60, 53, 1, 0}, | ||
| 335 | { 61, 54, 1, 0}, | ||
| 336 | { 62, 55, 1, 0}, | ||
| 337 | { 63, 56, 1, 0}, | ||
| 338 | { 64, 57, 1, 0}, | ||
| 339 | { 65, 58, 1, 0}, | ||
| 340 | { 66, 40, 1, 1}, | ||
| 341 | { 67, 41, 1, 1}, | ||
| 342 | { 68, 42, 1, 1}, | ||
| 343 | { 69, 43, 1, 1}, | ||
| 344 | { 70, 44, 1, 1}, | ||
| 345 | { 71, 45, 1, 1}, | ||
| 346 | { 72, 46, 1, 1}, | ||
| 347 | { 73, 47, 1, 1}, | ||
| 348 | { 74, 48, 1, 1}, | ||
| 349 | { 75, 49, 1, 1}, | ||
| 350 | { 76, 50, 1, 1}, | ||
| 351 | { 77, 51, 1, 1}, | ||
| 352 | { 78, 52, 1, 1}, | ||
| 353 | { 79, 53, 1, 1}, | ||
| 354 | { 80, 54, 1, 1}, | ||
| 355 | { 81, 55, 1, 1}, | ||
| 356 | { 82, 56, 1, 1}, | ||
| 357 | { 83, 57, 1, 1}, | ||
| 358 | { 84, 58, 1, 1}, | ||
| 359 | { 85, 59, 1, 1}, | ||
| 360 | }; | ||
| 361 | |||
| 362 | /* | ||
| 363 | * iConfiguration 0 | ||
| 364 | * bInterfaceNumber 0 | ||
| 365 | * bAlternateSetting 1 | ||
| 366 | * bNumEndpoints 1 | ||
| 367 | * bEndpointAddress 0x81 EP 1 IN | ||
| 368 | * bmAttributes 1 | ||
| 369 | * Transfer Type Isochronous | ||
| 370 | * wMaxPacketSize 0x1400 3x 1024 bytes | ||
| 371 | * bInterval 1 | ||
| 372 | */ | ||
| 373 | #define MAX_ISO_BUFS (8) | ||
| 374 | #define ISO_FRAMES_PER_DESC (8) | ||
| 375 | #define ISO_MAX_FRAME_SIZE (3 * 1024) | ||
| 376 | #define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) | ||
| 377 | #define MAX_ISOC_ERRORS 20 | ||
| 378 | |||
| 379 | /* TODO: These should be moved to V4L2 API */ | ||
| 380 | #define MSI3101_CID_SAMPLING_MODE ((V4L2_CID_USER_BASE | 0xf000) + 0) | ||
| 381 | #define MSI3101_CID_SAMPLING_RATE ((V4L2_CID_USER_BASE | 0xf000) + 1) | ||
| 382 | #define MSI3101_CID_SAMPLING_RESOLUTION ((V4L2_CID_USER_BASE | 0xf000) + 2) | ||
| 383 | #define MSI3101_CID_TUNER_RF ((V4L2_CID_USER_BASE | 0xf000) + 10) | ||
| 384 | #define MSI3101_CID_TUNER_BW ((V4L2_CID_USER_BASE | 0xf000) + 11) | ||
| 385 | #define MSI3101_CID_TUNER_IF ((V4L2_CID_USER_BASE | 0xf000) + 12) | ||
| 386 | #define MSI3101_CID_TUNER_GAIN ((V4L2_CID_USER_BASE | 0xf000) + 13) | ||
| 387 | |||
| 388 | /* intermediate buffers with raw data from the USB device */ | ||
| 389 | struct msi3101_frame_buf { | ||
| 390 | struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ | ||
| 391 | struct list_head list; | ||
| 392 | }; | ||
| 393 | |||
| 394 | struct msi3101_state { | ||
| 395 | struct video_device vdev; | ||
| 396 | struct v4l2_device v4l2_dev; | ||
| 397 | |||
| 398 | /* videobuf2 queue and queued buffers list */ | ||
| 399 | struct vb2_queue vb_queue; | ||
| 400 | struct list_head queued_bufs; | ||
| 401 | spinlock_t queued_bufs_lock; /* Protects queued_bufs */ | ||
| 402 | |||
| 403 | /* Note if taking both locks v4l2_lock must always be locked first! */ | ||
| 404 | struct mutex v4l2_lock; /* Protects everything else */ | ||
| 405 | struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ | ||
| 406 | |||
| 407 | /* Pointer to our usb_device, will be NULL after unplug */ | ||
| 408 | struct usb_device *udev; /* Both mutexes most be hold when setting! */ | ||
| 409 | |||
| 410 | unsigned int isoc_errors; /* number of contiguous ISOC errors */ | ||
| 411 | unsigned int vb_full; /* vb is full and packets dropped */ | ||
| 412 | |||
| 413 | struct urb *urbs[MAX_ISO_BUFS]; | ||
| 414 | int (*convert_stream) (struct msi3101_state *s, u32 *dst, u8 *src, | ||
| 415 | unsigned int src_len); | ||
| 416 | |||
| 417 | /* Controls */ | ||
| 418 | struct v4l2_ctrl_handler ctrl_handler; | ||
| 419 | struct v4l2_ctrl *ctrl_sampling_rate; | ||
| 420 | struct v4l2_ctrl *ctrl_tuner_rf; | ||
| 421 | struct v4l2_ctrl *ctrl_tuner_bw; | ||
| 422 | struct v4l2_ctrl *ctrl_tuner_if; | ||
| 423 | struct v4l2_ctrl *ctrl_tuner_gain; | ||
| 424 | |||
| 425 | u32 next_sample; /* for track lost packets */ | ||
| 426 | u32 sample; /* for sample rate calc */ | ||
| 427 | unsigned long jiffies; | ||
| 428 | unsigned int sample_ctrl_bit[4]; | ||
| 429 | }; | ||
| 430 | |||
| 431 | /* Private functions */ | ||
| 432 | static struct msi3101_frame_buf *msi3101_get_next_fill_buf( | ||
| 433 | struct msi3101_state *s) | ||
| 434 | { | ||
| 435 | unsigned long flags = 0; | ||
| 436 | struct msi3101_frame_buf *buf = NULL; | ||
| 437 | |||
| 438 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 439 | if (list_empty(&s->queued_bufs)) | ||
| 440 | goto leave; | ||
| 441 | |||
| 442 | buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, list); | ||
| 443 | list_del(&buf->list); | ||
| 444 | leave: | ||
| 445 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 446 | return buf; | ||
| 447 | } | ||
| 448 | |||
| 449 | /* | ||
| 450 | * +=========================================================================== | ||
| 451 | * | 00-1023 | USB packet type '384' | ||
| 452 | * +=========================================================================== | ||
| 453 | * | 00- 03 | sequence number of first sample in that USB packet | ||
| 454 | * +--------------------------------------------------------------------------- | ||
| 455 | * | 04- 15 | garbage | ||
| 456 | * +--------------------------------------------------------------------------- | ||
| 457 | * | 16- 175 | samples | ||
| 458 | * +--------------------------------------------------------------------------- | ||
| 459 | * | 176- 179 | control bits for previous samples | ||
| 460 | * +--------------------------------------------------------------------------- | ||
| 461 | * | 180- 339 | samples | ||
| 462 | * +--------------------------------------------------------------------------- | ||
| 463 | * | 340- 343 | control bits for previous samples | ||
| 464 | * +--------------------------------------------------------------------------- | ||
| 465 | * | 344- 503 | samples | ||
| 466 | * +--------------------------------------------------------------------------- | ||
| 467 | * | 504- 507 | control bits for previous samples | ||
| 468 | * +--------------------------------------------------------------------------- | ||
| 469 | * | 508- 667 | samples | ||
| 470 | * +--------------------------------------------------------------------------- | ||
| 471 | * | 668- 671 | control bits for previous samples | ||
| 472 | * +--------------------------------------------------------------------------- | ||
| 473 | * | 672- 831 | samples | ||
| 474 | * +--------------------------------------------------------------------------- | ||
| 475 | * | 832- 835 | control bits for previous samples | ||
| 476 | * +--------------------------------------------------------------------------- | ||
| 477 | * | 836- 995 | samples | ||
| 478 | * +--------------------------------------------------------------------------- | ||
| 479 | * | 996- 999 | control bits for previous samples | ||
| 480 | * +--------------------------------------------------------------------------- | ||
| 481 | * | 1000-1023 | garbage | ||
| 482 | * +--------------------------------------------------------------------------- | ||
| 483 | * | ||
| 484 | * Bytes 4 - 7 could have some meaning? | ||
| 485 | * | ||
| 486 | * Control bits for previous samples is 32-bit field, containing 16 x 2-bit | ||
| 487 | * numbers. This results one 2-bit number for 8 samples. It is likely used for | ||
| 488 | * for bit shifting sample by given bits, increasing actual sampling resolution. | ||
| 489 | * Number 2 (0b10) was never seen. | ||
| 490 | * | ||
| 491 | * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes | ||
| 492 | */ | ||
| 493 | |||
| 494 | /* | ||
| 495 | * Integer to 32-bit IEEE floating point representation routine is taken | ||
| 496 | * from Radeon R600 driver (drivers/gpu/drm/radeon/r600_blit_kms.c). | ||
| 497 | * | ||
| 498 | * TODO: Currently we do conversion here in Kernel, but in future that will | ||
| 499 | * be moved to the libv4l2 library as video format conversions are. | ||
| 500 | */ | ||
| 501 | #define I2F_FRAC_BITS 23 | ||
| 502 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) | ||
| 503 | |||
| 504 | /* | ||
| 505 | * Converts signed 8-bit integer into 32-bit IEEE floating point | ||
| 506 | * representation. | ||
| 507 | */ | ||
| 508 | static u32 msi3101_convert_sample_504(struct msi3101_state *s, u16 x) | ||
| 509 | { | ||
| 510 | u32 msb, exponent, fraction, sign; | ||
| 511 | |||
| 512 | /* Zero is special */ | ||
| 513 | if (!x) | ||
| 514 | return 0; | ||
| 515 | |||
| 516 | /* Negative / positive value */ | ||
| 517 | if (x & (1 << 7)) { | ||
| 518 | x = -x; | ||
| 519 | x &= 0x7f; /* result is 7 bit ... + sign */ | ||
| 520 | sign = 1 << 31; | ||
| 521 | } else { | ||
| 522 | sign = 0 << 31; | ||
| 523 | } | ||
| 524 | |||
| 525 | /* Get location of the most significant bit */ | ||
| 526 | msb = __fls(x); | ||
| 527 | |||
| 528 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; | ||
| 529 | exponent = (127 + msb) << I2F_FRAC_BITS; | ||
| 530 | |||
| 531 | return (fraction + exponent) | sign; | ||
| 532 | } | ||
| 533 | |||
| 534 | static int msi3101_convert_stream_504(struct msi3101_state *s, u32 *dst, | ||
| 535 | u8 *src, unsigned int src_len) | ||
| 536 | { | ||
| 537 | int i, j, i_max, dst_len = 0; | ||
| 538 | u16 sample[2]; | ||
| 539 | u32 sample_num[3]; | ||
| 540 | |||
| 541 | /* There could be 1-3 1024 bytes URB frames */ | ||
| 542 | i_max = src_len / 1024; | ||
| 543 | |||
| 544 | for (i = 0; i < i_max; i++) { | ||
| 545 | sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; | ||
| 546 | if (i == 0 && s->next_sample != sample_num[0]) { | ||
| 547 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 548 | "%d samples lost, %d %08x:%08x\n", | ||
| 549 | sample_num[0] - s->next_sample, | ||
| 550 | src_len, s->next_sample, sample_num[0]); | ||
| 551 | } | ||
| 552 | |||
| 553 | /* | ||
| 554 | * Dump all unknown 'garbage' data - maybe we will discover | ||
| 555 | * someday if there is something rational... | ||
| 556 | */ | ||
| 557 | dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); | ||
| 558 | |||
| 559 | src += 16; | ||
| 560 | for (j = 0; j < 1008; j += 2) { | ||
| 561 | sample[0] = src[j + 0]; | ||
| 562 | sample[1] = src[j + 1]; | ||
| 563 | |||
| 564 | *dst++ = msi3101_convert_sample_504(s, sample[0]); | ||
| 565 | *dst++ = msi3101_convert_sample_504(s, sample[1]); | ||
| 566 | } | ||
| 567 | /* 504 x I+Q 32bit float samples */ | ||
| 568 | dst_len += 504 * 2 * 4; | ||
| 569 | src += 1008; | ||
| 570 | } | ||
| 571 | |||
| 572 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
| 573 | if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) { | ||
| 574 | unsigned long jiffies_now = jiffies; | ||
| 575 | unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies); | ||
| 576 | unsigned int samples = sample_num[i_max - 1] - s->sample; | ||
| 577 | s->jiffies = jiffies_now; | ||
| 578 | s->sample = sample_num[i_max - 1]; | ||
| 579 | dev_dbg(&s->udev->dev, | ||
| 580 | "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", | ||
| 581 | src_len, samples, msecs, | ||
| 582 | samples * 1000UL / msecs); | ||
| 583 | } | ||
| 584 | |||
| 585 | /* next sample (sample = sample + i * 504) */ | ||
| 586 | s->next_sample = sample_num[i_max - 1] + 504; | ||
| 587 | |||
| 588 | return dst_len; | ||
| 589 | } | ||
| 590 | |||
| 591 | /* | ||
| 592 | * Converts signed ~10+2-bit integer into 32-bit IEEE floating point | ||
| 593 | * representation. | ||
| 594 | */ | ||
| 595 | static u32 msi3101_convert_sample_384(struct msi3101_state *s, u16 x, int shift) | ||
| 596 | { | ||
| 597 | u32 msb, exponent, fraction, sign; | ||
| 598 | s->sample_ctrl_bit[shift]++; | ||
| 599 | |||
| 600 | /* Zero is special */ | ||
| 601 | if (!x) | ||
| 602 | return 0; | ||
| 603 | |||
| 604 | if (shift == 3) | ||
| 605 | shift = 2; | ||
| 606 | |||
| 607 | /* Convert 10-bit two's complement to 12-bit */ | ||
| 608 | if (x & (1 << 9)) { | ||
| 609 | x |= ~0U << 10; /* set all the rest bits to one */ | ||
| 610 | x <<= shift; | ||
| 611 | x = -x; | ||
| 612 | x &= 0x7ff; /* result is 11 bit ... + sign */ | ||
| 613 | sign = 1 << 31; | ||
| 614 | } else { | ||
| 615 | x <<= shift; | ||
| 616 | sign = 0 << 31; | ||
| 617 | } | ||
| 618 | |||
| 619 | /* Get location of the most significant bit */ | ||
| 620 | msb = __fls(x); | ||
| 621 | |||
| 622 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; | ||
| 623 | exponent = (127 + msb) << I2F_FRAC_BITS; | ||
| 624 | |||
| 625 | return (fraction + exponent) | sign; | ||
| 626 | } | ||
| 627 | |||
| 628 | static int msi3101_convert_stream_384(struct msi3101_state *s, u32 *dst, | ||
| 629 | u8 *src, unsigned int src_len) | ||
| 630 | { | ||
| 631 | int i, j, k, l, i_max, dst_len = 0; | ||
| 632 | u16 sample[4]; | ||
| 633 | u32 bits; | ||
| 634 | u32 sample_num[3]; | ||
| 635 | |||
| 636 | /* There could be 1-3 1024 bytes URB frames */ | ||
| 637 | i_max = src_len / 1024; | ||
| 638 | for (i = 0; i < i_max; i++) { | ||
| 639 | sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; | ||
| 640 | if (i == 0 && s->next_sample != sample_num[0]) { | ||
| 641 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 642 | "%d samples lost, %d %08x:%08x\n", | ||
| 643 | sample_num[0] - s->next_sample, | ||
| 644 | src_len, s->next_sample, sample_num[0]); | ||
| 645 | } | ||
| 646 | |||
| 647 | /* | ||
| 648 | * Dump all unknown 'garbage' data - maybe we will discover | ||
| 649 | * someday if there is something rational... | ||
| 650 | */ | ||
| 651 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 652 | "%*ph %*ph\n", 12, &src[4], 24, &src[1000]); | ||
| 653 | |||
| 654 | src += 16; | ||
| 655 | for (j = 0; j < 6; j++) { | ||
| 656 | bits = src[160 + 3] << 24 | src[160 + 2] << 16 | src[160 + 1] << 8 | src[160 + 0] << 0; | ||
| 657 | for (k = 0; k < 16; k++) { | ||
| 658 | for (l = 0; l < 10; l += 5) { | ||
| 659 | sample[0] = (src[l + 0] & 0xff) >> 0 | (src[l + 1] & 0x03) << 8; | ||
| 660 | sample[1] = (src[l + 1] & 0xfc) >> 2 | (src[l + 2] & 0x0f) << 6; | ||
| 661 | sample[2] = (src[l + 2] & 0xf0) >> 4 | (src[l + 3] & 0x3f) << 4; | ||
| 662 | sample[3] = (src[l + 3] & 0xc0) >> 6 | (src[l + 4] & 0xff) << 2; | ||
| 663 | |||
| 664 | *dst++ = msi3101_convert_sample_384(s, sample[0], (bits >> (2 * k)) & 0x3); | ||
| 665 | *dst++ = msi3101_convert_sample_384(s, sample[1], (bits >> (2 * k)) & 0x3); | ||
| 666 | *dst++ = msi3101_convert_sample_384(s, sample[2], (bits >> (2 * k)) & 0x3); | ||
| 667 | *dst++ = msi3101_convert_sample_384(s, sample[3], (bits >> (2 * k)) & 0x3); | ||
| 668 | } | ||
| 669 | src += 10; | ||
| 670 | } | ||
| 671 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 672 | "sample control bits %08x\n", bits); | ||
| 673 | src += 4; | ||
| 674 | } | ||
| 675 | /* 384 x I+Q 32bit float samples */ | ||
| 676 | dst_len += 384 * 2 * 4; | ||
| 677 | src += 24; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
| 681 | if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) { | ||
| 682 | unsigned long jiffies_now = jiffies; | ||
| 683 | unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies); | ||
| 684 | unsigned int samples = sample_num[i_max - 1] - s->sample; | ||
| 685 | s->jiffies = jiffies_now; | ||
| 686 | s->sample = sample_num[i_max - 1]; | ||
| 687 | dev_dbg(&s->udev->dev, | ||
| 688 | "slen=%d samples=%u msecs=%lu sampling rate=%lu bits=%d.%d.%d.%d\n", | ||
| 689 | src_len, samples, msecs, | ||
| 690 | samples * 1000UL / msecs, | ||
| 691 | s->sample_ctrl_bit[0], s->sample_ctrl_bit[1], | ||
| 692 | s->sample_ctrl_bit[2], s->sample_ctrl_bit[3]); | ||
| 693 | } | ||
| 694 | |||
| 695 | /* next sample (sample = sample + i * 384) */ | ||
| 696 | s->next_sample = sample_num[i_max - 1] + 384; | ||
| 697 | |||
| 698 | return dst_len; | ||
| 699 | } | ||
| 700 | |||
| 701 | /* | ||
| 702 | * Converts signed 12-bit integer into 32-bit IEEE floating point | ||
| 703 | * representation. | ||
| 704 | */ | ||
| 705 | static u32 msi3101_convert_sample_336(struct msi3101_state *s, u16 x) | ||
| 706 | { | ||
| 707 | u32 msb, exponent, fraction, sign; | ||
| 708 | |||
| 709 | /* Zero is special */ | ||
| 710 | if (!x) | ||
| 711 | return 0; | ||
| 712 | |||
| 713 | /* Negative / positive value */ | ||
| 714 | if (x & (1 << 11)) { | ||
| 715 | x = -x; | ||
| 716 | x &= 0x7ff; /* result is 11 bit ... + sign */ | ||
| 717 | sign = 1 << 31; | ||
| 718 | } else { | ||
| 719 | sign = 0 << 31; | ||
| 720 | } | ||
| 721 | |||
| 722 | /* Get location of the most significant bit */ | ||
| 723 | msb = __fls(x); | ||
| 724 | |||
| 725 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; | ||
| 726 | exponent = (127 + msb) << I2F_FRAC_BITS; | ||
| 727 | |||
| 728 | return (fraction + exponent) | sign; | ||
| 729 | } | ||
| 730 | |||
| 731 | static int msi3101_convert_stream_336(struct msi3101_state *s, u32 *dst, | ||
| 732 | u8 *src, unsigned int src_len) | ||
| 733 | { | ||
| 734 | int i, j, i_max, dst_len = 0; | ||
| 735 | u16 sample[2]; | ||
| 736 | u32 sample_num[3]; | ||
| 737 | |||
| 738 | /* There could be 1-3 1024 bytes URB frames */ | ||
| 739 | i_max = src_len / 1024; | ||
| 740 | |||
| 741 | for (i = 0; i < i_max; i++) { | ||
| 742 | sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; | ||
| 743 | if (i == 0 && s->next_sample != sample_num[0]) { | ||
| 744 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 745 | "%d samples lost, %d %08x:%08x\n", | ||
| 746 | sample_num[0] - s->next_sample, | ||
| 747 | src_len, s->next_sample, sample_num[0]); | ||
| 748 | } | ||
| 749 | |||
| 750 | /* | ||
| 751 | * Dump all unknown 'garbage' data - maybe we will discover | ||
| 752 | * someday if there is something rational... | ||
| 753 | */ | ||
| 754 | dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); | ||
| 755 | |||
| 756 | src += 16; | ||
| 757 | for (j = 0; j < 1008; j += 3) { | ||
| 758 | sample[0] = (src[j + 0] & 0xff) >> 0 | (src[j + 1] & 0x0f) << 8; | ||
| 759 | sample[1] = (src[j + 1] & 0xf0) >> 4 | (src[j + 2] & 0xff) << 4; | ||
| 760 | |||
| 761 | *dst++ = msi3101_convert_sample_336(s, sample[0]); | ||
| 762 | *dst++ = msi3101_convert_sample_336(s, sample[1]); | ||
| 763 | } | ||
| 764 | /* 336 x I+Q 32bit float samples */ | ||
| 765 | dst_len += 336 * 2 * 4; | ||
| 766 | src += 1008; | ||
| 767 | } | ||
| 768 | |||
| 769 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
| 770 | if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) { | ||
| 771 | unsigned long jiffies_now = jiffies; | ||
| 772 | unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies); | ||
| 773 | unsigned int samples = sample_num[i_max - 1] - s->sample; | ||
| 774 | s->jiffies = jiffies_now; | ||
| 775 | s->sample = sample_num[i_max - 1]; | ||
| 776 | dev_dbg(&s->udev->dev, | ||
| 777 | "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", | ||
| 778 | src_len, samples, msecs, | ||
| 779 | samples * 1000UL / msecs); | ||
| 780 | } | ||
| 781 | |||
| 782 | /* next sample (sample = sample + i * 336) */ | ||
| 783 | s->next_sample = sample_num[i_max - 1] + 336; | ||
| 784 | |||
| 785 | return dst_len; | ||
| 786 | } | ||
| 787 | |||
| 788 | /* | ||
| 789 | * Converts signed 14-bit integer into 32-bit IEEE floating point | ||
| 790 | * representation. | ||
| 791 | */ | ||
| 792 | static u32 msi3101_convert_sample_252(struct msi3101_state *s, u16 x) | ||
| 793 | { | ||
| 794 | u32 msb, exponent, fraction, sign; | ||
| 795 | |||
| 796 | /* Zero is special */ | ||
| 797 | if (!x) | ||
| 798 | return 0; | ||
| 799 | |||
| 800 | /* Negative / positive value */ | ||
| 801 | if (x & (1 << 13)) { | ||
| 802 | x = -x; | ||
| 803 | x &= 0x1fff; /* result is 13 bit ... + sign */ | ||
| 804 | sign = 1 << 31; | ||
| 805 | } else { | ||
| 806 | sign = 0 << 31; | ||
| 807 | } | ||
| 808 | |||
| 809 | /* Get location of the most significant bit */ | ||
| 810 | msb = __fls(x); | ||
| 811 | |||
| 812 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; | ||
| 813 | exponent = (127 + msb) << I2F_FRAC_BITS; | ||
| 814 | |||
| 815 | return (fraction + exponent) | sign; | ||
| 816 | } | ||
| 817 | |||
| 818 | static int msi3101_convert_stream_252(struct msi3101_state *s, u32 *dst, | ||
| 819 | u8 *src, unsigned int src_len) | ||
| 820 | { | ||
| 821 | int i, j, i_max, dst_len = 0; | ||
| 822 | u16 sample[2]; | ||
| 823 | u32 sample_num[3]; | ||
| 824 | |||
| 825 | /* There could be 1-3 1024 bytes URB frames */ | ||
| 826 | i_max = src_len / 1024; | ||
| 827 | |||
| 828 | for (i = 0; i < i_max; i++) { | ||
| 829 | sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0; | ||
| 830 | if (i == 0 && s->next_sample != sample_num[0]) { | ||
| 831 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 832 | "%d samples lost, %d %08x:%08x\n", | ||
| 833 | sample_num[0] - s->next_sample, | ||
| 834 | src_len, s->next_sample, sample_num[0]); | ||
| 835 | } | ||
| 836 | |||
| 837 | /* | ||
| 838 | * Dump all unknown 'garbage' data - maybe we will discover | ||
| 839 | * someday if there is something rational... | ||
| 840 | */ | ||
| 841 | dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); | ||
| 842 | |||
| 843 | src += 16; | ||
| 844 | for (j = 0; j < 1008; j += 4) { | ||
| 845 | sample[0] = src[j + 0] >> 0 | src[j + 1] << 8; | ||
| 846 | sample[1] = src[j + 2] >> 0 | src[j + 3] << 8; | ||
| 847 | |||
| 848 | *dst++ = msi3101_convert_sample_252(s, sample[0]); | ||
| 849 | *dst++ = msi3101_convert_sample_252(s, sample[1]); | ||
| 850 | } | ||
| 851 | /* 252 x I+Q 32bit float samples */ | ||
| 852 | dst_len += 252 * 2 * 4; | ||
| 853 | src += 1008; | ||
| 854 | } | ||
| 855 | |||
| 856 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
| 857 | if ((s->jiffies + msecs_to_jiffies(10000)) <= jiffies) { | ||
| 858 | unsigned long jiffies_now = jiffies; | ||
| 859 | unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies); | ||
| 860 | unsigned int samples = sample_num[i_max - 1] - s->sample; | ||
| 861 | s->jiffies = jiffies_now; | ||
| 862 | s->sample = sample_num[i_max - 1]; | ||
| 863 | dev_dbg(&s->udev->dev, | ||
| 864 | "slen=%d samples=%u msecs=%lu sampling rate=%lu\n", | ||
| 865 | src_len, samples, msecs, | ||
| 866 | samples * 1000UL / msecs); | ||
| 867 | } | ||
| 868 | |||
| 869 | /* next sample (sample = sample + i * 252) */ | ||
| 870 | s->next_sample = sample_num[i_max - 1] + 252; | ||
| 871 | |||
| 872 | return dst_len; | ||
| 873 | } | ||
| 874 | |||
| 875 | /* | ||
| 876 | * This gets called for the Isochronous pipe (stream). This is done in interrupt | ||
| 877 | * time, so it has to be fast, not crash, and not stall. Neat. | ||
| 878 | */ | ||
| 879 | static void msi3101_isoc_handler(struct urb *urb) | ||
| 880 | { | ||
| 881 | struct msi3101_state *s = (struct msi3101_state *)urb->context; | ||
| 882 | int i, flen, fstatus; | ||
| 883 | unsigned char *iso_buf = NULL; | ||
| 884 | struct msi3101_frame_buf *fbuf; | ||
| 885 | |||
| 886 | if (urb->status == -ENOENT || urb->status == -ECONNRESET || | ||
| 887 | urb->status == -ESHUTDOWN) { | ||
| 888 | dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n", | ||
| 889 | urb, urb->status == -ENOENT ? "" : "a"); | ||
| 890 | return; | ||
| 891 | } | ||
| 892 | |||
| 893 | if (urb->status != 0) { | ||
| 894 | dev_dbg(&s->udev->dev, | ||
| 895 | "msi3101_isoc_handler() called with status %d\n", | ||
| 896 | urb->status); | ||
| 897 | /* Give up after a number of contiguous errors */ | ||
| 898 | if (++s->isoc_errors > MAX_ISOC_ERRORS) | ||
| 899 | dev_dbg(&s->udev->dev, | ||
| 900 | "Too many ISOC errors, bailing out\n"); | ||
| 901 | goto handler_end; | ||
| 902 | } else { | ||
| 903 | /* Reset ISOC error counter. We did get here, after all. */ | ||
| 904 | s->isoc_errors = 0; | ||
| 905 | } | ||
| 906 | |||
| 907 | /* Compact data */ | ||
| 908 | for (i = 0; i < urb->number_of_packets; i++) { | ||
| 909 | void *ptr; | ||
| 910 | |||
| 911 | /* Check frame error */ | ||
| 912 | fstatus = urb->iso_frame_desc[i].status; | ||
| 913 | if (fstatus) { | ||
| 914 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 915 | "frame=%d/%d has error %d skipping\n", | ||
| 916 | i, urb->number_of_packets, fstatus); | ||
| 917 | goto skip; | ||
| 918 | } | ||
| 919 | |||
| 920 | /* Check if that frame contains data */ | ||
| 921 | flen = urb->iso_frame_desc[i].actual_length; | ||
| 922 | if (flen == 0) | ||
| 923 | goto skip; | ||
| 924 | |||
| 925 | iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
| 926 | |||
| 927 | /* Get free framebuffer */ | ||
| 928 | fbuf = msi3101_get_next_fill_buf(s); | ||
| 929 | if (fbuf == NULL) { | ||
| 930 | s->vb_full++; | ||
| 931 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 932 | "videobuf is full, %d packets dropped\n", | ||
| 933 | s->vb_full); | ||
| 934 | goto skip; | ||
| 935 | } | ||
| 936 | |||
| 937 | /* fill framebuffer */ | ||
| 938 | ptr = vb2_plane_vaddr(&fbuf->vb, 0); | ||
| 939 | flen = s->convert_stream(s, ptr, iso_buf, flen); | ||
| 940 | vb2_set_plane_payload(&fbuf->vb, 0, flen); | ||
| 941 | vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); | ||
| 942 | skip: | ||
| 943 | ; | ||
| 944 | } | ||
| 945 | |||
| 946 | handler_end: | ||
| 947 | i = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 948 | if (i != 0) | ||
| 949 | dev_dbg(&s->udev->dev, | ||
| 950 | "Error (%d) re-submitting urb in msi3101_isoc_handler\n", | ||
| 951 | i); | ||
| 952 | } | ||
| 953 | |||
| 954 | static void msi3101_iso_stop(struct msi3101_state *s) | ||
| 955 | { | ||
| 956 | int i; | ||
| 957 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 958 | |||
| 959 | /* Unlinking ISOC buffers one by one */ | ||
| 960 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 961 | if (s->urbs[i]) { | ||
| 962 | dev_dbg(&s->udev->dev, "Unlinking URB %p\n", | ||
| 963 | s->urbs[i]); | ||
| 964 | usb_kill_urb(s->urbs[i]); | ||
| 965 | } | ||
| 966 | } | ||
| 967 | } | ||
| 968 | |||
| 969 | static void msi3101_iso_free(struct msi3101_state *s) | ||
| 970 | { | ||
| 971 | int i; | ||
| 972 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 973 | |||
| 974 | /* Freeing ISOC buffers one by one */ | ||
| 975 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 976 | if (s->urbs[i]) { | ||
| 977 | dev_dbg(&s->udev->dev, "Freeing URB\n"); | ||
| 978 | if (s->urbs[i]->transfer_buffer) { | ||
| 979 | usb_free_coherent(s->udev, | ||
| 980 | s->urbs[i]->transfer_buffer_length, | ||
| 981 | s->urbs[i]->transfer_buffer, | ||
| 982 | s->urbs[i]->transfer_dma); | ||
| 983 | } | ||
| 984 | usb_free_urb(s->urbs[i]); | ||
| 985 | s->urbs[i] = NULL; | ||
| 986 | } | ||
| 987 | } | ||
| 988 | } | ||
| 989 | |||
| 990 | /* Both v4l2_lock and vb_queue_lock should be locked when calling this */ | ||
| 991 | static void msi3101_isoc_cleanup(struct msi3101_state *s) | ||
| 992 | { | ||
| 993 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 994 | |||
| 995 | msi3101_iso_stop(s); | ||
| 996 | msi3101_iso_free(s); | ||
| 997 | } | ||
| 998 | |||
| 999 | /* Both v4l2_lock and vb_queue_lock should be locked when calling this */ | ||
| 1000 | static int msi3101_isoc_init(struct msi3101_state *s) | ||
| 1001 | { | ||
| 1002 | struct usb_device *udev; | ||
| 1003 | struct urb *urb; | ||
| 1004 | int i, j, ret; | ||
| 1005 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1006 | |||
| 1007 | s->isoc_errors = 0; | ||
| 1008 | udev = s->udev; | ||
| 1009 | |||
| 1010 | ret = usb_set_interface(s->udev, 0, 1); | ||
| 1011 | if (ret < 0) | ||
| 1012 | return ret; | ||
| 1013 | |||
| 1014 | /* Allocate and init Isochronuous urbs */ | ||
| 1015 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 1016 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); | ||
| 1017 | if (urb == NULL) { | ||
| 1018 | dev_err(&s->udev->dev, | ||
| 1019 | "Failed to allocate urb %d\n", i); | ||
| 1020 | msi3101_isoc_cleanup(s); | ||
| 1021 | return -ENOMEM; | ||
| 1022 | } | ||
| 1023 | s->urbs[i] = urb; | ||
| 1024 | dev_dbg(&s->udev->dev, "Allocated URB at 0x%p\n", urb); | ||
| 1025 | |||
| 1026 | urb->interval = 1; | ||
| 1027 | urb->dev = udev; | ||
| 1028 | urb->pipe = usb_rcvisocpipe(udev, 0x81); | ||
| 1029 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 1030 | urb->transfer_buffer = usb_alloc_coherent(udev, ISO_BUFFER_SIZE, | ||
| 1031 | GFP_KERNEL, &urb->transfer_dma); | ||
| 1032 | if (urb->transfer_buffer == NULL) { | ||
| 1033 | dev_err(&s->udev->dev, | ||
| 1034 | "Failed to allocate urb buffer %d\n", | ||
| 1035 | i); | ||
| 1036 | msi3101_isoc_cleanup(s); | ||
| 1037 | return -ENOMEM; | ||
| 1038 | } | ||
| 1039 | urb->transfer_buffer_length = ISO_BUFFER_SIZE; | ||
| 1040 | urb->complete = msi3101_isoc_handler; | ||
| 1041 | urb->context = s; | ||
| 1042 | urb->start_frame = 0; | ||
| 1043 | urb->number_of_packets = ISO_FRAMES_PER_DESC; | ||
| 1044 | for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { | ||
| 1045 | urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; | ||
| 1046 | urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; | ||
| 1047 | } | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | /* link */ | ||
| 1051 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 1052 | ret = usb_submit_urb(s->urbs[i], GFP_KERNEL); | ||
| 1053 | if (ret) { | ||
| 1054 | dev_err(&s->udev->dev, | ||
| 1055 | "isoc_init() submit_urb %d failed with error %d\n", | ||
| 1056 | i, ret); | ||
| 1057 | msi3101_isoc_cleanup(s); | ||
| 1058 | return ret; | ||
| 1059 | } | ||
| 1060 | dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | /* All is done... */ | ||
| 1064 | return 0; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | /* Must be called with vb_queue_lock hold */ | ||
| 1068 | static void msi3101_cleanup_queued_bufs(struct msi3101_state *s) | ||
| 1069 | { | ||
| 1070 | unsigned long flags = 0; | ||
| 1071 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1072 | |||
| 1073 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 1074 | while (!list_empty(&s->queued_bufs)) { | ||
| 1075 | struct msi3101_frame_buf *buf; | ||
| 1076 | |||
| 1077 | buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, | ||
| 1078 | list); | ||
| 1079 | list_del(&buf->list); | ||
| 1080 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 1081 | } | ||
| 1082 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | /* The user yanked out the cable... */ | ||
| 1086 | static void msi3101_disconnect(struct usb_interface *intf) | ||
| 1087 | { | ||
| 1088 | struct v4l2_device *v = usb_get_intfdata(intf); | ||
| 1089 | struct msi3101_state *s = | ||
| 1090 | container_of(v, struct msi3101_state, v4l2_dev); | ||
| 1091 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1092 | |||
| 1093 | mutex_lock(&s->vb_queue_lock); | ||
| 1094 | mutex_lock(&s->v4l2_lock); | ||
| 1095 | /* No need to keep the urbs around after disconnection */ | ||
| 1096 | s->udev = NULL; | ||
| 1097 | |||
| 1098 | v4l2_device_disconnect(&s->v4l2_dev); | ||
| 1099 | video_unregister_device(&s->vdev); | ||
| 1100 | mutex_unlock(&s->v4l2_lock); | ||
| 1101 | mutex_unlock(&s->vb_queue_lock); | ||
| 1102 | |||
| 1103 | v4l2_device_put(&s->v4l2_dev); | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | static int msi3101_querycap(struct file *file, void *fh, | ||
| 1107 | struct v4l2_capability *cap) | ||
| 1108 | { | ||
| 1109 | struct msi3101_state *s = video_drvdata(file); | ||
| 1110 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1111 | |||
| 1112 | strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | ||
| 1113 | strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); | ||
| 1114 | usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
| 1115 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | | ||
| 1116 | V4L2_CAP_READWRITE; | ||
| 1117 | cap->device_caps = V4L2_CAP_TUNER; | ||
| 1118 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
| 1119 | return 0; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | |||
| 1123 | /* Videobuf2 operations */ | ||
| 1124 | static int msi3101_queue_setup(struct vb2_queue *vq, | ||
| 1125 | const struct v4l2_format *fmt, unsigned int *nbuffers, | ||
| 1126 | unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) | ||
| 1127 | { | ||
| 1128 | struct msi3101_state *s = vb2_get_drv_priv(vq); | ||
| 1129 | dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); | ||
| 1130 | |||
| 1131 | /* Absolute min and max number of buffers available for mmap() */ | ||
| 1132 | *nbuffers = 32; | ||
| 1133 | *nplanes = 1; | ||
| 1134 | sizes[0] = PAGE_ALIGN(3 * 3072); /* 3 * 768 * 4 */ | ||
| 1135 | dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", | ||
| 1136 | __func__, *nbuffers, sizes[0]); | ||
| 1137 | return 0; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | static int msi3101_buf_prepare(struct vb2_buffer *vb) | ||
| 1141 | { | ||
| 1142 | struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue); | ||
| 1143 | |||
| 1144 | /* Don't allow queing new buffers after device disconnection */ | ||
| 1145 | if (!s->udev) | ||
| 1146 | return -ENODEV; | ||
| 1147 | |||
| 1148 | return 0; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | static void msi3101_buf_queue(struct vb2_buffer *vb) | ||
| 1152 | { | ||
| 1153 | struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue); | ||
| 1154 | struct msi3101_frame_buf *buf = | ||
| 1155 | container_of(vb, struct msi3101_frame_buf, vb); | ||
| 1156 | unsigned long flags = 0; | ||
| 1157 | |||
| 1158 | /* Check the device has not disconnected between prep and queuing */ | ||
| 1159 | if (!s->udev) { | ||
| 1160 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 1161 | return; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 1165 | list_add_tail(&buf->list, &s->queued_bufs); | ||
| 1166 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | #define CMD_WREG 0x41 | ||
| 1170 | #define CMD_START_STREAMING 0x43 | ||
| 1171 | #define CMD_STOP_STREAMING 0x45 | ||
| 1172 | #define CMD_READ_UNKNOW 0x48 | ||
| 1173 | |||
| 1174 | #define msi3101_dbg_usb_control_msg(udev, r, t, v, _i, b, l) { \ | ||
| 1175 | char *direction; \ | ||
| 1176 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
| 1177 | direction = ">>>"; \ | ||
| 1178 | else \ | ||
| 1179 | direction = "<<<"; \ | ||
| 1180 | dev_dbg(&udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ | ||
| 1181 | "%s %*ph\n", __func__, t, r, v & 0xff, v >> 8, \ | ||
| 1182 | _i & 0xff, _i >> 8, l & 0xff, l >> 8, direction, l, b); \ | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data) | ||
| 1186 | { | ||
| 1187 | int ret; | ||
| 1188 | u8 request = cmd; | ||
| 1189 | u8 requesttype = USB_DIR_OUT | USB_TYPE_VENDOR; | ||
| 1190 | u16 value = (data >> 0) & 0xffff; | ||
| 1191 | u16 index = (data >> 16) & 0xffff; | ||
| 1192 | |||
| 1193 | msi3101_dbg_usb_control_msg(s->udev, | ||
| 1194 | request, requesttype, value, index, NULL, 0); | ||
| 1195 | |||
| 1196 | ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0), | ||
| 1197 | request, requesttype, value, index, NULL, 0, 2000); | ||
| 1198 | |||
| 1199 | if (ret) | ||
| 1200 | dev_err(&s->udev->dev, "%s: failed %d, cmd %02x, data %04x\n", | ||
| 1201 | __func__, ret, cmd, data); | ||
| 1202 | |||
| 1203 | return ret; | ||
| 1204 | }; | ||
| 1205 | |||
| 1206 | static int msi3101_tuner_write(struct msi3101_state *s, u32 data) | ||
| 1207 | { | ||
| 1208 | return msi3101_ctrl_msg(s, CMD_WREG, data << 8 | 0x09); | ||
| 1209 | }; | ||
| 1210 | |||
| 1211 | #define F_REF 24000000 | ||
| 1212 | #define DIV_R_IN 2 | ||
| 1213 | static int msi3101_set_usb_adc(struct msi3101_state *s) | ||
| 1214 | { | ||
| 1215 | int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract; | ||
| 1216 | u32 reg3, reg4, reg7; | ||
| 1217 | |||
| 1218 | f_sr = s->ctrl_sampling_rate->val64; | ||
| 1219 | |||
| 1220 | /* select stream format */ | ||
| 1221 | if (f_sr < 6000000) { | ||
| 1222 | s->convert_stream = msi3101_convert_stream_252; | ||
| 1223 | reg7 = 0x00009407; | ||
| 1224 | } else if (f_sr < 8000000) { | ||
| 1225 | s->convert_stream = msi3101_convert_stream_336; | ||
| 1226 | reg7 = 0x00008507; | ||
| 1227 | } else if (f_sr < 9000000) { | ||
| 1228 | s->convert_stream = msi3101_convert_stream_384; | ||
| 1229 | reg7 = 0x0000a507; | ||
| 1230 | } else { | ||
| 1231 | s->convert_stream = msi3101_convert_stream_504; | ||
| 1232 | reg7 = 0x000c9407; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | /* | ||
| 1236 | * Synthesizer config is just a educated guess... | ||
| 1237 | * | ||
| 1238 | * [7:0] 0x03, register address | ||
| 1239 | * [8] 1, always | ||
| 1240 | * [9] ? | ||
| 1241 | * [12:10] output divider | ||
| 1242 | * [13] 0 ? | ||
| 1243 | * [14] 0 ? | ||
| 1244 | * [15] fractional MSB, bit 20 | ||
| 1245 | * [16:19] N | ||
| 1246 | * [23:20] ? | ||
| 1247 | * [24:31] 0x01 | ||
| 1248 | * | ||
| 1249 | * output divider | ||
| 1250 | * val div | ||
| 1251 | * 0 - (invalid) | ||
| 1252 | * 1 4 | ||
| 1253 | * 2 6 | ||
| 1254 | * 3 8 | ||
| 1255 | * 4 10 | ||
| 1256 | * 5 12 | ||
| 1257 | * 6 14 | ||
| 1258 | * 7 16 | ||
| 1259 | * | ||
| 1260 | * VCO 202000000 - 720000000++ | ||
| 1261 | */ | ||
| 1262 | reg3 = 0x01000303; | ||
| 1263 | reg4 = 0x00000004; | ||
| 1264 | |||
| 1265 | /* XXX: Filters? AGC? */ | ||
| 1266 | if (f_sr < 6000000) | ||
| 1267 | reg3 |= 0x1 << 20; | ||
| 1268 | else if (f_sr < 7000000) | ||
| 1269 | reg3 |= 0x5 << 20; | ||
| 1270 | else if (f_sr < 8500000) | ||
| 1271 | reg3 |= 0x9 << 20; | ||
| 1272 | else | ||
| 1273 | reg3 |= 0xd << 20; | ||
| 1274 | |||
| 1275 | for (div_r_out = 4; div_r_out < 16; div_r_out += 2) { | ||
| 1276 | f_vco = f_sr * div_r_out * 12; | ||
| 1277 | dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n", | ||
| 1278 | __func__, div_r_out, f_vco); | ||
| 1279 | if (f_vco >= 202000000) | ||
| 1280 | break; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | div_n = f_vco / (F_REF * DIV_R_IN); | ||
| 1284 | div_m = f_vco % (F_REF * DIV_R_IN); | ||
| 1285 | fract = 0x200000ul * div_m / (F_REF * DIV_R_IN); | ||
| 1286 | |||
| 1287 | reg3 |= div_n << 16; | ||
| 1288 | reg3 |= (div_r_out / 2 - 1) << 10; | ||
| 1289 | reg3 |= ((fract >> 20) & 0x000001) << 15; /* [20] */ | ||
| 1290 | reg4 |= ((fract >> 0) & 0x0fffff) << 8; /* [19:0] */ | ||
| 1291 | |||
| 1292 | dev_dbg(&s->udev->dev, | ||
| 1293 | "%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n", | ||
| 1294 | __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3, reg4); | ||
| 1295 | |||
| 1296 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008); | ||
| 1297 | if (ret) | ||
| 1298 | goto err; | ||
| 1299 | |||
| 1300 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00000c05); | ||
| 1301 | if (ret) | ||
| 1302 | goto err; | ||
| 1303 | |||
| 1304 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00020000); | ||
| 1305 | if (ret) | ||
| 1306 | goto err; | ||
| 1307 | |||
| 1308 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00480102); | ||
| 1309 | if (ret) | ||
| 1310 | goto err; | ||
| 1311 | |||
| 1312 | ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00f38008); | ||
| 1313 | if (ret) | ||
| 1314 | goto err; | ||
| 1315 | |||
| 1316 | ret = msi3101_ctrl_msg(s, CMD_WREG, reg7); | ||
| 1317 | if (ret) | ||
| 1318 | goto err; | ||
| 1319 | |||
| 1320 | ret = msi3101_ctrl_msg(s, CMD_WREG, reg4); | ||
| 1321 | if (ret) | ||
| 1322 | goto err; | ||
| 1323 | |||
| 1324 | ret = msi3101_ctrl_msg(s, CMD_WREG, reg3); | ||
| 1325 | if (ret) | ||
| 1326 | goto err; | ||
| 1327 | err: | ||
| 1328 | return ret; | ||
| 1329 | }; | ||
| 1330 | |||
| 1331 | static int msi3101_set_tuner(struct msi3101_state *s) | ||
| 1332 | { | ||
| 1333 | int ret, i, len; | ||
| 1334 | unsigned int n, m, thresh, frac, vco_step, tmp, f_if1; | ||
| 1335 | u32 reg; | ||
| 1336 | u64 f_vco, tmp64; | ||
| 1337 | u8 mode, filter_mode, lo_div; | ||
| 1338 | const struct msi3101_gain *gain_lut; | ||
| 1339 | static const struct { | ||
| 1340 | u32 rf; | ||
| 1341 | u8 mode; | ||
| 1342 | u8 lo_div; | ||
| 1343 | } band_lut[] = { | ||
| 1344 | { 50000000, 0xe1, 16}, /* AM_MODE2, antenna 2 */ | ||
| 1345 | {108000000, 0x42, 32}, /* VHF_MODE */ | ||
| 1346 | {330000000, 0x44, 16}, /* B3_MODE */ | ||
| 1347 | {960000000, 0x48, 4}, /* B45_MODE */ | ||
| 1348 | { ~0U, 0x50, 2}, /* BL_MODE */ | ||
| 1349 | }; | ||
| 1350 | static const struct { | ||
| 1351 | u32 freq; | ||
| 1352 | u8 filter_mode; | ||
| 1353 | } if_freq_lut[] = { | ||
| 1354 | { 0, 0x03}, /* Zero IF */ | ||
| 1355 | { 450000, 0x02}, /* 450 kHz IF */ | ||
| 1356 | {1620000, 0x01}, /* 1.62 MHz IF */ | ||
| 1357 | {2048000, 0x00}, /* 2.048 MHz IF */ | ||
| 1358 | }; | ||
| 1359 | static const struct { | ||
| 1360 | u32 freq; | ||
| 1361 | u8 val; | ||
| 1362 | } bandwidth_lut[] = { | ||
| 1363 | { 200000, 0x00}, /* 200 kHz */ | ||
| 1364 | { 300000, 0x01}, /* 300 kHz */ | ||
| 1365 | { 600000, 0x02}, /* 600 kHz */ | ||
| 1366 | {1536000, 0x03}, /* 1.536 MHz */ | ||
| 1367 | {5000000, 0x04}, /* 5 MHz */ | ||
| 1368 | {6000000, 0x05}, /* 6 MHz */ | ||
| 1369 | {7000000, 0x06}, /* 7 MHz */ | ||
| 1370 | {8000000, 0x07}, /* 8 MHz */ | ||
| 1371 | }; | ||
| 1372 | |||
| 1373 | unsigned int f_rf = s->ctrl_tuner_rf->val64; | ||
| 1374 | |||
| 1375 | /* | ||
| 1376 | * bandwidth (Hz) | ||
| 1377 | * 200000, 300000, 600000, 1536000, 5000000, 6000000, 7000000, 8000000 | ||
| 1378 | */ | ||
| 1379 | unsigned int bandwidth = s->ctrl_tuner_bw->val; | ||
| 1380 | |||
| 1381 | /* | ||
| 1382 | * intermediate frequency (Hz) | ||
| 1383 | * 0, 450000, 1620000, 2048000 | ||
| 1384 | */ | ||
| 1385 | unsigned int f_if = s->ctrl_tuner_if->val; | ||
| 1386 | |||
| 1387 | /* | ||
| 1388 | * gain reduction (dB) | ||
| 1389 | * 0 - 102 below 420 MHz | ||
| 1390 | * 0 - 85 above 420 MHz | ||
| 1391 | */ | ||
| 1392 | int gain = s->ctrl_tuner_gain->val; | ||
| 1393 | |||
| 1394 | dev_dbg(&s->udev->dev, | ||
| 1395 | "%s: f_rf=%d bandwidth=%d f_if=%d gain=%d\n", | ||
| 1396 | __func__, f_rf, bandwidth, f_if, gain); | ||
| 1397 | |||
| 1398 | ret = -EINVAL; | ||
| 1399 | |||
| 1400 | for (i = 0; i < ARRAY_SIZE(band_lut); i++) { | ||
| 1401 | if (f_rf <= band_lut[i].rf) { | ||
| 1402 | mode = band_lut[i].mode; | ||
| 1403 | lo_div = band_lut[i].lo_div; | ||
| 1404 | break; | ||
| 1405 | } | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | if (i == ARRAY_SIZE(band_lut)) | ||
| 1409 | goto err; | ||
| 1410 | |||
| 1411 | /* AM_MODE is upconverted */ | ||
| 1412 | if ((mode >> 0) & 0x1) | ||
| 1413 | f_if1 = 5 * F_REF; | ||
| 1414 | else | ||
| 1415 | f_if1 = 0; | ||
| 1416 | |||
| 1417 | for (i = 0; i < ARRAY_SIZE(if_freq_lut); i++) { | ||
| 1418 | if (f_if == if_freq_lut[i].freq) { | ||
| 1419 | filter_mode = if_freq_lut[i].filter_mode; | ||
| 1420 | break; | ||
| 1421 | } | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | if (i == ARRAY_SIZE(if_freq_lut)) | ||
| 1425 | goto err; | ||
| 1426 | |||
| 1427 | for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) { | ||
| 1428 | if (bandwidth == bandwidth_lut[i].freq) { | ||
| 1429 | bandwidth = bandwidth_lut[i].val; | ||
| 1430 | break; | ||
| 1431 | } | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | if (i == ARRAY_SIZE(bandwidth_lut)) | ||
| 1435 | goto err; | ||
| 1436 | |||
| 1437 | #define F_OUT_STEP 1 | ||
| 1438 | #define R_REF 4 | ||
| 1439 | f_vco = (f_rf + f_if + f_if1) * lo_div; | ||
| 1440 | |||
| 1441 | tmp64 = f_vco; | ||
| 1442 | m = do_div(tmp64, F_REF * R_REF); | ||
| 1443 | n = (unsigned int) tmp64; | ||
| 1444 | |||
| 1445 | vco_step = F_OUT_STEP * lo_div; | ||
| 1446 | thresh = (F_REF * R_REF) / vco_step; | ||
| 1447 | frac = 1ul * thresh * m / (F_REF * R_REF); | ||
| 1448 | |||
| 1449 | /* Find out greatest common divisor and divide to smaller. */ | ||
| 1450 | tmp = gcd(thresh, frac); | ||
| 1451 | thresh /= tmp; | ||
| 1452 | frac /= tmp; | ||
| 1453 | |||
| 1454 | /* Force divide to reg max. Resolution will be reduced. */ | ||
| 1455 | tmp = DIV_ROUND_UP(thresh, 4095); | ||
| 1456 | thresh = DIV_ROUND_CLOSEST(thresh, tmp); | ||
| 1457 | frac = DIV_ROUND_CLOSEST(frac, tmp); | ||
| 1458 | |||
| 1459 | /* calc real RF set */ | ||
| 1460 | tmp = 1ul * F_REF * R_REF * n; | ||
| 1461 | tmp += 1ul * F_REF * R_REF * frac / thresh; | ||
| 1462 | tmp /= lo_div; | ||
| 1463 | |||
| 1464 | dev_dbg(&s->udev->dev, | ||
| 1465 | "%s: rf=%u:%u n=%d thresh=%d frac=%d\n", | ||
| 1466 | __func__, f_rf, tmp, n, thresh, frac); | ||
| 1467 | |||
| 1468 | ret = msi3101_tuner_write(s, 0x00000e); | ||
| 1469 | if (ret) | ||
| 1470 | goto err; | ||
| 1471 | |||
| 1472 | ret = msi3101_tuner_write(s, 0x000003); | ||
| 1473 | if (ret) | ||
| 1474 | goto err; | ||
| 1475 | |||
| 1476 | reg = 0 << 0; | ||
| 1477 | reg |= mode << 4; | ||
| 1478 | reg |= filter_mode << 12; | ||
| 1479 | reg |= bandwidth << 14; | ||
| 1480 | reg |= 0x02 << 17; | ||
| 1481 | reg |= 0x00 << 20; | ||
| 1482 | ret = msi3101_tuner_write(s, reg); | ||
| 1483 | if (ret) | ||
| 1484 | goto err; | ||
| 1485 | |||
| 1486 | reg = 5 << 0; | ||
| 1487 | reg |= thresh << 4; | ||
| 1488 | reg |= 1 << 19; | ||
| 1489 | reg |= 1 << 21; | ||
| 1490 | ret = msi3101_tuner_write(s, reg); | ||
| 1491 | if (ret) | ||
| 1492 | goto err; | ||
| 1493 | |||
| 1494 | reg = 2 << 0; | ||
| 1495 | reg |= frac << 4; | ||
| 1496 | reg |= n << 16; | ||
| 1497 | ret = msi3101_tuner_write(s, reg); | ||
| 1498 | if (ret) | ||
| 1499 | goto err; | ||
| 1500 | |||
| 1501 | if (f_rf < 120000000) { | ||
| 1502 | gain_lut = msi3101_gain_lut_120; | ||
| 1503 | len = ARRAY_SIZE(msi3101_gain_lut_120); | ||
| 1504 | } else if (f_rf < 245000000) { | ||
| 1505 | gain_lut = msi3101_gain_lut_245; | ||
| 1506 | len = ARRAY_SIZE(msi3101_gain_lut_120); | ||
| 1507 | } else { | ||
| 1508 | gain_lut = msi3101_gain_lut_1000; | ||
| 1509 | len = ARRAY_SIZE(msi3101_gain_lut_1000); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | for (i = 0; i < len; i++) { | ||
| 1513 | if (gain_lut[i].tot >= gain) | ||
| 1514 | break; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | if (i == len) | ||
| 1518 | goto err; | ||
| 1519 | |||
| 1520 | dev_dbg(&s->udev->dev, | ||
| 1521 | "%s: gain tot=%d baseband=%d lna=%d mixer=%d\n", | ||
| 1522 | __func__, gain_lut[i].tot, gain_lut[i].baseband, | ||
| 1523 | gain_lut[i].lna, gain_lut[i].mixer); | ||
| 1524 | |||
| 1525 | reg = 1 << 0; | ||
| 1526 | reg |= gain_lut[i].baseband << 4; | ||
| 1527 | reg |= 0 << 10; | ||
| 1528 | reg |= gain_lut[i].mixer << 12; | ||
| 1529 | reg |= gain_lut[i].lna << 13; | ||
| 1530 | reg |= 4 << 14; | ||
| 1531 | reg |= 0 << 17; | ||
| 1532 | ret = msi3101_tuner_write(s, reg); | ||
| 1533 | if (ret) | ||
| 1534 | goto err; | ||
| 1535 | |||
| 1536 | reg = 6 << 0; | ||
| 1537 | reg |= 63 << 4; | ||
| 1538 | reg |= 4095 << 10; | ||
| 1539 | ret = msi3101_tuner_write(s, reg); | ||
| 1540 | if (ret) | ||
| 1541 | goto err; | ||
| 1542 | |||
| 1543 | return 0; | ||
| 1544 | err: | ||
| 1545 | dev_dbg(&s->udev->dev, "%s: failed %d\n", __func__, ret); | ||
| 1546 | return ret; | ||
| 1547 | }; | ||
| 1548 | |||
| 1549 | static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
| 1550 | { | ||
| 1551 | struct msi3101_state *s = vb2_get_drv_priv(vq); | ||
| 1552 | int ret; | ||
| 1553 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1554 | |||
| 1555 | if (!s->udev) | ||
| 1556 | return -ENODEV; | ||
| 1557 | |||
| 1558 | if (mutex_lock_interruptible(&s->v4l2_lock)) | ||
| 1559 | return -ERESTARTSYS; | ||
| 1560 | |||
| 1561 | ret = msi3101_set_usb_adc(s); | ||
| 1562 | |||
| 1563 | ret = msi3101_isoc_init(s); | ||
| 1564 | if (ret) | ||
| 1565 | msi3101_cleanup_queued_bufs(s); | ||
| 1566 | |||
| 1567 | ret = msi3101_ctrl_msg(s, CMD_START_STREAMING, 0); | ||
| 1568 | |||
| 1569 | mutex_unlock(&s->v4l2_lock); | ||
| 1570 | |||
| 1571 | return ret; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | static int msi3101_stop_streaming(struct vb2_queue *vq) | ||
| 1575 | { | ||
| 1576 | struct msi3101_state *s = vb2_get_drv_priv(vq); | ||
| 1577 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1578 | |||
| 1579 | if (mutex_lock_interruptible(&s->v4l2_lock)) | ||
| 1580 | return -ERESTARTSYS; | ||
| 1581 | |||
| 1582 | if (s->udev) | ||
| 1583 | msi3101_isoc_cleanup(s); | ||
| 1584 | |||
| 1585 | msi3101_cleanup_queued_bufs(s); | ||
| 1586 | |||
| 1587 | /* according to tests, at least 700us delay is required */ | ||
| 1588 | msleep(20); | ||
| 1589 | msi3101_ctrl_msg(s, CMD_STOP_STREAMING, 0); | ||
| 1590 | |||
| 1591 | mutex_unlock(&s->v4l2_lock); | ||
| 1592 | |||
| 1593 | return 0; | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | static struct vb2_ops msi3101_vb2_ops = { | ||
| 1597 | .queue_setup = msi3101_queue_setup, | ||
| 1598 | .buf_prepare = msi3101_buf_prepare, | ||
| 1599 | .buf_queue = msi3101_buf_queue, | ||
| 1600 | .start_streaming = msi3101_start_streaming, | ||
| 1601 | .stop_streaming = msi3101_stop_streaming, | ||
| 1602 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 1603 | .wait_finish = vb2_ops_wait_finish, | ||
| 1604 | }; | ||
| 1605 | |||
| 1606 | static int msi3101_enum_input(struct file *file, void *fh, struct v4l2_input *i) | ||
| 1607 | { | ||
| 1608 | if (i->index != 0) | ||
| 1609 | return -EINVAL; | ||
| 1610 | |||
| 1611 | strlcpy(i->name, "SDR data", sizeof(i->name)); | ||
| 1612 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
| 1613 | |||
| 1614 | return 0; | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | static int msi3101_g_input(struct file *file, void *fh, unsigned int *i) | ||
| 1618 | { | ||
| 1619 | *i = 0; | ||
| 1620 | |||
| 1621 | return 0; | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | static int msi3101_s_input(struct file *file, void *fh, unsigned int i) | ||
| 1625 | { | ||
| 1626 | return i ? -EINVAL : 0; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
| 1630 | const struct v4l2_tuner *v) | ||
| 1631 | { | ||
| 1632 | struct msi3101_state *s = video_drvdata(file); | ||
| 1633 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1634 | |||
| 1635 | return 0; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) | ||
| 1639 | { | ||
| 1640 | struct msi3101_state *s = video_drvdata(file); | ||
| 1641 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 1642 | |||
| 1643 | strcpy(v->name, "SDR RX"); | ||
| 1644 | v->capability = V4L2_TUNER_CAP_LOW; | ||
| 1645 | |||
| 1646 | return 0; | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
| 1650 | const struct v4l2_frequency *f) | ||
| 1651 | { | ||
| 1652 | struct msi3101_state *s = video_drvdata(file); | ||
| 1653 | dev_dbg(&s->udev->dev, "%s: frequency=%lu Hz (%u)\n", | ||
| 1654 | __func__, f->frequency * 625UL / 10UL, f->frequency); | ||
| 1655 | |||
| 1656 | return v4l2_ctrl_s_ctrl_int64(s->ctrl_tuner_rf, | ||
| 1657 | f->frequency * 625UL / 10UL); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | const struct v4l2_ioctl_ops msi3101_ioctl_ops = { | ||
| 1661 | .vidioc_querycap = msi3101_querycap, | ||
| 1662 | |||
| 1663 | .vidioc_enum_input = msi3101_enum_input, | ||
| 1664 | .vidioc_g_input = msi3101_g_input, | ||
| 1665 | .vidioc_s_input = msi3101_s_input, | ||
| 1666 | |||
| 1667 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
| 1668 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | ||
| 1669 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | ||
| 1670 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
| 1671 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
| 1672 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
| 1673 | |||
| 1674 | .vidioc_streamon = vb2_ioctl_streamon, | ||
| 1675 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
| 1676 | |||
| 1677 | .vidioc_g_tuner = vidioc_g_tuner, | ||
| 1678 | .vidioc_s_tuner = vidioc_s_tuner, | ||
| 1679 | .vidioc_s_frequency = vidioc_s_frequency, | ||
| 1680 | |||
| 1681 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
| 1682 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
| 1683 | .vidioc_log_status = v4l2_ctrl_log_status, | ||
| 1684 | }; | ||
| 1685 | |||
| 1686 | static const struct v4l2_file_operations msi3101_fops = { | ||
| 1687 | .owner = THIS_MODULE, | ||
| 1688 | .open = v4l2_fh_open, | ||
| 1689 | .release = vb2_fop_release, | ||
| 1690 | .read = vb2_fop_read, | ||
| 1691 | .poll = vb2_fop_poll, | ||
| 1692 | .mmap = vb2_fop_mmap, | ||
| 1693 | .unlocked_ioctl = video_ioctl2, | ||
| 1694 | }; | ||
| 1695 | |||
| 1696 | static struct video_device msi3101_template = { | ||
| 1697 | .name = "Mirics MSi3101 SDR Dongle", | ||
| 1698 | .release = video_device_release_empty, | ||
| 1699 | .fops = &msi3101_fops, | ||
| 1700 | .ioctl_ops = &msi3101_ioctl_ops, | ||
| 1701 | }; | ||
| 1702 | |||
| 1703 | static int msi3101_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1704 | { | ||
| 1705 | struct msi3101_state *s = | ||
| 1706 | container_of(ctrl->handler, struct msi3101_state, | ||
| 1707 | ctrl_handler); | ||
| 1708 | int ret; | ||
| 1709 | dev_dbg(&s->udev->dev, | ||
| 1710 | "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n", | ||
| 1711 | __func__, ctrl->id, ctrl->name, ctrl->val, | ||
| 1712 | ctrl->minimum, ctrl->maximum, ctrl->step); | ||
| 1713 | |||
| 1714 | switch (ctrl->id) { | ||
| 1715 | case MSI3101_CID_SAMPLING_MODE: | ||
| 1716 | case MSI3101_CID_SAMPLING_RATE: | ||
| 1717 | case MSI3101_CID_SAMPLING_RESOLUTION: | ||
| 1718 | ret = 0; | ||
| 1719 | break; | ||
| 1720 | case MSI3101_CID_TUNER_RF: | ||
| 1721 | case MSI3101_CID_TUNER_BW: | ||
| 1722 | case MSI3101_CID_TUNER_IF: | ||
| 1723 | case MSI3101_CID_TUNER_GAIN: | ||
| 1724 | ret = msi3101_set_tuner(s); | ||
| 1725 | break; | ||
| 1726 | default: | ||
| 1727 | ret = -EINVAL; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | return ret; | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | static const struct v4l2_ctrl_ops msi3101_ctrl_ops = { | ||
| 1734 | .s_ctrl = msi3101_s_ctrl, | ||
| 1735 | }; | ||
| 1736 | |||
| 1737 | static void msi3101_video_release(struct v4l2_device *v) | ||
| 1738 | { | ||
| 1739 | struct msi3101_state *s = | ||
| 1740 | container_of(v, struct msi3101_state, v4l2_dev); | ||
| 1741 | |||
| 1742 | v4l2_ctrl_handler_free(&s->ctrl_handler); | ||
| 1743 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 1744 | kfree(s); | ||
| 1745 | } | ||
| 1746 | |||
| 1747 | static int msi3101_probe(struct usb_interface *intf, | ||
| 1748 | const struct usb_device_id *id) | ||
| 1749 | { | ||
| 1750 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1751 | struct msi3101_state *s = NULL; | ||
| 1752 | int ret; | ||
| 1753 | static const char * const ctrl_sampling_mode_qmenu_strings[] = { | ||
| 1754 | "Quadrature Sampling", | ||
| 1755 | NULL, | ||
| 1756 | }; | ||
| 1757 | static const struct v4l2_ctrl_config ctrl_sampling_mode = { | ||
| 1758 | .ops = &msi3101_ctrl_ops, | ||
| 1759 | .id = MSI3101_CID_SAMPLING_MODE, | ||
| 1760 | .type = V4L2_CTRL_TYPE_MENU, | ||
| 1761 | .flags = V4L2_CTRL_FLAG_INACTIVE, | ||
| 1762 | .name = "Sampling Mode", | ||
| 1763 | .qmenu = ctrl_sampling_mode_qmenu_strings, | ||
| 1764 | }; | ||
| 1765 | static const struct v4l2_ctrl_config ctrl_sampling_rate = { | ||
| 1766 | .ops = &msi3101_ctrl_ops, | ||
| 1767 | .id = MSI3101_CID_SAMPLING_RATE, | ||
| 1768 | .type = V4L2_CTRL_TYPE_INTEGER64, | ||
| 1769 | .name = "Sampling Rate", | ||
| 1770 | .min = 500000, | ||
| 1771 | .max = 12000000, | ||
| 1772 | .def = 2048000, | ||
| 1773 | .step = 1, | ||
| 1774 | }; | ||
| 1775 | static const struct v4l2_ctrl_config ctrl_sampling_resolution = { | ||
| 1776 | .ops = &msi3101_ctrl_ops, | ||
| 1777 | .id = MSI3101_CID_SAMPLING_RESOLUTION, | ||
| 1778 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1779 | .flags = V4L2_CTRL_FLAG_INACTIVE, | ||
| 1780 | .name = "Sampling Resolution", | ||
| 1781 | .min = 10, | ||
| 1782 | .max = 10, | ||
| 1783 | .def = 10, | ||
| 1784 | .step = 1, | ||
| 1785 | }; | ||
| 1786 | static const struct v4l2_ctrl_config ctrl_tuner_rf = { | ||
| 1787 | .ops = &msi3101_ctrl_ops, | ||
| 1788 | .id = MSI3101_CID_TUNER_RF, | ||
| 1789 | .type = V4L2_CTRL_TYPE_INTEGER64, | ||
| 1790 | .name = "Tuner RF", | ||
| 1791 | .min = 40000000, | ||
| 1792 | .max = 2000000000, | ||
| 1793 | .def = 100000000, | ||
| 1794 | .step = 1, | ||
| 1795 | }; | ||
| 1796 | static const struct v4l2_ctrl_config ctrl_tuner_bw = { | ||
| 1797 | .ops = &msi3101_ctrl_ops, | ||
| 1798 | .id = MSI3101_CID_TUNER_BW, | ||
| 1799 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1800 | .name = "Tuner BW", | ||
| 1801 | .min = 200000, | ||
| 1802 | .max = 8000000, | ||
| 1803 | .def = 600000, | ||
| 1804 | .step = 1, | ||
| 1805 | }; | ||
| 1806 | static const struct v4l2_ctrl_config ctrl_tuner_if = { | ||
| 1807 | .ops = &msi3101_ctrl_ops, | ||
| 1808 | .id = MSI3101_CID_TUNER_IF, | ||
| 1809 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1810 | .flags = V4L2_CTRL_FLAG_INACTIVE, | ||
| 1811 | .name = "Tuner IF", | ||
| 1812 | .min = 0, | ||
| 1813 | .max = 2048000, | ||
| 1814 | .def = 0, | ||
| 1815 | .step = 1, | ||
| 1816 | }; | ||
| 1817 | static const struct v4l2_ctrl_config ctrl_tuner_gain = { | ||
| 1818 | .ops = &msi3101_ctrl_ops, | ||
| 1819 | .id = MSI3101_CID_TUNER_GAIN, | ||
| 1820 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1821 | .name = "Tuner Gain", | ||
| 1822 | .min = 0, | ||
| 1823 | .max = 102, | ||
| 1824 | .def = 0, | ||
| 1825 | .step = 1, | ||
| 1826 | }; | ||
| 1827 | |||
| 1828 | s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL); | ||
| 1829 | if (s == NULL) { | ||
| 1830 | pr_err("Could not allocate memory for msi3101_state\n"); | ||
| 1831 | return -ENOMEM; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | mutex_init(&s->v4l2_lock); | ||
| 1835 | mutex_init(&s->vb_queue_lock); | ||
| 1836 | spin_lock_init(&s->queued_bufs_lock); | ||
| 1837 | INIT_LIST_HEAD(&s->queued_bufs); | ||
| 1838 | |||
| 1839 | s->udev = udev; | ||
| 1840 | |||
| 1841 | /* Init videobuf2 queue structure */ | ||
| 1842 | s->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 1843 | s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; | ||
| 1844 | s->vb_queue.drv_priv = s; | ||
| 1845 | s->vb_queue.buf_struct_size = sizeof(struct msi3101_frame_buf); | ||
| 1846 | s->vb_queue.ops = &msi3101_vb2_ops; | ||
| 1847 | s->vb_queue.mem_ops = &vb2_vmalloc_memops; | ||
| 1848 | s->vb_queue.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
| 1849 | ret = vb2_queue_init(&s->vb_queue); | ||
| 1850 | if (ret < 0) { | ||
| 1851 | dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); | ||
| 1852 | goto err_free_mem; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | /* Init video_device structure */ | ||
| 1856 | s->vdev = msi3101_template; | ||
| 1857 | s->vdev.queue = &s->vb_queue; | ||
| 1858 | s->vdev.queue->lock = &s->vb_queue_lock; | ||
| 1859 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags); | ||
| 1860 | video_set_drvdata(&s->vdev, s); | ||
| 1861 | |||
| 1862 | /* Register controls */ | ||
| 1863 | v4l2_ctrl_handler_init(&s->ctrl_handler, 7); | ||
| 1864 | v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_mode, NULL); | ||
| 1865 | s->ctrl_sampling_rate = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_rate, NULL); | ||
| 1866 | v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_sampling_resolution, NULL); | ||
| 1867 | s->ctrl_tuner_rf = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_rf, NULL); | ||
| 1868 | s->ctrl_tuner_bw = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_bw, NULL); | ||
| 1869 | s->ctrl_tuner_if = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_if, NULL); | ||
| 1870 | s->ctrl_tuner_gain = v4l2_ctrl_new_custom(&s->ctrl_handler, &ctrl_tuner_gain, NULL); | ||
| 1871 | if (s->ctrl_handler.error) { | ||
| 1872 | ret = s->ctrl_handler.error; | ||
| 1873 | dev_err(&s->udev->dev, "Could not initialize controls\n"); | ||
| 1874 | goto err_free_controls; | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | /* Register the v4l2_device structure */ | ||
| 1878 | s->v4l2_dev.release = msi3101_video_release; | ||
| 1879 | ret = v4l2_device_register(&intf->dev, &s->v4l2_dev); | ||
| 1880 | if (ret) { | ||
| 1881 | dev_err(&s->udev->dev, | ||
| 1882 | "Failed to register v4l2-device (%d)\n", ret); | ||
| 1883 | goto err_free_controls; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | s->v4l2_dev.ctrl_handler = &s->ctrl_handler; | ||
| 1887 | s->vdev.v4l2_dev = &s->v4l2_dev; | ||
| 1888 | s->vdev.lock = &s->v4l2_lock; | ||
| 1889 | |||
| 1890 | ret = video_register_device(&s->vdev, VFL_TYPE_GRABBER, -1); | ||
| 1891 | if (ret < 0) { | ||
| 1892 | dev_err(&s->udev->dev, | ||
| 1893 | "Failed to register as video device (%d)\n", | ||
| 1894 | ret); | ||
| 1895 | goto err_unregister_v4l2_dev; | ||
| 1896 | } | ||
| 1897 | dev_info(&s->udev->dev, "Registered as %s\n", | ||
| 1898 | video_device_node_name(&s->vdev)); | ||
| 1899 | |||
| 1900 | return 0; | ||
| 1901 | |||
| 1902 | err_unregister_v4l2_dev: | ||
| 1903 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 1904 | err_free_controls: | ||
| 1905 | v4l2_ctrl_handler_free(&s->ctrl_handler); | ||
| 1906 | err_free_mem: | ||
| 1907 | kfree(s); | ||
| 1908 | return ret; | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | /* USB device ID list */ | ||
| 1912 | static struct usb_device_id msi3101_id_table[] = { | ||
| 1913 | { USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */ | ||
| 1914 | { USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */ | ||
| 1915 | { } | ||
| 1916 | }; | ||
| 1917 | MODULE_DEVICE_TABLE(usb, msi3101_id_table); | ||
| 1918 | |||
| 1919 | /* USB subsystem interface */ | ||
| 1920 | static struct usb_driver msi3101_driver = { | ||
| 1921 | .name = KBUILD_MODNAME, | ||
| 1922 | .probe = msi3101_probe, | ||
| 1923 | .disconnect = msi3101_disconnect, | ||
| 1924 | .id_table = msi3101_id_table, | ||
| 1925 | }; | ||
| 1926 | |||
| 1927 | module_usb_driver(msi3101_driver); | ||
| 1928 | |||
| 1929 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1930 | MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle"); | ||
| 1931 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/platform_data/camera-mx3.h b/include/linux/platform_data/camera-mx3.h index f226ee3777e1..a910dadc8258 100644 --- a/include/linux/platform_data/camera-mx3.h +++ b/include/linux/platform_data/camera-mx3.h | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #define MX3_CAMERA_DATAWIDTH_MASK (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | \ | 33 | #define MX3_CAMERA_DATAWIDTH_MASK (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | \ |
| 34 | MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15) | 34 | MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15) |
| 35 | 35 | ||
| 36 | struct v4l2_async_subdev; | ||
| 37 | |||
| 36 | /** | 38 | /** |
| 37 | * struct mx3_camera_pdata - i.MX3x camera platform data | 39 | * struct mx3_camera_pdata - i.MX3x camera platform data |
| 38 | * @flags: MX3_CAMERA_* flags | 40 | * @flags: MX3_CAMERA_* flags |
| @@ -43,6 +45,8 @@ struct mx3_camera_pdata { | |||
| 43 | unsigned long flags; | 45 | unsigned long flags; |
| 44 | unsigned long mclk_10khz; | 46 | unsigned long mclk_10khz; |
| 45 | struct device *dma_dev; | 47 | struct device *dma_dev; |
| 48 | struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ | ||
| 49 | int *asd_sizes; /* 0-terminated array of asd group sizes */ | ||
| 46 | }; | 50 | }; |
| 47 | 51 | ||
| 48 | #endif | 52 | #endif |
diff --git a/include/linux/platform_data/camera-rcar.h b/include/linux/platform_data/camera-rcar.h new file mode 100644 index 000000000000..dfc83c581593 --- /dev/null +++ b/include/linux/platform_data/camera-rcar.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * Platform data for Renesas R-Car VIN soc-camera driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011-2013 Renesas Solutions Corp. | ||
| 5 | * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __CAMERA_RCAR_H_ | ||
| 14 | #define __CAMERA_RCAR_H_ | ||
| 15 | |||
| 16 | #define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0) | ||
| 17 | #define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1) | ||
| 18 | #define RCAR_VIN_BT601 (1 << 2) | ||
| 19 | #define RCAR_VIN_BT656 (1 << 3) | ||
| 20 | |||
| 21 | struct rcar_vin_platform_data { | ||
| 22 | unsigned int flags; | ||
| 23 | }; | ||
| 24 | |||
| 25 | #endif /* __CAMERA_RCAR_H_ */ | ||
diff --git a/include/linux/platform_data/vsp1.h b/include/linux/platform_data/vsp1.h new file mode 100644 index 000000000000..a73a456d7f11 --- /dev/null +++ b/include/linux/platform_data/vsp1.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * vsp1.h -- R-Car VSP1 Platform Data | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Corporation | ||
| 5 | * | ||
| 6 | * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __PLATFORM_VSP1_H__ | ||
| 14 | #define __PLATFORM_VSP1_H__ | ||
| 15 | |||
| 16 | #define VSP1_HAS_LIF (1 << 0) | ||
| 17 | |||
| 18 | struct vsp1_platform_data { | ||
| 19 | unsigned int features; | ||
| 20 | unsigned int rpf_count; | ||
| 21 | unsigned int uds_count; | ||
| 22 | unsigned int wpf_count; | ||
| 23 | }; | ||
| 24 | |||
| 25 | #endif /* __PLATFORM_VSP1_H__ */ | ||
diff --git a/include/media/adv7343.h b/include/media/adv7343.h index 944757be49bb..e4142b1ef8cd 100644 --- a/include/media/adv7343.h +++ b/include/media/adv7343.h | |||
| @@ -28,12 +28,7 @@ | |||
| 28 | * @pll_control: PLL and oversampling control. This control allows internal | 28 | * @pll_control: PLL and oversampling control. This control allows internal |
| 29 | * PLL 1 circuit to be powered down and the oversampling to be | 29 | * PLL 1 circuit to be powered down and the oversampling to be |
| 30 | * switched off. | 30 | * switched off. |
| 31 | * @dac_1: power on/off DAC 1. | 31 | * @dac: array to configure power on/off DAC's 1..6 |
| 32 | * @dac_2: power on/off DAC 2. | ||
| 33 | * @dac_3: power on/off DAC 3. | ||
| 34 | * @dac_4: power on/off DAC 4. | ||
| 35 | * @dac_5: power on/off DAC 5. | ||
| 36 | * @dac_6: power on/off DAC 6. | ||
| 37 | * | 32 | * |
| 38 | * Power mode register (Register 0x0), for more info refer REGISTER MAP ACCESS | 33 | * Power mode register (Register 0x0), for more info refer REGISTER MAP ACCESS |
| 39 | * section of datasheet[1], table 17 page no 30. | 34 | * section of datasheet[1], table 17 page no 30. |
| @@ -43,23 +38,16 @@ | |||
| 43 | struct adv7343_power_mode { | 38 | struct adv7343_power_mode { |
| 44 | bool sleep_mode; | 39 | bool sleep_mode; |
| 45 | bool pll_control; | 40 | bool pll_control; |
| 46 | bool dac_1; | 41 | u32 dac[6]; |
| 47 | bool dac_2; | ||
| 48 | bool dac_3; | ||
| 49 | bool dac_4; | ||
| 50 | bool dac_5; | ||
| 51 | bool dac_6; | ||
| 52 | }; | 42 | }; |
| 53 | 43 | ||
| 54 | /** | 44 | /** |
| 55 | * struct adv7343_sd_config - SD Only Output Configuration. | 45 | * struct adv7343_sd_config - SD Only Output Configuration. |
| 56 | * @sd_dac_out1: Configure SD DAC Output 1. | 46 | * @sd_dac_out: array configuring SD DAC Outputs 1 and 2 |
| 57 | * @sd_dac_out2: Configure SD DAC Output 2. | ||
| 58 | */ | 47 | */ |
| 59 | struct adv7343_sd_config { | 48 | struct adv7343_sd_config { |
| 60 | /* SD only Output Configuration */ | 49 | /* SD only Output Configuration */ |
| 61 | bool sd_dac_out1; | 50 | u32 sd_dac_out[2]; |
| 62 | bool sd_dac_out2; | ||
| 63 | }; | 51 | }; |
| 64 | 52 | ||
| 65 | /** | 53 | /** |
diff --git a/include/media/adv7511.h b/include/media/adv7511.h new file mode 100644 index 000000000000..bb78bed9a5b8 --- /dev/null +++ b/include/media/adv7511.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * Analog Devices ADV7511 HDMI Transmitter Device Driver | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef ADV7511_H | ||
| 21 | #define ADV7511_H | ||
| 22 | |||
| 23 | /* notify events */ | ||
| 24 | #define ADV7511_MONITOR_DETECT 0 | ||
| 25 | #define ADV7511_EDID_DETECT 1 | ||
| 26 | |||
| 27 | |||
| 28 | struct adv7511_monitor_detect { | ||
| 29 | int present; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct adv7511_edid_detect { | ||
| 33 | int present; | ||
| 34 | int segment; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct adv7511_cec_arg { | ||
| 38 | void *arg; | ||
| 39 | u32 f_flags; | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct adv7511_platform_data { | ||
| 43 | uint8_t i2c_edid; | ||
| 44 | uint8_t i2c_cec; | ||
| 45 | uint32_t cec_clk; | ||
| 46 | }; | ||
| 47 | |||
| 48 | #endif | ||
diff --git a/include/media/adv7842.h b/include/media/adv7842.h new file mode 100644 index 000000000000..c02201d1c092 --- /dev/null +++ b/include/media/adv7842.h | |||
| @@ -0,0 +1,226 @@ | |||
| 1 | /* | ||
| 2 | * adv7842 - Analog Devices ADV7842 video decoder driver | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _ADV7842_ | ||
| 22 | #define _ADV7842_ | ||
| 23 | |||
| 24 | /* Analog input muxing modes (AFE register 0x02, [2:0]) */ | ||
| 25 | enum adv7842_ain_sel { | ||
| 26 | ADV7842_AIN1_2_3_NC_SYNC_1_2 = 0, | ||
| 27 | ADV7842_AIN4_5_6_NC_SYNC_2_1 = 1, | ||
| 28 | ADV7842_AIN7_8_9_NC_SYNC_3_1 = 2, | ||
| 29 | ADV7842_AIN10_11_12_NC_SYNC_4_1 = 3, | ||
| 30 | ADV7842_AIN9_4_5_6_SYNC_2_1 = 4, | ||
| 31 | }; | ||
| 32 | |||
| 33 | /* Bus rotation and reordering (IO register 0x04, [7:5]) */ | ||
| 34 | enum adv7842_op_ch_sel { | ||
| 35 | ADV7842_OP_CH_SEL_GBR = 0, | ||
| 36 | ADV7842_OP_CH_SEL_GRB = 1, | ||
| 37 | ADV7842_OP_CH_SEL_BGR = 2, | ||
| 38 | ADV7842_OP_CH_SEL_RGB = 3, | ||
| 39 | ADV7842_OP_CH_SEL_BRG = 4, | ||
| 40 | ADV7842_OP_CH_SEL_RBG = 5, | ||
| 41 | }; | ||
| 42 | |||
| 43 | /* Mode of operation */ | ||
| 44 | enum adv7842_mode { | ||
| 45 | ADV7842_MODE_SDP, | ||
| 46 | ADV7842_MODE_COMP, | ||
| 47 | ADV7842_MODE_RGB, | ||
| 48 | ADV7842_MODE_HDMI | ||
| 49 | }; | ||
| 50 | |||
| 51 | /* Video standard select (IO register 0x00, [5:0]) */ | ||
| 52 | enum adv7842_vid_std_select { | ||
| 53 | /* SDP */ | ||
| 54 | ADV7842_SDP_VID_STD_CVBS_SD_4x1 = 0x01, | ||
| 55 | ADV7842_SDP_VID_STD_YC_SD4_x1 = 0x09, | ||
| 56 | /* RGB */ | ||
| 57 | ADV7842_RGB_VID_STD_AUTO_GRAPH_MODE = 0x07, | ||
| 58 | /* HDMI GR */ | ||
| 59 | ADV7842_HDMI_GR_VID_STD_AUTO_GRAPH_MODE = 0x02, | ||
| 60 | /* HDMI COMP */ | ||
| 61 | ADV7842_HDMI_COMP_VID_STD_HD_1250P = 0x1e, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* Input Color Space (IO register 0x02, [7:4]) */ | ||
| 65 | enum adv7842_inp_color_space { | ||
| 66 | ADV7842_INP_COLOR_SPACE_LIM_RGB = 0, | ||
| 67 | ADV7842_INP_COLOR_SPACE_FULL_RGB = 1, | ||
| 68 | ADV7842_INP_COLOR_SPACE_LIM_YCbCr_601 = 2, | ||
| 69 | ADV7842_INP_COLOR_SPACE_LIM_YCbCr_709 = 3, | ||
| 70 | ADV7842_INP_COLOR_SPACE_XVYCC_601 = 4, | ||
| 71 | ADV7842_INP_COLOR_SPACE_XVYCC_709 = 5, | ||
| 72 | ADV7842_INP_COLOR_SPACE_FULL_YCbCr_601 = 6, | ||
| 73 | ADV7842_INP_COLOR_SPACE_FULL_YCbCr_709 = 7, | ||
| 74 | ADV7842_INP_COLOR_SPACE_AUTO = 0xf, | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* Select output format (IO register 0x03, [7:0]) */ | ||
| 78 | enum adv7842_op_format_sel { | ||
| 79 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_8 = 0x00, | ||
| 80 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_10 = 0x01, | ||
| 81 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_12_MODE0 = 0x02, | ||
| 82 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_12_MODE1 = 0x06, | ||
| 83 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_12_MODE2 = 0x0a, | ||
| 84 | ADV7842_OP_FORMAT_SEL_DDR_422_8 = 0x20, | ||
| 85 | ADV7842_OP_FORMAT_SEL_DDR_422_10 = 0x21, | ||
| 86 | ADV7842_OP_FORMAT_SEL_DDR_422_12_MODE0 = 0x22, | ||
| 87 | ADV7842_OP_FORMAT_SEL_DDR_422_12_MODE1 = 0x23, | ||
| 88 | ADV7842_OP_FORMAT_SEL_DDR_422_12_MODE2 = 0x24, | ||
| 89 | ADV7842_OP_FORMAT_SEL_SDR_444_24 = 0x40, | ||
| 90 | ADV7842_OP_FORMAT_SEL_SDR_444_30 = 0x41, | ||
| 91 | ADV7842_OP_FORMAT_SEL_SDR_444_36_MODE0 = 0x42, | ||
| 92 | ADV7842_OP_FORMAT_SEL_DDR_444_24 = 0x60, | ||
| 93 | ADV7842_OP_FORMAT_SEL_DDR_444_30 = 0x61, | ||
| 94 | ADV7842_OP_FORMAT_SEL_DDR_444_36 = 0x62, | ||
| 95 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_16 = 0x80, | ||
| 96 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_20 = 0x81, | ||
| 97 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_24_MODE0 = 0x82, | ||
| 98 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_24_MODE1 = 0x86, | ||
| 99 | ADV7842_OP_FORMAT_SEL_SDR_ITU656_24_MODE2 = 0x8a, | ||
| 100 | }; | ||
| 101 | |||
| 102 | enum adv7842_select_input { | ||
| 103 | ADV7842_SELECT_HDMI_PORT_A, | ||
| 104 | ADV7842_SELECT_HDMI_PORT_B, | ||
| 105 | ADV7842_SELECT_VGA_RGB, | ||
| 106 | ADV7842_SELECT_VGA_COMP, | ||
| 107 | ADV7842_SELECT_SDP_CVBS, | ||
| 108 | ADV7842_SELECT_SDP_YC, | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct adv7842_sdp_csc_coeff { | ||
| 112 | bool manual; | ||
| 113 | uint16_t scaling; | ||
| 114 | uint16_t A1; | ||
| 115 | uint16_t A2; | ||
| 116 | uint16_t A3; | ||
| 117 | uint16_t A4; | ||
| 118 | uint16_t B1; | ||
| 119 | uint16_t B2; | ||
| 120 | uint16_t B3; | ||
| 121 | uint16_t B4; | ||
| 122 | uint16_t C1; | ||
| 123 | uint16_t C2; | ||
| 124 | uint16_t C3; | ||
| 125 | uint16_t C4; | ||
| 126 | }; | ||
| 127 | |||
| 128 | struct adv7842_sdp_io_sync_adjustment { | ||
| 129 | bool adjust; | ||
| 130 | uint16_t hs_beg; | ||
| 131 | uint16_t hs_width; | ||
| 132 | uint16_t de_beg; | ||
| 133 | uint16_t de_end; | ||
| 134 | }; | ||
| 135 | |||
| 136 | /* Platform dependent definition */ | ||
| 137 | struct adv7842_platform_data { | ||
| 138 | /* connector - HDMI or DVI? */ | ||
| 139 | unsigned connector_hdmi:1; | ||
| 140 | |||
| 141 | /* chip reset during probe */ | ||
| 142 | unsigned chip_reset:1; | ||
| 143 | |||
| 144 | /* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */ | ||
| 145 | unsigned disable_pwrdnb:1; | ||
| 146 | |||
| 147 | /* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */ | ||
| 148 | unsigned disable_cable_det_rst:1; | ||
| 149 | |||
| 150 | /* Analog input muxing mode */ | ||
| 151 | enum adv7842_ain_sel ain_sel; | ||
| 152 | |||
| 153 | /* Bus rotation and reordering */ | ||
| 154 | enum adv7842_op_ch_sel op_ch_sel; | ||
| 155 | |||
| 156 | /* Default mode */ | ||
| 157 | enum adv7842_mode mode; | ||
| 158 | |||
| 159 | /* Video standard */ | ||
| 160 | enum adv7842_vid_std_select vid_std_select; | ||
| 161 | |||
| 162 | /* Input Color Space */ | ||
| 163 | enum adv7842_inp_color_space inp_color_space; | ||
| 164 | |||
| 165 | /* Select output format */ | ||
| 166 | enum adv7842_op_format_sel op_format_sel; | ||
| 167 | |||
| 168 | /* IO register 0x02 */ | ||
| 169 | unsigned alt_gamma:1; | ||
| 170 | unsigned op_656_range:1; | ||
| 171 | unsigned rgb_out:1; | ||
| 172 | unsigned alt_data_sat:1; | ||
| 173 | |||
| 174 | /* IO register 0x05 */ | ||
| 175 | unsigned blank_data:1; | ||
| 176 | unsigned insert_av_codes:1; | ||
| 177 | unsigned replicate_av_codes:1; | ||
| 178 | unsigned invert_cbcr:1; | ||
| 179 | |||
| 180 | /* IO register 0x30 */ | ||
| 181 | unsigned output_bus_lsb_to_msb:1; | ||
| 182 | |||
| 183 | /* IO register 0x14 */ | ||
| 184 | struct { | ||
| 185 | unsigned data:2; | ||
| 186 | unsigned clock:2; | ||
| 187 | unsigned sync:2; | ||
| 188 | } drive_strength; | ||
| 189 | |||
| 190 | /* External RAM for 3-D comb or frame synchronizer */ | ||
| 191 | unsigned sd_ram_size; /* ram size in MB */ | ||
| 192 | unsigned sd_ram_ddr:1; /* ddr or sdr sdram */ | ||
| 193 | |||
| 194 | /* Free run */ | ||
| 195 | unsigned hdmi_free_run_mode; | ||
| 196 | |||
| 197 | struct adv7842_sdp_csc_coeff sdp_csc_coeff; | ||
| 198 | |||
| 199 | struct adv7842_sdp_io_sync_adjustment sdp_io_sync; | ||
| 200 | |||
| 201 | /* i2c addresses */ | ||
| 202 | u8 i2c_sdp_io; | ||
| 203 | u8 i2c_sdp; | ||
| 204 | u8 i2c_cp; | ||
| 205 | u8 i2c_vdp; | ||
| 206 | u8 i2c_afe; | ||
| 207 | u8 i2c_hdmi; | ||
| 208 | u8 i2c_repeater; | ||
| 209 | u8 i2c_edid; | ||
| 210 | u8 i2c_infoframe; | ||
| 211 | u8 i2c_cec; | ||
| 212 | u8 i2c_avlink; | ||
| 213 | }; | ||
| 214 | |||
| 215 | #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000) | ||
| 216 | #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001) | ||
| 217 | #define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002) | ||
| 218 | |||
| 219 | /* notify events */ | ||
| 220 | #define ADV7842_FMT_CHANGE 1 | ||
| 221 | |||
| 222 | /* custom ioctl, used to test the external RAM that's used by the | ||
| 223 | * deinterlacer. */ | ||
| 224 | #define ADV7842_CMD_RAM_TEST _IO('V', BASE_VIDIOC_PRIVATE) | ||
| 225 | |||
| 226 | #endif | ||
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h index 3882e0675ccf..3cb1704a0650 100644 --- a/include/media/davinci/vpif_types.h +++ b/include/media/davinci/vpif_types.h | |||
| @@ -59,6 +59,8 @@ struct vpif_display_config { | |||
| 59 | int subdev_count; | 59 | int subdev_count; |
| 60 | struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS]; | 60 | struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS]; |
| 61 | const char *card_name; | 61 | const char *card_name; |
| 62 | struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ | ||
| 63 | int *asd_sizes; /* 0-terminated array of asd group sizes */ | ||
| 62 | }; | 64 | }; |
| 63 | 65 | ||
| 64 | struct vpif_input { | 66 | struct vpif_input { |
| @@ -81,5 +83,7 @@ struct vpif_capture_config { | |||
| 81 | struct vpif_subdev_info *subdev_info; | 83 | struct vpif_subdev_info *subdev_info; |
| 82 | int subdev_count; | 84 | int subdev_count; |
| 83 | const char *card_name; | 85 | const char *card_name; |
| 86 | struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ | ||
| 87 | int *asd_sizes; /* 0-terminated array of asd group sizes */ | ||
| 84 | }; | 88 | }; |
| 85 | #endif /* _VPIF_TYPES_H */ | 89 | #endif /* _VPIF_TYPES_H */ |
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 168dd0b1bae2..78f0637ca68d 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h | |||
| @@ -139,6 +139,7 @@ struct lirc_driver { | |||
| 139 | struct lirc_buffer *rbuf; | 139 | struct lirc_buffer *rbuf; |
| 140 | int (*set_use_inc) (void *data); | 140 | int (*set_use_inc) (void *data); |
| 141 | void (*set_use_dec) (void *data); | 141 | void (*set_use_dec) (void *data); |
| 142 | struct rc_dev *rdev; | ||
| 142 | const struct file_operations *fops; | 143 | const struct file_operations *fops; |
| 143 | struct device *dev; | 144 | struct device *dev; |
| 144 | struct module *owner; | 145 | struct module *owner; |
diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 06bacf937d61..10df55187981 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #ifndef _MEDIA_ENTITY_H | 23 | #ifndef _MEDIA_ENTITY_H |
| 24 | #define _MEDIA_ENTITY_H | 24 | #define _MEDIA_ENTITY_H |
| 25 | 25 | ||
| 26 | #include <linux/bitops.h> | ||
| 26 | #include <linux/list.h> | 27 | #include <linux/list.h> |
| 27 | #include <linux/media.h> | 28 | #include <linux/media.h> |
| 28 | 29 | ||
| @@ -113,12 +114,15 @@ static inline u32 media_entity_subtype(struct media_entity *entity) | |||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | #define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 | 116 | #define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 |
| 117 | #define MEDIA_ENTITY_ENUM_MAX_ID 64 | ||
| 116 | 118 | ||
| 117 | struct media_entity_graph { | 119 | struct media_entity_graph { |
| 118 | struct { | 120 | struct { |
| 119 | struct media_entity *entity; | 121 | struct media_entity *entity; |
| 120 | int link; | 122 | int link; |
| 121 | } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; | 123 | } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; |
| 124 | |||
| 125 | DECLARE_BITMAP(entities, MEDIA_ENTITY_ENUM_MAX_ID); | ||
| 122 | int top; | 126 | int top; |
| 123 | }; | 127 | }; |
| 124 | 128 | ||
diff --git a/include/media/mt9v032.h b/include/media/mt9v032.h index 78fd39eac219..12175a63c5b2 100644 --- a/include/media/mt9v032.h +++ b/include/media/mt9v032.h | |||
| @@ -1,13 +1,9 @@ | |||
| 1 | #ifndef _MEDIA_MT9V032_H | 1 | #ifndef _MEDIA_MT9V032_H |
| 2 | #define _MEDIA_MT9V032_H | 2 | #define _MEDIA_MT9V032_H |
| 3 | 3 | ||
| 4 | struct v4l2_subdev; | ||
| 5 | |||
| 6 | struct mt9v032_platform_data { | 4 | struct mt9v032_platform_data { |
| 7 | unsigned int clk_pol:1; | 5 | unsigned int clk_pol:1; |
| 8 | 6 | ||
| 9 | void (*set_clock)(struct v4l2_subdev *subdev, unsigned int rate); | ||
| 10 | |||
| 11 | const s64 *link_freqs; | 7 | const s64 *link_freqs; |
| 12 | s64 link_def_freq; | 8 | s64 link_def_freq; |
| 13 | }; | 9 | }; |
diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 06a75deff553..2f6f1f78d958 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h | |||
| @@ -101,6 +101,7 @@ struct rc_dev { | |||
| 101 | bool idle; | 101 | bool idle; |
| 102 | u64 allowed_protos; | 102 | u64 allowed_protos; |
| 103 | u64 enabled_protocols; | 103 | u64 enabled_protocols; |
| 104 | u32 users; | ||
| 104 | u32 scanmask; | 105 | u32 scanmask; |
| 105 | void *priv; | 106 | void *priv; |
| 106 | spinlock_t keylock; | 107 | spinlock_t keylock; |
| @@ -142,6 +143,9 @@ void rc_free_device(struct rc_dev *dev); | |||
| 142 | int rc_register_device(struct rc_dev *dev); | 143 | int rc_register_device(struct rc_dev *dev); |
| 143 | void rc_unregister_device(struct rc_dev *dev); | 144 | void rc_unregister_device(struct rc_dev *dev); |
| 144 | 145 | ||
| 146 | int rc_open(struct rc_dev *rdev); | ||
| 147 | void rc_close(struct rc_dev *rdev); | ||
| 148 | |||
| 145 | void rc_repeat(struct rc_dev *dev); | 149 | void rc_repeat(struct rc_dev *dev); |
| 146 | void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle); | 150 | void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle); |
| 147 | void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); | 151 | void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); |
diff --git a/include/media/saa7115.h b/include/media/saa7115.h index 407918625c80..76911e71de17 100644 --- a/include/media/saa7115.h +++ b/include/media/saa7115.h | |||
| @@ -47,9 +47,11 @@ | |||
| 47 | #define SAA7111_FMT_YUV411 0xc0 | 47 | #define SAA7111_FMT_YUV411 0xc0 |
| 48 | 48 | ||
| 49 | /* config flags */ | 49 | /* config flags */ |
| 50 | /* Register 0x85 should set bit 0 to 0 (it's 1 by default). This bit | 50 | /* |
| 51 | * Register 0x85 should set bit 0 to 0 (it's 1 by default). This bit | ||
| 51 | * controls the IDQ signal polarity which is set to 'inverted' if the bit | 52 | * controls the IDQ signal polarity which is set to 'inverted' if the bit |
| 52 | * it 1 and to 'default' if it is 0. */ | 53 | * it 1 and to 'default' if it is 0. |
| 54 | */ | ||
| 53 | #define SAA7115_IDQ_IS_DEFAULT (1 << 0) | 55 | #define SAA7115_IDQ_IS_DEFAULT (1 << 0) |
| 54 | 56 | ||
| 55 | /* s_crystal_freq values and flags */ | 57 | /* s_crystal_freq values and flags */ |
| @@ -64,5 +66,76 @@ | |||
| 64 | #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ | 66 | #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ |
| 65 | #define SAA7115_FREQ_FL_DOUBLE_ASCLK (1 << 3) /* SA 39, LRDIV, SAA7114/5 only */ | 67 | #define SAA7115_FREQ_FL_DOUBLE_ASCLK (1 << 3) /* SA 39, LRDIV, SAA7114/5 only */ |
| 66 | 68 | ||
| 69 | /* ===== SAA7113 Config enums ===== */ | ||
| 70 | |||
| 71 | /* Register 0x08 "Horizontal time constant" [Bit 3..4]: | ||
| 72 | * Should be set to "Fast Locking Mode" according to the datasheet, | ||
| 73 | * and that is the default setting in the gm7113c_init table. | ||
| 74 | * saa7113_init sets this value to "VTR Mode". */ | ||
| 75 | enum saa7113_r08_htc { | ||
| 76 | SAA7113_HTC_TV_MODE = 0x00, | ||
| 77 | SAA7113_HTC_VTR_MODE, /* Default for saa7113_init */ | ||
| 78 | SAA7113_HTC_FAST_LOCKING_MODE = 0x03 /* Default for gm7113c_init */ | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* Register 0x10 "Output format selection" [Bit 6..7]: | ||
| 82 | * Defaults to ITU_656 as specified in datasheet. */ | ||
| 83 | enum saa7113_r10_ofts { | ||
| 84 | SAA7113_OFTS_ITU_656 = 0x0, /* Default */ | ||
| 85 | SAA7113_OFTS_VFLAG_BY_VREF, | ||
| 86 | SAA7113_OFTS_VFLAG_BY_DATA_TYPE | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Register 0x12 "Output control" [Bit 0..3 Or Bit 4..7]: | ||
| 91 | * This is used to select what data is output on the RTS0 and RTS1 pins. | ||
| 92 | * RTS1 [Bit 4..7] Defaults to DOT_IN. (This value can not be set for RTS0) | ||
| 93 | * RTS0 [Bit 0..3] Defaults to VIPB in gm7113c_init as specified | ||
| 94 | * in the datasheet, but is set to HREF_HS in the saa7113_init table. | ||
| 95 | */ | ||
| 96 | enum saa7113_r12_rts { | ||
| 97 | SAA7113_RTS_DOT_IN = 0, /* OBS: Only for RTS1 (Default RTS1) */ | ||
| 98 | SAA7113_RTS_VIPB, /* Default RTS0 For gm7113c_init */ | ||
| 99 | SAA7113_RTS_GPSW, | ||
| 100 | SAA7115_RTS_HL, | ||
| 101 | SAA7113_RTS_VL, | ||
| 102 | SAA7113_RTS_DL, | ||
| 103 | SAA7113_RTS_PLIN, | ||
| 104 | SAA7113_RTS_HREF_HS, /* Default RTS0 For saa7113_init */ | ||
| 105 | SAA7113_RTS_HS, | ||
| 106 | SAA7113_RTS_HQ, | ||
| 107 | SAA7113_RTS_ODD, | ||
| 108 | SAA7113_RTS_VS, | ||
| 109 | SAA7113_RTS_V123, | ||
| 110 | SAA7113_RTS_VGATE, | ||
| 111 | SAA7113_RTS_VREF, | ||
| 112 | SAA7113_RTS_FID | ||
| 113 | }; | ||
| 114 | |||
| 115 | /** | ||
| 116 | * struct saa7115_platform_data - Allow overriding default initialization | ||
| 117 | * | ||
| 118 | * @saa7113_force_gm7113c_init: Force the use of the gm7113c_init table | ||
| 119 | * instead of saa7113_init table | ||
| 120 | * (saa7113 only) | ||
| 121 | * @saa7113_r08_htc: [R_08 - Bit 3..4] | ||
| 122 | * @saa7113_r10_vrln: [R_10 - Bit 3] | ||
| 123 | * default: Disabled for gm7113c_init | ||
| 124 | * Enabled for saa7113c_init | ||
| 125 | * @saa7113_r10_ofts: [R_10 - Bit 6..7] | ||
| 126 | * @saa7113_r12_rts0: [R_12 - Bit 0..3] | ||
| 127 | * @saa7113_r12_rts1: [R_12 - Bit 4..7] | ||
| 128 | * @saa7113_r13_adlsb: [R_13 - Bit 7] - default: disabled | ||
| 129 | */ | ||
| 130 | struct saa7115_platform_data { | ||
| 131 | bool saa7113_force_gm7113c_init; | ||
| 132 | enum saa7113_r08_htc *saa7113_r08_htc; | ||
| 133 | bool *saa7113_r10_vrln; | ||
| 134 | enum saa7113_r10_ofts *saa7113_r10_ofts; | ||
| 135 | enum saa7113_r12_rts *saa7113_r12_rts0; | ||
| 136 | enum saa7113_r12_rts *saa7113_r12_rts1; | ||
| 137 | bool *saa7113_r13_adlsb; | ||
| 138 | }; | ||
| 139 | |||
| 67 | #endif | 140 | #endif |
| 68 | 141 | ||
diff --git a/include/media/smiapp.h b/include/media/smiapp.h index 07f96a89e189..0b8f124a630c 100644 --- a/include/media/smiapp.h +++ b/include/media/smiapp.h | |||
| @@ -77,7 +77,6 @@ struct smiapp_platform_data { | |||
| 77 | struct smiapp_flash_strobe_parms *strobe_setup; | 77 | struct smiapp_flash_strobe_parms *strobe_setup; |
| 78 | 78 | ||
| 79 | int (*set_xclk)(struct v4l2_subdev *sd, int hz); | 79 | int (*set_xclk)(struct v4l2_subdev *sd, int hz); |
| 80 | char *ext_clk_name; | ||
| 81 | int xshutdown; /* gpio or SMIAPP_NO_XSHUTDOWN */ | 80 | int xshutdown; /* gpio or SMIAPP_NO_XSHUTDOWN */ |
| 82 | }; | 81 | }; |
| 83 | 82 | ||
diff --git a/include/sound/tea575x-tuner.h b/include/media/tea575x.h index 098c4de44945..2d4fa59db902 100644 --- a/include/sound/tea575x-tuner.h +++ b/include/media/tea575x.h | |||
| @@ -71,6 +71,7 @@ struct snd_tea575x { | |||
| 71 | int (*ext_init)(struct snd_tea575x *tea); | 71 | int (*ext_init)(struct snd_tea575x *tea); |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | int snd_tea575x_hw_init(struct snd_tea575x *tea); | ||
| 74 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); | 75 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); |
| 75 | void snd_tea575x_exit(struct snd_tea575x *tea); | 76 | void snd_tea575x_exit(struct snd_tea575x *tea); |
| 76 | void snd_tea575x_set_freq(struct snd_tea575x *tea); | 77 | void snd_tea575x_set_freq(struct snd_tea575x *tea); |
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index c3ec6ac75f7e..768356917bea 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
| 16 | 16 | ||
| 17 | struct device; | 17 | struct device; |
| 18 | struct device_node; | ||
| 18 | struct v4l2_device; | 19 | struct v4l2_device; |
| 19 | struct v4l2_subdev; | 20 | struct v4l2_subdev; |
| 20 | struct v4l2_async_notifier; | 21 | struct v4l2_async_notifier; |
| @@ -22,10 +23,11 @@ struct v4l2_async_notifier; | |||
| 22 | /* A random max subdevice number, used to allocate an array on stack */ | 23 | /* A random max subdevice number, used to allocate an array on stack */ |
| 23 | #define V4L2_MAX_SUBDEVS 128U | 24 | #define V4L2_MAX_SUBDEVS 128U |
| 24 | 25 | ||
| 25 | enum v4l2_async_bus_type { | 26 | enum v4l2_async_match_type { |
| 26 | V4L2_ASYNC_BUS_CUSTOM, | 27 | V4L2_ASYNC_MATCH_CUSTOM, |
| 27 | V4L2_ASYNC_BUS_PLATFORM, | 28 | V4L2_ASYNC_MATCH_DEVNAME, |
| 28 | V4L2_ASYNC_BUS_I2C, | 29 | V4L2_ASYNC_MATCH_I2C, |
| 30 | V4L2_ASYNC_MATCH_OF, | ||
| 29 | }; | 31 | }; |
| 30 | 32 | ||
| 31 | /** | 33 | /** |
| @@ -36,11 +38,14 @@ enum v4l2_async_bus_type { | |||
| 36 | * probed, to a notifier->waiting list | 38 | * probed, to a notifier->waiting list |
| 37 | */ | 39 | */ |
| 38 | struct v4l2_async_subdev { | 40 | struct v4l2_async_subdev { |
| 39 | enum v4l2_async_bus_type bus_type; | 41 | enum v4l2_async_match_type match_type; |
| 40 | union { | 42 | union { |
| 41 | struct { | 43 | struct { |
| 44 | const struct device_node *node; | ||
| 45 | } of; | ||
| 46 | struct { | ||
| 42 | const char *name; | 47 | const char *name; |
| 43 | } platform; | 48 | } device_name; |
| 44 | struct { | 49 | struct { |
| 45 | int adapter_id; | 50 | int adapter_id; |
| 46 | unsigned short address; | 51 | unsigned short address; |
| @@ -57,25 +62,12 @@ struct v4l2_async_subdev { | |||
| 57 | }; | 62 | }; |
| 58 | 63 | ||
| 59 | /** | 64 | /** |
| 60 | * v4l2_async_subdev_list - provided by subdevices | ||
| 61 | * @list: links struct v4l2_async_subdev_list objects to a global list | ||
| 62 | * before probing, and onto notifier->done after probing | ||
| 63 | * @asd: pointer to respective struct v4l2_async_subdev | ||
| 64 | * @notifier: pointer to managing notifier | ||
| 65 | */ | ||
| 66 | struct v4l2_async_subdev_list { | ||
| 67 | struct list_head list; | ||
| 68 | struct v4l2_async_subdev *asd; | ||
| 69 | struct v4l2_async_notifier *notifier; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /** | ||
| 73 | * v4l2_async_notifier - v4l2_device notifier data | 65 | * v4l2_async_notifier - v4l2_device notifier data |
| 74 | * @num_subdevs:number of subdevices | 66 | * @num_subdevs:number of subdevices |
| 75 | * @subdev: array of pointers to subdevice descriptors | 67 | * @subdevs: array of pointers to subdevice descriptors |
| 76 | * @v4l2_dev: pointer to struct v4l2_device | 68 | * @v4l2_dev: pointer to struct v4l2_device |
| 77 | * @waiting: list of struct v4l2_async_subdev, waiting for their drivers | 69 | * @waiting: list of struct v4l2_async_subdev, waiting for their drivers |
| 78 | * @done: list of struct v4l2_async_subdev_list, already probed | 70 | * @done: list of struct v4l2_subdev, already probed |
| 79 | * @list: member in a global list of notifiers | 71 | * @list: member in a global list of notifiers |
| 80 | * @bound: a subdevice driver has successfully probed one of subdevices | 72 | * @bound: a subdevice driver has successfully probed one of subdevices |
| 81 | * @complete: all subdevices have been probed successfully | 73 | * @complete: all subdevices have been probed successfully |
| @@ -83,7 +75,7 @@ struct v4l2_async_subdev_list { | |||
| 83 | */ | 75 | */ |
| 84 | struct v4l2_async_notifier { | 76 | struct v4l2_async_notifier { |
| 85 | unsigned int num_subdevs; | 77 | unsigned int num_subdevs; |
| 86 | struct v4l2_async_subdev **subdev; | 78 | struct v4l2_async_subdev **subdevs; |
| 87 | struct v4l2_device *v4l2_dev; | 79 | struct v4l2_device *v4l2_dev; |
| 88 | struct list_head waiting; | 80 | struct list_head waiting; |
| 89 | struct list_head done; | 81 | struct list_head done; |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 015ff82da73c..16550c439008 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
| @@ -86,6 +86,7 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, | |||
| 86 | const char * const *menu_items); | 86 | const char * const *menu_items); |
| 87 | const char *v4l2_ctrl_get_name(u32 id); | 87 | const char *v4l2_ctrl_get_name(u32 id); |
| 88 | const char * const *v4l2_ctrl_get_menu(u32 id); | 88 | const char * const *v4l2_ctrl_get_menu(u32 id); |
| 89 | const s64 const *v4l2_ctrl_get_int_menu(u32 id, u32 *len); | ||
| 89 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); | 90 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); |
| 90 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, | 91 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, |
| 91 | struct v4l2_queryctrl *qctrl, const char * const *menu_items); | 92 | struct v4l2_queryctrl *qctrl, const char * const *menu_items); |
| @@ -201,19 +202,6 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( | |||
| 201 | const struct v4l2_discrete_probe *probe, | 202 | const struct v4l2_discrete_probe *probe, |
| 202 | s32 width, s32 height); | 203 | s32 width, s32 height); |
| 203 | 204 | ||
| 204 | bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1, | ||
| 205 | const struct v4l2_dv_timings *t2, | ||
| 206 | unsigned pclock_delta); | ||
| 207 | |||
| 208 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 209 | u32 polarities, struct v4l2_dv_timings *fmt); | ||
| 210 | |||
| 211 | bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 212 | u32 polarities, struct v4l2_fract aspect, | ||
| 213 | struct v4l2_dv_timings *fmt); | ||
| 214 | |||
| 215 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait); | ||
| 216 | |||
| 217 | void v4l2_get_timestamp(struct timeval *tv); | 205 | void v4l2_get_timestamp(struct timeval *tv); |
| 218 | 206 | ||
| 219 | #endif /* V4L2_COMMON_H_ */ | 207 | #endif /* V4L2_COMMON_H_ */ |
diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h new file mode 100644 index 000000000000..4becc6716393 --- /dev/null +++ b/include/media/v4l2-dv-timings.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* | ||
| 2 | * v4l2-dv-timings - Internal header with dv-timings helper functions | ||
| 3 | * | ||
| 4 | * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you may redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 17 | * SOFTWARE. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __V4L2_DV_TIMINGS_H | ||
| 22 | #define __V4L2_DV_TIMINGS_H | ||
| 23 | |||
| 24 | #include <linux/videodev2.h> | ||
| 25 | |||
| 26 | /** v4l2_dv_timings_presets: list of all dv_timings presets. | ||
| 27 | */ | ||
| 28 | extern const struct v4l2_dv_timings v4l2_dv_timings_presets[]; | ||
| 29 | |||
| 30 | /** v4l2_check_dv_timings_fnc - timings check callback | ||
| 31 | * @t: the v4l2_dv_timings struct. | ||
| 32 | * @handle: a handle from the driver. | ||
| 33 | * | ||
| 34 | * Returns true if the given timings are valid. | ||
| 35 | */ | ||
| 36 | typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle); | ||
| 37 | |||
| 38 | /** v4l2_valid_dv_timings() - are these timings valid? | ||
| 39 | * @t: the v4l2_dv_timings struct. | ||
| 40 | * @cap: the v4l2_dv_timings_cap capabilities. | ||
| 41 | * @fnc: callback to check if this timing is OK. May be NULL. | ||
| 42 | * @fnc_handle: a handle that is passed on to @fnc. | ||
| 43 | * | ||
| 44 | * Returns true if the given dv_timings struct is supported by the | ||
| 45 | * hardware capabilities and the callback function (if non-NULL), returns | ||
| 46 | * false otherwise. | ||
| 47 | */ | ||
| 48 | bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, | ||
| 49 | const struct v4l2_dv_timings_cap *cap, | ||
| 50 | v4l2_check_dv_timings_fnc fnc, | ||
| 51 | void *fnc_handle); | ||
| 52 | |||
| 53 | /** v4l2_enum_dv_timings_cap() - Helper function to enumerate possible DV timings based on capabilities | ||
| 54 | * @t: the v4l2_enum_dv_timings struct. | ||
| 55 | * @cap: the v4l2_dv_timings_cap capabilities. | ||
| 56 | * @fnc: callback to check if this timing is OK. May be NULL. | ||
| 57 | * @fnc_handle: a handle that is passed on to @fnc. | ||
| 58 | * | ||
| 59 | * This enumerates dv_timings using the full list of possible CEA-861 and DMT | ||
| 60 | * timings, filtering out any timings that are not supported based on the | ||
| 61 | * hardware capabilities and the callback function (if non-NULL). | ||
| 62 | * | ||
| 63 | * If a valid timing for the given index is found, it will fill in @t and | ||
| 64 | * return 0, otherwise it returns -EINVAL. | ||
| 65 | */ | ||
| 66 | int v4l2_enum_dv_timings_cap(struct v4l2_enum_dv_timings *t, | ||
| 67 | const struct v4l2_dv_timings_cap *cap, | ||
| 68 | v4l2_check_dv_timings_fnc fnc, | ||
| 69 | void *fnc_handle); | ||
| 70 | |||
| 71 | /** v4l2_find_dv_timings_cap() - Find the closest timings struct | ||
| 72 | * @t: the v4l2_enum_dv_timings struct. | ||
| 73 | * @cap: the v4l2_dv_timings_cap capabilities. | ||
| 74 | * @pclock_delta: maximum delta between t->pixelclock and the timing struct | ||
| 75 | * under consideration. | ||
| 76 | * @fnc: callback to check if a given timings struct is OK. May be NULL. | ||
| 77 | * @fnc_handle: a handle that is passed on to @fnc. | ||
| 78 | * | ||
| 79 | * This function tries to map the given timings to an entry in the | ||
| 80 | * full list of possible CEA-861 and DMT timings, filtering out any timings | ||
| 81 | * that are not supported based on the hardware capabilities and the callback | ||
| 82 | * function (if non-NULL). | ||
| 83 | * | ||
| 84 | * On success it will fill in @t with the found timings and it returns true. | ||
| 85 | * On failure it will return false. | ||
| 86 | */ | ||
| 87 | bool v4l2_find_dv_timings_cap(struct v4l2_dv_timings *t, | ||
| 88 | const struct v4l2_dv_timings_cap *cap, | ||
| 89 | unsigned pclock_delta, | ||
| 90 | v4l2_check_dv_timings_fnc fnc, | ||
| 91 | void *fnc_handle); | ||
| 92 | |||
| 93 | /** v4l2_match_dv_timings() - do two timings match? | ||
| 94 | * @measured: the measured timings data. | ||
| 95 | * @standard: the timings according to the standard. | ||
| 96 | * @pclock_delta: maximum delta in Hz between standard->pixelclock and | ||
| 97 | * the measured timings. | ||
| 98 | * | ||
| 99 | * Returns true if the two timings match, returns false otherwise. | ||
| 100 | */ | ||
| 101 | bool v4l2_match_dv_timings(const struct v4l2_dv_timings *measured, | ||
| 102 | const struct v4l2_dv_timings *standard, | ||
| 103 | unsigned pclock_delta); | ||
| 104 | |||
| 105 | /** v4l2_print_dv_timings() - log the contents of a dv_timings struct | ||
| 106 | * @dev_prefix:device prefix for each log line. | ||
| 107 | * @prefix: additional prefix for each log line, may be NULL. | ||
| 108 | * @t: the timings data. | ||
| 109 | * @detailed: if true, give a detailed log. | ||
| 110 | */ | ||
| 111 | void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix, | ||
| 112 | const struct v4l2_dv_timings *t, bool detailed); | ||
| 113 | |||
| 114 | /** v4l2_detect_cvt - detect if the given timings follow the CVT standard | ||
| 115 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 116 | * @hfreq - the horizontal frequency in Hz. | ||
| 117 | * @vsync - the height of the vertical sync in lines. | ||
| 118 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 119 | * v4l2_bt_timings polarities). | ||
| 120 | * @fmt - the resulting timings. | ||
| 121 | * | ||
| 122 | * This function will attempt to detect if the given values correspond to a | ||
| 123 | * valid CVT format. If so, then it will return true, and fmt will be filled | ||
| 124 | * in with the found CVT timings. | ||
| 125 | */ | ||
| 126 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 127 | u32 polarities, struct v4l2_dv_timings *fmt); | ||
| 128 | |||
| 129 | /** v4l2_detect_gtf - detect if the given timings follow the GTF standard | ||
| 130 | * @frame_height - the total height of the frame (including blanking) in lines. | ||
| 131 | * @hfreq - the horizontal frequency in Hz. | ||
| 132 | * @vsync - the height of the vertical sync in lines. | ||
| 133 | * @polarities - the horizontal and vertical polarities (same as struct | ||
| 134 | * v4l2_bt_timings polarities). | ||
| 135 | * @aspect - preferred aspect ratio. GTF has no method of determining the | ||
| 136 | * aspect ratio in order to derive the image width from the | ||
| 137 | * image height, so it has to be passed explicitly. Usually | ||
| 138 | * the native screen aspect ratio is used for this. If it | ||
| 139 | * is not filled in correctly, then 16:9 will be assumed. | ||
| 140 | * @fmt - the resulting timings. | ||
| 141 | * | ||
| 142 | * This function will attempt to detect if the given values correspond to a | ||
| 143 | * valid GTF format. If so, then it will return true, and fmt will be filled | ||
| 144 | * in with the found GTF timings. | ||
| 145 | */ | ||
| 146 | bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync, | ||
| 147 | u32 polarities, struct v4l2_fract aspect, | ||
| 148 | struct v4l2_dv_timings *fmt); | ||
| 149 | |||
| 150 | /** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes | ||
| 151 | * 0x15 and 0x16 from the EDID. | ||
| 152 | * @hor_landscape - byte 0x15 from the EDID. | ||
| 153 | * @vert_portrait - byte 0x16 from the EDID. | ||
| 154 | * | ||
| 155 | * Determines the aspect ratio from the EDID. | ||
| 156 | * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: | ||
| 157 | * "Horizontal and Vertical Screen Size or Aspect Ratio" | ||
| 158 | */ | ||
| 159 | struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait); | ||
| 160 | |||
| 161 | #endif | ||
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h index 83ae07e53350..395c4a95a42a 100644 --- a/include/media/v4l2-mediabus.h +++ b/include/media/v4l2-mediabus.h | |||
| @@ -40,6 +40,9 @@ | |||
| 40 | #define V4L2_MBUS_FIELD_EVEN_HIGH (1 << 10) | 40 | #define V4L2_MBUS_FIELD_EVEN_HIGH (1 << 10) |
| 41 | /* FIELD = 1/0 - Field1 (odd)/Field2 (even) */ | 41 | /* FIELD = 1/0 - Field1 (odd)/Field2 (even) */ |
| 42 | #define V4L2_MBUS_FIELD_EVEN_LOW (1 << 11) | 42 | #define V4L2_MBUS_FIELD_EVEN_LOW (1 << 11) |
| 43 | /* Active state of Sync-on-green (SoG) signal, 0/1 for LOW/HIGH respectively. */ | ||
| 44 | #define V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH (1 << 12) | ||
| 45 | #define V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW (1 << 13) | ||
| 43 | 46 | ||
| 44 | /* Serial flags */ | 47 | /* Serial flags */ |
| 45 | /* How many lanes the client can use */ | 48 | /* How many lanes the client can use */ |
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 0f4555b2a31b..44542a20ab81 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h | |||
| @@ -60,6 +60,7 @@ struct v4l2_m2m_queue_ctx { | |||
| 60 | struct list_head rdy_queue; | 60 | struct list_head rdy_queue; |
| 61 | spinlock_t rdy_spinlock; | 61 | spinlock_t rdy_spinlock; |
| 62 | u8 num_rdy; | 62 | u8 num_rdy; |
| 63 | bool buffered; | ||
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | struct v4l2_m2m_ctx { | 66 | struct v4l2_m2m_ctx { |
| @@ -134,6 +135,18 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev, | |||
| 134 | void *drv_priv, | 135 | void *drv_priv, |
| 135 | int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)); | 136 | int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)); |
| 136 | 137 | ||
| 138 | static inline void v4l2_m2m_set_src_buffered(struct v4l2_m2m_ctx *m2m_ctx, | ||
| 139 | bool buffered) | ||
| 140 | { | ||
| 141 | m2m_ctx->out_q_ctx.buffered = buffered; | ||
| 142 | } | ||
| 143 | |||
| 144 | static inline void v4l2_m2m_set_dst_buffered(struct v4l2_m2m_ctx *m2m_ctx, | ||
| 145 | bool buffered) | ||
| 146 | { | ||
| 147 | m2m_ctx->cap_q_ctx.buffered = buffered; | ||
| 148 | } | ||
| 149 | |||
| 137 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx); | 150 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx); |
| 138 | 151 | ||
| 139 | void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb); | 152 | void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb); |
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 3250cc5e7925..bfda0fe9aeb0 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h | |||
| @@ -586,15 +586,14 @@ struct v4l2_subdev { | |||
| 586 | struct video_device *devnode; | 586 | struct video_device *devnode; |
| 587 | /* pointer to the physical device, if any */ | 587 | /* pointer to the physical device, if any */ |
| 588 | struct device *dev; | 588 | struct device *dev; |
| 589 | struct v4l2_async_subdev_list asdl; | 589 | /* Links this subdev to a global subdev_list or @notifier->done list. */ |
| 590 | struct list_head async_list; | ||
| 591 | /* Pointer to respective struct v4l2_async_subdev. */ | ||
| 592 | struct v4l2_async_subdev *asd; | ||
| 593 | /* Pointer to the managing notifier. */ | ||
| 594 | struct v4l2_async_notifier *notifier; | ||
| 590 | }; | 595 | }; |
| 591 | 596 | ||
| 592 | static inline struct v4l2_subdev *v4l2_async_to_subdev( | ||
| 593 | struct v4l2_async_subdev_list *asdl) | ||
| 594 | { | ||
| 595 | return container_of(asdl, struct v4l2_subdev, asdl); | ||
| 596 | } | ||
| 597 | |||
| 598 | #define media_entity_to_v4l2_subdev(ent) \ | 597 | #define media_entity_to_v4l2_subdev(ent) \ |
| 599 | container_of(ent, struct v4l2_subdev, entity) | 598 | container_of(ent, struct v4l2_subdev, entity) |
| 600 | #define vdev_to_v4l2_subdev(vdev) \ | 599 | #define vdev_to_v4l2_subdev(vdev) \ |
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index d88a098d1aff..6781258d0b67 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h | |||
| @@ -219,8 +219,9 @@ struct vb2_buffer { | |||
| 219 | * configured format and *num_buffers is the total number | 219 | * configured format and *num_buffers is the total number |
| 220 | * of buffers, that are being allocated. When called from | 220 | * of buffers, that are being allocated. When called from |
| 221 | * VIDIOC_CREATE_BUFS, fmt != NULL and it describes the | 221 | * VIDIOC_CREATE_BUFS, fmt != NULL and it describes the |
| 222 | * target frame format. In this case *num_buffers are being | 222 | * target frame format (if the format isn't valid the |
| 223 | * allocated additionally to q->num_buffers. | 223 | * callback must return -EINVAL). In this case *num_buffers |
| 224 | * are being allocated additionally to q->num_buffers. | ||
| 224 | * @wait_prepare: release any locks taken while calling vb2 functions; | 225 | * @wait_prepare: release any locks taken while calling vb2 functions; |
| 225 | * it is called before an ioctl needs to wait for a new | 226 | * it is called before an ioctl needs to wait for a new |
| 226 | * buffer to arrive; required to avoid a deadlock in | 227 | * buffer to arrive; required to avoid a deadlock in |
| @@ -236,8 +237,10 @@ struct vb2_buffer { | |||
| 236 | * @buf_prepare: called every time the buffer is queued from userspace | 237 | * @buf_prepare: called every time the buffer is queued from userspace |
| 237 | * and from the VIDIOC_PREPARE_BUF ioctl; drivers may | 238 | * and from the VIDIOC_PREPARE_BUF ioctl; drivers may |
| 238 | * perform any initialization required before each hardware | 239 | * perform any initialization required before each hardware |
| 239 | * operation in this callback; if an error is returned, the | 240 | * operation in this callback; drivers that support |
| 240 | * buffer will not be queued in driver; optional | 241 | * VIDIOC_CREATE_BUFS must also validate the buffer size; |
| 242 | * if an error is returned, the buffer will not be queued | ||
| 243 | * in driver; optional | ||
| 241 | * @buf_finish: called before every dequeue of the buffer back to | 244 | * @buf_finish: called before every dequeue of the buffer back to |
| 242 | * userspace; drivers may perform any operations required | 245 | * userspace; drivers may perform any operations required |
| 243 | * before userspace accesses the buffer; optional | 246 | * before userspace accesses the buffer; optional |
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index e90a88a8708f..083bb5a5aae2 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h | |||
| @@ -161,6 +161,8 @@ enum v4l2_colorfx { | |||
| 161 | #define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1040) | 161 | #define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1040) |
| 162 | 162 | ||
| 163 | /* MPEG-class control IDs */ | 163 | /* MPEG-class control IDs */ |
| 164 | /* The MPEG controls are applicable to all codec controls | ||
| 165 | * and the 'MPEG' part of the define is historical */ | ||
| 164 | 166 | ||
| 165 | #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) | 167 | #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) |
| 166 | #define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) | 168 | #define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) |
| @@ -522,6 +524,33 @@ enum v4l2_mpeg_video_mpeg4_profile { | |||
| 522 | }; | 524 | }; |
| 523 | #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL (V4L2_CID_MPEG_BASE+407) | 525 | #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL (V4L2_CID_MPEG_BASE+407) |
| 524 | 526 | ||
| 527 | /* Control IDs for VP8 streams | ||
| 528 | * Although VP8 is not part of MPEG we add these controls to the MPEG class | ||
| 529 | * as that class is already handling other video compression standards | ||
| 530 | */ | ||
| 531 | #define V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS (V4L2_CID_MPEG_BASE+500) | ||
| 532 | enum v4l2_vp8_num_partitions { | ||
| 533 | V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION = 0, | ||
| 534 | V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS = 1, | ||
| 535 | V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS = 2, | ||
| 536 | V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS = 3, | ||
| 537 | }; | ||
| 538 | #define V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4 (V4L2_CID_MPEG_BASE+501) | ||
| 539 | #define V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES (V4L2_CID_MPEG_BASE+502) | ||
| 540 | enum v4l2_vp8_num_ref_frames { | ||
| 541 | V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME = 0, | ||
| 542 | V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME = 1, | ||
| 543 | V4L2_CID_MPEG_VIDEO_VPX_3_REF_FRAME = 2, | ||
| 544 | }; | ||
| 545 | #define V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL (V4L2_CID_MPEG_BASE+503) | ||
| 546 | #define V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS (V4L2_CID_MPEG_BASE+504) | ||
| 547 | #define V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD (V4L2_CID_MPEG_BASE+505) | ||
| 548 | #define V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL (V4L2_CID_MPEG_BASE+506) | ||
| 549 | enum v4l2_vp8_golden_frame_sel { | ||
| 550 | V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV = 0, | ||
| 551 | V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD = 1, | ||
| 552 | }; | ||
| 553 | |||
| 525 | /* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ | 554 | /* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ |
| 526 | #define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) | 555 | #define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) |
| 527 | #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) | 556 | #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) |
diff --git a/include/uapi/linux/v4l2-dv-timings.h b/include/uapi/linux/v4l2-dv-timings.h index 4e0c58d25ff0..be709fe29552 100644 --- a/include/uapi/linux/v4l2-dv-timings.h +++ b/include/uapi/linux/v4l2-dv-timings.h | |||
| @@ -823,12 +823,4 @@ | |||
| 823 | V4L2_DV_FL_REDUCED_BLANKING) \ | 823 | V4L2_DV_FL_REDUCED_BLANKING) \ |
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | #define V4L2_DV_BT_DMT_1366X768P60 { \ | ||
| 827 | .type = V4L2_DV_BT_656_1120, \ | ||
| 828 | V4L2_INIT_BT_TIMINGS(1366, 768, 0, \ | ||
| 829 | V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \ | ||
| 830 | 85500000, 70, 143, 213, 3, 3, 24, 0, 0, 0, \ | ||
| 831 | V4L2_DV_BT_STD_DMT, 0) \ | ||
| 832 | } | ||
| 833 | |||
| 834 | #endif | 826 | #endif |
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h index 6ee63d09b32d..a9601257bb43 100644 --- a/include/uapi/linux/v4l2-mediabus.h +++ b/include/uapi/linux/v4l2-mediabus.h | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | enum v4l2_mbus_pixelcode { | 37 | enum v4l2_mbus_pixelcode { |
| 38 | V4L2_MBUS_FMT_FIXED = 0x0001, | 38 | V4L2_MBUS_FMT_FIXED = 0x0001, |
| 39 | 39 | ||
| 40 | /* RGB - next is 0x100d */ | 40 | /* RGB - next is 0x100e */ |
| 41 | V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001, | 41 | V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001, |
| 42 | V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002, | 42 | V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002, |
| 43 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003, | 43 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003, |
| @@ -50,8 +50,9 @@ enum v4l2_mbus_pixelcode { | |||
| 50 | V4L2_MBUS_FMT_RGB888_1X24 = 0x100a, | 50 | V4L2_MBUS_FMT_RGB888_1X24 = 0x100a, |
| 51 | V4L2_MBUS_FMT_RGB888_2X12_BE = 0x100b, | 51 | V4L2_MBUS_FMT_RGB888_2X12_BE = 0x100b, |
| 52 | V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c, | 52 | V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c, |
| 53 | V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d, | ||
| 53 | 54 | ||
| 54 | /* YUV (including grey) - next is 0x2017 */ | 55 | /* YUV (including grey) - next is 0x2018 */ |
| 55 | V4L2_MBUS_FMT_Y8_1X8 = 0x2001, | 56 | V4L2_MBUS_FMT_Y8_1X8 = 0x2001, |
| 56 | V4L2_MBUS_FMT_UV8_1X8 = 0x2015, | 57 | V4L2_MBUS_FMT_UV8_1X8 = 0x2015, |
| 57 | V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002, | 58 | V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002, |
| @@ -74,6 +75,7 @@ enum v4l2_mbus_pixelcode { | |||
| 74 | V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d, | 75 | V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d, |
| 75 | V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e, | 76 | V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e, |
| 76 | V4L2_MBUS_FMT_YUV10_1X30 = 0x2016, | 77 | V4L2_MBUS_FMT_YUV10_1X30 = 0x2016, |
| 78 | V4L2_MBUS_FMT_AYUV8_1X32 = 0x2017, | ||
| 77 | 79 | ||
| 78 | /* Bayer - next is 0x3019 */ | 80 | /* Bayer - next is 0x3019 */ |
| 79 | V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001, | 81 | V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001, |
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 95ef4551edc1..437f1b0f8937 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h | |||
| @@ -348,6 +348,8 @@ struct v4l2_pix_format { | |||
| 348 | /* two non contiguous planes - one Y, one Cr + Cb interleaved */ | 348 | /* two non contiguous planes - one Y, one Cr + Cb interleaved */ |
| 349 | #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ | 349 | #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ |
| 350 | #define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ | 350 | #define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */ |
| 351 | #define V4L2_PIX_FMT_NV16M v4l2_fourcc('N', 'M', '1', '6') /* 16 Y/CbCr 4:2:2 */ | ||
| 352 | #define V4L2_PIX_FMT_NV61M v4l2_fourcc('N', 'M', '6', '1') /* 16 Y/CrCb 4:2:2 */ | ||
| 351 | #define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ | 353 | #define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ |
| 352 | #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 macroblocks */ | 354 | #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 macroblocks */ |
| 353 | 355 | ||
| @@ -1055,6 +1057,16 @@ struct v4l2_bt_timings { | |||
| 1055 | or used depends on the hardware. */ | 1057 | or used depends on the hardware. */ |
| 1056 | #define V4L2_DV_FL_HALF_LINE (1 << 3) | 1058 | #define V4L2_DV_FL_HALF_LINE (1 << 3) |
| 1057 | 1059 | ||
| 1060 | /* A few useful defines to calculate the total blanking and frame sizes */ | ||
| 1061 | #define V4L2_DV_BT_BLANKING_WIDTH(bt) \ | ||
| 1062 | (bt->hfrontporch + bt->hsync + bt->hbackporch) | ||
| 1063 | #define V4L2_DV_BT_FRAME_WIDTH(bt) \ | ||
| 1064 | (bt->width + V4L2_DV_BT_BLANKING_WIDTH(bt)) | ||
| 1065 | #define V4L2_DV_BT_BLANKING_HEIGHT(bt) \ | ||
| 1066 | (bt->vfrontporch + bt->vsync + bt->vbackporch + \ | ||
| 1067 | bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch) | ||
| 1068 | #define V4L2_DV_BT_FRAME_HEIGHT(bt) \ | ||
| 1069 | (bt->height + V4L2_DV_BT_BLANKING_HEIGHT(bt)) | ||
| 1058 | 1070 | ||
| 1059 | /** struct v4l2_dv_timings - DV timings | 1071 | /** struct v4l2_dv_timings - DV timings |
| 1060 | * @type: the type of the timings | 1072 | * @type: the type of the timings |
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index c95d8f1aae87..5526b03b95a2 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
| @@ -8,10 +8,8 @@ snd-ak4117-objs := ak4117.o | |||
| 8 | snd-ak4113-objs := ak4113.o | 8 | snd-ak4113-objs := ak4113.o |
| 9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o | 9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o |
| 10 | snd-pt2258-objs := pt2258.o | 10 | snd-pt2258-objs := pt2258.o |
| 11 | snd-tea575x-tuner-objs := tea575x-tuner.o | ||
| 12 | 11 | ||
| 13 | # Module Dependency | 12 | # Module Dependency |
| 14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 13 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
| 15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 14 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
| 16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o | 15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
| 17 | obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index fe6fa93a6262..46ed9e8ae0fd 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
| @@ -1,10 +1,5 @@ | |||
| 1 | # ALSA PCI drivers | 1 | # ALSA PCI drivers |
| 2 | 2 | ||
| 3 | config SND_TEA575X | ||
| 4 | tristate | ||
| 5 | depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK | ||
| 6 | default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK | ||
| 7 | |||
| 8 | menuconfig SND_PCI | 3 | menuconfig SND_PCI |
| 9 | bool "PCI sound devices" | 4 | bool "PCI sound devices" |
| 10 | depends on PCI | 5 | depends on PCI |
| @@ -542,7 +537,11 @@ config SND_ES1968_INPUT | |||
| 542 | config SND_ES1968_RADIO | 537 | config SND_ES1968_RADIO |
| 543 | bool "Enable TEA5757 radio tuner support for es1968" | 538 | bool "Enable TEA5757 radio tuner support for es1968" |
| 544 | depends on SND_ES1968 | 539 | depends on SND_ES1968 |
| 540 | depends on MEDIA_RADIO_SUPPORT | ||
| 545 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 | 541 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 |
| 542 | select RADIO_ADAPTERS | ||
| 543 | select RADIO_TEA575X | ||
| 544 | |||
| 546 | help | 545 | help |
| 547 | Say Y here to include support for TEA5757 radio tuner integrated on | 546 | Say Y here to include support for TEA5757 radio tuner integrated on |
| 548 | some MediaForte cards (e.g. SF64-PCE2). | 547 | some MediaForte cards (e.g. SF64-PCE2). |
| @@ -562,7 +561,10 @@ config SND_FM801 | |||
| 562 | config SND_FM801_TEA575X_BOOL | 561 | config SND_FM801_TEA575X_BOOL |
| 563 | bool "ForteMedia FM801 + TEA5757 tuner" | 562 | bool "ForteMedia FM801 + TEA5757 tuner" |
| 564 | depends on SND_FM801 | 563 | depends on SND_FM801 |
| 564 | depends on MEDIA_RADIO_SUPPORT | ||
| 565 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 | 565 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 |
| 566 | select RADIO_ADAPTERS | ||
| 567 | select RADIO_TEA575X | ||
| 566 | help | 568 | help |
| 567 | Say Y here to include support for soundcards based on the ForteMedia | 569 | Say Y here to include support for soundcards based on the ForteMedia |
| 568 | FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and | 570 | FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5e2ec9687731..b0e3d92c4656 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
| @@ -113,7 +113,7 @@ | |||
| 113 | #include <sound/initval.h> | 113 | #include <sound/initval.h> |
| 114 | 114 | ||
| 115 | #ifdef CONFIG_SND_ES1968_RADIO | 115 | #ifdef CONFIG_SND_ES1968_RADIO |
| 116 | #include <sound/tea575x-tuner.h> | 116 | #include <media/tea575x.h> |
| 117 | #endif | 117 | #endif |
| 118 | 118 | ||
| 119 | #define CARD_NAME "ESS Maestro1/2" | 119 | #define CARD_NAME "ESS Maestro1/2" |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 706c5b67b708..45bc8a95b7c4 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 38 | 38 | ||
| 39 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL | 39 | #ifdef CONFIG_SND_FM801_TEA575X_BOOL |
| 40 | #include <sound/tea575x-tuner.h> | 40 | #include <media/tea575x.h> |
| 41 | #endif | 41 | #endif |
| 42 | 42 | ||
| 43 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 43 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
