Pull media updates from Mauro Carvalho Chehab: - the old V4L2 core videobuf kAPI was finally removed. All media drivers should now be using VB2 kAPI - new automotive driver: mgb4 - new platform video driver: npcm-video - new sensor driver: mt9m114 - new TI driver used in conjunction with Cadence CSI2RX IP to bridge TI-specific parts - ir-rx51 was removed and the N900 DT binding was moved to the pwm-ir-tx generic driver - drop atomisp-specific ov5693, using the upstream driver instead - the camss driver has gained RDI3 support for VFE 17x - the atomisp driver now detects ISP2400 or ISP2401 at run time. No need to set it up at build time anymore - lots of driver fixes, cleanups and improvements * tag 'media/v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (377 commits) media: nuvoton: VIDEO_NPCM_VCD_ECE should depend on ARCH_NPCM media: venus: Fix firmware path for resources media: venus: hfi_cmds: Replace one-element array with flex-array member and use __counted_by media: venus: hfi_parser: Add check to keep the number of codecs within range media: venus: hfi: add checks to handle capabilities from firmware media: venus: hfi: fix the check to handle session buffer requirement media: venus: hfi: add checks to perform sanity on queue pointers media: platform: cadence: select MIPI_DPHY dependency media: MAINTAINERS: Fix path for J721E CSI2RX bindings media: cec: meson: always include meson sub-directory in Makefile media: videobuf2: Fix IS_ERR checking in vb2_dc_put_userptr() media: platform: mtk-mdp3: fix uninitialized variable in mdp_path_config() media: mediatek: vcodec: using encoder device to alloc/free encoder memory media: imx-jpeg: notify source chagne event when the first picture parsed media: cx231xx: Use EP5_BUF_SIZE macro media: siano: Drop unnecessary error check for debugfs_create_dir/file() media: mediatek: vcodec: Handle invalid encoder vsi media: aspeed: Drop unnecessary error check for debugfs_create_file() Documentation: media: buffer.rst: fix V4L2_BUF_FLAG_PREPARED Documentation: media: gen-errors.rst: fix confusing ENOTTY description ...
Unified · Split
| @@ -0,0 +1,374 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | ==================== | ||
| 4 | mgb4 sysfs interface | ||
| 5 | ==================== | ||
| 6 | |||
| 7 | The mgb4 driver provides a sysfs interface, that is used to configure video | ||
| 8 | stream related parameters (some of them must be set properly before the v4l2 | ||
| 9 | device can be opened) and obtain the video device/stream status. | ||
| 10 | |||
| 11 | There are two types of parameters - global / PCI card related, found under | ||
| 12 | ``/sys/class/video4linux/videoX/device`` and module specific found under | ||
| 13 | ``/sys/class/video4linux/videoX``. | ||
| 14 | |||
| 15 | |||
| 16 | Global (PCI card) parameters | ||
| 17 | ============================ | ||
| 18 | |||
| 19 | **module_type** (R): | ||
| 20 | Module type. | ||
| 21 | |||
| 22 | | 0 - No module present | ||
| 23 | | 1 - FPDL3 | ||
| 24 | | 2 - GMSL | ||
| 25 | |||
| 26 | **module_version** (R): | ||
| 27 | Module version number. Zero in case of a missing module. | ||
| 28 | |||
| 29 | **fw_type** (R): | ||
| 30 | Firmware type. | ||
| 31 | |||
| 32 | | 1 - FPDL3 | ||
| 33 | | 2 - GMSL | ||
| 34 | |||
| 35 | **fw_version** (R): | ||
| 36 | Firmware version number. | ||
| 37 | |||
| 38 | **serial_number** (R): | ||
| 39 | Card serial number. The format is:: | ||
| 40 | |||
| 41 | PRODUCT-REVISION-SERIES-SERIAL | ||
| 42 | |||
| 43 | where each component is a 8b number. | ||
| 44 | |||
| 45 | |||
| 46 | Common FPDL3/GMSL input parameters | ||
| 47 | ================================== | ||
| 48 | |||
| 49 | **input_id** (R): | ||
| 50 | Input number ID, zero based. | ||
| 51 | |||
| 52 | **oldi_lane_width** (RW): | ||
| 53 | Number of deserializer output lanes. | ||
| 54 | |||
| 55 | | 0 - single | ||
| 56 | | 1 - dual (default) | ||
| 57 | |||
| 58 | **color_mapping** (RW): | ||
| 59 | Mapping of the incoming bits in the signal to the colour bits of the pixels. | ||
| 60 | |||
| 61 | | 0 - OLDI/JEIDA | ||
| 62 | | 1 - SPWG/VESA (default) | ||
| 63 | |||
| 64 | **link_status** (R): | ||
| 65 | Video link status. If the link is locked, chips are properly connected and | ||
| 66 | communicating at the same speed and protocol. The link can be locked without | ||
| 67 | an active video stream. | ||
| 68 | |||
| 69 | A value of 0 is equivalent to the V4L2_IN_ST_NO_SYNC flag of the V4L2 | ||
| 70 | VIDIOC_ENUMINPUT status bits. | ||
| 71 | |||
| 72 | | 0 - unlocked | ||
| 73 | | 1 - locked | ||
| 74 | |||
| 75 | **stream_status** (R): | ||
| 76 | Video stream status. A stream is detected if the link is locked, the input | ||
| 77 | pixel clock is running and the DE signal is moving. | ||
| 78 | |||
| 79 | A value of 0 is equivalent to the V4L2_IN_ST_NO_SIGNAL flag of the V4L2 | ||
| 80 | VIDIOC_ENUMINPUT status bits. | ||
| 81 | |||
| 82 | | 0 - not detected | ||
| 83 | | 1 - detected | ||
| 84 | |||
| 85 | **video_width** (R): | ||
| 86 | Video stream width. This is the actual width as detected by the HW. | ||
| 87 | |||
| 88 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in the width | ||
| 89 | field of the v4l2_bt_timings struct. | ||
| 90 | |||
| 91 | **video_height** (R): | ||
| 92 | Video stream height. This is the actual height as detected by the HW. | ||
| 93 | |||
| 94 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in the height | ||
| 95 | field of the v4l2_bt_timings struct. | ||
| 96 | |||
| 97 | **vsync_status** (R): | ||
| 98 | The type of VSYNC pulses as detected by the video format detector. | ||
| 99 | |||
| 100 | The value is equivalent to the flags returned by VIDIOC_QUERY_DV_TIMINGS in | ||
| 101 | the polarities field of the v4l2_bt_timings struct. | ||
| 102 | |||
| 103 | | 0 - active low | ||
| 104 | | 1 - active high | ||
| 105 | | 2 - not available | ||
| 106 | |||
| 107 | **hsync_status** (R): | ||
| 108 | The type of HSYNC pulses as detected by the video format detector. | ||
| 109 | |||
| 110 | The value is equivalent to the flags returned by VIDIOC_QUERY_DV_TIMINGS in | ||
| 111 | the polarities field of the v4l2_bt_timings struct. | ||
| 112 | |||
| 113 | | 0 - active low | ||
| 114 | | 1 - active high | ||
| 115 | | 2 - not available | ||
| 116 | |||
| 117 | **vsync_gap_length** (RW): | ||
| 118 | If the incoming video signal does not contain synchronization VSYNC and | ||
| 119 | HSYNC pulses, these must be generated internally in the FPGA to achieve | ||
| 120 | the correct frame ordering. This value indicates, how many "empty" pixels | ||
| 121 | (pixels with deasserted Data Enable signal) are necessary to generate the | ||
| 122 | internal VSYNC pulse. | ||
| 123 | |||
| 124 | **hsync_gap_length** (RW): | ||
| 125 | If the incoming video signal does not contain synchronization VSYNC and | ||
| 126 | HSYNC pulses, these must be generated internally in the FPGA to achieve | ||
| 127 | the correct frame ordering. This value indicates, how many "empty" pixels | ||
| 128 | (pixels with deasserted Data Enable signal) are necessary to generate the | ||
| 129 | internal HSYNC pulse. The value must be greater than 1 and smaller than | ||
| 130 | vsync_gap_length. | ||
| 131 | |||
| 132 | **pclk_frequency** (R): | ||
| 133 | Input pixel clock frequency in kHz. | ||
| 134 | |||
| 135 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 136 | the pixelclock field of the v4l2_bt_timings struct. | ||
| 137 | |||
| 138 | *Note: The frequency_range parameter must be set properly first to get | ||
| 139 | a valid frequency here.* | ||
| 140 | |||
| 141 | **hsync_width** (R): | ||
| 142 | Width of the HSYNC signal in PCLK clock ticks. | ||
| 143 | |||
| 144 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 145 | the hsync field of the v4l2_bt_timings struct. | ||
| 146 | |||
| 147 | **vsync_width** (R): | ||
| 148 | Width of the VSYNC signal in PCLK clock ticks. | ||
| 149 | |||
| 150 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 151 | the vsync field of the v4l2_bt_timings struct. | ||
| 152 | |||
| 153 | **hback_porch** (R): | ||
| 154 | Number of PCLK pulses between deassertion of the HSYNC signal and the first | ||
| 155 | valid pixel in the video line (marked by DE=1). | ||
| 156 | |||
| 157 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 158 | the hbackporch field of the v4l2_bt_timings struct. | ||
| 159 | |||
| 160 | **hfront_porch** (R): | ||
| 161 | Number of PCLK pulses between the end of the last valid pixel in the video | ||
| 162 | line (marked by DE=1) and assertion of the HSYNC signal. | ||
| 163 | |||
| 164 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 165 | the hfrontporch field of the v4l2_bt_timings struct. | ||
| 166 | |||
| 167 | **vback_porch** (R): | ||
| 168 | Number of video lines between deassertion of the VSYNC signal and the video | ||
| 169 | line with the first valid pixel (marked by DE=1). | ||
| 170 | |||
| 171 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 172 | the vbackporch field of the v4l2_bt_timings struct. | ||
| 173 | |||
| 174 | **vfront_porch** (R): | ||
| 175 | Number of video lines between the end of the last valid pixel line (marked | ||
| 176 | by DE=1) and assertion of the VSYNC signal. | ||
| 177 | |||
| 178 | The value is identical to what VIDIOC_QUERY_DV_TIMINGS returns in | ||
| 179 | the vfrontporch field of the v4l2_bt_timings struct. | ||
| 180 | |||
| 181 | **frequency_range** (RW) | ||
| 182 | PLL frequency range of the OLDI input clock generator. The PLL frequency is | ||
| 183 | derived from the Pixel Clock Frequency (PCLK) and is equal to PCLK if | ||
| 184 | oldi_lane_width is set to "single" and PCLK/2 if oldi_lane_width is set to | ||
| 185 | "dual". | ||
| 186 | |||
| 187 | | 0 - PLL < 50MHz (default) | ||
| 188 | | 1 - PLL >= 50MHz | ||
| 189 | |||
| 190 | *Note: This parameter can not be changed while the input v4l2 device is | ||
| 191 | open.* | ||
| 192 | |||
| 193 | |||
| 194 | Common FPDL3/GMSL output parameters | ||
| 195 | =================================== | ||
| 196 | |||
| 197 | **output_id** (R): | ||
| 198 | Output number ID, zero based. | ||
| 199 | |||
| 200 | **video_source** (RW): | ||
| 201 | Output video source. If set to 0 or 1, the source is the corresponding card | ||
| 202 | input and the v4l2 output devices are disabled. If set to 2 or 3, the source | ||
| 203 | is the corresponding v4l2 video output device. The default is | ||
| 204 | the corresponding v4l2 output, i.e. 2 for OUT1 and 3 for OUT2. | ||
| 205 | |||
| 206 | | 0 - input 0 | ||
| 207 | | 1 - input 1 | ||
| 208 | | 2 - v4l2 output 0 | ||
| 209 | | 3 - v4l2 output 1 | ||
| 210 | |||
| 211 | *Note: This parameter can not be changed while ANY of the input/output v4l2 | ||
| 212 | devices is open.* | ||
| 213 | |||
| 214 | **display_width** (RW): | ||
| 215 | Display width. There is no autodetection of the connected display, so the | ||
| 216 | proper value must be set before the start of streaming. The default width | ||
| 217 | is 1280. | ||
| 218 | |||
| 219 | *Note: This parameter can not be changed while the output v4l2 device is | ||
| 220 | open.* | ||
| 221 | |||
| 222 | **display_height** (RW): | ||
| 223 | Display height. There is no autodetection of the connected display, so the | ||
| 224 | proper value must be set before the start of streaming. The default height | ||
| 225 | is 640. | ||
| 226 | |||
| 227 | *Note: This parameter can not be changed while the output v4l2 device is | ||
| 228 | open.* | ||
| 229 | |||
| 230 | **frame_rate** (RW): | ||
| 231 | Output video frame rate in frames per second. The default frame rate is | ||
| 232 | 60Hz. | ||
| 233 | |||
| 234 | **hsync_polarity** (RW): | ||
| 235 | HSYNC signal polarity. | ||
| 236 | |||
| 237 | | 0 - active low (default) | ||
| 238 | | 1 - active high | ||
| 239 | |||
| 240 | **vsync_polarity** (RW): | ||
| 241 | VSYNC signal polarity. | ||
| 242 | |||
| 243 | | 0 - active low (default) | ||
| 244 | | 1 - active high | ||
| 245 | |||
| 246 | **de_polarity** (RW): | ||
| 247 | DE signal polarity. | ||
| 248 | |||
| 249 | | 0 - active low | ||
| 250 | | 1 - active high (default) | ||
| 251 | |||
| 252 | **pclk_frequency** (RW): | ||
| 253 | Output pixel clock frequency. Allowed values are between 25000-190000(kHz) | ||
| 254 | and there is a non-linear stepping between two consecutive allowed | ||
| 255 | frequencies. The driver finds the nearest allowed frequency to the given | ||
| 256 | value and sets it. When reading this property, you get the exact | ||
| 257 | frequency set by the driver. The default frequency is 70000kHz. | ||
| 258 | |||
| 259 | *Note: This parameter can not be changed while the output v4l2 device is | ||
| 260 | open.* | ||
| 261 | |||
| 262 | **hsync_width** (RW): | ||
| 263 | Width of the HSYNC signal in pixels. The default value is 16. | ||
| 264 | |||
| 265 | **vsync_width** (RW): | ||
| 266 | Width of the VSYNC signal in video lines. The default value is 2. | ||
| 267 | |||
| 268 | **hback_porch** (RW): | ||
| 269 | Number of PCLK pulses between deassertion of the HSYNC signal and the first | ||
| 270 | valid pixel in the video line (marked by DE=1). The default value is 32. | ||
| 271 | |||
| 272 | **hfront_porch** (RW): | ||
| 273 | Number of PCLK pulses between the end of the last valid pixel in the video | ||
| 274 | line (marked by DE=1) and assertion of the HSYNC signal. The default value | ||
| 275 | is 32. | ||
| 276 | |||
| 277 | **vback_porch** (RW): | ||
| 278 | Number of video lines between deassertion of the VSYNC signal and the video | ||
| 279 | line with the first valid pixel (marked by DE=1). The default value is 2. | ||
| 280 | |||
| 281 | **vfront_porch** (RW): | ||
| 282 | Number of video lines between the end of the last valid pixel line (marked | ||
| 283 | by DE=1) and assertion of the VSYNC signal. The default value is 2. | ||
| 284 | |||
| 285 | |||
| 286 | FPDL3 specific input parameters | ||
| 287 | =============================== | ||
| 288 | |||
| 289 | **fpdl3_input_width** (RW): | ||
| 290 | Number of deserializer input lines. | ||
| 291 | |||
| 292 | | 0 - auto (default) | ||
| 293 | | 1 - single | ||
| 294 | | 2 - dual | ||
| 295 | |||
| 296 | FPDL3 specific output parameters | ||
| 297 | ================================ | ||
| 298 | |||
| 299 | **fpdl3_output_width** (RW): | ||
| 300 | Number of serializer output lines. | ||
| 301 | |||
| 302 | | 0 - auto (default) | ||
| 303 | | 1 - single | ||
| 304 | | 2 - dual | ||
| 305 | |||
| 306 | GMSL specific input parameters | ||
| 307 | ============================== | ||
| 308 | |||
| 309 | **gmsl_mode** (RW): | ||
| 310 | GMSL speed mode. | ||
| 311 | |||
| 312 | | 0 - 12Gb/s (default) | ||
| 313 | | 1 - 6Gb/s | ||
| 314 | | 2 - 3Gb/s | ||
| 315 | | 3 - 1.5Gb/s | ||
| 316 | |||
| 317 | **gmsl_stream_id** (RW): | ||
| 318 | The GMSL multi-stream contains up to four video streams. This parameter | ||
| 319 | selects which stream is captured by the video input. The value is the | ||
| 320 | zero-based index of the stream. The default stream id is 0. | ||
| 321 | |||
| 322 | *Note: This parameter can not be changed while the input v4l2 device is | ||
| 323 | open.* | ||
| 324 | |||
| 325 | **gmsl_fec** (RW): | ||
| 326 | GMSL Forward Error Correction (FEC). | ||
| 327 | |||
| 328 | | 0 - disabled | ||
| 329 | | 1 - enabled (default) | ||
| 330 | |||
| 331 | |||
| 332 | ==================== | ||
| 333 | mgb4 mtd partitions | ||
| 334 | ==================== | ||
| 335 | |||
| 336 | The mgb4 driver creates a MTD device with two partitions: | ||
| 337 | - mgb4-fw.X - FPGA firmware. | ||
| 338 | - mgb4-data.X - Factory settings, e.g. card serial number. | ||
| 339 | |||
| 340 | The *mgb4-fw* partition is writable and is used for FW updates, *mgb4-data* is | ||
| 341 | read-only. The *X* attached to the partition name represents the card number. | ||
| 342 | Depending on the CONFIG_MTD_PARTITIONED_MASTER kernel configuration, you may | ||
| 343 | also have a third partition named *mgb4-flash* available in the system. This | ||
| 344 | partition represents the whole, unpartitioned, card's FLASH memory and one should | ||
| 345 | not fiddle with it... | ||
| 346 | |||
| 347 | ==================== | ||
| 348 | mgb4 iio (triggers) | ||
| 349 | ==================== | ||
| 350 | |||
| 351 | The mgb4 driver creates an Industrial I/O (IIO) device that provides trigger and | ||
| 352 | signal level status capability. The following scan elements are available: | ||
| 353 | |||
| 354 | **activity**: | ||
| 355 | The trigger levels and pending status. | ||
| 356 | |||
| 357 | | bit 1 - trigger 1 pending | ||
| 358 | | bit 2 - trigger 2 pending | ||
| 359 | | bit 5 - trigger 1 level | ||
| 360 | | bit 6 - trigger 2 level | ||
| 361 | |||
| 362 | **timestamp**: | ||
| 363 | The trigger event timestamp. | ||
| 364 | |||
| 365 | The iio device can operate either in "raw" mode where you can fetch the signal | ||
| 366 | levels (activity bits 5 and 6) using sysfs access or in triggered buffer mode. | ||
| 367 | In the triggered buffer mode you can follow the signal level changes (activity | ||
| 368 | bits 1 and 2) using the iio device in /dev. If you enable the timestamps, you | ||
| 369 | will also get the exact trigger event time that can be matched to a video frame | ||
| 370 | (every mgb4 video frame has a timestamp with the same clock source). | ||
| 371 | |||
| 372 | *Note: although the activity sample always contains all the status bits, it makes | ||
| 373 | no sense to get the pending bits in raw mode or the level bits in the triggered | ||
| 374 | buffer mode - the values do not represent valid data in such case.* | ||
| @@ -77,6 +77,7 @@ ipu3-cio2 Intel ipu3-cio2 driver · 76 unmodified lines | |||
| 77 | ivtv Conexant cx23416/cx23415 MPEG encoder/decoder | 77 | ivtv Conexant cx23416/cx23415 MPEG encoder/decoder |
| 78 | ivtvfb Conexant cx23415 framebuffer | 78 | ivtvfb Conexant cx23415 framebuffer |
| 79 | mantis MANTIS based cards | 79 | mantis MANTIS based cards |
| 80 | mgb4 Digiteq Automotive MGB4 frame grabber | ||
| 80 | mxb Siemens-Nixdorf 'Multimedia eXtension Board' | 81 | mxb Siemens-Nixdorf 'Multimedia eXtension Board' |
| 81 | netup-unidvb NetUP Universal DVB card | 82 | netup-unidvb NetUP Universal DVB card |
| 82 | ngene Micronas nGene | 83 | ngene Micronas nGene |
| @@ -17,6 +17,7 @@ Video4Linux (V4L) driver-specific documentation · 16 unmodified lines | |||
| 17 | imx7 | 17 | imx7 |
| 18 | ipu3 | 18 | ipu3 |
| 19 | ivtv | 19 | ivtv |
| 20 | mgb4 | ||
| 20 | omap3isp | 21 | omap3isp |
| 21 | omap4_camera | 22 | omap4_camera |
| 22 | philips | 23 | philips |
| @@ -78,7 +78,7 @@ The trace events are defined on a per-codec basis, e.g.: · 77 unmodified lines | |||
| 78 | 78 | ||
| 79 | .. code-block:: bash | 79 | .. code-block:: bash |
| 80 | 80 | ||
| 81 | $ ls /sys/kernel/debug/tracing/events/ | grep visl | 81 | $ ls /sys/kernel/tracing/events/ | grep visl |
| 82 | visl_fwht_controls | 82 | visl_fwht_controls |
| 83 | visl_h264_controls | 83 | visl_h264_controls |
| 84 | visl_hevc_controls | 84 | visl_hevc_controls |
| @@ -90,13 +90,13 @@ For example, in order to dump HEVC SPS data: · 5 unmodified lines | |||
| 90 | 90 | ||
| 91 | .. code-block:: bash | 91 | .. code-block:: bash |
| 92 | 92 | ||
| 93 | $ echo 1 > /sys/kernel/debug/tracing/events/visl_hevc_controls/v4l2_ctrl_hevc_sps/enable | 93 | $ echo 1 > /sys/kernel/tracing/events/visl_hevc_controls/v4l2_ctrl_hevc_sps/enable |
| 94 | 94 | ||
| 95 | The SPS data will be dumped to the trace buffer, i.e.: | 95 | The SPS data will be dumped to the trace buffer, i.e.: |
| 96 | 96 | ||
| 97 | .. code-block:: bash | 97 | .. code-block:: bash |
| 98 | 98 | ||
| 99 | $ cat /sys/kernel/debug/tracing/trace | 99 | $ cat /sys/kernel/tracing/trace |
| 100 | video_parameter_set_id 0 | 100 | video_parameter_set_id 0 |
| 101 | seq_parameter_set_id 0 | 101 | seq_parameter_set_id 0 |
| 102 | pic_width_in_luma_samples 1920 | 102 | pic_width_in_luma_samples 1920 |
| @@ -15,7 +15,10 @@ description: · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | properties: | 16 | properties: |
| 17 | compatible: | 17 | compatible: |
| 18 | const: pwm-ir-tx | 18 | oneOf: |
| 19 | - const: pwm-ir-tx | ||
| 20 | - const: nokia,n900-ir | ||
| 21 | deprecated: true | ||
| 19 | 22 | ||
| 20 | pwms: | 23 | pwms: |
| 21 | maxItems: 1 | 24 | maxItems: 1 |
| @@ -19,6 +19,7 @@ properties: · 18 unmodified lines | |||
| 19 | - amlogic,meson6-ir | 19 | - amlogic,meson6-ir |
| 20 | - amlogic,meson8b-ir | 20 | - amlogic,meson8b-ir |
| 21 | - amlogic,meson-gxbb-ir | 21 | - amlogic,meson-gxbb-ir |
| 22 | - amlogic,meson-s4-ir | ||
| 22 | - items: | 23 | - items: |
| 23 | - const: amlogic,meson-gx-ir | 24 | - const: amlogic,meson-gx-ir |
| 24 | - const: amlogic,meson-gxbb-ir | 25 | - const: amlogic,meson-gxbb-ir |
| @@ -18,6 +18,7 @@ properties: · 17 unmodified lines | |||
| 18 | items: | 18 | items: |
| 19 | - enum: | 19 | - enum: |
| 20 | - starfive,jh7110-csi2rx | 20 | - starfive,jh7110-csi2rx |
| 21 | - ti,j721e-csi2rx | ||
| 21 | - const: cdns,csi2rx | 22 | - const: cdns,csi2rx |
| 22 | 23 | ||
| 23 | reg: | 24 | reg: |
| @@ -14,6 +14,9 @@ description: |- · 13 unmodified lines | |||
| 14 | interface and CCI (I2C compatible) control bus. The output format | 14 | interface and CCI (I2C compatible) control bus. The output format |
| 15 | is raw Bayer. | 15 | is raw Bayer. |
| 16 | 16 | ||
| 17 | allOf: | ||
| 18 | - $ref: /schemas/media/video-interface-devices.yaml# | ||
| 19 | |||
| 17 | properties: | 20 | properties: |
| 18 | compatible: | 21 | compatible: |
| 19 | const: hynix,hi846 | 22 | const: hynix,hi846 |
| @@ -86,7 +89,7 @@ required: · 66 unmodified lines | |||
| 86 | - vddd-supply | 89 | - vddd-supply |
| 87 | - port | 90 | - port |
| 88 | 91 | ||
| 89 | additionalProperties: false | 92 | unevaluatedProperties: false |
| 90 | 93 | ||
| 91 | examples: | 94 | examples: |
| 92 | - | | 95 | - | |
| @@ -109,6 +112,8 @@ examples: · 16 unmodified lines | |||
| 109 | vddio-supply = <®_camera_vddio>; | 112 | vddio-supply = <®_camera_vddio>; |
| 110 | reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; | 113 | reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; |
| 111 | shutdown-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>; | 114 | shutdown-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>; |
| 115 | orientation = <0>; | ||
| 116 | rotation = <0>; | ||
| 112 | 117 | ||
| 113 | port { | 118 | port { |
| 114 | camera_out: endpoint { | 119 | camera_out: endpoint { |
| @@ -0,0 +1,114 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/media/i2c/onnn,mt9m114.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: onsemi 1/6-inch 720p CMOS Digital Image Sensor | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
| 11 | |||
| 12 | description: |- | ||
| 13 | The onsemi MT9M114 is a 1/6-inch 720p (1.26 Mp) CMOS digital image sensor | ||
| 14 | with an active pixel-array size of 1296H x 976V. It is programmable through | ||
| 15 | an I2C interface and outputs image data over a 8-bit parallel or 1-lane MIPI | ||
| 16 | CSI-2 connection. | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | const: onnn,mt9m114 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | description: I2C device address | ||
| 24 | enum: | ||
| 25 | - 0x48 | ||
| 26 | - 0x5d | ||
| 27 | |||
| 28 | clocks: | ||
| 29 | description: EXTCLK clock signal | ||
| 30 | maxItems: 1 | ||
| 31 | |||
| 32 | vdd-supply: | ||
| 33 | description: | ||
| 34 | Core digital voltage supply, 1.8V | ||
| 35 | |||
| 36 | vddio-supply: | ||
| 37 | description: | ||
| 38 | I/O digital voltage supply, 1.8V or 2.8V | ||
| 39 | |||
| 40 | vaa-supply: | ||
| 41 | description: | ||
| 42 | Analog voltage supply, 2.8V | ||
| 43 | |||
| 44 | reset-gpios: | ||
| 45 | description: |- | ||
| 46 | Reference to the GPIO connected to the RESET_BAR pin, if any (active | ||
| 47 | low). | ||
| 48 | |||
| 49 | port: | ||
| 50 | $ref: /schemas/graph.yaml#/$defs/port-base | ||
| 51 | additionalProperties: false | ||
| 52 | |||
| 53 | properties: | ||
| 54 | endpoint: | ||
| 55 | $ref: /schemas/media/video-interfaces.yaml# | ||
| 56 | additionalProperties: false | ||
| 57 | |||
| 58 | properties: | ||
| 59 | bus-type: | ||
| 60 | enum: [4, 5, 6] | ||
| 61 | |||
| 62 | link-frequencies: true | ||
| 63 | remote-endpoint: true | ||
| 64 | |||
| 65 | # The number and mapping of lanes (for CSI-2), and the bus width and | ||
| 66 | # signal polarities (for parallel and BT.656) are fixed and must not | ||
| 67 | # be specified. | ||
| 68 | |||
| 69 | required: | ||
| 70 | - bus-type | ||
| 71 | - link-frequencies | ||
| 72 | |||
| 73 | required: | ||
| 74 | - compatible | ||
| 75 | - reg | ||
| 76 | - clocks | ||
| 77 | - vdd-supply | ||
| 78 | - vddio-supply | ||
| 79 | - vaa-supply | ||
| 80 | - port | ||
| 81 | |||
| 82 | additionalProperties: false | ||
| 83 | |||
| 84 | examples: | ||
| 85 | - | | ||
| 86 | #include <dt-bindings/gpio/gpio.h> | ||
| 87 | #include <dt-bindings/media/video-interfaces.h> | ||
| 88 | |||
| 89 | i2c0 { | ||
| 90 | #address-cells = <1>; | ||
| 91 | #size-cells = <0>; | ||
| 92 | |||
| 93 | sensor@48 { | ||
| 94 | compatible = "onnn,mt9m114"; | ||
| 95 | reg = <0x48>; | ||
| 96 | |||
| 97 | clocks = <&clk24m 0>; | ||
| 98 | |||
| 99 | reset-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>; | ||
| 100 | |||
| 101 | vddio-supply = <®_cam_1v8>; | ||
| 102 | vdd-supply = <®_cam_1v8>; | ||
| 103 | vaa-supply = <®_2p8v>; | ||
| 104 | |||
| 105 | port { | ||
| 106 | endpoint { | ||
| 107 | bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>; | ||
| 108 | link-frequencies = /bits/ 64 <384000000>; | ||
| 109 | remote-endpoint = <&mipi_csi_in>; | ||
| 110 | }; | ||
| 111 | }; | ||
| 112 | }; | ||
| 113 | }; | ||
| 114 | ... | ||
| @@ -68,12 +68,6 @@ properties: · 67 unmodified lines | |||
| 68 | marked GPIO_ACTIVE_LOW. | 68 | marked GPIO_ACTIVE_LOW. |
| 69 | maxItems: 1 | 69 | maxItems: 1 |
| 70 | 70 | ||
| 71 | rotation: | ||
| 72 | enum: | ||
| 73 | - 0 # Sensor Mounted Upright | ||
| 74 | - 180 # Sensor Mounted Upside Down | ||
| 75 | default: 0 | ||
| 76 | |||
| 77 | port: | 71 | port: |
| 78 | $ref: /schemas/graph.yaml#/$defs/port-base | 72 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 79 | additionalProperties: false | 73 | additionalProperties: false |
| @@ -114,7 +108,7 @@ required: · 34 unmodified lines | |||
| 114 | - reset-gpios | 108 | - reset-gpios |
| 115 | - port | 109 | - port |
| 116 | 110 | ||
| 117 | additionalProperties: false | 111 | unevaluatedProperties: false |
| 118 | 112 | ||
| 119 | examples: | 113 | examples: |
| 120 | - | | 114 | - | |
| @@ -52,10 +52,6 @@ properties: · 51 unmodified lines | |||
| 52 | description: | 52 | description: |
| 53 | GPIO connected to the reset pin (active low) | 53 | GPIO connected to the reset pin (active low) |
| 54 | 54 | ||
| 55 | orientation: true | ||
| 56 | |||
| 57 | rotation: true | ||
| 58 | |||
| 59 | port: | 55 | port: |
| 60 | $ref: /schemas/graph.yaml#/$defs/port-base | 56 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 61 | additionalProperties: false | 57 | additionalProperties: false |
| @@ -95,7 +91,7 @@ required: · 33 unmodified lines | |||
| 95 | - dvdd-supply | 91 | - dvdd-supply |
| 96 | - port | 92 | - port |
| 97 | 93 | ||
| 98 | additionalProperties: false | 94 | unevaluatedProperties: false |
| 99 | 95 | ||
| 100 | examples: | 96 | examples: |
| 101 | - | | 97 | - | |
| @@ -44,11 +44,6 @@ properties: · 43 unmodified lines | |||
| 44 | description: > | 44 | description: > |
| 45 | Reference to the GPIO connected to the reset pin, if any. | 45 | Reference to the GPIO connected to the reset pin, if any. |
| 46 | 46 | ||
| 47 | rotation: | ||
| 48 | enum: | ||
| 49 | - 0 | ||
| 50 | - 180 | ||
| 51 | |||
| 52 | port: | 47 | port: |
| 53 | description: Digital Output Port | 48 | description: Digital Output Port |
| 54 | $ref: /schemas/graph.yaml#/$defs/port-base | 49 | $ref: /schemas/graph.yaml#/$defs/port-base |
| @@ -85,7 +80,7 @@ required: · 30 unmodified lines | |||
| 85 | - DOVDD-supply | 80 | - DOVDD-supply |
| 86 | - port | 81 | - port |
| 87 | 82 | ||
| 88 | additionalProperties: false | 83 | unevaluatedProperties: false |
| 89 | 84 | ||
| 90 | examples: | 85 | examples: |
| 91 | - | | 86 | - | |
| @@ -0,0 +1,141 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/media/i2c/ovti,ov5642.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: OmniVision OV5642 Image Sensor | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Fabio Estevam <festevam@gmail.com> | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: /schemas/media/video-interface-devices.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | const: ovti,ov5642 | ||
| 18 | |||
| 19 | reg: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | clocks: | ||
| 23 | description: XCLK Input Clock | ||
| 24 | |||
| 25 | AVDD-supply: | ||
| 26 | description: Analog voltage supply, 2.8V. | ||
| 27 | |||
| 28 | DVDD-supply: | ||
| 29 | description: Digital core voltage supply, 1.5V. | ||
| 30 | |||
| 31 | DOVDD-supply: | ||
| 32 | description: Digital I/O voltage supply, 1.8V. | ||
| 33 | |||
| 34 | powerdown-gpios: | ||
| 35 | maxItems: 1 | ||
| 36 | description: Reference to the GPIO connected to the powerdown pin, if any. | ||
| 37 | |||
| 38 | reset-gpios: | ||
| 39 | maxItems: 1 | ||
| 40 | description: Reference to the GPIO connected to the reset pin, if any. | ||
| 41 | |||
| 42 | port: | ||
| 43 | $ref: /schemas/graph.yaml#/$defs/port-base | ||
| 44 | description: | | ||
| 45 | Video output port. | ||
| 46 | |||
| 47 | properties: | ||
| 48 | endpoint: | ||
| 49 | $ref: /schemas/media/video-interfaces.yaml# | ||
| 50 | unevaluatedProperties: false | ||
| 51 | |||
| 52 | properties: | ||
| 53 | bus-type: | ||
| 54 | enum: [5, 6] | ||
| 55 | |||
| 56 | bus-width: | ||
| 57 | enum: [8, 10] | ||
| 58 | default: 10 | ||
| 59 | |||
| 60 | data-shift: | ||
| 61 | enum: [0, 2] | ||
| 62 | default: 0 | ||
| 63 | |||
| 64 | hsync-active: | ||
| 65 | enum: [0, 1] | ||
| 66 | default: 1 | ||
| 67 | |||
| 68 | vsync-active: | ||
| 69 | enum: [0, 1] | ||
| 70 | default: 1 | ||
| 71 | |||
| 72 | pclk-sample: | ||
| 73 | enum: [0, 1] | ||
| 74 | default: 1 | ||
| 75 | |||
| 76 | allOf: | ||
| 77 | - if: | ||
| 78 | properties: | ||
| 79 | bus-type: | ||
| 80 | const: 6 | ||
| 81 | then: | ||
| 82 | properties: | ||
| 83 | hsync-active: false | ||
| 84 | vsync-active: false | ||
| 85 | |||
| 86 | - if: | ||
| 87 | properties: | ||
| 88 | bus-width: | ||
| 89 | const: 10 | ||
| 90 | then: | ||
| 91 | properties: | ||
| 92 | data-shift: | ||
| 93 | const: 0 | ||
| 94 | |||
| 95 | required: | ||
| 96 | - bus-type | ||
| 97 | |||
| 98 | additionalProperties: false | ||
| 99 | |||
| 100 | required: | ||
| 101 | - compatible | ||
| 102 | - reg | ||
| 103 | - clocks | ||
| 104 | - port | ||
| 105 | |||
| 106 | additionalProperties: false | ||
| 107 | |||
| 108 | examples: | ||
| 109 | - | | ||
| 110 | #include <dt-bindings/gpio/gpio.h> | ||
| 111 | #include <dt-bindings/media/video-interfaces.h> | ||
| 112 | |||
| 113 | i2c { | ||
| 114 | #address-cells = <1>; | ||
| 115 | #size-cells = <0>; | ||
| 116 | |||
| 117 | camera@3c { | ||
| 118 | compatible = "ovti,ov5642"; | ||
| 119 | reg = <0x3c>; | ||
| 120 | pinctrl-names = "default"; | ||
| 121 | pinctrl-0 = <&pinctrl_ov5642>; | ||
| 122 | clocks = <&clk_ext_camera>; | ||
| 123 | DOVDD-supply = <&vgen4_reg>; | ||
| 124 | AVDD-supply = <&vgen3_reg>; | ||
| 125 | DVDD-supply = <&vgen2_reg>; | ||
| 126 | powerdown-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>; | ||
| 127 | reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; | ||
| 128 | |||
| 129 | port { | ||
| 130 | ov5642_to_parallel: endpoint { | ||
| 131 | bus-type = <MEDIA_BUS_TYPE_PARALLEL>; | ||
| 132 | remote-endpoint = <¶llel_from_ov5642>; | ||
| 133 | bus-width = <8>; | ||
| 134 | data-shift = <2>; /* lines 9:2 are used */ | ||
| 135 | hsync-active = <0>; | ||
| 136 | vsync-active = <0>; | ||
| 137 | pclk-sample = <1>; | ||
| 138 | }; | ||
| 139 | }; | ||
| 140 | }; | ||
| 141 | }; | ||
| @@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | |||
| 8 | title: Omnivision OV5693/OV5695 CMOS Sensors | 8 | title: Omnivision OV5693/OV5695 CMOS Sensors |
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Tommaso Merciai <tommaso.merciai@amarulasolutions.com> | 11 | - Tommaso Merciai <tomm.merciai@gmail.com> |
| 12 | 12 | ||
| 13 | description: | | 13 | description: | |
| 14 | The Omnivision OV5693/OV5695 are high performance, 1/4-inch, 5 megapixel, CMOS | 14 | The Omnivision OV5693/OV5695 are high performance, 1/4-inch, 5 megapixel, CMOS |
| @@ -91,7 +91,7 @@ required: · 90 unmodified lines | |||
| 91 | - vddd-supply | 91 | - vddd-supply |
| 92 | - port | 92 | - port |
| 93 | 93 | ||
| 94 | additionalProperties: false | 94 | unevaluatedProperties: false |
| 95 | 95 | ||
| 96 | examples: | 96 | examples: |
| 97 | - | | 97 | - | |
| @@ -44,14 +44,6 @@ properties: · 43 unmodified lines | |||
| 44 | description: Sensor reset (XCLR) GPIO | 44 | description: Sensor reset (XCLR) GPIO |
| 45 | maxItems: 1 | 45 | maxItems: 1 |
| 46 | 46 | ||
| 47 | flash-leds: true | ||
| 48 | |||
| 49 | lens-focus: true | ||
| 50 | |||
| 51 | orientation: true | ||
| 52 | |||
| 53 | rotation: true | ||
| 54 | |||
| 55 | port: | 47 | port: |
| 56 | $ref: /schemas/graph.yaml#/$defs/port-base | 48 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 57 | unevaluatedProperties: false | 49 | unevaluatedProperties: false |
| @@ -89,7 +81,7 @@ required: · 31 unmodified lines | |||
| 89 | - ovdd-supply | 81 | - ovdd-supply |
| 90 | - port | 82 | - port |
| 91 | 83 | ||
| 92 | additionalProperties: false | 84 | unevaluatedProperties: false |
| 93 | 85 | ||
| 94 | examples: | 86 | examples: |
| 95 | - | | 87 | - | |
| @@ -1,20 +0,0 @@ | |||
| 1 | Device-Tree bindings for LIRC TX driver for Nokia N900(RX51) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: should be "nokia,n900-ir". | ||
| 5 | - pwms: specifies PWM used for IR signal transmission. | ||
| 6 | |||
| 7 | Example node: | ||
| 8 | |||
| 9 | pwm9: dmtimer-pwm@9 { | ||
| 10 | compatible = "ti,omap-dmtimer-pwm"; | ||
| 11 | ti,timers = <&timer9>; | ||
| 12 | ti,clock-source = <0x00>; /* timer_sys_ck */ | ||
| 13 | #pwm-cells = <3>; | ||
| 14 | }; | ||
| 15 | |||
| 16 | ir: n900-ir { | ||
| 17 | compatible = "nokia,n900-ir"; | ||
| 18 | |||
| 19 | pwms = <&pwm9 0 26316 0>; /* 38000 Hz */ | ||
| 20 | }; | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/media/nuvoton,npcm-ece.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Nuvoton NPCM Encoding Compression Engine | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Joseph Liu <kwliu@nuvoton.com> | ||
| 11 | - Marvin Lin <kflin@nuvoton.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | Video Encoding Compression Engine (ECE) present on Nuvoton NPCM SoCs. | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | enum: | ||
| 19 | - nuvoton,npcm750-ece | ||
| 20 | - nuvoton,npcm845-ece | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | resets: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | required: | ||
| 29 | - compatible | ||
| 30 | - reg | ||
| 31 | - resets | ||
| 32 | |||
| 33 | additionalProperties: false | ||
| 34 | |||
| 35 | examples: | ||
| 36 | - | | ||
| 37 | #include <dt-bindings/reset/nuvoton,npcm7xx-reset.h> | ||
| 38 | |||
| 39 | ece: video-codec@f0820000 { | ||
| 40 | compatible = "nuvoton,npcm750-ece"; | ||
| 41 | reg = <0xf0820000 0x2000>; | ||
| 42 | resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_ECE>; | ||
| 43 | }; | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/media/nuvoton,npcm-vcd.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Nuvoton NPCM Video Capture/Differentiation Engine | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Joseph Liu <kwliu@nuvoton.com> | ||
| 11 | - Marvin Lin <kflin@nuvoton.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | Video Capture/Differentiation Engine (VCD) present on Nuvoton NPCM SoCs. | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | enum: | ||
| 19 | - nuvoton,npcm750-vcd | ||
| 20 | - nuvoton,npcm845-vcd | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | interrupts: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | resets: | ||
| 29 | maxItems: 1 | ||
| 30 | |||
| 31 | nuvoton,sysgcr: | ||
| 32 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 33 | description: phandle to access GCR (Global Control Register) registers. | ||
| 34 | |||
| 35 | nuvoton,sysgfxi: | ||
| 36 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 37 | description: phandle to access GFXI (Graphics Core Information) registers. | ||
| 38 | |||
| 39 | nuvoton,ece: | ||
| 40 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 41 | description: phandle to access ECE (Encoding Compression Engine) registers. | ||
| 42 | |||
| 43 | memory-region: | ||
| 44 | maxItems: 1 | ||
| 45 | description: | ||
| 46 | CMA pool to use for buffers allocation instead of the default CMA pool. | ||
| 47 | |||
| 48 | required: | ||
| 49 | - compatible | ||
| 50 | - reg | ||
| 51 | - interrupts | ||
| 52 | - resets | ||
| 53 | - nuvoton,sysgcr | ||
| 54 | - nuvoton,sysgfxi | ||
| 55 | - nuvoton,ece | ||
| 56 | |||
| 57 | additionalProperties: false | ||
| 58 | |||
| 59 | examples: | ||
| 60 | - | | ||
| 61 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 62 | #include <dt-bindings/reset/nuvoton,npcm7xx-reset.h> | ||
| 63 | |||
| 64 | vcd: vcd@f0810000 { | ||
| 65 | compatible = "nuvoton,npcm750-vcd"; | ||
| 66 | reg = <0xf0810000 0x10000>; | ||
| 67 | interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; | ||
| 68 | resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_VCD>; | ||
| 69 | nuvoton,sysgcr = <&gcr>; | ||
| 70 | nuvoton,sysgfxi = <&gfxi>; | ||
| 71 | nuvoton,ece = <&ece>; | ||
| 72 | }; | ||
| @@ -48,6 +48,14 @@ properties: · 47 unmodified lines | |||
| 48 | iommus: | 48 | iommus: |
| 49 | maxItems: 2 | 49 | maxItems: 2 |
| 50 | 50 | ||
| 51 | interconnects: | ||
| 52 | maxItems: 2 | ||
| 53 | |||
| 54 | interconnect-names: | ||
| 55 | items: | ||
| 56 | - const: video-mem | ||
| 57 | - const: cpu-cfg | ||
| 58 | |||
| 51 | operating-points-v2: true | 59 | operating-points-v2: true |
| 52 | opp-table: | 60 | opp-table: |
| 53 | type: object | 61 | type: object |
| @@ -68,6 +68,13 @@ properties: · 67 unmodified lines | |||
| 68 | iommus: | 68 | iommus: |
| 69 | maxItems: 1 | 69 | maxItems: 1 |
| 70 | 70 | ||
| 71 | resets: | ||
| 72 | items: | ||
| 73 | - description: AXI reset line | ||
| 74 | - description: AXI bus interface unit reset line | ||
| 75 | - description: APB reset line | ||
| 76 | - description: APB bus interface unit reset line | ||
| 77 | |||
| 71 | required: | 78 | required: |
| 72 | - compatible | 79 | - compatible |
| 73 | - reg | 80 | - reg |
| @@ -75,13 +75,20 @@ properties: · 74 unmodified lines | |||
| 75 | power-domains: | 75 | power-domains: |
| 76 | maxItems: 1 | 76 | maxItems: 1 |
| 77 | 77 | ||
| 78 | samsung,pmu-syscon: | ||
| 79 | $ref: /schemas/types.yaml#/definitions/phandle | ||
| 80 | description: | ||
| 81 | Power Management Unit (PMU) system controller interface, used to | ||
| 82 | power/start the ISP. | ||
| 83 | |||
| 78 | patternProperties: | 84 | patternProperties: |
| 79 | "^pmu@[0-9a-f]+$": | 85 | "^pmu@[0-9a-f]+$": |
| 80 | type: object | 86 | type: object |
| 81 | additionalProperties: false | 87 | additionalProperties: false |
| 88 | deprecated: true | ||
| 82 | description: | 89 | description: |
| 83 | Node representing the SoC's Power Management Unit (duplicated with the | 90 | Node representing the SoC's Power Management Unit (duplicated with the |
| 84 | correct PMU node in the SoC). | 91 | correct PMU node in the SoC). Deprecated, use samsung,pmu-syscon. |
| 85 | 92 | ||
| 86 | properties: | 93 | properties: |
| 87 | reg: | 94 | reg: |
| @@ -131,6 +138,7 @@ required: · 43 unmodified lines | |||
| 131 | - clock-names | 138 | - clock-names |
| 132 | - interrupts | 139 | - interrupts |
| 133 | - ranges | 140 | - ranges |
| 141 | - samsung,pmu-syscon | ||
| 134 | - '#size-cells' | 142 | - '#size-cells' |
| 135 | 143 | ||
| 136 | additionalProperties: false | 144 | additionalProperties: false |
| @@ -179,15 +187,12 @@ examples: · 42 unmodified lines | |||
| 179 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; | 187 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; |
| 180 | iommu-names = "isp", "drc", "fd", "mcuctl"; | 188 | iommu-names = "isp", "drc", "fd", "mcuctl"; |
| 181 | power-domains = <&pd_isp>; | 189 | power-domains = <&pd_isp>; |
| 190 | samsung,pmu-syscon = <&pmu_system_controller>; | ||
| 182 | 191 | ||
| 183 | #address-cells = <1>; | 192 | #address-cells = <1>; |
| 184 | #size-cells = <1>; | 193 | #size-cells = <1>; |
| 185 | ranges; | 194 | ranges; |
| 186 | 195 | ||
| 187 | pmu@10020000 { | ||
| 188 | reg = <0x10020000 0x3000>; | ||
| 189 | }; | ||
| 190 | |||
| 191 | i2c-isp@12140000 { | 196 | i2c-isp@12140000 { |
| 192 | compatible = "samsung,exynos4212-i2c-isp"; | 197 | compatible = "samsung,exynos4212-i2c-isp"; |
| 193 | reg = <0x12140000 0x100>; | 198 | reg = <0x12140000 0x100>; |
| @@ -118,7 +118,7 @@ examples: · 117 unmodified lines | |||
| 118 | #clock-cells = <1>; | 118 | #clock-cells = <1>; |
| 119 | #address-cells = <1>; | 119 | #address-cells = <1>; |
| 120 | #size-cells = <1>; | 120 | #size-cells = <1>; |
| 121 | ranges = <0x0 0x0 0x18000000>; | 121 | ranges = <0x0 0x0 0xba1000>; |
| 122 | 122 | ||
| 123 | clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>, | 123 | clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>, |
| 124 | <&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>; | 124 | <&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>; |
| @@ -133,9 +133,9 @@ examples: · 8 unmodified lines | |||
| 133 | pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; | 133 | pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; |
| 134 | pinctrl-names = "default"; | 134 | pinctrl-names = "default"; |
| 135 | 135 | ||
| 136 | fimc@11800000 { | 136 | fimc@0 { |
| 137 | compatible = "samsung,exynos4212-fimc"; | 137 | compatible = "samsung,exynos4212-fimc"; |
| 138 | reg = <0x11800000 0x1000>; | 138 | reg = <0x00000000 0x1000>; |
| 139 | interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; | 139 | interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; |
| 140 | clocks = <&clock CLK_FIMC0>, | 140 | clocks = <&clock CLK_FIMC0>, |
| 141 | <&clock CLK_SCLK_FIMC0>; | 141 | <&clock CLK_SCLK_FIMC0>; |
| @@ -152,9 +152,9 @@ examples: · 10 unmodified lines | |||
| 152 | 152 | ||
| 153 | /* ... FIMC 1-3 */ | 153 | /* ... FIMC 1-3 */ |
| 154 | 154 | ||
| 155 | csis@11880000 { | 155 | csis@80000 { |
| 156 | compatible = "samsung,exynos4210-csis"; | 156 | compatible = "samsung,exynos4210-csis"; |
| 157 | reg = <0x11880000 0x4000>; | 157 | reg = <0x00080000 0x4000>; |
| 158 | interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; | 158 | interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; |
| 159 | clocks = <&clock CLK_CSIS0>, | 159 | clocks = <&clock CLK_CSIS0>, |
| 160 | <&clock CLK_SCLK_CSIS0>; | 160 | <&clock CLK_SCLK_CSIS0>; |
| @@ -187,9 +187,9 @@ examples: · 26 unmodified lines | |||
| 187 | 187 | ||
| 188 | /* ... CSIS 1 */ | 188 | /* ... CSIS 1 */ |
| 189 | 189 | ||
| 190 | fimc-lite@12390000 { | 190 | fimc-lite@b90000 { |
| 191 | compatible = "samsung,exynos4212-fimc-lite"; | 191 | compatible = "samsung,exynos4212-fimc-lite"; |
| 192 | reg = <0x12390000 0x1000>; | 192 | reg = <0xb90000 0x1000>; |
| 193 | interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; | 193 | interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; |
| 194 | power-domains = <&pd_isp>; | 194 | power-domains = <&pd_isp>; |
| 195 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>; | 195 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>; |
| @@ -199,9 +199,9 @@ examples: · 3 unmodified lines | |||
| 199 | 199 | ||
| 200 | /* ... FIMC-LITE 1 */ | 200 | /* ... FIMC-LITE 1 */ |
| 201 | 201 | ||
| 202 | fimc-is@12000000 { | 202 | fimc-is@800000 { |
| 203 | compatible = "samsung,exynos4212-fimc-is"; | 203 | compatible = "samsung,exynos4212-fimc-is"; |
| 204 | reg = <0x12000000 0x260000>; | 204 | reg = <0x00800000 0x260000>; |
| 205 | interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, | 205 | interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, |
| 206 | <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; | 206 | <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; |
| 207 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>, | 207 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>, |
| @@ -237,18 +237,15 @@ examples: · 29 unmodified lines | |||
| 237 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; | 237 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; |
| 238 | iommu-names = "isp", "drc", "fd", "mcuctl"; | 238 | iommu-names = "isp", "drc", "fd", "mcuctl"; |
| 239 | power-domains = <&pd_isp>; | 239 | power-domains = <&pd_isp>; |
| 240 | samsung,pmu-syscon = <&pmu_system_controller>; | ||
| 240 | 241 | ||
| 241 | #address-cells = <1>; | 242 | #address-cells = <1>; |
| 242 | #size-cells = <1>; | 243 | #size-cells = <1>; |
| 243 | ranges; | 244 | ranges; |
| 244 | 245 | ||
| 245 | pmu@10020000 { | 246 | i2c-isp@940000 { |
| 246 | reg = <0x10020000 0x3000>; | ||
| 247 | }; | ||
| 248 | |||
| 249 | i2c-isp@12140000 { | ||
| 250 | compatible = "samsung,exynos4212-i2c-isp"; | 247 | compatible = "samsung,exynos4212-i2c-isp"; |
| 251 | reg = <0x12140000 0x100>; | 248 | reg = <0x00940000 0x100>; |
| 252 | clocks = <&isp_clock CLK_ISP_I2C1_ISP>; | 249 | clocks = <&isp_clock CLK_ISP_I2C1_ISP>; |
| 253 | clock-names = "i2c_isp"; | 250 | clock-names = "i2c_isp"; |
| 254 | pinctrl-0 = <&fimc_is_i2c1>; | 251 | pinctrl-0 = <&fimc_is_i2c1>; |
| @@ -0,0 +1,100 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: TI J721E CSI2RX Shim | ||
| 8 | |||
| 9 | description: | | ||
| 10 | The TI J721E CSI2RX Shim is a wrapper around Cadence CSI2RX bridge that | ||
| 11 | enables sending captured frames to memory over PSI-L DMA. In the J721E | ||
| 12 | Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the | ||
| 13 | CSI_RX_IF section. | ||
| 14 | |||
| 15 | maintainers: | ||
| 16 | - Jai Luthra <j-luthra@ti.com> | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | const: ti,j721e-csi2rx-shim | ||
| 21 | |||
| 22 | dmas: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | dma-names: | ||
| 26 | items: | ||
| 27 | - const: rx0 | ||
| 28 | |||
| 29 | reg: | ||
| 30 | maxItems: 1 | ||
| 31 | |||
| 32 | power-domains: | ||
| 33 | maxItems: 1 | ||
| 34 | |||
| 35 | ranges: true | ||
| 36 | |||
| 37 | "#address-cells": true | ||
| 38 | |||
| 39 | "#size-cells": true | ||
| 40 | |||
| 41 | patternProperties: | ||
| 42 | "^csi-bridge@": | ||
| 43 | type: object | ||
| 44 | description: CSI2 bridge node. | ||
| 45 | $ref: cdns,csi2rx.yaml# | ||
| 46 | |||
| 47 | required: | ||
| 48 | - compatible | ||
| 49 | - reg | ||
| 50 | - dmas | ||
| 51 | - dma-names | ||
| 52 | - power-domains | ||
| 53 | - ranges | ||
| 54 | - "#address-cells" | ||
| 55 | - "#size-cells" | ||
| 56 | |||
| 57 | additionalProperties: false | ||
| 58 | |||
| 59 | examples: | ||
| 60 | - | | ||
| 61 | #include <dt-bindings/soc/ti,sci_pm_domain.h> | ||
| 62 | |||
| 63 | ti_csi2rx0: ticsi2rx@4500000 { | ||
| 64 | compatible = "ti,j721e-csi2rx-shim"; | ||
| 65 | dmas = <&main_udmap 0x4940>; | ||
| 66 | dma-names = "rx0"; | ||
| 67 | reg = <0x4500000 0x1000>; | ||
| 68 | power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>; | ||
| 69 | #address-cells = <1>; | ||
| 70 | #size-cells = <1>; | ||
| 71 | ranges; | ||
| 72 | |||
| 73 | cdns_csi2rx: csi-bridge@4504000 { | ||
| 74 | compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; | ||
| 75 | reg = <0x4504000 0x1000>; | ||
| 76 | clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>, | ||
| 77 | <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>; | ||
| 78 | clock-names = "sys_clk", "p_clk", "pixel_if0_clk", | ||
| 79 | "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; | ||
| 80 | phys = <&dphy0>; | ||
| 81 | phy-names = "dphy"; | ||
| 82 | |||
| 83 | ports { | ||
| 84 | #address-cells = <1>; | ||
| 85 | #size-cells = <0>; | ||
| 86 | |||
| 87 | csi2_0: port@0 { | ||
| 88 | |||
| 89 | reg = <0>; | ||
| 90 | |||
| 91 | csi2rx0_in_sensor: endpoint { | ||
| 92 | remote-endpoint = <&csi2_cam0>; | ||
| 93 | bus-type = <4>; /* CSI2 DPHY. */ | ||
| 94 | clock-lanes = <0>; | ||
| 95 | data-lanes = <1 2>; | ||
| 96 | }; | ||
| 97 | }; | ||
| 98 | }; | ||
| 99 | }; | ||
| 100 | }; | ||
| @@ -160,6 +160,7 @@ properties: · 159 unmodified lines | |||
| 160 | $ref: /schemas/types.yaml#/definitions/uint32-array | 160 | $ref: /schemas/types.yaml#/definitions/uint32-array |
| 161 | minItems: 1 | 161 | minItems: 1 |
| 162 | maxItems: 8 | 162 | maxItems: 8 |
| 163 | uniqueItems: true | ||
| 163 | items: | 164 | items: |
| 164 | # Assume up to 9 physical lane indices | 165 | # Assume up to 9 physical lane indices |
| 165 | maximum: 8 | 166 | maximum: 8 |
| @@ -0,0 +1,39 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/soc/nuvoton/nuvoton,gfxi.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Graphics Core Information block in Nuvoton SoCs | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Joseph Liu <kwliu@nuvoton.com> | ||
| 11 | - Marvin Lin <kflin@nuvoton.com> | ||
| 12 | |||
| 13 | description: | ||
| 14 | The Graphics Core Information (GFXI) are a block of registers in Nuvoton SoCs | ||
| 15 | that analyzes Graphics core behavior and provides information in registers. | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | items: | ||
| 20 | - enum: | ||
| 21 | - nuvoton,npcm750-gfxi | ||
| 22 | - nuvoton,npcm845-gfxi | ||
| 23 | - const: syscon | ||
| 24 | |||
| 25 | reg: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | required: | ||
| 29 | - compatible | ||
| 30 | - reg | ||
| 31 | |||
| 32 | additionalProperties: false | ||
| 33 | |||
| 34 | examples: | ||
| 35 | - | | ||
| 36 | gfxi: gfxi@e000 { | ||
| 37 | compatible = "nuvoton,npcm750-gfxi", "syscon"; | ||
| 38 | reg = <0xe000 0x100>; | ||
| 39 | }; | ||
| @@ -309,8 +309,6 @@ properties: · 308 unmodified lines | |||
| 309 | - nuvoton,w83773g | 309 | - nuvoton,w83773g |
| 310 | # OKI ML86V7667 video decoder | 310 | # OKI ML86V7667 video decoder |
| 311 | - oki,ml86v7667 | 311 | - oki,ml86v7667 |
| 312 | # OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus | ||
| 313 | - ovti,ov5642 | ||
| 314 | # 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch | 312 | # 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch |
| 315 | - plx,pex8648 | 313 | - plx,pex8648 |
| 316 | # Pulsedlight LIDAR range-finding sensor | 314 | # Pulsedlight LIDAR range-finding sensor |
| @@ -1,8 +1,14 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | .. _media_writing_camera_sensor_drivers: | ||
| 4 | |||
| 3 | Writing camera sensor drivers | 5 | Writing camera sensor drivers |
| 4 | ============================= | 6 | ============================= |
| 5 | 7 | ||
| 8 | This document covers the in-kernel APIs only. For the best practices on | ||
| 9 | userspace API implementation in camera sensor drivers, please see | ||
| 10 | :ref:`media_using_camera_sensor_drivers`. | ||
| 11 | |||
| 6 | CSI-2 and parallel (BT.601 and BT.656) busses | 12 | CSI-2 and parallel (BT.601 and BT.656) busses |
| 7 | --------------------------------------------- | 13 | --------------------------------------------- |
| 8 | 14 | ||
| @@ -13,7 +19,7 @@ Handling clocks · 4 unmodified lines | |||
| 13 | 19 | ||
| 14 | Camera sensors have an internal clock tree including a PLL and a number of | 20 | Camera sensors have an internal clock tree including a PLL and a number of |
| 15 | divisors. The clock tree is generally configured by the driver based on a few | 21 | divisors. The clock tree is generally configured by the driver based on a few |
| 16 | input parameters that are specific to the hardware:: the external clock frequency | 22 | input parameters that are specific to the hardware: the external clock frequency |
| 17 | and the link frequency. The two parameters generally are obtained from system | 23 | and the link frequency. The two parameters generally are obtained from system |
| 18 | firmware. **No other frequencies should be used in any circumstances.** | 24 | firmware. **No other frequencies should be used in any circumstances.** |
| 19 | 25 | ||
| @@ -32,110 +38,61 @@ can rely on this frequency being used. · 12 unmodified lines | |||
| 32 | Devicetree | 38 | Devicetree |
| 33 | ~~~~~~~~~~ | 39 | ~~~~~~~~~~ |
| 34 | 40 | ||
| 35 | The currently preferred way to achieve this is using ``assigned-clocks``, | 41 | The preferred way to achieve this is using ``assigned-clocks``, |
| 36 | ``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See | 42 | ``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See the |
| 37 | ``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more | 43 | `clock device tree bindings |
| 38 | information. The driver then gets the frequency using ``clk_get_rate()``. | 44 | <https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/clock/clock.yaml>`_ |
| 45 | for more information. The driver then gets the frequency using | ||
| 46 | ``clk_get_rate()``. | ||
| 39 | 47 | ||
| 40 | This approach has the drawback that there's no guarantee that the frequency | 48 | This approach has the drawback that there's no guarantee that the frequency |
| 41 | hasn't been modified directly or indirectly by another driver, or supported by | 49 | hasn't been modified directly or indirectly by another driver, or supported by |
| 42 | the board's clock tree to begin with. Changes to the Common Clock Framework API | 50 | the board's clock tree to begin with. Changes to the Common Clock Framework API |
| 43 | are required to ensure reliability. | 51 | are required to ensure reliability. |
| 44 | 52 | ||
| 45 | Frame size | ||
| 46 | ---------- | ||
| 47 | |||
| 48 | There are two distinct ways to configure the frame size produced by camera | ||
| 49 | sensors. | ||
| 50 | |||
| 51 | Freely configurable camera sensor drivers | ||
| 52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 53 | |||
| 54 | Freely configurable camera sensor drivers expose the device's internal | ||
| 55 | processing pipeline as one or more sub-devices with different cropping and | ||
| 56 | scaling configurations. The output size of the device is the result of a series | ||
| 57 | of cropping and scaling operations from the device's pixel array's size. | ||
| 58 | |||
| 59 | An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``). | ||
| 60 | |||
| 61 | Register list based drivers | ||
| 62 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 63 | |||
| 64 | Register list based drivers generally, instead of able to configure the device | ||
| 65 | they control based on user requests, are limited to a number of preset | ||
| 66 | configurations that combine a number of different parameters that on hardware | ||
| 67 | level are independent. How a driver picks such configuration is based on the | ||
| 68 | format set on a source pad at the end of the device's internal pipeline. | ||
| 69 | |||
| 70 | Most sensor drivers are implemented this way, see e.g. | ||
| 71 | ``drivers/media/i2c/imx319.c`` for an example. | ||
| 72 | |||
| 73 | Frame interval configuration | ||
| 74 | ---------------------------- | ||
| 75 | |||
| 76 | There are two different methods for obtaining possibilities for different frame | ||
| 77 | intervals as well as configuring the frame interval. Which one to implement | ||
| 78 | depends on the type of the device. | ||
| 79 | |||
| 80 | Raw camera sensors | ||
| 81 | ~~~~~~~~~~~~~~~~~~ | ||
| 82 | |||
| 83 | Instead of a high level parameter such as frame interval, the frame interval is | ||
| 84 | a result of the configuration of a number of camera sensor implementation | ||
| 85 | specific parameters. Luckily, these parameters tend to be the same for more or | ||
| 86 | less all modern raw camera sensors. | ||
| 87 | |||
| 88 | The frame interval is calculated using the following equation:: | ||
| 89 | |||
| 90 | frame interval = (analogue crop width + horizontal blanking) * | ||
| 91 | (analogue crop height + vertical blanking) / pixel rate | ||
| 92 | |||
| 93 | The formula is bus independent and is applicable for raw timing parameters on | ||
| 94 | large variety of devices beyond camera sensors. Devices that have no analogue | ||
| 95 | crop, use the full source image size, i.e. pixel array size. | ||
| 96 | |||
| 97 | Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and | ||
| 98 | ``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control | ||
| 99 | is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in | ||
| 100 | the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same | ||
| 101 | sub-device. The unit of that control is pixels per second. | ||
| 102 | |||
| 103 | Register list based drivers need to implement read-only sub-device nodes for the | ||
| 104 | purpose. Devices that are not register list based need these to configure the | ||
| 105 | device's internal processing pipeline. | ||
| 106 | |||
| 107 | The first entity in the linear pipeline is the pixel array. The pixel array may | ||
| 108 | be followed by other entities that are there to allow configuring binning, | ||
| 109 | skipping, scaling or digital crop :ref:`v4l2-subdev-selections`. | ||
| 110 | |||
| 111 | USB cameras etc. devices | ||
| 112 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 113 | |||
| 114 | USB video class hardware, as well as many cameras offering a similar higher | ||
| 115 | level interface natively, generally use the concept of frame interval (or frame | ||
| 116 | rate) on device level in firmware or hardware. This means lower level controls | ||
| 117 | implemented by raw cameras may not be used on uAPI (or even kAPI) to control the | ||
| 118 | frame interval on these devices. | ||
| 119 | |||
| 120 | Power management | 53 | Power management |
| 121 | ---------------- | 54 | ---------------- |
| 122 | 55 | ||
| 123 | Always use runtime PM to manage the power states of your device. Camera sensor | 56 | Camera sensors are used in conjunction with other devices to form a camera |
| 124 | drivers are in no way special in this respect: they are responsible for | 57 | pipeline. They must obey the rules listed herein to ensure coherent power |
| 125 | controlling the power state of the device they otherwise control as well. In | 58 | management over the pipeline. |
| 126 | general, the device must be powered on at least when its registers are being | 59 | |
| 127 | accessed and when it is streaming. | 60 | Camera sensor drivers are responsible for controlling the power state of the |
| 128 | 61 | device they otherwise control as well. They shall use runtime PM to manage | |
| 129 | Existing camera sensor drivers may rely on the old | 62 | power states. Runtime PM shall be enabled at probe time and disabled at remove |
| 130 | struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to | 63 | time. Drivers should enable runtime PM autosuspend. |
| 131 | manage their power state. This is however **deprecated**. If you feel you need | 64 | |
| 132 | to begin calling an s_power from an ISP or a bridge driver, instead please add | 65 | The runtime PM handlers shall handle clocks, regulators, GPIOs, and other |
| 133 | runtime PM support to the sensor driver you are using. Likewise, new drivers | 66 | system resources required to power the sensor up and down. For drivers that |
| 134 | should not use s_power. | 67 | don't use any of those resources (such as drivers that support ACPI systems |
| 135 | 68 | only), the runtime PM handlers may be left unimplemented. | |
| 136 | Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and | 69 | |
| 137 | ``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI | 70 | In general, the device shall be powered on at least when its registers are |
| 138 | and DT based systems. | 71 | being accessed and when it is streaming. Drivers should use |
| 72 | ``pm_runtime_resume_and_get()`` when starting streaming and | ||
| 73 | ``pm_runtime_put()`` or ``pm_runtime_put_autosuspend()`` when stopping | ||
| 74 | streaming. They may power the device up at probe time (for example to read | ||
| 75 | identification registers), but should not keep it powered unconditionally after | ||
| 76 | probe. | ||
| 77 | |||
| 78 | At system suspend time, the whole camera pipeline must stop streaming, and | ||
| 79 | restart when the system is resumed. This requires coordination between the | ||
| 80 | camera sensor and the rest of the camera pipeline. Bridge drivers are | ||
| 81 | responsible for this coordination, and instruct camera sensors to stop and | ||
| 82 | restart streaming by calling the appropriate subdev operations | ||
| 83 | (``.s_stream()``, ``.enable_streams()`` or ``.disable_streams()``). Camera | ||
| 84 | sensor drivers shall therefore **not** keep track of the streaming state to | ||
| 85 | stop streaming in the PM suspend handler and restart it in the resume handler. | ||
| 86 | Drivers should in general not implement the system PM handlers. | ||
| 87 | |||
| 88 | Camera sensor drivers shall **not** implement the subdev ``.s_power()`` | ||
| 89 | operation, as it is deprecated. While this operation is implemented in some | ||
| 90 | existing drivers as they predate the deprecation, new drivers shall use runtime | ||
| 91 | PM instead. If you feel you need to begin calling ``.s_power()`` from an ISP or | ||
| 92 | a bridge driver, instead add runtime PM support to the sensor driver you are | ||
| 93 | using and drop its ``.s_power()`` handler. | ||
| 94 | |||
| 95 | Please also see :ref:`examples <media-camera-sensor-examples>`. | ||
| 139 | 96 | ||
| 140 | Control framework | 97 | Control framework |
| 141 | ~~~~~~~~~~~~~~~~~ | 98 | ~~~~~~~~~~~~~~~~~ |
| @@ -155,21 +112,36 @@ access the device. · 13 unmodified lines | |||
| 155 | Rotation, orientation and flipping | 112 | Rotation, orientation and flipping |
| 156 | ---------------------------------- | 113 | ---------------------------------- |
| 157 | 114 | ||
| 158 | Some systems have the camera sensor mounted upside down compared to its natural | ||
| 159 | mounting rotation. In such cases, drivers shall expose the information to | ||
| 160 | userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION | ||
| 161 | <v4l2-camera-sensor-rotation>` control. | ||
| 162 | |||
| 163 | Sensor drivers shall also report the sensor's mounting orientation with the | ||
| 164 | :ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION <v4l2-camera-sensor-orientation>`. | ||
| 165 | |||
| 166 | Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation | 115 | Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation |
| 167 | information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to | 116 | information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to |
| 168 | register the appropriate controls. | 117 | register the appropriate controls. |
| 169 | 118 | ||
| 170 | Sensor drivers that have any vertical or horizontal flips embedded in the | 119 | .. _media-camera-sensor-examples: |
| 171 | register programming sequences shall initialize the V4L2_CID_HFLIP and | 120 | |
| 172 | V4L2_CID_VFLIP controls with the values programmed by the register sequences. | 121 | Example drivers |
| 173 | The default values of these controls shall be 0 (disabled). Especially these | 122 | --------------- |
| 174 | controls shall not be inverted, independently of the sensor's mounting | 123 | |
| 175 | rotation. | 124 | Features implemented by sensor drivers vary, and depending on the set of |
| 125 | supported features and other qualities, particular sensor drivers better serve | ||
| 126 | the purpose of an example. The following drivers are known to be good examples: | ||
| 127 | |||
| 128 | .. flat-table:: Example sensor drivers | ||
| 129 | :header-rows: 0 | ||
| 130 | :widths: 1 1 1 2 | ||
| 131 | |||
| 132 | * - Driver name | ||
| 133 | - File(s) | ||
| 134 | - Driver type | ||
| 135 | - Example topic | ||
| 136 | * - CCS | ||
| 137 | - ``drivers/media/i2c/ccs/`` | ||
| 138 | - Freely configurable | ||
| 139 | - Power management (ACPI and DT), UAPI | ||
| 140 | * - imx219 | ||
| 141 | - ``drivers/media/i2c/imx219.c`` | ||
| 142 | - Register list based | ||
| 143 | - Power management (DT), UAPI, mode selection | ||
| 144 | * - imx319 | ||
| 145 | - ``drivers/media/i2c/imx319.c`` | ||
| 146 | - Register list based | ||
| 147 | - Power management (ACPI and DT) | ||
| @@ -30,7 +30,7 @@ that purpose, selection target ``V4L2_SEL_TGT_COMPOSE`` is supported on the · 29 unmodified lines | |||
| 30 | sink pad (0). | 30 | sink pad (0). |
| 31 | 31 | ||
| 32 | Additionally, if a device has no scaler or digital crop functionality, the | 32 | Additionally, if a device has no scaler or digital crop functionality, the |
| 33 | source pad (1) expses another digital crop selection rectangle that can only | 33 | source pad (1) exposes another digital crop selection rectangle that can only |
| 34 | crop at the end of the lines and frames. | 34 | crop at the end of the lines and frames. |
| 35 | 35 | ||
| 36 | Scaler | 36 | Scaler |
| @@ -78,6 +78,14 @@ For SMIA (non-++) compliant devices the static data file name is · 41 unmodified lines | |||
| 78 | vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID | 78 | vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID |
| 79 | and rrrr or rr revision number. | 79 | and rrrr or rr revision number. |
| 80 | 80 | ||
| 81 | CCS tools | ||
| 82 | ~~~~~~~~~ | ||
| 83 | |||
| 84 | `CCS tools <https://github.com/MIPI-Alliance/ccs-tools/>`_ is a set of | ||
| 85 | tools for working with CCS static data files. CCS tools includes a | ||
| 86 | definition of the human-readable CCS static data YAML format and includes a | ||
| 87 | program to convert it to a binary. | ||
| 88 | |||
| 81 | Register definition generator | 89 | Register definition generator |
| 82 | ----------------------------- | 90 | ----------------------------- |
| 83 | 91 | ||
| @@ -13,7 +13,6 @@ Video4Linux devices · 12 unmodified lines | |||
| 13 | v4l2-subdev | 13 | v4l2-subdev |
| 14 | v4l2-event | 14 | v4l2-event |
| 15 | v4l2-controls | 15 | v4l2-controls |
| 16 | v4l2-videobuf | ||
| 17 | v4l2-videobuf2 | 16 | v4l2-videobuf2 |
| 18 | v4l2-dv-timings | 17 | v4l2-dv-timings |
| 19 | v4l2-flash-led-class | 18 | v4l2-flash-led-class |
| @@ -157,14 +157,6 @@ changing the e.g. exposure of the webcam. · 156 unmodified lines | |||
| 157 | Of course, you can always do all the locking yourself by leaving both lock | 157 | Of course, you can always do all the locking yourself by leaving both lock |
| 158 | pointers at ``NULL``. | 158 | pointers at ``NULL``. |
| 159 | 159 | ||
| 160 | If you use the old :ref:`videobuf framework <vb_framework>` then you must | ||
| 161 | pass the :c:type:`video_device`->lock to the videobuf queue initialize | ||
| 162 | function: if videobuf has to wait for a frame to arrive, then it will | ||
| 163 | temporarily unlock the lock and relock it afterwards. If your driver also | ||
| 164 | waits in the code, then you should do the same to allow other | ||
| 165 | processes to access the device node while the first process is waiting for | ||
| 166 | something. | ||
| 167 | |||
| 168 | In the case of :ref:`videobuf2 <vb2_framework>` you will need to implement the | 160 | In the case of :ref:`videobuf2 <vb2_framework>` you will need to implement the |
| 169 | ``wait_prepare()`` and ``wait_finish()`` callbacks to unlock/lock if applicable. | 161 | ``wait_prepare()`` and ``wait_finish()`` callbacks to unlock/lock if applicable. |
| 170 | If you use the ``queue->lock`` pointer, then you can use the helper functions | 162 | If you use the ``queue->lock`` pointer, then you can use the helper functions |
| @@ -1,403 +0,0 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | .. _vb_framework: | ||
| 4 | |||
| 5 | Videobuf Framework | ||
| 6 | ================== | ||
| 7 | |||
| 8 | Author: Jonathan Corbet <corbet@lwn.net> | ||
| 9 | |||
| 10 | Current as of 2.6.33 | ||
| 11 | |||
| 12 | .. note:: | ||
| 13 | |||
| 14 | The videobuf framework was deprecated in favor of videobuf2. Shouldn't | ||
| 15 | be used on new drivers. | ||
| 16 | |||
| 17 | Introduction | ||
| 18 | ------------ | ||
| 19 | |||
| 20 | The videobuf layer functions as a sort of glue layer between a V4L2 driver | ||
| 21 | and user space. It handles the allocation and management of buffers for | ||
| 22 | the storage of video frames. There is a set of functions which can be used | ||
| 23 | to implement many of the standard POSIX I/O system calls, including read(), | ||
| 24 | poll(), and, happily, mmap(). Another set of functions can be used to | ||
| 25 | implement the bulk of the V4L2 ioctl() calls related to streaming I/O, | ||
| 26 | including buffer allocation, queueing and dequeueing, and streaming | ||
| 27 | control. Using videobuf imposes a few design decisions on the driver | ||
| 28 | author, but the payback comes in the form of reduced code in the driver and | ||
| 29 | a consistent implementation of the V4L2 user-space API. | ||
| 30 | |||
| 31 | Buffer types | ||
| 32 | ------------ | ||
| 33 | |||
| 34 | Not all video devices use the same kind of buffers. In fact, there are (at | ||
| 35 | least) three common variations: | ||
| 36 | |||
| 37 | - Buffers which are scattered in both the physical and (kernel) virtual | ||
| 38 | address spaces. (Almost) all user-space buffers are like this, but it | ||
| 39 | makes great sense to allocate kernel-space buffers this way as well when | ||
| 40 | it is possible. Unfortunately, it is not always possible; working with | ||
| 41 | this kind of buffer normally requires hardware which can do | ||
| 42 | scatter/gather DMA operations. | ||
| 43 | |||
| 44 | - Buffers which are physically scattered, but which are virtually | ||
| 45 | contiguous; buffers allocated with vmalloc(), in other words. These | ||
| 46 | buffers are just as hard to use for DMA operations, but they can be | ||
| 47 | useful in situations where DMA is not available but virtually-contiguous | ||
| 48 | buffers are convenient. | ||
| 49 | |||
| 50 | - Buffers which are physically contiguous. Allocation of this kind of | ||
| 51 | buffer can be unreliable on fragmented systems, but simpler DMA | ||
| 52 | controllers cannot deal with anything else. | ||
| 53 | |||
| 54 | Videobuf can work with all three types of buffers, but the driver author | ||
| 55 | must pick one at the outset and design the driver around that decision. | ||
| 56 | |||
| 57 | [It's worth noting that there's a fourth kind of buffer: "overlay" buffers | ||
| 58 | which are located within the system's video memory. The overlay | ||
| 59 | functionality is considered to be deprecated for most use, but it still | ||
| 60 | shows up occasionally in system-on-chip drivers where the performance | ||
| 61 | benefits merit the use of this technique. Overlay buffers can be handled | ||
| 62 | as a form of scattered buffer, but there are very few implementations in | ||
| 63 | the kernel and a description of this technique is currently beyond the | ||
| 64 | scope of this document.] | ||
| 65 | |||
| 66 | Data structures, callbacks, and initialization | ||
| 67 | ---------------------------------------------- | ||
| 68 | |||
| 69 | Depending on which type of buffers are being used, the driver should | ||
| 70 | include one of the following files: | ||
| 71 | |||
| 72 | .. code-block:: none | ||
| 73 | |||
| 74 | <media/videobuf-dma-sg.h> /* Physically scattered */ | ||
| 75 | <media/videobuf-vmalloc.h> /* vmalloc() buffers */ | ||
| 76 | <media/videobuf-dma-contig.h> /* Physically contiguous */ | ||
| 77 | |||
| 78 | The driver's data structure describing a V4L2 device should include a | ||
| 79 | struct videobuf_queue instance for the management of the buffer queue, | ||
| 80 | along with a list_head for the queue of available buffers. There will also | ||
| 81 | need to be an interrupt-safe spinlock which is used to protect (at least) | ||
| 82 | the queue. | ||
| 83 | |||
| 84 | The next step is to write four simple callbacks to help videobuf deal with | ||
| 85 | the management of buffers: | ||
| 86 | |||
| 87 | .. code-block:: none | ||
| 88 | |||
| 89 | struct videobuf_queue_ops { | ||
| 90 | int (*buf_setup)(struct videobuf_queue *q, | ||
| 91 | unsigned int *count, unsigned int *size); | ||
| 92 | int (*buf_prepare)(struct videobuf_queue *q, | ||
| 93 | struct videobuf_buffer *vb, | ||
| 94 | enum v4l2_field field); | ||
| 95 | void (*buf_queue)(struct videobuf_queue *q, | ||
| 96 | struct videobuf_buffer *vb); | ||
| 97 | void (*buf_release)(struct videobuf_queue *q, | ||
| 98 | struct videobuf_buffer *vb); | ||
| 99 | }; | ||
| 100 | |||
| 101 | buf_setup() is called early in the I/O process, when streaming is being | ||
| 102 | initiated; its purpose is to tell videobuf about the I/O stream. The count | ||
| 103 | parameter will be a suggested number of buffers to use; the driver should | ||
| 104 | check it for rationality and adjust it if need be. As a practical rule, a | ||
| 105 | minimum of two buffers are needed for proper streaming, and there is | ||
| 106 | usually a maximum (which cannot exceed 32) which makes sense for each | ||
| 107 | device. The size parameter should be set to the expected (maximum) size | ||
| 108 | for each frame of data. | ||
| 109 | |||
| 110 | Each buffer (in the form of a struct videobuf_buffer pointer) will be | ||
| 111 | passed to buf_prepare(), which should set the buffer's size, width, height, | ||
| 112 | and field fields properly. If the buffer's state field is | ||
| 113 | VIDEOBUF_NEEDS_INIT, the driver should pass it to: | ||
| 114 | |||
| 115 | .. code-block:: none | ||
| 116 | |||
| 117 | int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, | ||
| 118 | struct v4l2_framebuffer *fbuf); | ||
| 119 | |||
| 120 | Among other things, this call will usually allocate memory for the buffer. | ||
| 121 | Finally, the buf_prepare() function should set the buffer's state to | ||
| 122 | VIDEOBUF_PREPARED. | ||
| 123 | |||
| 124 | When a buffer is queued for I/O, it is passed to buf_queue(), which should | ||
| 125 | put it onto the driver's list of available buffers and set its state to | ||
| 126 | VIDEOBUF_QUEUED. Note that this function is called with the queue spinlock | ||
| 127 | held; if it tries to acquire it as well things will come to a screeching | ||
| 128 | halt. Yes, this is the voice of experience. Note also that videobuf may | ||
| 129 | wait on the first buffer in the queue; placing other buffers in front of it | ||
| 130 | could again gum up the works. So use list_add_tail() to enqueue buffers. | ||
| 131 | |||
| 132 | Finally, buf_release() is called when a buffer is no longer intended to be | ||
| 133 | used. The driver should ensure that there is no I/O active on the buffer, | ||
| 134 | then pass it to the appropriate free routine(s): | ||
| 135 | |||
| 136 | .. code-block:: none | ||
| 137 | |||
| 138 | /* Scatter/gather drivers */ | ||
| 139 | int videobuf_dma_unmap(struct videobuf_queue *q, | ||
| 140 | struct videobuf_dmabuf *dma); | ||
| 141 | int videobuf_dma_free(struct videobuf_dmabuf *dma); | ||
| 142 | |||
| 143 | /* vmalloc drivers */ | ||
| 144 | void videobuf_vmalloc_free (struct videobuf_buffer *buf); | ||
| 145 | |||
| 146 | /* Contiguous drivers */ | ||
| 147 | void videobuf_dma_contig_free(struct videobuf_queue *q, | ||
| 148 | struct videobuf_buffer *buf); | ||
| 149 | |||
| 150 | One way to ensure that a buffer is no longer under I/O is to pass it to: | ||
| 151 | |||
| 152 | .. code-block:: none | ||
| 153 | |||
| 154 | int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); | ||
| 155 | |||
| 156 | Here, vb is the buffer, non_blocking indicates whether non-blocking I/O | ||
| 157 | should be used (it should be zero in the buf_release() case), and intr | ||
| 158 | controls whether an interruptible wait is used. | ||
| 159 | |||
| 160 | File operations | ||
| 161 | --------------- | ||
| 162 | |||
| 163 | At this point, much of the work is done; much of the rest is slipping | ||
| 164 | videobuf calls into the implementation of the other driver callbacks. The | ||
| 165 | first step is in the open() function, which must initialize the | ||
| 166 | videobuf queue. The function to use depends on the type of buffer used: | ||
| 167 | |||
| 168 | .. code-block:: none | ||
| 169 | |||
| 170 | void videobuf_queue_sg_init(struct videobuf_queue *q, | ||
| 171 | struct videobuf_queue_ops *ops, | ||
| 172 | struct device *dev, | ||
| 173 | spinlock_t *irqlock, | ||
| 174 | enum v4l2_buf_type type, | ||
| 175 | enum v4l2_field field, | ||
| 176 | unsigned int msize, | ||
| 177 | void *priv); | ||
| 178 | |||
| 179 | void videobuf_queue_vmalloc_init(struct videobuf_queue *q, | ||
| 180 | struct videobuf_queue_ops *ops, | ||
| 181 | struct device *dev, | ||
| 182 | spinlock_t *irqlock, | ||
| 183 | enum v4l2_buf_type type, | ||
| 184 | enum v4l2_field field, | ||
| 185 | unsigned int msize, | ||
| 186 | void *priv); | ||
| 187 | |||
| 188 | void videobuf_queue_dma_contig_init(struct videobuf_queue *q, | ||
| 189 | struct videobuf_queue_ops *ops, | ||
| 190 | struct device *dev, | ||
| 191 | spinlock_t *irqlock, | ||
| 192 | enum v4l2_buf_type type, | ||
| 193 | enum v4l2_field field, | ||
| 194 | unsigned int msize, | ||
| 195 | void *priv); | ||
| 196 | |||
| 197 | In each case, the parameters are the same: q is the queue structure for the | ||
| 198 | device, ops is the set of callbacks as described above, dev is the device | ||
| 199 | structure for this video device, irqlock is an interrupt-safe spinlock to | ||
| 200 | protect access to the data structures, type is the buffer type used by the | ||
| 201 | device (cameras will use V4L2_BUF_TYPE_VIDEO_CAPTURE, for example), field | ||
| 202 | describes which field is being captured (often V4L2_FIELD_NONE for | ||
| 203 | progressive devices), msize is the size of any containing structure used | ||
| 204 | around struct videobuf_buffer, and priv is a private data pointer which | ||
| 205 | shows up in the priv_data field of struct videobuf_queue. Note that these | ||
| 206 | are void functions which, evidently, are immune to failure. | ||
| 207 | |||
| 208 | V4L2 capture drivers can be written to support either of two APIs: the | ||
| 209 | read() system call and the rather more complicated streaming mechanism. As | ||
| 210 | a general rule, it is necessary to support both to ensure that all | ||
| 211 | applications have a chance of working with the device. Videobuf makes it | ||
| 212 | easy to do that with the same code. To implement read(), the driver need | ||
| 213 | only make a call to one of: | ||
| 214 | |||
| 215 | .. code-block:: none | ||
| 216 | |||
| 217 | ssize_t videobuf_read_one(struct videobuf_queue *q, | ||
| 218 | char __user *data, size_t count, | ||
| 219 | loff_t *ppos, int nonblocking); | ||
| 220 | |||
| 221 | ssize_t videobuf_read_stream(struct videobuf_queue *q, | ||
| 222 | char __user *data, size_t count, | ||
| 223 | loff_t *ppos, int vbihack, int nonblocking); | ||
| 224 | |||
| 225 | Either one of these functions will read frame data into data, returning the | ||
| 226 | amount actually read; the difference is that videobuf_read_one() will only | ||
| 227 | read a single frame, while videobuf_read_stream() will read multiple frames | ||
| 228 | if they are needed to satisfy the count requested by the application. A | ||
| 229 | typical driver read() implementation will start the capture engine, call | ||
| 230 | one of the above functions, then stop the engine before returning (though a | ||
| 231 | smarter implementation might leave the engine running for a little while in | ||
| 232 | anticipation of another read() call happening in the near future). | ||
| 233 | |||
| 234 | The poll() function can usually be implemented with a direct call to: | ||
| 235 | |||
| 236 | .. code-block:: none | ||
| 237 | |||
| 238 | unsigned int videobuf_poll_stream(struct file *file, | ||
| 239 | struct videobuf_queue *q, | ||
| 240 | poll_table *wait); | ||
| 241 | |||
| 242 | Note that the actual wait queue eventually used will be the one associated | ||
| 243 | with the first available buffer. | ||
| 244 | |||
| 245 | When streaming I/O is done to kernel-space buffers, the driver must support | ||
| 246 | the mmap() system call to enable user space to access the data. In many | ||
| 247 | V4L2 drivers, the often-complex mmap() implementation simplifies to a | ||
| 248 | single call to: | ||
| 249 | |||
| 250 | .. code-block:: none | ||
| 251 | |||
| 252 | int videobuf_mmap_mapper(struct videobuf_queue *q, | ||
| 253 | struct vm_area_struct *vma); | ||
| 254 | |||
| 255 | Everything else is handled by the videobuf code. | ||
| 256 | |||
| 257 | The release() function requires two separate videobuf calls: | ||
| 258 | |||
| 259 | .. code-block:: none | ||
| 260 | |||
| 261 | void videobuf_stop(struct videobuf_queue *q); | ||
| 262 | int videobuf_mmap_free(struct videobuf_queue *q); | ||
| 263 | |||
| 264 | The call to videobuf_stop() terminates any I/O in progress - though it is | ||
| 265 | still up to the driver to stop the capture engine. The call to | ||
| 266 | videobuf_mmap_free() will ensure that all buffers have been unmapped; if | ||
| 267 | so, they will all be passed to the buf_release() callback. If buffers | ||
| 268 | remain mapped, videobuf_mmap_free() returns an error code instead. The | ||
| 269 | purpose is clearly to cause the closing of the file descriptor to fail if | ||
| 270 | buffers are still mapped, but every driver in the 2.6.32 kernel cheerfully | ||
| 271 | ignores its return value. | ||
| 272 | |||
| 273 | ioctl() operations | ||
| 274 | ------------------ | ||
| 275 | |||
| 276 | The V4L2 API includes a very long list of driver callbacks to respond to | ||
| 277 | the many ioctl() commands made available to user space. A number of these | ||
| 278 | - those associated with streaming I/O - turn almost directly into videobuf | ||
| 279 | calls. The relevant helper functions are: | ||
| 280 | |||
| 281 | .. code-block:: none | ||
| 282 | |||
| 283 | int videobuf_reqbufs(struct videobuf_queue *q, | ||
| 284 | struct v4l2_requestbuffers *req); | ||
| 285 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); | ||
| 286 | int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b); | ||
| 287 | int videobuf_dqbuf(struct videobuf_queue *q, struct v4l2_buffer *b, | ||
| 288 | int nonblocking); | ||
| 289 | int videobuf_streamon(struct videobuf_queue *q); | ||
| 290 | int videobuf_streamoff(struct videobuf_queue *q); | ||
| 291 | |||
| 292 | So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's | ||
| 293 | vidioc_reqbufs() callback which, in turn, usually only needs to locate the | ||
| 294 | proper struct videobuf_queue pointer and pass it to videobuf_reqbufs(). | ||
| 295 | These support functions can replace a great deal of buffer management | ||
| 296 | boilerplate in a lot of V4L2 drivers. | ||
| 297 | |||
| 298 | The vidioc_streamon() and vidioc_streamoff() functions will be a bit more | ||
| 299 | complex, of course, since they will also need to deal with starting and | ||
| 300 | stopping the capture engine. | ||
| 301 | |||
| 302 | Buffer allocation | ||
| 303 | ----------------- | ||
| 304 | |||
| 305 | Thus far, we have talked about buffers, but have not looked at how they are | ||
| 306 | allocated. The scatter/gather case is the most complex on this front. For | ||
| 307 | allocation, the driver can leave buffer allocation entirely up to the | ||
| 308 | videobuf layer; in this case, buffers will be allocated as anonymous | ||
| 309 | user-space pages and will be very scattered indeed. If the application is | ||
| 310 | using user-space buffers, no allocation is needed; the videobuf layer will | ||
| 311 | take care of calling get_user_pages() and filling in the scatterlist array. | ||
| 312 | |||
| 313 | If the driver needs to do its own memory allocation, it should be done in | ||
| 314 | the vidioc_reqbufs() function, *after* calling videobuf_reqbufs(). The | ||
| 315 | first step is a call to: | ||
| 316 | |||
| 317 | .. code-block:: none | ||
| 318 | |||
| 319 | struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); | ||
| 320 | |||
| 321 | The returned videobuf_dmabuf structure (defined in | ||
| 322 | <media/videobuf-dma-sg.h>) includes a couple of relevant fields: | ||
| 323 | |||
| 324 | .. code-block:: none | ||
| 325 | |||
| 326 | struct scatterlist *sglist; | ||
| 327 | int sglen; | ||
| 328 | |||
| 329 | The driver must allocate an appropriately-sized scatterlist array and | ||
| 330 | populate it with pointers to the pieces of the allocated buffer; sglen | ||
| 331 | should be set to the length of the array. | ||
| 332 | |||
| 333 | Drivers using the vmalloc() method need not (and cannot) concern themselves | ||
| 334 | with buffer allocation at all; videobuf will handle those details. The | ||
| 335 | same is normally true of contiguous-DMA drivers as well; videobuf will | ||
| 336 | allocate the buffers (with dma_alloc_coherent()) when it sees fit. That | ||
| 337 | means that these drivers may be trying to do high-order allocations at any | ||
| 338 | time, an operation which is not always guaranteed to work. Some drivers | ||
| 339 | play tricks by allocating DMA space at system boot time; videobuf does not | ||
| 340 | currently play well with those drivers. | ||
| 341 | |||
| 342 | As of 2.6.31, contiguous-DMA drivers can work with a user-supplied buffer, | ||
| 343 | as long as that buffer is physically contiguous. Normal user-space | ||
| 344 | allocations will not meet that criterion, but buffers obtained from other | ||
| 345 | kernel drivers, or those contained within huge pages, will work with these | ||
| 346 | drivers. | ||
| 347 | |||
| 348 | Filling the buffers | ||
| 349 | ------------------- | ||
| 350 | |||
| 351 | The final part of a videobuf implementation has no direct callback - it's | ||
| 352 | the portion of the code which actually puts frame data into the buffers, | ||
| 353 | usually in response to interrupts from the device. For all types of | ||
| 354 | drivers, this process works approximately as follows: | ||
| 355 | |||
| 356 | - Obtain the next available buffer and make sure that somebody is actually | ||
| 357 | waiting for it. | ||
| 358 | |||
| 359 | - Get a pointer to the memory and put video data there. | ||
| 360 | |||
| 361 | - Mark the buffer as done and wake up the process waiting for it. | ||
| 362 | |||
| 363 | Step (1) above is done by looking at the driver-managed list_head structure | ||
| 364 | - the one which is filled in the buf_queue() callback. Because starting | ||
| 365 | the engine and enqueueing buffers are done in separate steps, it's possible | ||
| 366 | for the engine to be running without any buffers available - in the | ||
| 367 | vmalloc() case especially. So the driver should be prepared for the list | ||
| 368 | to be empty. It is equally possible that nobody is yet interested in the | ||
| 369 | buffer; the driver should not remove it from the list or fill it until a | ||
| 370 | process is waiting on it. That test can be done by examining the buffer's | ||
| 371 | done field (a wait_queue_head_t structure) with waitqueue_active(). | ||
| 372 | |||
| 373 | A buffer's state should be set to VIDEOBUF_ACTIVE before being mapped for | ||
| 374 | DMA; that ensures that the videobuf layer will not try to do anything with | ||
| 375 | it while the device is transferring data. | ||
| 376 | |||
| 377 | For scatter/gather drivers, the needed memory pointers will be found in the | ||
| 378 | scatterlist structure described above. Drivers using the vmalloc() method | ||
| 379 | can get a memory pointer with: | ||
| 380 | |||
| 381 | .. code-block:: none | ||
| 382 | |||
| 383 | void *videobuf_to_vmalloc(struct videobuf_buffer *buf); | ||
| 384 | |||
| 385 | For contiguous DMA drivers, the function to use is: | ||
| 386 | |||
| 387 | .. code-block:: none | ||
| 388 | |||
| 389 | dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); | ||
| 390 | |||
| 391 | The contiguous DMA API goes out of its way to hide the kernel-space address | ||
| 392 | of the DMA buffer from drivers. | ||
| 393 | |||
| 394 | The final step is to set the size field of the relevant videobuf_buffer | ||
| 395 | structure to the actual size of the captured image, set state to | ||
| 396 | VIDEOBUF_DONE, then call wake_up() on the done queue. At this point, the | ||
| 397 | buffer is owned by the videobuf layer and the driver should not touch it | ||
| 398 | again. | ||
| 399 | |||
| 400 | Developers who are interested in more information can go into the relevant | ||
| 401 | header files; there are a few low-level functions declared there which have | ||
| 402 | not been talked about here. Note also that all of these calls are exported | ||
| 403 | GPL-only, so they will not be available to non-GPL kernel modules. | ||
| @@ -768,18 +768,6 @@ const char *video_device_node_name(struct video_device *vdev); · 767 unmodified lines | |||
| 768 | 此功能,而非访问 video_device::num 和 video_device::minor 域。 | 768 | 此功能,而非访问 video_device::num 和 video_device::minor 域。 |
| 769 | 769 | ||
| 770 | 770 | ||
| 771 | 视频缓冲辅助函数 | ||
| 772 | --------------- | ||
| 773 | |||
| 774 | v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videobuf”)。 | ||
| 775 | 这些方法使驱动可以通过统一的方式实现 read()、mmap() 和 overlay()。 | ||
| 776 | 目前在设备上支持视频缓冲的方法有分散/聚集 DMA(videobuf-dma-sg)、 | ||
| 777 | 线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc | ||
| 778 | 分配的缓冲(videobuf-vmalloc)。 | ||
| 779 | |||
| 780 | 请参阅 Documentation/driver-api/media/v4l2-videobuf.rst,以获得更多关于 videobuf | ||
| 781 | 层的使用信息。 | ||
| 782 | |||
| 783 | v4l2_fh 结构体 | 771 | v4l2_fh 结构体 |
| 784 | ------------- | 772 | ------------- |
| 785 | 773 | ||
| @@ -0,0 +1,104 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | .. _media_using_camera_sensor_drivers: | ||
| 4 | |||
| 5 | Using camera sensor drivers | ||
| 6 | =========================== | ||
| 7 | |||
| 8 | This section describes common practices for how the V4L2 sub-device interface is | ||
| 9 | used to control the camera sensor drivers. | ||
| 10 | |||
| 11 | You may also find :ref:`media_writing_camera_sensor_drivers` useful. | ||
| 12 | |||
| 13 | Frame size | ||
| 14 | ---------- | ||
| 15 | |||
| 16 | There are two distinct ways to configure the frame size produced by camera | ||
| 17 | sensors. | ||
| 18 | |||
| 19 | Freely configurable camera sensor drivers | ||
| 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 21 | |||
| 22 | Freely configurable camera sensor drivers expose the device's internal | ||
| 23 | processing pipeline as one or more sub-devices with different cropping and | ||
| 24 | scaling configurations. The output size of the device is the result of a series | ||
| 25 | of cropping and scaling operations from the device's pixel array's size. | ||
| 26 | |||
| 27 | An example of such a driver is the CCS driver. | ||
| 28 | |||
| 29 | Register list based drivers | ||
| 30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 31 | |||
| 32 | Register list based drivers generally, instead of able to configure the device | ||
| 33 | they control based on user requests, are limited to a number of preset | ||
| 34 | configurations that combine a number of different parameters that on hardware | ||
| 35 | level are independent. How a driver picks such configuration is based on the | ||
| 36 | format set on a source pad at the end of the device's internal pipeline. | ||
| 37 | |||
| 38 | Most sensor drivers are implemented this way. | ||
| 39 | |||
| 40 | Frame interval configuration | ||
| 41 | ---------------------------- | ||
| 42 | |||
| 43 | There are two different methods for obtaining possibilities for different frame | ||
| 44 | intervals as well as configuring the frame interval. Which one to implement | ||
| 45 | depends on the type of the device. | ||
| 46 | |||
| 47 | Raw camera sensors | ||
| 48 | ~~~~~~~~~~~~~~~~~~ | ||
| 49 | |||
| 50 | Instead of a high level parameter such as frame interval, the frame interval is | ||
| 51 | a result of the configuration of a number of camera sensor implementation | ||
| 52 | specific parameters. Luckily, these parameters tend to be the same for more or | ||
| 53 | less all modern raw camera sensors. | ||
| 54 | |||
| 55 | The frame interval is calculated using the following equation:: | ||
| 56 | |||
| 57 | frame interval = (analogue crop width + horizontal blanking) * | ||
| 58 | (analogue crop height + vertical blanking) / pixel rate | ||
| 59 | |||
| 60 | The formula is bus independent and is applicable for raw timing parameters on | ||
| 61 | large variety of devices beyond camera sensors. Devices that have no analogue | ||
| 62 | crop, use the full source image size, i.e. pixel array size. | ||
| 63 | |||
| 64 | Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and | ||
| 65 | ``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control | ||
| 66 | is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in | ||
| 67 | the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same | ||
| 68 | sub-device. The unit of that control is pixels per second. | ||
| 69 | |||
| 70 | Register list based drivers need to implement read-only sub-device nodes for the | ||
| 71 | purpose. Devices that are not register list based need these to configure the | ||
| 72 | device's internal processing pipeline. | ||
| 73 | |||
| 74 | The first entity in the linear pipeline is the pixel array. The pixel array may | ||
| 75 | be followed by other entities that are there to allow configuring binning, | ||
| 76 | skipping, scaling or digital crop, see :ref:`VIDIOC_SUBDEV_G_SELECTION | ||
| 77 | <VIDIOC_SUBDEV_G_SELECTION>`. | ||
| 78 | |||
| 79 | USB cameras etc. devices | ||
| 80 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 81 | |||
| 82 | USB video class hardware, as well as many cameras offering a similar higher | ||
| 83 | level interface natively, generally use the concept of frame interval (or frame | ||
| 84 | rate) on device level in firmware or hardware. This means lower level controls | ||
| 85 | implemented by raw cameras may not be used on uAPI (or even kAPI) to control the | ||
| 86 | frame interval on these devices. | ||
| 87 | |||
| 88 | Rotation, orientation and flipping | ||
| 89 | ---------------------------------- | ||
| 90 | |||
| 91 | Some systems have the camera sensor mounted upside down compared to its natural | ||
| 92 | mounting rotation. In such cases, drivers shall expose the information to | ||
| 93 | userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION | ||
| 94 | <v4l2-camera-sensor-rotation>` control. | ||
| 95 | |||
| 96 | Sensor drivers shall also report the sensor's mounting orientation with the | ||
| 97 | :ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION <v4l2-camera-sensor-orientation>`. | ||
| 98 | |||
| 99 | Sensor drivers that have any vertical or horizontal flips embedded in the | ||
| 100 | register programming sequences shall initialize the :ref:`V4L2_CID_HFLIP | ||
| 101 | <v4l2-cid-hflip>` and :ref:`V4L2_CID_VFLIP <v4l2-cid-vflip>` controls with the | ||
| 102 | values programmed by the register sequences. The default values of these | ||
| 103 | controls shall be 0 (disabled). Especially these controls shall not be inverted, | ||
| 104 | independently of the sensor's mounting rotation. | ||
| @@ -32,11 +32,13 @@ For more details see the file COPYING in the source distribution of Linux. · 31 unmodified lines | |||
| 32 | :numbered: | 32 | :numbered: |
| 33 | 33 | ||
| 34 | aspeed-video | 34 | aspeed-video |
| 35 | camera-sensor | ||
| 35 | ccs | 36 | ccs |
| 36 | cx2341x-uapi | 37 | cx2341x-uapi |
| 37 | dw100 | 38 | dw100 |
| 38 | imx-uapi | 39 | imx-uapi |
| 39 | max2175 | 40 | max2175 |
| 41 | npcm-video | ||
| 40 | omap3isp-uapi | 42 | omap3isp-uapi |
| 41 | st-vgxy61 | 43 | st-vgxy61 |
| 42 | uvcvideo | 44 | uvcvideo |
| @@ -0,0 +1,66 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | .. include:: <isonum.txt> | ||
| 4 | |||
| 5 | NPCM video driver | ||
| 6 | ================= | ||
| 7 | |||
| 8 | This driver is used to control the Video Capture/Differentiation (VCD) engine | ||
| 9 | and Encoding Compression Engine (ECE) present on Nuvoton NPCM SoCs. The VCD can | ||
| 10 | capture a frame from digital video input and compare two frames in memory, and | ||
| 11 | the ECE can compress the frame data into HEXTILE format. | ||
| 12 | |||
| 13 | Driver-specific Controls | ||
| 14 | ------------------------ | ||
| 15 | |||
| 16 | V4L2_CID_NPCM_CAPTURE_MODE | ||
| 17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 18 | |||
| 19 | The VCD engine supports two modes: | ||
| 20 | |||
| 21 | - COMPLETE mode: | ||
| 22 | |||
| 23 | Capture the next complete frame into memory. | ||
| 24 | |||
| 25 | - DIFF mode: | ||
| 26 | |||
| 27 | Compare the incoming frame with the frame stored in memory, and updates the | ||
| 28 | differentiated frame in memory. | ||
| 29 | |||
| 30 | Application can use ``V4L2_CID_NPCM_CAPTURE_MODE`` control to set the VCD mode | ||
| 31 | with different control values (enum v4l2_npcm_capture_mode): | ||
| 32 | |||
| 33 | - ``V4L2_NPCM_CAPTURE_MODE_COMPLETE``: will set VCD to COMPLETE mode. | ||
| 34 | - ``V4L2_NPCM_CAPTURE_MODE_DIFF``: will set VCD to DIFF mode. | ||
| 35 | |||
| 36 | V4L2_CID_NPCM_RECT_COUNT | ||
| 37 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 38 | |||
| 39 | If using V4L2_PIX_FMT_HEXTILE format, VCD will capture frame data and then ECE | ||
| 40 | will compress the data into HEXTILE rectangles and store them in V4L2 video | ||
| 41 | buffer with the layout defined in Remote Framebuffer Protocol: | ||
| 42 | :: | ||
| 43 | |||
| 44 | (RFC 6143, https://www.rfc-editor.org/rfc/rfc6143.html#section-7.6.1) | ||
| 45 | |||
| 46 | +--------------+--------------+-------------------+ | ||
| 47 | | No. of bytes | Type [Value] | Description | | ||
| 48 | +--------------+--------------+-------------------+ | ||
| 49 | | 2 | U16 | x-position | | ||
| 50 | | 2 | U16 | y-position | | ||
| 51 | | 2 | U16 | width | | ||
| 52 | | 2 | U16 | height | | ||
| 53 | | 4 | S32 | encoding-type (5) | | ||
| 54 | +--------------+--------------+-------------------+ | ||
| 55 | | HEXTILE rectangle data | | ||
| 56 | +-------------------------------------------------+ | ||
| 57 | |||
| 58 | Application can get the video buffer through VIDIOC_DQBUF, and followed by | ||
| 59 | calling ``V4L2_CID_NPCM_RECT_COUNT`` control to get the number of HEXTILE | ||
| 60 | rectangles in this buffer. | ||
| 61 | |||
| 62 | References | ||
| 63 | ---------- | ||
| 64 | include/uapi/linux/npcm-video.h | ||
| 65 | |||
| 66 | **Copyright** |copy| 2022 Nuvoton Technologies | ||
| @@ -59,9 +59,7 @@ Generic Error Codes · 58 unmodified lines | |||
| 59 | 59 | ||
| 60 | - - ``ENOTTY`` | 60 | - - ``ENOTTY`` |
| 61 | 61 | ||
| 62 | - The ioctl is not supported by the driver, actually meaning that | 62 | - The ioctl is not supported by the file descriptor. |
| 63 | the required functionality is not available, or the file | ||
| 64 | descriptor is not for a media device. | ||
| 65 | 63 | ||
| 66 | - - ``ENOSPC`` | 64 | - - ``ENOSPC`` |
| 67 | 65 | ||
| @@ -549,9 +549,9 @@ Buffer Flags · 548 unmodified lines | |||
| 549 | - 0x00000400 | 549 | - 0x00000400 |
| 550 | - The buffer has been prepared for I/O and can be queued by the | 550 | - The buffer has been prepared for I/O and can be queued by the |
| 551 | application. Drivers set or clear this flag when the | 551 | application. Drivers set or clear this flag when the |
| 552 | :ref:`VIDIOC_QUERYBUF`, | 552 | :ref:`VIDIOC_QUERYBUF <VIDIOC_QUERYBUF>`, |
| 553 | :ref:`VIDIOC_PREPARE_BUF <VIDIOC_QBUF>`, | 553 | :ref:`VIDIOC_PREPARE_BUF <VIDIOC_QBUF>`, |
| 554 | :ref:`VIDIOC_QBUF` or | 554 | :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` or |
| 555 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl is called. | 555 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl is called. |
| 556 | * .. _`V4L2-BUF-FLAG-NO-CACHE-INVALIDATE`: | 556 | * .. _`V4L2-BUF-FLAG-NO-CACHE-INVALIDATE`: |
| 557 | 557 | ||
| @@ -143,9 +143,13 @@ Control IDs · 142 unmodified lines | |||
| 143 | recognise the difference between digital and analogue gain use | 143 | recognise the difference between digital and analogue gain use |
| 144 | controls ``V4L2_CID_DIGITAL_GAIN`` and ``V4L2_CID_ANALOGUE_GAIN``. | 144 | controls ``V4L2_CID_DIGITAL_GAIN`` and ``V4L2_CID_ANALOGUE_GAIN``. |
| 145 | 145 | ||
| 146 | .. _v4l2-cid-hflip: | ||
| 147 | |||
| 146 | ``V4L2_CID_HFLIP`` ``(boolean)`` | 148 | ``V4L2_CID_HFLIP`` ``(boolean)`` |
| 147 | Mirror the picture horizontally. | 149 | Mirror the picture horizontally. |
| 148 | 150 | ||
| 151 | .. _v4l2-cid-vflip: | ||
| 152 | |||
| 149 | ``V4L2_CID_VFLIP`` ``(boolean)`` | 153 | ``V4L2_CID_VFLIP`` ``(boolean)`` |
| 150 | Mirror the picture vertically. | 154 | Mirror the picture vertically. |
| 151 | 155 | ||
| @@ -579,20 +579,19 @@ is started. · 578 unmodified lines | |||
| 579 | 579 | ||
| 580 | There are three steps in configuring the streams: | 580 | There are three steps in configuring the streams: |
| 581 | 581 | ||
| 582 | 1) Set up links. Connect the pads between sub-devices using the :ref:`Media | 582 | 1. Set up links. Connect the pads between sub-devices using the |
| 583 | Controller API <media_controller>` | 583 | :ref:`Media Controller API <media_controller>` |
| 584 | 584 | ||
| 585 | 2) Streams. Streams are declared and their routing is configured by | 585 | 2. Streams. Streams are declared and their routing is configured by setting the |
| 586 | setting the routing table for the sub-device using | 586 | routing table for the sub-device using :ref:`VIDIOC_SUBDEV_S_ROUTING |
| 587 | :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that | 587 | <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that setting the routing table will |
| 588 | setting the routing table will reset formats and selections in the | 588 | reset formats and selections in the sub-device to default values. |
| 589 | sub-device to default values. | ||
| 590 | 589 | ||
| 591 | 3) Configure formats and selections. Formats and selections of each stream | 590 | 3. Configure formats and selections. Formats and selections of each stream are |
| 592 | are configured separately as documented for plain sub-devices in | 591 | configured separately as documented for plain sub-devices in |
| 593 | :ref:`format-propagation`. The stream ID is set to the same stream ID | 592 | :ref:`format-propagation`. The stream ID is set to the same stream ID |
| 594 | associated with either sink or source pads of routes configured using the | 593 | associated with either sink or source pads of routes configured using the |
| 595 | :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. | 594 | :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. |
| 596 | 595 | ||
| 597 | Multiplexed streams setup example | 596 | Multiplexed streams setup example |
| 598 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 597 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| @@ -618,11 +617,11 @@ modeled as V4L2 devices, exposed to userspace via /dev/videoX nodes. · 19 unmodified lines | |||
| 618 | 617 | ||
| 619 | To configure this pipeline, the userspace must take the following steps: | 618 | To configure this pipeline, the userspace must take the following steps: |
| 620 | 619 | ||
| 621 | 1) Set up media links between entities: connect the sensors to the bridge, | 620 | 1. Set up media links between entities: connect the sensors to the bridge, |
| 622 | bridge to the receiver, and the receiver to the DMA engines. This step does | 621 | bridge to the receiver, and the receiver to the DMA engines. This step does |
| 623 | not differ from normal non-multiplexed media controller setup. | 622 | not differ from normal non-multiplexed media controller setup. |
| 624 | 623 | ||
| 625 | 2) Configure routing | 624 | 2. Configure routing |
| 626 | 625 | ||
| 627 | .. flat-table:: Bridge routing table | 626 | .. flat-table:: Bridge routing table |
| 628 | :header-rows: 1 | 627 | :header-rows: 1 |
| @@ -656,14 +655,14 @@ not differ from normal non-multiplexed media controller setup. · 27 unmodified lines | |||
| 656 | - V4L2_SUBDEV_ROUTE_FL_ACTIVE | 655 | - V4L2_SUBDEV_ROUTE_FL_ACTIVE |
| 657 | - Pixel data stream from Sensor B | 656 | - Pixel data stream from Sensor B |
| 658 | 657 | ||
| 659 | 3) Configure formats and selections | 658 | 3. Configure formats and selections |
| 660 | 659 | ||
| 661 | After configuring routing, the next step is configuring the formats and | 660 | After configuring routing, the next step is configuring the formats and |
| 662 | selections for the streams. This is similar to performing this step without | 661 | selections for the streams. This is similar to performing this step without |
| 663 | streams, with just one exception: the ``stream`` field needs to be assigned | 662 | streams, with just one exception: the ``stream`` field needs to be assigned |
| 664 | to the value of the stream ID. | 663 | to the value of the stream ID. |
| 665 | 664 | ||
| 666 | A common way to accomplish this is to start from the sensors and propagate the | 665 | A common way to accomplish this is to start from the sensors and propagate |
| 667 | configurations along the stream towards the receiver, | 666 | the configurations along the stream towards the receiver, using |
| 668 | using :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each | 667 | :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each |
| 669 | stream endpoint in each sub-device. | 668 | stream endpoint in each sub-device. |
| @@ -33,6 +33,27 @@ current DV timings they use the · 32 unmodified lines | |||
| 33 | the DV timings as seen by the video receiver applications use the | 33 | the DV timings as seen by the video receiver applications use the |
| 34 | :ref:`VIDIOC_QUERY_DV_TIMINGS` ioctl. | 34 | :ref:`VIDIOC_QUERY_DV_TIMINGS` ioctl. |
| 35 | 35 | ||
| 36 | When the hardware detects a video source change (e.g. the video | ||
| 37 | signal appears or disappears, or the video resolution changes), then | ||
| 38 | it will issue a `V4L2_EVENT_SOURCE_CHANGE` event. Use the | ||
| 39 | :ref:`ioctl VIDIOC_SUBSCRIBE_EVENT <VIDIOC_SUBSCRIBE_EVENT>` and the | ||
| 40 | :ref:`VIDIOC_DQEVENT` to check if this event was reported. | ||
| 41 | |||
| 42 | If the video signal changed, then the application has to stop | ||
| 43 | streaming, free all buffers, and call the :ref:`VIDIOC_QUERY_DV_TIMINGS` | ||
| 44 | to obtain the new video timings, and if they are valid, it can set | ||
| 45 | those by calling the :ref:`ioctl VIDIOC_S_DV_TIMINGS <VIDIOC_G_DV_TIMINGS>`. | ||
| 46 | This will also update the format, so use the :ref:`ioctl VIDIOC_G_FMT <VIDIOC_G_FMT>` | ||
| 47 | to obtain the new format. Now the application can allocate new buffers | ||
| 48 | and start streaming again. | ||
| 49 | |||
| 50 | The :ref:`VIDIOC_QUERY_DV_TIMINGS` will just report what the | ||
| 51 | hardware detects, it will never change the configuration. If the | ||
| 52 | currently set timings and the actually detected timings differ, then | ||
| 53 | typically this will mean that you will not be able to capture any | ||
| 54 | video. The correct approach is to rely on the `V4L2_EVENT_SOURCE_CHANGE` | ||
| 55 | event so you know when something changed. | ||
| 56 | |||
| 36 | Applications can make use of the :ref:`input-capabilities` and | 57 | Applications can make use of the :ref:`input-capabilities` and |
| 37 | :ref:`output-capabilities` flags to determine whether the digital | 58 | :ref:`output-capabilities` flags to determine whether the digital |
| 38 | video ioctls can be used with the given input or output. | 59 | video ioctls can be used with the given input or output. |
| @@ -288,6 +288,13 @@ please make a proposal on the linux-media mailing list. · 287 unmodified lines | |||
| 288 | - 'MT2110R' | 288 | - 'MT2110R' |
| 289 | - This format is two-planar 10-Bit raster mode and having similitude with | 289 | - This format is two-planar 10-Bit raster mode and having similitude with |
| 290 | ``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for AVC. | 290 | ``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for AVC. |
| 291 | * .. _V4L2-PIX-FMT-HEXTILE: | ||
| 292 | |||
| 293 | - ``V4L2_PIX_FMT_HEXTILE`` | ||
| 294 | - 'HXTL' | ||
| 295 | - Compressed format used by Nuvoton NPCM video driver. This format is | ||
| 296 | defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile | ||
| 297 | Encoding). | ||
| 291 | .. raw:: latex | 298 | .. raw:: latex |
| 292 | 299 | ||
| 293 | \normalsize | 300 | \normalsize |
| @@ -60,7 +60,7 @@ Each cell is one byte. · 59 unmodified lines | |||
| 60 | G\ :sub:`10low`\ (bits 3--0) | 60 | G\ :sub:`10low`\ (bits 3--0) |
| 61 | - G\ :sub:`12high` | 61 | - G\ :sub:`12high` |
| 62 | - R\ :sub:`13high` | 62 | - R\ :sub:`13high` |
| 63 | - R\ :sub:`13low`\ (bits 3--2) | 63 | - R\ :sub:`13low`\ (bits 7--4) |
| 64 | 64 | ||
| 65 | G\ :sub:`12low`\ (bits 3--0) | 65 | G\ :sub:`12low`\ (bits 3--0) |
| 66 | - - start + 12: | 66 | - - start + 12: |
| @@ -82,6 +82,6 @@ Each cell is one byte. · 15 unmodified lines | |||
| 82 | G\ :sub:`30low`\ (bits 3--0) | 82 | G\ :sub:`30low`\ (bits 3--0) |
| 83 | - G\ :sub:`32high` | 83 | - G\ :sub:`32high` |
| 84 | - R\ :sub:`33high` | 84 | - R\ :sub:`33high` |
| 85 | - R\ :sub:`33low`\ (bits 3--2) | 85 | - R\ :sub:`33low`\ (bits 7--4) |
| 86 | 86 | ||
| 87 | G\ :sub:`32low`\ (bits 3--0) | 87 | G\ :sub:`32low`\ (bits 3--0) |
| @@ -2510,6 +2510,18 @@ F: drivers/rtc/rtc-nct3018y.c · 2509 unmodified lines | |||
| 2510 | F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h | 2510 | F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h |
| 2511 | F: include/dt-bindings/clock/nuvoton,npcm845-clk.h | 2511 | F: include/dt-bindings/clock/nuvoton,npcm845-clk.h |
| 2512 | 2512 | ||
| 2513 | ARM/NUVOTON NPCM VIDEO ENGINE DRIVER | ||
| 2514 | M: Joseph Liu <kwliu@nuvoton.com> | ||
| 2515 | M: Marvin Lin <kflin@nuvoton.com> | ||
| 2516 | L: linux-media@vger.kernel.org | ||
| 2517 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) | ||
| 2518 | S: Maintained | ||
| 2519 | F: Documentation/devicetree/bindings/media/nuvoton,npcm-ece.yaml | ||
| 2520 | F: Documentation/devicetree/bindings/media/nuvoton,npcm-vcd.yaml | ||
| 2521 | F: Documentation/userspace-api/media/drivers/npcm-video.rst | ||
| 2522 | F: drivers/media/platform/nuvoton/ | ||
| 2523 | F: include/uapi/linux/npcm-video.h | ||
| 2524 | |||
| 2513 | ARM/NUVOTON WPCM450 ARCHITECTURE | 2525 | ARM/NUVOTON WPCM450 ARCHITECTURE |
| 2514 | M: Jonathan Neuschäfer <j.neuschaefer@gmx.net> | 2526 | M: Jonathan Neuschäfer <j.neuschaefer@gmx.net> |
| 2515 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) | 2527 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) |
| @@ -6143,6 +6155,13 @@ L: linux-gpio@vger.kernel.org · 3627 unmodified lines | |||
| 6143 | S: Maintained | 6155 | S: Maintained |
| 6144 | F: drivers/gpio/gpio-gpio-mm.c | 6156 | F: drivers/gpio/gpio-gpio-mm.c |
| 6145 | 6157 | ||
| 6158 | DIGITEQ AUTOMOTIVE MGB4 V4L2 DRIVER | ||
| 6159 | M: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 6160 | L: linux-media@vger.kernel.org | ||
| 6161 | S: Maintained | ||
| 6162 | F: Documentation/admin-guide/media/mgb4.rst | ||
| 6163 | F: drivers/media/pci/mgb4/ | ||
| 6164 | |||
| 6146 | DIOLAN U2C-12 I2C DRIVER | 6165 | DIOLAN U2C-12 I2C DRIVER |
| 6147 | M: Guenter Roeck <linux@roeck-us.net> | 6166 | M: Guenter Roeck <linux@roeck-us.net> |
| 6148 | L: linux-i2c@vger.kernel.org | 6167 | L: linux-i2c@vger.kernel.org |
| @@ -14684,6 +14703,14 @@ L: linux-mtd@lists.infradead.org · 8535 unmodified lines | |||
| 14684 | S: Maintained | 14703 | S: Maintained |
| 14685 | F: drivers/mtd/devices/docg3* | 14704 | F: drivers/mtd/devices/docg3* |
| 14686 | 14705 | ||
| 14706 | MT9M114 ONSEMI SENSOR DRIVER | ||
| 14707 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
| 14708 | L: linux-media@vger.kernel.org | ||
| 14709 | S: Maintained | ||
| 14710 | T: git git://linuxtv.org/media_tree.git | ||
| 14711 | F: Documentation/devicetree/bindings/media/i2c/onnn,mt9m114.yaml | ||
| 14712 | F: drivers/media/i2c/mt9m114.c | ||
| 14713 | |||
| 14687 | MT9P031 APTINA CAMERA SENSOR | 14714 | MT9P031 APTINA CAMERA SENSOR |
| 14688 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 14715 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 14689 | L: linux-media@vger.kernel.org | 14716 | L: linux-media@vger.kernel.org |
| @@ -15926,7 +15953,7 @@ L: linux-media@vger.kernel.org · 1236 unmodified lines | |||
| 15926 | S: Maintained | 15953 | S: Maintained |
| 15927 | T: git git://linuxtv.org/media_tree.git | 15954 | T: git git://linuxtv.org/media_tree.git |
| 15928 | F: Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml | 15955 | F: Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml |
| 15929 | F: drivers/media/i2c/ov5647.c | 15956 | F: drivers/media/i2c/ov4689.c |
| 15930 | 15957 | ||
| 15931 | OMNIVISION OV5640 SENSOR DRIVER | 15958 | OMNIVISION OV5640 SENSOR DRIVER |
| 15932 | M: Steve Longerbeam <slongerbeam@gmail.com> | 15959 | M: Steve Longerbeam <slongerbeam@gmail.com> |
| @@ -16016,8 +16043,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov8858.yaml · 83 unmodified lines | |||
| 16016 | F: drivers/media/i2c/ov8858.c | 16043 | F: drivers/media/i2c/ov8858.c |
| 16017 | 16044 | ||
| 16018 | OMNIVISION OV9282 SENSOR DRIVER | 16045 | OMNIVISION OV9282 SENSOR DRIVER |
| 16019 | M: Paul J. Murphy <paul.j.murphy@intel.com> | 16046 | M: Dave Stevenson <dave.stevenson@raspberrypi.com> |
| 16020 | M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | ||
| 16021 | L: linux-media@vger.kernel.org | 16047 | L: linux-media@vger.kernel.org |
| 16022 | S: Maintained | 16048 | S: Maintained |
| 16023 | T: git git://linuxtv.org/media_tree.git | 16049 | T: git git://linuxtv.org/media_tree.git |
| @@ -18666,6 +18692,7 @@ F: sound/soc/rockchip/rockchip_i2s_tdm.* · 2642 unmodified lines | |||
| 18666 | 18692 | ||
| 18667 | ROCKCHIP ISP V1 DRIVER | 18693 | ROCKCHIP ISP V1 DRIVER |
| 18668 | M: Dafna Hirschfeld <dafna@fastmail.com> | 18694 | M: Dafna Hirschfeld <dafna@fastmail.com> |
| 18695 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
| 18669 | L: linux-media@vger.kernel.org | 18696 | L: linux-media@vger.kernel.org |
| 18670 | L: linux-rockchip@lists.infradead.org | 18697 | L: linux-rockchip@lists.infradead.org |
| 18671 | S: Maintained | 18698 | S: Maintained |
| @@ -20160,19 +20187,15 @@ T: git git://linuxtv.org/media_tree.git · 1488 unmodified lines | |||
| 20160 | F: drivers/media/i2c/imx319.c | 20187 | F: drivers/media/i2c/imx319.c |
| 20161 | 20188 | ||
| 20162 | SONY IMX334 SENSOR DRIVER | 20189 | SONY IMX334 SENSOR DRIVER |
| 20163 | M: Paul J. Murphy <paul.j.murphy@intel.com> | ||
| 20164 | M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | ||
| 20165 | L: linux-media@vger.kernel.org | 20190 | L: linux-media@vger.kernel.org |
| 20166 | S: Maintained | 20191 | S: Orphan |
| 20167 | T: git git://linuxtv.org/media_tree.git | 20192 | T: git git://linuxtv.org/media_tree.git |
| 20168 | F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml | 20193 | F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml |
| 20169 | F: drivers/media/i2c/imx334.c | 20194 | F: drivers/media/i2c/imx334.c |
| 20170 | 20195 | ||
| 20171 | SONY IMX335 SENSOR DRIVER | 20196 | SONY IMX335 SENSOR DRIVER |
| 20172 | M: Paul J. Murphy <paul.j.murphy@intel.com> | ||
| 20173 | M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | ||
| 20174 | L: linux-media@vger.kernel.org | 20197 | L: linux-media@vger.kernel.org |
| 20175 | S: Maintained | 20198 | S: Orphan |
| 20176 | T: git git://linuxtv.org/media_tree.git | 20199 | T: git git://linuxtv.org/media_tree.git |
| 20177 | F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml | 20200 | F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml |
| 20178 | F: drivers/media/i2c/imx335.c | 20201 | F: drivers/media/i2c/imx335.c |
| @@ -20185,10 +20208,8 @@ T: git git://linuxtv.org/media_tree.git · 6 unmodified lines | |||
| 20185 | F: drivers/media/i2c/imx355.c | 20208 | F: drivers/media/i2c/imx355.c |
| 20186 | 20209 | ||
| 20187 | SONY IMX412 SENSOR DRIVER | 20210 | SONY IMX412 SENSOR DRIVER |
| 20188 | M: Paul J. Murphy <paul.j.murphy@intel.com> | ||
| 20189 | M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | ||
| 20190 | L: linux-media@vger.kernel.org | 20211 | L: linux-media@vger.kernel.org |
| 20191 | S: Maintained | 20212 | S: Orphan |
| 20192 | T: git git://linuxtv.org/media_tree.git | 20213 | T: git git://linuxtv.org/media_tree.git |
| 20193 | F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml | 20214 | F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml |
| 20194 | F: drivers/media/i2c/imx412.c | 20215 | F: drivers/media/i2c/imx412.c |
| @@ -21752,6 +21773,13 @@ F: Documentation/devicetree/bindings/media/i2c/ti,ds90* · 1557 unmodified lines | |||
| 21752 | F: drivers/media/i2c/ds90* | 21773 | F: drivers/media/i2c/ds90* |
| 21753 | F: include/media/i2c/ds90* | 21774 | F: include/media/i2c/ds90* |
| 21754 | 21775 | ||
| 21776 | TI J721E CSI2RX DRIVER | ||
| 21777 | M: Jai Luthra <j-luthra@ti.com> | ||
| 21778 | L: linux-media@vger.kernel.org | ||
| 21779 | S: Maintained | ||
| 21780 | F: Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml | ||
| 21781 | F: drivers/media/platform/ti/j721e-csi2rx/ | ||
| 21782 | |||
| 21755 | TI KEYSTONE MULTICORE NAVIGATOR DRIVERS | 21783 | TI KEYSTONE MULTICORE NAVIGATOR DRIVERS |
| 21756 | M: Nishanth Menon <nm@ti.com> | 21784 | M: Nishanth Menon <nm@ti.com> |
| 21757 | M: Santosh Shilimkar <ssantosh@kernel.org> | 21785 | M: Santosh Shilimkar <ssantosh@kernel.org> |
| @@ -477,7 +477,6 @@ CONFIG_LIRC=y · 476 unmodified lines | |||
| 477 | CONFIG_RC_DEVICES=y | 477 | CONFIG_RC_DEVICES=y |
| 478 | CONFIG_IR_GPIO_TX=m | 478 | CONFIG_IR_GPIO_TX=m |
| 479 | CONFIG_IR_PWM_TX=m | 479 | CONFIG_IR_PWM_TX=m |
| 480 | CONFIG_IR_RX51=m | ||
| 481 | CONFIG_IR_SPI=m | 480 | CONFIG_IR_SPI=m |
| 482 | CONFIG_MEDIA_SUPPORT=m | 481 | CONFIG_MEDIA_SUPPORT=m |
| 483 | CONFIG_V4L_PLATFORM_DRIVERS=y | 482 | CONFIG_V4L_PLATFORM_DRIVERS=y |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | # Please keep it in alphabetic order | 6 | # Please keep it in alphabetic order |
| 7 | obj-$(CONFIG_CEC_CROS_EC) += cros-ec/ | 7 | obj-$(CONFIG_CEC_CROS_EC) += cros-ec/ |
| 8 | obj-$(CONFIG_CEC_GPIO) += cec-gpio/ | 8 | obj-$(CONFIG_CEC_GPIO) += cec-gpio/ |
| 9 | obj-$(CONFIG_CEC_MESON_AO) += meson/ | 9 | obj-y += meson/ |
| 10 | obj-$(CONFIG_CEC_SAMSUNG_S5P) += s5p/ | 10 | obj-$(CONFIG_CEC_SAMSUNG_S5P) += s5p/ |
| 11 | obj-$(CONFIG_CEC_SECO) += seco/ | 11 | obj-$(CONFIG_CEC_SECO) += seco/ |
| 12 | obj-$(CONFIG_CEC_STI) += sti/ | 12 | obj-$(CONFIG_CEC_STI) += sti/ |
| @@ -22,50 +22,124 @@ · 21 unmodified lines | |||
| 22 | #define DRV_NAME "cros-ec-cec" | 22 | #define DRV_NAME "cros-ec-cec" |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * struct cros_ec_cec - Driver data for EC CEC | 25 | * struct cros_ec_cec_port - Driver data for a single EC CEC port |
| 26 | * | 26 | * |
| 27 | * @cros_ec: Pointer to EC device | 27 | * @port_num: port number |
| 28 | * @notifier: Notifier info for responding to EC events | ||
| 29 | * @adap: CEC adapter | 28 | * @adap: CEC adapter |
| 30 | * @notify: CEC notifier pointer | 29 | * @notify: CEC notifier pointer |
| 31 | * @rx_msg: storage for a received message | 30 | * @rx_msg: storage for a received message |
| 31 | * @cros_ec_cec: pointer to the parent struct | ||
| 32 | */ | 32 | */ |
| 33 | struct cros_ec_cec { | 33 | struct cros_ec_cec_port { |
| 34 | struct cros_ec_device *cros_ec; | 34 | int port_num; |
| 35 | struct notifier_block notifier; | ||
| 36 | struct cec_adapter *adap; | 35 | struct cec_adapter *adap; |
| 37 | struct cec_notifier *notify; | 36 | struct cec_notifier *notify; |
| 38 | struct cec_msg rx_msg; | 37 | struct cec_msg rx_msg; |
| 38 | struct cros_ec_cec *cros_ec_cec; | ||
| 39 | }; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct cros_ec_cec - Driver data for EC CEC | ||
| 43 | * | ||
| 44 | * @cros_ec: Pointer to EC device | ||
| 45 | * @notifier: Notifier info for responding to EC events | ||
| 46 | * @write_cmd_version: Highest supported version of EC_CMD_CEC_WRITE_MSG. | ||
| 47 | * @num_ports: Number of CEC ports | ||
| 48 | * @ports: Array of ports | ||
| 49 | */ | ||
| 50 | struct cros_ec_cec { | ||
| 51 | struct cros_ec_device *cros_ec; | ||
| 52 | struct notifier_block notifier; | ||
| 53 | int write_cmd_version; | ||
| 54 | int num_ports; | ||
| 55 | struct cros_ec_cec_port *ports[EC_CEC_MAX_PORTS]; | ||
| 39 | }; | 56 | }; |
| 40 | 57 | ||
| 58 | static void cros_ec_cec_received_message(struct cros_ec_cec_port *port, | ||
| 59 | uint8_t *msg, uint8_t len) | ||
| 60 | { | ||
| 61 | if (len > CEC_MAX_MSG_SIZE) | ||
| 62 | len = CEC_MAX_MSG_SIZE; | ||
| 63 | |||
| 64 | port->rx_msg.len = len; | ||
| 65 | memcpy(port->rx_msg.msg, msg, len); | ||
| 66 | |||
| 67 | cec_received_msg(port->adap, &port->rx_msg); | ||
| 68 | } | ||
| 69 | |||
| 41 | static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) | 70 | static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) |
| 42 | { | 71 | { |
| 43 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | 72 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 44 | uint8_t *cec_message = cros_ec->event_data.data.cec_message; | 73 | uint8_t *cec_message = cros_ec->event_data.data.cec_message; |
| 45 | unsigned int len = cros_ec->event_size; | 74 | unsigned int len = cros_ec->event_size; |
| 75 | struct cros_ec_cec_port *port; | ||
| 76 | /* | ||
| 77 | * There are two ways of receiving CEC messages: | ||
| 78 | * 1. Old EC firmware which only supports one port sends the data in a | ||
| 79 | * cec_message MKBP event. | ||
| 80 | * 2. New EC firmware which supports multiple ports uses | ||
| 81 | * EC_MKBP_CEC_HAVE_DATA to notify that data is ready and | ||
| 82 | * EC_CMD_CEC_READ_MSG to read it. | ||
| 83 | * Check that the EC only has one CEC port, and then we can assume the | ||
| 84 | * message is from port 0. | ||
| 85 | */ | ||
| 86 | if (cros_ec_cec->num_ports != 1) { | ||
| 87 | dev_err(cros_ec->dev, | ||
| 88 | "received cec_message on device with %d ports\n", | ||
| 89 | cros_ec_cec->num_ports); | ||
| 90 | return; | ||
| 91 | } | ||
| 92 | port = cros_ec_cec->ports[0]; | ||
| 46 | 93 | ||
| 47 | if (len > CEC_MAX_MSG_SIZE) | 94 | cros_ec_cec_received_message(port, cec_message, len); |
| 48 | len = CEC_MAX_MSG_SIZE; | 95 | } |
| 49 | cros_ec_cec->rx_msg.len = len; | 96 | |
| 50 | memcpy(cros_ec_cec->rx_msg.msg, cec_message, len); | 97 | static void cros_ec_cec_read_message(struct cros_ec_cec_port *port) |
| 98 | { | ||
| 99 | struct cros_ec_device *cros_ec = port->cros_ec_cec->cros_ec; | ||
| 100 | struct ec_params_cec_read params = { | ||
| 101 | .port = port->port_num, | ||
| 102 | }; | ||
| 103 | struct ec_response_cec_read response; | ||
| 104 | int ret; | ||
| 51 | 105 | ||
| 52 | cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg); | 106 | ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_READ_MSG, ¶ms, |
| 107 | sizeof(params), &response, sizeof(response)); | ||
| 108 | if (ret < 0) { | ||
| 109 | dev_err(cros_ec->dev, | ||
| 110 | "error reading CEC message on EC: %d\n", ret); | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 114 | cros_ec_cec_received_message(port, response.msg, response.msg_len); | ||
| 53 | } | 115 | } |
| 54 | 116 | ||
| 55 | static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) | 117 | static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) |
| 56 | { | 118 | { |
| 57 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | 119 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 58 | uint32_t events = cros_ec->event_data.data.cec_events; | 120 | uint32_t cec_events = cros_ec->event_data.data.cec_events; |
| 121 | uint32_t port_num = EC_MKBP_EVENT_CEC_GET_PORT(cec_events); | ||
| 122 | uint32_t events = EC_MKBP_EVENT_CEC_GET_EVENTS(cec_events); | ||
| 123 | struct cros_ec_cec_port *port; | ||
| 124 | |||
| 125 | if (port_num >= cros_ec_cec->num_ports) { | ||
| 126 | dev_err(cros_ec->dev, | ||
| 127 | "received CEC event for invalid port %d\n", port_num); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | port = cros_ec_cec->ports[port_num]; | ||
| 59 | 131 | ||
| 60 | if (events & EC_MKBP_CEC_SEND_OK) | 132 | if (events & EC_MKBP_CEC_SEND_OK) |
| 61 | cec_transmit_attempt_done(cros_ec_cec->adap, | 133 | cec_transmit_attempt_done(port->adap, CEC_TX_STATUS_OK); |
| 62 | CEC_TX_STATUS_OK); | ||
| 63 | 134 | ||
| 64 | /* FW takes care of all retries, tell core to avoid more retries */ | 135 | /* FW takes care of all retries, tell core to avoid more retries */ |
| 65 | if (events & EC_MKBP_CEC_SEND_FAILED) | 136 | if (events & EC_MKBP_CEC_SEND_FAILED) |
| 66 | cec_transmit_attempt_done(cros_ec_cec->adap, | 137 | cec_transmit_attempt_done(port->adap, |
| 67 | CEC_TX_STATUS_MAX_RETRIES | | 138 | CEC_TX_STATUS_MAX_RETRIES | |
| 68 | CEC_TX_STATUS_NACK); | 139 | CEC_TX_STATUS_NACK); |
| 140 | |||
| 141 | if (events & EC_MKBP_CEC_HAVE_DATA) | ||
| 142 | cros_ec_cec_read_message(port); | ||
| 69 | } | 143 | } |
| 70 | 144 | ||
| 71 | static int cros_ec_cec_event(struct notifier_block *nb, | 145 | static int cros_ec_cec_event(struct notifier_block *nb, |
| @@ -93,20 +167,18 @@ static int cros_ec_cec_event(struct notifier_block *nb, · 21 unmodified lines | |||
| 93 | 167 | ||
| 94 | static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) | 168 | static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) |
| 95 | { | 169 | { |
| 96 | struct cros_ec_cec *cros_ec_cec = adap->priv; | 170 | struct cros_ec_cec_port *port = adap->priv; |
| 171 | struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; | ||
| 97 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | 172 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 98 | struct { | 173 | struct ec_params_cec_set params = { |
| 99 | struct cros_ec_command msg; | 174 | .cmd = CEC_CMD_LOGICAL_ADDRESS, |
| 100 | struct ec_params_cec_set data; | 175 | .port = port->port_num, |
| 101 | } __packed msg = {}; | 176 | .val = logical_addr, |
| 177 | }; | ||
| 102 | int ret; | 178 | int ret; |
| 103 | 179 | ||
| 104 | msg.msg.command = EC_CMD_CEC_SET; | 180 | ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), |
| 105 | msg.msg.outsize = sizeof(msg.data); | 181 | NULL, 0); |
| 106 | msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS; | ||
| 107 | msg.data.val = logical_addr; | ||
| 108 | |||
| 109 | ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); | ||
| 110 | if (ret < 0) { | 182 | if (ret < 0) { |
| 111 | dev_err(cros_ec->dev, | 183 | dev_err(cros_ec->dev, |
| 112 | "error setting CEC logical address on EC: %d\n", ret); | 184 | "error setting CEC logical address on EC: %d\n", ret); |
| @@ -119,19 +191,26 @@ static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) · 6 unmodified lines | |||
| 119 | static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, | 191 | static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, |
| 120 | u32 signal_free_time, struct cec_msg *cec_msg) | 192 | u32 signal_free_time, struct cec_msg *cec_msg) |
| 121 | { | 193 | { |
| 122 | struct cros_ec_cec *cros_ec_cec = adap->priv; | 194 | struct cros_ec_cec_port *port = adap->priv; |
| 195 | struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; | ||
| 123 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | 196 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 124 | struct { | 197 | struct ec_params_cec_write params; |
| 125 | struct cros_ec_command msg; | 198 | struct ec_params_cec_write_v1 params_v1; |
| 126 | struct ec_params_cec_write data; | ||
| 127 | } __packed msg = {}; | ||
| 128 | int ret; | 199 | int ret; |
| 129 | 200 | ||
| 130 | msg.msg.command = EC_CMD_CEC_WRITE_MSG; | 201 | if (cros_ec_cec->write_cmd_version == 0) { |
| 131 | msg.msg.outsize = cec_msg->len; | 202 | memcpy(params.msg, cec_msg->msg, cec_msg->len); |
| 132 | memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); | 203 | ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_WRITE_MSG, ¶ms, |
| 204 | cec_msg->len, NULL, 0); | ||
| 205 | } else { | ||
| 206 | params_v1.port = port->port_num; | ||
| 207 | params_v1.msg_len = cec_msg->len; | ||
| 208 | memcpy(params_v1.msg, cec_msg->msg, cec_msg->len); | ||
| 209 | ret = cros_ec_cmd(cros_ec, cros_ec_cec->write_cmd_version, | ||
| 210 | EC_CMD_CEC_WRITE_MSG, ¶ms_v1, | ||
| 211 | sizeof(params_v1), NULL, 0); | ||
| 212 | } | ||
| 133 | 213 | ||
| 134 | ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); | ||
| 135 | if (ret < 0) { | 214 | if (ret < 0) { |
| 136 | dev_err(cros_ec->dev, | 215 | dev_err(cros_ec->dev, |
| 137 | "error writing CEC msg on EC: %d\n", ret); | 216 | "error writing CEC msg on EC: %d\n", ret); |
| @@ -143,20 +222,18 @@ static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, · 5 unmodified lines | |||
| 143 | 222 | ||
| 144 | static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) | 223 | static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) |
| 145 | { | 224 | { |
| 146 | struct cros_ec_cec *cros_ec_cec = adap->priv; | 225 | struct cros_ec_cec_port *port = adap->priv; |
| 226 | struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; | ||
| 147 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | 227 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 148 | struct { | 228 | struct ec_params_cec_set params = { |
| 149 | struct cros_ec_command msg; | 229 | .cmd = CEC_CMD_ENABLE, |
| 150 | struct ec_params_cec_set data; | 230 | .port = port->port_num, |
| 151 | } __packed msg = {}; | 231 | .val = enable, |
| 232 | }; | ||
| 152 | int ret; | 233 | int ret; |
| 153 | 234 | ||
| 154 | msg.msg.command = EC_CMD_CEC_SET; | 235 | ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), |
| 155 | msg.msg.outsize = sizeof(msg.data); | 236 | NULL, 0); |
| 156 | msg.data.cmd = CEC_CMD_ENABLE; | ||
| 157 | msg.data.val = enable; | ||
| 158 | |||
| 159 | ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); | ||
| 160 | if (ret < 0) { | 237 | if (ret < 0) { |
| 161 | dev_err(cros_ec->dev, | 238 | dev_err(cros_ec->dev, |
| 162 | "error %sabling CEC on EC: %d\n", | 239 | "error %sabling CEC on EC: %d\n", |
| @@ -203,38 +280,54 @@ static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, · 40 unmodified lines | |||
| 203 | #if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI) | 280 | #if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI) |
| 204 | 281 | ||
| 205 | /* | 282 | /* |
| 206 | * The Firmware only handles a single CEC interface tied to a single HDMI | 283 | * Specify the DRM device name handling the HDMI output and the HDMI connector |
| 207 | * connector we specify along with the DRM device name handling the HDMI output | 284 | * corresponding to each CEC port. The order of connectors must match the order |
| 285 | * in the EC (first connector is EC port 0, ...), and the number of connectors | ||
| 286 | * must match the number of ports in the EC (which can be queried using the | ||
| 287 | * EC_CMD_CEC_PORT_COUNT host command). | ||
| 208 | */ | 288 | */ |
| 209 | 289 | ||
| 210 | struct cec_dmi_match { | 290 | struct cec_dmi_match { |
| 211 | const char *sys_vendor; | 291 | const char *sys_vendor; |
| 212 | const char *product_name; | 292 | const char *product_name; |
| 213 | const char *devname; | 293 | const char *devname; |
| 214 | const char *conn; | 294 | const char *const *conns; |
| 215 | }; | 295 | }; |
| 216 | 296 | ||
| 297 | static const char *const port_b_conns[] = { "Port B", NULL }; | ||
| 298 | static const char *const port_db_conns[] = { "Port D", "Port B", NULL }; | ||
| 299 | static const char *const port_ba_conns[] = { "Port B", "Port A", NULL }; | ||
| 300 | static const char *const port_d_conns[] = { "Port D", NULL }; | ||
| 301 | |||
| 217 | static const struct cec_dmi_match cec_dmi_match_table[] = { | 302 | static const struct cec_dmi_match cec_dmi_match_table[] = { |
| 218 | /* Google Fizz */ | 303 | /* Google Fizz */ |
| 219 | { "Google", "Fizz", "0000:00:02.0", "Port B" }, | 304 | { "Google", "Fizz", "0000:00:02.0", port_b_conns }, |
| 220 | /* Google Brask */ | 305 | /* Google Brask */ |
| 221 | { "Google", "Brask", "0000:00:02.0", "Port B" }, | 306 | { "Google", "Brask", "0000:00:02.0", port_b_conns }, |
| 222 | /* Google Moli */ | 307 | /* Google Moli */ |
| 223 | { "Google", "Moli", "0000:00:02.0", "Port B" }, | 308 | { "Google", "Moli", "0000:00:02.0", port_b_conns }, |
| 224 | /* Google Kinox */ | 309 | /* Google Kinox */ |
| 225 | { "Google", "Kinox", "0000:00:02.0", "Port B" }, | 310 | { "Google", "Kinox", "0000:00:02.0", port_b_conns }, |
| 226 | /* Google Kuldax */ | 311 | /* Google Kuldax */ |
| 227 | { "Google", "Kuldax", "0000:00:02.0", "Port B" }, | 312 | { "Google", "Kuldax", "0000:00:02.0", port_b_conns }, |
| 228 | /* Google Aurash */ | 313 | /* Google Aurash */ |
| 229 | { "Google", "Aurash", "0000:00:02.0", "Port B" }, | 314 | { "Google", "Aurash", "0000:00:02.0", port_b_conns }, |
| 230 | /* Google Gladios */ | 315 | /* Google Gladios */ |
| 231 | { "Google", "Gladios", "0000:00:02.0", "Port B" }, | 316 | { "Google", "Gladios", "0000:00:02.0", port_b_conns }, |
| 232 | /* Google Lisbon */ | 317 | /* Google Lisbon */ |
| 233 | { "Google", "Lisbon", "0000:00:02.0", "Port B" }, | 318 | { "Google", "Lisbon", "0000:00:02.0", port_b_conns }, |
| 319 | /* Google Dibbi */ | ||
| 320 | { "Google", "Dibbi", "0000:00:02.0", port_db_conns }, | ||
| 321 | /* Google Constitution */ | ||
| 322 | { "Google", "Constitution", "0000:00:02.0", port_ba_conns }, | ||
| 323 | /* Google Boxy */ | ||
| 324 | { "Google", "Boxy", "0000:00:02.0", port_d_conns }, | ||
| 325 | /* Google Taranza */ | ||
| 326 | { "Google", "Taranza", "0000:00:02.0", port_db_conns }, | ||
| 234 | }; | 327 | }; |
| 235 | 328 | ||
| 236 | static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, | 329 | static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, |
| 237 | const char **conn) | 330 | const char * const **conns) |
| 238 | { | 331 | { |
| 239 | int i; | 332 | int i; |
| 240 | 333 | ||
| @@ -251,7 +344,7 @@ static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, · 10 unmodified lines | |||
| 251 | if (!d) | 344 | if (!d) |
| 252 | return ERR_PTR(-EPROBE_DEFER); | 345 | return ERR_PTR(-EPROBE_DEFER); |
| 253 | put_device(d); | 346 | put_device(d); |
| 254 | *conn = m->conn; | 347 | *conns = m->conns; |
| 255 | return d; | 348 | return d; |
| 256 | } | 349 | } |
| 257 | } | 350 | } |
| @@ -265,23 +358,137 @@ static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, · 7 unmodified lines | |||
| 265 | #else | 358 | #else |
| 266 | 359 | ||
| 267 | static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, | 360 | static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, |
| 268 | const char **conn) | 361 | const char * const **conns) |
| 269 | { | 362 | { |
| 270 | return ERR_PTR(-ENODEV); | 363 | return ERR_PTR(-ENODEV); |
| 271 | } | 364 | } |
| 272 | 365 | ||
| 273 | #endif | 366 | #endif |
| 274 | 367 | ||
| 368 | static int cros_ec_cec_get_num_ports(struct cros_ec_cec *cros_ec_cec) | ||
| 369 | { | ||
| 370 | struct ec_response_cec_port_count response; | ||
| 371 | int ret; | ||
| 372 | |||
| 373 | ret = cros_ec_cmd(cros_ec_cec->cros_ec, 0, EC_CMD_CEC_PORT_COUNT, NULL, | ||
| 374 | 0, &response, sizeof(response)); | ||
| 375 | if (ret < 0) { | ||
| 376 | /* | ||
| 377 | * Old EC firmware only supports one port and does not support | ||
| 378 | * the port count command, so fall back to assuming one port. | ||
| 379 | */ | ||
| 380 | cros_ec_cec->num_ports = 1; | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | if (response.port_count == 0) { | ||
| 385 | dev_err(cros_ec_cec->cros_ec->dev, | ||
| 386 | "EC reports 0 CEC ports\n"); | ||
| 387 | return -ENODEV; | ||
| 388 | } | ||
| 389 | |||
| 390 | if (response.port_count > EC_CEC_MAX_PORTS) { | ||
| 391 | dev_err(cros_ec_cec->cros_ec->dev, | ||
| 392 | "EC reports too many ports: %d\n", response.port_count); | ||
| 393 | return -EINVAL; | ||
| 394 | } | ||
| 395 | |||
| 396 | cros_ec_cec->num_ports = response.port_count; | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | static int cros_ec_cec_get_write_cmd_version(struct cros_ec_cec *cros_ec_cec) | ||
| 401 | { | ||
| 402 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; | ||
| 403 | struct ec_params_get_cmd_versions_v1 params = { | ||
| 404 | .cmd = EC_CMD_CEC_WRITE_MSG, | ||
| 405 | }; | ||
| 406 | struct ec_response_get_cmd_versions response; | ||
| 407 | int ret; | ||
| 408 | |||
| 409 | ret = cros_ec_cmd(cros_ec, 1, EC_CMD_GET_CMD_VERSIONS, ¶ms, | ||
| 410 | sizeof(params), &response, sizeof(response)); | ||
| 411 | if (ret < 0) { | ||
| 412 | dev_err(cros_ec->dev, | ||
| 413 | "error getting CEC write command version: %d\n", ret); | ||
| 414 | return ret; | ||
| 415 | } | ||
| 416 | |||
| 417 | if (response.version_mask & EC_VER_MASK(1)) { | ||
| 418 | cros_ec_cec->write_cmd_version = 1; | ||
| 419 | } else { | ||
| 420 | if (cros_ec_cec->num_ports != 1) { | ||
| 421 | dev_err(cros_ec->dev, | ||
| 422 | "v0 write command only supports 1 port, %d reported\n", | ||
| 423 | cros_ec_cec->num_ports); | ||
| 424 | return -EINVAL; | ||
| 425 | } | ||
| 426 | cros_ec_cec->write_cmd_version = 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 432 | static int cros_ec_cec_init_port(struct device *dev, | ||
| 433 | struct cros_ec_cec *cros_ec_cec, | ||
| 434 | int port_num, struct device *hdmi_dev, | ||
| 435 | const char * const *conns) | ||
| 436 | { | ||
| 437 | struct cros_ec_cec_port *port; | ||
| 438 | int ret; | ||
| 439 | |||
| 440 | port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); | ||
| 441 | if (!port) | ||
| 442 | return -ENOMEM; | ||
| 443 | |||
| 444 | port->cros_ec_cec = cros_ec_cec; | ||
| 445 | port->port_num = port_num; | ||
| 446 | |||
| 447 | port->adap = cec_allocate_adapter(&cros_ec_cec_ops, port, DRV_NAME, | ||
| 448 | CEC_CAP_DEFAULTS | | ||
| 449 | CEC_CAP_CONNECTOR_INFO, 1); | ||
| 450 | if (IS_ERR(port->adap)) | ||
| 451 | return PTR_ERR(port->adap); | ||
| 452 | |||
| 453 | if (!conns[port_num]) { | ||
| 454 | dev_err(dev, "no conn for port %d\n", port_num); | ||
| 455 | ret = -ENODEV; | ||
| 456 | goto out_probe_adapter; | ||
| 457 | } | ||
| 458 | |||
| 459 | port->notify = cec_notifier_cec_adap_register(hdmi_dev, conns[port_num], | ||
| 460 | port->adap); | ||
| 461 | if (!port->notify) { | ||
| 462 | ret = -ENOMEM; | ||
| 463 | goto out_probe_adapter; | ||
| 464 | } | ||
| 465 | |||
| 466 | ret = cec_register_adapter(port->adap, dev); | ||
| 467 | if (ret < 0) | ||
| 468 | goto out_probe_notify; | ||
| 469 | |||
| 470 | cros_ec_cec->ports[port_num] = port; | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | |||
| 474 | out_probe_notify: | ||
| 475 | cec_notifier_cec_adap_unregister(port->notify, port->adap); | ||
| 476 | out_probe_adapter: | ||
| 477 | cec_delete_adapter(port->adap); | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 275 | static int cros_ec_cec_probe(struct platform_device *pdev) | 481 | static int cros_ec_cec_probe(struct platform_device *pdev) |
| 276 | { | 482 | { |
| 277 | struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); | 483 | struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); |
| 278 | struct cros_ec_device *cros_ec = ec_dev->ec_dev; | 484 | struct cros_ec_device *cros_ec = ec_dev->ec_dev; |
| 279 | struct cros_ec_cec *cros_ec_cec; | 485 | struct cros_ec_cec *cros_ec_cec; |
| 486 | struct cros_ec_cec_port *port; | ||
| 280 | struct device *hdmi_dev; | 487 | struct device *hdmi_dev; |
| 281 | const char *conn = NULL; | 488 | const char * const *conns = NULL; |
| 282 | int ret; | 489 | int ret; |
| 283 | 490 | ||
| 284 | hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn); | 491 | hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conns); |
| 285 | if (IS_ERR(hdmi_dev)) | 492 | if (IS_ERR(hdmi_dev)) |
| 286 | return PTR_ERR(hdmi_dev); | 493 | return PTR_ERR(hdmi_dev); |
| 287 | 494 | ||
| @@ -295,18 +502,19 @@ static int cros_ec_cec_probe(struct platform_device *pdev) · 7 unmodified lines | |||
| 295 | 502 | ||
| 296 | device_init_wakeup(&pdev->dev, 1); | 503 | device_init_wakeup(&pdev->dev, 1); |
| 297 | 504 | ||
| 298 | cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, | 505 | ret = cros_ec_cec_get_num_ports(cros_ec_cec); |
| 299 | DRV_NAME, | 506 | if (ret) |
| 300 | CEC_CAP_DEFAULTS | | 507 | return ret; |
| 301 | CEC_CAP_CONNECTOR_INFO, 1); | ||
| 302 | if (IS_ERR(cros_ec_cec->adap)) | ||
| 303 | return PTR_ERR(cros_ec_cec->adap); | ||
| 304 | 508 | ||
| 305 | cros_ec_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, conn, | 509 | ret = cros_ec_cec_get_write_cmd_version(cros_ec_cec); |
| 306 | cros_ec_cec->adap); | 510 | if (ret) |
| 307 | if (!cros_ec_cec->notify) { | 511 | return ret; |
| 308 | ret = -ENOMEM; | 512 | |
| 309 | goto out_probe_adapter; | 513 | for (int i = 0; i < cros_ec_cec->num_ports; i++) { |
| 514 | ret = cros_ec_cec_init_port(&pdev->dev, cros_ec_cec, i, | ||
| 515 | hdmi_dev, conns); | ||
| 516 | if (ret) | ||
| 517 | goto unregister_ports; | ||
| 310 | } | 518 | } |
| 311 | 519 | ||
| 312 | /* Get CEC events from the EC. */ | 520 | /* Get CEC events from the EC. */ |
| @@ -315,20 +523,24 @@ static int cros_ec_cec_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 315 | &cros_ec_cec->notifier); | 523 | &cros_ec_cec->notifier); |
| 316 | if (ret) { | 524 | if (ret) { |
| 317 | dev_err(&pdev->dev, "failed to register notifier\n"); | 525 | dev_err(&pdev->dev, "failed to register notifier\n"); |
| 318 | goto out_probe_notify; | 526 | goto unregister_ports; |
| 319 | } | 527 | } |
| 320 | 528 | ||
| 321 | ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev); | ||
| 322 | if (ret < 0) | ||
| 323 | goto out_probe_notify; | ||
| 324 | |||
| 325 | return 0; | 529 | return 0; |
| 326 | 530 | ||
| 327 | out_probe_notify: | 531 | unregister_ports: |
| 328 | cec_notifier_cec_adap_unregister(cros_ec_cec->notify, | 532 | /* |
| 329 | cros_ec_cec->adap); | 533 | * Unregister any adapters which have been registered. We don't add the |
| 330 | out_probe_adapter: | 534 | * port to the array until the adapter has been registered successfully, |
| 331 | cec_delete_adapter(cros_ec_cec->adap); | 535 | * so any non-NULL ports must have been registered. |
| 536 | */ | ||
| 537 | for (int i = 0; i < cros_ec_cec->num_ports; i++) { | ||
| 538 | port = cros_ec_cec->ports[i]; | ||
| 539 | if (!port) | ||
| 540 | break; | ||
| 541 | cec_notifier_cec_adap_unregister(port->notify, port->adap); | ||
| 542 | cec_unregister_adapter(port->adap); | ||
| 543 | } | ||
| 332 | return ret; | 544 | return ret; |
| 333 | } | 545 | } |
| 334 | 546 | ||
| @@ -336,6 +548,7 @@ static void cros_ec_cec_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 336 | { | 548 | { |
| 337 | struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); | 549 | struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); |
| 338 | struct device *dev = &pdev->dev; | 550 | struct device *dev = &pdev->dev; |
| 551 | struct cros_ec_cec_port *port; | ||
| 339 | int ret; | 552 | int ret; |
| 340 | 553 | ||
| 341 | /* | 554 | /* |
| @@ -349,9 +562,11 @@ static void cros_ec_cec_remove(struct platform_device *pdev) · 7 unmodified lines | |||
| 349 | if (ret) | 562 | if (ret) |
| 350 | dev_err(dev, "failed to unregister notifier\n"); | 563 | dev_err(dev, "failed to unregister notifier\n"); |
| 351 | 564 | ||
| 352 | cec_notifier_cec_adap_unregister(cros_ec_cec->notify, | 565 | for (int i = 0; i < cros_ec_cec->num_ports; i++) { |
| 353 | cros_ec_cec->adap); | 566 | port = cros_ec_cec->ports[i]; |
| 354 | cec_unregister_adapter(cros_ec_cec->adap); | 567 | cec_notifier_cec_adap_unregister(port->notify, port->adap); |
| 568 | cec_unregister_adapter(port->adap); | ||
| 569 | } | ||
| 355 | } | 570 | } |
| 356 | 571 | ||
| 357 | static struct platform_driver cros_ec_cec_driver = { | 572 | static struct platform_driver cros_ec_cec_driver = { |
| @@ -353,31 +353,21 @@ static const struct file_operations debugfs_stats_ops = { · 352 unmodified lines | |||
| 353 | int smsdvb_debugfs_create(struct smsdvb_client_t *client) | 353 | int smsdvb_debugfs_create(struct smsdvb_client_t *client) |
| 354 | { | 354 | { |
| 355 | struct smscore_device_t *coredev = client->coredev; | 355 | struct smscore_device_t *coredev = client->coredev; |
| 356 | struct dentry *d; | ||
| 357 | struct smsdvb_debugfs *debug_data; | 356 | struct smsdvb_debugfs *debug_data; |
| 358 | 357 | ||
| 359 | if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device) | 358 | if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device) |
| 360 | return -ENODEV; | 359 | return -ENODEV; |
| 361 | 360 | ||
| 362 | client->debugfs = debugfs_create_dir(coredev->devpath, | ||
| 363 | smsdvb_debugfs_usb_root); | ||
| 364 | if (IS_ERR_OR_NULL(client->debugfs)) { | ||
| 365 | pr_info("Unable to create debugfs %s directory.\n", | ||
| 366 | coredev->devpath); | ||
| 367 | return -ENODEV; | ||
| 368 | } | ||
| 369 | |||
| 370 | d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs, | ||
| 371 | client, &debugfs_stats_ops); | ||
| 372 | if (!d) { | ||
| 373 | debugfs_remove(client->debugfs); | ||
| 374 | return -ENOMEM; | ||
| 375 | } | ||
| 376 | |||
| 377 | debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL); | 361 | debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL); |
| 378 | if (!debug_data) | 362 | if (!debug_data) |
| 379 | return -ENOMEM; | 363 | return -ENOMEM; |
| 380 | 364 | ||
| 365 | client->debugfs = debugfs_create_dir(coredev->devpath, | ||
| 366 | smsdvb_debugfs_usb_root); | ||
| 367 | |||
| 368 | debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs, | ||
| 369 | client, &debugfs_stats_ops); | ||
| 370 | |||
| 381 | client->debug_data = debug_data; | 371 | client->debug_data = debug_data; |
| 382 | client->prt_dvb_stats = smsdvb_print_dvb_stats; | 372 | client->prt_dvb_stats = smsdvb_print_dvb_stats; |
| 383 | client->prt_isdb_stats = smsdvb_print_isdb_stats; | 373 | client->prt_isdb_stats = smsdvb_print_isdb_stats; |
| @@ -159,7 +159,7 @@ EXPORT_SYMBOL(frame_vector_to_pfns); · 158 unmodified lines | |||
| 159 | struct frame_vector *frame_vector_create(unsigned int nr_frames) | 159 | struct frame_vector *frame_vector_create(unsigned int nr_frames) |
| 160 | { | 160 | { |
| 161 | struct frame_vector *vec; | 161 | struct frame_vector *vec; |
| 162 | int size = sizeof(struct frame_vector) + sizeof(void *) * nr_frames; | 162 | int size = struct_size(vec, ptrs, nr_frames); |
| 163 | 163 | ||
| 164 | if (WARN_ON_ONCE(nr_frames == 0)) | 164 | if (WARN_ON_ONCE(nr_frames == 0)) |
| 165 | return NULL; | 165 | return NULL; |
| @@ -2890,7 +2890,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ · 2889 unmodified lines | |||
| 2890 | if (copy_timestamp) | 2890 | if (copy_timestamp) |
| 2891 | b->timestamp = ktime_get_ns(); | 2891 | b->timestamp = ktime_get_ns(); |
| 2892 | ret = vb2_core_qbuf(q, index, NULL, NULL); | 2892 | ret = vb2_core_qbuf(q, index, NULL, NULL); |
| 2893 | dprintk(q, 5, "vb2_dbuf result: %d\n", ret); | 2893 | dprintk(q, 5, "vb2_qbuf result: %d\n", ret); |
| 2894 | if (ret) | 2894 | if (ret) |
| 2895 | return ret; | 2895 | return ret; |
| 2896 | 2896 | ||
| @@ -542,13 +542,14 @@ static void vb2_dc_put_userptr(void *buf_priv) · 541 unmodified lines | |||
| 542 | */ | 542 | */ |
| 543 | dma_unmap_sgtable(buf->dev, sgt, buf->dma_dir, | 543 | dma_unmap_sgtable(buf->dev, sgt, buf->dma_dir, |
| 544 | DMA_ATTR_SKIP_CPU_SYNC); | 544 | DMA_ATTR_SKIP_CPU_SYNC); |
| 545 | pages = frame_vector_pages(buf->vec); | ||
| 546 | /* sgt should exist only if vector contains pages... */ | ||
| 547 | BUG_ON(IS_ERR(pages)); | ||
| 548 | if (buf->dma_dir == DMA_FROM_DEVICE || | 545 | if (buf->dma_dir == DMA_FROM_DEVICE || |
| 549 | buf->dma_dir == DMA_BIDIRECTIONAL) | 546 | buf->dma_dir == DMA_BIDIRECTIONAL) { |
| 550 | for (i = 0; i < frame_vector_count(buf->vec); i++) | 547 | pages = frame_vector_pages(buf->vec); |
| 551 | set_page_dirty_lock(pages[i]); | 548 | /* sgt should exist only if vector contains pages... */ |
| 549 | if (!WARN_ON_ONCE(IS_ERR(pages))) | ||
| 550 | for (i = 0; i < frame_vector_count(buf->vec); i++) | ||
| 551 | set_page_dirty_lock(pages[i]); | ||
| 552 | } | ||
| 552 | sg_free_table(sgt); | 553 | sg_free_table(sgt); |
| 553 | kfree(sgt); | 554 | kfree(sgt); |
| 554 | } else { | 555 | } else { |
| @@ -133,13 +133,15 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) · 132 unmodified lines | |||
| 133 | 133 | ||
| 134 | if (!buf->vec->is_pfns) { | 134 | if (!buf->vec->is_pfns) { |
| 135 | n_pages = frame_vector_count(buf->vec); | 135 | n_pages = frame_vector_count(buf->vec); |
| 136 | pages = frame_vector_pages(buf->vec); | ||
| 137 | if (vaddr) | 136 | if (vaddr) |
| 138 | vm_unmap_ram((void *)vaddr, n_pages); | 137 | vm_unmap_ram((void *)vaddr, n_pages); |
| 139 | if (buf->dma_dir == DMA_FROM_DEVICE || | 138 | if (buf->dma_dir == DMA_FROM_DEVICE || |
| 140 | buf->dma_dir == DMA_BIDIRECTIONAL) | 139 | buf->dma_dir == DMA_BIDIRECTIONAL) { |
| 141 | for (i = 0; i < n_pages; i++) | 140 | pages = frame_vector_pages(buf->vec); |
| 142 | set_page_dirty_lock(pages[i]); | 141 | if (!WARN_ON_ONCE(IS_ERR(pages))) |
| 142 | for (i = 0; i < n_pages; i++) | ||
| 143 | set_page_dirty_lock(pages[i]); | ||
| 144 | } | ||
| 143 | } else { | 145 | } else { |
| 144 | iounmap((__force void __iomem *)buf->vaddr); | 146 | iounmap((__force void __iomem *)buf->vaddr); |
| 145 | } | 147 | } |
| @@ -4779,8 +4779,8 @@ set_frequency(struct drx_demod_instance *demod, · 4778 unmodified lines | |||
| 4779 | bool image_to_select; | 4779 | bool image_to_select; |
| 4780 | s32 fm_frequency_shift = 0; | 4780 | s32 fm_frequency_shift = 0; |
| 4781 | 4781 | ||
| 4782 | rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false; | 4782 | rf_mirror = ext_attr->mirror == DRX_MIRROR_YES; |
| 4783 | tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true; | 4783 | tuner_mirror = !demod->my_common_attr->mirror_freq_spect; |
| 4784 | /* | 4784 | /* |
| 4785 | Program frequency shifter | 4785 | Program frequency shifter |
| 4786 | No need to account for mirroring on RF | 4786 | No need to account for mirroring on RF |
| @@ -8765,7 +8765,7 @@ static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *c · 3978 unmodified lines | |||
| 8765 | goto rw_error; | 8765 | goto rw_error; |
| 8766 | } | 8766 | } |
| 8767 | ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs; | 8767 | ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs; |
| 8768 | ext_attr->pos_image = (ext_attr->pos_image) ? false : true; | 8768 | ext_attr->pos_image = !ext_attr->pos_image; |
| 8769 | 8769 | ||
| 8770 | /* freeze dq/fq updating */ | 8770 | /* freeze dq/fq updating */ |
| 8771 | rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0); | 8771 | rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0); |
| @@ -1920,8 +1920,7 @@ static void m88ds3103_remove(struct i2c_client *client) · 1919 unmodified lines | |||
| 1920 | 1920 | ||
| 1921 | dev_dbg(&client->dev, "\n"); | 1921 | dev_dbg(&client->dev, "\n"); |
| 1922 | 1922 | ||
| 1923 | if (dev->dt_client) | 1923 | i2c_unregister_device(dev->dt_client); |
| 1924 | i2c_unregister_device(dev->dt_client); | ||
| 1925 | 1924 | ||
| 1926 | i2c_mux_del_adapters(dev->muxc); | 1925 | i2c_mux_del_adapters(dev->muxc); |
| 1927 | 1926 | ||
| @@ -99,6 +99,7 @@ config VIDEO_IMX214 · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | config VIDEO_IMX219 | 100 | config VIDEO_IMX219 |
| 101 | tristate "Sony IMX219 sensor support" | 101 | tristate "Sony IMX219 sensor support" |
| 102 | select V4L2_CCI_I2C | ||
| 102 | help | 103 | help |
| 103 | This is a Video4Linux2 sensor driver for the Sony | 104 | This is a Video4Linux2 sensor driver for the Sony |
| 104 | IMX219 camera. | 105 | IMX219 camera. |
| @@ -215,6 +216,16 @@ config VIDEO_MT9M111 · 110 unmodified lines | |||
| 215 | This driver supports MT9M111, MT9M112 and MT9M131 cameras from | 216 | This driver supports MT9M111, MT9M112 and MT9M131 cameras from |
| 216 | Micron/Aptina | 217 | Micron/Aptina |
| 217 | 218 | ||
| 219 | config VIDEO_MT9M114 | ||
| 220 | tristate "onsemi MT9M114 sensor support" | ||
| 221 | select V4L2_CCI_I2C | ||
| 222 | help | ||
| 223 | This is a Video4Linux2 sensor-level driver for the onsemi MT9M114 | ||
| 224 | camera. | ||
| 225 | |||
| 226 | To compile this driver as a module, choose M here: the | ||
| 227 | module will be called mt9m114. | ||
| 228 | |||
| 218 | config VIDEO_MT9P031 | 229 | config VIDEO_MT9P031 |
| 219 | tristate "Aptina MT9P031 support" | 230 | tristate "Aptina MT9P031 support" |
| 220 | select VIDEO_APTINA_PLL | 231 | select VIDEO_APTINA_PLL |
| @@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o · 64 unmodified lines | |||
| 65 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 65 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
| 66 | obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o | 66 | obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o |
| 67 | obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o | 67 | obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o |
| 68 | obj-$(CONFIG_VIDEO_MT9M114) += mt9m114.o | ||
| 68 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o | 69 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o |
| 69 | obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o | 70 | obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o |
| 70 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | 71 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o |
| @@ -411,43 +411,44 @@ static int adp1653_of_init(struct i2c_client *client, · 410 unmodified lines | |||
| 411 | struct device_node *node) | 411 | struct device_node *node) |
| 412 | { | 412 | { |
| 413 | struct adp1653_platform_data *pd; | 413 | struct adp1653_platform_data *pd; |
| 414 | struct device_node *child; | 414 | struct device_node *node_indicator = NULL; |
| 415 | struct device_node *node_flash; | ||
| 415 | 416 | ||
| 416 | pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL); | 417 | pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL); |
| 417 | if (!pd) | 418 | if (!pd) |
| 418 | return -ENOMEM; | 419 | return -ENOMEM; |
| 419 | flash->platform_data = pd; | 420 | flash->platform_data = pd; |
| 420 | 421 | ||
| 421 | child = of_get_child_by_name(node, "flash"); | 422 | node_flash = of_get_child_by_name(node, "flash"); |
| 422 | if (!child) | 423 | if (!node_flash) |
| 423 | return -EINVAL; | 424 | return -EINVAL; |
| 424 | 425 | ||
| 425 | if (of_property_read_u32(child, "flash-timeout-us", | 426 | if (of_property_read_u32(node_flash, "flash-timeout-us", |
| 426 | &pd->max_flash_timeout)) | 427 | &pd->max_flash_timeout)) |
| 427 | goto err; | 428 | goto err; |
| 428 | 429 | ||
| 429 | if (of_property_read_u32(child, "flash-max-microamp", | 430 | if (of_property_read_u32(node_flash, "flash-max-microamp", |
| 430 | &pd->max_flash_intensity)) | 431 | &pd->max_flash_intensity)) |
| 431 | goto err; | 432 | goto err; |
| 432 | 433 | ||
| 433 | pd->max_flash_intensity /= 1000; | 434 | pd->max_flash_intensity /= 1000; |
| 434 | 435 | ||
| 435 | if (of_property_read_u32(child, "led-max-microamp", | 436 | if (of_property_read_u32(node_flash, "led-max-microamp", |
| 436 | &pd->max_torch_intensity)) | 437 | &pd->max_torch_intensity)) |
| 437 | goto err; | 438 | goto err; |
| 438 | 439 | ||
| 439 | pd->max_torch_intensity /= 1000; | 440 | pd->max_torch_intensity /= 1000; |
| 440 | of_node_put(child); | ||
| 441 | 441 | ||
| 442 | child = of_get_child_by_name(node, "indicator"); | 442 | node_indicator = of_get_child_by_name(node, "indicator"); |
| 443 | if (!child) | 443 | if (!node_indicator) |
| 444 | return -EINVAL; | 444 | goto err; |
| 445 | 445 | ||
| 446 | if (of_property_read_u32(child, "led-max-microamp", | 446 | if (of_property_read_u32(node_indicator, "led-max-microamp", |
| 447 | &pd->max_indicator_intensity)) | 447 | &pd->max_indicator_intensity)) |
| 448 | goto err; | 448 | goto err; |
| 449 | 449 | ||
| 450 | of_node_put(child); | 450 | of_node_put(node_flash); |
| 451 | of_node_put(node_indicator); | ||
| 451 | 452 | ||
| 452 | pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); | 453 | pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); |
| 453 | if (IS_ERR(pd->enable_gpio)) { | 454 | if (IS_ERR(pd->enable_gpio)) { |
| @@ -458,7 +459,8 @@ static int adp1653_of_init(struct i2c_client *client, · 4 unmodified lines | |||
| 458 | return 0; | 459 | return 0; |
| 459 | err: | 460 | err: |
| 460 | dev_err(&client->dev, "Required property not found\n"); | 461 | dev_err(&client->dev, "Required property not found\n"); |
| 461 | of_node_put(child); | 462 | of_node_put(node_flash); |
| 463 | of_node_put(node_indicator); | ||
| 462 | return -EINVAL; | 464 | return -EINVAL; |
| 463 | } | 465 | } |
| 464 | 466 | ||
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | * Copyright (C) 2013 Cogent Embedded, Inc. | 5 | * Copyright (C) 2013 Cogent Embedded, Inc. |
| 6 | * Copyright (C) 2013 Renesas Solutions Corp. | 6 | * Copyright (C) 2013 Renesas Solutions Corp. |
| 7 | */ | 7 | */ |
| 8 | #include <linux/mod_devicetable.h> | ||
| 8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 10 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| @@ -1395,7 +1396,6 @@ out_unlock: · 1384 unmodified lines | |||
| 1395 | 1396 | ||
| 1396 | static int adv7180_probe(struct i2c_client *client) | 1397 | static int adv7180_probe(struct i2c_client *client) |
| 1397 | { | 1398 | { |
| 1398 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | ||
| 1399 | struct device_node *np = client->dev.of_node; | 1399 | struct device_node *np = client->dev.of_node; |
| 1400 | struct adv7180_state *state; | 1400 | struct adv7180_state *state; |
| 1401 | struct v4l2_subdev *sd; | 1401 | struct v4l2_subdev *sd; |
| @@ -1411,7 +1411,7 @@ static int adv7180_probe(struct i2c_client *client) · 9 unmodified lines | |||
| 1411 | 1411 | ||
| 1412 | state->client = client; | 1412 | state->client = client; |
| 1413 | state->field = V4L2_FIELD_ALTERNATE; | 1413 | state->field = V4L2_FIELD_ALTERNATE; |
| 1414 | state->chip_info = (struct adv7180_chip_info *)id->driver_data; | 1414 | state->chip_info = i2c_get_match_data(client); |
| 1415 | 1415 | ||
| 1416 | state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", | 1416 | state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", |
| 1417 | GPIOD_OUT_HIGH); | 1417 | GPIOD_OUT_HIGH); |
| @@ -1536,22 +1536,6 @@ static void adv7180_remove(struct i2c_client *client) · 118 unmodified lines | |||
| 1536 | mutex_destroy(&state->mutex); | 1536 | mutex_destroy(&state->mutex); |
| 1537 | } | 1537 | } |
| 1538 | 1538 | ||
| 1539 | static const struct i2c_device_id adv7180_id[] = { | ||
| 1540 | { "adv7180", (kernel_ulong_t)&adv7180_info }, | ||
| 1541 | { "adv7180cp", (kernel_ulong_t)&adv7180_info }, | ||
| 1542 | { "adv7180st", (kernel_ulong_t)&adv7180_info }, | ||
| 1543 | { "adv7182", (kernel_ulong_t)&adv7182_info }, | ||
| 1544 | { "adv7280", (kernel_ulong_t)&adv7280_info }, | ||
| 1545 | { "adv7280-m", (kernel_ulong_t)&adv7280_m_info }, | ||
| 1546 | { "adv7281", (kernel_ulong_t)&adv7281_info }, | ||
| 1547 | { "adv7281-m", (kernel_ulong_t)&adv7281_m_info }, | ||
| 1548 | { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info }, | ||
| 1549 | { "adv7282", (kernel_ulong_t)&adv7282_info }, | ||
| 1550 | { "adv7282-m", (kernel_ulong_t)&adv7282_m_info }, | ||
| 1551 | {}, | ||
| 1552 | }; | ||
| 1553 | MODULE_DEVICE_TABLE(i2c, adv7180_id); | ||
| 1554 | |||
| 1555 | #ifdef CONFIG_PM_SLEEP | 1539 | #ifdef CONFIG_PM_SLEEP |
| 1556 | static int adv7180_suspend(struct device *dev) | 1540 | static int adv7180_suspend(struct device *dev) |
| 1557 | { | 1541 | { |
| @@ -1585,30 +1569,43 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); · 27 unmodified lines | |||
| 1585 | #define ADV7180_PM_OPS NULL | 1569 | #define ADV7180_PM_OPS NULL |
| 1586 | #endif | 1570 | #endif |
| 1587 | 1571 | ||
| 1588 | #ifdef CONFIG_OF | 1572 | static const struct i2c_device_id adv7180_id[] = { |
| 1589 | static const struct of_device_id adv7180_of_id[] = { | 1573 | { "adv7180", (kernel_ulong_t)&adv7180_info }, |
| 1590 | { .compatible = "adi,adv7180", }, | 1574 | { "adv7180cp", (kernel_ulong_t)&adv7180_info }, |
| 1591 | { .compatible = "adi,adv7180cp", }, | 1575 | { "adv7180st", (kernel_ulong_t)&adv7180_info }, |
| 1592 | { .compatible = "adi,adv7180st", }, | 1576 | { "adv7182", (kernel_ulong_t)&adv7182_info }, |
| 1593 | { .compatible = "adi,adv7182", }, | 1577 | { "adv7280", (kernel_ulong_t)&adv7280_info }, |
| 1594 | { .compatible = "adi,adv7280", }, | 1578 | { "adv7280-m", (kernel_ulong_t)&adv7280_m_info }, |
| 1595 | { .compatible = "adi,adv7280-m", }, | 1579 | { "adv7281", (kernel_ulong_t)&adv7281_info }, |
| 1596 | { .compatible = "adi,adv7281", }, | 1580 | { "adv7281-m", (kernel_ulong_t)&adv7281_m_info }, |
| 1597 | { .compatible = "adi,adv7281-m", }, | 1581 | { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info }, |
| 1598 | { .compatible = "adi,adv7281-ma", }, | 1582 | { "adv7282", (kernel_ulong_t)&adv7282_info }, |
| 1599 | { .compatible = "adi,adv7282", }, | 1583 | { "adv7282-m", (kernel_ulong_t)&adv7282_m_info }, |
| 1600 | { .compatible = "adi,adv7282-m", }, | 1584 | {} |
| 1601 | { }, | ||
| 1602 | }; | 1585 | }; |
| 1586 | MODULE_DEVICE_TABLE(i2c, adv7180_id); | ||
| 1603 | 1587 | ||
| 1588 | static const struct of_device_id adv7180_of_id[] = { | ||
| 1589 | { .compatible = "adi,adv7180", &adv7180_info }, | ||
| 1590 | { .compatible = "adi,adv7180cp", &adv7180_info }, | ||
| 1591 | { .compatible = "adi,adv7180st", &adv7180_info }, | ||
| 1592 | { .compatible = "adi,adv7182", &adv7182_info }, | ||
| 1593 | { .compatible = "adi,adv7280", &adv7280_info }, | ||
| 1594 | { .compatible = "adi,adv7280-m", &adv7280_m_info }, | ||
| 1595 | { .compatible = "adi,adv7281", &adv7281_info }, | ||
| 1596 | { .compatible = "adi,adv7281-m", &adv7281_m_info }, | ||
| 1597 | { .compatible = "adi,adv7281-ma", &adv7281_ma_info }, | ||
| 1598 | { .compatible = "adi,adv7282", &adv7282_info }, | ||
| 1599 | { .compatible = "adi,adv7282-m", &adv7282_m_info }, | ||
| 1600 | {} | ||
| 1601 | }; | ||
| 1604 | MODULE_DEVICE_TABLE(of, adv7180_of_id); | 1602 | MODULE_DEVICE_TABLE(of, adv7180_of_id); |
| 1605 | #endif | ||
| 1606 | 1603 | ||
| 1607 | static struct i2c_driver adv7180_driver = { | 1604 | static struct i2c_driver adv7180_driver = { |
| 1608 | .driver = { | 1605 | .driver = { |
| 1609 | .name = KBUILD_MODNAME, | 1606 | .name = KBUILD_MODNAME, |
| 1610 | .pm = ADV7180_PM_OPS, | 1607 | .pm = ADV7180_PM_OPS, |
| 1611 | .of_match_table = of_match_ptr(adv7180_of_id), | 1608 | .of_match_table = adv7180_of_id, |
| 1612 | }, | 1609 | }, |
| 1613 | .probe = adv7180_probe, | 1610 | .probe = adv7180_probe, |
| 1614 | .remove = adv7180_remove, | 1611 | .remove = adv7180_remove, |
| @@ -133,8 +133,6 @@ struct ar0521_dev { · 132 unmodified lines | |||
| 133 | u16 mult2; | 133 | u16 mult2; |
| 134 | u16 vt_pix; | 134 | u16 vt_pix; |
| 135 | } pll; | 135 | } pll; |
| 136 | |||
| 137 | bool streaming; | ||
| 138 | }; | 136 | }; |
| 139 | 137 | ||
| 140 | static inline struct ar0521_dev *to_ar0521_dev(struct v4l2_subdev *sd) | 138 | static inline struct ar0521_dev *to_ar0521_dev(struct v4l2_subdev *sd) |
| @@ -991,12 +989,9 @@ static int ar0521_s_stream(struct v4l2_subdev *sd, int enable) · 850 unmodified lines | |||
| 991 | int ret; | 989 | int ret; |
| 992 | 990 | ||
| 993 | mutex_lock(&sensor->lock); | 991 | mutex_lock(&sensor->lock); |
| 994 | |||
| 995 | ret = ar0521_set_stream(sensor, enable); | 992 | ret = ar0521_set_stream(sensor, enable); |
| 996 | if (!ret) | ||
| 997 | sensor->streaming = enable; | ||
| 998 | |||
| 999 | mutex_unlock(&sensor->lock); | 993 | mutex_unlock(&sensor->lock); |
| 994 | |||
| 1000 | return ret; | 995 | return ret; |
| 1001 | } | 996 | } |
| 1002 | 997 | ||
| @@ -1023,28 +1018,6 @@ static const struct v4l2_subdev_ops ar0521_subdev_ops = { · 20 unmodified lines | |||
| 1023 | .pad = &ar0521_pad_ops, | 1018 | .pad = &ar0521_pad_ops, |
| 1024 | }; | 1019 | }; |
| 1025 | 1020 | ||
| 1026 | static int __maybe_unused ar0521_suspend(struct device *dev) | ||
| 1027 | { | ||
| 1028 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1029 | struct ar0521_dev *sensor = to_ar0521_dev(sd); | ||
| 1030 | |||
| 1031 | if (sensor->streaming) | ||
| 1032 | ar0521_set_stream(sensor, 0); | ||
| 1033 | |||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static int __maybe_unused ar0521_resume(struct device *dev) | ||
| 1038 | { | ||
| 1039 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1040 | struct ar0521_dev *sensor = to_ar0521_dev(sd); | ||
| 1041 | |||
| 1042 | if (sensor->streaming) | ||
| 1043 | return ar0521_set_stream(sensor, 1); | ||
| 1044 | |||
| 1045 | return 0; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static int ar0521_probe(struct i2c_client *client) | 1021 | static int ar0521_probe(struct i2c_client *client) |
| 1049 | { | 1022 | { |
| 1050 | struct v4l2_fwnode_endpoint ep = { | 1023 | struct v4l2_fwnode_endpoint ep = { |
| @@ -1183,7 +1156,6 @@ static void ar0521_remove(struct i2c_client *client) · 132 unmodified lines | |||
| 1183 | } | 1156 | } |
| 1184 | 1157 | ||
| 1185 | static const struct dev_pm_ops ar0521_pm_ops = { | 1158 | static const struct dev_pm_ops ar0521_pm_ops = { |
| 1186 | SET_SYSTEM_SLEEP_PM_OPS(ar0521_suspend, ar0521_resume) | ||
| 1187 | SET_RUNTIME_PM_OPS(ar0521_power_off, ar0521_power_on, NULL) | 1159 | SET_RUNTIME_PM_OPS(ar0521_power_off, ar0521_power_on, NULL) |
| 1188 | }; | 1160 | }; |
| 1189 | static const struct of_device_id ar0521_dt_ids[] = { | 1161 | static const struct of_device_id ar0521_dt_ids[] = { |
| @@ -508,9 +508,8 @@ static void __ccs_update_exposure_limits(struct ccs_sensor *sensor) · 507 unmodified lines | |||
| 508 | struct v4l2_ctrl *ctrl = sensor->exposure; | 508 | struct v4l2_ctrl *ctrl = sensor->exposure; |
| 509 | int max; | 509 | int max; |
| 510 | 510 | ||
| 511 | max = sensor->pixel_array->crop[CCS_PA_PAD_SRC].height | 511 | max = sensor->pa_src.height + sensor->vblank->val - |
| 512 | + sensor->vblank->val | 512 | CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); |
| 513 | - CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); | ||
| 514 | 513 | ||
| 515 | __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max); | 514 | __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max); |
| 516 | } | 515 | } |
| @@ -728,15 +727,12 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) · 211 unmodified lines | |||
| 728 | break; | 727 | break; |
| 729 | case V4L2_CID_VBLANK: | 728 | case V4L2_CID_VBLANK: |
| 730 | rval = ccs_write(sensor, FRAME_LENGTH_LINES, | 729 | rval = ccs_write(sensor, FRAME_LENGTH_LINES, |
| 731 | sensor->pixel_array->crop[ | 730 | sensor->pa_src.height + ctrl->val); |
| 732 | CCS_PA_PAD_SRC].height | ||
| 733 | + ctrl->val); | ||
| 734 | 731 | ||
| 735 | break; | 732 | break; |
| 736 | case V4L2_CID_HBLANK: | 733 | case V4L2_CID_HBLANK: |
| 737 | rval = ccs_write(sensor, LINE_LENGTH_PCK, | 734 | rval = ccs_write(sensor, LINE_LENGTH_PCK, |
| 738 | sensor->pixel_array->crop[CCS_PA_PAD_SRC].width | 735 | sensor->pa_src.width + ctrl->val); |
| 739 | + ctrl->val); | ||
| 740 | 736 | ||
| 741 | break; | 737 | break; |
| 742 | case V4L2_CID_TEST_PATTERN: | 738 | case V4L2_CID_TEST_PATTERN: |
| @@ -1214,15 +1210,13 @@ static void ccs_update_blanking(struct ccs_sensor *sensor) · 471 unmodified lines | |||
| 1214 | 1210 | ||
| 1215 | min = max_t(int, | 1211 | min = max_t(int, |
| 1216 | CCS_LIM(sensor, MIN_FRAME_BLANKING_LINES), | 1212 | CCS_LIM(sensor, MIN_FRAME_BLANKING_LINES), |
| 1217 | min_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height); | 1213 | min_fll - sensor->pa_src.height); |
| 1218 | max = max_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height; | 1214 | max = max_fll - sensor->pa_src.height; |
| 1219 | 1215 | ||
| 1220 | __v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); | 1216 | __v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); |
| 1221 | 1217 | ||
| 1222 | min = max_t(int, | 1218 | min = max_t(int, min_llp - sensor->pa_src.width, min_lbp); |
| 1223 | min_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width, | 1219 | max = max_llp - sensor->pa_src.width; |
| 1224 | min_lbp); | ||
| 1225 | max = max_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width; | ||
| 1226 | 1220 | ||
| 1227 | __v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min); | 1221 | __v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min); |
| 1228 | 1222 | ||
| @@ -1246,10 +1240,8 @@ static int ccs_pll_blanking_update(struct ccs_sensor *sensor) · 17 unmodified lines | |||
| 1246 | 1240 | ||
| 1247 | dev_dbg(&client->dev, "real timeperframe\t100/%d\n", | 1241 | dev_dbg(&client->dev, "real timeperframe\t100/%d\n", |
| 1248 | sensor->pll.pixel_rate_pixel_array / | 1242 | sensor->pll.pixel_rate_pixel_array / |
| 1249 | ((sensor->pixel_array->crop[CCS_PA_PAD_SRC].width | 1243 | ((sensor->pa_src.width + sensor->hblank->val) * |
| 1250 | + sensor->hblank->val) * | 1244 | (sensor->pa_src.height + sensor->vblank->val) / 100)); |
| 1251 | (sensor->pixel_array->crop[CCS_PA_PAD_SRC].height | ||
| 1252 | + sensor->vblank->val) / 100)); | ||
| 1253 | 1245 | ||
| 1254 | return 0; | 1246 | return 0; |
| 1255 | } | 1247 | } |
| @@ -1756,28 +1748,22 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) · 500 unmodified lines | |||
| 1756 | goto out; | 1748 | goto out; |
| 1757 | 1749 | ||
| 1758 | /* Analog crop start coordinates */ | 1750 | /* Analog crop start coordinates */ |
| 1759 | rval = ccs_write(sensor, X_ADDR_START, | 1751 | rval = ccs_write(sensor, X_ADDR_START, sensor->pa_src.left); |
| 1760 | sensor->pixel_array->crop[CCS_PA_PAD_SRC].left); | ||
| 1761 | if (rval < 0) | 1752 | if (rval < 0) |
| 1762 | goto out; | 1753 | goto out; |
| 1763 | 1754 | ||
| 1764 | rval = ccs_write(sensor, Y_ADDR_START, | 1755 | rval = ccs_write(sensor, Y_ADDR_START, sensor->pa_src.top); |
| 1765 | sensor->pixel_array->crop[CCS_PA_PAD_SRC].top); | ||
| 1766 | if (rval < 0) | 1756 | if (rval < 0) |
| 1767 | goto out; | 1757 | goto out; |
| 1768 | 1758 | ||
| 1769 | /* Analog crop end coordinates */ | 1759 | /* Analog crop end coordinates */ |
| 1770 | rval = ccs_write( | 1760 | rval = ccs_write(sensor, X_ADDR_END, |
| 1771 | sensor, X_ADDR_END, | 1761 | sensor->pa_src.left + sensor->pa_src.width - 1); |
| 1772 | sensor->pixel_array->crop[CCS_PA_PAD_SRC].left | ||
| 1773 | + sensor->pixel_array->crop[CCS_PA_PAD_SRC].width - 1); | ||
| 1774 | if (rval < 0) | 1762 | if (rval < 0) |
| 1775 | goto out; | 1763 | goto out; |
| 1776 | 1764 | ||
| 1777 | rval = ccs_write( | 1765 | rval = ccs_write(sensor, Y_ADDR_END, |
| 1778 | sensor, Y_ADDR_END, | 1766 | sensor->pa_src.top + sensor->pa_src.height - 1); |
| 1779 | sensor->pixel_array->crop[CCS_PA_PAD_SRC].top | ||
| 1780 | + sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - 1); | ||
| 1781 | if (rval < 0) | 1767 | if (rval < 0) |
| 1782 | goto out; | 1768 | goto out; |
| 1783 | 1769 | ||
| @@ -1789,27 +1775,23 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) · 5 unmodified lines | |||
| 1789 | /* Digital crop */ | 1775 | /* Digital crop */ |
| 1790 | if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) | 1776 | if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) |
| 1791 | == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { | 1777 | == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { |
| 1792 | rval = ccs_write( | 1778 | rval = ccs_write(sensor, DIGITAL_CROP_X_OFFSET, |
| 1793 | sensor, DIGITAL_CROP_X_OFFSET, | 1779 | sensor->scaler_sink.left); |
| 1794 | sensor->scaler->crop[CCS_PAD_SINK].left); | ||
| 1795 | if (rval < 0) | 1780 | if (rval < 0) |
| 1796 | goto out; | 1781 | goto out; |
| 1797 | 1782 | ||
| 1798 | rval = ccs_write( | 1783 | rval = ccs_write(sensor, DIGITAL_CROP_Y_OFFSET, |
| 1799 | sensor, DIGITAL_CROP_Y_OFFSET, | 1784 | sensor->scaler_sink.top); |
| 1800 | sensor->scaler->crop[CCS_PAD_SINK].top); | ||
| 1801 | if (rval < 0) | 1785 | if (rval < 0) |
| 1802 | goto out; | 1786 | goto out; |
| 1803 | 1787 | ||
| 1804 | rval = ccs_write( | 1788 | rval = ccs_write(sensor, DIGITAL_CROP_IMAGE_WIDTH, |
| 1805 | sensor, DIGITAL_CROP_IMAGE_WIDTH, | 1789 | sensor->scaler_sink.width); |
| 1806 | sensor->scaler->crop[CCS_PAD_SINK].width); | ||
| 1807 | if (rval < 0) | 1790 | if (rval < 0) |
| 1808 | goto out; | 1791 | goto out; |
| 1809 | 1792 | ||
| 1810 | rval = ccs_write( | 1793 | rval = ccs_write(sensor, DIGITAL_CROP_IMAGE_HEIGHT, |
| 1811 | sensor, DIGITAL_CROP_IMAGE_HEIGHT, | 1794 | sensor->scaler_sink.height); |
| 1812 | sensor->scaler->crop[CCS_PAD_SINK].height); | ||
| 1813 | if (rval < 0) | 1795 | if (rval < 0) |
| 1814 | goto out; | 1796 | goto out; |
| 1815 | } | 1797 | } |
| @@ -1827,12 +1809,10 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) · 11 unmodified lines | |||
| 1827 | } | 1809 | } |
| 1828 | 1810 | ||
| 1829 | /* Output size from sensor */ | 1811 | /* Output size from sensor */ |
| 1830 | rval = ccs_write(sensor, X_OUTPUT_SIZE, | 1812 | rval = ccs_write(sensor, X_OUTPUT_SIZE, sensor->src_src.width); |
| 1831 | sensor->src->crop[CCS_PAD_SRC].width); | ||
| 1832 | if (rval < 0) | 1813 | if (rval < 0) |
| 1833 | goto out; | 1814 | goto out; |
| 1834 | rval = ccs_write(sensor, Y_OUTPUT_SIZE, | 1815 | rval = ccs_write(sensor, Y_OUTPUT_SIZE, sensor->src_src.height); |
| 1835 | sensor->src->crop[CCS_PAD_SRC].height); | ||
| 1836 | if (rval < 0) | 1816 | if (rval < 0) |
| 1837 | goto out; | 1817 | goto out; |
| 1838 | 1818 | ||
| @@ -1923,9 +1903,6 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) · 84 unmodified lines | |||
| 1923 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | 1903 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 1924 | int rval; | 1904 | int rval; |
| 1925 | 1905 | ||
| 1926 | if (sensor->streaming == enable) | ||
| 1927 | return 0; | ||
| 1928 | |||
| 1929 | if (!enable) { | 1906 | if (!enable) { |
| 1930 | ccs_stop_streaming(sensor); | 1907 | ccs_stop_streaming(sensor); |
| 1931 | sensor->streaming = false; | 1908 | sensor->streaming = false; |
| @@ -2053,24 +2030,8 @@ static int __ccs_get_format(struct v4l2_subdev *subdev, · 121 unmodified lines | |||
| 2053 | struct v4l2_subdev_state *sd_state, | 2030 | struct v4l2_subdev_state *sd_state, |
| 2054 | struct v4l2_subdev_format *fmt) | 2031 | struct v4l2_subdev_format *fmt) |
| 2055 | { | 2032 | { |
| 2056 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2033 | fmt->format = *v4l2_subdev_get_pad_format(subdev, sd_state, fmt->pad); |
| 2057 | 2034 | fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); | |
| 2058 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | ||
| 2059 | fmt->format = *v4l2_subdev_get_try_format(subdev, sd_state, | ||
| 2060 | fmt->pad); | ||
| 2061 | } else { | ||
| 2062 | struct v4l2_rect *r; | ||
| 2063 | |||
| 2064 | if (fmt->pad == ssd->source_pad) | ||
| 2065 | r = &ssd->crop[ssd->source_pad]; | ||
| 2066 | else | ||
| 2067 | r = &ssd->sink_fmt; | ||
| 2068 | |||
| 2069 | fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); | ||
| 2070 | fmt->format.width = r->width; | ||
| 2071 | fmt->format.height = r->height; | ||
| 2072 | fmt->format.field = V4L2_FIELD_NONE; | ||
| 2073 | } | ||
| 2074 | 2035 | ||
| 2075 | return 0; | 2036 | return 0; |
| 2076 | } | 2037 | } |
| @@ -2092,28 +2053,18 @@ static int ccs_get_format(struct v4l2_subdev *subdev, · 15 unmodified lines | |||
| 2092 | static void ccs_get_crop_compose(struct v4l2_subdev *subdev, | 2053 | static void ccs_get_crop_compose(struct v4l2_subdev *subdev, |
| 2093 | struct v4l2_subdev_state *sd_state, | 2054 | struct v4l2_subdev_state *sd_state, |
| 2094 | struct v4l2_rect **crops, | 2055 | struct v4l2_rect **crops, |
| 2095 | struct v4l2_rect **comps, int which) | 2056 | struct v4l2_rect **comps) |
| 2096 | { | 2057 | { |
| 2097 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2058 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2098 | unsigned int i; | 2059 | unsigned int i; |
| 2099 | 2060 | ||
| 2100 | if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { | 2061 | if (crops) |
| 2101 | if (crops) | 2062 | for (i = 0; i < subdev->entity.num_pads; i++) |
| 2102 | for (i = 0; i < subdev->entity.num_pads; i++) | 2063 | crops[i] = |
| 2103 | crops[i] = &ssd->crop[i]; | 2064 | v4l2_subdev_get_pad_crop(subdev, sd_state, i); |
| 2104 | if (comps) | 2065 | if (comps) |
| 2105 | *comps = &ssd->compose; | 2066 | *comps = v4l2_subdev_get_pad_compose(subdev, sd_state, |
| 2106 | } else { | 2067 | ssd->sink_pad); |
| 2107 | if (crops) { | ||
| 2108 | for (i = 0; i < subdev->entity.num_pads; i++) | ||
| 2109 | crops[i] = v4l2_subdev_get_try_crop(subdev, | ||
| 2110 | sd_state, | ||
| 2111 | i); | ||
| 2112 | } | ||
| 2113 | if (comps) | ||
| 2114 | *comps = v4l2_subdev_get_try_compose(subdev, sd_state, | ||
| 2115 | CCS_PAD_SINK); | ||
| 2116 | } | ||
| 2117 | } | 2068 | } |
| 2118 | 2069 | ||
| 2119 | /* Changes require propagation only on sink pad. */ | 2070 | /* Changes require propagation only on sink pad. */ |
| @@ -2124,8 +2075,9 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 4 unmodified lines | |||
| 2124 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | 2075 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2125 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2076 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2126 | struct v4l2_rect *comp, *crops[CCS_PADS]; | 2077 | struct v4l2_rect *comp, *crops[CCS_PADS]; |
| 2078 | struct v4l2_mbus_framefmt *fmt; | ||
| 2127 | 2079 | ||
| 2128 | ccs_get_crop_compose(subdev, sd_state, crops, &comp, which); | 2080 | ccs_get_crop_compose(subdev, sd_state, crops, &comp); |
| 2129 | 2081 | ||
| 2130 | switch (target) { | 2082 | switch (target) { |
| 2131 | case V4L2_SEL_TGT_CROP: | 2083 | case V4L2_SEL_TGT_CROP: |
| @@ -2136,6 +2088,7 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 4 unmodified lines | |||
| 2136 | sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); | 2088 | sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); |
| 2137 | sensor->scaling_mode = | 2089 | sensor->scaling_mode = |
| 2138 | CCS_SCALING_MODE_NO_SCALING; | 2090 | CCS_SCALING_MODE_NO_SCALING; |
| 2091 | sensor->scaler_sink = *comp; | ||
| 2139 | } else if (ssd == sensor->binner) { | 2092 | } else if (ssd == sensor->binner) { |
| 2140 | sensor->binning_horizontal = 1; | 2093 | sensor->binning_horizontal = 1; |
| 2141 | sensor->binning_vertical = 1; | 2094 | sensor->binning_vertical = 1; |
| @@ -2144,6 +2097,11 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 2 unmodified lines | |||
| 2144 | fallthrough; | 2097 | fallthrough; |
| 2145 | case V4L2_SEL_TGT_COMPOSE: | 2098 | case V4L2_SEL_TGT_COMPOSE: |
| 2146 | *crops[CCS_PAD_SRC] = *comp; | 2099 | *crops[CCS_PAD_SRC] = *comp; |
| 2100 | fmt = v4l2_subdev_get_pad_format(subdev, sd_state, CCS_PAD_SRC); | ||
| 2101 | fmt->width = comp->width; | ||
| 2102 | fmt->height = comp->height; | ||
| 2103 | if (which == V4L2_SUBDEV_FORMAT_ACTIVE && ssd == sensor->src) | ||
| 2104 | sensor->src_src = *crops[CCS_PAD_SRC]; | ||
| 2147 | break; | 2105 | break; |
| 2148 | default: | 2106 | default: |
| 2149 | WARN_ON_ONCE(1); | 2107 | WARN_ON_ONCE(1); |
| @@ -2252,14 +2210,12 @@ static int ccs_set_format(struct v4l2_subdev *subdev, · 102 unmodified lines | |||
| 2252 | CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), | 2210 | CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), |
| 2253 | CCS_LIM(sensor, MAX_Y_OUTPUT_SIZE)); | 2211 | CCS_LIM(sensor, MAX_Y_OUTPUT_SIZE)); |
| 2254 | 2212 | ||
| 2255 | ccs_get_crop_compose(subdev, sd_state, crops, NULL, fmt->which); | 2213 | ccs_get_crop_compose(subdev, sd_state, crops, NULL); |
| 2256 | 2214 | ||
| 2257 | crops[ssd->sink_pad]->left = 0; | 2215 | crops[ssd->sink_pad]->left = 0; |
| 2258 | crops[ssd->sink_pad]->top = 0; | 2216 | crops[ssd->sink_pad]->top = 0; |
| 2259 | crops[ssd->sink_pad]->width = fmt->format.width; | 2217 | crops[ssd->sink_pad]->width = fmt->format.width; |
| 2260 | crops[ssd->sink_pad]->height = fmt->format.height; | 2218 | crops[ssd->sink_pad]->height = fmt->format.height; |
| 2261 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
| 2262 | ssd->sink_fmt = *crops[ssd->sink_pad]; | ||
| 2263 | ccs_propagate(subdev, sd_state, fmt->which, V4L2_SEL_TGT_CROP); | 2219 | ccs_propagate(subdev, sd_state, fmt->which, V4L2_SEL_TGT_CROP); |
| 2264 | 2220 | ||
| 2265 | mutex_unlock(&sensor->mutex); | 2221 | mutex_unlock(&sensor->mutex); |
| @@ -2482,7 +2438,7 @@ static int ccs_set_compose(struct v4l2_subdev *subdev, · 216 unmodified lines | |||
| 2482 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2438 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2483 | struct v4l2_rect *comp, *crops[CCS_PADS]; | 2439 | struct v4l2_rect *comp, *crops[CCS_PADS]; |
| 2484 | 2440 | ||
| 2485 | ccs_get_crop_compose(subdev, sd_state, crops, &comp, sel->which); | 2441 | ccs_get_crop_compose(subdev, sd_state, crops, &comp); |
| 2486 | 2442 | ||
| 2487 | sel->r.top = 0; | 2443 | sel->r.top = 0; |
| 2488 | sel->r.left = 0; | 2444 | sel->r.left = 0; |
| @@ -2501,8 +2457,8 @@ static int ccs_set_compose(struct v4l2_subdev *subdev, · 12 unmodified lines | |||
| 2501 | return 0; | 2457 | return 0; |
| 2502 | } | 2458 | } |
| 2503 | 2459 | ||
| 2504 | static int __ccs_sel_supported(struct v4l2_subdev *subdev, | 2460 | static int ccs_sel_supported(struct v4l2_subdev *subdev, |
| 2505 | struct v4l2_subdev_selection *sel) | 2461 | struct v4l2_subdev_selection *sel) |
| 2506 | { | 2462 | { |
| 2507 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | 2463 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2508 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2464 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| @@ -2545,33 +2501,18 @@ static int ccs_set_crop(struct v4l2_subdev *subdev, · 36 unmodified lines | |||
| 2545 | { | 2501 | { |
| 2546 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | 2502 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2547 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2503 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2548 | struct v4l2_rect *src_size, *crops[CCS_PADS]; | 2504 | struct v4l2_rect src_size = { 0 }, *crops[CCS_PADS], *comp; |
| 2549 | struct v4l2_rect _r; | ||
| 2550 | 2505 | ||
| 2551 | ccs_get_crop_compose(subdev, sd_state, crops, NULL, sel->which); | 2506 | ccs_get_crop_compose(subdev, sd_state, crops, &comp); |
| 2552 | 2507 | ||
| 2553 | if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | 2508 | if (sel->pad == ssd->sink_pad) { |
| 2554 | if (sel->pad == ssd->sink_pad) | 2509 | struct v4l2_mbus_framefmt *mfmt = |
| 2555 | src_size = &ssd->sink_fmt; | 2510 | v4l2_subdev_get_pad_format(subdev, sd_state, sel->pad); |
| 2556 | else | 2511 | |
| 2557 | src_size = &ssd->compose; | 2512 | src_size.width = mfmt->width; |
| 2513 | src_size.height = mfmt->height; | ||
| 2558 | } else { | 2514 | } else { |
| 2559 | if (sel->pad == ssd->sink_pad) { | 2515 | src_size = *comp; |
| 2560 | _r.left = 0; | ||
| 2561 | _r.top = 0; | ||
| 2562 | _r.width = v4l2_subdev_get_try_format(subdev, | ||
| 2563 | sd_state, | ||
| 2564 | sel->pad) | ||
| 2565 | ->width; | ||
| 2566 | _r.height = v4l2_subdev_get_try_format(subdev, | ||
| 2567 | sd_state, | ||
| 2568 | sel->pad) | ||
| 2569 | ->height; | ||
| 2570 | src_size = &_r; | ||
| 2571 | } else { | ||
| 2572 | src_size = v4l2_subdev_get_try_compose( | ||
| 2573 | subdev, sd_state, ssd->sink_pad); | ||
| 2574 | } | ||
| 2575 | } | 2516 | } |
| 2576 | 2517 | ||
| 2577 | if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) { | 2518 | if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) { |
| @@ -2579,16 +2520,19 @@ static int ccs_set_crop(struct v4l2_subdev *subdev, · 1 unmodified line | |||
| 2579 | sel->r.top = 0; | 2520 | sel->r.top = 0; |
| 2580 | } | 2521 | } |
| 2581 | 2522 | ||
| 2582 | sel->r.width = min(sel->r.width, src_size->width); | 2523 | sel->r.width = min(sel->r.width, src_size.width); |
| 2583 | sel->r.height = min(sel->r.height, src_size->height); | 2524 | sel->r.height = min(sel->r.height, src_size.height); |
| 2584 | 2525 | ||
| 2585 | sel->r.left = min_t(int, sel->r.left, src_size->width - sel->r.width); | 2526 | sel->r.left = min_t(int, sel->r.left, src_size.width - sel->r.width); |
| 2586 | sel->r.top = min_t(int, sel->r.top, src_size->height - sel->r.height); | 2527 | sel->r.top = min_t(int, sel->r.top, src_size.height - sel->r.height); |
| 2587 | 2528 | ||
| 2588 | *crops[sel->pad] = sel->r; | 2529 | *crops[sel->pad] = sel->r; |
| 2589 | 2530 | ||
| 2590 | if (ssd != sensor->pixel_array && sel->pad == CCS_PAD_SINK) | 2531 | if (ssd != sensor->pixel_array && sel->pad == CCS_PAD_SINK) |
| 2591 | ccs_propagate(subdev, sd_state, sel->which, V4L2_SEL_TGT_CROP); | 2532 | ccs_propagate(subdev, sd_state, sel->which, V4L2_SEL_TGT_CROP); |
| 2533 | else if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE && | ||
| 2534 | ssd == sensor->pixel_array) | ||
| 2535 | sensor->pa_src = sel->r; | ||
| 2592 | 2536 | ||
| 2593 | return 0; | 2537 | return 0; |
| 2594 | } | 2538 | } |
| @@ -2601,44 +2545,36 @@ static void ccs_get_native_size(struct ccs_subdev *ssd, struct v4l2_rect *r) · 6 unmodified lines | |||
| 2601 | r->height = CCS_LIM(ssd->sensor, Y_ADDR_MAX) + 1; | 2545 | r->height = CCS_LIM(ssd->sensor, Y_ADDR_MAX) + 1; |
| 2602 | } | 2546 | } |
| 2603 | 2547 | ||
| 2604 | static int __ccs_get_selection(struct v4l2_subdev *subdev, | 2548 | static int ccs_get_selection(struct v4l2_subdev *subdev, |
| 2605 | struct v4l2_subdev_state *sd_state, | 2549 | struct v4l2_subdev_state *sd_state, |
| 2606 | struct v4l2_subdev_selection *sel) | 2550 | struct v4l2_subdev_selection *sel) |
| 2607 | { | 2551 | { |
| 2608 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | 2552 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2609 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); | 2553 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2610 | struct v4l2_rect *comp, *crops[CCS_PADS]; | 2554 | struct v4l2_rect *comp, *crops[CCS_PADS]; |
| 2611 | struct v4l2_rect sink_fmt; | ||
| 2612 | int ret; | 2555 | int ret; |
| 2613 | 2556 | ||
| 2614 | ret = __ccs_sel_supported(subdev, sel); | 2557 | ret = ccs_sel_supported(subdev, sel); |
| 2615 | if (ret) | 2558 | if (ret) |
| 2616 | return ret; | 2559 | return ret; |
| 2617 | 2560 | ||
| 2618 | ccs_get_crop_compose(subdev, sd_state, crops, &comp, sel->which); | 2561 | ccs_get_crop_compose(subdev, sd_state, crops, &comp); |
| 2619 | |||
| 2620 | if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
| 2621 | sink_fmt = ssd->sink_fmt; | ||
| 2622 | } else { | ||
| 2623 | struct v4l2_mbus_framefmt *fmt = | ||
| 2624 | v4l2_subdev_get_try_format(subdev, sd_state, | ||
| 2625 | ssd->sink_pad); | ||
| 2626 | |||
| 2627 | sink_fmt.left = 0; | ||
| 2628 | sink_fmt.top = 0; | ||
| 2629 | sink_fmt.width = fmt->width; | ||
| 2630 | sink_fmt.height = fmt->height; | ||
| 2631 | } | ||
| 2632 | 2562 | ||
| 2633 | switch (sel->target) { | 2563 | switch (sel->target) { |
| 2634 | case V4L2_SEL_TGT_CROP_BOUNDS: | 2564 | case V4L2_SEL_TGT_CROP_BOUNDS: |
| 2635 | case V4L2_SEL_TGT_NATIVE_SIZE: | 2565 | case V4L2_SEL_TGT_NATIVE_SIZE: |
| 2636 | if (ssd == sensor->pixel_array) | 2566 | if (ssd == sensor->pixel_array) { |
| 2637 | ccs_get_native_size(ssd, &sel->r); | 2567 | ccs_get_native_size(ssd, &sel->r); |
| 2638 | else if (sel->pad == ssd->sink_pad) | 2568 | } else if (sel->pad == ssd->sink_pad) { |
| 2639 | sel->r = sink_fmt; | 2569 | struct v4l2_mbus_framefmt *sink_fmt = |
| 2640 | else | 2570 | v4l2_subdev_get_pad_format(subdev, sd_state, |
| 2571 | ssd->sink_pad); | ||
| 2572 | sel->r.top = sel->r.left = 0; | ||
| 2573 | sel->r.width = sink_fmt->width; | ||
| 2574 | sel->r.height = sink_fmt->height; | ||
| 2575 | } else { | ||
| 2641 | sel->r = *comp; | 2576 | sel->r = *comp; |
| 2577 | } | ||
| 2642 | break; | 2578 | break; |
| 2643 | case V4L2_SEL_TGT_CROP: | 2579 | case V4L2_SEL_TGT_CROP: |
| 2644 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | 2580 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
| @@ -2652,20 +2588,6 @@ static int __ccs_get_selection(struct v4l2_subdev *subdev, · 7 unmodified lines | |||
| 2652 | return 0; | 2588 | return 0; |
| 2653 | } | 2589 | } |
| 2654 | 2590 | ||
| 2655 | static int ccs_get_selection(struct v4l2_subdev *subdev, | ||
| 2656 | struct v4l2_subdev_state *sd_state, | ||
| 2657 | struct v4l2_subdev_selection *sel) | ||
| 2658 | { | ||
| 2659 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | ||
| 2660 | int rval; | ||
| 2661 | |||
| 2662 | mutex_lock(&sensor->mutex); | ||
| 2663 | rval = __ccs_get_selection(subdev, sd_state, sel); | ||
| 2664 | mutex_unlock(&sensor->mutex); | ||
| 2665 | |||
| 2666 | return rval; | ||
| 2667 | } | ||
| 2668 | |||
| 2669 | static int ccs_set_selection(struct v4l2_subdev *subdev, | 2591 | static int ccs_set_selection(struct v4l2_subdev *subdev, |
| 2670 | struct v4l2_subdev_state *sd_state, | 2592 | struct v4l2_subdev_state *sd_state, |
| 2671 | struct v4l2_subdev_selection *sel) | 2593 | struct v4l2_subdev_selection *sel) |
| @@ -2673,7 +2595,7 @@ static int ccs_set_selection(struct v4l2_subdev *subdev, · 1 unmodified line | |||
| 2673 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | 2595 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2674 | int ret; | 2596 | int ret; |
| 2675 | 2597 | ||
| 2676 | ret = __ccs_sel_supported(subdev, sel); | 2598 | ret = ccs_sel_supported(subdev, sel); |
| 2677 | if (ret) | 2599 | if (ret) |
| 2678 | return ret; | 2600 | return ret; |
| 2679 | 2601 | ||
| @@ -2945,7 +2867,6 @@ static int ccs_identify_module(struct ccs_sensor *sensor) · 265 unmodified lines | |||
| 2945 | } | 2867 | } |
| 2946 | 2868 | ||
| 2947 | static const struct v4l2_subdev_ops ccs_ops; | 2869 | static const struct v4l2_subdev_ops ccs_ops; |
| 2948 | static const struct v4l2_subdev_internal_ops ccs_internal_ops; | ||
| 2949 | static const struct media_entity_operations ccs_entity_ops; | 2870 | static const struct media_entity_operations ccs_entity_ops; |
| 2950 | 2871 | ||
| 2951 | static int ccs_register_subdev(struct ccs_sensor *sensor, | 2872 | static int ccs_register_subdev(struct ccs_sensor *sensor, |
| @@ -2959,12 +2880,6 @@ static int ccs_register_subdev(struct ccs_sensor *sensor, · 7 unmodified lines | |||
| 2959 | if (!sink_ssd) | 2880 | if (!sink_ssd) |
| 2960 | return 0; | 2881 | return 0; |
| 2961 | 2882 | ||
| 2962 | rval = media_entity_pads_init(&ssd->sd.entity, ssd->npads, ssd->pads); | ||
| 2963 | if (rval) { | ||
| 2964 | dev_err(&client->dev, "media_entity_pads_init failed\n"); | ||
| 2965 | return rval; | ||
| 2966 | } | ||
| 2967 | |||
| 2968 | rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, &ssd->sd); | 2883 | rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, &ssd->sd); |
| 2969 | if (rval) { | 2884 | if (rval) { |
| 2970 | dev_err(&client->dev, "v4l2_device_register_subdev failed\n"); | 2885 | dev_err(&client->dev, "v4l2_device_register_subdev failed\n"); |
| @@ -3025,6 +2940,12 @@ out_err: · 54 unmodified lines | |||
| 3025 | static void ccs_cleanup(struct ccs_sensor *sensor) | 2940 | static void ccs_cleanup(struct ccs_sensor *sensor) |
| 3026 | { | 2941 | { |
| 3027 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | 2942 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 2943 | unsigned int i; | ||
| 2944 | |||
| 2945 | for (i = 0; i < sensor->ssds_used; i++) { | ||
| 2946 | v4l2_subdev_cleanup(&sensor->ssds[2].sd); | ||
| 2947 | media_entity_cleanup(&sensor->ssds[i].sd.entity); | ||
| 2948 | } | ||
| 3028 | 2949 | ||
| 3029 | device_remove_file(&client->dev, &dev_attr_nvm); | 2950 | device_remove_file(&client->dev, &dev_attr_nvm); |
| 3030 | device_remove_file(&client->dev, &dev_attr_ident); | 2951 | device_remove_file(&client->dev, &dev_attr_ident); |
| @@ -3032,14 +2953,17 @@ static void ccs_cleanup(struct ccs_sensor *sensor) · 1 unmodified line | |||
| 3032 | ccs_free_controls(sensor); | 2953 | ccs_free_controls(sensor); |
| 3033 | } | 2954 | } |
| 3034 | 2955 | ||
| 3035 | static void ccs_create_subdev(struct ccs_sensor *sensor, | 2956 | static int ccs_init_subdev(struct ccs_sensor *sensor, |
| 3036 | struct ccs_subdev *ssd, const char *name, | 2957 | struct ccs_subdev *ssd, const char *name, |
| 3037 | unsigned short num_pads, u32 function) | 2958 | unsigned short num_pads, u32 function, |
| 2959 | const char *lock_name, | ||
| 2960 | struct lock_class_key *lock_key) | ||
| 3038 | { | 2961 | { |
| 3039 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | 2962 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 2963 | int rval; | ||
| 3040 | 2964 | ||
| 3041 | if (!ssd) | 2965 | if (!ssd) |
| 3042 | return; | 2966 | return 0; |
| 3043 | 2967 | ||
| 3044 | if (ssd != sensor->src) | 2968 | if (ssd != sensor->src) |
| 3045 | v4l2_subdev_init(&ssd->sd, &ccs_ops); | 2969 | v4l2_subdev_init(&ssd->sd, &ccs_ops); |
| @@ -3053,57 +2977,70 @@ static void ccs_create_subdev(struct ccs_sensor *sensor, · 7 unmodified lines | |||
| 3053 | 2977 | ||
| 3054 | v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name); | 2978 | v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name); |
| 3055 | 2979 | ||
| 3056 | ccs_get_native_size(ssd, &ssd->sink_fmt); | ||
| 3057 | |||
| 3058 | ssd->compose.width = ssd->sink_fmt.width; | ||
| 3059 | ssd->compose.height = ssd->sink_fmt.height; | ||
| 3060 | ssd->crop[ssd->source_pad] = ssd->compose; | ||
| 3061 | ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE; | 2980 | ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE; |
| 3062 | if (ssd != sensor->pixel_array) { | 2981 | if (ssd != sensor->pixel_array) |
| 3063 | ssd->crop[ssd->sink_pad] = ssd->compose; | ||
| 3064 | ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK; | 2982 | ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK; |
| 3065 | } | ||
| 3066 | 2983 | ||
| 3067 | ssd->sd.entity.ops = &ccs_entity_ops; | 2984 | ssd->sd.entity.ops = &ccs_entity_ops; |
| 3068 | 2985 | ||
| 3069 | if (ssd == sensor->src) | 2986 | if (ssd != sensor->src) { |
| 3070 | return; | 2987 | ssd->sd.owner = THIS_MODULE; |
| 2988 | ssd->sd.dev = &client->dev; | ||
| 2989 | v4l2_set_subdevdata(&ssd->sd, client); | ||
| 2990 | } | ||
| 2991 | |||
| 2992 | rval = media_entity_pads_init(&ssd->sd.entity, ssd->npads, ssd->pads); | ||
| 2993 | if (rval) { | ||
| 2994 | dev_err(&client->dev, "media_entity_pads_init failed\n"); | ||
| 2995 | return rval; | ||
| 2996 | } | ||
| 3071 | 2997 | ||
| 3072 | ssd->sd.internal_ops = &ccs_internal_ops; | 2998 | rval = __v4l2_subdev_init_finalize(&ssd->sd, lock_name, lock_key); |
| 3073 | ssd->sd.owner = THIS_MODULE; | 2999 | if (rval) { |
| 3074 | ssd->sd.dev = &client->dev; | 3000 | media_entity_cleanup(&ssd->sd.entity); |
| 3075 | v4l2_set_subdevdata(&ssd->sd, client); | 3001 | return rval; |
| 3002 | } | ||
| 3003 | |||
| 3004 | return 0; | ||
| 3076 | } | 3005 | } |
| 3077 | 3006 | ||
| 3078 | static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 3007 | static int ccs_init_cfg(struct v4l2_subdev *sd, |
| 3008 | struct v4l2_subdev_state *sd_state) | ||
| 3079 | { | 3009 | { |
| 3080 | struct ccs_subdev *ssd = to_ccs_subdev(sd); | 3010 | struct ccs_subdev *ssd = to_ccs_subdev(sd); |
| 3081 | struct ccs_sensor *sensor = ssd->sensor; | 3011 | struct ccs_sensor *sensor = ssd->sensor; |
| 3082 | unsigned int i; | 3012 | unsigned int pad = ssd == sensor->pixel_array ? |
| 3013 | CCS_PA_PAD_SRC : CCS_PAD_SINK; | ||
| 3014 | struct v4l2_mbus_framefmt *fmt = | ||
| 3015 | v4l2_subdev_get_pad_format(sd, sd_state, pad); | ||
| 3016 | struct v4l2_rect *crop = | ||
| 3017 | v4l2_subdev_get_pad_crop(sd, sd_state, pad); | ||
| 3018 | bool is_active = !sd->active_state || sd->active_state == sd_state; | ||
| 3083 | 3019 | ||
| 3084 | mutex_lock(&sensor->mutex); | 3020 | mutex_lock(&sensor->mutex); |
| 3085 | 3021 | ||
| 3086 | for (i = 0; i < ssd->npads; i++) { | 3022 | ccs_get_native_size(ssd, crop); |
| 3087 | struct v4l2_mbus_framefmt *try_fmt = | ||
| 3088 | v4l2_subdev_get_try_format(sd, fh->state, i); | ||
| 3089 | struct v4l2_rect *try_crop = | ||
| 3090 | v4l2_subdev_get_try_crop(sd, fh->state, i); | ||
| 3091 | struct v4l2_rect *try_comp; | ||
| 3092 | 3023 | ||
| 3093 | ccs_get_native_size(ssd, try_crop); | 3024 | fmt->width = crop->width; |
| 3025 | fmt->height = crop->height; | ||
| 3026 | fmt->code = sensor->internal_csi_format->code; | ||
| 3027 | fmt->field = V4L2_FIELD_NONE; | ||
| 3094 | 3028 | ||
| 3095 | try_fmt->width = try_crop->width; | 3029 | if (ssd == sensor->pixel_array) { |
| 3096 | try_fmt->height = try_crop->height; | 3030 | if (is_active) |
| 3097 | try_fmt->code = sensor->internal_csi_format->code; | 3031 | sensor->pa_src = *crop; |
| 3098 | try_fmt->field = V4L2_FIELD_NONE; | ||
| 3099 | 3032 | ||
| 3100 | if (ssd != sensor->pixel_array) | 3033 | mutex_unlock(&sensor->mutex); |
| 3101 | continue; | 3034 | return 0; |
| 3102 | |||
| 3103 | try_comp = v4l2_subdev_get_try_compose(sd, fh->state, i); | ||
| 3104 | *try_comp = *try_crop; | ||
| 3105 | } | 3035 | } |
| 3106 | 3036 | ||
| 3037 | fmt = v4l2_subdev_get_pad_format(sd, sd_state, CCS_PAD_SRC); | ||
| 3038 | fmt->code = ssd == sensor->src ? | ||
| 3039 | sensor->csi_format->code : sensor->internal_csi_format->code; | ||
| 3040 | fmt->field = V4L2_FIELD_NONE; | ||
| 3041 | |||
| 3042 | ccs_propagate(sd, sd_state, is_active, V4L2_SEL_TGT_CROP); | ||
| 3043 | |||
| 3107 | mutex_unlock(&sensor->mutex); | 3044 | mutex_unlock(&sensor->mutex); |
| 3108 | 3045 | ||
| 3109 | return 0; | 3046 | return 0; |
| @@ -3116,6 +3053,7 @@ static const struct v4l2_subdev_video_ops ccs_video_ops = { · 6 unmodified lines | |||
| 3116 | }; | 3053 | }; |
| 3117 | 3054 | ||
| 3118 | static const struct v4l2_subdev_pad_ops ccs_pad_ops = { | 3055 | static const struct v4l2_subdev_pad_ops ccs_pad_ops = { |
| 3056 | .init_cfg = ccs_init_cfg, | ||
| 3119 | .enum_mbus_code = ccs_enum_mbus_code, | 3057 | .enum_mbus_code = ccs_enum_mbus_code, |
| 3120 | .get_fmt = ccs_get_format, | 3058 | .get_fmt = ccs_get_format, |
| 3121 | .set_fmt = ccs_set_format, | 3059 | .set_fmt = ccs_set_format, |
| @@ -3141,53 +3079,12 @@ static const struct media_entity_operations ccs_entity_ops = { · 19 unmodified lines | |||
| 3141 | static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { | 3079 | static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { |
| 3142 | .registered = ccs_registered, | 3080 | .registered = ccs_registered, |
| 3143 | .unregistered = ccs_unregistered, | 3081 | .unregistered = ccs_unregistered, |
| 3144 | .open = ccs_open, | ||
| 3145 | }; | ||
| 3146 | |||
| 3147 | static const struct v4l2_subdev_internal_ops ccs_internal_ops = { | ||
| 3148 | .open = ccs_open, | ||
| 3149 | }; | 3082 | }; |
| 3150 | 3083 | ||
| 3151 | /* ----------------------------------------------------------------------------- | 3084 | /* ----------------------------------------------------------------------------- |
| 3152 | * I2C Driver | 3085 | * I2C Driver |
| 3153 | */ | 3086 | */ |
| 3154 | 3087 | ||
| 3155 | static int __maybe_unused ccs_suspend(struct device *dev) | ||
| 3156 | { | ||
| 3157 | struct i2c_client *client = to_i2c_client(dev); | ||
| 3158 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
| 3159 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | ||
| 3160 | bool streaming = sensor->streaming; | ||
| 3161 | int rval; | ||
| 3162 | |||
| 3163 | rval = pm_runtime_resume_and_get(dev); | ||
| 3164 | if (rval < 0) | ||
| 3165 | return rval; | ||
| 3166 | |||
| 3167 | if (sensor->streaming) | ||
| 3168 | ccs_stop_streaming(sensor); | ||
| 3169 | |||
| 3170 | /* save state for resume */ | ||
| 3171 | sensor->streaming = streaming; | ||
| 3172 | |||
| 3173 | return 0; | ||
| 3174 | } | ||
| 3175 | |||
| 3176 | static int __maybe_unused ccs_resume(struct device *dev) | ||
| 3177 | { | ||
| 3178 | struct i2c_client *client = to_i2c_client(dev); | ||
| 3179 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
| 3180 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); | ||
| 3181 | int rval = 0; | ||
| 3182 | |||
| 3183 | pm_runtime_put(dev); | ||
| 3184 | |||
| 3185 | if (sensor->streaming) | ||
| 3186 | rval = ccs_start_streaming(sensor); | ||
| 3187 | |||
| 3188 | return rval; | ||
| 3189 | } | ||
| 3190 | |||
| 3191 | static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) | 3088 | static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) |
| 3192 | { | 3089 | { |
| 3193 | struct ccs_hwconfig *hwcfg = &sensor->hwcfg; | 3090 | struct ccs_hwconfig *hwcfg = &sensor->hwcfg; |
| @@ -3311,6 +3208,8 @@ static int ccs_firmware_name(struct i2c_client *client, · 117 unmodified lines | |||
| 3311 | 3208 | ||
| 3312 | static int ccs_probe(struct i2c_client *client) | 3209 | static int ccs_probe(struct i2c_client *client) |
| 3313 | { | 3210 | { |
| 3211 | static struct lock_class_key pixel_array_lock_key, binner_lock_key, | ||
| 3212 | scaler_lock_key; | ||
| 3314 | const struct ccs_device *ccsdev = device_get_match_data(&client->dev); | 3213 | const struct ccs_device *ccsdev = device_get_match_data(&client->dev); |
| 3315 | struct ccs_sensor *sensor; | 3214 | struct ccs_sensor *sensor; |
| 3316 | const struct firmware *fw; | 3215 | const struct firmware *fw; |
| @@ -3587,12 +3486,27 @@ static int ccs_probe(struct i2c_client *client) · 270 unmodified lines | |||
| 3587 | sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; | 3486 | sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; |
| 3588 | sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); | 3487 | sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); |
| 3589 | 3488 | ||
| 3590 | ccs_create_subdev(sensor, sensor->scaler, " scaler", 2, | 3489 | rval = ccs_get_mbus_formats(sensor); |
| 3591 | MEDIA_ENT_F_PROC_VIDEO_SCALER); | 3490 | if (rval) { |
| 3592 | ccs_create_subdev(sensor, sensor->binner, " binner", 2, | 3491 | rval = -ENODEV; |
| 3593 | MEDIA_ENT_F_PROC_VIDEO_SCALER); | 3492 | goto out_cleanup; |
| 3594 | ccs_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1, | 3493 | } |
| 3595 | MEDIA_ENT_F_CAM_SENSOR); | 3494 | |
| 3495 | rval = ccs_init_subdev(sensor, sensor->scaler, " scaler", 2, | ||
| 3496 | MEDIA_ENT_F_PROC_VIDEO_SCALER, | ||
| 3497 | "ccs scaler mutex", &scaler_lock_key); | ||
| 3498 | if (rval) | ||
| 3499 | goto out_cleanup; | ||
| 3500 | rval = ccs_init_subdev(sensor, sensor->binner, " binner", 2, | ||
| 3501 | MEDIA_ENT_F_PROC_VIDEO_SCALER, | ||
| 3502 | "ccs binner mutex", &binner_lock_key); | ||
| 3503 | if (rval) | ||
| 3504 | goto out_cleanup; | ||
| 3505 | rval = ccs_init_subdev(sensor, sensor->pixel_array, " pixel_array", 1, | ||
| 3506 | MEDIA_ENT_F_CAM_SENSOR, "ccs pixel array mutex", | ||
| 3507 | &pixel_array_lock_key); | ||
| 3508 | if (rval) | ||
| 3509 | goto out_cleanup; | ||
| 3596 | 3510 | ||
| 3597 | rval = ccs_init_controls(sensor); | 3511 | rval = ccs_init_controls(sensor); |
| 3598 | if (rval < 0) | 3512 | if (rval < 0) |
| @@ -3602,12 +3516,6 @@ static int ccs_probe(struct i2c_client *client) · 3 unmodified lines | |||
| 3602 | if (rval) | 3516 | if (rval) |
| 3603 | goto out_cleanup; | 3517 | goto out_cleanup; |
| 3604 | 3518 | ||
| 3605 | rval = ccs_get_mbus_formats(sensor); | ||
| 3606 | if (rval) { | ||
| 3607 | rval = -ENODEV; | ||
| 3608 | goto out_cleanup; | ||
| 3609 | } | ||
| 3610 | |||
| 3611 | rval = ccs_init_late_controls(sensor); | 3519 | rval = ccs_init_late_controls(sensor); |
| 3612 | if (rval) { | 3520 | if (rval) { |
| 3613 | rval = -ENODEV; | 3521 | rval = -ENODEV; |
| @@ -3625,14 +3533,9 @@ static int ccs_probe(struct i2c_client *client) · 11 unmodified lines | |||
| 3625 | sensor->streaming = false; | 3533 | sensor->streaming = false; |
| 3626 | sensor->dev_init_done = true; | 3534 | sensor->dev_init_done = true; |
| 3627 | 3535 | ||
| 3628 | rval = media_entity_pads_init(&sensor->src->sd.entity, 2, | ||
| 3629 | sensor->src->pads); | ||
| 3630 | if (rval < 0) | ||
| 3631 | goto out_media_entity_cleanup; | ||
| 3632 | |||
| 3633 | rval = ccs_write_msr_regs(sensor); | 3536 | rval = ccs_write_msr_regs(sensor); |
| 3634 | if (rval) | 3537 | if (rval) |
| 3635 | goto out_media_entity_cleanup; | 3538 | goto out_cleanup; |
| 3636 | 3539 | ||
| 3637 | pm_runtime_set_active(&client->dev); | 3540 | pm_runtime_set_active(&client->dev); |
| 3638 | pm_runtime_get_noresume(&client->dev); | 3541 | pm_runtime_get_noresume(&client->dev); |
| @@ -3652,9 +3555,6 @@ out_disable_runtime_pm: · 13 unmodified lines | |||
| 3652 | pm_runtime_put_noidle(&client->dev); | 3555 | pm_runtime_put_noidle(&client->dev); |
| 3653 | pm_runtime_disable(&client->dev); | 3556 | pm_runtime_disable(&client->dev); |
| 3654 | 3557 | ||
| 3655 | out_media_entity_cleanup: | ||
| 3656 | media_entity_cleanup(&sensor->src->sd.entity); | ||
| 3657 | |||
| 3658 | out_cleanup: | 3558 | out_cleanup: |
| 3659 | ccs_cleanup(sensor); | 3559 | ccs_cleanup(sensor); |
| 3660 | 3560 | ||
| @@ -3687,10 +3587,8 @@ static void ccs_remove(struct i2c_client *client) · 26 unmodified lines | |||
| 3687 | ccs_power_off(&client->dev); | 3587 | ccs_power_off(&client->dev); |
| 3688 | pm_runtime_set_suspended(&client->dev); | 3588 | pm_runtime_set_suspended(&client->dev); |
| 3689 | 3589 | ||
| 3690 | for (i = 0; i < sensor->ssds_used; i++) { | 3590 | for (i = 0; i < sensor->ssds_used; i++) |
| 3691 | v4l2_device_unregister_subdev(&sensor->ssds[i].sd); | 3591 | v4l2_device_unregister_subdev(&sensor->ssds[i].sd); |
| 3692 | media_entity_cleanup(&sensor->ssds[i].sd.entity); | ||
| 3693 | } | ||
| 3694 | ccs_cleanup(sensor); | 3592 | ccs_cleanup(sensor); |
| 3695 | mutex_destroy(&sensor->mutex); | 3593 | mutex_destroy(&sensor->mutex); |
| 3696 | kfree(sensor->ccs_limits); | 3594 | kfree(sensor->ccs_limits); |
| @@ -3720,7 +3618,6 @@ static const struct of_device_id ccs_of_table[] = { · 23 unmodified lines | |||
| 3720 | MODULE_DEVICE_TABLE(of, ccs_of_table); | 3618 | MODULE_DEVICE_TABLE(of, ccs_of_table); |
| 3721 | 3619 | ||
| 3722 | static const struct dev_pm_ops ccs_pm_ops = { | 3620 | static const struct dev_pm_ops ccs_pm_ops = { |
| 3723 | SET_SYSTEM_SLEEP_PM_OPS(ccs_suspend, ccs_resume) | ||
| 3724 | SET_RUNTIME_PM_OPS(ccs_power_off, ccs_power_on, NULL) | 3621 | SET_RUNTIME_PM_OPS(ccs_power_off, ccs_power_on, NULL) |
| 3725 | }; | 3622 | }; |
| 3726 | 3623 | ||
| @@ -32,12 +32,10 @@ struct ccs_sensor; · 31 unmodified lines | |||
| 32 | * @reg: Pointer to the register to access | 32 | * @reg: Pointer to the register to access |
| 33 | * @value: Register value, set by the caller on write, or | 33 | * @value: Register value, set by the caller on write, or |
| 34 | * by the quirk on read | 34 | * by the quirk on read |
| 35 | * | ||
| 36 | * @flags: Quirk flags | ||
| 37 | * | ||
| 38 | * @return: 0 on success, -ENOIOCTLCMD if no register | 35 | * @return: 0 on success, -ENOIOCTLCMD if no register |
| 39 | * access may be done by the caller (default read | 36 | * access may be done by the caller (default read |
| 40 | * value is zero), else negative error code on error | 37 | * value is zero), else negative error code on error |
| 38 | * @flags: Quirk flags | ||
| 41 | */ | 39 | */ |
| 42 | struct ccs_quirk { | 40 | struct ccs_quirk { |
| 43 | int (*limits)(struct ccs_sensor *sensor); | 41 | int (*limits)(struct ccs_sensor *sensor); |
| @@ -182,9 +182,6 @@ struct ccs_binning_subtype { · 181 unmodified lines | |||
| 182 | struct ccs_subdev { | 182 | struct ccs_subdev { |
| 183 | struct v4l2_subdev sd; | 183 | struct v4l2_subdev sd; |
| 184 | struct media_pad pads[CCS_PADS]; | 184 | struct media_pad pads[CCS_PADS]; |
| 185 | struct v4l2_rect sink_fmt; | ||
| 186 | struct v4l2_rect crop[CCS_PADS]; | ||
| 187 | struct v4l2_rect compose; /* compose on sink */ | ||
| 188 | unsigned short sink_pad; | 185 | unsigned short sink_pad; |
| 189 | unsigned short source_pad; | 186 | unsigned short source_pad; |
| 190 | int npads; | 187 | int npads; |
| @@ -220,6 +217,7 @@ struct ccs_sensor { · 29 unmodified lines | |||
| 220 | u32 mbus_frame_fmts; | 217 | u32 mbus_frame_fmts; |
| 221 | const struct ccs_csi_data_format *csi_format; | 218 | const struct ccs_csi_data_format *csi_format; |
| 222 | const struct ccs_csi_data_format *internal_csi_format; | 219 | const struct ccs_csi_data_format *internal_csi_format; |
| 220 | struct v4l2_rect pa_src, scaler_sink, src_src; | ||
| 223 | u32 default_mbus_frame_fmts; | 221 | u32 default_mbus_frame_fmts; |
| 224 | int default_pixel_order; | 222 | int default_pixel_order; |
| 225 | struct ccs_data_container sdata, mdata; | 223 | struct ccs_data_container sdata, mdata; |
| @@ -2738,10 +2738,801 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status, · 2737 unmodified lines | |||
| 2738 | #define DIF_BPF_COEFF3435 (0x38c) | 2738 | #define DIF_BPF_COEFF3435 (0x38c) |
| 2739 | #define DIF_BPF_COEFF36 (0x390) | 2739 | #define DIF_BPF_COEFF36 (0x390) |
| 2740 | 2740 | ||
| 2741 | static const u32 ifhz_coeffs[][19] = { | ||
| 2742 | { // 3.0 MHz | ||
| 2743 | 0x00000002, 0x00080012, 0x001e0024, 0x001bfff8, | ||
| 2744 | 0xffb4ff50, 0xfed8fe68, 0xfe24fe34, 0xfebaffc7, | ||
| 2745 | 0x014d031f, 0x04f0065d, 0x07010688, 0x04c901d6, | ||
| 2746 | 0xfe00f9d3, 0xf600f342, 0xf235f337, 0xf64efb22, | ||
| 2747 | 0x0105070f, 0x0c460fce, 0x110d0000, | ||
| 2748 | }, { // 3.1 MHz | ||
| 2749 | 0x00000001, 0x00070012, 0x00220032, 0x00370026, | ||
| 2750 | 0xfff0ff91, 0xff0efe7c, 0xfe01fdcc, 0xfe0afedb, | ||
| 2751 | 0x00440224, 0x0434060c, 0x0738074e, 0x06090361, | ||
| 2752 | 0xff99fb39, 0xf6fef3b6, 0xf21af2a5, 0xf573fa33, | ||
| 2753 | 0x0034067d, 0x0bfb0fb9, 0x110d0000, | ||
| 2754 | }, { // 3.2 MHz | ||
| 2755 | 0x00000000, 0x0004000e, 0x00200038, 0x004c004f, | ||
| 2756 | 0x002fffdf, 0xff5cfeb6, 0xfe0dfd92, 0xfd7ffe03, | ||
| 2757 | 0xff36010a, 0x03410575, 0x072607d2, 0x071804d5, | ||
| 2758 | 0x0134fcb7, 0xf81ff451, 0xf223f22e, 0xf4a7f94b, | ||
| 2759 | 0xff6405e8, 0x0bae0fa4, 0x110d0000, | ||
| 2760 | }, { // 3.3 MHz | ||
| 2761 | 0x0000ffff, 0x00000008, 0x001a0036, 0x0056006d, | ||
| 2762 | 0x00670030, 0xffbdff10, 0xfe46fd8d, 0xfd25fd4f, | ||
| 2763 | 0xfe35ffe0, 0x0224049f, 0x06c9080e, 0x07ef0627, | ||
| 2764 | 0x02c9fe45, 0xf961f513, 0xf250f1d2, 0xf3ecf869, | ||
| 2765 | 0xfe930552, 0x0b5f0f8f, 0x110d0000, | ||
| 2766 | }, { // 3.4 MHz | ||
| 2767 | 0xfffffffe, 0xfffd0001, 0x000f002c, 0x0054007d, | ||
| 2768 | 0x0093007c, 0x0024ff82, 0xfea6fdbb, 0xfd03fcca, | ||
| 2769 | 0xfd51feb9, 0x00eb0392, 0x06270802, 0x08880750, | ||
| 2770 | 0x044dffdb, 0xfabdf5f8, 0xf2a0f193, 0xf342f78f, | ||
| 2771 | 0xfdc404b9, 0x0b0e0f78, 0x110d0000, | ||
| 2772 | }, { // 3.5 MHz | ||
| 2773 | 0xfffffffd, 0xfffafff9, 0x0002001b, 0x0046007d, | ||
| 2774 | 0x00ad00ba, 0x00870000, 0xff26fe1a, 0xfd1bfc7e, | ||
| 2775 | 0xfc99fda4, 0xffa5025c, 0x054507ad, 0x08dd0847, | ||
| 2776 | 0x05b80172, 0xfc2ef6ff, 0xf313f170, 0xf2abf6bd, | ||
| 2777 | 0xfcf6041f, 0x0abc0f61, 0x110d0000, | ||
| 2778 | }, { // 3.6 MHz | ||
| 2779 | 0xfffffffd, 0xfff8fff3, 0xfff50006, 0x002f006c, | ||
| 2780 | 0x00b200e3, 0x00dc007e, 0xffb9fea0, 0xfd6bfc71, | ||
| 2781 | 0xfc17fcb1, 0xfe65010b, 0x042d0713, 0x08ec0906, | ||
| 2782 | 0x07020302, 0xfdaff823, 0xf3a7f16a, 0xf228f5f5, | ||
| 2783 | 0xfc2a0384, 0x0a670f4a, 0x110d0000, | ||
| 2784 | }, { // 3.7 MHz | ||
| 2785 | 0x0000fffd, 0xfff7ffef, 0xffe9fff1, 0x0010004d, | ||
| 2786 | 0x00a100f2, 0x011a00f0, 0x0053ff44, 0xfdedfca2, | ||
| 2787 | 0xfbd3fbef, 0xfd39ffae, 0x02ea0638, 0x08b50987, | ||
| 2788 | 0x08230483, 0xff39f960, 0xf45bf180, 0xf1b8f537, | ||
| 2789 | 0xfb6102e7, 0x0a110f32, 0x110d0000, | ||
| 2790 | }, { // 3.8 MHz | ||
| 2791 | 0x0000fffe, 0xfff9ffee, 0xffe1ffdd, 0xfff00024, | ||
| 2792 | 0x007c00e5, 0x013a014a, 0x00e6fff8, 0xfe98fd0f, | ||
| 2793 | 0xfbd3fb67, 0xfc32fe54, 0x01880525, 0x083909c7, | ||
| 2794 | 0x091505ee, 0x00c7fab3, 0xf52df1b4, 0xf15df484, | ||
| 2795 | 0xfa9b0249, 0x09ba0f19, 0x110d0000, | ||
| 2796 | }, { // 3.9 MHz | ||
| 2797 | 0x00000000, 0xfffbfff0, 0xffdeffcf, 0xffd1fff6, | ||
| 2798 | 0x004800be, 0x01390184, 0x016300ac, 0xff5efdb1, | ||
| 2799 | 0xfc17fb23, 0xfb5cfd0d, 0x001703e4, 0x077b09c4, | ||
| 2800 | 0x09d2073c, 0x0251fc18, 0xf61cf203, 0xf118f3dc, | ||
| 2801 | 0xf9d801aa, 0x09600eff, 0x110d0000, | ||
| 2802 | }, { // 4.0 MHz | ||
| 2803 | 0x00000001, 0xfffefff4, 0xffe1ffc8, 0xffbaffca, | ||
| 2804 | 0x000b0082, 0x01170198, 0x01c10152, 0x0030fe7b, | ||
| 2805 | 0xfc99fb24, 0xfac3fbe9, 0xfea5027f, 0x0683097f, | ||
| 2806 | 0x0a560867, 0x03d2fd89, 0xf723f26f, 0xf0e8f341, | ||
| 2807 | 0xf919010a, 0x09060ee5, 0x110d0000, | ||
| 2808 | }, { // 4.1 MHz | ||
| 2809 | 0x00010002, 0x0002fffb, 0xffe8ffca, 0xffacffa4, | ||
| 2810 | 0xffcd0036, 0x00d70184, 0x01f601dc, 0x00ffff60, | ||
| 2811 | 0xfd51fb6d, 0xfa6efaf5, 0xfd410103, 0x055708f9, | ||
| 2812 | 0x0a9e0969, 0x0543ff02, 0xf842f2f5, 0xf0cef2b2, | ||
| 2813 | 0xf85e006b, 0x08aa0ecb, 0x110d0000, | ||
| 2814 | }, { // 4.2 MHz | ||
| 2815 | 0x00010003, 0x00050003, 0xfff3ffd3, 0xffaaff8b, | ||
| 2816 | 0xff95ffe5, 0x0080014a, 0x01fe023f, 0x01ba0050, | ||
| 2817 | 0xfe35fbf8, 0xfa62fa3b, 0xfbf9ff7e, 0x04010836, | ||
| 2818 | 0x0aa90a3d, 0x069f007f, 0xf975f395, 0xf0cbf231, | ||
| 2819 | 0xf7a9ffcb, 0x084c0eaf, 0x110d0000, | ||
| 2820 | }, { // 4.3 MHz | ||
| 2821 | 0x00010003, 0x0008000a, 0x0000ffe4, 0xffb4ff81, | ||
| 2822 | 0xff6aff96, 0x001c00f0, 0x01d70271, 0x0254013b, | ||
| 2823 | 0xff36fcbd, 0xfa9ff9c5, 0xfadbfdfe, 0x028c073b, | ||
| 2824 | 0x0a750adf, 0x07e101fa, 0xfab8f44e, 0xf0ddf1be, | ||
| 2825 | 0xf6f9ff2b, 0x07ed0e94, 0x110d0000, | ||
| 2826 | }, { // 4.4 MHz | ||
| 2827 | 0x00000003, 0x0009000f, 0x000efff8, 0xffc9ff87, | ||
| 2828 | 0xff52ff54, 0xffb5007e, 0x01860270, 0x02c00210, | ||
| 2829 | 0x0044fdb2, 0xfb22f997, 0xf9f2fc90, 0x0102060f, | ||
| 2830 | 0x0a050b4c, 0x0902036e, 0xfc0af51e, 0xf106f15a, | ||
| 2831 | 0xf64efe8b, 0x078d0e77, 0x110d0000, | ||
| 2832 | }, { // 4.5 MHz | ||
| 2833 | 0x00000002, 0x00080012, 0x0019000e, 0xffe5ff9e, | ||
| 2834 | 0xff4fff25, 0xff560000, 0x0112023b, 0x02f702c0, | ||
| 2835 | 0x014dfec8, 0xfbe5f9b3, 0xf947fb41, 0xff7004b9, | ||
| 2836 | 0x095a0b81, 0x0a0004d8, 0xfd65f603, 0xf144f104, | ||
| 2837 | 0xf5aafdec, 0x072b0e5a, 0x110d0000, | ||
| 2838 | }, { // 4.6 MHz | ||
| 2839 | 0x00000001, 0x00060012, 0x00200022, 0x0005ffc1, | ||
| 2840 | 0xff61ff10, 0xff09ff82, 0x008601d7, 0x02f50340, | ||
| 2841 | 0x0241fff0, 0xfcddfa19, 0xf8e2fa1e, 0xfde30343, | ||
| 2842 | 0x08790b7f, 0x0ad50631, 0xfec7f6fc, 0xf198f0bd, | ||
| 2843 | 0xf50dfd4e, 0x06c90e3d, 0x110d0000, | ||
| 2844 | }, { // 4.7 MHz | ||
| 2845 | 0x0000ffff, 0x0003000f, 0x00220030, 0x0025ffed, | ||
| 2846 | 0xff87ff15, 0xfed6ff10, 0xffed014c, 0x02b90386, | ||
| 2847 | 0x03110119, 0xfdfefac4, 0xf8c6f92f, 0xfc6701b7, | ||
| 2848 | 0x07670b44, 0x0b7e0776, 0x002df807, 0xf200f086, | ||
| 2849 | 0xf477fcb1, 0x06650e1e, 0x110d0000, | ||
| 2850 | }, { // 4.8 MHz | ||
| 2851 | 0xfffffffe, 0xffff0009, 0x001e0038, 0x003f001b, | ||
| 2852 | 0xffbcff36, 0xfec2feb6, 0xff5600a5, 0x0248038d, | ||
| 2853 | 0x03b00232, 0xff39fbab, 0xf8f4f87f, 0xfb060020, | ||
| 2854 | 0x062a0ad2, 0x0bf908a3, 0x0192f922, 0xf27df05e, | ||
| 2855 | 0xf3e8fc14, 0x06000e00, 0x110d0000, | ||
| 2856 | }, { // 4.9 MHz | ||
| 2857 | 0xfffffffd, 0xfffc0002, 0x00160037, 0x00510046, | ||
| 2858 | 0xfff9ff6d, 0xfed0fe7c, 0xfecefff0, 0x01aa0356, | ||
| 2859 | 0x0413032b, 0x007ffcc5, 0xf96cf812, 0xf9cefe87, | ||
| 2860 | 0x04c90a2c, 0x0c4309b4, 0x02f3fa4a, 0xf30ef046, | ||
| 2861 | 0xf361fb7a, 0x059b0de0, 0x110d0000, | ||
| 2862 | }, { // 5.0 MHz | ||
| 2863 | 0xfffffffd, 0xfff9fffa, 0x000a002d, 0x00570067, | ||
| 2864 | 0x0037ffb5, 0xfefffe68, 0xfe62ff3d, 0x00ec02e3, | ||
| 2865 | 0x043503f6, 0x01befe05, 0xfa27f7ee, 0xf8c6fcf8, | ||
| 2866 | 0x034c0954, 0x0c5c0aa4, 0x044cfb7e, 0xf3b1f03f, | ||
| 2867 | 0xf2e2fae1, 0x05340dc0, 0x110d0000, | ||
| 2868 | }, { // 5.1 MHz | ||
| 2869 | 0x0000fffd, 0xfff8fff4, 0xfffd001e, 0x0051007b, | ||
| 2870 | 0x006e0006, 0xff48fe7c, 0xfe1bfe9a, 0x001d023e, | ||
| 2871 | 0x04130488, 0x02e6ff5b, 0xfb1ef812, 0xf7f7fb7f, | ||
| 2872 | 0x01bc084e, 0x0c430b72, 0x059afcba, 0xf467f046, | ||
| 2873 | 0xf26cfa4a, 0x04cd0da0, 0x110d0000, | ||
| 2874 | }, { // 5.2 MHz | ||
| 2875 | 0x0000fffe, 0xfff8ffef, 0xfff00009, 0x003f007f, | ||
| 2876 | 0x00980056, 0xffa5feb6, 0xfe00fe15, 0xff4b0170, | ||
| 2877 | 0x03b004d7, 0x03e800b9, 0xfc48f87f, 0xf768fa23, | ||
| 2878 | 0x0022071f, 0x0bf90c1b, 0x06dafdfd, 0xf52df05e, | ||
| 2879 | 0xf1fef9b5, 0x04640d7f, 0x110d0000, | ||
| 2880 | }, { // 5.3 MHz | ||
| 2881 | 0x0000ffff, 0xfff9ffee, 0xffe6fff3, 0x00250072, | ||
| 2882 | 0x00af009c, 0x000cff10, 0xfe13fdb8, 0xfe870089, | ||
| 2883 | 0x031104e1, 0x04b8020f, 0xfd98f92f, 0xf71df8f0, | ||
| 2884 | 0xfe8805ce, 0x0b7e0c9c, 0x0808ff44, 0xf603f086, | ||
| 2885 | 0xf19af922, 0x03fb0d5e, 0x110d0000, | ||
| 2886 | }, { // 5.4 MHz | ||
| 2887 | 0x00000001, 0xfffcffef, 0xffe0ffe0, 0x00050056, | ||
| 2888 | 0x00b000d1, 0x0071ff82, 0xfe53fd8c, 0xfddfff99, | ||
| 2889 | 0x024104a3, 0x054a034d, 0xff01fa1e, 0xf717f7ed, | ||
| 2890 | 0xfcf50461, 0x0ad50cf4, 0x0921008d, 0xf6e7f0bd, | ||
| 2891 | 0xf13ff891, 0x03920d3b, 0x110d0000, | ||
| 2892 | }, { // 5.5 MHz | ||
| 2893 | 0x00010002, 0xfffffff3, 0xffdeffd1, 0xffe5002f, | ||
| 2894 | 0x009c00ed, 0x00cb0000, 0xfebafd94, 0xfd61feb0, | ||
| 2895 | 0x014d0422, 0x05970464, 0x0074fb41, 0xf759f721, | ||
| 2896 | 0xfb7502de, 0x0a000d21, 0x0a2201d4, 0xf7d9f104, | ||
| 2897 | 0xf0edf804, 0x03280d19, 0x110d0000, | ||
| 2898 | }, { // 5.6 MHz | ||
| 2899 | 0x00010003, 0x0003fffa, 0xffe3ffc9, 0xffc90002, | ||
| 2900 | 0x007500ef, 0x010e007e, 0xff3dfdcf, 0xfd16fddd, | ||
| 2901 | 0x00440365, 0x059b0548, 0x01e3fc90, 0xf7dff691, | ||
| 2902 | 0xfa0f014d, 0x09020d23, 0x0b0a0318, 0xf8d7f15a, | ||
| 2903 | 0xf0a5f779, 0x02bd0cf6, 0x110d0000, | ||
| 2904 | }, { // 5.7 MHz | ||
| 2905 | 0x00010003, 0x00060001, 0xffecffc9, 0xffb4ffd4, | ||
| 2906 | 0x004000d5, 0x013600f0, 0xffd3fe39, 0xfd04fd31, | ||
| 2907 | 0xff360277, 0x055605ef, 0x033efdfe, 0xf8a5f642, | ||
| 2908 | 0xf8cbffb6, 0x07e10cfb, 0x0bd50456, 0xf9dff1be, | ||
| 2909 | 0xf067f6f2, 0x02520cd2, 0x110d0000, | ||
| 2910 | }, { // 5.8 MHz | ||
| 2911 | 0x00000003, 0x00080009, 0xfff8ffd2, 0xffaaffac, | ||
| 2912 | 0x000200a3, 0x013c014a, 0x006dfec9, 0xfd2bfcb7, | ||
| 2913 | 0xfe350165, 0x04cb0651, 0x0477ff7e, 0xf9a5f635, | ||
| 2914 | 0xf7b1fe20, 0x069f0ca8, 0x0c81058b, 0xfaf0f231, | ||
| 2915 | 0xf033f66d, 0x01e60cae, 0x110d0000, | ||
| 2916 | }, { // 5.9 MHz | ||
| 2917 | 0x00000002, 0x0009000e, 0x0005ffe1, 0xffacff90, | ||
| 2918 | 0xffc5005f, 0x01210184, 0x00fcff72, 0xfd8afc77, | ||
| 2919 | 0xfd51003f, 0x04020669, 0x05830103, 0xfad7f66b, | ||
| 2920 | 0xf6c8fc93, 0x05430c2b, 0x0d0d06b5, 0xfc08f2b2, | ||
| 2921 | 0xf00af5ec, 0x017b0c89, 0x110d0000, | ||
| 2922 | }, { // 6.0 MHz | ||
| 2923 | 0x00000001, 0x00070012, 0x0012fff5, 0xffbaff82, | ||
| 2924 | 0xff8e000f, 0x00e80198, 0x01750028, 0xfe18fc75, | ||
| 2925 | 0xfc99ff15, 0x03050636, 0x0656027f, 0xfc32f6e2, | ||
| 2926 | 0xf614fb17, 0x03d20b87, 0x0d7707d2, 0xfd26f341, | ||
| 2927 | 0xefeaf56f, 0x010f0c64, 0x110d0000, | ||
| 2928 | }, { // 6.1 MHz | ||
| 2929 | 0xffff0000, 0x00050012, 0x001c000b, 0xffd1ff84, | ||
| 2930 | 0xff66ffbe, 0x00960184, 0x01cd00da, 0xfeccfcb2, | ||
| 2931 | 0xfc17fdf9, 0x01e005bc, 0x06e703e4, 0xfdabf798, | ||
| 2932 | 0xf599f9b3, 0x02510abd, 0x0dbf08df, 0xfe48f3dc, | ||
| 2933 | 0xefd5f4f6, 0x00a20c3e, 0x110d0000, | ||
| 2934 | }, { // 6.2 MHz | ||
| 2935 | 0xfffffffe, 0x0002000f, 0x0021001f, 0xfff0ff97, | ||
| 2936 | 0xff50ff74, 0x0034014a, 0x01fa0179, 0xff97fd2a, | ||
| 2937 | 0xfbd3fcfa, 0x00a304fe, 0x07310525, 0xff37f886, | ||
| 2938 | 0xf55cf86e, 0x00c709d0, 0x0de209db, 0xff6df484, | ||
| 2939 | 0xefcbf481, 0x00360c18, 0x110d0000, | ||
| 2940 | }, { // 6.3 MHz | ||
| 2941 | 0xfffffffd, 0xfffe000a, 0x0021002f, 0x0010ffb8, | ||
| 2942 | 0xff50ff3b, 0xffcc00f0, 0x01fa01fa, 0x0069fdd4, | ||
| 2943 | 0xfbd3fc26, 0xff5d0407, 0x07310638, 0x00c9f9a8, | ||
| 2944 | 0xf55cf74e, 0xff3908c3, 0x0de20ac3, 0x0093f537, | ||
| 2945 | 0xefcbf410, 0xffca0bf2, 0x110d0000, | ||
| 2946 | }, { // 6.4 MHz | ||
| 2947 | 0xfffffffd, 0xfffb0003, 0x001c0037, 0x002fffe2, | ||
| 2948 | 0xff66ff17, 0xff6a007e, 0x01cd0251, 0x0134fea5, | ||
| 2949 | 0xfc17fb8b, 0xfe2002e0, 0x06e70713, 0x0255faf5, | ||
| 2950 | 0xf599f658, 0xfdaf0799, 0x0dbf0b96, 0x01b8f5f5, | ||
| 2951 | 0xefd5f3a3, 0xff5e0bca, 0x110d0000, | ||
| 2952 | }, { // 6.5 MHz | ||
| 2953 | 0x0000fffd, 0xfff9fffb, 0x00120037, 0x00460010, | ||
| 2954 | 0xff8eff0f, 0xff180000, 0x01750276, 0x01e8ff8d, | ||
| 2955 | 0xfc99fb31, 0xfcfb0198, 0x065607ad, 0x03cefc64, | ||
| 2956 | 0xf614f592, 0xfc2e0656, 0x0d770c52, 0x02daf6bd, | ||
| 2957 | 0xefeaf33b, 0xfef10ba3, 0x110d0000, | ||
| 2958 | }, { // 6.6 MHz | ||
| 2959 | 0x0000fffe, 0xfff7fff5, 0x0005002f, 0x0054003c, | ||
| 2960 | 0xffc5ff22, 0xfedfff82, 0x00fc0267, 0x0276007e, | ||
| 2961 | 0xfd51fb1c, 0xfbfe003e, 0x05830802, 0x0529fdec, | ||
| 2962 | 0xf6c8f4fe, 0xfabd04ff, 0x0d0d0cf6, 0x03f8f78f, | ||
| 2963 | 0xf00af2d7, 0xfe850b7b, 0x110d0000, | ||
| 2964 | }, { // 6.7 MHz | ||
| 2965 | 0x0000ffff, 0xfff8fff0, 0xfff80020, 0x00560060, | ||
| 2966 | 0x0002ff4e, 0xfec4ff10, 0x006d0225, 0x02d50166, | ||
| 2967 | 0xfe35fb4e, 0xfb35fee1, 0x0477080e, 0x065bff82, | ||
| 2968 | 0xf7b1f4a0, 0xf9610397, 0x0c810d80, 0x0510f869, | ||
| 2969 | 0xf033f278, 0xfe1a0b52, 0x110d0000, | ||
| 2970 | }, { // 6.8 MHz | ||
| 2971 | 0x00010000, 0xfffaffee, 0xffec000c, 0x004c0078, | ||
| 2972 | 0x0040ff8e, 0xfecafeb6, 0xffd301b6, 0x02fc0235, | ||
| 2973 | 0xff36fbc5, 0xfaaafd90, 0x033e07d2, 0x075b011b, | ||
| 2974 | 0xf8cbf47a, 0xf81f0224, 0x0bd50def, 0x0621f94b, | ||
| 2975 | 0xf067f21e, 0xfdae0b29, 0x110d0000, | ||
| 2976 | }, { // 6.9 MHz | ||
| 2977 | 0x00010001, 0xfffdffef, 0xffe3fff6, 0x0037007f, | ||
| 2978 | 0x0075ffdc, 0xfef2fe7c, 0xff3d0122, 0x02ea02dd, | ||
| 2979 | 0x0044fc79, 0xfa65fc5d, 0x01e3074e, 0x082102ad, | ||
| 2980 | 0xfa0ff48c, 0xf6fe00a9, 0x0b0a0e43, 0x0729fa33, | ||
| 2981 | 0xf0a5f1c9, 0xfd430b00, 0x110d0000, | ||
| 2982 | }, { // 7.0 MHz | ||
| 2983 | 0x00010002, 0x0001fff3, 0xffdeffe2, 0x001b0076, | ||
| 2984 | 0x009c002d, 0xff35fe68, 0xfeba0076, 0x029f0352, | ||
| 2985 | 0x014dfd60, 0xfa69fb53, 0x00740688, 0x08a7042d, | ||
| 2986 | 0xfb75f4d6, 0xf600ff2d, 0x0a220e7a, 0x0827fb22, | ||
| 2987 | 0xf0edf17a, 0xfcd80ad6, 0x110d0000, | ||
| 2988 | }, { // 7.1 MHz | ||
| 2989 | 0x00000003, 0x0004fff9, 0xffe0ffd2, 0xfffb005e, | ||
| 2990 | 0x00b0007a, 0xff8ffe7c, 0xfe53ffc1, 0x0221038c, | ||
| 2991 | 0x0241fe6e, 0xfab6fa80, 0xff010587, 0x08e90590, | ||
| 2992 | 0xfcf5f556, 0xf52bfdb3, 0x09210e95, 0x0919fc15, | ||
| 2993 | 0xf13ff12f, 0xfc6e0aab, 0x110d0000, | ||
| 2994 | }, { // 7.2 MHz | ||
| 2995 | 0x00000003, 0x00070000, 0xffe6ffc9, 0xffdb0039, | ||
| 2996 | 0x00af00b8, 0xfff4feb6, 0xfe13ff10, 0x01790388, | ||
| 2997 | 0x0311ff92, 0xfb48f9ed, 0xfd980453, 0x08e306cd, | ||
| 2998 | 0xfe88f60a, 0xf482fc40, 0x08080e93, 0x09fdfd0c, | ||
| 2999 | 0xf19af0ea, 0xfc050a81, 0x110d0000, | ||
| 3000 | }, { // 7.3 MHz | ||
| 3001 | 0x00000002, 0x00080008, 0xfff0ffc9, 0xffc1000d, | ||
| 3002 | 0x009800e2, 0x005bff10, 0xfe00fe74, 0x00b50345, | ||
| 3003 | 0x03b000bc, 0xfc18f9a1, 0xfc4802f9, 0x089807dc, | ||
| 3004 | 0x0022f6f0, 0xf407fada, 0x06da0e74, 0x0ad3fe06, | ||
| 3005 | 0xf1fef0ab, 0xfb9c0a55, 0x110d0000, | ||
| 3006 | }, { // 7.4 MHz | ||
| 3007 | 0x00000001, 0x0008000e, 0xfffdffd0, 0xffafffdf, | ||
| 3008 | 0x006e00f2, 0x00b8ff82, 0xfe1bfdf8, 0xffe302c8, | ||
| 3009 | 0x041301dc, 0xfd1af99e, 0xfb1e0183, 0x080908b5, | ||
| 3010 | 0x01bcf801, 0xf3bdf985, 0x059a0e38, 0x0b99ff03, | ||
| 3011 | 0xf26cf071, 0xfb330a2a, 0x110d0000, | ||
| 3012 | }, { // 7.5 MHz | ||
| 3013 | 0xffff0000, 0x00070011, 0x000affdf, 0xffa9ffb5, | ||
| 3014 | 0x003700e6, 0x01010000, 0xfe62fda8, 0xff140219, | ||
| 3015 | 0x043502e1, 0xfe42f9e6, 0xfa270000, 0x073a0953, | ||
| 3016 | 0x034cf939, 0xf3a4f845, 0x044c0de1, 0x0c4f0000, | ||
| 3017 | 0xf2e2f03c, 0xfacc09fe, 0x110d0000, | ||
| 3018 | }, { // 7.6 MHz | ||
| 3019 | 0xffffffff, 0x00040012, 0x0016fff3, 0xffafff95, | ||
| 3020 | 0xfff900c0, 0x0130007e, 0xfecefd89, 0xfe560146, | ||
| 3021 | 0x041303bc, 0xff81fa76, 0xf96cfe7d, 0x063209b1, | ||
| 3022 | 0x04c9fa93, 0xf3bdf71e, 0x02f30d6e, 0x0cf200fd, | ||
| 3023 | 0xf361f00e, 0xfa6509d1, 0x110d0000, | ||
| 3024 | }, { // 7.7 MHz | ||
| 3025 | 0xfffffffe, 0x00010010, 0x001e0008, 0xffc1ff84, | ||
| 3026 | 0xffbc0084, 0x013e00f0, 0xff56fd9f, 0xfdb8005c, | ||
| 3027 | 0x03b00460, 0x00c7fb45, 0xf8f4fd07, 0x04fa09ce, | ||
| 3028 | 0x062afc07, 0xf407f614, 0x01920ce0, 0x0d8301fa, | ||
| 3029 | 0xf3e8efe5, 0xfa0009a4, 0x110d0000, | ||
| 3030 | }, { // 7.8 MHz | ||
| 3031 | 0x0000fffd, 0xfffd000b, 0x0022001d, 0xffdbff82, | ||
| 3032 | 0xff870039, 0x012a014a, 0xffedfde7, 0xfd47ff6b, | ||
| 3033 | 0x031104c6, 0x0202fc4c, 0xf8c6fbad, 0x039909a7, | ||
| 3034 | 0x0767fd8e, 0xf482f52b, 0x002d0c39, 0x0e0002f4, | ||
| 3035 | 0xf477efc2, 0xf99b0977, 0x110d0000, | ||
| 3036 | }, { // 7.9 MHz | ||
| 3037 | 0x0000fffd, 0xfffa0004, 0x0020002d, 0xfffbff91, | ||
| 3038 | 0xff61ffe8, 0x00f70184, 0x0086fe5c, 0xfd0bfe85, | ||
| 3039 | 0x024104e5, 0x0323fd7d, 0xf8e2fa79, 0x021d093f, | ||
| 3040 | 0x0879ff22, 0xf52bf465, 0xfec70b79, 0x0e6803eb, | ||
| 3041 | 0xf50defa5, 0xf937094a, 0x110d0000, | ||
| 3042 | }, { // 8.0 MHz | ||
| 3043 | 0x0000fffe, 0xfff8fffd, 0x00190036, 0x001bffaf, | ||
| 3044 | 0xff4fff99, 0x00aa0198, 0x0112fef3, 0xfd09fdb9, | ||
| 3045 | 0x014d04be, 0x041bfecc, 0xf947f978, 0x00900897, | ||
| 3046 | 0x095a00b9, 0xf600f3c5, 0xfd650aa3, 0x0ebc04de, | ||
| 3047 | 0xf5aaef8e, 0xf8d5091c, 0x110d0000, | ||
| 3048 | }, { // 8.1 MHz | ||
| 3049 | 0x0000ffff, 0xfff7fff6, 0x000e0038, 0x0037ffd7, | ||
| 3050 | 0xff52ff56, 0x004b0184, 0x0186ffa1, 0xfd40fd16, | ||
| 3051 | 0x00440452, 0x04de0029, 0xf9f2f8b2, 0xfefe07b5, | ||
| 3052 | 0x0a05024d, 0xf6fef34d, 0xfc0a09b8, 0x0efa05cd, | ||
| 3053 | 0xf64eef7d, 0xf87308ed, 0x110d0000, | ||
| 3054 | }, { // 8.2 MHz | ||
| 3055 | 0x00010000, 0xfff8fff0, 0x00000031, 0x004c0005, | ||
| 3056 | 0xff6aff27, 0xffe4014a, 0x01d70057, 0xfdacfca6, | ||
| 3057 | 0xff3603a7, 0x05610184, 0xfadbf82e, 0xfd74069f, | ||
| 3058 | 0x0a7503d6, 0xf81ff2ff, 0xfab808b9, 0x0f2306b5, | ||
| 3059 | 0xf6f9ef72, 0xf81308bf, 0x110d0000, | ||
| 3060 | }, { // 8.3 MHz | ||
| 3061 | 0x00010001, 0xfffbffee, 0xfff30022, 0x00560032, | ||
| 3062 | 0xff95ff10, 0xff8000f0, 0x01fe0106, 0xfe46fc71, | ||
| 3063 | 0xfe3502c7, 0x059e02ce, 0xfbf9f7f2, 0xfbff055b, | ||
| 3064 | 0x0aa9054c, 0xf961f2db, 0xf97507aa, 0x0f350797, | ||
| 3065 | 0xf7a9ef6d, 0xf7b40890, 0x110d0000, | ||
| 3066 | }, { // 8.4 MHz | ||
| 3067 | 0x00010002, 0xfffeffee, 0xffe8000f, 0x00540058, | ||
| 3068 | 0xffcdff14, 0xff29007e, 0x01f6019e, 0xff01fc7c, | ||
| 3069 | 0xfd5101bf, 0x059203f6, 0xfd41f7fe, 0xfaa903f3, | ||
| 3070 | 0x0a9e06a9, 0xfabdf2e2, 0xf842068b, 0x0f320871, | ||
| 3071 | 0xf85eef6e, 0xf7560860, 0x110d0000, | ||
| 3072 | }, { // 8.5 MHz | ||
| 3073 | 0x00000003, 0x0002fff2, 0xffe1fff9, 0x00460073, | ||
| 3074 | 0x000bff34, 0xfee90000, 0x01c10215, 0xffd0fcc5, | ||
| 3075 | 0xfc99009d, 0x053d04f1, 0xfea5f853, 0xf97d0270, | ||
| 3076 | 0x0a5607e4, 0xfc2ef314, 0xf723055f, 0x0f180943, | ||
| 3077 | 0xf919ef75, 0xf6fa0830, 0x110d0000, | ||
| 3078 | }, { // 8.6 MHz | ||
| 3079 | 0x00000003, 0x0005fff8, 0xffdeffe4, 0x002f007f, | ||
| 3080 | 0x0048ff6b, 0xfec7ff82, 0x0163025f, 0x00a2fd47, | ||
| 3081 | 0xfc17ff73, 0x04a405b2, 0x0017f8ed, 0xf88500dc, | ||
| 3082 | 0x09d208f9, 0xfdaff370, 0xf61c0429, 0x0ee80a0b, | ||
| 3083 | 0xf9d8ef82, 0xf6a00800, 0x110d0000, | ||
| 3084 | }, { // 8.7 MHz | ||
| 3085 | 0x00000003, 0x0007ffff, 0xffe1ffd4, 0x0010007a, | ||
| 3086 | 0x007cffb2, 0xfec6ff10, 0x00e60277, 0x0168fdf9, | ||
| 3087 | 0xfbd3fe50, 0x03ce0631, 0x0188f9c8, 0xf7c7ff43, | ||
| 3088 | 0x091509e3, 0xff39f3f6, 0xf52d02ea, 0x0ea30ac9, | ||
| 3089 | 0xfa9bef95, 0xf64607d0, 0x110d0000, | ||
| 3090 | }, { // 8.8 MHz | ||
| 3091 | 0x00000002, 0x00090007, 0xffe9ffca, 0xfff00065, | ||
| 3092 | 0x00a10003, 0xfee6feb6, 0x0053025b, 0x0213fed0, | ||
| 3093 | 0xfbd3fd46, 0x02c70668, 0x02eafadb, 0xf74bfdae, | ||
| 3094 | 0x08230a9c, 0x00c7f4a3, 0xf45b01a6, 0x0e480b7c, | ||
| 3095 | 0xfb61efae, 0xf5ef079f, 0x110d0000, | ||
| 3096 | }, { // 8.9 MHz | ||
| 3097 | 0xffff0000, 0x0008000d, 0xfff5ffc8, 0xffd10043, | ||
| 3098 | 0x00b20053, 0xff24fe7c, 0xffb9020c, 0x0295ffbb, | ||
| 3099 | 0xfc17fc64, 0x019b0654, 0x042dfc1c, 0xf714fc2a, | ||
| 3100 | 0x07020b21, 0x0251f575, 0xf3a7005e, 0x0dd80c24, | ||
| 3101 | 0xfc2aefcd, 0xf599076e, 0x110d0000, | ||
| 3102 | }, { // 9.0 MHz | ||
| 3103 | 0xffffffff, 0x00060011, 0x0002ffcf, 0xffba0018, | ||
| 3104 | 0x00ad009a, 0xff79fe68, 0xff260192, 0x02e500ab, | ||
| 3105 | 0xfc99fbb6, 0x005b05f7, 0x0545fd81, 0xf723fabf, | ||
| 3106 | 0x05b80b70, 0x03d2f669, 0xf313ff15, 0x0d550cbf, | ||
| 3107 | 0xfcf6eff2, 0xf544073d, 0x110d0000, | ||
| 3108 | }, { // 9.1 MHz | ||
| 3109 | 0xfffffffe, 0x00030012, 0x000fffdd, 0xffacffea, | ||
| 3110 | 0x009300cf, 0xffdcfe7c, 0xfea600f7, 0x02fd0190, | ||
| 3111 | 0xfd51fb46, 0xff150554, 0x0627fefd, 0xf778f978, | ||
| 3112 | 0x044d0b87, 0x0543f77d, 0xf2a0fdcf, 0x0cbe0d4e, | ||
| 3113 | 0xfdc4f01d, 0xf4f2070b, 0x110d0000, | ||
| 3114 | }, { // 9.2 MHz | ||
| 3115 | 0x0000fffd, 0x00000010, 0x001afff0, 0xffaaffbf, | ||
| 3116 | 0x006700ed, 0x0043feb6, 0xfe460047, 0x02db0258, | ||
| 3117 | 0xfe35fb1b, 0xfddc0473, 0x06c90082, 0xf811f85e, | ||
| 3118 | 0x02c90b66, 0x069ff8ad, 0xf250fc8d, 0x0c140dcf, | ||
| 3119 | 0xfe93f04d, 0xf4a106d9, 0x110d0000, | ||
| 3120 | }, { // 9.3 MHz | ||
| 3121 | 0x0000fffd, 0xfffc000c, 0x00200006, 0xffb4ff9c, | ||
| 3122 | 0x002f00ef, 0x00a4ff10, 0xfe0dff92, 0x028102f7, | ||
| 3123 | 0xff36fb37, 0xfcbf035e, 0x07260202, 0xf8e8f778, | ||
| 3124 | 0x01340b0d, 0x07e1f9f4, 0xf223fb51, 0x0b590e42, | ||
| 3125 | 0xff64f083, 0xf45206a7, 0x110d0000, | ||
| 3126 | }, { // 9.4 MHz | ||
| 3127 | 0x0000fffd, 0xfff90005, 0x0022001a, 0xffc9ff86, | ||
| 3128 | 0xfff000d7, 0x00f2ff82, 0xfe01fee5, 0x01f60362, | ||
| 3129 | 0x0044fb99, 0xfbcc0222, 0x07380370, 0xf9f7f6cc, | ||
| 3130 | 0xff990a7e, 0x0902fb50, 0xf21afa1f, 0x0a8d0ea6, | ||
| 3131 | 0x0034f0bf, 0xf4050675, 0x110d0000, | ||
| 3132 | }, { // 9.5 MHz | ||
| 3133 | 0x0000fffe, 0xfff8fffe, 0x001e002b, 0xffe5ff81, | ||
| 3134 | 0xffb400a5, 0x01280000, 0xfe24fe50, 0x01460390, | ||
| 3135 | 0x014dfc3a, 0xfb1000ce, 0x070104bf, 0xfb37f65f, | ||
| 3136 | 0xfe0009bc, 0x0a00fcbb, 0xf235f8f8, 0x09b20efc, | ||
| 3137 | 0x0105f101, 0xf3ba0642, 0x110d0000, | ||
| 3138 | }, { // 9.6 MHz | ||
| 3139 | 0x0001ffff, 0xfff8fff7, 0x00150036, 0x0005ff8c, | ||
| 3140 | 0xff810061, 0x013d007e, 0xfe71fddf, 0x007c0380, | ||
| 3141 | 0x0241fd13, 0xfa94ff70, 0x068005e2, 0xfc9bf633, | ||
| 3142 | 0xfc7308ca, 0x0ad5fe30, 0xf274f7e0, 0x08c90f43, | ||
| 3143 | 0x01d4f147, 0xf371060f, 0x110d0000, | ||
| 3144 | }, { // 9.7 MHz | ||
| 3145 | 0x00010001, 0xfff9fff1, 0x00090038, 0x0025ffa7, | ||
| 3146 | 0xff5e0012, 0x013200f0, 0xfee3fd9b, 0xffaa0331, | ||
| 3147 | 0x0311fe15, 0xfa60fe18, 0x05bd06d1, 0xfe1bf64a, | ||
| 3148 | 0xfafa07ae, 0x0b7effab, 0xf2d5f6d7, 0x07d30f7a, | ||
| 3149 | 0x02a3f194, 0xf32905dc, 0x110d0000, | ||
| 3150 | }, { // 9.8 MHz | ||
| 3151 | 0x00010002, 0xfffcffee, 0xfffb0032, 0x003fffcd, | ||
| 3152 | 0xff4effc1, 0x0106014a, 0xff6efd8a, 0xfedd02aa, | ||
| 3153 | 0x03b0ff34, 0xfa74fcd7, 0x04bf0781, 0xffaaf6a3, | ||
| 3154 | 0xf99e066b, 0x0bf90128, 0xf359f5e1, 0x06d20fa2, | ||
| 3155 | 0x0370f1e5, 0xf2e405a8, 0x110d0000, | ||
| 3156 | }, { // 9.9 MHz | ||
| 3157 | 0x00000003, 0xffffffee, 0xffef0024, 0x0051fffa, | ||
| 3158 | 0xff54ff77, 0x00be0184, 0x0006fdad, 0xfe2701f3, | ||
| 3159 | 0x0413005e, 0xfad1fbba, 0x039007ee, 0x013bf73d, | ||
| 3160 | 0xf868050a, 0x0c4302a1, 0xf3fdf4fe, 0x05c70fba, | ||
| 3161 | 0x043bf23c, 0xf2a10575, 0x110d0000, | ||
| 3162 | }, { // 10.0 MHz | ||
| 3163 | 0x00000003, 0x0003fff1, 0xffe50011, 0x00570027, | ||
| 3164 | 0xff70ff3c, 0x00620198, 0x009efe01, 0xfd95011a, | ||
| 3165 | 0x04350183, 0xfb71fad0, 0x023c0812, 0x02c3f811, | ||
| 3166 | 0xf75e0390, 0x0c5c0411, 0xf4c1f432, 0x04b30fc1, | ||
| 3167 | 0x0503f297, 0xf2610541, 0x110d0000, | ||
| 3168 | }, { // 10.1 MHz | ||
| 3169 | 0x00000003, 0x0006fff7, 0xffdffffc, 0x00510050, | ||
| 3170 | 0xff9dff18, 0xfffc0184, 0x0128fe80, 0xfd32002e, | ||
| 3171 | 0x04130292, 0xfc4dfa21, 0x00d107ee, 0x0435f91c, | ||
| 3172 | 0xf6850205, 0x0c430573, 0xf5a1f37d, 0x03990fba, | ||
| 3173 | 0x05c7f2f8, 0xf222050d, 0x110d0000, | ||
| 3174 | }, { // 10.2 MHz | ||
| 3175 | 0x00000002, 0x0008fffe, 0xffdfffe7, 0x003f006e, | ||
| 3176 | 0xffd6ff0f, 0xff96014a, 0x0197ff1f, 0xfd05ff3e, | ||
| 3177 | 0x03b0037c, 0xfd59f9b7, 0xff5d0781, 0x0585fa56, | ||
| 3178 | 0xf5e4006f, 0x0bf906c4, 0xf69df2e0, 0x02790fa2, | ||
| 3179 | 0x0688f35d, 0xf1e604d8, 0x110d0000, | ||
| 3180 | }, { // 10.3 MHz | ||
| 3181 | 0xffff0001, 0x00090005, 0xffe4ffd6, 0x0025007e, | ||
| 3182 | 0x0014ff20, 0xff3c00f0, 0x01e1ffd0, 0xfd12fe5c, | ||
| 3183 | 0x03110433, 0xfe88f996, 0xfdf106d1, 0x06aafbb7, | ||
| 3184 | 0xf57efed8, 0x0b7e07ff, 0xf7b0f25e, 0x01560f7a, | ||
| 3185 | 0x0745f3c7, 0xf1ac04a4, 0x110d0000, | ||
| 3186 | }, { // 10.4 MHz | ||
| 3187 | 0xffffffff, 0x0008000c, 0xffedffcb, 0x0005007d, | ||
| 3188 | 0x0050ff4c, 0xfef6007e, 0x01ff0086, 0xfd58fd97, | ||
| 3189 | 0x024104ad, 0xffcaf9c0, 0xfc9905e2, 0x079afd35, | ||
| 3190 | 0xf555fd46, 0x0ad50920, 0xf8d9f1f6, 0x00310f43, | ||
| 3191 | 0x07fdf435, 0xf174046f, 0x110d0000, | ||
| 3192 | }, { // 10.5 MHz | ||
| 3193 | 0xfffffffe, 0x00050011, 0xfffaffc8, 0xffe5006b, | ||
| 3194 | 0x0082ff8c, 0xfecc0000, 0x01f00130, 0xfdd2fcfc, | ||
| 3195 | 0x014d04e3, 0x010efa32, 0xfb6404bf, 0x084efec5, | ||
| 3196 | 0xf569fbc2, 0x0a000a23, 0xfa15f1ab, 0xff0b0efc, | ||
| 3197 | 0x08b0f4a7, 0xf13f043a, 0x110d0000, | ||
| 3198 | }, { // 10.6 MHz | ||
| 3199 | 0x0000fffd, 0x00020012, 0x0007ffcd, 0xffc9004c, | ||
| 3200 | 0x00a4ffd9, 0xfec3ff82, 0x01b401c1, 0xfe76fc97, | ||
| 3201 | 0x004404d2, 0x0245fae8, 0xfa5f0370, 0x08c1005f, | ||
| 3202 | 0xf5bcfa52, 0x09020b04, 0xfb60f17b, 0xfde70ea6, | ||
| 3203 | 0x095df51e, 0xf10c0405, 0x110d0000, | ||
| 3204 | }, { // 10.7 MHz | ||
| 3205 | 0x0000fffd, 0xffff0011, 0x0014ffdb, 0xffb40023, | ||
| 3206 | 0x00b2002a, 0xfedbff10, 0x0150022d, 0xff38fc6f, | ||
| 3207 | 0xff36047b, 0x035efbda, 0xf9940202, 0x08ee01f5, | ||
| 3208 | 0xf649f8fe, 0x07e10bc2, 0xfcb6f169, 0xfcc60e42, | ||
| 3209 | 0x0a04f599, 0xf0db03d0, 0x110d0000, | ||
| 3210 | }, { // 10.8 MHz | ||
| 3211 | 0x0000fffd, 0xfffb000d, 0x001dffed, 0xffaafff5, | ||
| 3212 | 0x00aa0077, 0xff13feb6, 0x00ce026b, 0x000afc85, | ||
| 3213 | 0xfe3503e3, 0x044cfcfb, 0xf90c0082, 0x08d5037f, | ||
| 3214 | 0xf710f7cc, 0x069f0c59, 0xfe16f173, 0xfbaa0dcf, | ||
| 3215 | 0x0aa5f617, 0xf0ad039b, 0x110d0000, | ||
| 3216 | }, { // 10.9 MHz | ||
| 3217 | 0x0000fffe, 0xfff90006, 0x00210003, 0xffacffc8, | ||
| 3218 | 0x008e00b6, 0xff63fe7c, 0x003a0275, 0x00dafcda, | ||
| 3219 | 0xfd510313, 0x0501fe40, 0xf8cbfefd, 0x087604f0, | ||
| 3220 | 0xf80af6c2, 0x05430cc8, 0xff7af19a, 0xfa940d4e, | ||
| 3221 | 0x0b3ff699, 0xf0810365, 0x110d0000, | ||
| 3222 | }, { // 11.0 MHz | ||
| 3223 | 0x0001ffff, 0xfff8ffff, 0x00210018, 0xffbaffa3, | ||
| 3224 | 0x006000e1, 0xffc4fe68, 0xffa0024b, 0x019afd66, | ||
| 3225 | 0xfc990216, 0x0575ff99, 0xf8d4fd81, 0x07d40640, | ||
| 3226 | 0xf932f5e6, 0x03d20d0d, 0x00dff1de, 0xf9860cbf, | ||
| 3227 | 0x0bd1f71e, 0xf058032f, 0x110d0000, | ||
| 3228 | }, { // 11.1 MHz | ||
| 3229 | 0x00010000, 0xfff8fff8, 0x001b0029, 0xffd1ff8a, | ||
| 3230 | 0x002600f2, 0x002cfe7c, 0xff0f01f0, 0x023bfe20, | ||
| 3231 | 0xfc1700fa, 0x05a200f7, 0xf927fc1c, 0x06f40765, | ||
| 3232 | 0xfa82f53b, 0x02510d27, 0x0243f23d, 0xf8810c24, | ||
| 3233 | 0x0c5cf7a7, 0xf03102fa, 0x110d0000, | ||
| 3234 | }, { // 11.2 MHz | ||
| 3235 | 0x00010002, 0xfffafff2, 0x00110035, 0xfff0ff81, | ||
| 3236 | 0xffe700e7, 0x008ffeb6, 0xfe94016d, 0x02b0fefb, | ||
| 3237 | 0xfbd3ffd1, 0x05850249, 0xf9c1fadb, 0x05de0858, | ||
| 3238 | 0xfbf2f4c4, 0x00c70d17, 0x03a0f2b8, 0xf7870b7c, | ||
| 3239 | 0x0cdff833, 0xf00d02c4, 0x110d0000, | ||
| 3240 | }, { // 11.3 MHz | ||
| 3241 | 0x00000003, 0xfffdffee, 0x00040038, 0x0010ff88, | ||
| 3242 | 0xffac00c2, 0x00e2ff10, 0xfe3900cb, 0x02f1ffe9, | ||
| 3243 | 0xfbd3feaa, 0x05210381, 0xfa9cf9c8, 0x04990912, | ||
| 3244 | 0xfd7af484, 0xff390cdb, 0x04f4f34d, 0xf69a0ac9, | ||
| 3245 | 0x0d5af8c1, 0xefec028e, 0x110d0000, | ||
| 3246 | }, { // 11.4 MHz | ||
| 3247 | 0x00000003, 0x0000ffee, 0xfff60033, 0x002fff9f, | ||
| 3248 | 0xff7b0087, 0x011eff82, 0xfe080018, 0x02f900d8, | ||
| 3249 | 0xfc17fd96, 0x04790490, 0xfbadf8ed, 0x032f098e, | ||
| 3250 | 0xff10f47d, 0xfdaf0c75, 0x063cf3fc, 0xf5ba0a0b, | ||
| 3251 | 0x0dccf952, 0xefcd0258, 0x110d0000, | ||
| 3252 | }, { // 11.5 MHz | ||
| 3253 | 0x00000003, 0x0004fff1, 0xffea0026, 0x0046ffc3, | ||
| 3254 | 0xff5a003c, 0x013b0000, 0xfe04ff63, 0x02c801b8, | ||
| 3255 | 0xfc99fca6, 0x0397056a, 0xfcecf853, 0x01ad09c9, | ||
| 3256 | 0x00acf4ad, 0xfc2e0be7, 0x0773f4c2, 0xf4e90943, | ||
| 3257 | 0x0e35f9e6, 0xefb10221, 0x110d0000, | ||
| 3258 | }, { // 11.6 MHz | ||
| 3259 | 0x00000002, 0x0007fff6, 0xffe20014, 0x0054ffee, | ||
| 3260 | 0xff4effeb, 0x0137007e, 0xfe2efebb, 0x0260027a, | ||
| 3261 | 0xfd51fbe6, 0x02870605, 0xfe4af7fe, 0x001d09c1, | ||
| 3262 | 0x0243f515, 0xfabd0b32, 0x0897f59e, 0xf4280871, | ||
| 3263 | 0x0e95fa7c, 0xef9701eb, 0x110d0000, | ||
| 3264 | }, { // 11.7 MHz | ||
| 3265 | 0xffff0001, 0x0008fffd, 0xffdeffff, 0x0056001d, | ||
| 3266 | 0xff57ff9c, 0x011300f0, 0xfe82fe2e, 0x01ca0310, | ||
| 3267 | 0xfe35fb62, 0x0155065a, 0xffbaf7f2, 0xfe8c0977, | ||
| 3268 | 0x03cef5b2, 0xf9610a58, 0x09a5f68f, 0xf3790797, | ||
| 3269 | 0x0eebfb14, 0xef8001b5, 0x110d0000, | ||
| 3270 | }, { // 11.8 MHz | ||
| 3271 | 0xffff0000, 0x00080004, 0xffe0ffe9, 0x004c0047, | ||
| 3272 | 0xff75ff58, 0x00d1014a, 0xfef9fdc8, 0x0111036f, | ||
| 3273 | 0xff36fb21, 0x00120665, 0x012df82e, 0xfd0708ec, | ||
| 3274 | 0x0542f682, 0xf81f095c, 0x0a9af792, 0xf2db06b5, | ||
| 3275 | 0x0f38fbad, 0xef6c017e, 0x110d0000, | ||
| 3276 | }, { // 11.9 MHz | ||
| 3277 | 0xffffffff, 0x0007000b, 0xffe7ffd8, 0x00370068, | ||
| 3278 | 0xffa4ff28, 0x00790184, 0xff87fd91, 0x00430392, | ||
| 3279 | 0x0044fb26, 0xfece0626, 0x0294f8b2, 0xfb990825, | ||
| 3280 | 0x0698f77f, 0xf6fe0842, 0x0b73f8a7, 0xf25105cd, | ||
| 3281 | 0x0f7bfc48, 0xef5a0148, 0x110d0000, | ||
| 3282 | }, { // 12.0 MHz | ||
| 3283 | 0x0000fffe, 0x00050010, 0xfff2ffcc, 0x001b007b, | ||
| 3284 | 0xffdfff10, 0x00140198, 0x0020fd8e, 0xff710375, | ||
| 3285 | 0x014dfb73, 0xfd9a059f, 0x03e0f978, 0xfa4e0726, | ||
| 3286 | 0x07c8f8a7, 0xf600070c, 0x0c2ff9c9, 0xf1db04de, | ||
| 3287 | 0x0fb4fce5, 0xef4b0111, 0x110d0000, | ||
| 3288 | }, { // 12.1 MHz | ||
| 3289 | 0x0000fffd, 0x00010012, 0xffffffc8, 0xfffb007e, | ||
| 3290 | 0x001dff14, 0xffad0184, 0x00b7fdbe, 0xfea9031b, | ||
| 3291 | 0x0241fc01, 0xfc8504d6, 0x0504fa79, 0xf93005f6, | ||
| 3292 | 0x08caf9f2, 0xf52b05c0, 0x0ccbfaf9, 0xf17903eb, | ||
| 3293 | 0x0fe3fd83, 0xef3f00db, 0x110d0000, | ||
| 3294 | }, { // 12.2 MHz | ||
| 3295 | 0x0000fffd, 0xfffe0011, 0x000cffcc, 0xffdb0071, | ||
| 3296 | 0x0058ff32, 0xff4f014a, 0x013cfe1f, 0xfdfb028a, | ||
| 3297 | 0x0311fcc9, 0xfb9d03d6, 0x05f4fbad, 0xf848049d, | ||
| 3298 | 0x0999fb5b, 0xf4820461, 0x0d46fc32, 0xf12d02f4, | ||
| 3299 | 0x1007fe21, 0xef3600a4, 0x110d0000, | ||
| 3300 | }, { // 12.3 MHz | ||
| 3301 | 0x0000fffe, 0xfffa000e, 0x0017ffd9, 0xffc10055, | ||
| 3302 | 0x0088ff68, 0xff0400f0, 0x01a6fea7, 0xfd7501cc, | ||
| 3303 | 0x03b0fdc0, 0xfaef02a8, 0x06a7fd07, 0xf79d0326, | ||
| 3304 | 0x0a31fcda, 0xf40702f3, 0x0d9ffd72, 0xf0f601fa, | ||
| 3305 | 0x1021fec0, 0xef2f006d, 0x110d0000, | ||
| 3306 | }, { // 12.4 MHz | ||
| 3307 | 0x0001ffff, 0xfff80007, 0x001fffeb, 0xffaf002d, | ||
| 3308 | 0x00a8ffb0, 0xfed3007e, 0x01e9ff4c, 0xfd2000ee, | ||
| 3309 | 0x0413fed8, 0xfa82015c, 0x0715fe7d, 0xf7340198, | ||
| 3310 | 0x0a8dfe69, 0xf3bd017c, 0x0dd5feb8, 0xf0d500fd, | ||
| 3311 | 0x1031ff60, 0xef2b0037, 0x110d0000, | ||
| 3312 | }, { // 12.5 MHz | ||
| 3313 | 0x00010000, 0xfff70000, 0x00220000, 0xffa90000, | ||
| 3314 | 0x00b30000, 0xfec20000, 0x02000000, 0xfd030000, | ||
| 3315 | 0x04350000, 0xfa5e0000, 0x073b0000, 0xf7110000, | ||
| 3316 | 0x0aac0000, 0xf3a40000, 0x0de70000, 0xf0c90000, | ||
| 3317 | 0x10360000, 0xef290000, 0x110d0000, | ||
| 3318 | }, { // 12.6 MHz | ||
| 3319 | 0x00010001, 0xfff8fff9, 0x001f0015, 0xffafffd3, | ||
| 3320 | 0x00a80050, 0xfed3ff82, 0x01e900b4, 0xfd20ff12, | ||
| 3321 | 0x04130128, 0xfa82fea4, 0x07150183, 0xf734fe68, | ||
| 3322 | 0x0a8d0197, 0xf3bdfe84, 0x0dd50148, 0xf0d5ff03, | ||
| 3323 | 0x103100a0, 0xef2bffc9, 0x110d0000, | ||
| 3324 | }, { // 12.7 MHz | ||
| 3325 | 0x00000002, 0xfffafff2, 0x00170027, 0xffc1ffab, | ||
| 3326 | 0x00880098, 0xff04ff10, 0x01a60159, 0xfd75fe34, | ||
| 3327 | 0x03b00240, 0xfaeffd58, 0x06a702f9, 0xf79dfcda, | ||
| 3328 | 0x0a310326, 0xf407fd0d, 0x0d9f028e, 0xf0f6fe06, | ||
| 3329 | 0x10210140, 0xef2fff93, 0x110d0000, | ||
| 3330 | }, { // 12.8 MHz | ||
| 3331 | 0x00000003, 0xfffeffef, 0x000c0034, 0xffdbff8f, | ||
| 3332 | 0x005800ce, 0xff4ffeb6, 0x013c01e1, 0xfdfbfd76, | ||
| 3333 | 0x03110337, 0xfb9dfc2a, 0x05f40453, 0xf848fb63, | ||
| 3334 | 0x099904a5, 0xf482fb9f, 0x0d4603ce, 0xf12dfd0c, | ||
| 3335 | 0x100701df, 0xef36ff5c, 0x110d0000, | ||
| 3336 | }, { // 12.9 MHz | ||
| 3337 | 0x00000003, 0x0001ffee, 0xffff0038, 0xfffbff82, | ||
| 3338 | 0x001d00ec, 0xffadfe7c, 0x00b70242, 0xfea9fce5, | ||
| 3339 | 0x024103ff, 0xfc85fb2a, 0x05040587, 0xf930fa0a, | ||
| 3340 | 0x08ca060e, 0xf52bfa40, 0x0ccb0507, 0xf179fc15, | ||
| 3341 | 0x0fe3027d, 0xef3fff25, 0x110d0000, | ||
| 3342 | }, { // 13.0 MHz | ||
| 3343 | 0x00000002, 0x0005fff0, 0xfff20034, 0x001bff85, | ||
| 3344 | 0xffdf00f0, 0x0014fe68, 0x00200272, 0xff71fc8b, | ||
| 3345 | 0x014d048d, 0xfd9afa61, 0x03e00688, 0xfa4ef8da, | ||
| 3346 | 0x07c80759, 0xf600f8f4, 0x0c2f0637, 0xf1dbfb22, | ||
| 3347 | 0x0fb4031b, 0xef4bfeef, 0x110d0000, | ||
| 3348 | }, { // 13.1 MHz | ||
| 3349 | 0xffff0001, 0x0007fff5, 0xffe70028, 0x0037ff98, | ||
| 3350 | 0xffa400d8, 0x0079fe7c, 0xff87026f, 0x0043fc6e, | ||
| 3351 | 0x004404da, 0xfecef9da, 0x0294074e, 0xfb99f7db, | ||
| 3352 | 0x06980881, 0xf6fef7be, 0x0b730759, 0xf251fa33, | ||
| 3353 | 0x0f7b03b8, 0xef5afeb8, 0x110d0000, | ||
| 3354 | }, { // 13.2 MHz | ||
| 3355 | 0xffff0000, 0x0008fffc, 0xffe00017, 0x004cffb9, | ||
| 3356 | 0xff7500a8, 0x00d1feb6, 0xfef90238, 0x0111fc91, | ||
| 3357 | 0xff3604df, 0x0012f99b, 0x012d07d2, 0xfd07f714, | ||
| 3358 | 0x0542097e, 0xf81ff6a4, 0x0a9a086e, 0xf2dbf94b, | ||
| 3359 | 0x0f380453, 0xef6cfe82, 0x110d0000, | ||
| 3360 | }, { // 13.3 MHz | ||
| 3361 | 0xffffffff, 0x00080003, 0xffde0001, 0x0056ffe3, | ||
| 3362 | 0xff570064, 0x0113ff10, 0xfe8201d2, 0x01cafcf0, | ||
| 3363 | 0xfe35049e, 0x0155f9a6, 0xffba080e, 0xfe8cf689, | ||
| 3364 | 0x03ce0a4e, 0xf961f5a8, 0x09a50971, 0xf379f869, | ||
| 3365 | 0x0eeb04ec, 0xef80fe4b, 0x110d0000, | ||
| 3366 | }, { // 13.4 MHz | ||
| 3367 | 0x0000fffe, 0x0007000a, 0xffe2ffec, 0x00540012, | ||
| 3368 | 0xff4e0015, 0x0137ff82, 0xfe2e0145, 0x0260fd86, | ||
| 3369 | 0xfd51041a, 0x0287f9fb, 0xfe4a0802, 0x001df63f, | ||
| 3370 | 0x02430aeb, 0xfabdf4ce, 0x08970a62, 0xf428f78f, | ||
| 3371 | 0x0e950584, 0xef97fe15, 0x110d0000, | ||
| 3372 | }, { // 13.5 MHz | ||
| 3373 | 0x0000fffd, 0x0004000f, 0xffeaffda, 0x0046003d, | ||
| 3374 | 0xff5affc4, 0x013b0000, 0xfe04009d, 0x02c8fe48, | ||
| 3375 | 0xfc99035a, 0x0397fa96, 0xfcec07ad, 0x01adf637, | ||
| 3376 | 0x00ac0b53, 0xfc2ef419, 0x07730b3e, 0xf4e9f6bd, | ||
| 3377 | 0x0e35061a, 0xefb1fddf, 0x110d0000, | ||
| 3378 | }, { // 13.6 MHz | ||
| 3379 | 0x0000fffd, 0x00000012, 0xfff6ffcd, 0x002f0061, | ||
| 3380 | 0xff7bff79, 0x011e007e, 0xfe08ffe8, 0x02f9ff28, | ||
| 3381 | 0xfc17026a, 0x0479fb70, 0xfbad0713, 0x032ff672, | ||
| 3382 | 0xff100b83, 0xfdaff38b, 0x063c0c04, 0xf5baf5f5, | ||
| 3383 | 0x0dcc06ae, 0xefcdfda8, 0x110d0000, | ||
| 3384 | }, { // 13.7 MHz | ||
| 3385 | 0x0000fffd, 0xfffd0012, 0x0004ffc8, 0x00100078, | ||
| 3386 | 0xffacff3e, 0x00e200f0, 0xfe39ff35, 0x02f10017, | ||
| 3387 | 0xfbd30156, 0x0521fc7f, 0xfa9c0638, 0x0499f6ee, | ||
| 3388 | 0xfd7a0b7c, 0xff39f325, 0x04f40cb3, 0xf69af537, | ||
| 3389 | 0x0d5a073f, 0xefecfd72, 0x110d0000, | ||
| 3390 | }, { // 13.8 MHz | ||
| 3391 | 0x0001fffe, 0xfffa000e, 0x0011ffcb, 0xfff0007f, | ||
| 3392 | 0xffe7ff19, 0x008f014a, 0xfe94fe93, 0x02b00105, | ||
| 3393 | 0xfbd3002f, 0x0585fdb7, 0xf9c10525, 0x05def7a8, | ||
| 3394 | 0xfbf20b3c, 0x00c7f2e9, 0x03a00d48, 0xf787f484, | ||
| 3395 | 0x0cdf07cd, 0xf00dfd3c, 0x110d0000, | ||
| 3396 | }, { // 13.9 MHz | ||
| 3397 | 0x00010000, 0xfff80008, 0x001bffd7, 0xffd10076, | ||
| 3398 | 0x0026ff0e, 0x002c0184, 0xff0ffe10, 0x023b01e0, | ||
| 3399 | 0xfc17ff06, 0x05a2ff09, 0xf92703e4, 0x06f4f89b, | ||
| 3400 | 0xfa820ac5, 0x0251f2d9, 0x02430dc3, 0xf881f3dc, | ||
| 3401 | 0x0c5c0859, 0xf031fd06, 0x110d0000, | ||
| 3402 | }, { // 14.0 MHz | ||
| 3403 | 0x00010001, 0xfff80001, 0x0021ffe8, 0xffba005d, | ||
| 3404 | 0x0060ff1f, 0xffc40198, 0xffa0fdb5, 0x019a029a, | ||
| 3405 | 0xfc99fdea, 0x05750067, 0xf8d4027f, 0x07d4f9c0, | ||
| 3406 | 0xf9320a1a, 0x03d2f2f3, 0x00df0e22, 0xf986f341, | ||
| 3407 | 0x0bd108e2, 0xf058fcd1, 0x110d0000, | ||
| 3408 | }, { // 14.1 MHz | ||
| 3409 | 0x00000002, 0xfff9fffa, 0x0021fffd, 0xffac0038, | ||
| 3410 | 0x008eff4a, 0xff630184, 0x003afd8b, 0x00da0326, | ||
| 3411 | 0xfd51fced, 0x050101c0, 0xf8cb0103, 0x0876fb10, | ||
| 3412 | 0xf80a093e, 0x0543f338, 0xff7a0e66, 0xfa94f2b2, | ||
| 3413 | 0x0b3f0967, 0xf081fc9b, 0x110d0000, | ||
| 3414 | }, { // 14.2 MHz | ||
| 3415 | 0x00000003, 0xfffbfff3, 0x001d0013, 0xffaa000b, | ||
| 3416 | 0x00aaff89, 0xff13014a, 0x00cefd95, 0x000a037b, | ||
| 3417 | 0xfe35fc1d, 0x044c0305, 0xf90cff7e, 0x08d5fc81, | ||
| 3418 | 0xf7100834, 0x069ff3a7, 0xfe160e8d, 0xfbaaf231, | ||
| 3419 | 0x0aa509e9, 0xf0adfc65, 0x110d0000, | ||
| 3420 | }, { // 14.3 MHz | ||
| 3421 | 0x00000003, 0xffffffef, 0x00140025, 0xffb4ffdd, | ||
| 3422 | 0x00b2ffd6, 0xfedb00f0, 0x0150fdd3, 0xff380391, | ||
| 3423 | 0xff36fb85, 0x035e0426, 0xf994fdfe, 0x08eefe0b, | ||
| 3424 | 0xf6490702, 0x07e1f43e, 0xfcb60e97, 0xfcc6f1be, | ||
| 3425 | 0x0a040a67, 0xf0dbfc30, 0x110d0000, | ||
| 3426 | }, { // 14.4 MHz | ||
| 3427 | 0x00000003, 0x0002ffee, 0x00070033, 0xffc9ffb4, | ||
| 3428 | 0x00a40027, 0xfec3007e, 0x01b4fe3f, 0xfe760369, | ||
| 3429 | 0x0044fb2e, 0x02450518, 0xfa5ffc90, 0x08c1ffa1, | ||
| 3430 | 0xf5bc05ae, 0x0902f4fc, 0xfb600e85, 0xfde7f15a, | ||
| 3431 | 0x095d0ae2, 0xf10cfbfb, 0x110d0000, | ||
| 3432 | }, { // 14.5 MHz | ||
| 3433 | 0xffff0002, 0x0005ffef, 0xfffa0038, 0xffe5ff95, | ||
| 3434 | 0x00820074, 0xfecc0000, 0x01f0fed0, 0xfdd20304, | ||
| 3435 | 0x014dfb1d, 0x010e05ce, 0xfb64fb41, 0x084e013b, | ||
| 3436 | 0xf569043e, 0x0a00f5dd, 0xfa150e55, 0xff0bf104, | ||
| 3437 | 0x08b00b59, 0xf13ffbc6, 0x110d0000, | ||
| 3438 | }, { // 14.6 MHz | ||
| 3439 | 0xffff0001, 0x0008fff4, 0xffed0035, 0x0005ff83, | ||
| 3440 | 0x005000b4, 0xfef6ff82, 0x01ffff7a, 0xfd580269, | ||
| 3441 | 0x0241fb53, 0xffca0640, 0xfc99fa1e, 0x079a02cb, | ||
| 3442 | 0xf55502ba, 0x0ad5f6e0, 0xf8d90e0a, 0x0031f0bd, | ||
| 3443 | 0x07fd0bcb, 0xf174fb91, 0x110d0000, | ||
| 3444 | }, { // 14.7 MHz | ||
| 3445 | 0xffffffff, 0x0009fffb, 0xffe4002a, 0x0025ff82, | ||
| 3446 | 0x001400e0, 0xff3cff10, 0x01e10030, 0xfd1201a4, | ||
| 3447 | 0x0311fbcd, 0xfe88066a, 0xfdf1f92f, 0x06aa0449, | ||
| 3448 | 0xf57e0128, 0x0b7ef801, 0xf7b00da2, 0x0156f086, | ||
| 3449 | 0x07450c39, 0xf1acfb5c, 0x110d0000, | ||
| 3450 | }, { // 14.8 MHz | ||
| 3451 | 0x0000fffe, 0x00080002, 0xffdf0019, 0x003fff92, | ||
| 3452 | 0xffd600f1, 0xff96feb6, 0x019700e1, 0xfd0500c2, | ||
| 3453 | 0x03b0fc84, 0xfd590649, 0xff5df87f, 0x058505aa, | ||
| 3454 | 0xf5e4ff91, 0x0bf9f93c, 0xf69d0d20, 0x0279f05e, | ||
| 3455 | 0x06880ca3, 0xf1e6fb28, 0x110d0000, | ||
| 3456 | }, { // 14.9 MHz | ||
| 3457 | 0x0000fffd, 0x00060009, 0xffdf0004, 0x0051ffb0, | ||
| 3458 | 0xff9d00e8, 0xfffcfe7c, 0x01280180, 0xfd32ffd2, | ||
| 3459 | 0x0413fd6e, 0xfc4d05df, 0x00d1f812, 0x043506e4, | ||
| 3460 | 0xf685fdfb, 0x0c43fa8d, 0xf5a10c83, 0x0399f046, | ||
| 3461 | 0x05c70d08, 0xf222faf3, 0x110d0000, | ||
| 3462 | }, { // 15.0 MHz | ||
| 3463 | 0x0000fffd, 0x0003000f, 0xffe5ffef, 0x0057ffd9, | ||
| 3464 | 0xff7000c4, 0x0062fe68, 0x009e01ff, 0xfd95fee6, | ||
| 3465 | 0x0435fe7d, 0xfb710530, 0x023cf7ee, 0x02c307ef, | ||
| 3466 | 0xf75efc70, 0x0c5cfbef, 0xf4c10bce, 0x04b3f03f, | ||
| 3467 | 0x05030d69, 0xf261fabf, 0x110d0000, | ||
| 3468 | }, { // 15.1 MHz | ||
| 3469 | 0x0000fffd, 0xffff0012, 0xffefffdc, 0x00510006, | ||
| 3470 | 0xff540089, 0x00befe7c, 0x00060253, 0xfe27fe0d, | ||
| 3471 | 0x0413ffa2, 0xfad10446, 0x0390f812, 0x013b08c3, | ||
| 3472 | 0xf868faf6, 0x0c43fd5f, 0xf3fd0b02, 0x05c7f046, | ||
| 3473 | 0x043b0dc4, 0xf2a1fa8b, 0x110d0000, | ||
| 3474 | }, { // 15.2 MHz | ||
| 3475 | 0x0001fffe, 0xfffc0012, 0xfffbffce, 0x003f0033, | ||
| 3476 | 0xff4e003f, 0x0106feb6, 0xff6e0276, 0xfeddfd56, | ||
| 3477 | 0x03b000cc, 0xfa740329, 0x04bff87f, 0xffaa095d, | ||
| 3478 | 0xf99ef995, 0x0bf9fed8, 0xf3590a1f, 0x06d2f05e, | ||
| 3479 | 0x03700e1b, 0xf2e4fa58, 0x110d0000, | ||
| 3480 | }, { // 15.3 MHz | ||
| 3481 | 0x0001ffff, 0xfff9000f, 0x0009ffc8, 0x00250059, | ||
| 3482 | 0xff5effee, 0x0132ff10, 0xfee30265, 0xffaafccf, | ||
| 3483 | 0x031101eb, 0xfa6001e8, 0x05bdf92f, 0xfe1b09b6, | ||
| 3484 | 0xfafaf852, 0x0b7e0055, 0xf2d50929, 0x07d3f086, | ||
| 3485 | 0x02a30e6c, 0xf329fa24, 0x110d0000, | ||
| 3486 | }, { // 15.4 MHz | ||
| 3487 | 0x00010001, 0xfff80009, 0x0015ffca, 0x00050074, | ||
| 3488 | 0xff81ff9f, 0x013dff82, 0xfe710221, 0x007cfc80, | ||
| 3489 | 0x024102ed, 0xfa940090, 0x0680fa1e, 0xfc9b09cd, | ||
| 3490 | 0xfc73f736, 0x0ad501d0, 0xf2740820, 0x08c9f0bd, | ||
| 3491 | 0x01d40eb9, 0xf371f9f1, 0x110d0000, | ||
| 3492 | }, { // 15.5 MHz | ||
| 3493 | 0x00000002, 0xfff80002, 0x001effd5, 0xffe5007f, | ||
| 3494 | 0xffb4ff5b, 0x01280000, 0xfe2401b0, 0x0146fc70, | ||
| 3495 | 0x014d03c6, 0xfb10ff32, 0x0701fb41, 0xfb3709a1, | ||
| 3496 | 0xfe00f644, 0x0a000345, 0xf2350708, 0x09b2f104, | ||
| 3497 | 0x01050eff, 0xf3baf9be, 0x110d0000, | ||
| 3498 | }, { // 15.6 MHz | ||
| 3499 | 0x00000003, 0xfff9fffb, 0x0022ffe6, 0xffc9007a, | ||
| 3500 | 0xfff0ff29, 0x00f2007e, 0xfe01011b, 0x01f6fc9e, | ||
| 3501 | 0x00440467, 0xfbccfdde, 0x0738fc90, 0xf9f70934, | ||
| 3502 | 0xff99f582, 0x090204b0, 0xf21a05e1, 0x0a8df15a, | ||
| 3503 | 0x00340f41, 0xf405f98b, 0x110d0000, | ||
| 3504 | }, { // 15.7 MHz | ||
| 3505 | 0x00000003, 0xfffcfff4, 0x0020fffa, 0xffb40064, | ||
| 3506 | 0x002fff11, 0x00a400f0, 0xfe0d006e, 0x0281fd09, | ||
| 3507 | 0xff3604c9, 0xfcbffca2, 0x0726fdfe, 0xf8e80888, | ||
| 3508 | 0x0134f4f3, 0x07e1060c, 0xf22304af, 0x0b59f1be, | ||
| 3509 | 0xff640f7d, 0xf452f959, 0x110d0000, | ||
| 3510 | }, { // 15.8 MHz | ||
| 3511 | 0x00000003, 0x0000fff0, 0x001a0010, 0xffaa0041, | ||
| 3512 | 0x0067ff13, 0x0043014a, 0xfe46ffb9, 0x02dbfda8, | ||
| 3513 | 0xfe3504e5, 0xfddcfb8d, 0x06c9ff7e, 0xf81107a2, | ||
| 3514 | 0x02c9f49a, 0x069f0753, 0xf2500373, 0x0c14f231, | ||
| 3515 | 0xfe930fb3, 0xf4a1f927, 0x110d0000, | ||
| 3516 | }, { // 15.9 MHz | ||
| 3517 | 0xffff0002, 0x0003ffee, 0x000f0023, 0xffac0016, | ||
| 3518 | 0x0093ff31, 0xffdc0184, 0xfea6ff09, 0x02fdfe70, | ||
| 3519 | 0xfd5104ba, 0xff15faac, 0x06270103, 0xf7780688, | ||
| 3520 | 0x044df479, 0x05430883, 0xf2a00231, 0x0cbef2b2, | ||
| 3521 | 0xfdc40fe3, 0xf4f2f8f5, 0x110d0000, | ||
| 3522 | }, { // 16.0 MHz | ||
| 3523 | 0xffff0001, 0x0006ffef, 0x00020031, 0xffbaffe8, | ||
| 3524 | 0x00adff66, 0xff790198, 0xff26fe6e, 0x02e5ff55, | ||
| 3525 | 0xfc99044a, 0x005bfa09, 0x0545027f, 0xf7230541, | ||
| 3526 | 0x05b8f490, 0x03d20997, 0xf31300eb, 0x0d55f341, | ||
| 3527 | 0xfcf6100e, 0xf544f8c3, 0x110d0000, | ||
| 3528 | } | ||
| 3529 | }; | ||
| 3530 | |||
| 2741 | static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) | 3531 | static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) |
| 2742 | { | 3532 | { |
| 2743 | u64 pll_freq; | 3533 | u64 pll_freq; |
| 2744 | u32 pll_freq_word; | 3534 | u32 pll_freq_word; |
| 3535 | const u32 *coeffs; | ||
| 2745 | 3536 | ||
| 2746 | v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz); | 3537 | v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz); |
| 2747 | 3538 | ||
| @@ -2763,2889 +3554,26 @@ static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) · 15 unmodified lines | |||
| 2763 | 3554 | ||
| 2764 | v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz); | 3555 | v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz); |
| 2765 | 3556 | ||
| 2766 | switch (ifHz) { | 3557 | coeffs = ifhz_coeffs[(ifHz - 3000000) / 100000]; |
| 2767 | case 3000000: | 3558 | cx25840_write4(client, DIF_BPF_COEFF01, coeffs[0]); |
| 2768 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | 3559 | cx25840_write4(client, DIF_BPF_COEFF23, coeffs[1]); |
| 2769 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012); | 3560 | cx25840_write4(client, DIF_BPF_COEFF45, coeffs[2]); |
| 2770 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024); | 3561 | cx25840_write4(client, DIF_BPF_COEFF67, coeffs[3]); |
| 2771 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8); | 3562 | cx25840_write4(client, DIF_BPF_COEFF89, coeffs[4]); |
| 2772 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50); | 3563 | cx25840_write4(client, DIF_BPF_COEFF1011, coeffs[5]); |
| 2773 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68); | 3564 | cx25840_write4(client, DIF_BPF_COEFF1213, coeffs[6]); |
| 2774 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34); | 3565 | cx25840_write4(client, DIF_BPF_COEFF1415, coeffs[7]); |
| 2775 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7); | 3566 | cx25840_write4(client, DIF_BPF_COEFF1617, coeffs[8]); |
| 2776 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f); | 3567 | cx25840_write4(client, DIF_BPF_COEFF1819, coeffs[9]); |
| 2777 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d); | 3568 | cx25840_write4(client, DIF_BPF_COEFF2021, coeffs[10]); |
| 2778 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688); | 3569 | cx25840_write4(client, DIF_BPF_COEFF2223, coeffs[11]); |
| 2779 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6); | 3570 | cx25840_write4(client, DIF_BPF_COEFF2425, coeffs[12]); |
| 2780 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3); | 3571 | cx25840_write4(client, DIF_BPF_COEFF2627, coeffs[13]); |
| 2781 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342); | 3572 | cx25840_write4(client, DIF_BPF_COEFF2829, coeffs[14]); |
| 2782 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337); | 3573 | cx25840_write4(client, DIF_BPF_COEFF3031, coeffs[15]); |
| 2783 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22); | 3574 | cx25840_write4(client, DIF_BPF_COEFF3233, coeffs[16]); |
| 2784 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f); | 3575 | cx25840_write4(client, DIF_BPF_COEFF3435, coeffs[17]); |
| 2785 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce); | 3576 | cx25840_write4(client, DIF_BPF_COEFF36, coeffs[18]); |
| 2786 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2787 | break; | ||
| 2788 | |||
| 2789 | case 3100000: | ||
| 2790 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 2791 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012); | ||
| 2792 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220032); | ||
| 2793 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00370026); | ||
| 2794 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff91); | ||
| 2795 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0efe7c); | ||
| 2796 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fdcc); | ||
| 2797 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe0afedb); | ||
| 2798 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440224); | ||
| 2799 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0434060c); | ||
| 2800 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738074e); | ||
| 2801 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06090361); | ||
| 2802 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99fb39); | ||
| 2803 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef3b6); | ||
| 2804 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21af2a5); | ||
| 2805 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf573fa33); | ||
| 2806 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034067d); | ||
| 2807 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bfb0fb9); | ||
| 2808 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2809 | break; | ||
| 2810 | |||
| 2811 | case 3200000: | ||
| 2812 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000); | ||
| 2813 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000e); | ||
| 2814 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200038); | ||
| 2815 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c004f); | ||
| 2816 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002fffdf); | ||
| 2817 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff5cfeb6); | ||
| 2818 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dfd92); | ||
| 2819 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7ffe03); | ||
| 2820 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36010a); | ||
| 2821 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03410575); | ||
| 2822 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x072607d2); | ||
| 2823 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x071804d5); | ||
| 2824 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134fcb7); | ||
| 2825 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff451); | ||
| 2826 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223f22e); | ||
| 2827 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4a7f94b); | ||
| 2828 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff6405e8); | ||
| 2829 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bae0fa4); | ||
| 2830 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2831 | break; | ||
| 2832 | |||
| 2833 | case 3300000: | ||
| 2834 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
| 2835 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000008); | ||
| 2836 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0036); | ||
| 2837 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056006d); | ||
| 2838 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00670030); | ||
| 2839 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffbdff10); | ||
| 2840 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46fd8d); | ||
| 2841 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd25fd4f); | ||
| 2842 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35ffe0); | ||
| 2843 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0224049f); | ||
| 2844 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9080e); | ||
| 2845 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07ef0627); | ||
| 2846 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9fe45); | ||
| 2847 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f513); | ||
| 2848 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250f1d2); | ||
| 2849 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3ecf869); | ||
| 2850 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930552); | ||
| 2851 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b5f0f8f); | ||
| 2852 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2853 | break; | ||
| 2854 | |||
| 2855 | case 3400000: | ||
| 2856 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 2857 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0001); | ||
| 2858 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000f002c); | ||
| 2859 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054007d); | ||
| 2860 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0093007c); | ||
| 2861 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0024ff82); | ||
| 2862 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6fdbb); | ||
| 2863 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd03fcca); | ||
| 2864 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51feb9); | ||
| 2865 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00eb0392); | ||
| 2866 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270802); | ||
| 2867 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08880750); | ||
| 2868 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044dffdb); | ||
| 2869 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf5f8); | ||
| 2870 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0f193); | ||
| 2871 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf342f78f); | ||
| 2872 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc404b9); | ||
| 2873 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b0e0f78); | ||
| 2874 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2875 | break; | ||
| 2876 | |||
| 2877 | case 3500000: | ||
| 2878 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 2879 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff9); | ||
| 2880 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0002001b); | ||
| 2881 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046007d); | ||
| 2882 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad00ba); | ||
| 2883 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00870000); | ||
| 2884 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe1a); | ||
| 2885 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1bfc7e); | ||
| 2886 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fda4); | ||
| 2887 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffa5025c); | ||
| 2888 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x054507ad); | ||
| 2889 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08dd0847); | ||
| 2890 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80172); | ||
| 2891 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef6ff); | ||
| 2892 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313f170); | ||
| 2893 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2abf6bd); | ||
| 2894 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6041f); | ||
| 2895 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0abc0f61); | ||
| 2896 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2897 | break; | ||
| 2898 | |||
| 2899 | case 3600000: | ||
| 2900 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 2901 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff3); | ||
| 2902 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff50006); | ||
| 2903 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f006c); | ||
| 2904 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b200e3); | ||
| 2905 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00dc007e); | ||
| 2906 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9fea0); | ||
| 2907 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd6bfc71); | ||
| 2908 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fcb1); | ||
| 2909 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe65010b); | ||
| 2910 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x042d0713); | ||
| 2911 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ec0906); | ||
| 2912 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020302); | ||
| 2913 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff823); | ||
| 2914 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7f16a); | ||
| 2915 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf228f5f5); | ||
| 2916 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2a0384); | ||
| 2917 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a670f4a); | ||
| 2918 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2919 | break; | ||
| 2920 | |||
| 2921 | case 3700000: | ||
| 2922 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 2923 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7ffef); | ||
| 2924 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9fff1); | ||
| 2925 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010004d); | ||
| 2926 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a100f2); | ||
| 2927 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011a00f0); | ||
| 2928 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053ff44); | ||
| 2929 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdedfca2); | ||
| 2930 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fbef); | ||
| 2931 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd39ffae); | ||
| 2932 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x02ea0638); | ||
| 2933 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08b50987); | ||
| 2934 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230483); | ||
| 2935 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f960); | ||
| 2936 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45bf180); | ||
| 2937 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1b8f537); | ||
| 2938 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb6102e7); | ||
| 2939 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a110f32); | ||
| 2940 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2941 | break; | ||
| 2942 | |||
| 2943 | case 3800000: | ||
| 2944 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 2945 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee); | ||
| 2946 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffdd); | ||
| 2947 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00024); | ||
| 2948 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007c00e5); | ||
| 2949 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013a014a); | ||
| 2950 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e6fff8); | ||
| 2951 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe98fd0f); | ||
| 2952 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fb67); | ||
| 2953 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc32fe54); | ||
| 2954 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01880525); | ||
| 2955 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x083909c7); | ||
| 2956 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x091505ee); | ||
| 2957 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7fab3); | ||
| 2958 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52df1b4); | ||
| 2959 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf15df484); | ||
| 2960 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9b0249); | ||
| 2961 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09ba0f19); | ||
| 2962 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2963 | break; | ||
| 2964 | |||
| 2965 | case 3900000: | ||
| 2966 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000); | ||
| 2967 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff0); | ||
| 2968 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffcf); | ||
| 2969 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1fff6); | ||
| 2970 | cx25840_write4(client, DIF_BPF_COEFF89, 0x004800be); | ||
| 2971 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01390184); | ||
| 2972 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x016300ac); | ||
| 2973 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff5efdb1); | ||
| 2974 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb23); | ||
| 2975 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb5cfd0d); | ||
| 2976 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x001703e4); | ||
| 2977 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x077b09c4); | ||
| 2978 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d2073c); | ||
| 2979 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251fc18); | ||
| 2980 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61cf203); | ||
| 2981 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf118f3dc); | ||
| 2982 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d801aa); | ||
| 2983 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09600eff); | ||
| 2984 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 2985 | break; | ||
| 2986 | |||
| 2987 | case 4000000: | ||
| 2988 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 2989 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffefff4); | ||
| 2990 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffc8); | ||
| 2991 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffca); | ||
| 2992 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000b0082); | ||
| 2993 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01170198); | ||
| 2994 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10152); | ||
| 2995 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0030fe7b); | ||
| 2996 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb24); | ||
| 2997 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfac3fbe9); | ||
| 2998 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5027f); | ||
| 2999 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0683097f); | ||
| 3000 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a560867); | ||
| 3001 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2fd89); | ||
| 3002 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723f26f); | ||
| 3003 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0e8f341); | ||
| 3004 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919010a); | ||
| 3005 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09060ee5); | ||
| 3006 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3007 | break; | ||
| 3008 | |||
| 3009 | case 4100000: | ||
| 3010 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 3011 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fffb); | ||
| 3012 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8ffca); | ||
| 3013 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffa4); | ||
| 3014 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffcd0036); | ||
| 3015 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d70184); | ||
| 3016 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f601dc); | ||
| 3017 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ffff60); | ||
| 3018 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb6d); | ||
| 3019 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6efaf5); | ||
| 3020 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd410103); | ||
| 3021 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x055708f9); | ||
| 3022 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e0969); | ||
| 3023 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543ff02); | ||
| 3024 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842f2f5); | ||
| 3025 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cef2b2); | ||
| 3026 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85e006b); | ||
| 3027 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x08aa0ecb); | ||
| 3028 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3029 | break; | ||
| 3030 | |||
| 3031 | case 4200000: | ||
| 3032 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
| 3033 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050003); | ||
| 3034 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff3ffd3); | ||
| 3035 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaff8b); | ||
| 3036 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ffe5); | ||
| 3037 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0080014a); | ||
| 3038 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe023f); | ||
| 3039 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ba0050); | ||
| 3040 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fbf8); | ||
| 3041 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa62fa3b); | ||
| 3042 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9ff7e); | ||
| 3043 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04010836); | ||
| 3044 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa90a3d); | ||
| 3045 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f007f); | ||
| 3046 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf975f395); | ||
| 3047 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cbf231); | ||
| 3048 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ffcb); | ||
| 3049 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x084c0eaf); | ||
| 3050 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3051 | break; | ||
| 3052 | |||
| 3053 | case 4300000: | ||
| 3054 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
| 3055 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000a); | ||
| 3056 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0000ffe4); | ||
| 3057 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff81); | ||
| 3058 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff96); | ||
| 3059 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x001c00f0); | ||
| 3060 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70271); | ||
| 3061 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0254013b); | ||
| 3062 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fcbd); | ||
| 3063 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa9ff9c5); | ||
| 3064 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbfdfe); | ||
| 3065 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x028c073b); | ||
| 3066 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a750adf); | ||
| 3067 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e101fa); | ||
| 3068 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab8f44e); | ||
| 3069 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0ddf1be); | ||
| 3070 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ff2b); | ||
| 3071 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x07ed0e94); | ||
| 3072 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3073 | break; | ||
| 3074 | |||
| 3075 | case 4400000: | ||
| 3076 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 3077 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000f); | ||
| 3078 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000efff8); | ||
| 3079 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff87); | ||
| 3080 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff54); | ||
| 3081 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffb5007e); | ||
| 3082 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01860270); | ||
| 3083 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c00210); | ||
| 3084 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fdb2); | ||
| 3085 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb22f997); | ||
| 3086 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2fc90); | ||
| 3087 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0102060f); | ||
| 3088 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a050b4c); | ||
| 3089 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902036e); | ||
| 3090 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0af51e); | ||
| 3091 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf106f15a); | ||
| 3092 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64efe8b); | ||
| 3093 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x078d0e77); | ||
| 3094 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3095 | break; | ||
| 3096 | |||
| 3097 | case 4500000: | ||
| 3098 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 3099 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012); | ||
| 3100 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0019000e); | ||
| 3101 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff9e); | ||
| 3102 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff25); | ||
| 3103 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff560000); | ||
| 3104 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112023b); | ||
| 3105 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f702c0); | ||
| 3106 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfec8); | ||
| 3107 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbe5f9b3); | ||
| 3108 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947fb41); | ||
| 3109 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xff7004b9); | ||
| 3110 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a0b81); | ||
| 3111 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a0004d8); | ||
| 3112 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd65f603); | ||
| 3113 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf144f104); | ||
| 3114 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aafdec); | ||
| 3115 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x072b0e5a); | ||
| 3116 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3117 | break; | ||
| 3118 | |||
| 3119 | case 4600000: | ||
| 3120 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 3121 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060012); | ||
| 3122 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200022); | ||
| 3123 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ffc1); | ||
| 3124 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ff10); | ||
| 3125 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff09ff82); | ||
| 3126 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x008601d7); | ||
| 3127 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f50340); | ||
| 3128 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fff0); | ||
| 3129 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcddfa19); | ||
| 3130 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa1e); | ||
| 3131 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfde30343); | ||
| 3132 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08790b7f); | ||
| 3133 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50631); | ||
| 3134 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec7f6fc); | ||
| 3135 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf198f0bd); | ||
| 3136 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50dfd4e); | ||
| 3137 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06c90e3d); | ||
| 3138 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3139 | break; | ||
| 3140 | |||
| 3141 | case 4700000: | ||
| 3142 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
| 3143 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f); | ||
| 3144 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220030); | ||
| 3145 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffed); | ||
| 3146 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff87ff15); | ||
| 3147 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed6ff10); | ||
| 3148 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffed014c); | ||
| 3149 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b90386); | ||
| 3150 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110119); | ||
| 3151 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfdfefac4); | ||
| 3152 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6f92f); | ||
| 3153 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc6701b7); | ||
| 3154 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07670b44); | ||
| 3155 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0776); | ||
| 3156 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x002df807); | ||
| 3157 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf200f086); | ||
| 3158 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477fcb1); | ||
| 3159 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06650e1e); | ||
| 3160 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3161 | break; | ||
| 3162 | |||
| 3163 | case 4800000: | ||
| 3164 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 3165 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0009); | ||
| 3166 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0038); | ||
| 3167 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f001b); | ||
| 3168 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffbcff36); | ||
| 3169 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec2feb6); | ||
| 3170 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff5600a5); | ||
| 3171 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0248038d); | ||
| 3172 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00232); | ||
| 3173 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff39fbab); | ||
| 3174 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4f87f); | ||
| 3175 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb060020); | ||
| 3176 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x062a0ad2); | ||
| 3177 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf908a3); | ||
| 3178 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0192f922); | ||
| 3179 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf27df05e); | ||
| 3180 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8fc14); | ||
| 3181 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06000e00); | ||
| 3182 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3183 | break; | ||
| 3184 | |||
| 3185 | case 4900000: | ||
| 3186 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 3187 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0002); | ||
| 3188 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00160037); | ||
| 3189 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510046); | ||
| 3190 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff9ff6d); | ||
| 3191 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed0fe7c); | ||
| 3192 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefff0); | ||
| 3193 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01aa0356); | ||
| 3194 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413032b); | ||
| 3195 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x007ffcc5); | ||
| 3196 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cf812); | ||
| 3197 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9cefe87); | ||
| 3198 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c90a2c); | ||
| 3199 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4309b4); | ||
| 3200 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f3fa4a); | ||
| 3201 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf30ef046); | ||
| 3202 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361fb7a); | ||
| 3203 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x059b0de0); | ||
| 3204 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3205 | break; | ||
| 3206 | |||
| 3207 | case 5000000: | ||
| 3208 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 3209 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa); | ||
| 3210 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000a002d); | ||
| 3211 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00570067); | ||
| 3212 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0037ffb5); | ||
| 3213 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfefffe68); | ||
| 3214 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62ff3d); | ||
| 3215 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ec02e3); | ||
| 3216 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x043503f6); | ||
| 3217 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x01befe05); | ||
| 3218 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa27f7ee); | ||
| 3219 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8c6fcf8); | ||
| 3220 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x034c0954); | ||
| 3221 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0aa4); | ||
| 3222 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x044cfb7e); | ||
| 3223 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3b1f03f); | ||
| 3224 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2fae1); | ||
| 3225 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x05340dc0); | ||
| 3226 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3227 | break; | ||
| 3228 | |||
| 3229 | case 5100000: | ||
| 3230 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 3231 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff4); | ||
| 3232 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffd001e); | ||
| 3233 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051007b); | ||
| 3234 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006e0006); | ||
| 3235 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff48fe7c); | ||
| 3236 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfe9a); | ||
| 3237 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x001d023e); | ||
| 3238 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130488); | ||
| 3239 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02e6ff5b); | ||
| 3240 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1ef812); | ||
| 3241 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7f7fb7f); | ||
| 3242 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bc084e); | ||
| 3243 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430b72); | ||
| 3244 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x059afcba); | ||
| 3245 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf467f046); | ||
| 3246 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cfa4a); | ||
| 3247 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x04cd0da0); | ||
| 3248 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3249 | break; | ||
| 3250 | |||
| 3251 | case 5200000: | ||
| 3252 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 3253 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffef); | ||
| 3254 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff00009); | ||
| 3255 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f007f); | ||
| 3256 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00980056); | ||
| 3257 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffa5feb6); | ||
| 3258 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe15); | ||
| 3259 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff4b0170); | ||
| 3260 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b004d7); | ||
| 3261 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03e800b9); | ||
| 3262 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc48f87f); | ||
| 3263 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf768fa23); | ||
| 3264 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022071f); | ||
| 3265 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90c1b); | ||
| 3266 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x06dafdfd); | ||
| 3267 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf52df05e); | ||
| 3268 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef9b5); | ||
| 3269 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x04640d7f); | ||
| 3270 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3271 | break; | ||
| 3272 | |||
| 3273 | case 5300000: | ||
| 3274 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
| 3275 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee); | ||
| 3276 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6fff3); | ||
| 3277 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00250072); | ||
| 3278 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00af009c); | ||
| 3279 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x000cff10); | ||
| 3280 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13fdb8); | ||
| 3281 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe870089); | ||
| 3282 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104e1); | ||
| 3283 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04b8020f); | ||
| 3284 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd98f92f); | ||
| 3285 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf71df8f0); | ||
| 3286 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe8805ce); | ||
| 3287 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0c9c); | ||
| 3288 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0808ff44); | ||
| 3289 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf603f086); | ||
| 3290 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af922); | ||
| 3291 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03fb0d5e); | ||
| 3292 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3293 | break; | ||
| 3294 | |||
| 3295 | case 5400000: | ||
| 3296 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 3297 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffef); | ||
| 3298 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe0); | ||
| 3299 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00050056); | ||
| 3300 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b000d1); | ||
| 3301 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0071ff82); | ||
| 3302 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53fd8c); | ||
| 3303 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfddfff99); | ||
| 3304 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104a3); | ||
| 3305 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x054a034d); | ||
| 3306 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff01fa1e); | ||
| 3307 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf717f7ed); | ||
| 3308 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf50461); | ||
| 3309 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50cf4); | ||
| 3310 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0921008d); | ||
| 3311 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf6e7f0bd); | ||
| 3312 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff891); | ||
| 3313 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03920d3b); | ||
| 3314 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3315 | break; | ||
| 3316 | |||
| 3317 | case 5500000: | ||
| 3318 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 3319 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffffff3); | ||
| 3320 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffd1); | ||
| 3321 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5002f); | ||
| 3322 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009c00ed); | ||
| 3323 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00cb0000); | ||
| 3324 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfebafd94); | ||
| 3325 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd61feb0); | ||
| 3326 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d0422); | ||
| 3327 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05970464); | ||
| 3328 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0074fb41); | ||
| 3329 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf759f721); | ||
| 3330 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb7502de); | ||
| 3331 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000d21); | ||
| 3332 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a2201d4); | ||
| 3333 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7d9f104); | ||
| 3334 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf804); | ||
| 3335 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03280d19); | ||
| 3336 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3337 | break; | ||
| 3338 | |||
| 3339 | case 5600000: | ||
| 3340 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
| 3341 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fffa); | ||
| 3342 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3ffc9); | ||
| 3343 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc90002); | ||
| 3344 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007500ef); | ||
| 3345 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x010e007e); | ||
| 3346 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3dfdcf); | ||
| 3347 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd16fddd); | ||
| 3348 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440365); | ||
| 3349 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059b0548); | ||
| 3350 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3fc90); | ||
| 3351 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7dff691); | ||
| 3352 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0f014d); | ||
| 3353 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020d23); | ||
| 3354 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0318); | ||
| 3355 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8d7f15a); | ||
| 3356 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f779); | ||
| 3357 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x02bd0cf6); | ||
| 3358 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3359 | break; | ||
| 3360 | |||
| 3361 | case 5700000: | ||
| 3362 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
| 3363 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060001); | ||
| 3364 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffecffc9); | ||
| 3365 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffd4); | ||
| 3366 | cx25840_write4(client, DIF_BPF_COEFF89, 0x004000d5); | ||
| 3367 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013600f0); | ||
| 3368 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd3fe39); | ||
| 3369 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd04fd31); | ||
| 3370 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff360277); | ||
| 3371 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x055605ef); | ||
| 3372 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x033efdfe); | ||
| 3373 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8a5f642); | ||
| 3374 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbffb6); | ||
| 3375 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10cfb); | ||
| 3376 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50456); | ||
| 3377 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9dff1be); | ||
| 3378 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f6f2); | ||
| 3379 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x02520cd2); | ||
| 3380 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3381 | break; | ||
| 3382 | |||
| 3383 | case 5800000: | ||
| 3384 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 3385 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080009); | ||
| 3386 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff8ffd2); | ||
| 3387 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffac); | ||
| 3388 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000200a3); | ||
| 3389 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013c014a); | ||
| 3390 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x006dfec9); | ||
| 3391 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2bfcb7); | ||
| 3392 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe350165); | ||
| 3393 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04cb0651); | ||
| 3394 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477ff7e); | ||
| 3395 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9a5f635); | ||
| 3396 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1fe20); | ||
| 3397 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0ca8); | ||
| 3398 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c81058b); | ||
| 3399 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfaf0f231); | ||
| 3400 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f66d); | ||
| 3401 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x01e60cae); | ||
| 3402 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3403 | break; | ||
| 3404 | |||
| 3405 | case 5900000: | ||
| 3406 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 3407 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000e); | ||
| 3408 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0005ffe1); | ||
| 3409 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacff90); | ||
| 3410 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5005f); | ||
| 3411 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01210184); | ||
| 3412 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fcff72); | ||
| 3413 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd8afc77); | ||
| 3414 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51003f); | ||
| 3415 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04020669); | ||
| 3416 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830103); | ||
| 3417 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfad7f66b); | ||
| 3418 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8fc93); | ||
| 3419 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430c2b); | ||
| 3420 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d06b5); | ||
| 3421 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfc08f2b2); | ||
| 3422 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af5ec); | ||
| 3423 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x017b0c89); | ||
| 3424 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3425 | break; | ||
| 3426 | |||
| 3427 | case 6000000: | ||
| 3428 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 3429 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012); | ||
| 3430 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0012fff5); | ||
| 3431 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaff82); | ||
| 3432 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff8e000f); | ||
| 3433 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e80198); | ||
| 3434 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750028); | ||
| 3435 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe18fc75); | ||
| 3436 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99ff15); | ||
| 3437 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03050636); | ||
| 3438 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0656027f); | ||
| 3439 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc32f6e2); | ||
| 3440 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614fb17); | ||
| 3441 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20b87); | ||
| 3442 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d7707d2); | ||
| 3443 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfd26f341); | ||
| 3444 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf56f); | ||
| 3445 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x010f0c64); | ||
| 3446 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3447 | break; | ||
| 3448 | |||
| 3449 | case 6100000: | ||
| 3450 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
| 3451 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050012); | ||
| 3452 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001c000b); | ||
| 3453 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff84); | ||
| 3454 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ffbe); | ||
| 3455 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00960184); | ||
| 3456 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd00da); | ||
| 3457 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeccfcb2); | ||
| 3458 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fdf9); | ||
| 3459 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x01e005bc); | ||
| 3460 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e703e4); | ||
| 3461 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfdabf798); | ||
| 3462 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f9b3); | ||
| 3463 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510abd); | ||
| 3464 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf08df); | ||
| 3465 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfe48f3dc); | ||
| 3466 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f4f6); | ||
| 3467 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x00a20c3e); | ||
| 3468 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3469 | break; | ||
| 3470 | |||
| 3471 | case 6200000: | ||
| 3472 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 3473 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002000f); | ||
| 3474 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021001f); | ||
| 3475 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff97); | ||
| 3476 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff74); | ||
| 3477 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0034014a); | ||
| 3478 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa0179); | ||
| 3479 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff97fd2a); | ||
| 3480 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fcfa); | ||
| 3481 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00a304fe); | ||
| 3482 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310525); | ||
| 3483 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xff37f886); | ||
| 3484 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf86e); | ||
| 3485 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c709d0); | ||
| 3486 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de209db); | ||
| 3487 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff6df484); | ||
| 3488 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf481); | ||
| 3489 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x00360c18); | ||
| 3490 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3491 | break; | ||
| 3492 | |||
| 3493 | case 6300000: | ||
| 3494 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 3495 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe000a); | ||
| 3496 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021002f); | ||
| 3497 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ffb8); | ||
| 3498 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff3b); | ||
| 3499 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffcc00f0); | ||
| 3500 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa01fa); | ||
| 3501 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0069fdd4); | ||
| 3502 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fc26); | ||
| 3503 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff5d0407); | ||
| 3504 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310638); | ||
| 3505 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x00c9f9a8); | ||
| 3506 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf74e); | ||
| 3507 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff3908c3); | ||
| 3508 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de20ac3); | ||
| 3509 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0093f537); | ||
| 3510 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf410); | ||
| 3511 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xffca0bf2); | ||
| 3512 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3513 | break; | ||
| 3514 | |||
| 3515 | case 6400000: | ||
| 3516 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
| 3517 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb0003); | ||
| 3518 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001c0037); | ||
| 3519 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002fffe2); | ||
| 3520 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ff17); | ||
| 3521 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff6a007e); | ||
| 3522 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd0251); | ||
| 3523 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0134fea5); | ||
| 3524 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb8b); | ||
| 3525 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe2002e0); | ||
| 3526 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e70713); | ||
| 3527 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0255faf5); | ||
| 3528 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f658); | ||
| 3529 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0799); | ||
| 3530 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf0b96); | ||
| 3531 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x01b8f5f5); | ||
| 3532 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f3a3); | ||
| 3533 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xff5e0bca); | ||
| 3534 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3535 | break; | ||
| 3536 | |||
| 3537 | case 6500000: | ||
| 3538 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 3539 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb); | ||
| 3540 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00120037); | ||
| 3541 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00460010); | ||
| 3542 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff8eff0f); | ||
| 3543 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff180000); | ||
| 3544 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750276); | ||
| 3545 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01e8ff8d); | ||
| 3546 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb31); | ||
| 3547 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcfb0198); | ||
| 3548 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x065607ad); | ||
| 3549 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x03cefc64); | ||
| 3550 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614f592); | ||
| 3551 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0656); | ||
| 3552 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d770c52); | ||
| 3553 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x02daf6bd); | ||
| 3554 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf33b); | ||
| 3555 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfef10ba3); | ||
| 3556 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3557 | break; | ||
| 3558 | |||
| 3559 | case 6600000: | ||
| 3560 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 3561 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff5); | ||
| 3562 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0005002f); | ||
| 3563 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054003c); | ||
| 3564 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5ff22); | ||
| 3565 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedfff82); | ||
| 3566 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fc0267); | ||
| 3567 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0276007e); | ||
| 3568 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb1c); | ||
| 3569 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbfe003e); | ||
| 3570 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830802); | ||
| 3571 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0529fdec); | ||
| 3572 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8f4fe); | ||
| 3573 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd04ff); | ||
| 3574 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d0cf6); | ||
| 3575 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x03f8f78f); | ||
| 3576 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af2d7); | ||
| 3577 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe850b7b); | ||
| 3578 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3579 | break; | ||
| 3580 | |||
| 3581 | case 6700000: | ||
| 3582 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
| 3583 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0); | ||
| 3584 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff80020); | ||
| 3585 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00560060); | ||
| 3586 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0002ff4e); | ||
| 3587 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec4ff10); | ||
| 3588 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x006d0225); | ||
| 3589 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02d50166); | ||
| 3590 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb4e); | ||
| 3591 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb35fee1); | ||
| 3592 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477080e); | ||
| 3593 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x065bff82); | ||
| 3594 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1f4a0); | ||
| 3595 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610397); | ||
| 3596 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c810d80); | ||
| 3597 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0510f869); | ||
| 3598 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f278); | ||
| 3599 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe1a0b52); | ||
| 3600 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3601 | break; | ||
| 3602 | |||
| 3603 | case 6800000: | ||
| 3604 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
| 3605 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffaffee); | ||
| 3606 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffec000c); | ||
| 3607 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0078); | ||
| 3608 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0040ff8e); | ||
| 3609 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecafeb6); | ||
| 3610 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd301b6); | ||
| 3611 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fc0235); | ||
| 3612 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fbc5); | ||
| 3613 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaaafd90); | ||
| 3614 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x033e07d2); | ||
| 3615 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x075b011b); | ||
| 3616 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbf47a); | ||
| 3617 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f0224); | ||
| 3618 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50def); | ||
| 3619 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0621f94b); | ||
| 3620 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f21e); | ||
| 3621 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfdae0b29); | ||
| 3622 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3623 | break; | ||
| 3624 | |||
| 3625 | case 6900000: | ||
| 3626 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 3627 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffef); | ||
| 3628 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3fff6); | ||
| 3629 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037007f); | ||
| 3630 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0075ffdc); | ||
| 3631 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef2fe7c); | ||
| 3632 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3d0122); | ||
| 3633 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02ea02dd); | ||
| 3634 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fc79); | ||
| 3635 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa65fc5d); | ||
| 3636 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3074e); | ||
| 3637 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x082102ad); | ||
| 3638 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0ff48c); | ||
| 3639 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe00a9); | ||
| 3640 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0e43); | ||
| 3641 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0729fa33); | ||
| 3642 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f1c9); | ||
| 3643 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfd430b00); | ||
| 3644 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3645 | break; | ||
| 3646 | |||
| 3647 | case 7000000: | ||
| 3648 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 3649 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0001fff3); | ||
| 3650 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe2); | ||
| 3651 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001b0076); | ||
| 3652 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009c002d); | ||
| 3653 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff35fe68); | ||
| 3654 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfeba0076); | ||
| 3655 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x029f0352); | ||
| 3656 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfd60); | ||
| 3657 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa69fb53); | ||
| 3658 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00740688); | ||
| 3659 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08a7042d); | ||
| 3660 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb75f4d6); | ||
| 3661 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600ff2d); | ||
| 3662 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a220e7a); | ||
| 3663 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0827fb22); | ||
| 3664 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf17a); | ||
| 3665 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfcd80ad6); | ||
| 3666 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3667 | break; | ||
| 3668 | |||
| 3669 | case 7100000: | ||
| 3670 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 3671 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff9); | ||
| 3672 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffd2); | ||
| 3673 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb005e); | ||
| 3674 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b0007a); | ||
| 3675 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8ffe7c); | ||
| 3676 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53ffc1); | ||
| 3677 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0221038c); | ||
| 3678 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fe6e); | ||
| 3679 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfab6fa80); | ||
| 3680 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff010587); | ||
| 3681 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e90590); | ||
| 3682 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf5f556); | ||
| 3683 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfdb3); | ||
| 3684 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09210e95); | ||
| 3685 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0919fc15); | ||
| 3686 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff12f); | ||
| 3687 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc6e0aab); | ||
| 3688 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3689 | break; | ||
| 3690 | |||
| 3691 | case 7200000: | ||
| 3692 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 3693 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070000); | ||
| 3694 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6ffc9); | ||
| 3695 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0039); | ||
| 3696 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00af00b8); | ||
| 3697 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfff4feb6); | ||
| 3698 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13ff10); | ||
| 3699 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01790388); | ||
| 3700 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311ff92); | ||
| 3701 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb48f9ed); | ||
| 3702 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd980453); | ||
| 3703 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e306cd); | ||
| 3704 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe88f60a); | ||
| 3705 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fc40); | ||
| 3706 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x08080e93); | ||
| 3707 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09fdfd0c); | ||
| 3708 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af0ea); | ||
| 3709 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc050a81); | ||
| 3710 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3711 | break; | ||
| 3712 | |||
| 3713 | case 7300000: | ||
| 3714 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 3715 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080008); | ||
| 3716 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff0ffc9); | ||
| 3717 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1000d); | ||
| 3718 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009800e2); | ||
| 3719 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x005bff10); | ||
| 3720 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe74); | ||
| 3721 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00b50345); | ||
| 3722 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000bc); | ||
| 3723 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc18f9a1); | ||
| 3724 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc4802f9); | ||
| 3725 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x089807dc); | ||
| 3726 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022f6f0); | ||
| 3727 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fada); | ||
| 3728 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x06da0e74); | ||
| 3729 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ad3fe06); | ||
| 3730 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef0ab); | ||
| 3731 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb9c0a55); | ||
| 3732 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3733 | break; | ||
| 3734 | |||
| 3735 | case 7400000: | ||
| 3736 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
| 3737 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000e); | ||
| 3738 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffdffd0); | ||
| 3739 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffdf); | ||
| 3740 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006e00f2); | ||
| 3741 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00b8ff82); | ||
| 3742 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfdf8); | ||
| 3743 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffe302c8); | ||
| 3744 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x041301dc); | ||
| 3745 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd1af99e); | ||
| 3746 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1e0183); | ||
| 3747 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x080908b5); | ||
| 3748 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bcf801); | ||
| 3749 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf985); | ||
| 3750 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x059a0e38); | ||
| 3751 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b99ff03); | ||
| 3752 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cf071); | ||
| 3753 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb330a2a); | ||
| 3754 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3755 | break; | ||
| 3756 | |||
| 3757 | case 7500000: | ||
| 3758 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
| 3759 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070011); | ||
| 3760 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000affdf); | ||
| 3761 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffa9ffb5); | ||
| 3762 | cx25840_write4(client, DIF_BPF_COEFF89, 0x003700e6); | ||
| 3763 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01010000); | ||
| 3764 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62fda8); | ||
| 3765 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff140219); | ||
| 3766 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x043502e1); | ||
| 3767 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe42f9e6); | ||
| 3768 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa270000); | ||
| 3769 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x073a0953); | ||
| 3770 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x034cf939); | ||
| 3771 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a4f845); | ||
| 3772 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x044c0de1); | ||
| 3773 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c4f0000); | ||
| 3774 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2f03c); | ||
| 3775 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfacc09fe); | ||
| 3776 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3777 | break; | ||
| 3778 | |||
| 3779 | case 7600000: | ||
| 3780 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 3781 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00040012); | ||
| 3782 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0016fff3); | ||
| 3783 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafff95); | ||
| 3784 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff900c0); | ||
| 3785 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0130007e); | ||
| 3786 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefd89); | ||
| 3787 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe560146); | ||
| 3788 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x041303bc); | ||
| 3789 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff81fa76); | ||
| 3790 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cfe7d); | ||
| 3791 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x063209b1); | ||
| 3792 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c9fa93); | ||
| 3793 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf71e); | ||
| 3794 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f30d6e); | ||
| 3795 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cf200fd); | ||
| 3796 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361f00e); | ||
| 3797 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa6509d1); | ||
| 3798 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3799 | break; | ||
| 3800 | |||
| 3801 | case 7700000: | ||
| 3802 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 3803 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00010010); | ||
| 3804 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0008); | ||
| 3805 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ff84); | ||
| 3806 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffbc0084); | ||
| 3807 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013e00f0); | ||
| 3808 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff56fd9f); | ||
| 3809 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdb8005c); | ||
| 3810 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00460); | ||
| 3811 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00c7fb45); | ||
| 3812 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4fd07); | ||
| 3813 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04fa09ce); | ||
| 3814 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x062afc07); | ||
| 3815 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407f614); | ||
| 3816 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x01920ce0); | ||
| 3817 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d8301fa); | ||
| 3818 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8efe5); | ||
| 3819 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa0009a4); | ||
| 3820 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3821 | break; | ||
| 3822 | |||
| 3823 | case 7800000: | ||
| 3824 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 3825 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd000b); | ||
| 3826 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001d); | ||
| 3827 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff82); | ||
| 3828 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff870039); | ||
| 3829 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x012a014a); | ||
| 3830 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffedfde7); | ||
| 3831 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd47ff6b); | ||
| 3832 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104c6); | ||
| 3833 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0202fc4c); | ||
| 3834 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6fbad); | ||
| 3835 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x039909a7); | ||
| 3836 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0767fd8e); | ||
| 3837 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482f52b); | ||
| 3838 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x002d0c39); | ||
| 3839 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e0002f4); | ||
| 3840 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477efc2); | ||
| 3841 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf99b0977); | ||
| 3842 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3843 | break; | ||
| 3844 | |||
| 3845 | case 7900000: | ||
| 3846 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 3847 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa0004); | ||
| 3848 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0020002d); | ||
| 3849 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff91); | ||
| 3850 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ffe8); | ||
| 3851 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f70184); | ||
| 3852 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0086fe5c); | ||
| 3853 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0bfe85); | ||
| 3854 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104e5); | ||
| 3855 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0323fd7d); | ||
| 3856 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa79); | ||
| 3857 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x021d093f); | ||
| 3858 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0879ff22); | ||
| 3859 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bf465); | ||
| 3860 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec70b79); | ||
| 3861 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e6803eb); | ||
| 3862 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50defa5); | ||
| 3863 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf937094a); | ||
| 3864 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3865 | break; | ||
| 3866 | |||
| 3867 | case 8000000: | ||
| 3868 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 3869 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffd); | ||
| 3870 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00190036); | ||
| 3871 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bffaf); | ||
| 3872 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff99); | ||
| 3873 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00aa0198); | ||
| 3874 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112fef3); | ||
| 3875 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd09fdb9); | ||
| 3876 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04be); | ||
| 3877 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x041bfecc); | ||
| 3878 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947f978); | ||
| 3879 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x00900897); | ||
| 3880 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a00b9); | ||
| 3881 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f3c5); | ||
| 3882 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd650aa3); | ||
| 3883 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ebc04de); | ||
| 3884 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aaef8e); | ||
| 3885 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf8d5091c); | ||
| 3886 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3887 | break; | ||
| 3888 | |||
| 3889 | case 8100000: | ||
| 3890 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
| 3891 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff6); | ||
| 3892 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000e0038); | ||
| 3893 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ffd7); | ||
| 3894 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff56); | ||
| 3895 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x004b0184); | ||
| 3896 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0186ffa1); | ||
| 3897 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd40fd16); | ||
| 3898 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440452); | ||
| 3899 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04de0029); | ||
| 3900 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2f8b2); | ||
| 3901 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfefe07b5); | ||
| 3902 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a05024d); | ||
| 3903 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef34d); | ||
| 3904 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0a09b8); | ||
| 3905 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0efa05cd); | ||
| 3906 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64eef7d); | ||
| 3907 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf87308ed); | ||
| 3908 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3909 | break; | ||
| 3910 | |||
| 3911 | case 8200000: | ||
| 3912 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
| 3913 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0); | ||
| 3914 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00000031); | ||
| 3915 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0005); | ||
| 3916 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff27); | ||
| 3917 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffe4014a); | ||
| 3918 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70057); | ||
| 3919 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdacfca6); | ||
| 3920 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3603a7); | ||
| 3921 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05610184); | ||
| 3922 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbf82e); | ||
| 3923 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd74069f); | ||
| 3924 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a7503d6); | ||
| 3925 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff2ff); | ||
| 3926 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab808b9); | ||
| 3927 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f2306b5); | ||
| 3928 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ef72); | ||
| 3929 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf81308bf); | ||
| 3930 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3931 | break; | ||
| 3932 | |||
| 3933 | case 8300000: | ||
| 3934 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 3935 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbffee); | ||
| 3936 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff30022); | ||
| 3937 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00560032); | ||
| 3938 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ff10); | ||
| 3939 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8000f0); | ||
| 3940 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe0106); | ||
| 3941 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe46fc71); | ||
| 3942 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3502c7); | ||
| 3943 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059e02ce); | ||
| 3944 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9f7f2); | ||
| 3945 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfbff055b); | ||
| 3946 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa9054c); | ||
| 3947 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f2db); | ||
| 3948 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf97507aa); | ||
| 3949 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f350797); | ||
| 3950 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ef6d); | ||
| 3951 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7b40890); | ||
| 3952 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3953 | break; | ||
| 3954 | |||
| 3955 | case 8400000: | ||
| 3956 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 3957 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffee); | ||
| 3958 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8000f); | ||
| 3959 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00540058); | ||
| 3960 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffcdff14); | ||
| 3961 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff29007e); | ||
| 3962 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f6019e); | ||
| 3963 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff01fc7c); | ||
| 3964 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5101bf); | ||
| 3965 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059203f6); | ||
| 3966 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd41f7fe); | ||
| 3967 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfaa903f3); | ||
| 3968 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e06a9); | ||
| 3969 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf2e2); | ||
| 3970 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842068b); | ||
| 3971 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f320871); | ||
| 3972 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85eef6e); | ||
| 3973 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7560860); | ||
| 3974 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3975 | break; | ||
| 3976 | |||
| 3977 | case 8500000: | ||
| 3978 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 3979 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fff2); | ||
| 3980 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1fff9); | ||
| 3981 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00460073); | ||
| 3982 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000bff34); | ||
| 3983 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee90000); | ||
| 3984 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10215); | ||
| 3985 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffd0fcc5); | ||
| 3986 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99009d); | ||
| 3987 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x053d04f1); | ||
| 3988 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5f853); | ||
| 3989 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf97d0270); | ||
| 3990 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a5607e4); | ||
| 3991 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef314); | ||
| 3992 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723055f); | ||
| 3993 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f180943); | ||
| 3994 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919ef75); | ||
| 3995 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6fa0830); | ||
| 3996 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 3997 | break; | ||
| 3998 | |||
| 3999 | case 8600000: | ||
| 4000 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4001 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff8); | ||
| 4002 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe4); | ||
| 4003 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f007f); | ||
| 4004 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0048ff6b); | ||
| 4005 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec7ff82); | ||
| 4006 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0163025f); | ||
| 4007 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00a2fd47); | ||
| 4008 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff73); | ||
| 4009 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04a405b2); | ||
| 4010 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0017f8ed); | ||
| 4011 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf88500dc); | ||
| 4012 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d208f9); | ||
| 4013 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff370); | ||
| 4014 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61c0429); | ||
| 4015 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ee80a0b); | ||
| 4016 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d8ef82); | ||
| 4017 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6a00800); | ||
| 4018 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4019 | break; | ||
| 4020 | |||
| 4021 | case 8700000: | ||
| 4022 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4023 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007ffff); | ||
| 4024 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffd4); | ||
| 4025 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010007a); | ||
| 4026 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007cffb2); | ||
| 4027 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec6ff10); | ||
| 4028 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e60277); | ||
| 4029 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0168fdf9); | ||
| 4030 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fe50); | ||
| 4031 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03ce0631); | ||
| 4032 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0188f9c8); | ||
| 4033 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7c7ff43); | ||
| 4034 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x091509e3); | ||
| 4035 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f3f6); | ||
| 4036 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52d02ea); | ||
| 4037 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ea30ac9); | ||
| 4038 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9bef95); | ||
| 4039 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf64607d0); | ||
| 4040 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4041 | break; | ||
| 4042 | |||
| 4043 | case 8800000: | ||
| 4044 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 4045 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00090007); | ||
| 4046 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9ffca); | ||
| 4047 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00065); | ||
| 4048 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a10003); | ||
| 4049 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee6feb6); | ||
| 4050 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053025b); | ||
| 4051 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0213fed0); | ||
| 4052 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fd46); | ||
| 4053 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02c70668); | ||
| 4054 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x02eafadb); | ||
| 4055 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf74bfdae); | ||
| 4056 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230a9c); | ||
| 4057 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f4a3); | ||
| 4058 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45b01a6); | ||
| 4059 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e480b7c); | ||
| 4060 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb61efae); | ||
| 4061 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf5ef079f); | ||
| 4062 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4063 | break; | ||
| 4064 | |||
| 4065 | case 8900000: | ||
| 4066 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
| 4067 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000d); | ||
| 4068 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff5ffc8); | ||
| 4069 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10043); | ||
| 4070 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b20053); | ||
| 4071 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff24fe7c); | ||
| 4072 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9020c); | ||
| 4073 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0295ffbb); | ||
| 4074 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fc64); | ||
| 4075 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x019b0654); | ||
| 4076 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x042dfc1c); | ||
| 4077 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf714fc2a); | ||
| 4078 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020b21); | ||
| 4079 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f575); | ||
| 4080 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7005e); | ||
| 4081 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0dd80c24); | ||
| 4082 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2aefcd); | ||
| 4083 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf599076e); | ||
| 4084 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4085 | break; | ||
| 4086 | |||
| 4087 | case 9000000: | ||
| 4088 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 4089 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060011); | ||
| 4090 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0002ffcf); | ||
| 4091 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffba0018); | ||
| 4092 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad009a); | ||
| 4093 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff79fe68); | ||
| 4094 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff260192); | ||
| 4095 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e500ab); | ||
| 4096 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fbb6); | ||
| 4097 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x005b05f7); | ||
| 4098 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545fd81); | ||
| 4099 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf723fabf); | ||
| 4100 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80b70); | ||
| 4101 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f669); | ||
| 4102 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313ff15); | ||
| 4103 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d550cbf); | ||
| 4104 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6eff2); | ||
| 4105 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544073d); | ||
| 4106 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4107 | break; | ||
| 4108 | |||
| 4109 | case 9100000: | ||
| 4110 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 4111 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00030012); | ||
| 4112 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000fffdd); | ||
| 4113 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffea); | ||
| 4114 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009300cf); | ||
| 4115 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdcfe7c); | ||
| 4116 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea600f7); | ||
| 4117 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fd0190); | ||
| 4118 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb46); | ||
| 4119 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff150554); | ||
| 4120 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0627fefd); | ||
| 4121 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf778f978); | ||
| 4122 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044d0b87); | ||
| 4123 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f77d); | ||
| 4124 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0fdcf); | ||
| 4125 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbe0d4e); | ||
| 4126 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc4f01d); | ||
| 4127 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2070b); | ||
| 4128 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4129 | break; | ||
| 4130 | |||
| 4131 | case 9200000: | ||
| 4132 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4133 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000010); | ||
| 4134 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001afff0); | ||
| 4135 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffbf); | ||
| 4136 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006700ed); | ||
| 4137 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043feb6); | ||
| 4138 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe460047); | ||
| 4139 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02db0258); | ||
| 4140 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb1b); | ||
| 4141 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddc0473); | ||
| 4142 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c90082); | ||
| 4143 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf811f85e); | ||
| 4144 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c90b66); | ||
| 4145 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff8ad); | ||
| 4146 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250fc8d); | ||
| 4147 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c140dcf); | ||
| 4148 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe93f04d); | ||
| 4149 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a106d9); | ||
| 4150 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4151 | break; | ||
| 4152 | |||
| 4153 | case 9300000: | ||
| 4154 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4155 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc000c); | ||
| 4156 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200006); | ||
| 4157 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff9c); | ||
| 4158 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002f00ef); | ||
| 4159 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a4ff10); | ||
| 4160 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dff92); | ||
| 4161 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x028102f7); | ||
| 4162 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb37); | ||
| 4163 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbf035e); | ||
| 4164 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07260202); | ||
| 4165 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e8f778); | ||
| 4166 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01340b0d); | ||
| 4167 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f9f4); | ||
| 4168 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223fb51); | ||
| 4169 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b590e42); | ||
| 4170 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff64f083); | ||
| 4171 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf45206a7); | ||
| 4172 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4173 | break; | ||
| 4174 | |||
| 4175 | case 9400000: | ||
| 4176 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4177 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90005); | ||
| 4178 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001a); | ||
| 4179 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff86); | ||
| 4180 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff000d7); | ||
| 4181 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2ff82); | ||
| 4182 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fee5); | ||
| 4183 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f60362); | ||
| 4184 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb99); | ||
| 4185 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbcc0222); | ||
| 4186 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07380370); | ||
| 4187 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f7f6cc); | ||
| 4188 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff990a7e); | ||
| 4189 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902fb50); | ||
| 4190 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21afa1f); | ||
| 4191 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8d0ea6); | ||
| 4192 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034f0bf); | ||
| 4193 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4050675); | ||
| 4194 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4195 | break; | ||
| 4196 | |||
| 4197 | case 9500000: | ||
| 4198 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 4199 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffe); | ||
| 4200 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e002b); | ||
| 4201 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff81); | ||
| 4202 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb400a5); | ||
| 4203 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000); | ||
| 4204 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe50); | ||
| 4205 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01460390); | ||
| 4206 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfc3a); | ||
| 4207 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb1000ce); | ||
| 4208 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x070104bf); | ||
| 4209 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb37f65f); | ||
| 4210 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe0009bc); | ||
| 4211 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00fcbb); | ||
| 4212 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f8f8); | ||
| 4213 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b20efc); | ||
| 4214 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105f101); | ||
| 4215 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3ba0642); | ||
| 4216 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4217 | break; | ||
| 4218 | |||
| 4219 | case 9600000: | ||
| 4220 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
| 4221 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff7); | ||
| 4222 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00150036); | ||
| 4223 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff8c); | ||
| 4224 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff810061); | ||
| 4225 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013d007e); | ||
| 4226 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe71fddf); | ||
| 4227 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x007c0380); | ||
| 4228 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fd13); | ||
| 4229 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa94ff70); | ||
| 4230 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x068005e2); | ||
| 4231 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9bf633); | ||
| 4232 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc7308ca); | ||
| 4233 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5fe30); | ||
| 4234 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf274f7e0); | ||
| 4235 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c90f43); | ||
| 4236 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d4f147); | ||
| 4237 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371060f); | ||
| 4238 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4239 | break; | ||
| 4240 | |||
| 4241 | case 9700000: | ||
| 4242 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 4243 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fff1); | ||
| 4244 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00090038); | ||
| 4245 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffa7); | ||
| 4246 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5e0012); | ||
| 4247 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013200f0); | ||
| 4248 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee3fd9b); | ||
| 4249 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaa0331); | ||
| 4250 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fe15); | ||
| 4251 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa60fe18); | ||
| 4252 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bd06d1); | ||
| 4253 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1bf64a); | ||
| 4254 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafa07ae); | ||
| 4255 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7effab); | ||
| 4256 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d5f6d7); | ||
| 4257 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d30f7a); | ||
| 4258 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a3f194); | ||
| 4259 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf32905dc); | ||
| 4260 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4261 | break; | ||
| 4262 | |||
| 4263 | case 9800000: | ||
| 4264 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 4265 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffee); | ||
| 4266 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffb0032); | ||
| 4267 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003fffcd); | ||
| 4268 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effc1); | ||
| 4269 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106014a); | ||
| 4270 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6efd8a); | ||
| 4271 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfedd02aa); | ||
| 4272 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0ff34); | ||
| 4273 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa74fcd7); | ||
| 4274 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bf0781); | ||
| 4275 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaaf6a3); | ||
| 4276 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99e066b); | ||
| 4277 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90128); | ||
| 4278 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf359f5e1); | ||
| 4279 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d20fa2); | ||
| 4280 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0370f1e5); | ||
| 4281 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e405a8); | ||
| 4282 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4283 | break; | ||
| 4284 | |||
| 4285 | case 9900000: | ||
| 4286 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4287 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffee); | ||
| 4288 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffef0024); | ||
| 4289 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051fffa); | ||
| 4290 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff54ff77); | ||
| 4291 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00be0184); | ||
| 4292 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0006fdad); | ||
| 4293 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe2701f3); | ||
| 4294 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413005e); | ||
| 4295 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad1fbba); | ||
| 4296 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x039007ee); | ||
| 4297 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x013bf73d); | ||
| 4298 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868050a); | ||
| 4299 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4302a1); | ||
| 4300 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fdf4fe); | ||
| 4301 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c70fba); | ||
| 4302 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x043bf23c); | ||
| 4303 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a10575); | ||
| 4304 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4305 | break; | ||
| 4306 | |||
| 4307 | case 10000000: | ||
| 4308 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4309 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fff1); | ||
| 4310 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe50011); | ||
| 4311 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00570027); | ||
| 4312 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff70ff3c); | ||
| 4313 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00620198); | ||
| 4314 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x009efe01); | ||
| 4315 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95011a); | ||
| 4316 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350183); | ||
| 4317 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb71fad0); | ||
| 4318 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x023c0812); | ||
| 4319 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c3f811); | ||
| 4320 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75e0390); | ||
| 4321 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0411); | ||
| 4322 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c1f432); | ||
| 4323 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b30fc1); | ||
| 4324 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0503f297); | ||
| 4325 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2610541); | ||
| 4326 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4327 | break; | ||
| 4328 | |||
| 4329 | case 10100000: | ||
| 4330 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4331 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0006fff7); | ||
| 4332 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdffffc); | ||
| 4333 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510050); | ||
| 4334 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff9dff18); | ||
| 4335 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffc0184); | ||
| 4336 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0128fe80); | ||
| 4337 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32002e); | ||
| 4338 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130292); | ||
| 4339 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4dfa21); | ||
| 4340 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d107ee); | ||
| 4341 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0435f91c); | ||
| 4342 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6850205); | ||
| 4343 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430573); | ||
| 4344 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a1f37d); | ||
| 4345 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x03990fba); | ||
| 4346 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c7f2f8); | ||
| 4347 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222050d); | ||
| 4348 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4349 | break; | ||
| 4350 | |||
| 4351 | case 10200000: | ||
| 4352 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 4353 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffe); | ||
| 4354 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdfffe7); | ||
| 4355 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f006e); | ||
| 4356 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffd6ff0f); | ||
| 4357 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96014a); | ||
| 4358 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0197ff1f); | ||
| 4359 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd05ff3e); | ||
| 4360 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0037c); | ||
| 4361 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd59f9b7); | ||
| 4362 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5d0781); | ||
| 4363 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0585fa56); | ||
| 4364 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4006f); | ||
| 4365 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf906c4); | ||
| 4366 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69df2e0); | ||
| 4367 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x02790fa2); | ||
| 4368 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0688f35d); | ||
| 4369 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e604d8); | ||
| 4370 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4371 | break; | ||
| 4372 | |||
| 4373 | case 10300000: | ||
| 4374 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
| 4375 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00090005); | ||
| 4376 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4ffd6); | ||
| 4377 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025007e); | ||
| 4378 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0014ff20); | ||
| 4379 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3c00f0); | ||
| 4380 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e1ffd0); | ||
| 4381 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd12fe5c); | ||
| 4382 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110433); | ||
| 4383 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88f996); | ||
| 4384 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf106d1); | ||
| 4385 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aafbb7); | ||
| 4386 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57efed8); | ||
| 4387 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e07ff); | ||
| 4388 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b0f25e); | ||
| 4389 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x01560f7a); | ||
| 4390 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0745f3c7); | ||
| 4391 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1ac04a4); | ||
| 4392 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4393 | break; | ||
| 4394 | |||
| 4395 | case 10400000: | ||
| 4396 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 4397 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000c); | ||
| 4398 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffedffcb); | ||
| 4399 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005007d); | ||
| 4400 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0050ff4c); | ||
| 4401 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6007e); | ||
| 4402 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ff0086); | ||
| 4403 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd58fd97); | ||
| 4404 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104ad); | ||
| 4405 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffcaf9c0); | ||
| 4406 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc9905e2); | ||
| 4407 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x079afd35); | ||
| 4408 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf555fd46); | ||
| 4409 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50920); | ||
| 4410 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d9f1f6); | ||
| 4411 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x00310f43); | ||
| 4412 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fdf435); | ||
| 4413 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174046f); | ||
| 4414 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4415 | break; | ||
| 4416 | |||
| 4417 | case 10500000: | ||
| 4418 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
| 4419 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050011); | ||
| 4420 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffaffc8); | ||
| 4421 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5006b); | ||
| 4422 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0082ff8c); | ||
| 4423 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000); | ||
| 4424 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f00130); | ||
| 4425 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd2fcfc); | ||
| 4426 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04e3); | ||
| 4427 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x010efa32); | ||
| 4428 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb6404bf); | ||
| 4429 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x084efec5); | ||
| 4430 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569fbc2); | ||
| 4431 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000a23); | ||
| 4432 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa15f1ab); | ||
| 4433 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0b0efc); | ||
| 4434 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b0f4a7); | ||
| 4435 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13f043a); | ||
| 4436 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4437 | break; | ||
| 4438 | |||
| 4439 | case 10600000: | ||
| 4440 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4441 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00020012); | ||
| 4442 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0007ffcd); | ||
| 4443 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9004c); | ||
| 4444 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a4ffd9); | ||
| 4445 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3ff82); | ||
| 4446 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b401c1); | ||
| 4447 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe76fc97); | ||
| 4448 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404d2); | ||
| 4449 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0245fae8); | ||
| 4450 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5f0370); | ||
| 4451 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1005f); | ||
| 4452 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bcfa52); | ||
| 4453 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020b04); | ||
| 4454 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb60f17b); | ||
| 4455 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde70ea6); | ||
| 4456 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x095df51e); | ||
| 4457 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10c0405); | ||
| 4458 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4459 | break; | ||
| 4460 | |||
| 4461 | case 10700000: | ||
| 4462 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4463 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0011); | ||
| 4464 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0014ffdb); | ||
| 4465 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40023); | ||
| 4466 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2002a); | ||
| 4467 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedbff10); | ||
| 4468 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150022d); | ||
| 4469 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff38fc6f); | ||
| 4470 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36047b); | ||
| 4471 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x035efbda); | ||
| 4472 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9940202); | ||
| 4473 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ee01f5); | ||
| 4474 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf649f8fe); | ||
| 4475 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10bc2); | ||
| 4476 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb6f169); | ||
| 4477 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc60e42); | ||
| 4478 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a04f599); | ||
| 4479 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0db03d0); | ||
| 4480 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4481 | break; | ||
| 4482 | |||
| 4483 | case 10800000: | ||
| 4484 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4485 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb000d); | ||
| 4486 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001dffed); | ||
| 4487 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaafff5); | ||
| 4488 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00aa0077); | ||
| 4489 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13feb6); | ||
| 4490 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00ce026b); | ||
| 4491 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x000afc85); | ||
| 4492 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3503e3); | ||
| 4493 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x044cfcfb); | ||
| 4494 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90c0082); | ||
| 4495 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5037f); | ||
| 4496 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf710f7cc); | ||
| 4497 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0c59); | ||
| 4498 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe16f173); | ||
| 4499 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaa0dcf); | ||
| 4500 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa5f617); | ||
| 4501 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0ad039b); | ||
| 4502 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4503 | break; | ||
| 4504 | |||
| 4505 | case 10900000: | ||
| 4506 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 4507 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90006); | ||
| 4508 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00210003); | ||
| 4509 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffc8); | ||
| 4510 | cx25840_write4(client, DIF_BPF_COEFF89, 0x008e00b6); | ||
| 4511 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff63fe7c); | ||
| 4512 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x003a0275); | ||
| 4513 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00dafcda); | ||
| 4514 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd510313); | ||
| 4515 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0501fe40); | ||
| 4516 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cbfefd); | ||
| 4517 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x087604f0); | ||
| 4518 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80af6c2); | ||
| 4519 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430cc8); | ||
| 4520 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7af19a); | ||
| 4521 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa940d4e); | ||
| 4522 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3ff699); | ||
| 4523 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0810365); | ||
| 4524 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4525 | break; | ||
| 4526 | |||
| 4527 | case 11000000: | ||
| 4528 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
| 4529 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffff); | ||
| 4530 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00210018); | ||
| 4531 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffa3); | ||
| 4532 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006000e1); | ||
| 4533 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc4fe68); | ||
| 4534 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0024b); | ||
| 4535 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x019afd66); | ||
| 4536 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc990216); | ||
| 4537 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0575ff99); | ||
| 4538 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4fd81); | ||
| 4539 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d40640); | ||
| 4540 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf932f5e6); | ||
| 4541 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20d0d); | ||
| 4542 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x00dff1de); | ||
| 4543 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9860cbf); | ||
| 4544 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd1f71e); | ||
| 4545 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058032f); | ||
| 4546 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4547 | break; | ||
| 4548 | |||
| 4549 | case 11100000: | ||
| 4550 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
| 4551 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff8); | ||
| 4552 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001b0029); | ||
| 4553 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff8a); | ||
| 4554 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002600f2); | ||
| 4555 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x002cfe7c); | ||
| 4556 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0f01f0); | ||
| 4557 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x023bfe20); | ||
| 4558 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc1700fa); | ||
| 4559 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a200f7); | ||
| 4560 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf927fc1c); | ||
| 4561 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f40765); | ||
| 4562 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa82f53b); | ||
| 4563 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510d27); | ||
| 4564 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0243f23d); | ||
| 4565 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8810c24); | ||
| 4566 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5cf7a7); | ||
| 4567 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf03102fa); | ||
| 4568 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4569 | break; | ||
| 4570 | |||
| 4571 | case 11200000: | ||
| 4572 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
| 4573 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2); | ||
| 4574 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00110035); | ||
| 4575 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff81); | ||
| 4576 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffe700e7); | ||
| 4577 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x008ffeb6); | ||
| 4578 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94016d); | ||
| 4579 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b0fefb); | ||
| 4580 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3ffd1); | ||
| 4581 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05850249); | ||
| 4582 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c1fadb); | ||
| 4583 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x05de0858); | ||
| 4584 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf2f4c4); | ||
| 4585 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c70d17); | ||
| 4586 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a0f2b8); | ||
| 4587 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7870b7c); | ||
| 4588 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdff833); | ||
| 4589 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00d02c4); | ||
| 4590 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4591 | break; | ||
| 4592 | |||
| 4593 | case 11300000: | ||
| 4594 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4595 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffee); | ||
| 4596 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00040038); | ||
| 4597 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ff88); | ||
| 4598 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffac00c2); | ||
| 4599 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e2ff10); | ||
| 4600 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe3900cb); | ||
| 4601 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f1ffe9); | ||
| 4602 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3feaa); | ||
| 4603 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05210381); | ||
| 4604 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9cf9c8); | ||
| 4605 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04990912); | ||
| 4606 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7af484); | ||
| 4607 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff390cdb); | ||
| 4608 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f4f34d); | ||
| 4609 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69a0ac9); | ||
| 4610 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5af8c1); | ||
| 4611 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefec028e); | ||
| 4612 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4613 | break; | ||
| 4614 | |||
| 4615 | case 11400000: | ||
| 4616 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4617 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0000ffee); | ||
| 4618 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff60033); | ||
| 4619 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002fff9f); | ||
| 4620 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7b0087); | ||
| 4621 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011eff82); | ||
| 4622 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe080018); | ||
| 4623 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f900d8); | ||
| 4624 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fd96); | ||
| 4625 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04790490); | ||
| 4626 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbadf8ed); | ||
| 4627 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x032f098e); | ||
| 4628 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff10f47d); | ||
| 4629 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0c75); | ||
| 4630 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x063cf3fc); | ||
| 4631 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5ba0a0b); | ||
| 4632 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dccf952); | ||
| 4633 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcd0258); | ||
| 4634 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4635 | break; | ||
| 4636 | |||
| 4637 | case 11500000: | ||
| 4638 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4639 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff1); | ||
| 4640 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffea0026); | ||
| 4641 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046ffc3); | ||
| 4642 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5a003c); | ||
| 4643 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000); | ||
| 4644 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04ff63); | ||
| 4645 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c801b8); | ||
| 4646 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fca6); | ||
| 4647 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397056a); | ||
| 4648 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcecf853); | ||
| 4649 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x01ad09c9); | ||
| 4650 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x00acf4ad); | ||
| 4651 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0be7); | ||
| 4652 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0773f4c2); | ||
| 4653 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e90943); | ||
| 4654 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35f9e6); | ||
| 4655 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb10221); | ||
| 4656 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4657 | break; | ||
| 4658 | |||
| 4659 | case 11600000: | ||
| 4660 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 4661 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff6); | ||
| 4662 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe20014); | ||
| 4663 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054ffee); | ||
| 4664 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effeb); | ||
| 4665 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137007e); | ||
| 4666 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2efebb); | ||
| 4667 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260027a); | ||
| 4668 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fbe6); | ||
| 4669 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02870605); | ||
| 4670 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4af7fe); | ||
| 4671 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x001d09c1); | ||
| 4672 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0243f515); | ||
| 4673 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd0b32); | ||
| 4674 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0897f59e); | ||
| 4675 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4280871); | ||
| 4676 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e95fa7c); | ||
| 4677 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef9701eb); | ||
| 4678 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4679 | break; | ||
| 4680 | |||
| 4681 | case 11700000: | ||
| 4682 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
| 4683 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffd); | ||
| 4684 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffff); | ||
| 4685 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056001d); | ||
| 4686 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff57ff9c); | ||
| 4687 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011300f0); | ||
| 4688 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe82fe2e); | ||
| 4689 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ca0310); | ||
| 4690 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb62); | ||
| 4691 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155065a); | ||
| 4692 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xffbaf7f2); | ||
| 4693 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8c0977); | ||
| 4694 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x03cef5b2); | ||
| 4695 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610a58); | ||
| 4696 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a5f68f); | ||
| 4697 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3790797); | ||
| 4698 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eebfb14); | ||
| 4699 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef8001b5); | ||
| 4700 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4701 | break; | ||
| 4702 | |||
| 4703 | case 11800000: | ||
| 4704 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
| 4705 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080004); | ||
| 4706 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe9); | ||
| 4707 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0047); | ||
| 4708 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff75ff58); | ||
| 4709 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1014a); | ||
| 4710 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef9fdc8); | ||
| 4711 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111036f); | ||
| 4712 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb21); | ||
| 4713 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00120665); | ||
| 4714 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x012df82e); | ||
| 4715 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd0708ec); | ||
| 4716 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542f682); | ||
| 4717 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f095c); | ||
| 4718 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9af792); | ||
| 4719 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2db06b5); | ||
| 4720 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f38fbad); | ||
| 4721 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6c017e); | ||
| 4722 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4723 | break; | ||
| 4724 | |||
| 4725 | case 11900000: | ||
| 4726 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 4727 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000b); | ||
| 4728 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe7ffd8); | ||
| 4729 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00370068); | ||
| 4730 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffa4ff28); | ||
| 4731 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00790184); | ||
| 4732 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87fd91); | ||
| 4733 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00430392); | ||
| 4734 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb26); | ||
| 4735 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfece0626); | ||
| 4736 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294f8b2); | ||
| 4737 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb990825); | ||
| 4738 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0698f77f); | ||
| 4739 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe0842); | ||
| 4740 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b73f8a7); | ||
| 4741 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf25105cd); | ||
| 4742 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7bfc48); | ||
| 4743 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5a0148); | ||
| 4744 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4745 | break; | ||
| 4746 | |||
| 4747 | case 12000000: | ||
| 4748 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 4749 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050010); | ||
| 4750 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff2ffcc); | ||
| 4751 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001b007b); | ||
| 4752 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffdfff10); | ||
| 4753 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00140198); | ||
| 4754 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0020fd8e); | ||
| 4755 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff710375); | ||
| 4756 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb73); | ||
| 4757 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9a059f); | ||
| 4758 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e0f978); | ||
| 4759 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4e0726); | ||
| 4760 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c8f8a7); | ||
| 4761 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600070c); | ||
| 4762 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2ff9c9); | ||
| 4763 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1db04de); | ||
| 4764 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4fce5); | ||
| 4765 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4b0111); | ||
| 4766 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4767 | break; | ||
| 4768 | |||
| 4769 | case 12100000: | ||
| 4770 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4771 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00010012); | ||
| 4772 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffffffc8); | ||
| 4773 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb007e); | ||
| 4774 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001dff14); | ||
| 4775 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffad0184); | ||
| 4776 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b7fdbe); | ||
| 4777 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9031b); | ||
| 4778 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fc01); | ||
| 4779 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc8504d6); | ||
| 4780 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0504fa79); | ||
| 4781 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf93005f6); | ||
| 4782 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08caf9f2); | ||
| 4783 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52b05c0); | ||
| 4784 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccbfaf9); | ||
| 4785 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf17903eb); | ||
| 4786 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3fd83); | ||
| 4787 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3f00db); | ||
| 4788 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4789 | break; | ||
| 4790 | |||
| 4791 | case 12200000: | ||
| 4792 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 4793 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe0011); | ||
| 4794 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000cffcc); | ||
| 4795 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0071); | ||
| 4796 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0058ff32); | ||
| 4797 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4f014a); | ||
| 4798 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x013cfe1f); | ||
| 4799 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfb028a); | ||
| 4800 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fcc9); | ||
| 4801 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9d03d6); | ||
| 4802 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f4fbad); | ||
| 4803 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848049d); | ||
| 4804 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0999fb5b); | ||
| 4805 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf4820461); | ||
| 4806 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d46fc32); | ||
| 4807 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12d02f4); | ||
| 4808 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1007fe21); | ||
| 4809 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3600a4); | ||
| 4810 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4811 | break; | ||
| 4812 | |||
| 4813 | case 12300000: | ||
| 4814 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 4815 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e); | ||
| 4816 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0017ffd9); | ||
| 4817 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc10055); | ||
| 4818 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0088ff68); | ||
| 4819 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0400f0); | ||
| 4820 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a6fea7); | ||
| 4821 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7501cc); | ||
| 4822 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fdc0); | ||
| 4823 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaef02a8); | ||
| 4824 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a7fd07); | ||
| 4825 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79d0326); | ||
| 4826 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a31fcda); | ||
| 4827 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf40702f3); | ||
| 4828 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9ffd72); | ||
| 4829 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f601fa); | ||
| 4830 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1021fec0); | ||
| 4831 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2f006d); | ||
| 4832 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4833 | break; | ||
| 4834 | |||
| 4835 | case 12400000: | ||
| 4836 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
| 4837 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80007); | ||
| 4838 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001fffeb); | ||
| 4839 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaf002d); | ||
| 4840 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a8ffb0); | ||
| 4841 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3007e); | ||
| 4842 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e9ff4c); | ||
| 4843 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2000ee); | ||
| 4844 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fed8); | ||
| 4845 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82015c); | ||
| 4846 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0715fe7d); | ||
| 4847 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7340198); | ||
| 4848 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8dfe69); | ||
| 4849 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bd017c); | ||
| 4850 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd5feb8); | ||
| 4851 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d500fd); | ||
| 4852 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1031ff60); | ||
| 4853 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2b0037); | ||
| 4854 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4855 | break; | ||
| 4856 | |||
| 4857 | case 12500000: | ||
| 4858 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
| 4859 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff70000); | ||
| 4860 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220000); | ||
| 4861 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffa90000); | ||
| 4862 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b30000); | ||
| 4863 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec20000); | ||
| 4864 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x02000000); | ||
| 4865 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd030000); | ||
| 4866 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350000); | ||
| 4867 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa5e0000); | ||
| 4868 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x073b0000); | ||
| 4869 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7110000); | ||
| 4870 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aac0000); | ||
| 4871 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a40000); | ||
| 4872 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de70000); | ||
| 4873 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0c90000); | ||
| 4874 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x10360000); | ||
| 4875 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef290000); | ||
| 4876 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4877 | break; | ||
| 4878 | |||
| 4879 | case 12600000: | ||
| 4880 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 4881 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff9); | ||
| 4882 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001f0015); | ||
| 4883 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffd3); | ||
| 4884 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a80050); | ||
| 4885 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3ff82); | ||
| 4886 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e900b4); | ||
| 4887 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd20ff12); | ||
| 4888 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130128); | ||
| 4889 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82fea4); | ||
| 4890 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07150183); | ||
| 4891 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf734fe68); | ||
| 4892 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8d0197); | ||
| 4893 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdfe84); | ||
| 4894 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd50148); | ||
| 4895 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d5ff03); | ||
| 4896 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x103100a0); | ||
| 4897 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2bffc9); | ||
| 4898 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4899 | break; | ||
| 4900 | |||
| 4901 | case 12700000: | ||
| 4902 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 4903 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2); | ||
| 4904 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00170027); | ||
| 4905 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ffab); | ||
| 4906 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00880098); | ||
| 4907 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff04ff10); | ||
| 4908 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a60159); | ||
| 4909 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd75fe34); | ||
| 4910 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00240); | ||
| 4911 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaeffd58); | ||
| 4912 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a702f9); | ||
| 4913 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79dfcda); | ||
| 4914 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a310326); | ||
| 4915 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fd0d); | ||
| 4916 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9f028e); | ||
| 4917 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f6fe06); | ||
| 4918 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x10210140); | ||
| 4919 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2fff93); | ||
| 4920 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4921 | break; | ||
| 4922 | |||
| 4923 | case 12800000: | ||
| 4924 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4925 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffef); | ||
| 4926 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000c0034); | ||
| 4927 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff8f); | ||
| 4928 | cx25840_write4(client, DIF_BPF_COEFF89, 0x005800ce); | ||
| 4929 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4ffeb6); | ||
| 4930 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x013c01e1); | ||
| 4931 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfbfd76); | ||
| 4932 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110337); | ||
| 4933 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9dfc2a); | ||
| 4934 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f40453); | ||
| 4935 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848fb63); | ||
| 4936 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x099904a5); | ||
| 4937 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fb9f); | ||
| 4938 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d4603ce); | ||
| 4939 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12dfd0c); | ||
| 4940 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x100701df); | ||
| 4941 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef36ff5c); | ||
| 4942 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4943 | break; | ||
| 4944 | |||
| 4945 | case 12900000: | ||
| 4946 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 4947 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0001ffee); | ||
| 4948 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffff0038); | ||
| 4949 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff82); | ||
| 4950 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001d00ec); | ||
| 4951 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffadfe7c); | ||
| 4952 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b70242); | ||
| 4953 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9fce5); | ||
| 4954 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024103ff); | ||
| 4955 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc85fb2a); | ||
| 4956 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05040587); | ||
| 4957 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf930fa0a); | ||
| 4958 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08ca060e); | ||
| 4959 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfa40); | ||
| 4960 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccb0507); | ||
| 4961 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf179fc15); | ||
| 4962 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3027d); | ||
| 4963 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3fff25); | ||
| 4964 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4965 | break; | ||
| 4966 | |||
| 4967 | case 13000000: | ||
| 4968 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 4969 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff0); | ||
| 4970 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff20034); | ||
| 4971 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bff85); | ||
| 4972 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffdf00f0); | ||
| 4973 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0014fe68); | ||
| 4974 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00200272); | ||
| 4975 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff71fc8b); | ||
| 4976 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d048d); | ||
| 4977 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9afa61); | ||
| 4978 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e00688); | ||
| 4979 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4ef8da); | ||
| 4980 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c80759); | ||
| 4981 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f8f4); | ||
| 4982 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2f0637); | ||
| 4983 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1dbfb22); | ||
| 4984 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4031b); | ||
| 4985 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4bfeef); | ||
| 4986 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 4987 | break; | ||
| 4988 | |||
| 4989 | case 13100000: | ||
| 4990 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
| 4991 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff5); | ||
| 4992 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe70028); | ||
| 4993 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ff98); | ||
| 4994 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffa400d8); | ||
| 4995 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0079fe7c); | ||
| 4996 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87026f); | ||
| 4997 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0043fc6e); | ||
| 4998 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404da); | ||
| 4999 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfecef9da); | ||
| 5000 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294074e); | ||
| 5001 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb99f7db); | ||
| 5002 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x06980881); | ||
| 5003 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef7be); | ||
| 5004 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b730759); | ||
| 5005 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf251fa33); | ||
| 5006 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7b03b8); | ||
| 5007 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5afeb8); | ||
| 5008 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5009 | break; | ||
| 5010 | |||
| 5011 | case 13200000: | ||
| 5012 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
| 5013 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffc); | ||
| 5014 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe00017); | ||
| 5015 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004cffb9); | ||
| 5016 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7500a8); | ||
| 5017 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1feb6); | ||
| 5018 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef90238); | ||
| 5019 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111fc91); | ||
| 5020 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604df); | ||
| 5021 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0012f99b); | ||
| 5022 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x012d07d2); | ||
| 5023 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd07f714); | ||
| 5024 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542097e); | ||
| 5025 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff6a4); | ||
| 5026 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9a086e); | ||
| 5027 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2dbf94b); | ||
| 5028 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f380453); | ||
| 5029 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6cfe82); | ||
| 5030 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5031 | break; | ||
| 5032 | |||
| 5033 | case 13300000: | ||
| 5034 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 5035 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080003); | ||
| 5036 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffde0001); | ||
| 5037 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056ffe3); | ||
| 5038 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff570064); | ||
| 5039 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0113ff10); | ||
| 5040 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe8201d2); | ||
| 5041 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01cafcf0); | ||
| 5042 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35049e); | ||
| 5043 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155f9a6); | ||
| 5044 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xffba080e); | ||
| 5045 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8cf689); | ||
| 5046 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x03ce0a4e); | ||
| 5047 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f5a8); | ||
| 5048 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a50971); | ||
| 5049 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf379f869); | ||
| 5050 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eeb04ec); | ||
| 5051 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef80fe4b); | ||
| 5052 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5053 | break; | ||
| 5054 | |||
| 5055 | case 13400000: | ||
| 5056 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 5057 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000a); | ||
| 5058 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe2ffec); | ||
| 5059 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00540012); | ||
| 5060 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e0015); | ||
| 5061 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137ff82); | ||
| 5062 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2e0145); | ||
| 5063 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260fd86); | ||
| 5064 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51041a); | ||
| 5065 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0287f9fb); | ||
| 5066 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4a0802); | ||
| 5067 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x001df63f); | ||
| 5068 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02430aeb); | ||
| 5069 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf4ce); | ||
| 5070 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x08970a62); | ||
| 5071 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf428f78f); | ||
| 5072 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e950584); | ||
| 5073 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef97fe15); | ||
| 5074 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5075 | break; | ||
| 5076 | |||
| 5077 | case 13500000: | ||
| 5078 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5079 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000f); | ||
| 5080 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffeaffda); | ||
| 5081 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046003d); | ||
| 5082 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5affc4); | ||
| 5083 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000); | ||
| 5084 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04009d); | ||
| 5085 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c8fe48); | ||
| 5086 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99035a); | ||
| 5087 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397fa96); | ||
| 5088 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcec07ad); | ||
| 5089 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x01adf637); | ||
| 5090 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x00ac0b53); | ||
| 5091 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef419); | ||
| 5092 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x07730b3e); | ||
| 5093 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e9f6bd); | ||
| 5094 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35061a); | ||
| 5095 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb1fddf); | ||
| 5096 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5097 | break; | ||
| 5098 | |||
| 5099 | case 13600000: | ||
| 5100 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5101 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000012); | ||
| 5102 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff6ffcd); | ||
| 5103 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f0061); | ||
| 5104 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7bff79); | ||
| 5105 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011e007e); | ||
| 5106 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe08ffe8); | ||
| 5107 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f9ff28); | ||
| 5108 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17026a); | ||
| 5109 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0479fb70); | ||
| 5110 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbad0713); | ||
| 5111 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x032ff672); | ||
| 5112 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff100b83); | ||
| 5113 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff38b); | ||
| 5114 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x063c0c04); | ||
| 5115 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5baf5f5); | ||
| 5116 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dcc06ae); | ||
| 5117 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcdfda8); | ||
| 5118 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5119 | break; | ||
| 5120 | |||
| 5121 | case 13700000: | ||
| 5122 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5123 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0012); | ||
| 5124 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0004ffc8); | ||
| 5125 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00100078); | ||
| 5126 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffacff3e); | ||
| 5127 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e200f0); | ||
| 5128 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe39ff35); | ||
| 5129 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f10017); | ||
| 5130 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd30156); | ||
| 5131 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0521fc7f); | ||
| 5132 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9c0638); | ||
| 5133 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0499f6ee); | ||
| 5134 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7a0b7c); | ||
| 5135 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f325); | ||
| 5136 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f40cb3); | ||
| 5137 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69af537); | ||
| 5138 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5a073f); | ||
| 5139 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefecfd72); | ||
| 5140 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5141 | break; | ||
| 5142 | |||
| 5143 | case 13800000: | ||
| 5144 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe); | ||
| 5145 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e); | ||
| 5146 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0011ffcb); | ||
| 5147 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0007f); | ||
| 5148 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffe7ff19); | ||
| 5149 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x008f014a); | ||
| 5150 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94fe93); | ||
| 5151 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b00105); | ||
| 5152 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3002f); | ||
| 5153 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0585fdb7); | ||
| 5154 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c10525); | ||
| 5155 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x05def7a8); | ||
| 5156 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf20b3c); | ||
| 5157 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f2e9); | ||
| 5158 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a00d48); | ||
| 5159 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf787f484); | ||
| 5160 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdf07cd); | ||
| 5161 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00dfd3c); | ||
| 5162 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5163 | break; | ||
| 5164 | |||
| 5165 | case 13900000: | ||
| 5166 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
| 5167 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80008); | ||
| 5168 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001bffd7); | ||
| 5169 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10076); | ||
| 5170 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0026ff0e); | ||
| 5171 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x002c0184); | ||
| 5172 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0ffe10); | ||
| 5173 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x023b01e0); | ||
| 5174 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff06); | ||
| 5175 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a2ff09); | ||
| 5176 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf92703e4); | ||
| 5177 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f4f89b); | ||
| 5178 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa820ac5); | ||
| 5179 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f2d9); | ||
| 5180 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02430dc3); | ||
| 5181 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf881f3dc); | ||
| 5182 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5c0859); | ||
| 5183 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf031fd06); | ||
| 5184 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5185 | break; | ||
| 5186 | |||
| 5187 | case 14000000: | ||
| 5188 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 5189 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80001); | ||
| 5190 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021ffe8); | ||
| 5191 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffba005d); | ||
| 5192 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0060ff1f); | ||
| 5193 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc40198); | ||
| 5194 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0fdb5); | ||
| 5195 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x019a029a); | ||
| 5196 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fdea); | ||
| 5197 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05750067); | ||
| 5198 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4027f); | ||
| 5199 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d4f9c0); | ||
| 5200 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf9320a1a); | ||
| 5201 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f2f3); | ||
| 5202 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x00df0e22); | ||
| 5203 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf986f341); | ||
| 5204 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd108e2); | ||
| 5205 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058fcd1); | ||
| 5206 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5207 | break; | ||
| 5208 | |||
| 5209 | case 14100000: | ||
| 5210 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 5211 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa); | ||
| 5212 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021fffd); | ||
| 5213 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0038); | ||
| 5214 | cx25840_write4(client, DIF_BPF_COEFF89, 0x008eff4a); | ||
| 5215 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff630184); | ||
| 5216 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x003afd8b); | ||
| 5217 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00da0326); | ||
| 5218 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fced); | ||
| 5219 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x050101c0); | ||
| 5220 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cb0103); | ||
| 5221 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0876fb10); | ||
| 5222 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80a093e); | ||
| 5223 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f338); | ||
| 5224 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7a0e66); | ||
| 5225 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa94f2b2); | ||
| 5226 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3f0967); | ||
| 5227 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf081fc9b); | ||
| 5228 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5229 | break; | ||
| 5230 | |||
| 5231 | case 14200000: | ||
| 5232 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5233 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff3); | ||
| 5234 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001d0013); | ||
| 5235 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa000b); | ||
| 5236 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00aaff89); | ||
| 5237 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13014a); | ||
| 5238 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00cefd95); | ||
| 5239 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x000a037b); | ||
| 5240 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fc1d); | ||
| 5241 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x044c0305); | ||
| 5242 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90cff7e); | ||
| 5243 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5fc81); | ||
| 5244 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7100834); | ||
| 5245 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff3a7); | ||
| 5246 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe160e8d); | ||
| 5247 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaaf231); | ||
| 5248 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa509e9); | ||
| 5249 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0adfc65); | ||
| 5250 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5251 | break; | ||
| 5252 | |||
| 5253 | case 14300000: | ||
| 5254 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5255 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffef); | ||
| 5256 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00140025); | ||
| 5257 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffdd); | ||
| 5258 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2ffd6); | ||
| 5259 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedb00f0); | ||
| 5260 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150fdd3); | ||
| 5261 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff380391); | ||
| 5262 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb85); | ||
| 5263 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x035e0426); | ||
| 5264 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf994fdfe); | ||
| 5265 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08eefe0b); | ||
| 5266 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6490702); | ||
| 5267 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f43e); | ||
| 5268 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb60e97); | ||
| 5269 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc6f1be); | ||
| 5270 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a040a67); | ||
| 5271 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0dbfc30); | ||
| 5272 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5273 | break; | ||
| 5274 | |||
| 5275 | case 14400000: | ||
| 5276 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5277 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002ffee); | ||
| 5278 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00070033); | ||
| 5279 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ffb4); | ||
| 5280 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a40027); | ||
| 5281 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3007e); | ||
| 5282 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b4fe3f); | ||
| 5283 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe760369); | ||
| 5284 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb2e); | ||
| 5285 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02450518); | ||
| 5286 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5ffc90); | ||
| 5287 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1ffa1); | ||
| 5288 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bc05ae); | ||
| 5289 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902f4fc); | ||
| 5290 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb600e85); | ||
| 5291 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde7f15a); | ||
| 5292 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x095d0ae2); | ||
| 5293 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10cfbfb); | ||
| 5294 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5295 | break; | ||
| 5296 | |||
| 5297 | case 14500000: | ||
| 5298 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002); | ||
| 5299 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005ffef); | ||
| 5300 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffa0038); | ||
| 5301 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff95); | ||
| 5302 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00820074); | ||
| 5303 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000); | ||
| 5304 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f0fed0); | ||
| 5305 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd20304); | ||
| 5306 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb1d); | ||
| 5307 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x010e05ce); | ||
| 5308 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb64fb41); | ||
| 5309 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x084e013b); | ||
| 5310 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569043e); | ||
| 5311 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00f5dd); | ||
| 5312 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa150e55); | ||
| 5313 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0bf104); | ||
| 5314 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b00b59); | ||
| 5315 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13ffbc6); | ||
| 5316 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5317 | break; | ||
| 5318 | |||
| 5319 | case 14600000: | ||
| 5320 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
| 5321 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fff4); | ||
| 5322 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffed0035); | ||
| 5323 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff83); | ||
| 5324 | cx25840_write4(client, DIF_BPF_COEFF89, 0x005000b4); | ||
| 5325 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6ff82); | ||
| 5326 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ffff7a); | ||
| 5327 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd580269); | ||
| 5328 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fb53); | ||
| 5329 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffca0640); | ||
| 5330 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc99fa1e); | ||
| 5331 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x079a02cb); | ||
| 5332 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55502ba); | ||
| 5333 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5f6e0); | ||
| 5334 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d90e0a); | ||
| 5335 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0031f0bd); | ||
| 5336 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fd0bcb); | ||
| 5337 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174fb91); | ||
| 5338 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5339 | break; | ||
| 5340 | |||
| 5341 | case 14700000: | ||
| 5342 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
| 5343 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009fffb); | ||
| 5344 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4002a); | ||
| 5345 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ff82); | ||
| 5346 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001400e0); | ||
| 5347 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3cff10); | ||
| 5348 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e10030); | ||
| 5349 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1201a4); | ||
| 5350 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fbcd); | ||
| 5351 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88066a); | ||
| 5352 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf1f92f); | ||
| 5353 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aa0449); | ||
| 5354 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57e0128); | ||
| 5355 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7ef801); | ||
| 5356 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b00da2); | ||
| 5357 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0156f086); | ||
| 5358 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07450c39); | ||
| 5359 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1acfb5c); | ||
| 5360 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5361 | break; | ||
| 5362 | |||
| 5363 | case 14800000: | ||
| 5364 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
| 5365 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080002); | ||
| 5366 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0019); | ||
| 5367 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003fff92); | ||
| 5368 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffd600f1); | ||
| 5369 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96feb6); | ||
| 5370 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x019700e1); | ||
| 5371 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0500c2); | ||
| 5372 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fc84); | ||
| 5373 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd590649); | ||
| 5374 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5df87f); | ||
| 5375 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x058505aa); | ||
| 5376 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4ff91); | ||
| 5377 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9f93c); | ||
| 5378 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69d0d20); | ||
| 5379 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0279f05e); | ||
| 5380 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x06880ca3); | ||
| 5381 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e6fb28); | ||
| 5382 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5383 | break; | ||
| 5384 | |||
| 5385 | case 14900000: | ||
| 5386 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5387 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060009); | ||
| 5388 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0004); | ||
| 5389 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051ffb0); | ||
| 5390 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff9d00e8); | ||
| 5391 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffcfe7c); | ||
| 5392 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01280180); | ||
| 5393 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32ffd2); | ||
| 5394 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fd6e); | ||
| 5395 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4d05df); | ||
| 5396 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d1f812); | ||
| 5397 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x043506e4); | ||
| 5398 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf685fdfb); | ||
| 5399 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fa8d); | ||
| 5400 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a10c83); | ||
| 5401 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0399f046); | ||
| 5402 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c70d08); | ||
| 5403 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222faf3); | ||
| 5404 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5405 | break; | ||
| 5406 | |||
| 5407 | case 15000000: | ||
| 5408 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5409 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f); | ||
| 5410 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe5ffef); | ||
| 5411 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0057ffd9); | ||
| 5412 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7000c4); | ||
| 5413 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0062fe68); | ||
| 5414 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x009e01ff); | ||
| 5415 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95fee6); | ||
| 5416 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0435fe7d); | ||
| 5417 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb710530); | ||
| 5418 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x023cf7ee); | ||
| 5419 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c307ef); | ||
| 5420 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75efc70); | ||
| 5421 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5cfbef); | ||
| 5422 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c10bce); | ||
| 5423 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b3f03f); | ||
| 5424 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05030d69); | ||
| 5425 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf261fabf); | ||
| 5426 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5427 | break; | ||
| 5428 | |||
| 5429 | case 15100000: | ||
| 5430 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
| 5431 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0012); | ||
| 5432 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffefffdc); | ||
| 5433 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510006); | ||
| 5434 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff540089); | ||
| 5435 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00befe7c); | ||
| 5436 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00060253); | ||
| 5437 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe27fe0d); | ||
| 5438 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413ffa2); | ||
| 5439 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad10446); | ||
| 5440 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0390f812); | ||
| 5441 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x013b08c3); | ||
| 5442 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868faf6); | ||
| 5443 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fd5f); | ||
| 5444 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fd0b02); | ||
| 5445 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c7f046); | ||
| 5446 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x043b0dc4); | ||
| 5447 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a1fa8b); | ||
| 5448 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5449 | break; | ||
| 5450 | |||
| 5451 | case 15200000: | ||
| 5452 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe); | ||
| 5453 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0012); | ||
| 5454 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffbffce); | ||
| 5455 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f0033); | ||
| 5456 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e003f); | ||
| 5457 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106feb6); | ||
| 5458 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6e0276); | ||
| 5459 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeddfd56); | ||
| 5460 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000cc); | ||
| 5461 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa740329); | ||
| 5462 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bff87f); | ||
| 5463 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaa095d); | ||
| 5464 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99ef995); | ||
| 5465 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9fed8); | ||
| 5466 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3590a1f); | ||
| 5467 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d2f05e); | ||
| 5468 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x03700e1b); | ||
| 5469 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e4fa58); | ||
| 5470 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5471 | break; | ||
| 5472 | |||
| 5473 | case 15300000: | ||
| 5474 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
| 5475 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9000f); | ||
| 5476 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0009ffc8); | ||
| 5477 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00250059); | ||
| 5478 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5effee); | ||
| 5479 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0132ff10); | ||
| 5480 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee30265); | ||
| 5481 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaafccf); | ||
| 5482 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031101eb); | ||
| 5483 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6001e8); | ||
| 5484 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bdf92f); | ||
| 5485 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1b09b6); | ||
| 5486 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafaf852); | ||
| 5487 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0055); | ||
| 5488 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d50929); | ||
| 5489 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d3f086); | ||
| 5490 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a30e6c); | ||
| 5491 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf329fa24); | ||
| 5492 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5493 | break; | ||
| 5494 | |||
| 5495 | case 15400000: | ||
| 5496 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
| 5497 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80009); | ||
| 5498 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0015ffca); | ||
| 5499 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00050074); | ||
| 5500 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff81ff9f); | ||
| 5501 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013dff82); | ||
| 5502 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe710221); | ||
| 5503 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x007cfc80); | ||
| 5504 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024102ed); | ||
| 5505 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa940090); | ||
| 5506 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0680fa1e); | ||
| 5507 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9b09cd); | ||
| 5508 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc73f736); | ||
| 5509 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad501d0); | ||
| 5510 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2740820); | ||
| 5511 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c9f0bd); | ||
| 5512 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d40eb9); | ||
| 5513 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371f9f1); | ||
| 5514 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5515 | break; | ||
| 5516 | |||
| 5517 | case 15500000: | ||
| 5518 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
| 5519 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80002); | ||
| 5520 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001effd5); | ||
| 5521 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5007f); | ||
| 5522 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff5b); | ||
| 5523 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000); | ||
| 5524 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2401b0); | ||
| 5525 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0146fc70); | ||
| 5526 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d03c6); | ||
| 5527 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb10ff32); | ||
| 5528 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0701fb41); | ||
| 5529 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb3709a1); | ||
| 5530 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f644); | ||
| 5531 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000345); | ||
| 5532 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2350708); | ||
| 5533 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b2f104); | ||
| 5534 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01050eff); | ||
| 5535 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3baf9be); | ||
| 5536 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5537 | break; | ||
| 5538 | |||
| 5539 | case 15600000: | ||
| 5540 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5541 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb); | ||
| 5542 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022ffe6); | ||
| 5543 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9007a); | ||
| 5544 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff29); | ||
| 5545 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2007e); | ||
| 5546 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01011b); | ||
| 5547 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f6fc9e); | ||
| 5548 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440467); | ||
| 5549 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbccfdde); | ||
| 5550 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738fc90); | ||
| 5551 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f70934); | ||
| 5552 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99f582); | ||
| 5553 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x090204b0); | ||
| 5554 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21a05e1); | ||
| 5555 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8df15a); | ||
| 5556 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x00340f41); | ||
| 5557 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf405f98b); | ||
| 5558 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5559 | break; | ||
| 5560 | |||
| 5561 | case 15700000: | ||
| 5562 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5563 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcfff4); | ||
| 5564 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0020fffa); | ||
| 5565 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40064); | ||
| 5566 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002fff11); | ||
| 5567 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a400f0); | ||
| 5568 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0d006e); | ||
| 5569 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0281fd09); | ||
| 5570 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604c9); | ||
| 5571 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbffca2); | ||
| 5572 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0726fdfe); | ||
| 5573 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e80888); | ||
| 5574 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134f4f3); | ||
| 5575 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1060c); | ||
| 5576 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf22304af); | ||
| 5577 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b59f1be); | ||
| 5578 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff640f7d); | ||
| 5579 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf452f959); | ||
| 5580 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5581 | break; | ||
| 5582 | |||
| 5583 | case 15800000: | ||
| 5584 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
| 5585 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0000fff0); | ||
| 5586 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0010); | ||
| 5587 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa0041); | ||
| 5588 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0067ff13); | ||
| 5589 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043014a); | ||
| 5590 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46ffb9); | ||
| 5591 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02dbfda8); | ||
| 5592 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3504e5); | ||
| 5593 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddcfb8d); | ||
| 5594 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9ff7e); | ||
| 5595 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf81107a2); | ||
| 5596 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9f49a); | ||
| 5597 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0753); | ||
| 5598 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2500373); | ||
| 5599 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c14f231); | ||
| 5600 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930fb3); | ||
| 5601 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a1f927); | ||
| 5602 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5603 | break; | ||
| 5604 | |||
| 5605 | case 15900000: | ||
| 5606 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002); | ||
| 5607 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003ffee); | ||
| 5608 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000f0023); | ||
| 5609 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0016); | ||
| 5610 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0093ff31); | ||
| 5611 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdc0184); | ||
| 5612 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6ff09); | ||
| 5613 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fdfe70); | ||
| 5614 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5104ba); | ||
| 5615 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff15faac); | ||
| 5616 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270103); | ||
| 5617 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7780688); | ||
| 5618 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044df479); | ||
| 5619 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430883); | ||
| 5620 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a00231); | ||
| 5621 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbef2b2); | ||
| 5622 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc40fe3); | ||
| 5623 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2f8f5); | ||
| 5624 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5625 | break; | ||
| 5626 | |||
| 5627 | case 16000000: | ||
| 5628 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
| 5629 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0006ffef); | ||
| 5630 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00020031); | ||
| 5631 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffe8); | ||
| 5632 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00adff66); | ||
| 5633 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff790198); | ||
| 5634 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe6e); | ||
| 5635 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e5ff55); | ||
| 5636 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99044a); | ||
| 5637 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x005bfa09); | ||
| 5638 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545027f); | ||
| 5639 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7230541); | ||
| 5640 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b8f490); | ||
| 5641 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20997); | ||
| 5642 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf31300eb); | ||
| 5643 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d55f341); | ||
| 5644 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6100e); | ||
| 5645 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544f8c3); | ||
| 5646 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
| 5647 | break; | ||
| 5648 | } | ||
| 5649 | } | 3577 | } |
| 5650 | 3578 | ||
| 5651 | static void cx23888_std_setup(struct i2c_client *client) | 3579 | static void cx23888_std_setup(struct i2c_client *client) |
| @@ -362,8 +362,6 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, · 361 unmodified lines | |||
| 362 | if (ret) | 362 | if (ret) |
| 363 | return ret; | 363 | return ret; |
| 364 | 364 | ||
| 365 | memset(fd, 0, sizeof(*fd)); | ||
| 366 | |||
| 367 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL; | 365 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL; |
| 368 | 366 | ||
| 369 | state = v4l2_subdev_lock_and_get_active_state(sd); | 367 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| @@ -499,8 +499,6 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, · 498 unmodified lines | |||
| 499 | if (ret) | 499 | if (ret) |
| 500 | return ret; | 500 | return ret; |
| 501 | 501 | ||
| 502 | memset(fd, 0, sizeof(*fd)); | ||
| 503 | |||
| 504 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; | 502 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; |
| 505 | 503 | ||
| 506 | state = v4l2_subdev_lock_and_get_active_state(sd); | 504 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| @@ -2786,8 +2786,6 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, · 2785 unmodified lines | |||
| 2786 | if (!ub960_pad_is_source(priv, pad)) | 2786 | if (!ub960_pad_is_source(priv, pad)) |
| 2787 | return -EINVAL; | 2787 | return -EINVAL; |
| 2788 | 2788 | ||
| 2789 | memset(fd, 0, sizeof(*fd)); | ||
| 2790 | |||
| 2791 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; | 2789 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; |
| 2792 | 2790 | ||
| 2793 | state = v4l2_subdev_lock_and_get_active_state(&priv->sd); | 2791 | state = v4l2_subdev_lock_and_get_active_state(&priv->sd); |
| @@ -477,6 +477,50 @@ static const struct hi556_reg mode_1296x972_regs[] = { · 476 unmodified lines | |||
| 477 | {0x0958, 0xbb80}, | 477 | {0x0958, 0xbb80}, |
| 478 | }; | 478 | }; |
| 479 | 479 | ||
| 480 | static const struct hi556_reg mode_1296x722_regs[] = { | ||
| 481 | {0x0a00, 0x0000}, | ||
| 482 | {0x0b0a, 0x8259}, | ||
| 483 | {0x0f30, 0x5b15}, | ||
| 484 | {0x0f32, 0x7167}, | ||
| 485 | {0x004a, 0x0100}, | ||
| 486 | {0x004c, 0x0000}, | ||
| 487 | {0x004e, 0x0100}, | ||
| 488 | {0x000c, 0x0122}, | ||
| 489 | {0x0008, 0x0b00}, | ||
| 490 | {0x005a, 0x0404}, | ||
| 491 | {0x0012, 0x000c}, | ||
| 492 | {0x0018, 0x0a33}, | ||
| 493 | {0x0022, 0x0008}, | ||
| 494 | {0x0028, 0x0017}, | ||
| 495 | {0x0024, 0x0022}, | ||
| 496 | {0x002a, 0x002b}, | ||
| 497 | {0x0026, 0x012a}, | ||
| 498 | {0x002c, 0x06cf}, | ||
| 499 | {0x002e, 0x3311}, | ||
| 500 | {0x0030, 0x3311}, | ||
| 501 | {0x0032, 0x3311}, | ||
| 502 | {0x0006, 0x0814}, | ||
| 503 | {0x0a22, 0x0000}, | ||
| 504 | {0x0a12, 0x0510}, | ||
| 505 | {0x0a14, 0x02d2}, | ||
| 506 | {0x003e, 0x0000}, | ||
| 507 | {0x0074, 0x0812}, | ||
| 508 | {0x0070, 0x0409}, | ||
| 509 | {0x0804, 0x0308}, | ||
| 510 | {0x0806, 0x0100}, | ||
| 511 | {0x0a04, 0x016a}, | ||
| 512 | {0x090c, 0x09c0}, | ||
| 513 | {0x090e, 0x0010}, | ||
| 514 | {0x0902, 0x4319}, | ||
| 515 | {0x0914, 0xc106}, | ||
| 516 | {0x0916, 0x040e}, | ||
| 517 | {0x0918, 0x0304}, | ||
| 518 | {0x091a, 0x0708}, | ||
| 519 | {0x091c, 0x0e06}, | ||
| 520 | {0x091e, 0x0300}, | ||
| 521 | {0x0958, 0xbb80}, | ||
| 522 | }; | ||
| 523 | |||
| 480 | static const char * const hi556_test_pattern_menu[] = { | 524 | static const char * const hi556_test_pattern_menu[] = { |
| 481 | "Disabled", | 525 | "Disabled", |
| 482 | "Solid Colour", | 526 | "Solid Colour", |
| @@ -556,7 +600,25 @@ static const struct hi556_mode supported_modes[] = { · 73 unmodified lines | |||
| 556 | .regs = mode_1296x972_regs, | 600 | .regs = mode_1296x972_regs, |
| 557 | }, | 601 | }, |
| 558 | .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX, | 602 | .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX, |
| 559 | } | 603 | }, |
| 604 | { | ||
| 605 | .width = 1296, | ||
| 606 | .height = 722, | ||
| 607 | .crop = { | ||
| 608 | .left = HI556_PIXEL_ARRAY_LEFT, | ||
| 609 | .top = 250, | ||
| 610 | .width = HI556_PIXEL_ARRAY_WIDTH, | ||
| 611 | .height = 1444 | ||
| 612 | }, | ||
| 613 | .fll_def = HI556_FLL_30FPS, | ||
| 614 | .fll_min = HI556_FLL_30FPS_MIN, | ||
| 615 | .llp = 0x0b00, | ||
| 616 | .reg_list = { | ||
| 617 | .num_of_regs = ARRAY_SIZE(mode_1296x722_regs), | ||
| 618 | .regs = mode_1296x722_regs, | ||
| 619 | }, | ||
| 620 | .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX, | ||
| 621 | }, | ||
| 560 | }; | 622 | }; |
| 561 | 623 | ||
| 562 | struct hi556 { | 624 | struct hi556 { |
| @@ -577,9 +639,6 @@ struct hi556 { · 14 unmodified lines | |||
| 577 | /* To serialize asynchronus callbacks */ | 639 | /* To serialize asynchronus callbacks */ |
| 578 | struct mutex mutex; | 640 | struct mutex mutex; |
| 579 | 641 | ||
| 580 | /* Streaming on/off */ | ||
| 581 | bool streaming; | ||
| 582 | |||
| 583 | /* True if the device has been identified */ | 642 | /* True if the device has been identified */ |
| 584 | bool identified; | 643 | bool identified; |
| 585 | }; | 644 | }; |
| @@ -976,9 +1035,6 @@ static int hi556_set_stream(struct v4l2_subdev *sd, int enable) · 390 unmodified lines | |||
| 976 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1035 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 977 | int ret = 0; | 1036 | int ret = 0; |
| 978 | 1037 | ||
| 979 | if (hi556->streaming == enable) | ||
| 980 | return 0; | ||
| 981 | |||
| 982 | mutex_lock(&hi556->mutex); | 1038 | mutex_lock(&hi556->mutex); |
| 983 | if (enable) { | 1039 | if (enable) { |
| 984 | ret = pm_runtime_resume_and_get(&client->dev); | 1040 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -998,47 +1054,8 @@ static int hi556_set_stream(struct v4l2_subdev *sd, int enable) · 13 unmodified lines | |||
| 998 | pm_runtime_put(&client->dev); | 1054 | pm_runtime_put(&client->dev); |
| 999 | } | 1055 | } |
| 1000 | 1056 | ||
| 1001 | hi556->streaming = enable; | ||
| 1002 | mutex_unlock(&hi556->mutex); | ||
| 1003 | |||
| 1004 | return ret; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static int __maybe_unused hi556_suspend(struct device *dev) | ||
| 1008 | { | ||
| 1009 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1010 | struct hi556 *hi556 = to_hi556(sd); | ||
| 1011 | |||
| 1012 | mutex_lock(&hi556->mutex); | ||
| 1013 | if (hi556->streaming) | ||
| 1014 | hi556_stop_streaming(hi556); | ||
| 1015 | |||
| 1016 | mutex_unlock(&hi556->mutex); | ||
| 1017 | |||
| 1018 | return 0; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | static int __maybe_unused hi556_resume(struct device *dev) | ||
| 1022 | { | ||
| 1023 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1024 | struct hi556 *hi556 = to_hi556(sd); | ||
| 1025 | int ret; | ||
| 1026 | |||
| 1027 | mutex_lock(&hi556->mutex); | ||
| 1028 | if (hi556->streaming) { | ||
| 1029 | ret = hi556_start_streaming(hi556); | ||
| 1030 | if (ret) | ||
| 1031 | goto error; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | mutex_unlock(&hi556->mutex); | 1057 | mutex_unlock(&hi556->mutex); |
| 1035 | 1058 | ||
| 1036 | return 0; | ||
| 1037 | |||
| 1038 | error: | ||
| 1039 | hi556_stop_streaming(hi556); | ||
| 1040 | hi556->streaming = 0; | ||
| 1041 | mutex_unlock(&hi556->mutex); | ||
| 1042 | return ret; | 1059 | return ret; |
| 1043 | } | 1060 | } |
| 1044 | 1061 | ||
| @@ -1331,10 +1348,6 @@ probe_error_v4l2_ctrl_handler_free: · 286 unmodified lines | |||
| 1331 | return ret; | 1348 | return ret; |
| 1332 | } | 1349 | } |
| 1333 | 1350 | ||
| 1334 | static const struct dev_pm_ops hi556_pm_ops = { | ||
| 1335 | SET_SYSTEM_SLEEP_PM_OPS(hi556_suspend, hi556_resume) | ||
| 1336 | }; | ||
| 1337 | |||
| 1338 | #ifdef CONFIG_ACPI | 1351 | #ifdef CONFIG_ACPI |
| 1339 | static const struct acpi_device_id hi556_acpi_ids[] = { | 1352 | static const struct acpi_device_id hi556_acpi_ids[] = { |
| 1340 | {"INT3537"}, | 1353 | {"INT3537"}, |
| @@ -1347,7 +1360,6 @@ MODULE_DEVICE_TABLE(acpi, hi556_acpi_ids); · 6 unmodified lines | |||
| 1347 | static struct i2c_driver hi556_i2c_driver = { | 1360 | static struct i2c_driver hi556_i2c_driver = { |
| 1348 | .driver = { | 1361 | .driver = { |
| 1349 | .name = "hi556", | 1362 | .name = "hi556", |
| 1350 | .pm = &hi556_pm_ops, | ||
| 1351 | .acpi_match_table = ACPI_PTR(hi556_acpi_ids), | 1363 | .acpi_match_table = ACPI_PTR(hi556_acpi_ids), |
| 1352 | }, | 1364 | }, |
| 1353 | .probe = hi556_probe, | 1365 | .probe = hi556_probe, |
| @@ -1607,17 +1607,12 @@ static int hi846_set_stream(struct v4l2_subdev *sd, int enable) · 1606 unmodified lines | |||
| 1607 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1607 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 1608 | int ret = 0; | 1608 | int ret = 0; |
| 1609 | 1609 | ||
| 1610 | if (hi846->streaming == enable) | ||
| 1611 | return 0; | ||
| 1612 | |||
| 1613 | mutex_lock(&hi846->mutex); | 1610 | mutex_lock(&hi846->mutex); |
| 1614 | 1611 | ||
| 1615 | if (enable) { | 1612 | if (enable) { |
| 1616 | ret = pm_runtime_get_sync(&client->dev); | 1613 | ret = pm_runtime_resume_and_get(&client->dev); |
| 1617 | if (ret < 0) { | 1614 | if (ret) |
| 1618 | pm_runtime_put_noidle(&client->dev); | ||
| 1619 | goto out; | 1615 | goto out; |
| 1620 | } | ||
| 1621 | 1616 | ||
| 1622 | ret = hi846_start_streaming(hi846); | 1617 | ret = hi846_start_streaming(hi846); |
| 1623 | } | 1618 | } |
| @@ -1680,9 +1675,6 @@ static int __maybe_unused hi846_suspend(struct device *dev) · 56 unmodified lines | |||
| 1680 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 1675 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1681 | struct hi846 *hi846 = to_hi846(sd); | 1676 | struct hi846 *hi846 = to_hi846(sd); |
| 1682 | 1677 | ||
| 1683 | if (hi846->streaming) | ||
| 1684 | hi846_stop_streaming(hi846); | ||
| 1685 | |||
| 1686 | return hi846_power_off(hi846); | 1678 | return hi846_power_off(hi846); |
| 1687 | } | 1679 | } |
| 1688 | 1680 | ||
| @@ -1691,26 +1683,8 @@ static int __maybe_unused hi846_resume(struct device *dev) · 2 unmodified lines | |||
| 1691 | struct i2c_client *client = to_i2c_client(dev); | 1683 | struct i2c_client *client = to_i2c_client(dev); |
| 1692 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 1684 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1693 | struct hi846 *hi846 = to_hi846(sd); | 1685 | struct hi846 *hi846 = to_hi846(sd); |
| 1694 | int ret; | ||
| 1695 | |||
| 1696 | ret = hi846_power_on(hi846); | ||
| 1697 | if (ret) | ||
| 1698 | return ret; | ||
| 1699 | 1686 | ||
| 1700 | if (hi846->streaming) { | 1687 | return hi846_power_on(hi846); |
| 1701 | ret = hi846_start_streaming(hi846); | ||
| 1702 | if (ret) { | ||
| 1703 | dev_err(dev, "%s: start streaming failed: %d\n", | ||
| 1704 | __func__, ret); | ||
| 1705 | goto error; | ||
| 1706 | } | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | return 0; | ||
| 1710 | |||
| 1711 | error: | ||
| 1712 | hi846_power_off(hi846); | ||
| 1713 | return ret; | ||
| 1714 | } | 1688 | } |
| 1715 | 1689 | ||
| 1716 | static int hi846_set_format(struct v4l2_subdev *sd, | 1690 | static int hi846_set_format(struct v4l2_subdev *sd, |
| @@ -2173,8 +2147,6 @@ static void hi846_remove(struct i2c_client *client) · 456 unmodified lines | |||
| 2173 | } | 2147 | } |
| 2174 | 2148 | ||
| 2175 | static const struct dev_pm_ops hi846_pm_ops = { | 2149 | static const struct dev_pm_ops hi846_pm_ops = { |
| 2176 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
| 2177 | pm_runtime_force_resume) | ||
| 2178 | SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL) | 2150 | SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL) |
| 2179 | }; | 2151 | }; |
| 2180 | 2152 | ||
| @@ -2184,9 +2184,6 @@ struct hi847 { · 2183 unmodified lines | |||
| 2184 | 2184 | ||
| 2185 | /* To serialize asynchronus callbacks */ | 2185 | /* To serialize asynchronus callbacks */ |
| 2186 | struct mutex mutex; | 2186 | struct mutex mutex; |
| 2187 | |||
| 2188 | /* Streaming on/off */ | ||
| 2189 | bool streaming; | ||
| 2190 | }; | 2187 | }; |
| 2191 | 2188 | ||
| 2192 | static u64 to_pixel_rate(u32 f_index) | 2189 | static u64 to_pixel_rate(u32 f_index) |
| @@ -2618,14 +2615,10 @@ static int hi847_set_stream(struct v4l2_subdev *sd, int enable) · 425 unmodified lines | |||
| 2618 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 2615 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 2619 | int ret = 0; | 2616 | int ret = 0; |
| 2620 | 2617 | ||
| 2621 | if (hi847->streaming == enable) | ||
| 2622 | return 0; | ||
| 2623 | |||
| 2624 | mutex_lock(&hi847->mutex); | 2618 | mutex_lock(&hi847->mutex); |
| 2625 | if (enable) { | 2619 | if (enable) { |
| 2626 | ret = pm_runtime_get_sync(&client->dev); | 2620 | ret = pm_runtime_resume_and_get(&client->dev); |
| 2627 | if (ret < 0) { | 2621 | if (ret) { |
| 2628 | pm_runtime_put_noidle(&client->dev); | ||
| 2629 | mutex_unlock(&hi847->mutex); | 2622 | mutex_unlock(&hi847->mutex); |
| 2630 | return ret; | 2623 | return ret; |
| 2631 | } | 2624 | } |
| @@ -2641,49 +2634,8 @@ static int hi847_set_stream(struct v4l2_subdev *sd, int enable) · 9 unmodified lines | |||
| 2641 | pm_runtime_put(&client->dev); | 2634 | pm_runtime_put(&client->dev); |
| 2642 | } | 2635 | } |
| 2643 | 2636 | ||
| 2644 | hi847->streaming = enable; | ||
| 2645 | mutex_unlock(&hi847->mutex); | ||
| 2646 | |||
| 2647 | return ret; | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | static int __maybe_unused hi847_suspend(struct device *dev) | ||
| 2651 | { | ||
| 2652 | struct i2c_client *client = to_i2c_client(dev); | ||
| 2653 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 2654 | struct hi847 *hi847 = to_hi847(sd); | ||
| 2655 | |||
| 2656 | mutex_lock(&hi847->mutex); | ||
| 2657 | if (hi847->streaming) | ||
| 2658 | hi847_stop_streaming(hi847); | ||
| 2659 | |||
| 2660 | mutex_unlock(&hi847->mutex); | ||
| 2661 | |||
| 2662 | return 0; | ||
| 2663 | } | ||
| 2664 | |||
| 2665 | static int __maybe_unused hi847_resume(struct device *dev) | ||
| 2666 | { | ||
| 2667 | struct i2c_client *client = to_i2c_client(dev); | ||
| 2668 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 2669 | struct hi847 *hi847 = to_hi847(sd); | ||
| 2670 | int ret; | ||
| 2671 | |||
| 2672 | mutex_lock(&hi847->mutex); | ||
| 2673 | if (hi847->streaming) { | ||
| 2674 | ret = hi847_start_streaming(hi847); | ||
| 2675 | if (ret) | ||
| 2676 | goto error; | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | mutex_unlock(&hi847->mutex); | 2637 | mutex_unlock(&hi847->mutex); |
| 2680 | 2638 | ||
| 2681 | return 0; | ||
| 2682 | |||
| 2683 | error: | ||
| 2684 | hi847_stop_streaming(hi847); | ||
| 2685 | hi847->streaming = 0; | ||
| 2686 | mutex_unlock(&hi847->mutex); | ||
| 2687 | return ret; | 2639 | return ret; |
| 2688 | } | 2640 | } |
| 2689 | 2641 | ||
| @@ -2980,10 +2932,6 @@ probe_error_v4l2_ctrl_handler_free: · 290 unmodified lines | |||
| 2980 | return ret; | 2932 | return ret; |
| 2981 | } | 2933 | } |
| 2982 | 2934 | ||
| 2983 | static const struct dev_pm_ops hi847_pm_ops = { | ||
| 2984 | SET_SYSTEM_SLEEP_PM_OPS(hi847_suspend, hi847_resume) | ||
| 2985 | }; | ||
| 2986 | |||
| 2987 | #ifdef CONFIG_ACPI | 2935 | #ifdef CONFIG_ACPI |
| 2988 | static const struct acpi_device_id hi847_acpi_ids[] = { | 2936 | static const struct acpi_device_id hi847_acpi_ids[] = { |
| 2989 | {"HYV0847"}, | 2937 | {"HYV0847"}, |
| @@ -2996,7 +2944,6 @@ MODULE_DEVICE_TABLE(acpi, hi847_acpi_ids); · 6 unmodified lines | |||
| 2996 | static struct i2c_driver hi847_i2c_driver = { | 2944 | static struct i2c_driver hi847_i2c_driver = { |
| 2997 | .driver = { | 2945 | .driver = { |
| 2998 | .name = "hi847", | 2946 | .name = "hi847", |
| 2999 | .pm = &hi847_pm_ops, | ||
| 3000 | .acpi_match_table = ACPI_PTR(hi847_acpi_ids), | 2947 | .acpi_match_table = ACPI_PTR(hi847_acpi_ids), |
| 3001 | }, | 2948 | }, |
| 3002 | .probe = hi847_probe, | 2949 | .probe = hi847_probe, |
| @@ -290,9 +290,6 @@ struct imx208 { · 289 unmodified lines | |||
| 290 | */ | 290 | */ |
| 291 | struct mutex imx208_mx; | 291 | struct mutex imx208_mx; |
| 292 | 292 | ||
| 293 | /* Streaming on/off */ | ||
| 294 | bool streaming; | ||
| 295 | |||
| 296 | /* OTP data */ | 293 | /* OTP data */ |
| 297 | bool otp_read; | 294 | bool otp_read; |
| 298 | char otp_data[IMX208_OTP_SIZE]; | 295 | char otp_data[IMX208_OTP_SIZE]; |
| @@ -714,15 +711,13 @@ static int imx208_set_stream(struct v4l2_subdev *sd, int enable) · 415 unmodified lines | |||
| 714 | int ret = 0; | 711 | int ret = 0; |
| 715 | 712 | ||
| 716 | mutex_lock(&imx208->imx208_mx); | 713 | mutex_lock(&imx208->imx208_mx); |
| 717 | if (imx208->streaming == enable) { | ||
| 718 | mutex_unlock(&imx208->imx208_mx); | ||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | 714 | ||
| 722 | if (enable) { | 715 | if (enable) { |
| 723 | ret = pm_runtime_get_sync(&client->dev); | 716 | ret = pm_runtime_resume_and_get(&client->dev); |
| 724 | if (ret < 0) | 717 | if (ret) { |
| 725 | goto err_rpm_put; | 718 | mutex_unlock(&imx208->imx208_mx); |
| 719 | return ret; | ||
| 720 | } | ||
| 726 | 721 | ||
| 727 | /* | 722 | /* |
| 728 | * Apply default & customized values | 723 | * Apply default & customized values |
| @@ -736,7 +731,6 @@ static int imx208_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 736 | pm_runtime_put(&client->dev); | 731 | pm_runtime_put(&client->dev); |
| 737 | } | 732 | } |
| 738 | 733 | ||
| 739 | imx208->streaming = enable; | ||
| 740 | mutex_unlock(&imx208->imx208_mx); | 734 | mutex_unlock(&imx208->imx208_mx); |
| 741 | 735 | ||
| 742 | /* vflip and hflip cannot change during streaming */ | 736 | /* vflip and hflip cannot change during streaming */ |
| @@ -752,40 +746,6 @@ err_rpm_put: · 9 unmodified lines | |||
| 752 | return ret; | 746 | return ret; |
| 753 | } | 747 | } |
| 754 | 748 | ||
| 755 | static int __maybe_unused imx208_suspend(struct device *dev) | ||
| 756 | { | ||
| 757 | struct i2c_client *client = to_i2c_client(dev); | ||
| 758 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 759 | struct imx208 *imx208 = to_imx208(sd); | ||
| 760 | |||
| 761 | if (imx208->streaming) | ||
| 762 | imx208_stop_streaming(imx208); | ||
| 763 | |||
| 764 | return 0; | ||
| 765 | } | ||
| 766 | |||
| 767 | static int __maybe_unused imx208_resume(struct device *dev) | ||
| 768 | { | ||
| 769 | struct i2c_client *client = to_i2c_client(dev); | ||
| 770 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 771 | struct imx208 *imx208 = to_imx208(sd); | ||
| 772 | int ret; | ||
| 773 | |||
| 774 | if (imx208->streaming) { | ||
| 775 | ret = imx208_start_streaming(imx208); | ||
| 776 | if (ret) | ||
| 777 | goto error; | ||
| 778 | } | ||
| 779 | |||
| 780 | return 0; | ||
| 781 | |||
| 782 | error: | ||
| 783 | imx208_stop_streaming(imx208); | ||
| 784 | imx208->streaming = 0; | ||
| 785 | |||
| 786 | return ret; | ||
| 787 | } | ||
| 788 | |||
| 789 | /* Verify chip ID */ | 749 | /* Verify chip ID */ |
| 790 | static const struct v4l2_subdev_video_ops imx208_video_ops = { | 750 | static const struct v4l2_subdev_video_ops imx208_video_ops = { |
| 791 | .s_stream = imx208_set_stream, | 751 | .s_stream = imx208_set_stream, |
| @@ -819,11 +779,9 @@ static int imx208_read_otp(struct imx208 *imx208) · 27 unmodified lines | |||
| 819 | if (imx208->otp_read) | 779 | if (imx208->otp_read) |
| 820 | goto out_unlock; | 780 | goto out_unlock; |
| 821 | 781 | ||
| 822 | ret = pm_runtime_get_sync(&client->dev); | 782 | ret = pm_runtime_resume_and_get(&client->dev); |
| 823 | if (ret < 0) { | 783 | if (ret) |
| 824 | pm_runtime_put_noidle(&client->dev); | ||
| 825 | goto out_unlock; | 784 | goto out_unlock; |
| 826 | } | ||
| 827 | 785 | ||
| 828 | ret = imx208_identify_module(imx208); | 786 | ret = imx208_identify_module(imx208); |
| 829 | if (ret) | 787 | if (ret) |
| @@ -1081,10 +1039,6 @@ static void imx208_remove(struct i2c_client *client) · 251 unmodified lines | |||
| 1081 | mutex_destroy(&imx208->imx208_mx); | 1039 | mutex_destroy(&imx208->imx208_mx); |
| 1082 | } | 1040 | } |
| 1083 | 1041 | ||
| 1084 | static const struct dev_pm_ops imx208_pm_ops = { | ||
| 1085 | SET_SYSTEM_SLEEP_PM_OPS(imx208_suspend, imx208_resume) | ||
| 1086 | }; | ||
| 1087 | |||
| 1088 | #ifdef CONFIG_ACPI | 1042 | #ifdef CONFIG_ACPI |
| 1089 | static const struct acpi_device_id imx208_acpi_ids[] = { | 1043 | static const struct acpi_device_id imx208_acpi_ids[] = { |
| 1090 | { "INT3478" }, | 1044 | { "INT3478" }, |
| @@ -1097,7 +1051,6 @@ MODULE_DEVICE_TABLE(acpi, imx208_acpi_ids); · 6 unmodified lines | |||
| 1097 | static struct i2c_driver imx208_i2c_driver = { | 1051 | static struct i2c_driver imx208_i2c_driver = { |
| 1098 | .driver = { | 1052 | .driver = { |
| 1099 | .name = "imx208", | 1053 | .name = "imx208", |
| 1100 | .pm = &imx208_pm_ops, | ||
| 1101 | .acpi_match_table = ACPI_PTR(imx208_acpi_ids), | 1054 | .acpi_match_table = ACPI_PTR(imx208_acpi_ids), |
| 1102 | }, | 1055 | }, |
| 1103 | .probe = imx208_probe, | 1056 | .probe = imx208_probe, |
| @@ -58,8 +58,6 @@ struct imx214 { · 57 unmodified lines | |||
| 58 | * and start streaming. | 58 | * and start streaming. |
| 59 | */ | 59 | */ |
| 60 | struct mutex mutex; | 60 | struct mutex mutex; |
| 61 | |||
| 62 | bool streaming; | ||
| 63 | }; | 61 | }; |
| 64 | 62 | ||
| 65 | struct reg_8 { | 63 | struct reg_8 { |
| @@ -775,9 +773,6 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) · 709 unmodified lines | |||
| 775 | struct imx214 *imx214 = to_imx214(subdev); | 773 | struct imx214 *imx214 = to_imx214(subdev); |
| 776 | int ret; | 774 | int ret; |
| 777 | 775 | ||
| 778 | if (imx214->streaming == enable) | ||
| 779 | return 0; | ||
| 780 | |||
| 781 | if (enable) { | 776 | if (enable) { |
| 782 | ret = pm_runtime_resume_and_get(imx214->dev); | 777 | ret = pm_runtime_resume_and_get(imx214->dev); |
| 783 | if (ret < 0) | 778 | if (ret < 0) |
| @@ -793,7 +788,6 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) · 9 unmodified lines | |||
| 793 | pm_runtime_put(imx214->dev); | 788 | pm_runtime_put(imx214->dev); |
| 794 | } | 789 | } |
| 795 | 790 | ||
| 796 | imx214->streaming = enable; | ||
| 797 | return 0; | 791 | return 0; |
| 798 | 792 | ||
| 799 | err_rpm_put: | 793 | err_rpm_put: |
| @@ -909,39 +903,6 @@ done: · 109 unmodified lines | |||
| 909 | return ret; | 903 | return ret; |
| 910 | } | 904 | } |
| 911 | 905 | ||
| 912 | static int __maybe_unused imx214_suspend(struct device *dev) | ||
| 913 | { | ||
| 914 | struct i2c_client *client = to_i2c_client(dev); | ||
| 915 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 916 | struct imx214 *imx214 = to_imx214(sd); | ||
| 917 | |||
| 918 | if (imx214->streaming) | ||
| 919 | imx214_stop_streaming(imx214); | ||
| 920 | |||
| 921 | return 0; | ||
| 922 | } | ||
| 923 | |||
| 924 | static int __maybe_unused imx214_resume(struct device *dev) | ||
| 925 | { | ||
| 926 | struct i2c_client *client = to_i2c_client(dev); | ||
| 927 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 928 | struct imx214 *imx214 = to_imx214(sd); | ||
| 929 | int ret; | ||
| 930 | |||
| 931 | if (imx214->streaming) { | ||
| 932 | ret = imx214_start_streaming(imx214); | ||
| 933 | if (ret) | ||
| 934 | goto error; | ||
| 935 | } | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | |||
| 939 | error: | ||
| 940 | imx214_stop_streaming(imx214); | ||
| 941 | imx214->streaming = 0; | ||
| 942 | return ret; | ||
| 943 | } | ||
| 944 | |||
| 945 | static int imx214_probe(struct i2c_client *client) | 906 | static int imx214_probe(struct i2c_client *client) |
| 946 | { | 907 | { |
| 947 | struct device *dev = &client->dev; | 908 | struct device *dev = &client->dev; |
| @@ -1102,7 +1063,6 @@ static const struct of_device_id imx214_of_match[] = { · 154 unmodified lines | |||
| 1102 | MODULE_DEVICE_TABLE(of, imx214_of_match); | 1063 | MODULE_DEVICE_TABLE(of, imx214_of_match); |
| 1103 | 1064 | ||
| 1104 | static const struct dev_pm_ops imx214_pm_ops = { | 1065 | static const struct dev_pm_ops imx214_pm_ops = { |
| 1105 | SET_SYSTEM_SLEEP_PM_OPS(imx214_suspend, imx214_resume) | ||
| 1106 | SET_RUNTIME_PM_OPS(imx214_power_off, imx214_power_on, NULL) | 1066 | SET_RUNTIME_PM_OPS(imx214_power_off, imx214_power_on, NULL) |
| 1107 | }; | 1067 | }; |
| 1108 | 1068 | ||
| @@ -18,91 +18,99 @@ · 17 unmodified lines | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/gpio/consumer.h> | 19 | #include <linux/gpio/consumer.h> |
| 20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
| 21 | #include <linux/minmax.h> | ||
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
| 23 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
| 25 | |||
| 26 | #include <media/v4l2-cci.h> | ||
| 24 | #include <media/v4l2-ctrls.h> | 27 | #include <media/v4l2-ctrls.h> |
| 25 | #include <media/v4l2-device.h> | 28 | #include <media/v4l2-device.h> |
| 26 | #include <media/v4l2-event.h> | 29 | #include <media/v4l2-event.h> |
| 27 | #include <media/v4l2-fwnode.h> | 30 | #include <media/v4l2-fwnode.h> |
| 28 | #include <media/v4l2-mediabus.h> | 31 | #include <media/v4l2-mediabus.h> |
| 29 | #include <asm/unaligned.h> | ||
| 30 | |||
| 31 | #define IMX219_REG_VALUE_08BIT 1 | ||
| 32 | #define IMX219_REG_VALUE_16BIT 2 | ||
| 33 | |||
| 34 | #define IMX219_REG_MODE_SELECT 0x0100 | ||
| 35 | #define IMX219_MODE_STANDBY 0x00 | ||
| 36 | #define IMX219_MODE_STREAMING 0x01 | ||
| 37 | 32 | ||
| 38 | /* Chip ID */ | 33 | /* Chip ID */ |
| 39 | #define IMX219_REG_CHIP_ID 0x0000 | 34 | #define IMX219_REG_CHIP_ID CCI_REG16(0x0000) |
| 40 | #define IMX219_CHIP_ID 0x0219 | 35 | #define IMX219_CHIP_ID 0x0219 |
| 41 | 36 | ||
| 42 | /* External clock frequency is 24.0M */ | 37 | #define IMX219_REG_MODE_SELECT CCI_REG8(0x0100) |
| 43 | #define IMX219_XCLK_FREQ 24000000 | 38 | #define IMX219_MODE_STANDBY 0x00 |
| 44 | 39 | #define IMX219_MODE_STREAMING 0x01 | |
| 45 | /* Pixel rate is fixed for all the modes */ | ||
| 46 | #define IMX219_PIXEL_RATE 182400000 | ||
| 47 | #define IMX219_PIXEL_RATE_4LANE 280800000 | ||
| 48 | |||
| 49 | #define IMX219_DEFAULT_LINK_FREQ 456000000 | ||
| 50 | #define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000 | ||
| 51 | 40 | ||
| 52 | #define IMX219_REG_CSI_LANE_MODE 0x0114 | 41 | #define IMX219_REG_CSI_LANE_MODE CCI_REG8(0x0114) |
| 53 | #define IMX219_CSI_2_LANE_MODE 0x01 | 42 | #define IMX219_CSI_2_LANE_MODE 0x01 |
| 54 | #define IMX219_CSI_4_LANE_MODE 0x03 | 43 | #define IMX219_CSI_4_LANE_MODE 0x03 |
| 55 | 44 | ||
| 56 | /* V_TIMING internal */ | 45 | #define IMX219_REG_DPHY_CTRL CCI_REG8(0x0128) |
| 57 | #define IMX219_REG_VTS 0x0160 | 46 | #define IMX219_DPHY_CTRL_TIMING_AUTO 0 |
| 58 | #define IMX219_VTS_15FPS 0x0dc6 | 47 | #define IMX219_DPHY_CTRL_TIMING_MANUAL 1 |
| 59 | #define IMX219_VTS_30FPS_1080P 0x06e3 | ||
| 60 | #define IMX219_VTS_30FPS_BINNED 0x06e3 | ||
| 61 | #define IMX219_VTS_30FPS_640x480 0x06e3 | ||
| 62 | #define IMX219_VTS_MAX 0xffff | ||
| 63 | |||
| 64 | #define IMX219_VBLANK_MIN 4 | ||
| 65 | |||
| 66 | /*Frame Length Line*/ | ||
| 67 | #define IMX219_FLL_MIN 0x08a6 | ||
| 68 | #define IMX219_FLL_MAX 0xffff | ||
| 69 | #define IMX219_FLL_STEP 1 | ||
| 70 | #define IMX219_FLL_DEFAULT 0x0c98 | ||
| 71 | |||
| 72 | /* HBLANK control - read only */ | ||
| 73 | #define IMX219_PPL_DEFAULT 3448 | ||
| 74 | 48 | ||
| 75 | /* Exposure control */ | 49 | #define IMX219_REG_EXCK_FREQ CCI_REG16(0x012a) |
| 76 | #define IMX219_REG_EXPOSURE 0x015a | 50 | #define IMX219_EXCK_FREQ(n) ((n) * 256) /* n expressed in MHz */ |
| 77 | #define IMX219_EXPOSURE_MIN 4 | ||
| 78 | #define IMX219_EXPOSURE_STEP 1 | ||
| 79 | #define IMX219_EXPOSURE_DEFAULT 0x640 | ||
| 80 | #define IMX219_EXPOSURE_MAX 65535 | ||
| 81 | 51 | ||
| 82 | /* Analog gain control */ | 52 | /* Analog gain control */ |
| 83 | #define IMX219_REG_ANALOG_GAIN 0x0157 | 53 | #define IMX219_REG_ANALOG_GAIN CCI_REG8(0x0157) |
| 84 | #define IMX219_ANA_GAIN_MIN 0 | 54 | #define IMX219_ANA_GAIN_MIN 0 |
| 85 | #define IMX219_ANA_GAIN_MAX 232 | 55 | #define IMX219_ANA_GAIN_MAX 232 |
| 86 | #define IMX219_ANA_GAIN_STEP 1 | 56 | #define IMX219_ANA_GAIN_STEP 1 |
| 87 | #define IMX219_ANA_GAIN_DEFAULT 0x0 | 57 | #define IMX219_ANA_GAIN_DEFAULT 0x0 |
| 88 | 58 | ||
| 89 | /* Digital gain control */ | 59 | /* Digital gain control */ |
| 90 | #define IMX219_REG_DIGITAL_GAIN 0x0158 | 60 | #define IMX219_REG_DIGITAL_GAIN CCI_REG16(0x0158) |
| 91 | #define IMX219_DGTL_GAIN_MIN 0x0100 | 61 | #define IMX219_DGTL_GAIN_MIN 0x0100 |
| 92 | #define IMX219_DGTL_GAIN_MAX 0x0fff | 62 | #define IMX219_DGTL_GAIN_MAX 0x0fff |
| 93 | #define IMX219_DGTL_GAIN_DEFAULT 0x0100 | 63 | #define IMX219_DGTL_GAIN_DEFAULT 0x0100 |
| 94 | #define IMX219_DGTL_GAIN_STEP 1 | 64 | #define IMX219_DGTL_GAIN_STEP 1 |
| 95 | 65 | ||
| 96 | #define IMX219_REG_ORIENTATION 0x0172 | 66 | /* Exposure control */ |
| 67 | #define IMX219_REG_EXPOSURE CCI_REG16(0x015a) | ||
| 68 | #define IMX219_EXPOSURE_MIN 4 | ||
| 69 | #define IMX219_EXPOSURE_STEP 1 | ||
| 70 | #define IMX219_EXPOSURE_DEFAULT 0x640 | ||
| 71 | #define IMX219_EXPOSURE_MAX 65535 | ||
| 72 | |||
| 73 | /* V_TIMING internal */ | ||
| 74 | #define IMX219_REG_VTS CCI_REG16(0x0160) | ||
| 75 | #define IMX219_VTS_MAX 0xffff | ||
| 76 | |||
| 77 | #define IMX219_VBLANK_MIN 4 | ||
| 78 | |||
| 79 | /* HBLANK control - read only */ | ||
| 80 | #define IMX219_PPL_DEFAULT 3448 | ||
| 81 | |||
| 82 | #define IMX219_REG_LINE_LENGTH_A CCI_REG16(0x0162) | ||
| 83 | #define IMX219_REG_X_ADD_STA_A CCI_REG16(0x0164) | ||
| 84 | #define IMX219_REG_X_ADD_END_A CCI_REG16(0x0166) | ||
| 85 | #define IMX219_REG_Y_ADD_STA_A CCI_REG16(0x0168) | ||
| 86 | #define IMX219_REG_Y_ADD_END_A CCI_REG16(0x016a) | ||
| 87 | #define IMX219_REG_X_OUTPUT_SIZE CCI_REG16(0x016c) | ||
| 88 | #define IMX219_REG_Y_OUTPUT_SIZE CCI_REG16(0x016e) | ||
| 89 | #define IMX219_REG_X_ODD_INC_A CCI_REG8(0x0170) | ||
| 90 | #define IMX219_REG_Y_ODD_INC_A CCI_REG8(0x0171) | ||
| 91 | #define IMX219_REG_ORIENTATION CCI_REG8(0x0172) | ||
| 97 | 92 | ||
| 98 | /* Binning Mode */ | 93 | /* Binning Mode */ |
| 99 | #define IMX219_REG_BINNING_MODE 0x0174 | 94 | #define IMX219_REG_BINNING_MODE_H CCI_REG8(0x0174) |
| 100 | #define IMX219_BINNING_NONE 0x0000 | 95 | #define IMX219_REG_BINNING_MODE_V CCI_REG8(0x0175) |
| 101 | #define IMX219_BINNING_2X2 0x0101 | 96 | #define IMX219_BINNING_NONE 0x00 |
| 102 | #define IMX219_BINNING_2X2_ANALOG 0x0303 | 97 | #define IMX219_BINNING_X2 0x01 |
| 98 | #define IMX219_BINNING_X2_ANALOG 0x03 | ||
| 99 | |||
| 100 | #define IMX219_REG_CSI_DATA_FORMAT_A CCI_REG16(0x018c) | ||
| 101 | |||
| 102 | /* PLL Settings */ | ||
| 103 | #define IMX219_REG_VTPXCK_DIV CCI_REG8(0x0301) | ||
| 104 | #define IMX219_REG_VTSYCK_DIV CCI_REG8(0x0303) | ||
| 105 | #define IMX219_REG_PREPLLCK_VT_DIV CCI_REG8(0x0304) | ||
| 106 | #define IMX219_REG_PREPLLCK_OP_DIV CCI_REG8(0x0305) | ||
| 107 | #define IMX219_REG_PLL_VT_MPY CCI_REG16(0x0306) | ||
| 108 | #define IMX219_REG_OPPXCK_DIV CCI_REG8(0x0309) | ||
| 109 | #define IMX219_REG_OPSYCK_DIV CCI_REG8(0x030b) | ||
| 110 | #define IMX219_REG_PLL_OP_MPY CCI_REG16(0x030c) | ||
| 103 | 111 | ||
| 104 | /* Test Pattern Control */ | 112 | /* Test Pattern Control */ |
| 105 | #define IMX219_REG_TEST_PATTERN 0x0600 | 113 | #define IMX219_REG_TEST_PATTERN CCI_REG16(0x0600) |
| 106 | #define IMX219_TEST_PATTERN_DISABLE 0 | 114 | #define IMX219_TEST_PATTERN_DISABLE 0 |
| 107 | #define IMX219_TEST_PATTERN_SOLID_COLOR 1 | 115 | #define IMX219_TEST_PATTERN_SOLID_COLOR 1 |
| 108 | #define IMX219_TEST_PATTERN_COLOR_BARS 2 | 116 | #define IMX219_TEST_PATTERN_COLOR_BARS 2 |
| @@ -110,17 +118,26 @@ · 1 unmodified line | |||
| 110 | #define IMX219_TEST_PATTERN_PN9 4 | 118 | #define IMX219_TEST_PATTERN_PN9 4 |
| 111 | 119 | ||
| 112 | /* Test pattern colour components */ | 120 | /* Test pattern colour components */ |
| 113 | #define IMX219_REG_TESTP_RED 0x0602 | 121 | #define IMX219_REG_TESTP_RED CCI_REG16(0x0602) |
| 114 | #define IMX219_REG_TESTP_GREENR 0x0604 | 122 | #define IMX219_REG_TESTP_GREENR CCI_REG16(0x0604) |
| 115 | #define IMX219_REG_TESTP_BLUE 0x0606 | 123 | #define IMX219_REG_TESTP_BLUE CCI_REG16(0x0606) |
| 116 | #define IMX219_REG_TESTP_GREENB 0x0608 | 124 | #define IMX219_REG_TESTP_GREENB CCI_REG16(0x0608) |
| 117 | #define IMX219_TESTP_COLOUR_MIN 0 | 125 | #define IMX219_TESTP_COLOUR_MIN 0 |
| 118 | #define IMX219_TESTP_COLOUR_MAX 0x03ff | 126 | #define IMX219_TESTP_COLOUR_MAX 0x03ff |
| 119 | #define IMX219_TESTP_COLOUR_STEP 1 | 127 | #define IMX219_TESTP_COLOUR_STEP 1 |
| 120 | #define IMX219_TESTP_RED_DEFAULT IMX219_TESTP_COLOUR_MAX | 128 | |
| 121 | #define IMX219_TESTP_GREENR_DEFAULT 0 | 129 | #define IMX219_REG_TP_WINDOW_WIDTH CCI_REG16(0x0624) |
| 122 | #define IMX219_TESTP_BLUE_DEFAULT 0 | 130 | #define IMX219_REG_TP_WINDOW_HEIGHT CCI_REG16(0x0626) |
| 123 | #define IMX219_TESTP_GREENB_DEFAULT 0 | 131 | |
| 132 | /* External clock frequency is 24.0M */ | ||
| 133 | #define IMX219_XCLK_FREQ 24000000 | ||
| 134 | |||
| 135 | /* Pixel rate is fixed for all the modes */ | ||
| 136 | #define IMX219_PIXEL_RATE 182400000 | ||
| 137 | #define IMX219_PIXEL_RATE_4LANE 280800000 | ||
| 138 | |||
| 139 | #define IMX219_DEFAULT_LINK_FREQ 456000000 | ||
| 140 | #define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000 | ||
| 124 | 141 | ||
| 125 | /* IMX219 native and active pixel array size. */ | 142 | /* IMX219 native and active pixel array size. */ |
| 126 | #define IMX219_NATIVE_WIDTH 3296U | 143 | #define IMX219_NATIVE_WIDTH 3296U |
| @@ -130,16 +147,6 @@ · 3 unmodified lines | |||
| 130 | #define IMX219_PIXEL_ARRAY_WIDTH 3280U | 147 | #define IMX219_PIXEL_ARRAY_WIDTH 3280U |
| 131 | #define IMX219_PIXEL_ARRAY_HEIGHT 2464U | 148 | #define IMX219_PIXEL_ARRAY_HEIGHT 2464U |
| 132 | 149 | ||
| 133 | struct imx219_reg { | ||
| 134 | u16 address; | ||
| 135 | u8 val; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct imx219_reg_list { | ||
| 139 | unsigned int num_of_regs; | ||
| 140 | const struct imx219_reg *regs; | ||
| 141 | }; | ||
| 142 | |||
| 143 | /* Mode : resolution and related config&values */ | 150 | /* Mode : resolution and related config&values */ |
| 144 | struct imx219_mode { | 151 | struct imx219_mode { |
| 145 | /* Frame width */ | 152 | /* Frame width */ |
| @@ -147,159 +154,52 @@ struct imx219_mode { · 1 unmodified line | |||
| 147 | /* Frame height */ | 154 | /* Frame height */ |
| 148 | unsigned int height; | 155 | unsigned int height; |
| 149 | 156 | ||
| 150 | /* Analog crop rectangle. */ | ||
| 151 | struct v4l2_rect crop; | ||
| 152 | |||
| 153 | /* V-timing */ | 157 | /* V-timing */ |
| 154 | unsigned int vts_def; | 158 | unsigned int vts_def; |
| 155 | |||
| 156 | /* Default register values */ | ||
| 157 | struct imx219_reg_list reg_list; | ||
| 158 | |||
| 159 | /* 2x2 binning is used */ | ||
| 160 | bool binning; | ||
| 161 | }; | 159 | }; |
| 162 | 160 | ||
| 163 | static const struct imx219_reg imx219_common_regs[] = { | 161 | static const struct cci_reg_sequence imx219_common_regs[] = { |
| 164 | {0x0100, 0x00}, /* Mode Select */ | 162 | { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */ |
| 165 | 163 | ||
| 166 | /* To Access Addresses 3000-5fff, send the following commands */ | 164 | /* To Access Addresses 3000-5fff, send the following commands */ |
| 167 | {0x30eb, 0x0c}, | 165 | { CCI_REG8(0x30eb), 0x0c }, |
| 168 | {0x30eb, 0x05}, | 166 | { CCI_REG8(0x30eb), 0x05 }, |
| 169 | {0x300a, 0xff}, | 167 | { CCI_REG8(0x300a), 0xff }, |
| 170 | {0x300b, 0xff}, | 168 | { CCI_REG8(0x300b), 0xff }, |
| 171 | {0x30eb, 0x05}, | 169 | { CCI_REG8(0x30eb), 0x05 }, |
| 172 | {0x30eb, 0x09}, | 170 | { CCI_REG8(0x30eb), 0x09 }, |
| 173 | 171 | ||
| 174 | /* PLL Clock Table */ | 172 | /* PLL Clock Table */ |
| 175 | {0x0301, 0x05}, /* VTPXCK_DIV */ | 173 | { IMX219_REG_VTPXCK_DIV, 5 }, |
| 176 | {0x0303, 0x01}, /* VTSYSCK_DIV */ | 174 | { IMX219_REG_VTSYCK_DIV, 1 }, |
| 177 | {0x0304, 0x03}, /* PREPLLCK_VT_DIV 0x03 = AUTO set */ | 175 | { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ |
| 178 | {0x0305, 0x03}, /* PREPLLCK_OP_DIV 0x03 = AUTO set */ | 176 | { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ |
| 179 | {0x0306, 0x00}, /* PLL_VT_MPY */ | 177 | { IMX219_REG_PLL_VT_MPY, 57 }, |
| 180 | {0x0307, 0x39}, | 178 | { IMX219_REG_OPSYCK_DIV, 1 }, |
| 181 | {0x030b, 0x01}, /* OP_SYS_CLK_DIV */ | 179 | { IMX219_REG_PLL_OP_MPY, 114 }, |
| 182 | {0x030c, 0x00}, /* PLL_OP_MPY */ | ||
| 183 | {0x030d, 0x72}, | ||
| 184 | 180 | ||
| 185 | /* Undocumented registers */ | 181 | /* Undocumented registers */ |
| 186 | {0x455e, 0x00}, | 182 | { CCI_REG8(0x455e), 0x00 }, |
| 187 | {0x471e, 0x4b}, | 183 | { CCI_REG8(0x471e), 0x4b }, |
| 188 | {0x4767, 0x0f}, | 184 | { CCI_REG8(0x4767), 0x0f }, |
| 189 | {0x4750, 0x14}, | 185 | { CCI_REG8(0x4750), 0x14 }, |
| 190 | {0x4540, 0x00}, | 186 | { CCI_REG8(0x4540), 0x00 }, |
| 191 | {0x47b4, 0x14}, | 187 | { CCI_REG8(0x47b4), 0x14 }, |
| 192 | {0x4713, 0x30}, | 188 | { CCI_REG8(0x4713), 0x30 }, |
| 193 | {0x478b, 0x10}, | 189 | { CCI_REG8(0x478b), 0x10 }, |
| 194 | {0x478f, 0x10}, | 190 | { CCI_REG8(0x478f), 0x10 }, |
| 195 | {0x4793, 0x10}, | 191 | { CCI_REG8(0x4793), 0x10 }, |
| 196 | {0x4797, 0x0e}, | 192 | { CCI_REG8(0x4797), 0x0e }, |
| 197 | {0x479b, 0x0e}, | 193 | { CCI_REG8(0x479b), 0x0e }, |
| 198 | 194 | ||
| 199 | /* Frame Bank Register Group "A" */ | 195 | /* Frame Bank Register Group "A" */ |
| 200 | {0x0162, 0x0d}, /* Line_Length_A */ | 196 | { IMX219_REG_LINE_LENGTH_A, 3448 }, |
| 201 | {0x0163, 0x78}, | 197 | { IMX219_REG_X_ODD_INC_A, 1 }, |
| 202 | {0x0170, 0x01}, /* X_ODD_INC_A */ | 198 | { IMX219_REG_Y_ODD_INC_A, 1 }, |
| 203 | {0x0171, 0x01}, /* Y_ODD_INC_A */ | ||
| 204 | 199 | ||
| 205 | /* Output setup registers */ | 200 | /* Output setup registers */ |
| 206 | {0x0114, 0x01}, /* CSI 2-Lane Mode */ | 201 | { IMX219_REG_DPHY_CTRL, IMX219_DPHY_CTRL_TIMING_AUTO }, |
| 207 | {0x0128, 0x00}, /* DPHY Auto Mode */ | 202 | { IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) }, |
| 208 | {0x012a, 0x18}, /* EXCK_Freq */ | ||
| 209 | {0x012b, 0x00}, | ||
| 210 | }; | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Register sets lifted off the i2C interface from the Raspberry Pi firmware | ||
| 214 | * driver. | ||
| 215 | * 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7. | ||
| 216 | */ | ||
| 217 | static const struct imx219_reg mode_3280x2464_regs[] = { | ||
| 218 | {0x0164, 0x00}, | ||
| 219 | {0x0165, 0x00}, | ||
| 220 | {0x0166, 0x0c}, | ||
| 221 | {0x0167, 0xcf}, | ||
| 222 | {0x0168, 0x00}, | ||
| 223 | {0x0169, 0x00}, | ||
| 224 | {0x016a, 0x09}, | ||
| 225 | {0x016b, 0x9f}, | ||
| 226 | {0x016c, 0x0c}, | ||
| 227 | {0x016d, 0xd0}, | ||
| 228 | {0x016e, 0x09}, | ||
| 229 | {0x016f, 0xa0}, | ||
| 230 | {0x0624, 0x0c}, | ||
| 231 | {0x0625, 0xd0}, | ||
| 232 | {0x0626, 0x09}, | ||
| 233 | {0x0627, 0xa0}, | ||
| 234 | }; | ||
| 235 | |||
| 236 | static const struct imx219_reg mode_1920_1080_regs[] = { | ||
| 237 | {0x0164, 0x02}, | ||
| 238 | {0x0165, 0xa8}, | ||
| 239 | {0x0166, 0x0a}, | ||
| 240 | {0x0167, 0x27}, | ||
| 241 | {0x0168, 0x02}, | ||
| 242 | {0x0169, 0xb4}, | ||
| 243 | {0x016a, 0x06}, | ||
| 244 | {0x016b, 0xeb}, | ||
| 245 | {0x016c, 0x07}, | ||
| 246 | {0x016d, 0x80}, | ||
| 247 | {0x016e, 0x04}, | ||
| 248 | {0x016f, 0x38}, | ||
| 249 | {0x0624, 0x07}, | ||
| 250 | {0x0625, 0x80}, | ||
| 251 | {0x0626, 0x04}, | ||
| 252 | {0x0627, 0x38}, | ||
| 253 | }; | ||
| 254 | |||
| 255 | static const struct imx219_reg mode_1640_1232_regs[] = { | ||
| 256 | {0x0164, 0x00}, | ||
| 257 | {0x0165, 0x00}, | ||
| 258 | {0x0166, 0x0c}, | ||
| 259 | {0x0167, 0xcf}, | ||
| 260 | {0x0168, 0x00}, | ||
| 261 | {0x0169, 0x00}, | ||
| 262 | {0x016a, 0x09}, | ||
| 263 | {0x016b, 0x9f}, | ||
| 264 | {0x016c, 0x06}, | ||
| 265 | {0x016d, 0x68}, | ||
| 266 | {0x016e, 0x04}, | ||
| 267 | {0x016f, 0xd0}, | ||
| 268 | {0x0624, 0x06}, | ||
| 269 | {0x0625, 0x68}, | ||
| 270 | {0x0626, 0x04}, | ||
| 271 | {0x0627, 0xd0}, | ||
| 272 | }; | ||
| 273 | |||
| 274 | static const struct imx219_reg mode_640_480_regs[] = { | ||
| 275 | {0x0164, 0x03}, | ||
| 276 | {0x0165, 0xe8}, | ||
| 277 | {0x0166, 0x08}, | ||
| 278 | {0x0167, 0xe7}, | ||
| 279 | {0x0168, 0x02}, | ||
| 280 | {0x0169, 0xf0}, | ||
| 281 | {0x016a, 0x06}, | ||
| 282 | {0x016b, 0xaf}, | ||
| 283 | {0x016c, 0x02}, | ||
| 284 | {0x016d, 0x80}, | ||
| 285 | {0x016e, 0x01}, | ||
| 286 | {0x016f, 0xe0}, | ||
| 287 | {0x0624, 0x06}, | ||
| 288 | {0x0625, 0x68}, | ||
| 289 | {0x0626, 0x04}, | ||
| 290 | {0x0627, 0xd0}, | ||
| 291 | }; | ||
| 292 | |||
| 293 | static const struct imx219_reg raw8_framefmt_regs[] = { | ||
| 294 | {0x018c, 0x08}, | ||
| 295 | {0x018d, 0x08}, | ||
| 296 | {0x0309, 0x08}, | ||
| 297 | }; | ||
| 298 | |||
| 299 | static const struct imx219_reg raw10_framefmt_regs[] = { | ||
| 300 | {0x018c, 0x0a}, | ||
| 301 | {0x018d, 0x0a}, | ||
| 302 | {0x0309, 0x0a}, | ||
| 303 | }; | 203 | }; |
| 304 | 204 | ||
| 305 | static const s64 imx219_link_freq_menu[] = { | 205 | static const s64 imx219_link_freq_menu[] = { |
| @@ -390,69 +290,25 @@ static const struct imx219_mode supported_modes[] = { · 84 unmodified lines | |||
| 390 | /* 8MPix 15fps mode */ | 290 | /* 8MPix 15fps mode */ |
| 391 | .width = 3280, | 291 | .width = 3280, |
| 392 | .height = 2464, | 292 | .height = 2464, |
| 393 | .crop = { | 293 | .vts_def = 3526, |
| 394 | .left = IMX219_PIXEL_ARRAY_LEFT, | ||
| 395 | .top = IMX219_PIXEL_ARRAY_TOP, | ||
| 396 | .width = 3280, | ||
| 397 | .height = 2464 | ||
| 398 | }, | ||
| 399 | .vts_def = IMX219_VTS_15FPS, | ||
| 400 | .reg_list = { | ||
| 401 | .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), | ||
| 402 | .regs = mode_3280x2464_regs, | ||
| 403 | }, | ||
| 404 | .binning = false, | ||
| 405 | }, | 294 | }, |
| 406 | { | 295 | { |
| 407 | /* 1080P 30fps cropped */ | 296 | /* 1080P 30fps cropped */ |
| 408 | .width = 1920, | 297 | .width = 1920, |
| 409 | .height = 1080, | 298 | .height = 1080, |
| 410 | .crop = { | 299 | .vts_def = 1763, |
| 411 | .left = 688, | ||
| 412 | .top = 700, | ||
| 413 | .width = 1920, | ||
| 414 | .height = 1080 | ||
| 415 | }, | ||
| 416 | .vts_def = IMX219_VTS_30FPS_1080P, | ||
| 417 | .reg_list = { | ||
| 418 | .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), | ||
| 419 | .regs = mode_1920_1080_regs, | ||
| 420 | }, | ||
| 421 | .binning = false, | ||
| 422 | }, | 300 | }, |
| 423 | { | 301 | { |
| 424 | /* 2x2 binned 30fps mode */ | 302 | /* 2x2 binned 30fps mode */ |
| 425 | .width = 1640, | 303 | .width = 1640, |
| 426 | .height = 1232, | 304 | .height = 1232, |
| 427 | .crop = { | 305 | .vts_def = 1763, |
| 428 | .left = IMX219_PIXEL_ARRAY_LEFT, | ||
| 429 | .top = IMX219_PIXEL_ARRAY_TOP, | ||
| 430 | .width = 3280, | ||
| 431 | .height = 2464 | ||
| 432 | }, | ||
| 433 | .vts_def = IMX219_VTS_30FPS_BINNED, | ||
| 434 | .reg_list = { | ||
| 435 | .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), | ||
| 436 | .regs = mode_1640_1232_regs, | ||
| 437 | }, | ||
| 438 | .binning = true, | ||
| 439 | }, | 306 | }, |
| 440 | { | 307 | { |
| 441 | /* 640x480 30fps mode */ | 308 | /* 640x480 30fps mode */ |
| 442 | .width = 640, | 309 | .width = 640, |
| 443 | .height = 480, | 310 | .height = 480, |
| 444 | .crop = { | 311 | .vts_def = 1763, |
| 445 | .left = 1008, | ||
| 446 | .top = 760, | ||
| 447 | .width = 1280, | ||
| 448 | .height = 960 | ||
| 449 | }, | ||
| 450 | .vts_def = IMX219_VTS_30FPS_640x480, | ||
| 451 | .reg_list = { | ||
| 452 | .num_of_regs = ARRAY_SIZE(mode_640_480_regs), | ||
| 453 | .regs = mode_640_480_regs, | ||
| 454 | }, | ||
| 455 | .binning = true, | ||
| 456 | }, | 312 | }, |
| 457 | }; | 313 | }; |
| 458 | 314 | ||
| @@ -460,6 +316,7 @@ struct imx219 { · 1 unmodified line | |||
| 460 | struct v4l2_subdev sd; | 316 | struct v4l2_subdev sd; |
| 461 | struct media_pad pad; | 317 | struct media_pad pad; |
| 462 | 318 | ||
| 319 | struct regmap *regmap; | ||
| 463 | struct clk *xclk; /* system clock to IMX219 */ | 320 | struct clk *xclk; /* system clock to IMX219 */ |
| 464 | u32 xclk_freq; | 321 | u32 xclk_freq; |
| 465 | 322 | ||
| @@ -476,12 +333,6 @@ struct imx219 { · 10 unmodified lines | |||
| 476 | struct v4l2_ctrl *vblank; | 333 | struct v4l2_ctrl *vblank; |
| 477 | struct v4l2_ctrl *hblank; | 334 | struct v4l2_ctrl *hblank; |
| 478 | 335 | ||
| 479 | /* Current mode */ | ||
| 480 | const struct imx219_mode *mode; | ||
| 481 | |||
| 482 | /* Streaming on/off */ | ||
| 483 | bool streaming; | ||
| 484 | |||
| 485 | /* Two or Four lanes */ | 336 | /* Two or Four lanes */ |
| 486 | u8 lanes; | 337 | u8 lanes; |
| 487 | }; | 338 | }; |
| @@ -491,78 +342,6 @@ static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd) · 3 unmodified lines | |||
| 491 | return container_of(_sd, struct imx219, sd); | 342 | return container_of(_sd, struct imx219, sd); |
| 492 | } | 343 | } |
| 493 | 344 | ||
| 494 | /* Read registers up to 2 at a time */ | ||
| 495 | static int imx219_read_reg(struct imx219 *imx219, u16 reg, u32 len, u32 *val) | ||
| 496 | { | ||
| 497 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | ||
| 498 | struct i2c_msg msgs[2]; | ||
| 499 | u8 addr_buf[2] = { reg >> 8, reg & 0xff }; | ||
| 500 | u8 data_buf[4] = { 0, }; | ||
| 501 | int ret; | ||
| 502 | |||
| 503 | if (len > 4) | ||
| 504 | return -EINVAL; | ||
| 505 | |||
| 506 | /* Write register address */ | ||
| 507 | msgs[0].addr = client->addr; | ||
| 508 | msgs[0].flags = 0; | ||
| 509 | msgs[0].len = ARRAY_SIZE(addr_buf); | ||
| 510 | msgs[0].buf = addr_buf; | ||
| 511 | |||
| 512 | /* Read data from register */ | ||
| 513 | msgs[1].addr = client->addr; | ||
| 514 | msgs[1].flags = I2C_M_RD; | ||
| 515 | msgs[1].len = len; | ||
| 516 | msgs[1].buf = &data_buf[4 - len]; | ||
| 517 | |||
| 518 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 519 | if (ret != ARRAY_SIZE(msgs)) | ||
| 520 | return -EIO; | ||
| 521 | |||
| 522 | *val = get_unaligned_be32(data_buf); | ||
| 523 | |||
| 524 | return 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | /* Write registers up to 2 at a time */ | ||
| 528 | static int imx219_write_reg(struct imx219 *imx219, u16 reg, u32 len, u32 val) | ||
| 529 | { | ||
| 530 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | ||
| 531 | u8 buf[6]; | ||
| 532 | |||
| 533 | if (len > 4) | ||
| 534 | return -EINVAL; | ||
| 535 | |||
| 536 | put_unaligned_be16(reg, buf); | ||
| 537 | put_unaligned_be32(val << (8 * (4 - len)), buf + 2); | ||
| 538 | if (i2c_master_send(client, buf, len + 2) != len + 2) | ||
| 539 | return -EIO; | ||
| 540 | |||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | |||
| 544 | /* Write a list of registers */ | ||
| 545 | static int imx219_write_regs(struct imx219 *imx219, | ||
| 546 | const struct imx219_reg *regs, u32 len) | ||
| 547 | { | ||
| 548 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | ||
| 549 | unsigned int i; | ||
| 550 | int ret; | ||
| 551 | |||
| 552 | for (i = 0; i < len; i++) { | ||
| 553 | ret = imx219_write_reg(imx219, regs[i].address, 1, regs[i].val); | ||
| 554 | if (ret) { | ||
| 555 | dev_err_ratelimited(&client->dev, | ||
| 556 | "Failed to write reg 0x%4.4x. error = %d\n", | ||
| 557 | regs[i].address, ret); | ||
| 558 | |||
| 559 | return ret; | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | |||
| 566 | /* Get bayer order based on flip setting. */ | 345 | /* Get bayer order based on flip setting. */ |
| 567 | static u32 imx219_get_format_code(struct imx219 *imx219, u32 code) | 346 | static u32 imx219_get_format_code(struct imx219 *imx219, u32 code) |
| 568 | { | 347 | { |
| @@ -581,18 +360,27 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code) · 12 unmodified lines | |||
| 581 | return imx219_mbus_formats[i]; | 360 | return imx219_mbus_formats[i]; |
| 582 | } | 361 | } |
| 583 | 362 | ||
| 363 | /* ----------------------------------------------------------------------------- | ||
| 364 | * Controls | ||
| 365 | */ | ||
| 366 | |||
| 584 | static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) | 367 | static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) |
| 585 | { | 368 | { |
| 586 | struct imx219 *imx219 = | 369 | struct imx219 *imx219 = |
| 587 | container_of(ctrl->handler, struct imx219, ctrl_handler); | 370 | container_of(ctrl->handler, struct imx219, ctrl_handler); |
| 588 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | 371 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); |
| 589 | int ret; | 372 | const struct v4l2_mbus_framefmt *format; |
| 373 | struct v4l2_subdev_state *state; | ||
| 374 | int ret = 0; | ||
| 375 | |||
| 376 | state = v4l2_subdev_get_locked_active_state(&imx219->sd); | ||
| 377 | format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0); | ||
| 590 | 378 | ||
| 591 | if (ctrl->id == V4L2_CID_VBLANK) { | 379 | if (ctrl->id == V4L2_CID_VBLANK) { |
| 592 | int exposure_max, exposure_def; | 380 | int exposure_max, exposure_def; |
| 593 | 381 | ||
| 594 | /* Update max exposure while meeting expected vblanking */ | 382 | /* Update max exposure while meeting expected vblanking */ |
| 595 | exposure_max = imx219->mode->height + ctrl->val - 4; | 383 | exposure_max = format->height + ctrl->val - 4; |
| 596 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? | 384 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? |
| 597 | exposure_max : IMX219_EXPOSURE_DEFAULT; | 385 | exposure_max : IMX219_EXPOSURE_DEFAULT; |
| 598 | __v4l2_ctrl_modify_range(imx219->exposure, | 386 | __v4l2_ctrl_modify_range(imx219->exposure, |
| @@ -610,48 +398,45 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) · 11 unmodified lines | |||
| 610 | 398 | ||
| 611 | switch (ctrl->id) { | 399 | switch (ctrl->id) { |
| 612 | case V4L2_CID_ANALOGUE_GAIN: | 400 | case V4L2_CID_ANALOGUE_GAIN: |
| 613 | ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN, | 401 | cci_write(imx219->regmap, IMX219_REG_ANALOG_GAIN, |
| 614 | IMX219_REG_VALUE_08BIT, ctrl->val); | 402 | ctrl->val, &ret); |
| 615 | break; | 403 | break; |
| 616 | case V4L2_CID_EXPOSURE: | 404 | case V4L2_CID_EXPOSURE: |
| 617 | ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE, | 405 | cci_write(imx219->regmap, IMX219_REG_EXPOSURE, |
| 618 | IMX219_REG_VALUE_16BIT, ctrl->val); | 406 | ctrl->val, &ret); |
| 619 | break; | 407 | break; |
| 620 | case V4L2_CID_DIGITAL_GAIN: | 408 | case V4L2_CID_DIGITAL_GAIN: |
| 621 | ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN, | 409 | cci_write(imx219->regmap, IMX219_REG_DIGITAL_GAIN, |
| 622 | IMX219_REG_VALUE_16BIT, ctrl->val); | 410 | ctrl->val, &ret); |
| 623 | break; | 411 | break; |
| 624 | case V4L2_CID_TEST_PATTERN: | 412 | case V4L2_CID_TEST_PATTERN: |
| 625 | ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN, | 413 | cci_write(imx219->regmap, IMX219_REG_TEST_PATTERN, |
| 626 | IMX219_REG_VALUE_16BIT, | 414 | imx219_test_pattern_val[ctrl->val], &ret); |
| 627 | imx219_test_pattern_val[ctrl->val]); | ||
| 628 | break; | 415 | break; |
| 629 | case V4L2_CID_HFLIP: | 416 | case V4L2_CID_HFLIP: |
| 630 | case V4L2_CID_VFLIP: | 417 | case V4L2_CID_VFLIP: |
| 631 | ret = imx219_write_reg(imx219, IMX219_REG_ORIENTATION, 1, | 418 | cci_write(imx219->regmap, IMX219_REG_ORIENTATION, |
| 632 | imx219->hflip->val | | 419 | imx219->hflip->val | imx219->vflip->val << 1, &ret); |
| 633 | imx219->vflip->val << 1); | ||
| 634 | break; | 420 | break; |
| 635 | case V4L2_CID_VBLANK: | 421 | case V4L2_CID_VBLANK: |
| 636 | ret = imx219_write_reg(imx219, IMX219_REG_VTS, | 422 | cci_write(imx219->regmap, IMX219_REG_VTS, |
| 637 | IMX219_REG_VALUE_16BIT, | 423 | format->height + ctrl->val, &ret); |
| 638 | imx219->mode->height + ctrl->val); | ||
| 639 | break; | 424 | break; |
| 640 | case V4L2_CID_TEST_PATTERN_RED: | 425 | case V4L2_CID_TEST_PATTERN_RED: |
| 641 | ret = imx219_write_reg(imx219, IMX219_REG_TESTP_RED, | 426 | cci_write(imx219->regmap, IMX219_REG_TESTP_RED, |
| 642 | IMX219_REG_VALUE_16BIT, ctrl->val); | 427 | ctrl->val, &ret); |
| 643 | break; | 428 | break; |
| 644 | case V4L2_CID_TEST_PATTERN_GREENR: | 429 | case V4L2_CID_TEST_PATTERN_GREENR: |
| 645 | ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENR, | 430 | cci_write(imx219->regmap, IMX219_REG_TESTP_GREENR, |
| 646 | IMX219_REG_VALUE_16BIT, ctrl->val); | 431 | ctrl->val, &ret); |
| 647 | break; | 432 | break; |
| 648 | case V4L2_CID_TEST_PATTERN_BLUE: | 433 | case V4L2_CID_TEST_PATTERN_BLUE: |
| 649 | ret = imx219_write_reg(imx219, IMX219_REG_TESTP_BLUE, | 434 | cci_write(imx219->regmap, IMX219_REG_TESTP_BLUE, |
| 650 | IMX219_REG_VALUE_16BIT, ctrl->val); | 435 | ctrl->val, &ret); |
| 651 | break; | 436 | break; |
| 652 | case V4L2_CID_TEST_PATTERN_GREENB: | 437 | case V4L2_CID_TEST_PATTERN_GREENB: |
| 653 | ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENB, | 438 | cci_write(imx219->regmap, IMX219_REG_TESTP_GREENB, |
| 654 | IMX219_REG_VALUE_16BIT, ctrl->val); | 439 | ctrl->val, &ret); |
| 655 | break; | 440 | break; |
| 656 | default: | 441 | default: |
| 657 | dev_info(&client->dev, | 442 | dev_info(&client->dev, |
| @@ -670,226 +455,224 @@ static const struct v4l2_ctrl_ops imx219_ctrl_ops = { · 12 unmodified lines | |||
| 670 | .s_ctrl = imx219_set_ctrl, | 455 | .s_ctrl = imx219_set_ctrl, |
| 671 | }; | 456 | }; |
| 672 | 457 | ||
| 673 | static void imx219_update_pad_format(struct imx219 *imx219, | 458 | static unsigned long imx219_get_pixel_rate(struct imx219 *imx219) |
| 674 | const struct imx219_mode *mode, | ||
| 675 | struct v4l2_mbus_framefmt *fmt, u32 code) | ||
| 676 | { | 459 | { |
| 677 | /* Bayer order varies with flips */ | 460 | return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; |
| 678 | fmt->code = imx219_get_format_code(imx219, code); | ||
| 679 | fmt->width = mode->width; | ||
| 680 | fmt->height = mode->height; | ||
| 681 | fmt->field = V4L2_FIELD_NONE; | ||
| 682 | fmt->colorspace = V4L2_COLORSPACE_RAW; | ||
| 683 | fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; | ||
| 684 | fmt->xfer_func = V4L2_XFER_FUNC_NONE; | ||
| 685 | } | 461 | } |
| 686 | 462 | ||
| 687 | static int imx219_init_cfg(struct v4l2_subdev *sd, | 463 | /* Initialize control handlers */ |
| 688 | struct v4l2_subdev_state *state) | 464 | static int imx219_init_controls(struct imx219 *imx219) |
| 689 | { | 465 | { |
| 690 | struct imx219 *imx219 = to_imx219(sd); | 466 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); |
| 691 | struct v4l2_mbus_framefmt *format; | 467 | const struct imx219_mode *mode = &supported_modes[0]; |
| 692 | struct v4l2_rect *crop; | 468 | struct v4l2_ctrl_handler *ctrl_hdlr; |
| 469 | struct v4l2_fwnode_device_properties props; | ||
| 470 | int exposure_max, exposure_def, hblank; | ||
| 471 | int i, ret; | ||
| 693 | 472 | ||
| 694 | /* Initialize the format. */ | 473 | ctrl_hdlr = &imx219->ctrl_handler; |
| 695 | format = v4l2_subdev_get_pad_format(sd, state, 0); | 474 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); |
| 696 | imx219_update_pad_format(imx219, &supported_modes[0], format, | 475 | if (ret) |
| 697 | MEDIA_BUS_FMT_SRGGB10_1X10); | 476 | return ret; |
| 698 | 477 | ||
| 699 | /* Initialize the crop rectangle. */ | 478 | /* By default, PIXEL_RATE is read only */ |
| 700 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | 479 | imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, |
| 701 | crop->top = IMX219_PIXEL_ARRAY_TOP; | 480 | V4L2_CID_PIXEL_RATE, |
| 702 | crop->left = IMX219_PIXEL_ARRAY_LEFT; | 481 | imx219_get_pixel_rate(imx219), |
| 703 | crop->width = IMX219_PIXEL_ARRAY_WIDTH; | 482 | imx219_get_pixel_rate(imx219), 1, |
| 704 | crop->height = IMX219_PIXEL_ARRAY_HEIGHT; | 483 | imx219_get_pixel_rate(imx219)); |
| 705 | 484 | ||
| 706 | return 0; | 485 | imx219->link_freq = |
| 707 | } | 486 | v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, |
| 487 | V4L2_CID_LINK_FREQ, | ||
| 488 | ARRAY_SIZE(imx219_link_freq_menu) - 1, 0, | ||
| 489 | (imx219->lanes == 2) ? imx219_link_freq_menu : | ||
| 490 | imx219_link_freq_4lane_menu); | ||
| 491 | if (imx219->link_freq) | ||
| 492 | imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 708 | 493 | ||
| 709 | static int imx219_enum_mbus_code(struct v4l2_subdev *sd, | 494 | /* Initial vblank/hblank/exposure parameters based on current mode */ |
| 710 | struct v4l2_subdev_state *sd_state, | 495 | imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, |
| 711 | struct v4l2_subdev_mbus_code_enum *code) | 496 | V4L2_CID_VBLANK, IMX219_VBLANK_MIN, |
| 712 | { | 497 | IMX219_VTS_MAX - mode->height, 1, |
| 713 | struct imx219 *imx219 = to_imx219(sd); | 498 | mode->vts_def - mode->height); |
| 499 | hblank = IMX219_PPL_DEFAULT - mode->width; | ||
| 500 | imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 501 | V4L2_CID_HBLANK, hblank, hblank, | ||
| 502 | 1, hblank); | ||
| 503 | if (imx219->hblank) | ||
| 504 | imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 505 | exposure_max = mode->vts_def - 4; | ||
| 506 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? | ||
| 507 | exposure_max : IMX219_EXPOSURE_DEFAULT; | ||
| 508 | imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 509 | V4L2_CID_EXPOSURE, | ||
| 510 | IMX219_EXPOSURE_MIN, exposure_max, | ||
| 511 | IMX219_EXPOSURE_STEP, | ||
| 512 | exposure_def); | ||
| 714 | 513 | ||
| 715 | if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4)) | 514 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, |
| 716 | return -EINVAL; | 515 | IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX, |
| 516 | IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT); | ||
| 717 | 517 | ||
| 718 | code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]); | 518 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN, |
| 519 | IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX, | ||
| 520 | IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT); | ||
| 719 | 521 | ||
| 720 | return 0; | 522 | imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, |
| 721 | } | 523 | V4L2_CID_HFLIP, 0, 1, 1, 0); |
| 524 | if (imx219->hflip) | ||
| 525 | imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | ||
| 722 | 526 | ||
| 723 | static int imx219_enum_frame_size(struct v4l2_subdev *sd, | 527 | imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, |
| 724 | struct v4l2_subdev_state *sd_state, | 528 | V4L2_CID_VFLIP, 0, 1, 1, 0); |
| 725 | struct v4l2_subdev_frame_size_enum *fse) | 529 | if (imx219->vflip) |
| 726 | { | 530 | imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; |
| 727 | struct imx219 *imx219 = to_imx219(sd); | ||
| 728 | u32 code; | ||
| 729 | 531 | ||
| 730 | if (fse->index >= ARRAY_SIZE(supported_modes)) | 532 | v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, |
| 731 | return -EINVAL; | 533 | V4L2_CID_TEST_PATTERN, |
| 534 | ARRAY_SIZE(imx219_test_pattern_menu) - 1, | ||
| 535 | 0, 0, imx219_test_pattern_menu); | ||
| 536 | for (i = 0; i < 4; i++) { | ||
| 537 | /* | ||
| 538 | * The assumption is that | ||
| 539 | * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1 | ||
| 540 | * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2 | ||
| 541 | * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3 | ||
| 542 | */ | ||
| 543 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 544 | V4L2_CID_TEST_PATTERN_RED + i, | ||
| 545 | IMX219_TESTP_COLOUR_MIN, | ||
| 546 | IMX219_TESTP_COLOUR_MAX, | ||
| 547 | IMX219_TESTP_COLOUR_STEP, | ||
| 548 | IMX219_TESTP_COLOUR_MAX); | ||
| 549 | /* The "Solid color" pattern is white by default */ | ||
| 550 | } | ||
| 732 | 551 | ||
| 733 | code = imx219_get_format_code(imx219, fse->code); | 552 | if (ctrl_hdlr->error) { |
| 734 | if (fse->code != code) | 553 | ret = ctrl_hdlr->error; |
| 735 | return -EINVAL; | 554 | dev_err(&client->dev, "%s control init failed (%d)\n", |
| 555 | __func__, ret); | ||
| 556 | goto error; | ||
| 557 | } | ||
| 736 | 558 | ||
| 737 | fse->min_width = supported_modes[fse->index].width; | 559 | ret = v4l2_fwnode_device_parse(&client->dev, &props); |
| 738 | fse->max_width = fse->min_width; | 560 | if (ret) |
| 739 | fse->min_height = supported_modes[fse->index].height; | 561 | goto error; |
| 740 | fse->max_height = fse->min_height; | ||
| 741 | 562 | ||
| 742 | return 0; | 563 | ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, |
| 743 | } | 564 | &props); |
| 744 | 565 | if (ret) | |
| 745 | static int imx219_set_pad_format(struct v4l2_subdev *sd, | 566 | goto error; |
| 746 | struct v4l2_subdev_state *sd_state, | ||
| 747 | struct v4l2_subdev_format *fmt) | ||
| 748 | { | ||
| 749 | struct imx219 *imx219 = to_imx219(sd); | ||
| 750 | const struct imx219_mode *mode; | ||
| 751 | int exposure_max, exposure_def, hblank; | ||
| 752 | struct v4l2_mbus_framefmt *format; | ||
| 753 | struct v4l2_rect *crop; | ||
| 754 | |||
| 755 | mode = v4l2_find_nearest_size(supported_modes, | ||
| 756 | ARRAY_SIZE(supported_modes), | ||
| 757 | width, height, | ||
| 758 | fmt->format.width, fmt->format.height); | ||
| 759 | |||
| 760 | imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); | ||
| 761 | 567 | ||
| 762 | format = v4l2_subdev_get_pad_format(sd, sd_state, 0); | 568 | imx219->sd.ctrl_handler = ctrl_hdlr; |
| 763 | crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); | ||
| 764 | 569 | ||
| 765 | *format = fmt->format; | 570 | return 0; |
| 766 | *crop = mode->crop; | ||
| 767 | 571 | ||
| 768 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | 572 | error: |
| 769 | imx219->mode = mode; | 573 | v4l2_ctrl_handler_free(ctrl_hdlr); |
| 770 | /* Update limits and set FPS to default */ | ||
| 771 | __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN, | ||
| 772 | IMX219_VTS_MAX - mode->height, 1, | ||
| 773 | mode->vts_def - mode->height); | ||
| 774 | __v4l2_ctrl_s_ctrl(imx219->vblank, | ||
| 775 | mode->vts_def - mode->height); | ||
| 776 | /* Update max exposure while meeting expected vblanking */ | ||
| 777 | exposure_max = mode->vts_def - 4; | ||
| 778 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? | ||
| 779 | exposure_max : IMX219_EXPOSURE_DEFAULT; | ||
| 780 | __v4l2_ctrl_modify_range(imx219->exposure, | ||
| 781 | imx219->exposure->minimum, | ||
| 782 | exposure_max, imx219->exposure->step, | ||
| 783 | exposure_def); | ||
| 784 | /* | ||
| 785 | * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank | ||
| 786 | * depends on mode->width only, and is not changeble in any | ||
| 787 | * way other than changing the mode. | ||
| 788 | */ | ||
| 789 | hblank = IMX219_PPL_DEFAULT - mode->width; | ||
| 790 | __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1, | ||
| 791 | hblank); | ||
| 792 | } | ||
| 793 | 574 | ||
| 794 | return 0; | 575 | return ret; |
| 795 | } | 576 | } |
| 796 | 577 | ||
| 797 | static int imx219_set_framefmt(struct imx219 *imx219, | 578 | static void imx219_free_controls(struct imx219 *imx219) |
| 798 | const struct v4l2_mbus_framefmt *format) | ||
| 799 | { | 579 | { |
| 800 | switch (format->code) { | 580 | v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); |
| 801 | case MEDIA_BUS_FMT_SRGGB8_1X8: | ||
| 802 | case MEDIA_BUS_FMT_SGRBG8_1X8: | ||
| 803 | case MEDIA_BUS_FMT_SGBRG8_1X8: | ||
| 804 | case MEDIA_BUS_FMT_SBGGR8_1X8: | ||
| 805 | return imx219_write_regs(imx219, raw8_framefmt_regs, | ||
| 806 | ARRAY_SIZE(raw8_framefmt_regs)); | ||
| 807 | |||
| 808 | case MEDIA_BUS_FMT_SRGGB10_1X10: | ||
| 809 | case MEDIA_BUS_FMT_SGRBG10_1X10: | ||
| 810 | case MEDIA_BUS_FMT_SGBRG10_1X10: | ||
| 811 | case MEDIA_BUS_FMT_SBGGR10_1X10: | ||
| 812 | return imx219_write_regs(imx219, raw10_framefmt_regs, | ||
| 813 | ARRAY_SIZE(raw10_framefmt_regs)); | ||
| 814 | } | ||
| 815 | |||
| 816 | return -EINVAL; | ||
| 817 | } | 581 | } |
| 818 | 582 | ||
| 819 | static int imx219_set_binning(struct imx219 *imx219, | 583 | /* ----------------------------------------------------------------------------- |
| 820 | const struct v4l2_mbus_framefmt *format) | 584 | * Subdev operations |
| 585 | */ | ||
| 586 | |||
| 587 | static int imx219_set_framefmt(struct imx219 *imx219, | ||
| 588 | struct v4l2_subdev_state *state) | ||
| 821 | { | 589 | { |
| 822 | if (!imx219->mode->binning) { | 590 | const struct v4l2_mbus_framefmt *format; |
| 823 | return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | 591 | const struct v4l2_rect *crop; |
| 824 | IMX219_REG_VALUE_16BIT, | 592 | unsigned int bpp; |
| 825 | IMX219_BINNING_NONE); | 593 | u64 bin_h, bin_v; |
| 826 | } | 594 | int ret = 0; |
| 595 | |||
| 596 | format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0); | ||
| 597 | crop = v4l2_subdev_get_pad_crop(&imx219->sd, state, 0); | ||
| 827 | 598 | ||
| 828 | switch (format->code) { | 599 | switch (format->code) { |
| 829 | case MEDIA_BUS_FMT_SRGGB8_1X8: | 600 | case MEDIA_BUS_FMT_SRGGB8_1X8: |
| 830 | case MEDIA_BUS_FMT_SGRBG8_1X8: | 601 | case MEDIA_BUS_FMT_SGRBG8_1X8: |
| 831 | case MEDIA_BUS_FMT_SGBRG8_1X8: | 602 | case MEDIA_BUS_FMT_SGBRG8_1X8: |
| 832 | case MEDIA_BUS_FMT_SBGGR8_1X8: | 603 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
| 833 | return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | 604 | bpp = 8; |
| 834 | IMX219_REG_VALUE_16BIT, | 605 | break; |
| 835 | IMX219_BINNING_2X2_ANALOG); | ||
| 836 | 606 | ||
| 837 | case MEDIA_BUS_FMT_SRGGB10_1X10: | 607 | case MEDIA_BUS_FMT_SRGGB10_1X10: |
| 838 | case MEDIA_BUS_FMT_SGRBG10_1X10: | 608 | case MEDIA_BUS_FMT_SGRBG10_1X10: |
| 839 | case MEDIA_BUS_FMT_SGBRG10_1X10: | 609 | case MEDIA_BUS_FMT_SGBRG10_1X10: |
| 840 | case MEDIA_BUS_FMT_SBGGR10_1X10: | 610 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
| 841 | return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | 611 | default: |
| 842 | IMX219_REG_VALUE_16BIT, | 612 | bpp = 10; |
| 843 | IMX219_BINNING_2X2); | 613 | break; |
| 844 | } | 614 | } |
| 845 | 615 | ||
| 846 | return -EINVAL; | 616 | cci_write(imx219->regmap, IMX219_REG_X_ADD_STA_A, |
| 847 | } | 617 | crop->left - IMX219_PIXEL_ARRAY_LEFT, &ret); |
| 618 | cci_write(imx219->regmap, IMX219_REG_X_ADD_END_A, | ||
| 619 | crop->left - IMX219_PIXEL_ARRAY_LEFT + crop->width - 1, &ret); | ||
| 620 | cci_write(imx219->regmap, IMX219_REG_Y_ADD_STA_A, | ||
| 621 | crop->top - IMX219_PIXEL_ARRAY_TOP, &ret); | ||
| 622 | cci_write(imx219->regmap, IMX219_REG_Y_ADD_END_A, | ||
| 623 | crop->top - IMX219_PIXEL_ARRAY_TOP + crop->height - 1, &ret); | ||
| 624 | |||
| 625 | switch (crop->width / format->width) { | ||
| 626 | case 1: | ||
| 627 | default: | ||
| 628 | bin_h = IMX219_BINNING_NONE; | ||
| 629 | break; | ||
| 630 | case 2: | ||
| 631 | bin_h = bpp == 8 ? IMX219_BINNING_X2_ANALOG : IMX219_BINNING_X2; | ||
| 632 | break; | ||
| 633 | } | ||
| 848 | 634 | ||
| 849 | static int imx219_get_selection(struct v4l2_subdev *sd, | 635 | switch (crop->height / format->height) { |
| 850 | struct v4l2_subdev_state *sd_state, | 636 | case 1: |
| 851 | struct v4l2_subdev_selection *sel) | 637 | default: |
| 852 | { | 638 | bin_v = IMX219_BINNING_NONE; |
| 853 | switch (sel->target) { | 639 | break; |
| 854 | case V4L2_SEL_TGT_CROP: { | 640 | case 2: |
| 855 | sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); | 641 | bin_v = bpp == 8 ? IMX219_BINNING_X2_ANALOG : IMX219_BINNING_X2; |
| 856 | return 0; | 642 | break; |
| 857 | } | 643 | } |
| 858 | 644 | ||
| 859 | case V4L2_SEL_TGT_NATIVE_SIZE: | 645 | cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H, bin_h, &ret); |
| 860 | sel->r.top = 0; | 646 | cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V, bin_v, &ret); |
| 861 | sel->r.left = 0; | ||
| 862 | sel->r.width = IMX219_NATIVE_WIDTH; | ||
| 863 | sel->r.height = IMX219_NATIVE_HEIGHT; | ||
| 864 | 647 | ||
| 865 | return 0; | 648 | cci_write(imx219->regmap, IMX219_REG_X_OUTPUT_SIZE, |
| 649 | format->width, &ret); | ||
| 650 | cci_write(imx219->regmap, IMX219_REG_Y_OUTPUT_SIZE, | ||
| 651 | format->height, &ret); | ||
| 866 | 652 | ||
| 867 | case V4L2_SEL_TGT_CROP_DEFAULT: | 653 | cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_WIDTH, |
| 868 | case V4L2_SEL_TGT_CROP_BOUNDS: | 654 | format->width, &ret); |
| 869 | sel->r.top = IMX219_PIXEL_ARRAY_TOP; | 655 | cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_HEIGHT, |
| 870 | sel->r.left = IMX219_PIXEL_ARRAY_LEFT; | 656 | format->height, &ret); |
| 871 | sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; | ||
| 872 | sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; | ||
| 873 | 657 | ||
| 874 | return 0; | 658 | cci_write(imx219->regmap, IMX219_REG_CSI_DATA_FORMAT_A, |
| 875 | } | 659 | (bpp << 8) | bpp, &ret); |
| 660 | cci_write(imx219->regmap, IMX219_REG_OPPXCK_DIV, bpp, &ret); | ||
| 876 | 661 | ||
| 877 | return -EINVAL; | 662 | return ret; |
| 878 | } | 663 | } |
| 879 | 664 | ||
| 880 | static int imx219_configure_lanes(struct imx219 *imx219) | 665 | static int imx219_configure_lanes(struct imx219 *imx219) |
| 881 | { | 666 | { |
| 882 | return imx219_write_reg(imx219, IMX219_REG_CSI_LANE_MODE, | 667 | return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE, |
| 883 | IMX219_REG_VALUE_08BIT, (imx219->lanes == 2) ? | 668 | imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE : |
| 884 | IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE); | 669 | IMX219_CSI_4_LANE_MODE, NULL); |
| 885 | }; | 670 | }; |
| 886 | 671 | ||
| 887 | static int imx219_start_streaming(struct imx219 *imx219, | 672 | static int imx219_start_streaming(struct imx219 *imx219, |
| 888 | struct v4l2_subdev_state *state) | 673 | struct v4l2_subdev_state *state) |
| 889 | { | 674 | { |
| 890 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | 675 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); |
| 891 | const struct v4l2_mbus_framefmt *format; | ||
| 892 | const struct imx219_reg_list *reg_list; | ||
| 893 | int ret; | 676 | int ret; |
| 894 | 677 | ||
| 895 | ret = pm_runtime_resume_and_get(&client->dev); | 678 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -897,7 +680,8 @@ static int imx219_start_streaming(struct imx219 *imx219, · 1 unmodified line | |||
| 897 | return ret; | 680 | return ret; |
| 898 | 681 | ||
| 899 | /* Send all registers that are common to all modes */ | 682 | /* Send all registers that are common to all modes */ |
| 900 | ret = imx219_write_regs(imx219, imx219_common_regs, ARRAY_SIZE(imx219_common_regs)); | 683 | ret = cci_multi_reg_write(imx219->regmap, imx219_common_regs, |
| 684 | ARRAY_SIZE(imx219_common_regs), NULL); | ||
| 901 | if (ret) { | 685 | if (ret) { |
| 902 | dev_err(&client->dev, "%s failed to send mfg header\n", __func__); | 686 | dev_err(&client->dev, "%s failed to send mfg header\n", __func__); |
| 903 | goto err_rpm_put; | 687 | goto err_rpm_put; |
| @@ -910,37 +694,22 @@ static int imx219_start_streaming(struct imx219 *imx219, · 6 unmodified lines | |||
| 910 | goto err_rpm_put; | 694 | goto err_rpm_put; |
| 911 | } | 695 | } |
| 912 | 696 | ||
| 913 | /* Apply default values of current mode */ | 697 | /* Apply format and crop settings. */ |
| 914 | reg_list = &imx219->mode->reg_list; | 698 | ret = imx219_set_framefmt(imx219, state); |
| 915 | ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs); | ||
| 916 | if (ret) { | ||
| 917 | dev_err(&client->dev, "%s failed to set mode\n", __func__); | ||
| 918 | goto err_rpm_put; | ||
| 919 | } | ||
| 920 | |||
| 921 | format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0); | ||
| 922 | ret = imx219_set_framefmt(imx219, format); | ||
| 923 | if (ret) { | 699 | if (ret) { |
| 924 | dev_err(&client->dev, "%s failed to set frame format: %d\n", | 700 | dev_err(&client->dev, "%s failed to set frame format: %d\n", |
| 925 | __func__, ret); | 701 | __func__, ret); |
| 926 | goto err_rpm_put; | 702 | goto err_rpm_put; |
| 927 | } | 703 | } |
| 928 | 704 | ||
| 929 | ret = imx219_set_binning(imx219, format); | ||
| 930 | if (ret) { | ||
| 931 | dev_err(&client->dev, "%s failed to set binning: %d\n", | ||
| 932 | __func__, ret); | ||
| 933 | goto err_rpm_put; | ||
| 934 | } | ||
| 935 | |||
| 936 | /* Apply customized values from user */ | 705 | /* Apply customized values from user */ |
| 937 | ret = __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler); | 706 | ret = __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler); |
| 938 | if (ret) | 707 | if (ret) |
| 939 | goto err_rpm_put; | 708 | goto err_rpm_put; |
| 940 | 709 | ||
| 941 | /* set stream on register */ | 710 | /* set stream on register */ |
| 942 | ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | 711 | ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, |
| 943 | IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING); | 712 | IMX219_MODE_STREAMING, NULL); |
| 944 | if (ret) | 713 | if (ret) |
| 945 | goto err_rpm_put; | 714 | goto err_rpm_put; |
| 946 | 715 | ||
| @@ -961,8 +730,8 @@ static void imx219_stop_streaming(struct imx219 *imx219) · 14 unmodified lines | |||
| 961 | int ret; | 730 | int ret; |
| 962 | 731 | ||
| 963 | /* set stream off register */ | 732 | /* set stream off register */ |
| 964 | ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | 733 | ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, |
| 965 | IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY); | 734 | IMX219_MODE_STANDBY, NULL); |
| 966 | if (ret) | 735 | if (ret) |
| 967 | dev_err(&client->dev, "%s failed to set stream\n", __func__); | 736 | dev_err(&client->dev, "%s failed to set stream\n", __func__); |
| 968 | 737 | ||
| @@ -980,142 +749,176 @@ static int imx219_set_stream(struct v4l2_subdev *sd, int enable) · 11 unmodified lines | |||
| 980 | 749 | ||
| 981 | state = v4l2_subdev_lock_and_get_active_state(sd); | 750 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| 982 | 751 | ||
| 983 | if (imx219->streaming == enable) | 752 | if (enable) |
| 984 | goto unlock; | ||
| 985 | |||
| 986 | if (enable) { | ||
| 987 | /* | ||
| 988 | * Apply default & customized values | ||
| 989 | * and then start streaming. | ||
| 990 | */ | ||
| 991 | ret = imx219_start_streaming(imx219, state); | 753 | ret = imx219_start_streaming(imx219, state); |
| 992 | if (ret) | 754 | else |
| 993 | goto unlock; | ||
| 994 | } else { | ||
| 995 | imx219_stop_streaming(imx219); | 755 | imx219_stop_streaming(imx219); |
| 996 | } | ||
| 997 | |||
| 998 | imx219->streaming = enable; | ||
| 999 | 756 | ||
| 1000 | unlock: | ||
| 1001 | v4l2_subdev_unlock_state(state); | 757 | v4l2_subdev_unlock_state(state); |
| 1002 | return ret; | 758 | return ret; |
| 1003 | } | 759 | } |
| 1004 | 760 | ||
| 1005 | /* Power/clock management functions */ | 761 | static void imx219_update_pad_format(struct imx219 *imx219, |
| 1006 | static int imx219_power_on(struct device *dev) | 762 | const struct imx219_mode *mode, |
| 763 | struct v4l2_mbus_framefmt *fmt, u32 code) | ||
| 1007 | { | 764 | { |
| 1008 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | 765 | /* Bayer order varies with flips */ |
| 1009 | struct imx219 *imx219 = to_imx219(sd); | 766 | fmt->code = imx219_get_format_code(imx219, code); |
| 1010 | int ret; | 767 | fmt->width = mode->width; |
| 768 | fmt->height = mode->height; | ||
| 769 | fmt->field = V4L2_FIELD_NONE; | ||
| 770 | fmt->colorspace = V4L2_COLORSPACE_RAW; | ||
| 771 | fmt->ycbcr_enc = V4L2_YCBCR_ENC_601; | ||
| 772 | fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; | ||
| 773 | fmt->xfer_func = V4L2_XFER_FUNC_NONE; | ||
| 774 | } | ||
| 1011 | 775 | ||
| 1012 | ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES, | 776 | static int imx219_enum_mbus_code(struct v4l2_subdev *sd, |
| 1013 | imx219->supplies); | 777 | struct v4l2_subdev_state *state, |
| 1014 | if (ret) { | 778 | struct v4l2_subdev_mbus_code_enum *code) |
| 1015 | dev_err(dev, "%s: failed to enable regulators\n", | 779 | { |
| 1016 | __func__); | 780 | struct imx219 *imx219 = to_imx219(sd); |
| 1017 | return ret; | ||
| 1018 | } | ||
| 1019 | 781 | ||
| 1020 | ret = clk_prepare_enable(imx219->xclk); | 782 | if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4)) |
| 1021 | if (ret) { | 783 | return -EINVAL; |
| 1022 | dev_err(dev, "%s: failed to enable clock\n", | ||
| 1023 | __func__); | ||
| 1024 | goto reg_off; | ||
| 1025 | } | ||
| 1026 | 784 | ||
| 1027 | gpiod_set_value_cansleep(imx219->reset_gpio, 1); | 785 | code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]); |
| 1028 | usleep_range(IMX219_XCLR_MIN_DELAY_US, | ||
| 1029 | IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US); | ||
| 1030 | 786 | ||
| 1031 | return 0; | 787 | return 0; |
| 1032 | |||
| 1033 | reg_off: | ||
| 1034 | regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); | ||
| 1035 | |||
| 1036 | return ret; | ||
| 1037 | } | 788 | } |
| 1038 | 789 | ||
| 1039 | static int imx219_power_off(struct device *dev) | 790 | static int imx219_enum_frame_size(struct v4l2_subdev *sd, |
| 791 | struct v4l2_subdev_state *state, | ||
| 792 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 1040 | { | 793 | { |
| 1041 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1042 | struct imx219 *imx219 = to_imx219(sd); | 794 | struct imx219 *imx219 = to_imx219(sd); |
| 795 | u32 code; | ||
| 1043 | 796 | ||
| 1044 | gpiod_set_value_cansleep(imx219->reset_gpio, 0); | 797 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
| 1045 | regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); | 798 | return -EINVAL; |
| 1046 | clk_disable_unprepare(imx219->xclk); | 799 | |
| 800 | code = imx219_get_format_code(imx219, fse->code); | ||
| 801 | if (fse->code != code) | ||
| 802 | return -EINVAL; | ||
| 803 | |||
| 804 | fse->min_width = supported_modes[fse->index].width; | ||
| 805 | fse->max_width = fse->min_width; | ||
| 806 | fse->min_height = supported_modes[fse->index].height; | ||
| 807 | fse->max_height = fse->min_height; | ||
| 1047 | 808 | ||
| 1048 | return 0; | 809 | return 0; |
| 1049 | } | 810 | } |
| 1050 | 811 | ||
| 1051 | static int __maybe_unused imx219_suspend(struct device *dev) | 812 | static int imx219_set_pad_format(struct v4l2_subdev *sd, |
| 813 | struct v4l2_subdev_state *state, | ||
| 814 | struct v4l2_subdev_format *fmt) | ||
| 1052 | { | 815 | { |
| 1053 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1054 | struct imx219 *imx219 = to_imx219(sd); | 816 | struct imx219 *imx219 = to_imx219(sd); |
| 817 | const struct imx219_mode *mode; | ||
| 818 | struct v4l2_mbus_framefmt *format; | ||
| 819 | struct v4l2_rect *crop; | ||
| 820 | unsigned int bin_h, bin_v; | ||
| 1055 | 821 | ||
| 1056 | if (imx219->streaming) | 822 | mode = v4l2_find_nearest_size(supported_modes, |
| 1057 | imx219_stop_streaming(imx219); | 823 | ARRAY_SIZE(supported_modes), |
| 824 | width, height, | ||
| 825 | fmt->format.width, fmt->format.height); | ||
| 1058 | 826 | ||
| 1059 | return 0; | 827 | imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); |
| 1060 | } | ||
| 1061 | 828 | ||
| 1062 | static int __maybe_unused imx219_resume(struct device *dev) | 829 | format = v4l2_subdev_get_pad_format(sd, state, 0); |
| 1063 | { | 830 | *format = fmt->format; |
| 1064 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1065 | struct imx219 *imx219 = to_imx219(sd); | ||
| 1066 | struct v4l2_subdev_state *state; | ||
| 1067 | int ret; | ||
| 1068 | 831 | ||
| 1069 | if (imx219->streaming) { | 832 | /* |
| 1070 | state = v4l2_subdev_lock_and_get_active_state(sd); | 833 | * Use binning to maximize the crop rectangle size, and centre it in the |
| 1071 | ret = imx219_start_streaming(imx219, state); | 834 | * sensor. |
| 1072 | v4l2_subdev_unlock_state(state); | 835 | */ |
| 1073 | if (ret) | 836 | bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U); |
| 1074 | goto error; | 837 | bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U); |
| 1075 | } | ||
| 1076 | 838 | ||
| 1077 | return 0; | 839 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); |
| 840 | crop->width = format->width * bin_h; | ||
| 841 | crop->height = format->height * bin_v; | ||
| 842 | crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2; | ||
| 843 | crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2; | ||
| 1078 | 844 | ||
| 1079 | error: | 845 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { |
| 1080 | imx219_stop_streaming(imx219); | 846 | int exposure_max; |
| 1081 | imx219->streaming = false; | 847 | int exposure_def; |
| 848 | int hblank; | ||
| 1082 | 849 | ||
| 1083 | return ret; | 850 | /* Update limits and set FPS to default */ |
| 851 | __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN, | ||
| 852 | IMX219_VTS_MAX - mode->height, 1, | ||
| 853 | mode->vts_def - mode->height); | ||
| 854 | __v4l2_ctrl_s_ctrl(imx219->vblank, | ||
| 855 | mode->vts_def - mode->height); | ||
| 856 | /* Update max exposure while meeting expected vblanking */ | ||
| 857 | exposure_max = mode->vts_def - 4; | ||
| 858 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? | ||
| 859 | exposure_max : IMX219_EXPOSURE_DEFAULT; | ||
| 860 | __v4l2_ctrl_modify_range(imx219->exposure, | ||
| 861 | imx219->exposure->minimum, | ||
| 862 | exposure_max, imx219->exposure->step, | ||
| 863 | exposure_def); | ||
| 864 | /* | ||
| 865 | * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank | ||
| 866 | * depends on mode->width only, and is not changeble in any | ||
| 867 | * way other than changing the mode. | ||
| 868 | */ | ||
| 869 | hblank = IMX219_PPL_DEFAULT - mode->width; | ||
| 870 | __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1, | ||
| 871 | hblank); | ||
| 872 | } | ||
| 873 | |||
| 874 | return 0; | ||
| 1084 | } | 875 | } |
| 1085 | 876 | ||
| 1086 | static int imx219_get_regulators(struct imx219 *imx219) | 877 | static int imx219_get_selection(struct v4l2_subdev *sd, |
| 878 | struct v4l2_subdev_state *state, | ||
| 879 | struct v4l2_subdev_selection *sel) | ||
| 1087 | { | 880 | { |
| 1088 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | 881 | switch (sel->target) { |
| 1089 | unsigned int i; | 882 | case V4L2_SEL_TGT_CROP: { |
| 883 | sel->r = *v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 884 | return 0; | ||
| 885 | } | ||
| 1090 | 886 | ||
| 1091 | for (i = 0; i < IMX219_NUM_SUPPLIES; i++) | 887 | case V4L2_SEL_TGT_NATIVE_SIZE: |
| 1092 | imx219->supplies[i].supply = imx219_supply_name[i]; | 888 | sel->r.top = 0; |
| 889 | sel->r.left = 0; | ||
| 890 | sel->r.width = IMX219_NATIVE_WIDTH; | ||
| 891 | sel->r.height = IMX219_NATIVE_HEIGHT; | ||
| 1093 | 892 | ||
| 1094 | return devm_regulator_bulk_get(&client->dev, | 893 | return 0; |
| 1095 | IMX219_NUM_SUPPLIES, | ||
| 1096 | imx219->supplies); | ||
| 1097 | } | ||
| 1098 | 894 | ||
| 1099 | /* Verify chip ID */ | 895 | case V4L2_SEL_TGT_CROP_DEFAULT: |
| 1100 | static int imx219_identify_module(struct imx219 *imx219) | 896 | case V4L2_SEL_TGT_CROP_BOUNDS: |
| 1101 | { | 897 | sel->r.top = IMX219_PIXEL_ARRAY_TOP; |
| 1102 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | 898 | sel->r.left = IMX219_PIXEL_ARRAY_LEFT; |
| 1103 | int ret; | 899 | sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; |
| 1104 | u32 val; | 900 | sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; |
| 1105 | 901 | ||
| 1106 | ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID, | 902 | return 0; |
| 1107 | IMX219_REG_VALUE_16BIT, &val); | ||
| 1108 | if (ret) { | ||
| 1109 | dev_err(&client->dev, "failed to read chip id %x\n", | ||
| 1110 | IMX219_CHIP_ID); | ||
| 1111 | return ret; | ||
| 1112 | } | 903 | } |
| 1113 | 904 | ||
| 1114 | if (val != IMX219_CHIP_ID) { | 905 | return -EINVAL; |
| 1115 | dev_err(&client->dev, "chip id mismatch: %x!=%x\n", | 906 | } |
| 1116 | IMX219_CHIP_ID, val); | 907 | |
| 1117 | return -EIO; | 908 | static int imx219_init_cfg(struct v4l2_subdev *sd, |
| 1118 | } | 909 | struct v4l2_subdev_state *state) |
| 910 | { | ||
| 911 | struct v4l2_subdev_format fmt = { | ||
| 912 | .which = V4L2_SUBDEV_FORMAT_TRY, | ||
| 913 | .pad = 0, | ||
| 914 | .format = { | ||
| 915 | .code = MEDIA_BUS_FMT_SRGGB10_1X10, | ||
| 916 | .width = supported_modes[0].width, | ||
| 917 | .height = supported_modes[0].height, | ||
| 918 | }, | ||
| 919 | }; | ||
| 920 | |||
| 921 | imx219_set_pad_format(sd, state, &fmt); | ||
| 1119 | 922 | ||
| 1120 | return 0; | 923 | return 0; |
| 1121 | } | 924 | } |
| @@ -1145,129 +948,93 @@ static const struct v4l2_subdev_ops imx219_subdev_ops = { · 23 unmodified lines | |||
| 1145 | }; | 948 | }; |
| 1146 | 949 | ||
| 1147 | 950 | ||
| 1148 | static unsigned long imx219_get_pixel_rate(struct imx219 *imx219) | 951 | /* ----------------------------------------------------------------------------- |
| 1149 | { | 952 | * Power management |
| 1150 | return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; | 953 | */ |
| 1151 | } | ||
| 1152 | 954 | ||
| 1153 | /* Initialize control handlers */ | 955 | static int imx219_power_on(struct device *dev) |
| 1154 | static int imx219_init_controls(struct imx219 *imx219) | ||
| 1155 | { | 956 | { |
| 1156 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | 957 | struct v4l2_subdev *sd = dev_get_drvdata(dev); |
| 1157 | struct v4l2_ctrl_handler *ctrl_hdlr; | 958 | struct imx219 *imx219 = to_imx219(sd); |
| 1158 | unsigned int height = imx219->mode->height; | 959 | int ret; |
| 1159 | struct v4l2_fwnode_device_properties props; | ||
| 1160 | int exposure_max, exposure_def, hblank; | ||
| 1161 | int i, ret; | ||
| 1162 | 960 | ||
| 1163 | ctrl_hdlr = &imx219->ctrl_handler; | 961 | ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES, |
| 1164 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); | 962 | imx219->supplies); |
| 1165 | if (ret) | 963 | if (ret) { |
| 964 | dev_err(dev, "%s: failed to enable regulators\n", | ||
| 965 | __func__); | ||
| 1166 | return ret; | 966 | return ret; |
| 967 | } | ||
| 1167 | 968 | ||
| 1168 | /* By default, PIXEL_RATE is read only */ | 969 | ret = clk_prepare_enable(imx219->xclk); |
| 1169 | imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | 970 | if (ret) { |
| 1170 | V4L2_CID_PIXEL_RATE, | 971 | dev_err(dev, "%s: failed to enable clock\n", |
| 1171 | imx219_get_pixel_rate(imx219), | 972 | __func__); |
| 1172 | imx219_get_pixel_rate(imx219), 1, | 973 | goto reg_off; |
| 1173 | imx219_get_pixel_rate(imx219)); | 974 | } |
| 1174 | 975 | ||
| 1175 | imx219->link_freq = | 976 | gpiod_set_value_cansleep(imx219->reset_gpio, 1); |
| 1176 | v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, | 977 | usleep_range(IMX219_XCLR_MIN_DELAY_US, |
| 1177 | V4L2_CID_LINK_FREQ, | 978 | IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US); |
| 1178 | ARRAY_SIZE(imx219_link_freq_menu) - 1, 0, | ||
| 1179 | (imx219->lanes == 2) ? imx219_link_freq_menu : | ||
| 1180 | imx219_link_freq_4lane_menu); | ||
| 1181 | if (imx219->link_freq) | ||
| 1182 | imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 1183 | 979 | ||
| 1184 | /* Initial vblank/hblank/exposure parameters based on current mode */ | 980 | return 0; |
| 1185 | imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 1186 | V4L2_CID_VBLANK, IMX219_VBLANK_MIN, | ||
| 1187 | IMX219_VTS_MAX - height, 1, | ||
| 1188 | imx219->mode->vts_def - height); | ||
| 1189 | hblank = IMX219_PPL_DEFAULT - imx219->mode->width; | ||
| 1190 | imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 1191 | V4L2_CID_HBLANK, hblank, hblank, | ||
| 1192 | 1, hblank); | ||
| 1193 | if (imx219->hblank) | ||
| 1194 | imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 1195 | exposure_max = imx219->mode->vts_def - 4; | ||
| 1196 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? | ||
| 1197 | exposure_max : IMX219_EXPOSURE_DEFAULT; | ||
| 1198 | imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 1199 | V4L2_CID_EXPOSURE, | ||
| 1200 | IMX219_EXPOSURE_MIN, exposure_max, | ||
| 1201 | IMX219_EXPOSURE_STEP, | ||
| 1202 | exposure_def); | ||
| 1203 | 981 | ||
| 1204 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, | 982 | reg_off: |
| 1205 | IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX, | 983 | regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); |
| 1206 | IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT); | ||
| 1207 | 984 | ||
| 1208 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN, | 985 | return ret; |
| 1209 | IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX, | 986 | } |
| 1210 | IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT); | ||
| 1211 | 987 | ||
| 1212 | imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | 988 | static int imx219_power_off(struct device *dev) |
| 1213 | V4L2_CID_HFLIP, 0, 1, 1, 0); | 989 | { |
| 1214 | if (imx219->hflip) | 990 | struct v4l2_subdev *sd = dev_get_drvdata(dev); |
| 1215 | imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | 991 | struct imx219 *imx219 = to_imx219(sd); |
| 1216 | 992 | ||
| 1217 | imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | 993 | gpiod_set_value_cansleep(imx219->reset_gpio, 0); |
| 1218 | V4L2_CID_VFLIP, 0, 1, 1, 0); | 994 | regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); |
| 1219 | if (imx219->vflip) | 995 | clk_disable_unprepare(imx219->xclk); |
| 1220 | imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | ||
| 1221 | 996 | ||
| 1222 | v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, | 997 | return 0; |
| 1223 | V4L2_CID_TEST_PATTERN, | 998 | } |
| 1224 | ARRAY_SIZE(imx219_test_pattern_menu) - 1, | ||
| 1225 | 0, 0, imx219_test_pattern_menu); | ||
| 1226 | for (i = 0; i < 4; i++) { | ||
| 1227 | /* | ||
| 1228 | * The assumption is that | ||
| 1229 | * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1 | ||
| 1230 | * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2 | ||
| 1231 | * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3 | ||
| 1232 | */ | ||
| 1233 | v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | ||
| 1234 | V4L2_CID_TEST_PATTERN_RED + i, | ||
| 1235 | IMX219_TESTP_COLOUR_MIN, | ||
| 1236 | IMX219_TESTP_COLOUR_MAX, | ||
| 1237 | IMX219_TESTP_COLOUR_STEP, | ||
| 1238 | IMX219_TESTP_COLOUR_MAX); | ||
| 1239 | /* The "Solid color" pattern is white by default */ | ||
| 1240 | } | ||
| 1241 | 999 | ||
| 1242 | if (ctrl_hdlr->error) { | 1000 | /* ----------------------------------------------------------------------------- |
| 1243 | ret = ctrl_hdlr->error; | 1001 | * Probe & remove |
| 1244 | dev_err(&client->dev, "%s control init failed (%d)\n", | 1002 | */ |
| 1245 | __func__, ret); | ||
| 1246 | goto error; | ||
| 1247 | } | ||
| 1248 | 1003 | ||
| 1249 | ret = v4l2_fwnode_device_parse(&client->dev, &props); | 1004 | static int imx219_get_regulators(struct imx219 *imx219) |
| 1250 | if (ret) | 1005 | { |
| 1251 | goto error; | 1006 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); |
| 1007 | unsigned int i; | ||
| 1252 | 1008 | ||
| 1253 | ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, | 1009 | for (i = 0; i < IMX219_NUM_SUPPLIES; i++) |
| 1254 | &props); | 1010 | imx219->supplies[i].supply = imx219_supply_name[i]; |
| 1255 | if (ret) | ||
| 1256 | goto error; | ||
| 1257 | 1011 | ||
| 1258 | imx219->sd.ctrl_handler = ctrl_hdlr; | 1012 | return devm_regulator_bulk_get(&client->dev, |
| 1013 | IMX219_NUM_SUPPLIES, | ||
| 1014 | imx219->supplies); | ||
| 1015 | } | ||
| 1259 | 1016 | ||
| 1260 | return 0; | 1017 | /* Verify chip ID */ |
| 1018 | static int imx219_identify_module(struct imx219 *imx219) | ||
| 1019 | { | ||
| 1020 | struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | ||
| 1021 | int ret; | ||
| 1022 | u64 val; | ||
| 1261 | 1023 | ||
| 1262 | error: | 1024 | ret = cci_read(imx219->regmap, IMX219_REG_CHIP_ID, &val, NULL); |
| 1263 | v4l2_ctrl_handler_free(ctrl_hdlr); | 1025 | if (ret) { |
| 1026 | dev_err(&client->dev, "failed to read chip id %x\n", | ||
| 1027 | IMX219_CHIP_ID); | ||
| 1028 | return ret; | ||
| 1029 | } | ||
| 1264 | 1030 | ||
| 1265 | return ret; | 1031 | if (val != IMX219_CHIP_ID) { |
| 1266 | } | 1032 | dev_err(&client->dev, "chip id mismatch: %x!=%llx\n", |
| 1033 | IMX219_CHIP_ID, val); | ||
| 1034 | return -EIO; | ||
| 1035 | } | ||
| 1267 | 1036 | ||
| 1268 | static void imx219_free_controls(struct imx219 *imx219) | 1037 | return 0; |
| 1269 | { | ||
| 1270 | v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); | ||
| 1271 | } | 1038 | } |
| 1272 | 1039 | ||
| 1273 | static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219) | 1040 | static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219) |
| @@ -1336,6 +1103,13 @@ static int imx219_probe(struct i2c_client *client) · 62 unmodified lines | |||
| 1336 | if (imx219_check_hwcfg(dev, imx219)) | 1103 | if (imx219_check_hwcfg(dev, imx219)) |
| 1337 | return -EINVAL; | 1104 | return -EINVAL; |
| 1338 | 1105 | ||
| 1106 | imx219->regmap = devm_cci_regmap_init_i2c(client, 16); | ||
| 1107 | if (IS_ERR(imx219->regmap)) { | ||
| 1108 | ret = PTR_ERR(imx219->regmap); | ||
| 1109 | dev_err(dev, "failed to initialize CCI: %d\n", ret); | ||
| 1110 | return ret; | ||
| 1111 | } | ||
| 1112 | |||
| 1339 | /* Get system clock (xclk) */ | 1113 | /* Get system clock (xclk) */ |
| 1340 | imx219->xclk = devm_clk_get(dev, NULL); | 1114 | imx219->xclk = devm_clk_get(dev, NULL); |
| 1341 | if (IS_ERR(imx219->xclk)) { | 1115 | if (IS_ERR(imx219->xclk)) { |
| @@ -1372,24 +1146,24 @@ static int imx219_probe(struct i2c_client *client) · 30 unmodified lines | |||
| 1372 | if (ret) | 1146 | if (ret) |
| 1373 | goto error_power_off; | 1147 | goto error_power_off; |
| 1374 | 1148 | ||
| 1375 | /* Set default mode to max resolution */ | 1149 | /* |
| 1376 | imx219->mode = &supported_modes[0]; | 1150 | * Sensor doesn't enter LP-11 state upon power up until and unless |
| 1377 | |||
| 1378 | /* sensor doesn't enter LP-11 state upon power up until and unless | ||
| 1379 | * streaming is started, so upon power up switch the modes to: | 1151 | * streaming is started, so upon power up switch the modes to: |
| 1380 | * streaming -> standby | 1152 | * streaming -> standby |
| 1381 | */ | 1153 | */ |
| 1382 | ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | 1154 | ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, |
| 1383 | IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING); | 1155 | IMX219_MODE_STREAMING, NULL); |
| 1384 | if (ret < 0) | 1156 | if (ret < 0) |
| 1385 | goto error_power_off; | 1157 | goto error_power_off; |
| 1158 | |||
| 1386 | usleep_range(100, 110); | 1159 | usleep_range(100, 110); |
| 1387 | 1160 | ||
| 1388 | /* put sensor back to standby mode */ | 1161 | /* put sensor back to standby mode */ |
| 1389 | ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | 1162 | ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, |
| 1390 | IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY); | 1163 | IMX219_MODE_STANDBY, NULL); |
| 1391 | if (ret < 0) | 1164 | if (ret < 0) |
| 1392 | goto error_power_off; | 1165 | goto error_power_off; |
| 1166 | |||
| 1393 | usleep_range(100, 110); | 1167 | usleep_range(100, 110); |
| 1394 | 1168 | ||
| 1395 | ret = imx219_init_controls(imx219); | 1169 | ret = imx219_init_controls(imx219); |
| @@ -1468,7 +1242,6 @@ static const struct of_device_id imx219_dt_ids[] = { · 72 unmodified lines | |||
| 1468 | MODULE_DEVICE_TABLE(of, imx219_dt_ids); | 1242 | MODULE_DEVICE_TABLE(of, imx219_dt_ids); |
| 1469 | 1243 | ||
| 1470 | static const struct dev_pm_ops imx219_pm_ops = { | 1244 | static const struct dev_pm_ops imx219_pm_ops = { |
| 1471 | SET_SYSTEM_SLEEP_PM_OPS(imx219_suspend, imx219_resume) | ||
| 1472 | SET_RUNTIME_PM_OPS(imx219_power_off, imx219_power_on, NULL) | 1245 | SET_RUNTIME_PM_OPS(imx219_power_off, imx219_power_on, NULL) |
| 1473 | }; | 1246 | }; |
| 1474 | 1247 | ||
| @@ -622,9 +622,6 @@ struct imx258 { · 621 unmodified lines | |||
| 622 | */ | 622 | */ |
| 623 | struct mutex mutex; | 623 | struct mutex mutex; |
| 624 | 624 | ||
| 625 | /* Streaming on/off */ | ||
| 626 | bool streaming; | ||
| 627 | |||
| 628 | struct clk *clk; | 625 | struct clk *clk; |
| 629 | }; | 626 | }; |
| 630 | 627 | ||
| @@ -1035,10 +1032,6 @@ static int imx258_set_stream(struct v4l2_subdev *sd, int enable) · 404 unmodified lines | |||
| 1035 | int ret = 0; | 1032 | int ret = 0; |
| 1036 | 1033 | ||
| 1037 | mutex_lock(&imx258->mutex); | 1034 | mutex_lock(&imx258->mutex); |
| 1038 | if (imx258->streaming == enable) { | ||
| 1039 | mutex_unlock(&imx258->mutex); | ||
| 1040 | return 0; | ||
| 1041 | } | ||
| 1042 | 1035 | ||
| 1043 | if (enable) { | 1036 | if (enable) { |
| 1044 | ret = pm_runtime_resume_and_get(&client->dev); | 1037 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -1057,7 +1050,6 @@ static int imx258_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 1057 | pm_runtime_put(&client->dev); | 1050 | pm_runtime_put(&client->dev); |
| 1058 | } | 1051 | } |
| 1059 | 1052 | ||
| 1060 | imx258->streaming = enable; | ||
| 1061 | mutex_unlock(&imx258->mutex); | 1053 | mutex_unlock(&imx258->mutex); |
| 1062 | 1054 | ||
| 1063 | return ret; | 1055 | return ret; |
| @@ -1070,37 +1062,6 @@ err_unlock: · 6 unmodified lines | |||
| 1070 | return ret; | 1062 | return ret; |
| 1071 | } | 1063 | } |
| 1072 | 1064 | ||
| 1073 | static int __maybe_unused imx258_suspend(struct device *dev) | ||
| 1074 | { | ||
| 1075 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1076 | struct imx258 *imx258 = to_imx258(sd); | ||
| 1077 | |||
| 1078 | if (imx258->streaming) | ||
| 1079 | imx258_stop_streaming(imx258); | ||
| 1080 | |||
| 1081 | return 0; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | static int __maybe_unused imx258_resume(struct device *dev) | ||
| 1085 | { | ||
| 1086 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1087 | struct imx258 *imx258 = to_imx258(sd); | ||
| 1088 | int ret; | ||
| 1089 | |||
| 1090 | if (imx258->streaming) { | ||
| 1091 | ret = imx258_start_streaming(imx258); | ||
| 1092 | if (ret) | ||
| 1093 | goto error; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | return 0; | ||
| 1097 | |||
| 1098 | error: | ||
| 1099 | imx258_stop_streaming(imx258); | ||
| 1100 | imx258->streaming = 0; | ||
| 1101 | return ret; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | /* Verify chip ID */ | 1065 | /* Verify chip ID */ |
| 1105 | static int imx258_identify_module(struct imx258 *imx258) | 1066 | static int imx258_identify_module(struct imx258 *imx258) |
| 1106 | { | 1067 | { |
| @@ -1369,7 +1330,6 @@ static void imx258_remove(struct i2c_client *client) · 262 unmodified lines | |||
| 1369 | } | 1330 | } |
| 1370 | 1331 | ||
| 1371 | static const struct dev_pm_ops imx258_pm_ops = { | 1332 | static const struct dev_pm_ops imx258_pm_ops = { |
| 1372 | SET_SYSTEM_SLEEP_PM_OPS(imx258_suspend, imx258_resume) | ||
| 1373 | SET_RUNTIME_PM_OPS(imx258_power_off, imx258_power_on, NULL) | 1333 | SET_RUNTIME_PM_OPS(imx258_power_off, imx258_power_on, NULL) |
| 1374 | }; | 1334 | }; |
| 1375 | 1335 | ||
| @@ -201,8 +201,6 @@ struct imx296 { · 200 unmodified lines | |||
| 201 | const struct imx296_clk_params *clk_params; | 201 | const struct imx296_clk_params *clk_params; |
| 202 | bool mono; | 202 | bool mono; |
| 203 | 203 | ||
| 204 | bool streaming; | ||
| 205 | |||
| 206 | struct v4l2_subdev subdev; | 204 | struct v4l2_subdev subdev; |
| 207 | struct media_pad pad; | 205 | struct media_pad pad; |
| 208 | 206 | ||
| @@ -321,7 +319,7 @@ static int imx296_s_ctrl(struct v4l2_ctrl *ctrl) · 112 unmodified lines | |||
| 321 | unsigned int vmax; | 319 | unsigned int vmax; |
| 322 | int ret = 0; | 320 | int ret = 0; |
| 323 | 321 | ||
| 324 | if (!sensor->streaming) | 322 | if (!pm_runtime_get_if_in_use(sensor->dev)) |
| 325 | return 0; | 323 | return 0; |
| 326 | 324 | ||
| 327 | state = v4l2_subdev_get_locked_active_state(&sensor->subdev); | 325 | state = v4l2_subdev_get_locked_active_state(&sensor->subdev); |
| @@ -376,6 +374,8 @@ static int imx296_s_ctrl(struct v4l2_ctrl *ctrl) · 48 unmodified lines | |||
| 376 | break; | 374 | break; |
| 377 | } | 375 | } |
| 378 | 376 | ||
| 377 | pm_runtime_put(sensor->dev); | ||
| 378 | |||
| 379 | return ret; | 379 | return ret; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| @@ -607,8 +607,6 @@ static int imx296_s_stream(struct v4l2_subdev *sd, int enable) · 225 unmodified lines | |||
| 607 | pm_runtime_mark_last_busy(sensor->dev); | 607 | pm_runtime_mark_last_busy(sensor->dev); |
| 608 | pm_runtime_put_autosuspend(sensor->dev); | 608 | pm_runtime_put_autosuspend(sensor->dev); |
| 609 | 609 | ||
| 610 | sensor->streaming = false; | ||
| 611 | |||
| 612 | goto unlock; | 610 | goto unlock; |
| 613 | } | 611 | } |
| 614 | 612 | ||
| @@ -620,13 +618,6 @@ static int imx296_s_stream(struct v4l2_subdev *sd, int enable) · 5 unmodified lines | |||
| 620 | if (ret < 0) | 618 | if (ret < 0) |
| 621 | goto err_pm; | 619 | goto err_pm; |
| 622 | 620 | ||
| 623 | /* | ||
| 624 | * Set streaming to true to ensure __v4l2_ctrl_handler_setup() will set | ||
| 625 | * the controls. The flag is reset to false further down if an error | ||
| 626 | * occurs. | ||
| 627 | */ | ||
| 628 | sensor->streaming = true; | ||
| 629 | |||
| 630 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); | 621 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); |
| 631 | if (ret < 0) | 622 | if (ret < 0) |
| 632 | goto err_pm; | 623 | goto err_pm; |
| @@ -646,7 +637,6 @@ err_pm: · 13 unmodified lines | |||
| 646 | * likely has no other chance to recover. | 637 | * likely has no other chance to recover. |
| 647 | */ | 638 | */ |
| 648 | pm_runtime_put_sync(sensor->dev); | 639 | pm_runtime_put_sync(sensor->dev); |
| 649 | sensor->streaming = false; | ||
| 650 | 640 | ||
| 651 | goto unlock; | 641 | goto unlock; |
| 652 | } | 642 | } |
| @@ -138,8 +138,6 @@ struct imx319 { · 137 unmodified lines | |||
| 138 | */ | 138 | */ |
| 139 | struct mutex mutex; | 139 | struct mutex mutex; |
| 140 | 140 | ||
| 141 | /* Streaming on/off */ | ||
| 142 | bool streaming; | ||
| 143 | /* True if the device has been identified */ | 141 | /* True if the device has been identified */ |
| 144 | bool identified; | 142 | bool identified; |
| 145 | }; | 143 | }; |
| @@ -2166,10 +2164,6 @@ static int imx319_set_stream(struct v4l2_subdev *sd, int enable) · 2020 unmodified lines | |||
| 2166 | int ret = 0; | 2164 | int ret = 0; |
| 2167 | 2165 | ||
| 2168 | mutex_lock(&imx319->mutex); | 2166 | mutex_lock(&imx319->mutex); |
| 2169 | if (imx319->streaming == enable) { | ||
| 2170 | mutex_unlock(&imx319->mutex); | ||
| 2171 | return 0; | ||
| 2172 | } | ||
| 2173 | 2167 | ||
| 2174 | if (enable) { | 2168 | if (enable) { |
| 2175 | ret = pm_runtime_resume_and_get(&client->dev); | 2169 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -2188,8 +2182,6 @@ static int imx319_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 2188 | pm_runtime_put(&client->dev); | 2182 | pm_runtime_put(&client->dev); |
| 2189 | } | 2183 | } |
| 2190 | 2184 | ||
| 2191 | imx319->streaming = enable; | ||
| 2192 | |||
| 2193 | /* vflip and hflip cannot change during streaming */ | 2185 | /* vflip and hflip cannot change during streaming */ |
| 2194 | __v4l2_ctrl_grab(imx319->vflip, enable); | 2186 | __v4l2_ctrl_grab(imx319->vflip, enable); |
| 2195 | __v4l2_ctrl_grab(imx319->hflip, enable); | 2187 | __v4l2_ctrl_grab(imx319->hflip, enable); |
| @@ -2206,37 +2198,6 @@ err_unlock: · 10 unmodified lines | |||
| 2206 | return ret; | 2198 | return ret; |
| 2207 | } | 2199 | } |
| 2208 | 2200 | ||
| 2209 | static int __maybe_unused imx319_suspend(struct device *dev) | ||
| 2210 | { | ||
| 2211 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2212 | struct imx319 *imx319 = to_imx319(sd); | ||
| 2213 | |||
| 2214 | if (imx319->streaming) | ||
| 2215 | imx319_stop_streaming(imx319); | ||
| 2216 | |||
| 2217 | return 0; | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | static int __maybe_unused imx319_resume(struct device *dev) | ||
| 2221 | { | ||
| 2222 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2223 | struct imx319 *imx319 = to_imx319(sd); | ||
| 2224 | int ret; | ||
| 2225 | |||
| 2226 | if (imx319->streaming) { | ||
| 2227 | ret = imx319_start_streaming(imx319); | ||
| 2228 | if (ret) | ||
| 2229 | goto error; | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | return 0; | ||
| 2233 | |||
| 2234 | error: | ||
| 2235 | imx319_stop_streaming(imx319); | ||
| 2236 | imx319->streaming = 0; | ||
| 2237 | return ret; | ||
| 2238 | } | ||
| 2239 | |||
| 2240 | static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = { | 2201 | static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = { |
| 2241 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, | 2202 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
| 2242 | .unsubscribe_event = v4l2_event_subdev_unsubscribe, | 2203 | .unsubscribe_event = v4l2_event_subdev_unsubscribe, |
| @@ -2542,10 +2503,6 @@ static void imx319_remove(struct i2c_client *client) · 299 unmodified lines | |||
| 2542 | mutex_destroy(&imx319->mutex); | 2503 | mutex_destroy(&imx319->mutex); |
| 2543 | } | 2504 | } |
| 2544 | 2505 | ||
| 2545 | static const struct dev_pm_ops imx319_pm_ops = { | ||
| 2546 | SET_SYSTEM_SLEEP_PM_OPS(imx319_suspend, imx319_resume) | ||
| 2547 | }; | ||
| 2548 | |||
| 2549 | static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = { | 2506 | static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = { |
| 2550 | { "SONY319A" }, | 2507 | { "SONY319A" }, |
| 2551 | { /* sentinel */ } | 2508 | { /* sentinel */ } |
| @@ -2555,7 +2512,6 @@ MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids); · 3 unmodified lines | |||
| 2555 | static struct i2c_driver imx319_i2c_driver = { | 2512 | static struct i2c_driver imx319_i2c_driver = { |
| 2556 | .driver = { | 2513 | .driver = { |
| 2557 | .name = "imx319", | 2514 | .name = "imx319", |
| 2558 | .pm = &imx319_pm_ops, | ||
| 2559 | .acpi_match_table = ACPI_PTR(imx319_acpi_ids), | 2515 | .acpi_match_table = ACPI_PTR(imx319_acpi_ids), |
| 2560 | }, | 2516 | }, |
| 2561 | .probe = imx319_probe, | 2517 | .probe = imx319_probe, |
| @@ -56,6 +56,24 @@ · 55 unmodified lines | |||
| 56 | #define IMX334_REG_MIN 0x00 | 56 | #define IMX334_REG_MIN 0x00 |
| 57 | #define IMX334_REG_MAX 0xfffff | 57 | #define IMX334_REG_MAX 0xfffff |
| 58 | 58 | ||
| 59 | /* Test Pattern Control */ | ||
| 60 | #define IMX334_REG_TP 0x329e | ||
| 61 | #define IMX334_TP_COLOR_HBARS 0xA | ||
| 62 | #define IMX334_TP_COLOR_VBARS 0xB | ||
| 63 | |||
| 64 | #define IMX334_TPG_EN_DOUT 0x329c | ||
| 65 | #define IMX334_TP_ENABLE 0x1 | ||
| 66 | #define IMX334_TP_DISABLE 0x0 | ||
| 67 | |||
| 68 | #define IMX334_TPG_COLORW 0x32a0 | ||
| 69 | #define IMX334_TPG_COLORW_120P 0x13 | ||
| 70 | |||
| 71 | #define IMX334_TP_CLK_EN 0x3148 | ||
| 72 | #define IMX334_TP_CLK_EN_VAL 0x10 | ||
| 73 | #define IMX334_TP_CLK_DIS_VAL 0x0 | ||
| 74 | |||
| 75 | #define IMX334_DIG_CLP_MODE 0x3280 | ||
| 76 | |||
| 59 | /** | 77 | /** |
| 60 | * struct imx334_reg - imx334 sensor register | 78 | * struct imx334_reg - imx334 sensor register |
| 61 | * @address: Register address | 79 | * @address: Register address |
| @@ -120,7 +138,6 @@ struct imx334_mode { · 58 unmodified lines | |||
| 120 | * @mutex: Mutex for serializing sensor controls | 138 | * @mutex: Mutex for serializing sensor controls |
| 121 | * @menu_skip_mask: Menu skip mask for link_freq_ctrl | 139 | * @menu_skip_mask: Menu skip mask for link_freq_ctrl |
| 122 | * @cur_code: current selected format code | 140 | * @cur_code: current selected format code |
| 123 | * @streaming: Flag indicating streaming state | ||
| 124 | */ | 141 | */ |
| 125 | struct imx334 { | 142 | struct imx334 { |
| 126 | struct device *dev; | 143 | struct device *dev; |
| @@ -143,7 +160,6 @@ struct imx334 { · 16 unmodified lines | |||
| 143 | struct mutex mutex; | 160 | struct mutex mutex; |
| 144 | unsigned long menu_skip_mask; | 161 | unsigned long menu_skip_mask; |
| 145 | u32 cur_code; | 162 | u32 cur_code; |
| 146 | bool streaming; | ||
| 147 | }; | 163 | }; |
| 148 | 164 | ||
| 149 | static const s64 link_freq[] = { | 165 | static const s64 link_freq[] = { |
| @@ -430,6 +446,18 @@ static const struct imx334_reg mode_3840x2160_regs[] = { · 280 unmodified lines | |||
| 430 | {0x3a29, 0x00}, | 446 | {0x3a29, 0x00}, |
| 431 | }; | 447 | }; |
| 432 | 448 | ||
| 449 | static const char * const imx334_test_pattern_menu[] = { | ||
| 450 | "Disabled", | ||
| 451 | "Vertical Color Bars", | ||
| 452 | "Horizontal Color Bars", | ||
| 453 | }; | ||
| 454 | |||
| 455 | static const int imx334_test_pattern_val[] = { | ||
| 456 | IMX334_TP_DISABLE, | ||
| 457 | IMX334_TP_COLOR_HBARS, | ||
| 458 | IMX334_TP_COLOR_VBARS, | ||
| 459 | }; | ||
| 460 | |||
| 433 | static const struct imx334_reg raw10_framefmt_regs[] = { | 461 | static const struct imx334_reg raw10_framefmt_regs[] = { |
| 434 | {0x3050, 0x00}, | 462 | {0x3050, 0x00}, |
| 435 | {0x319d, 0x00}, | 463 | {0x319d, 0x00}, |
| @@ -716,6 +744,26 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) · 280 unmodified lines | |||
| 716 | case V4L2_CID_HBLANK: | 744 | case V4L2_CID_HBLANK: |
| 717 | ret = 0; | 745 | ret = 0; |
| 718 | break; | 746 | break; |
| 747 | case V4L2_CID_TEST_PATTERN: | ||
| 748 | if (ctrl->val) { | ||
| 749 | imx334_write_reg(imx334, IMX334_TP_CLK_EN, 1, | ||
| 750 | IMX334_TP_CLK_EN_VAL); | ||
| 751 | imx334_write_reg(imx334, IMX334_DIG_CLP_MODE, 1, 0x0); | ||
| 752 | imx334_write_reg(imx334, IMX334_TPG_COLORW, 1, | ||
| 753 | IMX334_TPG_COLORW_120P); | ||
| 754 | imx334_write_reg(imx334, IMX334_REG_TP, 1, | ||
| 755 | imx334_test_pattern_val[ctrl->val]); | ||
| 756 | imx334_write_reg(imx334, IMX334_TPG_EN_DOUT, 1, | ||
| 757 | IMX334_TP_ENABLE); | ||
| 758 | } else { | ||
| 759 | imx334_write_reg(imx334, IMX334_DIG_CLP_MODE, 1, 0x1); | ||
| 760 | imx334_write_reg(imx334, IMX334_TP_CLK_EN, 1, | ||
| 761 | IMX334_TP_CLK_DIS_VAL); | ||
| 762 | imx334_write_reg(imx334, IMX334_TPG_EN_DOUT, 1, | ||
| 763 | IMX334_TP_DISABLE); | ||
| 764 | } | ||
| 765 | ret = 0; | ||
| 766 | break; | ||
| 719 | default: | 767 | default: |
| 720 | dev_err(imx334->dev, "Invalid control %d", ctrl->id); | 768 | dev_err(imx334->dev, "Invalid control %d", ctrl->id); |
| 721 | ret = -EINVAL; | 769 | ret = -EINVAL; |
| @@ -1001,11 +1049,6 @@ static int imx334_set_stream(struct v4l2_subdev *sd, int enable) · 279 unmodified lines | |||
| 1001 | 1049 | ||
| 1002 | mutex_lock(&imx334->mutex); | 1050 | mutex_lock(&imx334->mutex); |
| 1003 | 1051 | ||
| 1004 | if (imx334->streaming == enable) { | ||
| 1005 | mutex_unlock(&imx334->mutex); | ||
| 1006 | return 0; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | if (enable) { | 1052 | if (enable) { |
| 1010 | ret = pm_runtime_resume_and_get(imx334->dev); | 1053 | ret = pm_runtime_resume_and_get(imx334->dev); |
| 1011 | if (ret < 0) | 1054 | if (ret < 0) |
| @@ -1019,8 +1062,6 @@ static int imx334_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 1019 | pm_runtime_put(imx334->dev); | 1062 | pm_runtime_put(imx334->dev); |
| 1020 | } | 1063 | } |
| 1021 | 1064 | ||
| 1022 | imx334->streaming = enable; | ||
| 1023 | |||
| 1024 | mutex_unlock(&imx334->mutex); | 1065 | mutex_unlock(&imx334->mutex); |
| 1025 | 1066 | ||
| 1026 | return 0; | 1067 | return 0; |
| @@ -1222,7 +1263,7 @@ static int imx334_init_controls(struct imx334 *imx334) · 195 unmodified lines | |||
| 1222 | u32 lpfr; | 1263 | u32 lpfr; |
| 1223 | int ret; | 1264 | int ret; |
| 1224 | 1265 | ||
| 1225 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); | 1266 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 7); |
| 1226 | if (ret) | 1267 | if (ret) |
| 1227 | return ret; | 1268 | return ret; |
| 1228 | 1269 | ||
| @@ -1282,6 +1323,11 @@ static int imx334_init_controls(struct imx334 *imx334) · 53 unmodified lines | |||
| 1282 | if (imx334->hblank_ctrl) | 1323 | if (imx334->hblank_ctrl) |
| 1283 | imx334->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 1324 | imx334->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
| 1284 | 1325 | ||
| 1326 | v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx334_ctrl_ops, | ||
| 1327 | V4L2_CID_TEST_PATTERN, | ||
| 1328 | ARRAY_SIZE(imx334_test_pattern_menu) - 1, | ||
| 1329 | 0, 0, imx334_test_pattern_menu); | ||
| 1330 | |||
| 1285 | if (ctrl_hdlr->error) { | 1331 | if (ctrl_hdlr->error) { |
| 1286 | dev_err(imx334->dev, "control init failed: %d", | 1332 | dev_err(imx334->dev, "control init failed: %d", |
| 1287 | ctrl_hdlr->error); | 1333 | ctrl_hdlr->error); |
| @@ -119,7 +119,6 @@ struct imx335_mode { · 118 unmodified lines | |||
| 119 | * @vblank: Vertical blanking in lines | 119 | * @vblank: Vertical blanking in lines |
| 120 | * @cur_mode: Pointer to current selected sensor mode | 120 | * @cur_mode: Pointer to current selected sensor mode |
| 121 | * @mutex: Mutex for serializing sensor controls | 121 | * @mutex: Mutex for serializing sensor controls |
| 122 | * @streaming: Flag indicating streaming state | ||
| 123 | */ | 122 | */ |
| 124 | struct imx335 { | 123 | struct imx335 { |
| 125 | struct device *dev; | 124 | struct device *dev; |
| @@ -140,7 +139,6 @@ struct imx335 { · 14 unmodified lines | |||
| 140 | u32 vblank; | 139 | u32 vblank; |
| 141 | const struct imx335_mode *cur_mode; | 140 | const struct imx335_mode *cur_mode; |
| 142 | struct mutex mutex; | 141 | struct mutex mutex; |
| 143 | bool streaming; | ||
| 144 | }; | 142 | }; |
| 145 | 143 | ||
| 146 | static const s64 link_freq[] = { | 144 | static const s64 link_freq[] = { |
| @@ -705,11 +703,6 @@ static int imx335_set_stream(struct v4l2_subdev *sd, int enable) · 558 unmodified lines | |||
| 705 | 703 | ||
| 706 | mutex_lock(&imx335->mutex); | 704 | mutex_lock(&imx335->mutex); |
| 707 | 705 | ||
| 708 | if (imx335->streaming == enable) { | ||
| 709 | mutex_unlock(&imx335->mutex); | ||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | if (enable) { | 706 | if (enable) { |
| 714 | ret = pm_runtime_resume_and_get(imx335->dev); | 707 | ret = pm_runtime_resume_and_get(imx335->dev); |
| 715 | if (ret) | 708 | if (ret) |
| @@ -723,8 +716,6 @@ static int imx335_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 723 | pm_runtime_put(imx335->dev); | 716 | pm_runtime_put(imx335->dev); |
| 724 | } | 717 | } |
| 725 | 718 | ||
| 726 | imx335->streaming = enable; | ||
| 727 | |||
| 728 | mutex_unlock(&imx335->mutex); | 719 | mutex_unlock(&imx335->mutex); |
| 729 | 720 | ||
| 730 | return 0; | 721 | return 0; |
| @@ -123,9 +123,6 @@ struct imx355 { · 122 unmodified lines | |||
| 123 | * Protect access to sensor v4l2 controls. | 123 | * Protect access to sensor v4l2 controls. |
| 124 | */ | 124 | */ |
| 125 | struct mutex mutex; | 125 | struct mutex mutex; |
| 126 | |||
| 127 | /* Streaming on/off */ | ||
| 128 | bool streaming; | ||
| 129 | }; | 126 | }; |
| 130 | 127 | ||
| 131 | static const struct imx355_reg imx355_global_regs[] = { | 128 | static const struct imx355_reg imx355_global_regs[] = { |
| @@ -1436,10 +1433,6 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable) · 1304 unmodified lines | |||
| 1436 | int ret = 0; | 1433 | int ret = 0; |
| 1437 | 1434 | ||
| 1438 | mutex_lock(&imx355->mutex); | 1435 | mutex_lock(&imx355->mutex); |
| 1439 | if (imx355->streaming == enable) { | ||
| 1440 | mutex_unlock(&imx355->mutex); | ||
| 1441 | return 0; | ||
| 1442 | } | ||
| 1443 | 1436 | ||
| 1444 | if (enable) { | 1437 | if (enable) { |
| 1445 | ret = pm_runtime_resume_and_get(&client->dev); | 1438 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -1458,8 +1451,6 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 1458 | pm_runtime_put(&client->dev); | 1451 | pm_runtime_put(&client->dev); |
| 1459 | } | 1452 | } |
| 1460 | 1453 | ||
| 1461 | imx355->streaming = enable; | ||
| 1462 | |||
| 1463 | /* vflip and hflip cannot change during streaming */ | 1454 | /* vflip and hflip cannot change during streaming */ |
| 1464 | __v4l2_ctrl_grab(imx355->vflip, enable); | 1455 | __v4l2_ctrl_grab(imx355->vflip, enable); |
| 1465 | __v4l2_ctrl_grab(imx355->hflip, enable); | 1456 | __v4l2_ctrl_grab(imx355->hflip, enable); |
| @@ -1476,37 +1467,6 @@ err_unlock: · 10 unmodified lines | |||
| 1476 | return ret; | 1467 | return ret; |
| 1477 | } | 1468 | } |
| 1478 | 1469 | ||
| 1479 | static int __maybe_unused imx355_suspend(struct device *dev) | ||
| 1480 | { | ||
| 1481 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1482 | struct imx355 *imx355 = to_imx355(sd); | ||
| 1483 | |||
| 1484 | if (imx355->streaming) | ||
| 1485 | imx355_stop_streaming(imx355); | ||
| 1486 | |||
| 1487 | return 0; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | static int __maybe_unused imx355_resume(struct device *dev) | ||
| 1491 | { | ||
| 1492 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1493 | struct imx355 *imx355 = to_imx355(sd); | ||
| 1494 | int ret; | ||
| 1495 | |||
| 1496 | if (imx355->streaming) { | ||
| 1497 | ret = imx355_start_streaming(imx355); | ||
| 1498 | if (ret) | ||
| 1499 | goto error; | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | return 0; | ||
| 1503 | |||
| 1504 | error: | ||
| 1505 | imx355_stop_streaming(imx355); | ||
| 1506 | imx355->streaming = 0; | ||
| 1507 | return ret; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | /* Verify chip ID */ | 1470 | /* Verify chip ID */ |
| 1511 | static int imx355_identify_module(struct imx355 *imx355) | 1471 | static int imx355_identify_module(struct imx355 *imx355) |
| 1512 | { | 1472 | { |
| @@ -1829,10 +1789,6 @@ static void imx355_remove(struct i2c_client *client) · 316 unmodified lines | |||
| 1829 | mutex_destroy(&imx355->mutex); | 1789 | mutex_destroy(&imx355->mutex); |
| 1830 | } | 1790 | } |
| 1831 | 1791 | ||
| 1832 | static const struct dev_pm_ops imx355_pm_ops = { | ||
| 1833 | SET_SYSTEM_SLEEP_PM_OPS(imx355_suspend, imx355_resume) | ||
| 1834 | }; | ||
| 1835 | |||
| 1836 | static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = { | 1792 | static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = { |
| 1837 | { "SONY355A" }, | 1793 | { "SONY355A" }, |
| 1838 | { /* sentinel */ } | 1794 | { /* sentinel */ } |
| @@ -1842,7 +1798,6 @@ MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids); · 3 unmodified lines | |||
| 1842 | static struct i2c_driver imx355_i2c_driver = { | 1798 | static struct i2c_driver imx355_i2c_driver = { |
| 1843 | .driver = { | 1799 | .driver = { |
| 1844 | .name = "imx355", | 1800 | .name = "imx355", |
| 1845 | .pm = &imx355_pm_ops, | ||
| 1846 | .acpi_match_table = ACPI_PTR(imx355_acpi_ids), | 1801 | .acpi_match_table = ACPI_PTR(imx355_acpi_ids), |
| 1847 | }, | 1802 | }, |
| 1848 | .probe = imx355_probe, | 1803 | .probe = imx355_probe, |
| @@ -127,7 +127,6 @@ static const char * const imx412_supply_names[] = { · 126 unmodified lines | |||
| 127 | * @vblank: Vertical blanking in lines | 127 | * @vblank: Vertical blanking in lines |
| 128 | * @cur_mode: Pointer to current selected sensor mode | 128 | * @cur_mode: Pointer to current selected sensor mode |
| 129 | * @mutex: Mutex for serializing sensor controls | 129 | * @mutex: Mutex for serializing sensor controls |
| 130 | * @streaming: Flag indicating streaming state | ||
| 131 | */ | 130 | */ |
| 132 | struct imx412 { | 131 | struct imx412 { |
| 133 | struct device *dev; | 132 | struct device *dev; |
| @@ -149,7 +148,6 @@ struct imx412 { · 15 unmodified lines | |||
| 149 | u32 vblank; | 148 | u32 vblank; |
| 150 | const struct imx412_mode *cur_mode; | 149 | const struct imx412_mode *cur_mode; |
| 151 | struct mutex mutex; | 150 | struct mutex mutex; |
| 152 | bool streaming; | ||
| 153 | }; | 151 | }; |
| 154 | 152 | ||
| 155 | static const s64 link_freq[] = { | 153 | static const s64 link_freq[] = { |
| @@ -857,11 +855,6 @@ static int imx412_set_stream(struct v4l2_subdev *sd, int enable) · 701 unmodified lines | |||
| 857 | 855 | ||
| 858 | mutex_lock(&imx412->mutex); | 856 | mutex_lock(&imx412->mutex); |
| 859 | 857 | ||
| 860 | if (imx412->streaming == enable) { | ||
| 861 | mutex_unlock(&imx412->mutex); | ||
| 862 | return 0; | ||
| 863 | } | ||
| 864 | |||
| 865 | if (enable) { | 858 | if (enable) { |
| 866 | ret = pm_runtime_resume_and_get(imx412->dev); | 859 | ret = pm_runtime_resume_and_get(imx412->dev); |
| 867 | if (ret) | 860 | if (ret) |
| @@ -875,8 +868,6 @@ static int imx412_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 875 | pm_runtime_put(imx412->dev); | 868 | pm_runtime_put(imx412->dev); |
| 876 | } | 869 | } |
| 877 | 870 | ||
| 878 | imx412->streaming = enable; | ||
| 879 | |||
| 880 | mutex_unlock(&imx412->mutex); | 871 | mutex_unlock(&imx412->mutex); |
| 881 | 872 | ||
| 882 | return 0; | 873 | return 0; |
| @@ -353,8 +353,6 @@ struct imx415 { · 352 unmodified lines | |||
| 353 | 353 | ||
| 354 | const struct imx415_clk_params *clk_params; | 354 | const struct imx415_clk_params *clk_params; |
| 355 | 355 | ||
| 356 | bool streaming; | ||
| 357 | |||
| 358 | struct v4l2_subdev subdev; | 356 | struct v4l2_subdev subdev; |
| 359 | struct media_pad pad; | 357 | struct media_pad pad; |
| 360 | 358 | ||
| @@ -542,8 +540,9 @@ static int imx415_s_ctrl(struct v4l2_ctrl *ctrl) · 181 unmodified lines | |||
| 542 | struct v4l2_subdev_state *state; | 540 | struct v4l2_subdev_state *state; |
| 543 | unsigned int vmax; | 541 | unsigned int vmax; |
| 544 | unsigned int flip; | 542 | unsigned int flip; |
| 543 | int ret; | ||
| 545 | 544 | ||
| 546 | if (!sensor->streaming) | 545 | if (!pm_runtime_get_if_in_use(sensor->dev)) |
| 547 | return 0; | 546 | return 0; |
| 548 | 547 | ||
| 549 | state = v4l2_subdev_get_locked_active_state(&sensor->subdev); | 548 | state = v4l2_subdev_get_locked_active_state(&sensor->subdev); |
| @@ -554,24 +553,33 @@ static int imx415_s_ctrl(struct v4l2_ctrl *ctrl) · 4 unmodified lines | |||
| 554 | /* clamp the exposure value to VMAX. */ | 553 | /* clamp the exposure value to VMAX. */ |
| 555 | vmax = format->height + sensor->vblank->cur.val; | 554 | vmax = format->height + sensor->vblank->cur.val; |
| 556 | ctrl->val = min_t(int, ctrl->val, vmax); | 555 | ctrl->val = min_t(int, ctrl->val, vmax); |
| 557 | return imx415_write(sensor, IMX415_SHR0, vmax - ctrl->val); | 556 | ret = imx415_write(sensor, IMX415_SHR0, vmax - ctrl->val); |
| 557 | break; | ||
| 558 | 558 | ||
| 559 | case V4L2_CID_ANALOGUE_GAIN: | 559 | case V4L2_CID_ANALOGUE_GAIN: |
| 560 | /* analogue gain in 0.3 dB step size */ | 560 | /* analogue gain in 0.3 dB step size */ |
| 561 | return imx415_write(sensor, IMX415_GAIN_PCG_0, ctrl->val); | 561 | ret = imx415_write(sensor, IMX415_GAIN_PCG_0, ctrl->val); |
| 562 | break; | ||
| 562 | 563 | ||
| 563 | case V4L2_CID_HFLIP: | 564 | case V4L2_CID_HFLIP: |
| 564 | case V4L2_CID_VFLIP: | 565 | case V4L2_CID_VFLIP: |
| 565 | flip = (sensor->hflip->val << IMX415_HREVERSE_SHIFT) | | 566 | flip = (sensor->hflip->val << IMX415_HREVERSE_SHIFT) | |
| 566 | (sensor->vflip->val << IMX415_VREVERSE_SHIFT); | 567 | (sensor->vflip->val << IMX415_VREVERSE_SHIFT); |
| 567 | return imx415_write(sensor, IMX415_REVERSE, flip); | 568 | ret = imx415_write(sensor, IMX415_REVERSE, flip); |
| 569 | break; | ||
| 568 | 570 | ||
| 569 | case V4L2_CID_TEST_PATTERN: | 571 | case V4L2_CID_TEST_PATTERN: |
| 570 | return imx415_set_testpattern(sensor, ctrl->val); | 572 | ret = imx415_set_testpattern(sensor, ctrl->val); |
| 573 | break; | ||
| 571 | 574 | ||
| 572 | default: | 575 | default: |
| 573 | return -EINVAL; | 576 | ret = -EINVAL; |
| 577 | break; | ||
| 574 | } | 578 | } |
| 579 | |||
| 580 | pm_runtime_put(sensor->dev); | ||
| 581 | |||
| 582 | return ret; | ||
| 575 | } | 583 | } |
| 576 | 584 | ||
| 577 | static const struct v4l2_ctrl_ops imx415_ctrl_ops = { | 585 | static const struct v4l2_ctrl_ops imx415_ctrl_ops = { |
| @@ -766,8 +774,6 @@ static int imx415_s_stream(struct v4l2_subdev *sd, int enable) · 188 unmodified lines | |||
| 766 | pm_runtime_mark_last_busy(sensor->dev); | 774 | pm_runtime_mark_last_busy(sensor->dev); |
| 767 | pm_runtime_put_autosuspend(sensor->dev); | 775 | pm_runtime_put_autosuspend(sensor->dev); |
| 768 | 776 | ||
| 769 | sensor->streaming = false; | ||
| 770 | |||
| 771 | goto unlock; | 777 | goto unlock; |
| 772 | } | 778 | } |
| 773 | 779 | ||
| @@ -779,13 +785,6 @@ static int imx415_s_stream(struct v4l2_subdev *sd, int enable) · 5 unmodified lines | |||
| 779 | if (ret) | 785 | if (ret) |
| 780 | goto err_pm; | 786 | goto err_pm; |
| 781 | 787 | ||
| 782 | /* | ||
| 783 | * Set streaming to true to ensure __v4l2_ctrl_handler_setup() will set | ||
| 784 | * the controls. The flag is reset to false further down if an error | ||
| 785 | * occurs. | ||
| 786 | */ | ||
| 787 | sensor->streaming = true; | ||
| 788 | |||
| 789 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); | 788 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); |
| 790 | if (ret < 0) | 789 | if (ret < 0) |
| 791 | goto err_pm; | 790 | goto err_pm; |
| @@ -807,7 +806,6 @@ err_pm: · 15 unmodified lines | |||
| 807 | * likely has no other chance to recover. | 806 | * likely has no other chance to recover. |
| 808 | */ | 807 | */ |
| 809 | pm_runtime_put_sync(sensor->dev); | 808 | pm_runtime_put_sync(sensor->dev); |
| 810 | sensor->streaming = false; | ||
| 811 | 809 | ||
| 812 | goto unlock; | 810 | goto unlock; |
| 813 | } | 811 | } |
| @@ -842,15 +840,6 @@ static int imx415_enum_frame_size(struct v4l2_subdev *sd, · 28 unmodified lines | |||
| 842 | return 0; | 840 | return 0; |
| 843 | } | 841 | } |
| 844 | 842 | ||
| 845 | static int imx415_get_format(struct v4l2_subdev *sd, | ||
| 846 | struct v4l2_subdev_state *state, | ||
| 847 | struct v4l2_subdev_format *fmt) | ||
| 848 | { | ||
| 849 | fmt->format = *v4l2_subdev_get_pad_format(sd, state, fmt->pad); | ||
| 850 | |||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | |||
| 854 | static int imx415_set_format(struct v4l2_subdev *sd, | 843 | static int imx415_set_format(struct v4l2_subdev *sd, |
| 855 | struct v4l2_subdev_state *state, | 844 | struct v4l2_subdev_state *state, |
| 856 | struct v4l2_subdev_format *fmt) | 845 | struct v4l2_subdev_format *fmt) |
| @@ -913,7 +902,7 @@ static const struct v4l2_subdev_video_ops imx415_subdev_video_ops = { · 56 unmodified lines | |||
| 913 | static const struct v4l2_subdev_pad_ops imx415_subdev_pad_ops = { | 902 | static const struct v4l2_subdev_pad_ops imx415_subdev_pad_ops = { |
| 914 | .enum_mbus_code = imx415_enum_mbus_code, | 903 | .enum_mbus_code = imx415_enum_mbus_code, |
| 915 | .enum_frame_size = imx415_enum_frame_size, | 904 | .enum_frame_size = imx415_enum_frame_size, |
| 916 | .get_fmt = imx415_get_format, | 905 | .get_fmt = v4l2_subdev_get_fmt, |
| 917 | .set_fmt = imx415_set_format, | 906 | .set_fmt = imx415_set_format, |
| 918 | .get_selection = imx415_get_selection, | 907 | .get_selection = imx415_get_selection, |
| 919 | .init_cfg = imx415_init_cfg, | 908 | .init_cfg = imx415_init_cfg, |
| @@ -1449,7 +1449,6 @@ static int max9286_parse_dt(struct max9286_priv *priv) · 1448 unmodified lines | |||
| 1449 | 1449 | ||
| 1450 | i2c_mux_mask |= BIT(id); | 1450 | i2c_mux_mask |= BIT(id); |
| 1451 | } | 1451 | } |
| 1452 | of_node_put(node); | ||
| 1453 | of_node_put(i2c_mux); | 1452 | of_node_put(i2c_mux); |
| 1454 | 1453 | ||
| 1455 | /* Parse the endpoints */ | 1454 | /* Parse the endpoints */ |
| @@ -1513,7 +1512,6 @@ static int max9286_parse_dt(struct max9286_priv *priv) · 57 unmodified lines | |||
| 1513 | priv->source_mask |= BIT(ep.port); | 1512 | priv->source_mask |= BIT(ep.port); |
| 1514 | priv->nsources++; | 1513 | priv->nsources++; |
| 1515 | } | 1514 | } |
| 1516 | of_node_put(node); | ||
| 1517 | 1515 | ||
| 1518 | of_property_read_u32(dev->of_node, "maxim,bus-width", &priv->bus_width); | 1516 | of_property_read_u32(dev->of_node, "maxim,bus-width", &priv->bus_width); |
| 1519 | switch (priv->bus_width) { | 1517 | switch (priv->bus_width) { |
| @@ -561,7 +561,7 @@ static int msp_log_status(struct v4l2_subdev *sd) · 560 unmodified lines | |||
| 561 | struct msp_state *state = to_state(sd); | 561 | struct msp_state *state = to_state(sd); |
| 562 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 562 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 563 | const char *p; | 563 | const char *p; |
| 564 | char prefix[V4L2_SUBDEV_NAME_SIZE + 20]; | 564 | char prefix[sizeof(sd->name) + 20]; |
| 565 | 565 | ||
| 566 | if (state->opmode == OPMODE_AUTOSELECT) | 566 | if (state->opmode == OPMODE_AUTOSELECT) |
| 567 | msp_detect_stereo(client); | 567 | msp_detect_stereo(client); |
| @@ -93,7 +93,6 @@ struct mt9m001 { · 92 unmodified lines | |||
| 93 | struct v4l2_ctrl *autoexposure; | 93 | struct v4l2_ctrl *autoexposure; |
| 94 | struct v4l2_ctrl *exposure; | 94 | struct v4l2_ctrl *exposure; |
| 95 | }; | 95 | }; |
| 96 | bool streaming; | ||
| 97 | struct mutex mutex; | 96 | struct mutex mutex; |
| 98 | struct v4l2_rect rect; /* Sensor window */ | 97 | struct v4l2_rect rect; /* Sensor window */ |
| 99 | struct clk *clk; | 98 | struct clk *clk; |
| @@ -213,9 +212,6 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) · 113 unmodified lines | |||
| 213 | 212 | ||
| 214 | mutex_lock(&mt9m001->mutex); | 213 | mutex_lock(&mt9m001->mutex); |
| 215 | 214 | ||
| 216 | if (mt9m001->streaming == enable) | ||
| 217 | goto done; | ||
| 218 | |||
| 219 | if (enable) { | 215 | if (enable) { |
| 220 | ret = pm_runtime_resume_and_get(&client->dev); | 216 | ret = pm_runtime_resume_and_get(&client->dev); |
| 221 | if (ret < 0) | 217 | if (ret < 0) |
| @@ -239,8 +235,6 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) · 17 unmodified lines | |||
| 239 | pm_runtime_put(&client->dev); | 235 | pm_runtime_put(&client->dev); |
| 240 | } | 236 | } |
| 241 | 237 | ||
| 242 | mt9m001->streaming = enable; | ||
| 243 | done: | ||
| 244 | mutex_unlock(&mt9m001->mutex); | 238 | mutex_unlock(&mt9m001->mutex); |
| 245 | 239 | ||
| 246 | return 0; | 240 | return 0; |
| @@ -244,9 +244,7 @@ struct mt9m111 { · 243 unmodified lines | |||
| 244 | bool is_streaming; | 244 | bool is_streaming; |
| 245 | /* user point of view - 0: falling 1: rising edge */ | 245 | /* user point of view - 0: falling 1: rising edge */ |
| 246 | unsigned int pclk_sample:1; | 246 | unsigned int pclk_sample:1; |
| 247 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 248 | struct media_pad pad; | 247 | struct media_pad pad; |
| 249 | #endif | ||
| 250 | }; | 248 | }; |
| 251 | 249 | ||
| 252 | static const struct mt9m111_mode_info mt9m111_mode_data[MT9M111_NUM_MODES] = { | 250 | static const struct mt9m111_mode_info mt9m111_mode_data[MT9M111_NUM_MODES] = { |
| @@ -527,13 +525,9 @@ static int mt9m111_get_fmt(struct v4l2_subdev *sd, · 274 unmodified lines | |||
| 527 | return -EINVAL; | 525 | return -EINVAL; |
| 528 | 526 | ||
| 529 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { | 527 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 530 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 531 | mf = v4l2_subdev_get_try_format(sd, sd_state, format->pad); | 528 | mf = v4l2_subdev_get_try_format(sd, sd_state, format->pad); |
| 532 | format->format = *mf; | 529 | format->format = *mf; |
| 533 | return 0; | 530 | return 0; |
| 534 | #else | ||
| 535 | return -EINVAL; | ||
| 536 | #endif | ||
| 537 | } | 531 | } |
| 538 | 532 | ||
| 539 | mf->width = mt9m111->width; | 533 | mf->width = mt9m111->width; |
| @@ -1120,7 +1114,6 @@ static int mt9m111_s_stream(struct v4l2_subdev *sd, int enable) · 580 unmodified lines | |||
| 1120 | static int mt9m111_init_cfg(struct v4l2_subdev *sd, | 1114 | static int mt9m111_init_cfg(struct v4l2_subdev *sd, |
| 1121 | struct v4l2_subdev_state *sd_state) | 1115 | struct v4l2_subdev_state *sd_state) |
| 1122 | { | 1116 | { |
| 1123 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1124 | struct v4l2_mbus_framefmt *format = | 1117 | struct v4l2_mbus_framefmt *format = |
| 1125 | v4l2_subdev_get_try_format(sd, sd_state, 0); | 1118 | v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 1126 | 1119 | ||
| @@ -1132,7 +1125,7 @@ static int mt9m111_init_cfg(struct v4l2_subdev *sd, · 5 unmodified lines | |||
| 1132 | format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | 1125 | format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
| 1133 | format->quantization = V4L2_QUANTIZATION_DEFAULT; | 1126 | format->quantization = V4L2_QUANTIZATION_DEFAULT; |
| 1134 | format->xfer_func = V4L2_XFER_FUNC_DEFAULT; | 1127 | format->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
| 1135 | #endif | 1128 | |
| 1136 | return 0; | 1129 | return 0; |
| 1137 | } | 1130 | } |
| 1138 | 1131 | ||
| @@ -1315,13 +1308,11 @@ static int mt9m111_probe(struct i2c_client *client) · 176 unmodified lines | |||
| 1315 | return ret; | 1308 | return ret; |
| 1316 | } | 1309 | } |
| 1317 | 1310 | ||
| 1318 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 1319 | mt9m111->pad.flags = MEDIA_PAD_FL_SOURCE; | 1311 | mt9m111->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1320 | mt9m111->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1312 | mt9m111->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1321 | ret = media_entity_pads_init(&mt9m111->subdev.entity, 1, &mt9m111->pad); | 1313 | ret = media_entity_pads_init(&mt9m111->subdev.entity, 1, &mt9m111->pad); |
| 1322 | if (ret < 0) | 1314 | if (ret < 0) |
| 1323 | goto out_hdlfree; | 1315 | goto out_hdlfree; |
| 1324 | #endif | ||
| 1325 | 1316 | ||
| 1326 | mt9m111->current_mode = &mt9m111_mode_data[MT9M111_MODE_SXGA_15FPS]; | 1317 | mt9m111->current_mode = &mt9m111_mode_data[MT9M111_MODE_SXGA_15FPS]; |
| 1327 | mt9m111->frame_interval.numerator = 1; | 1318 | mt9m111->frame_interval.numerator = 1; |
| @@ -1350,10 +1341,8 @@ static int mt9m111_probe(struct i2c_client *client) · 22 unmodified lines | |||
| 1350 | return 0; | 1341 | return 0; |
| 1351 | 1342 | ||
| 1352 | out_entityclean: | 1343 | out_entityclean: |
| 1353 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 1354 | media_entity_cleanup(&mt9m111->subdev.entity); | 1344 | media_entity_cleanup(&mt9m111->subdev.entity); |
| 1355 | out_hdlfree: | 1345 | out_hdlfree: |
| 1356 | #endif | ||
| 1357 | v4l2_ctrl_handler_free(&mt9m111->hdl); | 1346 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
| 1358 | 1347 | ||
| 1359 | return ret; | 1348 | return ret; |
| @@ -0,0 +1,2481 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * mt9m114.c onsemi MT9M114 sensor driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2020-2023 Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
| 6 | * Copyright (c) 2012 Analog Devices Inc. | ||
| 7 | * | ||
| 8 | * Almost complete rewrite of work by Scott Jiang <Scott.Jiang.Linux@gmail.com> | ||
| 9 | * itself based on work from Andrew Chew <achew@nvidia.com>. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/clk.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/mod_devicetable.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/pm_runtime.h> | ||
| 21 | #include <linux/regmap.h> | ||
| 22 | #include <linux/regulator/consumer.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/videodev2.h> | ||
| 25 | |||
| 26 | #include <media/v4l2-async.h> | ||
| 27 | #include <media/v4l2-cci.h> | ||
| 28 | #include <media/v4l2-ctrls.h> | ||
| 29 | #include <media/v4l2-device.h> | ||
| 30 | #include <media/v4l2-fwnode.h> | ||
| 31 | #include <media/v4l2-mediabus.h> | ||
| 32 | #include <media/v4l2-subdev.h> | ||
| 33 | |||
| 34 | /* Sysctl registers */ | ||
| 35 | #define MT9M114_CHIP_ID CCI_REG16(0x0000) | ||
| 36 | #define MT9M114_COMMAND_REGISTER CCI_REG16(0x0080) | ||
| 37 | #define MT9M114_COMMAND_REGISTER_APPLY_PATCH BIT(0) | ||
| 38 | #define MT9M114_COMMAND_REGISTER_SET_STATE BIT(1) | ||
| 39 | #define MT9M114_COMMAND_REGISTER_REFRESH BIT(2) | ||
| 40 | #define MT9M114_COMMAND_REGISTER_WAIT_FOR_EVENT BIT(3) | ||
| 41 | #define MT9M114_COMMAND_REGISTER_OK BIT(15) | ||
| 42 | #define MT9M114_RESET_AND_MISC_CONTROL CCI_REG16(0x001a) | ||
| 43 | #define MT9M114_RESET_SOC BIT(0) | ||
| 44 | #define MT9M114_PAD_SLEW CCI_REG16(0x001e) | ||
| 45 | #define MT9M114_PAD_CONTROL CCI_REG16(0x0032) | ||
| 46 | |||
| 47 | /* XDMA registers */ | ||
| 48 | #define MT9M114_ACCESS_CTL_STAT CCI_REG16(0x0982) | ||
| 49 | #define MT9M114_PHYSICAL_ADDRESS_ACCESS CCI_REG16(0x098a) | ||
| 50 | #define MT9M114_LOGICAL_ADDRESS_ACCESS CCI_REG16(0x098e) | ||
| 51 | |||
| 52 | /* Sensor Core registers */ | ||
| 53 | #define MT9M114_COARSE_INTEGRATION_TIME CCI_REG16(0x3012) | ||
| 54 | #define MT9M114_FINE_INTEGRATION_TIME CCI_REG16(0x3014) | ||
| 55 | #define MT9M114_RESET_REGISTER CCI_REG16(0x301a) | ||
| 56 | #define MT9M114_RESET_REGISTER_LOCK_REG BIT(3) | ||
| 57 | #define MT9M114_RESET_REGISTER_MASK_BAD BIT(9) | ||
| 58 | #define MT9M114_FLASH CCI_REG16(0x3046) | ||
| 59 | #define MT9M114_GREEN1_GAIN CCI_REG16(0x3056) | ||
| 60 | #define MT9M114_BLUE_GAIN CCI_REG16(0x3058) | ||
| 61 | #define MT9M114_RED_GAIN CCI_REG16(0x305a) | ||
| 62 | #define MT9M114_GREEN2_GAIN CCI_REG16(0x305c) | ||
| 63 | #define MT9M114_GLOBAL_GAIN CCI_REG16(0x305e) | ||
| 64 | #define MT9M114_GAIN_DIGITAL_GAIN(n) ((n) << 12) | ||
| 65 | #define MT9M114_GAIN_DIGITAL_GAIN_MASK (0xf << 12) | ||
| 66 | #define MT9M114_GAIN_ANALOG_GAIN(n) ((n) << 0) | ||
| 67 | #define MT9M114_GAIN_ANALOG_GAIN_MASK (0xff << 0) | ||
| 68 | #define MT9M114_CUSTOMER_REV CCI_REG16(0x31fe) | ||
| 69 | |||
| 70 | /* Monitor registers */ | ||
| 71 | #define MT9M114_MON_MAJOR_VERSION CCI_REG16(0x8000) | ||
| 72 | #define MT9M114_MON_MINOR_VERSION CCI_REG16(0x8002) | ||
| 73 | #define MT9M114_MON_RELEASE_VERSION CCI_REG16(0x8004) | ||
| 74 | |||
| 75 | /* Auto-Exposure Track registers */ | ||
| 76 | #define MT9M114_AE_TRACK_ALGO CCI_REG16(0xa804) | ||
| 77 | #define MT9M114_AE_TRACK_EXEC_AUTOMATIC_EXPOSURE BIT(0) | ||
| 78 | #define MT9M114_AE_TRACK_AE_TRACKING_DAMPENING_SPEED CCI_REG8(0xa80a) | ||
| 79 | |||
| 80 | /* Color Correction Matrix registers */ | ||
| 81 | #define MT9M114_CCM_ALGO CCI_REG16(0xb404) | ||
| 82 | #define MT9M114_CCM_EXEC_CALC_CCM_MATRIX BIT(4) | ||
| 83 | #define MT9M114_CCM_DELTA_GAIN CCI_REG8(0xb42a) | ||
| 84 | |||
| 85 | /* Camera Control registers */ | ||
| 86 | #define MT9M114_CAM_SENSOR_CFG_Y_ADDR_START CCI_REG16(0xc800) | ||
| 87 | #define MT9M114_CAM_SENSOR_CFG_X_ADDR_START CCI_REG16(0xc802) | ||
| 88 | #define MT9M114_CAM_SENSOR_CFG_Y_ADDR_END CCI_REG16(0xc804) | ||
| 89 | #define MT9M114_CAM_SENSOR_CFG_X_ADDR_END CCI_REG16(0xc806) | ||
| 90 | #define MT9M114_CAM_SENSOR_CFG_PIXCLK CCI_REG32(0xc808) | ||
| 91 | #define MT9M114_CAM_SENSOR_CFG_ROW_SPEED CCI_REG16(0xc80c) | ||
| 92 | #define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN CCI_REG16(0xc80e) | ||
| 93 | #define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX CCI_REG16(0xc810) | ||
| 94 | #define MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES CCI_REG16(0xc812) | ||
| 95 | #define MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES_MAX 65535 | ||
| 96 | #define MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK CCI_REG16(0xc814) | ||
| 97 | #define MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK_MAX 8191 | ||
| 98 | #define MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION CCI_REG16(0xc816) | ||
| 99 | #define MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW CCI_REG16(0xc818) | ||
| 100 | #define MT9M114_CAM_SENSOR_CFG_REG_0_DATA CCI_REG16(0xc826) | ||
| 101 | #define MT9M114_CAM_SENSOR_CONTROL_READ_MODE CCI_REG16(0xc834) | ||
| 102 | #define MT9M114_CAM_SENSOR_CONTROL_HORZ_MIRROR_EN BIT(0) | ||
| 103 | #define MT9M114_CAM_SENSOR_CONTROL_VERT_FLIP_EN BIT(1) | ||
| 104 | #define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_NORMAL (0 << 4) | ||
| 105 | #define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SKIPPING (1 << 4) | ||
| 106 | #define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_AVERAGE (2 << 4) | ||
| 107 | #define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SUMMING (3 << 4) | ||
| 108 | #define MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_MASK (3 << 4) | ||
| 109 | #define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_NORMAL (0 << 8) | ||
| 110 | #define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SKIPPING (1 << 8) | ||
| 111 | #define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SUMMING (3 << 8) | ||
| 112 | #define MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_MASK (3 << 8) | ||
| 113 | #define MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN CCI_REG16(0xc836) | ||
| 114 | #define MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME CCI_REG16(0xc83c) | ||
| 115 | #define MT9M114_CAM_SENSOR_CONTROL_FINE_INTEGRATION_TIME CCI_REG16(0xc83e) | ||
| 116 | #define MT9M114_CAM_MODE_SELECT CCI_REG8(0xc84c) | ||
| 117 | #define MT9M114_CAM_MODE_SELECT_NORMAL (0 << 0) | ||
| 118 | #define MT9M114_CAM_MODE_SELECT_LENS_CALIBRATION (1 << 0) | ||
| 119 | #define MT9M114_CAM_MODE_SELECT_TEST_PATTERN (2 << 0) | ||
| 120 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT CCI_REG8(0xc84d) | ||
| 121 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID (1 << 0) | ||
| 122 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID_BARS (4 << 0) | ||
| 123 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_RANDOM (5 << 0) | ||
| 124 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_FADING_BARS (8 << 0) | ||
| 125 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_10B (10 << 0) | ||
| 126 | #define MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_8B (11 << 0) | ||
| 127 | #define MT9M114_CAM_MODE_TEST_PATTERN_RED CCI_REG16(0xc84e) | ||
| 128 | #define MT9M114_CAM_MODE_TEST_PATTERN_GREEN CCI_REG16(0xc850) | ||
| 129 | #define MT9M114_CAM_MODE_TEST_PATTERN_BLUE CCI_REG16(0xc852) | ||
| 130 | #define MT9M114_CAM_CROP_WINDOW_XOFFSET CCI_REG16(0xc854) | ||
| 131 | #define MT9M114_CAM_CROP_WINDOW_YOFFSET CCI_REG16(0xc856) | ||
| 132 | #define MT9M114_CAM_CROP_WINDOW_WIDTH CCI_REG16(0xc858) | ||
| 133 | #define MT9M114_CAM_CROP_WINDOW_HEIGHT CCI_REG16(0xc85a) | ||
| 134 | #define MT9M114_CAM_CROP_CROPMODE CCI_REG8(0xc85c) | ||
| 135 | #define MT9M114_CAM_CROP_MODE_AE_AUTO_CROP_EN BIT(0) | ||
| 136 | #define MT9M114_CAM_CROP_MODE_AWB_AUTO_CROP_EN BIT(1) | ||
| 137 | #define MT9M114_CAM_OUTPUT_WIDTH CCI_REG16(0xc868) | ||
| 138 | #define MT9M114_CAM_OUTPUT_HEIGHT CCI_REG16(0xc86a) | ||
| 139 | #define MT9M114_CAM_OUTPUT_FORMAT CCI_REG16(0xc86c) | ||
| 140 | #define MT9M114_CAM_OUTPUT_FORMAT_SWAP_RED_BLUE BIT(0) | ||
| 141 | #define MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES BIT(1) | ||
| 142 | #define MT9M114_CAM_OUTPUT_FORMAT_MONO_ENABLE BIT(2) | ||
| 143 | #define MT9M114_CAM_OUTPUT_FORMAT_BT656_ENABLE BIT(3) | ||
| 144 | #define MT9M114_CAM_OUTPUT_FORMAT_BT656_CROP_SCALE_DISABLE BIT(4) | ||
| 145 | #define MT9M114_CAM_OUTPUT_FORMAT_FVLV_DISABLE BIT(5) | ||
| 146 | #define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV (0 << 8) | ||
| 147 | #define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB (1 << 8) | ||
| 148 | #define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER (2 << 8) | ||
| 149 | #define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_NONE (3 << 8) | ||
| 150 | #define MT9M114_CAM_OUTPUT_FORMAT_FORMAT_MASK (3 << 8) | ||
| 151 | #define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_RAWR10 (0 << 10) | ||
| 152 | #define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PRELSC_8_2 (1 << 10) | ||
| 153 | #define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_POSTLSC_8_2 (2 << 10) | ||
| 154 | #define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PROCESSED8 (3 << 10) | ||
| 155 | #define MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_MASK (3 << 10) | ||
| 156 | #define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB (0 << 12) | ||
| 157 | #define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_555RGB (1 << 12) | ||
| 158 | #define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_444xRGB (2 << 12) | ||
| 159 | #define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_444RGBx (3 << 12) | ||
| 160 | #define MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_MASK (3 << 12) | ||
| 161 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV CCI_REG16(0xc86e) | ||
| 162 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_CLIP BIT(5) | ||
| 163 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_AUV_OFFSET BIT(4) | ||
| 164 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_SELECT_601 BIT(3) | ||
| 165 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_NORMALISE BIT(2) | ||
| 166 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_EVEN_UV (0 << 0) | ||
| 167 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_ODD_UV (1 << 0) | ||
| 168 | #define MT9M114_CAM_OUTPUT_FORMAT_YUV_SAMPLING_EVENU_ODDV (2 << 0) | ||
| 169 | #define MT9M114_CAM_OUTPUT_Y_OFFSET CCI_REG8(0xc870) | ||
| 170 | #define MT9M114_CAM_AET_AEMODE CCI_REG8(0xc878) | ||
| 171 | #define MT9M114_CAM_AET_EXEC_SET_INDOOR BIT(0) | ||
| 172 | #define MT9M114_CAM_AET_DISCRETE_FRAMERATE BIT(1) | ||
| 173 | #define MT9M114_CAM_AET_ADAPTATIVE_TARGET_LUMA BIT(2) | ||
| 174 | #define MT9M114_CAM_AET_ADAPTATIVE_SKIP_FRAMES BIT(3) | ||
| 175 | #define MT9M114_CAM_AET_SKIP_FRAMES CCI_REG8(0xc879) | ||
| 176 | #define MT9M114_CAM_AET_TARGET_AVERAGE_LUMA CCI_REG8(0xc87a) | ||
| 177 | #define MT9M114_CAM_AET_TARGET_AVERAGE_LUMA_DARK CCI_REG8(0xc87b) | ||
| 178 | #define MT9M114_CAM_AET_BLACK_CLIPPING_TARGET CCI_REG16(0xc87c) | ||
| 179 | #define MT9M114_CAM_AET_AE_MIN_VIRT_INT_TIME_PCLK CCI_REG16(0xc87e) | ||
| 180 | #define MT9M114_CAM_AET_AE_MIN_VIRT_DGAIN CCI_REG16(0xc880) | ||
| 181 | #define MT9M114_CAM_AET_AE_MAX_VIRT_DGAIN CCI_REG16(0xc882) | ||
| 182 | #define MT9M114_CAM_AET_AE_MIN_VIRT_AGAIN CCI_REG16(0xc884) | ||
| 183 | #define MT9M114_CAM_AET_AE_MAX_VIRT_AGAIN CCI_REG16(0xc886) | ||
| 184 | #define MT9M114_CAM_AET_AE_VIRT_GAIN_TH_EG CCI_REG16(0xc888) | ||
| 185 | #define MT9M114_CAM_AET_AE_EG_GATE_PERCENTAGE CCI_REG8(0xc88a) | ||
| 186 | #define MT9M114_CAM_AET_FLICKER_FREQ_HZ CCI_REG8(0xc88b) | ||
| 187 | #define MT9M114_CAM_AET_MAX_FRAME_RATE CCI_REG16(0xc88c) | ||
| 188 | #define MT9M114_CAM_AET_MIN_FRAME_RATE CCI_REG16(0xc88e) | ||
| 189 | #define MT9M114_CAM_AET_TARGET_GAIN CCI_REG16(0xc890) | ||
| 190 | #define MT9M114_CAM_AWB_CCM_L(n) CCI_REG16(0xc892 + (n) * 2) | ||
| 191 | #define MT9M114_CAM_AWB_CCM_M(n) CCI_REG16(0xc8a4 + (n) * 2) | ||
| 192 | #define MT9M114_CAM_AWB_CCM_R(n) CCI_REG16(0xc8b6 + (n) * 2) | ||
| 193 | #define MT9M114_CAM_AWB_CCM_L_RG_GAIN CCI_REG16(0xc8c8) | ||
| 194 | #define MT9M114_CAM_AWB_CCM_L_BG_GAIN CCI_REG16(0xc8ca) | ||
| 195 | #define MT9M114_CAM_AWB_CCM_M_RG_GAIN CCI_REG16(0xc8cc) | ||
| 196 | #define MT9M114_CAM_AWB_CCM_M_BG_GAIN CCI_REG16(0xc8ce) | ||
| 197 | #define MT9M114_CAM_AWB_CCM_R_RG_GAIN CCI_REG16(0xc8d0) | ||
| 198 | #define MT9M114_CAM_AWB_CCM_R_BG_GAIN CCI_REG16(0xc8d2) | ||
| 199 | #define MT9M114_CAM_AWB_CCM_L_CTEMP CCI_REG16(0xc8d4) | ||
| 200 | #define MT9M114_CAM_AWB_CCM_M_CTEMP CCI_REG16(0xc8d6) | ||
| 201 | #define MT9M114_CAM_AWB_CCM_R_CTEMP CCI_REG16(0xc8d8) | ||
| 202 | #define MT9M114_CAM_AWB_AWB_XSCALE CCI_REG8(0xc8f2) | ||
| 203 | #define MT9M114_CAM_AWB_AWB_YSCALE CCI_REG8(0xc8f3) | ||
| 204 | #define MT9M114_CAM_AWB_AWB_WEIGHTS(n) CCI_REG16(0xc8f4 + (n) * 2) | ||
| 205 | #define MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ CCI_REG16(0xc904) | ||
| 206 | #define MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ CCI_REG16(0xc906) | ||
| 207 | #define MT9M114_CAM_AWB_AWBMODE CCI_REG8(0xc909) | ||
| 208 | #define MT9M114_CAM_AWB_MODE_AUTO BIT(1) | ||
| 209 | #define MT9M114_CAM_AWB_MODE_EXCLUSIVE_AE BIT(0) | ||
| 210 | #define MT9M114_CAM_AWB_K_R_L CCI_REG8(0xc90c) | ||
| 211 | #define MT9M114_CAM_AWB_K_G_L CCI_REG8(0xc90d) | ||
| 212 | #define MT9M114_CAM_AWB_K_B_L CCI_REG8(0xc90e) | ||
| 213 | #define MT9M114_CAM_AWB_K_R_R CCI_REG8(0xc90f) | ||
| 214 | #define MT9M114_CAM_AWB_K_G_R CCI_REG8(0xc910) | ||
| 215 | #define MT9M114_CAM_AWB_K_B_R CCI_REG8(0xc911) | ||
| 216 | #define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART CCI_REG16(0xc914) | ||
| 217 | #define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART CCI_REG16(0xc916) | ||
| 218 | #define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND CCI_REG16(0xc918) | ||
| 219 | #define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND CCI_REG16(0xc91a) | ||
| 220 | #define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART CCI_REG16(0xc91c) | ||
| 221 | #define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART CCI_REG16(0xc91e) | ||
| 222 | #define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND CCI_REG16(0xc920) | ||
| 223 | #define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND CCI_REG16(0xc922) | ||
| 224 | #define MT9M114_CAM_LL_LLMODE CCI_REG16(0xc924) | ||
| 225 | #define MT9M114_CAM_LL_START_BRIGHTNESS CCI_REG16(0xc926) | ||
| 226 | #define MT9M114_CAM_LL_STOP_BRIGHTNESS CCI_REG16(0xc928) | ||
| 227 | #define MT9M114_CAM_LL_START_SATURATION CCI_REG8(0xc92a) | ||
| 228 | #define MT9M114_CAM_LL_END_SATURATION CCI_REG8(0xc92b) | ||
| 229 | #define MT9M114_CAM_LL_START_DESATURATION CCI_REG8(0xc92c) | ||
| 230 | #define MT9M114_CAM_LL_END_DESATURATION CCI_REG8(0xc92d) | ||
| 231 | #define MT9M114_CAM_LL_START_DEMOSAICING CCI_REG8(0xc92e) | ||
| 232 | #define MT9M114_CAM_LL_START_AP_GAIN CCI_REG8(0xc92f) | ||
| 233 | #define MT9M114_CAM_LL_START_AP_THRESH CCI_REG8(0xc930) | ||
| 234 | #define MT9M114_CAM_LL_STOP_DEMOSAICING CCI_REG8(0xc931) | ||
| 235 | #define MT9M114_CAM_LL_STOP_AP_GAIN CCI_REG8(0xc932) | ||
| 236 | #define MT9M114_CAM_LL_STOP_AP_THRESH CCI_REG8(0xc933) | ||
| 237 | #define MT9M114_CAM_LL_START_NR_RED CCI_REG8(0xc934) | ||
| 238 | #define MT9M114_CAM_LL_START_NR_GREEN CCI_REG8(0xc935) | ||
| 239 | #define MT9M114_CAM_LL_START_NR_BLUE CCI_REG8(0xc936) | ||
| 240 | #define MT9M114_CAM_LL_START_NR_THRESH CCI_REG8(0xc937) | ||
| 241 | #define MT9M114_CAM_LL_STOP_NR_RED CCI_REG8(0xc938) | ||
| 242 | #define MT9M114_CAM_LL_STOP_NR_GREEN CCI_REG8(0xc939) | ||
| 243 | #define MT9M114_CAM_LL_STOP_NR_BLUE CCI_REG8(0xc93a) | ||
| 244 | #define MT9M114_CAM_LL_STOP_NR_THRESH CCI_REG8(0xc93b) | ||
| 245 | #define MT9M114_CAM_LL_START_CONTRAST_BM CCI_REG16(0xc93c) | ||
| 246 | #define MT9M114_CAM_LL_STOP_CONTRAST_BM CCI_REG16(0xc93e) | ||
| 247 | #define MT9M114_CAM_LL_GAMMA CCI_REG16(0xc940) | ||
| 248 | #define MT9M114_CAM_LL_START_CONTRAST_GRADIENT CCI_REG8(0xc942) | ||
| 249 | #define MT9M114_CAM_LL_STOP_CONTRAST_GRADIENT CCI_REG8(0xc943) | ||
| 250 | #define MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE CCI_REG8(0xc944) | ||
| 251 | #define MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE CCI_REG8(0xc945) | ||
| 252 | #define MT9M114_CAM_LL_START_GAIN_METRIC CCI_REG16(0xc946) | ||
| 253 | #define MT9M114_CAM_LL_STOP_GAIN_METRIC CCI_REG16(0xc948) | ||
| 254 | #define MT9M114_CAM_LL_START_FADE_TO_BLACK_LUMA CCI_REG16(0xc94a) | ||
| 255 | #define MT9M114_CAM_LL_STOP_FADE_TO_BLACK_LUMA CCI_REG16(0xc94c) | ||
| 256 | #define MT9M114_CAM_LL_CLUSTER_DC_TH_BM CCI_REG16(0xc94e) | ||
| 257 | #define MT9M114_CAM_LL_CLUSTER_DC_GATE_PERCENTAGE CCI_REG8(0xc950) | ||
| 258 | #define MT9M114_CAM_LL_SUMMING_SENSITIVITY_FACTOR CCI_REG8(0xc951) | ||
| 259 | #define MT9M114_CAM_LL_START_TARGET_LUMA_BM CCI_REG16(0xc952) | ||
| 260 | #define MT9M114_CAM_LL_STOP_TARGET_LUMA_BM CCI_REG16(0xc954) | ||
| 261 | #define MT9M114_CAM_PGA_PGA_CONTROL CCI_REG16(0xc95e) | ||
| 262 | #define MT9M114_CAM_SYSCTL_PLL_ENABLE CCI_REG8(0xc97e) | ||
| 263 | #define MT9M114_CAM_SYSCTL_PLL_ENABLE_VALUE BIT(0) | ||
| 264 | #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N CCI_REG16(0xc980) | ||
| 265 | #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(m, n) (((n) << 8) | (m)) | ||
| 266 | #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P CCI_REG16(0xc982) | ||
| 267 | #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(p) ((p) << 8) | ||
| 268 | #define MT9M114_CAM_PORT_OUTPUT_CONTROL CCI_REG16(0xc984) | ||
| 269 | #define MT9M114_CAM_PORT_PORT_SELECT_PARALLEL (0 << 0) | ||
| 270 | #define MT9M114_CAM_PORT_PORT_SELECT_MIPI (1 << 0) | ||
| 271 | #define MT9M114_CAM_PORT_CLOCK_SLOWDOWN BIT(3) | ||
| 272 | #define MT9M114_CAM_PORT_TRUNCATE_RAW_BAYER BIT(4) | ||
| 273 | #define MT9M114_CAM_PORT_PIXCLK_GATE BIT(5) | ||
| 274 | #define MT9M114_CAM_PORT_CONT_MIPI_CLK BIT(6) | ||
| 275 | #define MT9M114_CAM_PORT_CHAN_NUM(vc) ((vc) << 8) | ||
| 276 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_ZERO CCI_REG16(0xc988) | ||
| 277 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_ZERO_VALUE(n) ((n) << 8) | ||
| 278 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_EXIT_TRAIL CCI_REG16(0xc98a) | ||
| 279 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_EXIT_VALUE(n) ((n) << 8) | ||
| 280 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_HS_TRAIL_VALUE(n) ((n) << 0) | ||
| 281 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_POST_PRE CCI_REG16(0xc98c) | ||
| 282 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_POST_VALUE(n) ((n) << 8) | ||
| 283 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_PRE_VALUE(n) ((n) << 0) | ||
| 284 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_TRAIL_ZERO CCI_REG16(0xc98e) | ||
| 285 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_TRAIL_VALUE(n) ((n) << 8) | ||
| 286 | #define MT9M114_CAM_PORT_MIPI_TIMING_T_CLK_ZERO_VALUE(n) ((n) << 0) | ||
| 287 | |||
| 288 | /* System Manager registers */ | ||
| 289 | #define MT9M114_SYSMGR_NEXT_STATE CCI_REG8(0xdc00) | ||
| 290 | #define MT9M114_SYSMGR_CURRENT_STATE CCI_REG8(0xdc01) | ||
| 291 | #define MT9M114_SYSMGR_CMD_STATUS CCI_REG8(0xdc02) | ||
| 292 | |||
| 293 | /* Patch Loader registers */ | ||
| 294 | #define MT9M114_PATCHLDR_LOADER_ADDRESS CCI_REG16(0xe000) | ||
| 295 | #define MT9M114_PATCHLDR_PATCH_ID CCI_REG16(0xe002) | ||
| 296 | #define MT9M114_PATCHLDR_FIRMWARE_ID CCI_REG32(0xe004) | ||
| 297 | #define MT9M114_PATCHLDR_APPLY_STATUS CCI_REG8(0xe008) | ||
| 298 | #define MT9M114_PATCHLDR_NUM_PATCHES CCI_REG8(0xe009) | ||
| 299 | #define MT9M114_PATCHLDR_PATCH_ID_0 CCI_REG16(0xe00a) | ||
| 300 | #define MT9M114_PATCHLDR_PATCH_ID_1 CCI_REG16(0xe00c) | ||
| 301 | #define MT9M114_PATCHLDR_PATCH_ID_2 CCI_REG16(0xe00e) | ||
| 302 | #define MT9M114_PATCHLDR_PATCH_ID_3 CCI_REG16(0xe010) | ||
| 303 | #define MT9M114_PATCHLDR_PATCH_ID_4 CCI_REG16(0xe012) | ||
| 304 | #define MT9M114_PATCHLDR_PATCH_ID_5 CCI_REG16(0xe014) | ||
| 305 | #define MT9M114_PATCHLDR_PATCH_ID_6 CCI_REG16(0xe016) | ||
| 306 | #define MT9M114_PATCHLDR_PATCH_ID_7 CCI_REG16(0xe018) | ||
| 307 | |||
| 308 | /* SYS_STATE values (for SYSMGR_NEXT_STATE and SYSMGR_CURRENT_STATE) */ | ||
| 309 | #define MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE 0x28 | ||
| 310 | #define MT9M114_SYS_STATE_STREAMING 0x31 | ||
| 311 | #define MT9M114_SYS_STATE_START_STREAMING 0x34 | ||
| 312 | #define MT9M114_SYS_STATE_ENTER_SUSPEND 0x40 | ||
| 313 | #define MT9M114_SYS_STATE_SUSPENDED 0x41 | ||
| 314 | #define MT9M114_SYS_STATE_ENTER_STANDBY 0x50 | ||
| 315 | #define MT9M114_SYS_STATE_STANDBY 0x52 | ||
| 316 | #define MT9M114_SYS_STATE_LEAVE_STANDBY 0x54 | ||
| 317 | |||
| 318 | /* Result status of last SET_STATE comamnd */ | ||
| 319 | #define MT9M114_SET_STATE_RESULT_ENOERR 0x00 | ||
| 320 | #define MT9M114_SET_STATE_RESULT_EINVAL 0x0c | ||
| 321 | #define MT9M114_SET_STATE_RESULT_ENOSPC 0x0d | ||
| 322 | |||
| 323 | /* | ||
| 324 | * The minimum amount of horizontal and vertical blanking is undocumented. The | ||
| 325 | * minimum values that have been seen in register lists are 303 and 38, use | ||
| 326 | * them. | ||
| 327 | * | ||
| 328 | * Set the default to achieve 1280x960 at 30fps. | ||
| 329 | */ | ||
| 330 | #define MT9M114_MIN_HBLANK 303 | ||
| 331 | #define MT9M114_MIN_VBLANK 38 | ||
| 332 | #define MT9M114_DEF_HBLANK 323 | ||
| 333 | #define MT9M114_DEF_VBLANK 39 | ||
| 334 | |||
| 335 | #define MT9M114_DEF_FRAME_RATE 30 | ||
| 336 | #define MT9M114_MAX_FRAME_RATE 120 | ||
| 337 | |||
| 338 | #define MT9M114_PIXEL_ARRAY_WIDTH 1296U | ||
| 339 | #define MT9M114_PIXEL_ARRAY_HEIGHT 976U | ||
| 340 | |||
| 341 | /* | ||
| 342 | * These values are not well documented and are semi-arbitrary. The pixel array | ||
| 343 | * minimum output size is 8 pixels larger than the minimum scaler cropped input | ||
| 344 | * width to account for the demosaicing. | ||
| 345 | */ | ||
| 346 | #define MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH (32U + 8U) | ||
| 347 | #define MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT (32U + 8U) | ||
| 348 | #define MT9M114_SCALER_CROPPED_INPUT_WIDTH 32U | ||
| 349 | #define MT9M114_SCALER_CROPPED_INPUT_HEIGHT 32U | ||
| 350 | |||
| 351 | /* Indices into the mt9m114.ifp.tpg array. */ | ||
| 352 | #define MT9M114_TPG_PATTERN 0 | ||
| 353 | #define MT9M114_TPG_RED 1 | ||
| 354 | #define MT9M114_TPG_GREEN 2 | ||
| 355 | #define MT9M114_TPG_BLUE 3 | ||
| 356 | |||
| 357 | /* ----------------------------------------------------------------------------- | ||
| 358 | * Data Structures | ||
| 359 | */ | ||
| 360 | |||
| 361 | enum mt9m114_format_flag { | ||
| 362 | MT9M114_FMT_FLAG_PARALLEL = BIT(0), | ||
| 363 | MT9M114_FMT_FLAG_CSI2 = BIT(1), | ||
| 364 | }; | ||
| 365 | |||
| 366 | struct mt9m114_format_info { | ||
| 367 | u32 code; | ||
| 368 | u32 output_format; | ||
| 369 | u32 flags; | ||
| 370 | }; | ||
| 371 | |||
| 372 | struct mt9m114 { | ||
| 373 | struct i2c_client *client; | ||
| 374 | struct regmap *regmap; | ||
| 375 | |||
| 376 | struct clk *clk; | ||
| 377 | struct gpio_desc *reset; | ||
| 378 | struct regulator_bulk_data supplies[3]; | ||
| 379 | struct v4l2_fwnode_endpoint bus_cfg; | ||
| 380 | |||
| 381 | struct { | ||
| 382 | unsigned int m; | ||
| 383 | unsigned int n; | ||
| 384 | unsigned int p; | ||
| 385 | } pll; | ||
| 386 | |||
| 387 | unsigned int pixrate; | ||
| 388 | bool streaming; | ||
| 389 | |||
| 390 | /* Pixel Array */ | ||
| 391 | struct { | ||
| 392 | struct v4l2_subdev sd; | ||
| 393 | struct media_pad pad; | ||
| 394 | |||
| 395 | struct v4l2_ctrl_handler hdl; | ||
| 396 | struct v4l2_ctrl *exposure; | ||
| 397 | struct v4l2_ctrl *gain; | ||
| 398 | struct v4l2_ctrl *hblank; | ||
| 399 | struct v4l2_ctrl *vblank; | ||
| 400 | } pa; | ||
| 401 | |||
| 402 | /* Image Flow Processor */ | ||
| 403 | struct { | ||
| 404 | struct v4l2_subdev sd; | ||
| 405 | struct media_pad pads[2]; | ||
| 406 | |||
| 407 | struct v4l2_ctrl_handler hdl; | ||
| 408 | unsigned int frame_rate; | ||
| 409 | |||
| 410 | struct v4l2_ctrl *tpg[4]; | ||
| 411 | } ifp; | ||
| 412 | }; | ||
| 413 | |||
| 414 | /* ----------------------------------------------------------------------------- | ||
| 415 | * Formats | ||
| 416 | */ | ||
| 417 | |||
| 418 | static const struct mt9m114_format_info mt9m114_format_infos[] = { | ||
| 419 | { | ||
| 420 | /* | ||
| 421 | * The first two entries are used as defaults, for parallel and | ||
| 422 | * CSI-2 buses respectively. Keep them in that order. | ||
| 423 | */ | ||
| 424 | .code = MEDIA_BUS_FMT_UYVY8_2X8, | ||
| 425 | .flags = MT9M114_FMT_FLAG_PARALLEL, | ||
| 426 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV, | ||
| 427 | }, { | ||
| 428 | .code = MEDIA_BUS_FMT_UYVY8_1X16, | ||
| 429 | .flags = MT9M114_FMT_FLAG_CSI2, | ||
| 430 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV, | ||
| 431 | }, { | ||
| 432 | .code = MEDIA_BUS_FMT_YUYV8_2X8, | ||
| 433 | .flags = MT9M114_FMT_FLAG_PARALLEL, | ||
| 434 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV | ||
| 435 | | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES, | ||
| 436 | }, { | ||
| 437 | .code = MEDIA_BUS_FMT_YUYV8_1X16, | ||
| 438 | .flags = MT9M114_FMT_FLAG_CSI2, | ||
| 439 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_FORMAT_YUV | ||
| 440 | | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES, | ||
| 441 | }, { | ||
| 442 | .code = MEDIA_BUS_FMT_RGB565_2X8_LE, | ||
| 443 | .flags = MT9M114_FMT_FLAG_PARALLEL, | ||
| 444 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB | ||
| 445 | | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB | ||
| 446 | | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES, | ||
| 447 | }, { | ||
| 448 | .code = MEDIA_BUS_FMT_RGB565_2X8_BE, | ||
| 449 | .flags = MT9M114_FMT_FLAG_PARALLEL, | ||
| 450 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB | ||
| 451 | | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB, | ||
| 452 | }, { | ||
| 453 | .code = MEDIA_BUS_FMT_RGB565_1X16, | ||
| 454 | .flags = MT9M114_FMT_FLAG_CSI2, | ||
| 455 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_565RGB | ||
| 456 | | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_RGB, | ||
| 457 | }, { | ||
| 458 | .code = MEDIA_BUS_FMT_SGRBG8_1X8, | ||
| 459 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_PROCESSED8 | ||
| 460 | | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER, | ||
| 461 | .flags = MT9M114_FMT_FLAG_PARALLEL | MT9M114_FMT_FLAG_CSI2, | ||
| 462 | }, { | ||
| 463 | /* Keep the format compatible with the IFP sink pad last. */ | ||
| 464 | .code = MEDIA_BUS_FMT_SGRBG10_1X10, | ||
| 465 | .output_format = MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_RAWR10 | ||
| 466 | | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_BAYER, | ||
| 467 | .flags = MT9M114_FMT_FLAG_PARALLEL | MT9M114_FMT_FLAG_CSI2, | ||
| 468 | } | ||
| 469 | }; | ||
| 470 | |||
| 471 | static const struct mt9m114_format_info * | ||
| 472 | mt9m114_default_format_info(struct mt9m114 *sensor) | ||
| 473 | { | ||
| 474 | if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY) | ||
| 475 | return &mt9m114_format_infos[1]; | ||
| 476 | else | ||
| 477 | return &mt9m114_format_infos[0]; | ||
| 478 | } | ||
| 479 | |||
| 480 | static const struct mt9m114_format_info * | ||
| 481 | mt9m114_format_info(struct mt9m114 *sensor, unsigned int pad, u32 code) | ||
| 482 | { | ||
| 483 | const unsigned int num_formats = ARRAY_SIZE(mt9m114_format_infos); | ||
| 484 | unsigned int flag; | ||
| 485 | unsigned int i; | ||
| 486 | |||
| 487 | switch (pad) { | ||
| 488 | case 0: | ||
| 489 | return &mt9m114_format_infos[num_formats - 1]; | ||
| 490 | |||
| 491 | case 1: | ||
| 492 | if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY) | ||
| 493 | flag = MT9M114_FMT_FLAG_CSI2; | ||
| 494 | else | ||
| 495 | flag = MT9M114_FMT_FLAG_PARALLEL; | ||
| 496 | |||
| 497 | for (i = 0; i < num_formats; ++i) { | ||
| 498 | const struct mt9m114_format_info *info = | ||
| 499 | &mt9m114_format_infos[i]; | ||
| 500 | |||
| 501 | if (info->code == code && info->flags & flag) | ||
| 502 | return info; | ||
| 503 | } | ||
| 504 | |||
| 505 | return mt9m114_default_format_info(sensor); | ||
| 506 | |||
| 507 | default: | ||
| 508 | return NULL; | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | /* ----------------------------------------------------------------------------- | ||
| 513 | * Initialization | ||
| 514 | */ | ||
| 515 | |||
| 516 | static const struct cci_reg_sequence mt9m114_init[] = { | ||
| 517 | { MT9M114_RESET_REGISTER, MT9M114_RESET_REGISTER_MASK_BAD | | ||
| 518 | MT9M114_RESET_REGISTER_LOCK_REG | | ||
| 519 | 0x0010 }, | ||
| 520 | |||
| 521 | /* Sensor optimization */ | ||
| 522 | { CCI_REG16(0x316a), 0x8270 }, | ||
| 523 | { CCI_REG16(0x316c), 0x8270 }, | ||
| 524 | { CCI_REG16(0x3ed0), 0x2305 }, | ||
| 525 | { CCI_REG16(0x3ed2), 0x77cf }, | ||
| 526 | { CCI_REG16(0x316e), 0x8202 }, | ||
| 527 | { CCI_REG16(0x3180), 0x87ff }, | ||
| 528 | { CCI_REG16(0x30d4), 0x6080 }, | ||
| 529 | { CCI_REG16(0xa802), 0x0008 }, | ||
| 530 | |||
| 531 | { CCI_REG16(0x3e14), 0xff39 }, | ||
| 532 | |||
| 533 | /* APGA */ | ||
| 534 | { MT9M114_CAM_PGA_PGA_CONTROL, 0x0000 }, | ||
| 535 | |||
| 536 | /* Automatic White balance */ | ||
| 537 | { MT9M114_CAM_AWB_CCM_L(0), 0x0267 }, | ||
| 538 | { MT9M114_CAM_AWB_CCM_L(1), 0xff1a }, | ||
| 539 | { MT9M114_CAM_AWB_CCM_L(2), 0xffb3 }, | ||
| 540 | { MT9M114_CAM_AWB_CCM_L(3), 0xff80 }, | ||
| 541 | { MT9M114_CAM_AWB_CCM_L(4), 0x0166 }, | ||
| 542 | { MT9M114_CAM_AWB_CCM_L(5), 0x0003 }, | ||
| 543 | { MT9M114_CAM_AWB_CCM_L(6), 0xff9a }, | ||
| 544 | { MT9M114_CAM_AWB_CCM_L(7), 0xfeb4 }, | ||
| 545 | { MT9M114_CAM_AWB_CCM_L(8), 0x024d }, | ||
| 546 | { MT9M114_CAM_AWB_CCM_M(0), 0x01bf }, | ||
| 547 | { MT9M114_CAM_AWB_CCM_M(1), 0xff01 }, | ||
| 548 | { MT9M114_CAM_AWB_CCM_M(2), 0xfff3 }, | ||
| 549 | { MT9M114_CAM_AWB_CCM_M(3), 0xff75 }, | ||
| 550 | { MT9M114_CAM_AWB_CCM_M(4), 0x0198 }, | ||
| 551 | { MT9M114_CAM_AWB_CCM_M(5), 0xfffd }, | ||
| 552 | { MT9M114_CAM_AWB_CCM_M(6), 0xff9a }, | ||
| 553 | { MT9M114_CAM_AWB_CCM_M(7), 0xfee7 }, | ||
| 554 | { MT9M114_CAM_AWB_CCM_M(8), 0x02a8 }, | ||
| 555 | { MT9M114_CAM_AWB_CCM_R(0), 0x01d9 }, | ||
| 556 | { MT9M114_CAM_AWB_CCM_R(1), 0xff26 }, | ||
| 557 | { MT9M114_CAM_AWB_CCM_R(2), 0xfff3 }, | ||
| 558 | { MT9M114_CAM_AWB_CCM_R(3), 0xffb3 }, | ||
| 559 | { MT9M114_CAM_AWB_CCM_R(4), 0x0132 }, | ||
| 560 | { MT9M114_CAM_AWB_CCM_R(5), 0xffe8 }, | ||
| 561 | { MT9M114_CAM_AWB_CCM_R(6), 0xffda }, | ||
| 562 | { MT9M114_CAM_AWB_CCM_R(7), 0xfecd }, | ||
| 563 | { MT9M114_CAM_AWB_CCM_R(8), 0x02c2 }, | ||
| 564 | { MT9M114_CAM_AWB_CCM_L_RG_GAIN, 0x0075 }, | ||
| 565 | { MT9M114_CAM_AWB_CCM_L_BG_GAIN, 0x011c }, | ||
| 566 | { MT9M114_CAM_AWB_CCM_M_RG_GAIN, 0x009a }, | ||
| 567 | { MT9M114_CAM_AWB_CCM_M_BG_GAIN, 0x0105 }, | ||
| 568 | { MT9M114_CAM_AWB_CCM_R_RG_GAIN, 0x00a4 }, | ||
| 569 | { MT9M114_CAM_AWB_CCM_R_BG_GAIN, 0x00ac }, | ||
| 570 | { MT9M114_CAM_AWB_CCM_L_CTEMP, 0x0a8c }, | ||
| 571 | { MT9M114_CAM_AWB_CCM_M_CTEMP, 0x0f0a }, | ||
| 572 | { MT9M114_CAM_AWB_CCM_R_CTEMP, 0x1964 }, | ||
| 573 | { MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ, 51 }, | ||
| 574 | { MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ, 60 }, | ||
| 575 | { MT9M114_CAM_AWB_AWB_XSCALE, 3 }, | ||
| 576 | { MT9M114_CAM_AWB_AWB_YSCALE, 2 }, | ||
| 577 | { MT9M114_CAM_AWB_AWB_WEIGHTS(0), 0x0000 }, | ||
| 578 | { MT9M114_CAM_AWB_AWB_WEIGHTS(1), 0x0000 }, | ||
| 579 | { MT9M114_CAM_AWB_AWB_WEIGHTS(2), 0x0000 }, | ||
| 580 | { MT9M114_CAM_AWB_AWB_WEIGHTS(3), 0xe724 }, | ||
| 581 | { MT9M114_CAM_AWB_AWB_WEIGHTS(4), 0x1583 }, | ||
| 582 | { MT9M114_CAM_AWB_AWB_WEIGHTS(5), 0x2045 }, | ||
| 583 | { MT9M114_CAM_AWB_AWB_WEIGHTS(6), 0x03ff }, | ||
| 584 | { MT9M114_CAM_AWB_AWB_WEIGHTS(7), 0x007c }, | ||
| 585 | { MT9M114_CAM_AWB_K_R_L, 0x80 }, | ||
| 586 | { MT9M114_CAM_AWB_K_G_L, 0x80 }, | ||
| 587 | { MT9M114_CAM_AWB_K_B_L, 0x80 }, | ||
| 588 | { MT9M114_CAM_AWB_K_R_R, 0x88 }, | ||
| 589 | { MT9M114_CAM_AWB_K_G_R, 0x80 }, | ||
| 590 | { MT9M114_CAM_AWB_K_B_R, 0x80 }, | ||
| 591 | |||
| 592 | /* Low-Light Image Enhancements */ | ||
| 593 | { MT9M114_CAM_LL_START_BRIGHTNESS, 0x0020 }, | ||
| 594 | { MT9M114_CAM_LL_STOP_BRIGHTNESS, 0x009a }, | ||
| 595 | { MT9M114_CAM_LL_START_GAIN_METRIC, 0x0070 }, | ||
| 596 | { MT9M114_CAM_LL_STOP_GAIN_METRIC, 0x00f3 }, | ||
| 597 | { MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE, 0x20 }, | ||
| 598 | { MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE, 0x9a }, | ||
| 599 | { MT9M114_CAM_LL_START_SATURATION, 0x80 }, | ||
| 600 | { MT9M114_CAM_LL_END_SATURATION, 0x4b }, | ||
| 601 | { MT9M114_CAM_LL_START_DESATURATION, 0x00 }, | ||
| 602 | { MT9M114_CAM_LL_END_DESATURATION, 0xff }, | ||
| 603 | { MT9M114_CAM_LL_START_DEMOSAICING, 0x3c }, | ||
| 604 | { MT9M114_CAM_LL_START_AP_GAIN, 0x02 }, | ||
| 605 | { MT9M114_CAM_LL_START_AP_THRESH, 0x06 }, | ||
| 606 | { MT9M114_CAM_LL_STOP_DEMOSAICING, 0x64 }, | ||
| 607 | { MT9M114_CAM_LL_STOP_AP_GAIN, 0x01 }, | ||
| 608 | { MT9M114_CAM_LL_STOP_AP_THRESH, 0x0c }, | ||
| 609 | { MT9M114_CAM_LL_START_NR_RED, 0x3c }, | ||
| 610 | { MT9M114_CAM_LL_START_NR_GREEN, 0x3c }, | ||
| 611 | { MT9M114_CAM_LL_START_NR_BLUE, 0x3c }, | ||
| 612 | { MT9M114_CAM_LL_START_NR_THRESH, 0x0f }, | ||
| 613 | { MT9M114_CAM_LL_STOP_NR_RED, 0x64 }, | ||
| 614 | { MT9M114_CAM_LL_STOP_NR_GREEN, 0x64 }, | ||
| 615 | { MT9M114_CAM_LL_STOP_NR_BLUE, 0x64 }, | ||
| 616 | { MT9M114_CAM_LL_STOP_NR_THRESH, 0x32 }, | ||
| 617 | { MT9M114_CAM_LL_START_CONTRAST_BM, 0x0020 }, | ||
| 618 | { MT9M114_CAM_LL_STOP_CONTRAST_BM, 0x009a }, | ||
| 619 | { MT9M114_CAM_LL_GAMMA, 0x00dc }, | ||
| 620 | { MT9M114_CAM_LL_START_CONTRAST_GRADIENT, 0x38 }, | ||
| 621 | { MT9M114_CAM_LL_STOP_CONTRAST_GRADIENT, 0x30 }, | ||
| 622 | { MT9M114_CAM_LL_START_CONTRAST_LUMA_PERCENTAGE, 0x50 }, | ||
| 623 | { MT9M114_CAM_LL_STOP_CONTRAST_LUMA_PERCENTAGE, 0x19 }, | ||
| 624 | { MT9M114_CAM_LL_START_FADE_TO_BLACK_LUMA, 0x0230 }, | ||
| 625 | { MT9M114_CAM_LL_STOP_FADE_TO_BLACK_LUMA, 0x0010 }, | ||
| 626 | { MT9M114_CAM_LL_CLUSTER_DC_TH_BM, 0x01cd }, | ||
| 627 | { MT9M114_CAM_LL_CLUSTER_DC_GATE_PERCENTAGE, 0x05 }, | ||
| 628 | { MT9M114_CAM_LL_SUMMING_SENSITIVITY_FACTOR, 0x40 }, | ||
| 629 | |||
| 630 | /* Auto-Exposure */ | ||
| 631 | { MT9M114_CAM_AET_TARGET_AVERAGE_LUMA_DARK, 0x1b }, | ||
| 632 | { MT9M114_CAM_AET_AEMODE, 0x00 }, | ||
| 633 | { MT9M114_CAM_AET_TARGET_GAIN, 0x0080 }, | ||
| 634 | { MT9M114_CAM_AET_AE_MAX_VIRT_AGAIN, 0x0100 }, | ||
| 635 | { MT9M114_CAM_AET_BLACK_CLIPPING_TARGET, 0x005a }, | ||
| 636 | |||
| 637 | { MT9M114_CCM_DELTA_GAIN, 0x05 }, | ||
| 638 | { MT9M114_AE_TRACK_AE_TRACKING_DAMPENING_SPEED, 0x20 }, | ||
| 639 | |||
| 640 | /* Pixel array timings and integration time */ | ||
| 641 | { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 1 }, | ||
| 642 | { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 219 }, | ||
| 643 | { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 1459 }, | ||
| 644 | { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 96 }, | ||
| 645 | { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 32 }, | ||
| 646 | |||
| 647 | /* Miscellaneous settings */ | ||
| 648 | { MT9M114_PAD_SLEW, 0x0777 }, | ||
| 649 | }; | ||
| 650 | |||
| 651 | /* ----------------------------------------------------------------------------- | ||
| 652 | * Hardware Configuration | ||
| 653 | */ | ||
| 654 | |||
| 655 | /* Wait for a command to complete. */ | ||
| 656 | static int mt9m114_poll_command(struct mt9m114 *sensor, u32 command) | ||
| 657 | { | ||
| 658 | unsigned int i; | ||
| 659 | u64 value; | ||
| 660 | int ret; | ||
| 661 | |||
| 662 | for (i = 0; i < 100; ++i) { | ||
| 663 | ret = cci_read(sensor->regmap, MT9M114_COMMAND_REGISTER, &value, | ||
| 664 | NULL); | ||
| 665 | if (ret < 0) | ||
| 666 | return ret; | ||
| 667 | |||
| 668 | if (!(value & command)) | ||
| 669 | break; | ||
| 670 | |||
| 671 | usleep_range(5000, 6000); | ||
| 672 | } | ||
| 673 | |||
| 674 | if (value & command) { | ||
| 675 | dev_err(&sensor->client->dev, "Command %u completion timeout\n", | ||
| 676 | command); | ||
| 677 | return -ETIMEDOUT; | ||
| 678 | } | ||
| 679 | |||
| 680 | if (!(value & MT9M114_COMMAND_REGISTER_OK)) { | ||
| 681 | dev_err(&sensor->client->dev, "Command %u failed\n", command); | ||
| 682 | return -EIO; | ||
| 683 | } | ||
| 684 | |||
| 685 | return 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | /* Wait for a state to be entered. */ | ||
| 689 | static int mt9m114_poll_state(struct mt9m114 *sensor, u32 state) | ||
| 690 | { | ||
| 691 | unsigned int i; | ||
| 692 | u64 value; | ||
| 693 | int ret; | ||
| 694 | |||
| 695 | for (i = 0; i < 100; ++i) { | ||
| 696 | ret = cci_read(sensor->regmap, MT9M114_SYSMGR_CURRENT_STATE, | ||
| 697 | &value, NULL); | ||
| 698 | if (ret < 0) | ||
| 699 | return ret; | ||
| 700 | |||
| 701 | if (value == state) | ||
| 702 | return 0; | ||
| 703 | |||
| 704 | usleep_range(1000, 1500); | ||
| 705 | } | ||
| 706 | |||
| 707 | dev_err(&sensor->client->dev, "Timeout waiting for state 0x%02x\n", | ||
| 708 | state); | ||
| 709 | return -ETIMEDOUT; | ||
| 710 | } | ||
| 711 | |||
| 712 | static int mt9m114_set_state(struct mt9m114 *sensor, u8 next_state) | ||
| 713 | { | ||
| 714 | int ret = 0; | ||
| 715 | |||
| 716 | /* Set the next desired state and start the state transition. */ | ||
| 717 | cci_write(sensor->regmap, MT9M114_SYSMGR_NEXT_STATE, next_state, &ret); | ||
| 718 | cci_write(sensor->regmap, MT9M114_COMMAND_REGISTER, | ||
| 719 | MT9M114_COMMAND_REGISTER_OK | | ||
| 720 | MT9M114_COMMAND_REGISTER_SET_STATE, &ret); | ||
| 721 | if (ret < 0) | ||
| 722 | return ret; | ||
| 723 | |||
| 724 | /* Wait for the state transition to complete. */ | ||
| 725 | ret = mt9m114_poll_command(sensor, MT9M114_COMMAND_REGISTER_SET_STATE); | ||
| 726 | if (ret < 0) | ||
| 727 | return ret; | ||
| 728 | |||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | static int mt9m114_initialize(struct mt9m114 *sensor) | ||
| 733 | { | ||
| 734 | u32 value; | ||
| 735 | int ret; | ||
| 736 | |||
| 737 | ret = cci_multi_reg_write(sensor->regmap, mt9m114_init, | ||
| 738 | ARRAY_SIZE(mt9m114_init), NULL); | ||
| 739 | if (ret < 0) { | ||
| 740 | dev_err(&sensor->client->dev, | ||
| 741 | "Failed to initialize the sensor\n"); | ||
| 742 | return ret; | ||
| 743 | } | ||
| 744 | |||
| 745 | /* Configure the PLL. */ | ||
| 746 | cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_ENABLE, | ||
| 747 | MT9M114_CAM_SYSCTL_PLL_ENABLE_VALUE, &ret); | ||
| 748 | cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N, | ||
| 749 | MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(sensor->pll.m, | ||
| 750 | sensor->pll.n), | ||
| 751 | &ret); | ||
| 752 | cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_DIVIDER_P, | ||
| 753 | MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(sensor->pll.p), &ret); | ||
| 754 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_PIXCLK, | ||
| 755 | sensor->pixrate, &ret); | ||
| 756 | |||
| 757 | /* Configure the output mode. */ | ||
| 758 | if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY) { | ||
| 759 | value = MT9M114_CAM_PORT_PORT_SELECT_MIPI | ||
| 760 | | MT9M114_CAM_PORT_CHAN_NUM(0) | ||
| 761 | | 0x8000; | ||
| 762 | if (!(sensor->bus_cfg.bus.mipi_csi2.flags & | ||
| 763 | V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK)) | ||
| 764 | value |= MT9M114_CAM_PORT_CONT_MIPI_CLK; | ||
| 765 | } else { | ||
| 766 | value = MT9M114_CAM_PORT_PORT_SELECT_PARALLEL | ||
| 767 | | 0x8000; | ||
| 768 | } | ||
| 769 | cci_write(sensor->regmap, MT9M114_CAM_PORT_OUTPUT_CONTROL, value, &ret); | ||
| 770 | if (ret < 0) | ||
| 771 | return ret; | ||
| 772 | |||
| 773 | ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); | ||
| 774 | if (ret < 0) | ||
| 775 | return ret; | ||
| 776 | |||
| 777 | ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_SUSPEND); | ||
| 778 | if (ret < 0) | ||
| 779 | return ret; | ||
| 780 | |||
| 781 | return 0; | ||
| 782 | } | ||
| 783 | |||
| 784 | static int mt9m114_configure(struct mt9m114 *sensor, | ||
| 785 | struct v4l2_subdev_state *pa_state, | ||
| 786 | struct v4l2_subdev_state *ifp_state) | ||
| 787 | { | ||
| 788 | const struct v4l2_mbus_framefmt *pa_format; | ||
| 789 | const struct v4l2_rect *pa_crop; | ||
| 790 | const struct mt9m114_format_info *ifp_info; | ||
| 791 | const struct v4l2_mbus_framefmt *ifp_format; | ||
| 792 | const struct v4l2_rect *ifp_crop; | ||
| 793 | const struct v4l2_rect *ifp_compose; | ||
| 794 | unsigned int hratio, vratio; | ||
| 795 | u64 output_format; | ||
| 796 | u64 read_mode; | ||
| 797 | int ret = 0; | ||
| 798 | |||
| 799 | pa_format = v4l2_subdev_get_pad_format(&sensor->pa.sd, pa_state, 0); | ||
| 800 | pa_crop = v4l2_subdev_get_pad_crop(&sensor->pa.sd, pa_state, 0); | ||
| 801 | |||
| 802 | ifp_format = v4l2_subdev_get_pad_format(&sensor->ifp.sd, ifp_state, 1); | ||
| 803 | ifp_info = mt9m114_format_info(sensor, 1, ifp_format->code); | ||
| 804 | ifp_crop = v4l2_subdev_get_pad_crop(&sensor->ifp.sd, ifp_state, 0); | ||
| 805 | ifp_compose = v4l2_subdev_get_pad_compose(&sensor->ifp.sd, ifp_state, 0); | ||
| 806 | |||
| 807 | ret = cci_read(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_READ_MODE, | ||
| 808 | &read_mode, NULL); | ||
| 809 | if (ret < 0) | ||
| 810 | return ret; | ||
| 811 | |||
| 812 | ret = cci_read(sensor->regmap, MT9M114_CAM_OUTPUT_FORMAT, | ||
| 813 | &output_format, NULL); | ||
| 814 | if (ret < 0) | ||
| 815 | return ret; | ||
| 816 | |||
| 817 | hratio = pa_crop->width / pa_format->width; | ||
| 818 | vratio = pa_crop->height / pa_format->height; | ||
| 819 | |||
| 820 | /* | ||
| 821 | * Pixel array crop and binning. The CAM_SENSOR_CFG_CPIPE_LAST_ROW | ||
| 822 | * register isn't clearly documented, but is always set to the number | ||
| 823 | * of active rows minus 4 divided by the vertical binning factor in all | ||
| 824 | * example sensor modes. | ||
| 825 | */ | ||
| 826 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_X_ADDR_START, | ||
| 827 | pa_crop->left, &ret); | ||
| 828 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, | ||
| 829 | pa_crop->top, &ret); | ||
| 830 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_X_ADDR_END, | ||
| 831 | pa_crop->width + pa_crop->left - 1, &ret); | ||
| 832 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, | ||
| 833 | pa_crop->height + pa_crop->top - 1, &ret); | ||
| 834 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, | ||
| 835 | (pa_crop->height - 4) / vratio - 1, &ret); | ||
| 836 | |||
| 837 | read_mode &= ~(MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_MASK | | ||
| 838 | MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_MASK); | ||
| 839 | |||
| 840 | if (hratio > 1) | ||
| 841 | read_mode |= MT9M114_CAM_SENSOR_CONTROL_X_READ_OUT_SUMMING; | ||
| 842 | if (vratio > 1) | ||
| 843 | read_mode |= MT9M114_CAM_SENSOR_CONTROL_Y_READ_OUT_SUMMING; | ||
| 844 | |||
| 845 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_READ_MODE, | ||
| 846 | read_mode, &ret); | ||
| 847 | |||
| 848 | /* | ||
| 849 | * Color pipeline (IFP) cropping and scaling. Subtract 4 from the left | ||
| 850 | * and top coordinates to compensate for the lines and columns removed | ||
| 851 | * by demosaicing that are taken into account in the crop rectangle but | ||
| 852 | * not in the hardware. | ||
| 853 | */ | ||
| 854 | cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_XOFFSET, | ||
| 855 | ifp_crop->left - 4, &ret); | ||
| 856 | cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_YOFFSET, | ||
| 857 | ifp_crop->top - 4, &ret); | ||
| 858 | cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_WIDTH, | ||
| 859 | ifp_crop->width, &ret); | ||
| 860 | cci_write(sensor->regmap, MT9M114_CAM_CROP_WINDOW_HEIGHT, | ||
| 861 | ifp_crop->height, &ret); | ||
| 862 | |||
| 863 | cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_WIDTH, | ||
| 864 | ifp_compose->width, &ret); | ||
| 865 | cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_HEIGHT, | ||
| 866 | ifp_compose->height, &ret); | ||
| 867 | |||
| 868 | /* AWB and AE windows, use the full frame. */ | ||
| 869 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART, | ||
| 870 | 0, &ret); | ||
| 871 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART, | ||
| 872 | 0, &ret); | ||
| 873 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND, | ||
| 874 | ifp_compose->width - 1, &ret); | ||
| 875 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, | ||
| 876 | ifp_compose->height - 1, &ret); | ||
| 877 | |||
| 878 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, | ||
| 879 | 0, &ret); | ||
| 880 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, | ||
| 881 | 0, &ret); | ||
| 882 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, | ||
| 883 | ifp_compose->width / 5 - 1, &ret); | ||
| 884 | cci_write(sensor->regmap, MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, | ||
| 885 | ifp_compose->height / 5 - 1, &ret); | ||
| 886 | |||
| 887 | cci_write(sensor->regmap, MT9M114_CAM_CROP_CROPMODE, | ||
| 888 | MT9M114_CAM_CROP_MODE_AWB_AUTO_CROP_EN | | ||
| 889 | MT9M114_CAM_CROP_MODE_AE_AUTO_CROP_EN, &ret); | ||
| 890 | |||
| 891 | /* Set the media bus code. */ | ||
| 892 | output_format &= ~(MT9M114_CAM_OUTPUT_FORMAT_RGB_FORMAT_MASK | | ||
| 893 | MT9M114_CAM_OUTPUT_FORMAT_BAYER_FORMAT_MASK | | ||
| 894 | MT9M114_CAM_OUTPUT_FORMAT_FORMAT_MASK | | ||
| 895 | MT9M114_CAM_OUTPUT_FORMAT_SWAP_BYTES | | ||
| 896 | MT9M114_CAM_OUTPUT_FORMAT_SWAP_RED_BLUE); | ||
| 897 | output_format |= ifp_info->output_format; | ||
| 898 | |||
| 899 | cci_write(sensor->regmap, MT9M114_CAM_OUTPUT_FORMAT, | ||
| 900 | output_format, &ret); | ||
| 901 | |||
| 902 | return ret; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int mt9m114_set_frame_rate(struct mt9m114 *sensor) | ||
| 906 | { | ||
| 907 | u16 frame_rate = sensor->ifp.frame_rate << 8; | ||
| 908 | int ret = 0; | ||
| 909 | |||
| 910 | cci_write(sensor->regmap, MT9M114_CAM_AET_MIN_FRAME_RATE, | ||
| 911 | frame_rate, &ret); | ||
| 912 | cci_write(sensor->regmap, MT9M114_CAM_AET_MAX_FRAME_RATE, | ||
| 913 | frame_rate, &ret); | ||
| 914 | |||
| 915 | return ret; | ||
| 916 | } | ||
| 917 | |||
| 918 | static int mt9m114_start_streaming(struct mt9m114 *sensor, | ||
| 919 | struct v4l2_subdev_state *pa_state, | ||
| 920 | struct v4l2_subdev_state *ifp_state) | ||
| 921 | { | ||
| 922 | int ret; | ||
| 923 | |||
| 924 | ret = pm_runtime_resume_and_get(&sensor->client->dev); | ||
| 925 | if (ret) | ||
| 926 | return ret; | ||
| 927 | |||
| 928 | ret = mt9m114_configure(sensor, pa_state, ifp_state); | ||
| 929 | if (ret) | ||
| 930 | goto error; | ||
| 931 | |||
| 932 | ret = mt9m114_set_frame_rate(sensor); | ||
| 933 | if (ret) | ||
| 934 | goto error; | ||
| 935 | |||
| 936 | ret = __v4l2_ctrl_handler_setup(&sensor->pa.hdl); | ||
| 937 | if (ret) | ||
| 938 | goto error; | ||
| 939 | |||
| 940 | ret = __v4l2_ctrl_handler_setup(&sensor->ifp.hdl); | ||
| 941 | if (ret) | ||
| 942 | goto error; | ||
| 943 | |||
| 944 | /* | ||
| 945 | * The Change-Config state is transient and moves to the streaming | ||
| 946 | * state automatically. | ||
| 947 | */ | ||
| 948 | ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); | ||
| 949 | if (ret) | ||
| 950 | goto error; | ||
| 951 | |||
| 952 | sensor->streaming = true; | ||
| 953 | |||
| 954 | return 0; | ||
| 955 | |||
| 956 | error: | ||
| 957 | pm_runtime_mark_last_busy(&sensor->client->dev); | ||
| 958 | pm_runtime_put_autosuspend(&sensor->client->dev); | ||
| 959 | |||
| 960 | return ret; | ||
| 961 | } | ||
| 962 | |||
| 963 | static int mt9m114_stop_streaming(struct mt9m114 *sensor) | ||
| 964 | { | ||
| 965 | int ret; | ||
| 966 | |||
| 967 | sensor->streaming = false; | ||
| 968 | |||
| 969 | ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_SUSPEND); | ||
| 970 | |||
| 971 | pm_runtime_mark_last_busy(&sensor->client->dev); | ||
| 972 | pm_runtime_put_autosuspend(&sensor->client->dev); | ||
| 973 | |||
| 974 | return ret; | ||
| 975 | } | ||
| 976 | |||
| 977 | /* ----------------------------------------------------------------------------- | ||
| 978 | * Common Subdev Operations | ||
| 979 | */ | ||
| 980 | |||
| 981 | static const struct media_entity_operations mt9m114_entity_ops = { | ||
| 982 | .link_validate = v4l2_subdev_link_validate, | ||
| 983 | }; | ||
| 984 | |||
| 985 | /* ----------------------------------------------------------------------------- | ||
| 986 | * Pixel Array Control Operations | ||
| 987 | */ | ||
| 988 | |||
| 989 | static inline struct mt9m114 *pa_ctrl_to_mt9m114(struct v4l2_ctrl *ctrl) | ||
| 990 | { | ||
| 991 | return container_of(ctrl->handler, struct mt9m114, pa.hdl); | ||
| 992 | } | ||
| 993 | |||
| 994 | static int mt9m114_pa_g_ctrl(struct v4l2_ctrl *ctrl) | ||
| 995 | { | ||
| 996 | struct mt9m114 *sensor = pa_ctrl_to_mt9m114(ctrl); | ||
| 997 | u64 value; | ||
| 998 | int ret; | ||
| 999 | |||
| 1000 | if (!pm_runtime_get_if_in_use(&sensor->client->dev)) | ||
| 1001 | return 0; | ||
| 1002 | |||
| 1003 | switch (ctrl->id) { | ||
| 1004 | case V4L2_CID_EXPOSURE: | ||
| 1005 | ret = cci_read(sensor->regmap, | ||
| 1006 | MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME, | ||
| 1007 | &value, NULL); | ||
| 1008 | if (ret) | ||
| 1009 | break; | ||
| 1010 | |||
| 1011 | ctrl->val = value; | ||
| 1012 | break; | ||
| 1013 | |||
| 1014 | case V4L2_CID_ANALOGUE_GAIN: | ||
| 1015 | ret = cci_read(sensor->regmap, | ||
| 1016 | MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN, | ||
| 1017 | &value, NULL); | ||
| 1018 | if (ret) | ||
| 1019 | break; | ||
| 1020 | |||
| 1021 | ctrl->val = value; | ||
| 1022 | break; | ||
| 1023 | |||
| 1024 | default: | ||
| 1025 | ret = -EINVAL; | ||
| 1026 | break; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | pm_runtime_mark_last_busy(&sensor->client->dev); | ||
| 1030 | pm_runtime_put_autosuspend(&sensor->client->dev); | ||
| 1031 | |||
| 1032 | return ret; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static int mt9m114_pa_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1036 | { | ||
| 1037 | struct mt9m114 *sensor = pa_ctrl_to_mt9m114(ctrl); | ||
| 1038 | const struct v4l2_mbus_framefmt *format; | ||
| 1039 | struct v4l2_subdev_state *state; | ||
| 1040 | int ret = 0; | ||
| 1041 | u64 mask; | ||
| 1042 | |||
| 1043 | /* V4L2 controls values are applied only when power is up. */ | ||
| 1044 | if (!pm_runtime_get_if_in_use(&sensor->client->dev)) | ||
| 1045 | return 0; | ||
| 1046 | |||
| 1047 | state = v4l2_subdev_get_locked_active_state(&sensor->pa.sd); | ||
| 1048 | format = v4l2_subdev_get_pad_format(&sensor->pa.sd, state, 0); | ||
| 1049 | |||
| 1050 | switch (ctrl->id) { | ||
| 1051 | case V4L2_CID_HBLANK: | ||
| 1052 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, | ||
| 1053 | ctrl->val + format->width, &ret); | ||
| 1054 | break; | ||
| 1055 | |||
| 1056 | case V4L2_CID_VBLANK: | ||
| 1057 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, | ||
| 1058 | ctrl->val + format->height, &ret); | ||
| 1059 | break; | ||
| 1060 | |||
| 1061 | case V4L2_CID_EXPOSURE: | ||
| 1062 | cci_write(sensor->regmap, | ||
| 1063 | MT9M114_CAM_SENSOR_CONTROL_COARSE_INTEGRATION_TIME, | ||
| 1064 | ctrl->val, &ret); | ||
| 1065 | break; | ||
| 1066 | |||
| 1067 | case V4L2_CID_ANALOGUE_GAIN: | ||
| 1068 | /* | ||
| 1069 | * The CAM_SENSOR_CONTROL_ANALOG_GAIN contains linear analog | ||
| 1070 | * gain values that are mapped to the GLOBAL_GAIN register | ||
| 1071 | * values by the sensor firmware. | ||
| 1072 | */ | ||
| 1073 | cci_write(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_ANALOG_GAIN, | ||
| 1074 | ctrl->val, &ret); | ||
| 1075 | break; | ||
| 1076 | |||
| 1077 | case V4L2_CID_HFLIP: | ||
| 1078 | mask = MT9M114_CAM_SENSOR_CONTROL_HORZ_MIRROR_EN; | ||
| 1079 | ret = cci_update_bits(sensor->regmap, | ||
| 1080 | MT9M114_CAM_SENSOR_CONTROL_READ_MODE, | ||
| 1081 | mask, ctrl->val ? mask : 0, NULL); | ||
| 1082 | break; | ||
| 1083 | |||
| 1084 | case V4L2_CID_VFLIP: | ||
| 1085 | mask = MT9M114_CAM_SENSOR_CONTROL_VERT_FLIP_EN; | ||
| 1086 | ret = cci_update_bits(sensor->regmap, | ||
| 1087 | MT9M114_CAM_SENSOR_CONTROL_READ_MODE, | ||
| 1088 | mask, ctrl->val ? mask : 0, NULL); | ||
| 1089 | break; | ||
| 1090 | |||
| 1091 | default: | ||
| 1092 | ret = -EINVAL; | ||
| 1093 | break; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | pm_runtime_mark_last_busy(&sensor->client->dev); | ||
| 1097 | pm_runtime_put_autosuspend(&sensor->client->dev); | ||
| 1098 | |||
| 1099 | return ret; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | static const struct v4l2_ctrl_ops mt9m114_pa_ctrl_ops = { | ||
| 1103 | .g_volatile_ctrl = mt9m114_pa_g_ctrl, | ||
| 1104 | .s_ctrl = mt9m114_pa_s_ctrl, | ||
| 1105 | }; | ||
| 1106 | |||
| 1107 | static void mt9m114_pa_ctrl_update_exposure(struct mt9m114 *sensor, bool manual) | ||
| 1108 | { | ||
| 1109 | /* | ||
| 1110 | * Update the volatile flag on the manual exposure and gain controls. | ||
| 1111 | * If the controls have switched to manual, read their current value | ||
| 1112 | * from the hardware to ensure that control read and write operations | ||
| 1113 | * will behave correctly | ||
| 1114 | */ | ||
| 1115 | if (manual) { | ||
| 1116 | mt9m114_pa_g_ctrl(sensor->pa.exposure); | ||
| 1117 | sensor->pa.exposure->cur.val = sensor->pa.exposure->val; | ||
| 1118 | sensor->pa.exposure->flags &= ~V4L2_CTRL_FLAG_VOLATILE; | ||
| 1119 | |||
| 1120 | mt9m114_pa_g_ctrl(sensor->pa.gain); | ||
| 1121 | sensor->pa.gain->cur.val = sensor->pa.gain->val; | ||
| 1122 | sensor->pa.gain->flags &= ~V4L2_CTRL_FLAG_VOLATILE; | ||
| 1123 | } else { | ||
| 1124 | sensor->pa.exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
| 1125 | sensor->pa.gain->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | static void mt9m114_pa_ctrl_update_blanking(struct mt9m114 *sensor, | ||
| 1130 | const struct v4l2_mbus_framefmt *format) | ||
| 1131 | { | ||
| 1132 | unsigned int max_blank; | ||
| 1133 | |||
| 1134 | /* Update the blanking controls ranges based on the output size. */ | ||
| 1135 | max_blank = MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK_MAX | ||
| 1136 | - format->width; | ||
| 1137 | __v4l2_ctrl_modify_range(sensor->pa.hblank, MT9M114_MIN_HBLANK, | ||
| 1138 | max_blank, 1, MT9M114_DEF_HBLANK); | ||
| 1139 | |||
| 1140 | max_blank = MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES_MAX | ||
| 1141 | - format->height; | ||
| 1142 | __v4l2_ctrl_modify_range(sensor->pa.vblank, MT9M114_MIN_VBLANK, | ||
| 1143 | max_blank, 1, MT9M114_DEF_VBLANK); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | /* ----------------------------------------------------------------------------- | ||
| 1147 | * Pixel Array Subdev Operations | ||
| 1148 | */ | ||
| 1149 | |||
| 1150 | static inline struct mt9m114 *pa_to_mt9m114(struct v4l2_subdev *sd) | ||
| 1151 | { | ||
| 1152 | return container_of(sd, struct mt9m114, pa.sd); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | static int mt9m114_pa_init_cfg(struct v4l2_subdev *sd, | ||
| 1156 | struct v4l2_subdev_state *state) | ||
| 1157 | { | ||
| 1158 | struct v4l2_mbus_framefmt *format; | ||
| 1159 | struct v4l2_rect *crop; | ||
| 1160 | |||
| 1161 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1162 | |||
| 1163 | crop->left = 0; | ||
| 1164 | crop->top = 0; | ||
| 1165 | crop->width = MT9M114_PIXEL_ARRAY_WIDTH; | ||
| 1166 | crop->height = MT9M114_PIXEL_ARRAY_HEIGHT; | ||
| 1167 | |||
| 1168 | format = v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1169 | |||
| 1170 | format->width = MT9M114_PIXEL_ARRAY_WIDTH; | ||
| 1171 | format->height = MT9M114_PIXEL_ARRAY_HEIGHT; | ||
| 1172 | format->code = MEDIA_BUS_FMT_SGRBG10_1X10; | ||
| 1173 | format->field = V4L2_FIELD_NONE; | ||
| 1174 | format->colorspace = V4L2_COLORSPACE_RAW; | ||
| 1175 | format->ycbcr_enc = V4L2_YCBCR_ENC_601; | ||
| 1176 | format->quantization = V4L2_QUANTIZATION_FULL_RANGE; | ||
| 1177 | format->xfer_func = V4L2_XFER_FUNC_NONE; | ||
| 1178 | |||
| 1179 | return 0; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | static int mt9m114_pa_enum_mbus_code(struct v4l2_subdev *sd, | ||
| 1183 | struct v4l2_subdev_state *state, | ||
| 1184 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 1185 | { | ||
| 1186 | if (code->index > 0) | ||
| 1187 | return -EINVAL; | ||
| 1188 | |||
| 1189 | code->code = MEDIA_BUS_FMT_SGRBG10_1X10; | ||
| 1190 | |||
| 1191 | return 0; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | static int mt9m114_pa_enum_framesizes(struct v4l2_subdev *sd, | ||
| 1195 | struct v4l2_subdev_state *state, | ||
| 1196 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 1197 | { | ||
| 1198 | if (fse->index > 1) | ||
| 1199 | return -EINVAL; | ||
| 1200 | |||
| 1201 | if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) | ||
| 1202 | return -EINVAL; | ||
| 1203 | |||
| 1204 | /* Report binning capability through frame size enumeration. */ | ||
| 1205 | fse->min_width = MT9M114_PIXEL_ARRAY_WIDTH / (fse->index + 1); | ||
| 1206 | fse->max_width = MT9M114_PIXEL_ARRAY_WIDTH / (fse->index + 1); | ||
| 1207 | fse->min_height = MT9M114_PIXEL_ARRAY_HEIGHT / (fse->index + 1); | ||
| 1208 | fse->max_height = MT9M114_PIXEL_ARRAY_HEIGHT / (fse->index + 1); | ||
| 1209 | |||
| 1210 | return 0; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | static int mt9m114_pa_set_fmt(struct v4l2_subdev *sd, | ||
| 1214 | struct v4l2_subdev_state *state, | ||
| 1215 | struct v4l2_subdev_format *fmt) | ||
| 1216 | { | ||
| 1217 | struct mt9m114 *sensor = pa_to_mt9m114(sd); | ||
| 1218 | struct v4l2_mbus_framefmt *format; | ||
| 1219 | struct v4l2_rect *crop; | ||
| 1220 | unsigned int hscale; | ||
| 1221 | unsigned int vscale; | ||
| 1222 | |||
| 1223 | crop = v4l2_subdev_get_pad_crop(sd, state, fmt->pad); | ||
| 1224 | format = v4l2_subdev_get_pad_format(sd, state, fmt->pad); | ||
| 1225 | |||
| 1226 | /* The sensor can bin horizontally and vertically. */ | ||
| 1227 | hscale = DIV_ROUND_CLOSEST(crop->width, fmt->format.width ? : 1); | ||
| 1228 | vscale = DIV_ROUND_CLOSEST(crop->height, fmt->format.height ? : 1); | ||
| 1229 | format->width = crop->width / clamp(hscale, 1U, 2U); | ||
| 1230 | format->height = crop->height / clamp(vscale, 1U, 2U); | ||
| 1231 | |||
| 1232 | fmt->format = *format; | ||
| 1233 | |||
| 1234 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
| 1235 | mt9m114_pa_ctrl_update_blanking(sensor, format); | ||
| 1236 | |||
| 1237 | return 0; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | static int mt9m114_pa_get_selection(struct v4l2_subdev *sd, | ||
| 1241 | struct v4l2_subdev_state *state, | ||
| 1242 | struct v4l2_subdev_selection *sel) | ||
| 1243 | { | ||
| 1244 | switch (sel->target) { | ||
| 1245 | case V4L2_SEL_TGT_CROP: | ||
| 1246 | sel->r = *v4l2_subdev_get_pad_crop(sd, state, sel->pad); | ||
| 1247 | return 0; | ||
| 1248 | |||
| 1249 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
| 1250 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
| 1251 | case V4L2_SEL_TGT_NATIVE_SIZE: | ||
| 1252 | sel->r.left = 0; | ||
| 1253 | sel->r.top = 0; | ||
| 1254 | sel->r.width = MT9M114_PIXEL_ARRAY_WIDTH; | ||
| 1255 | sel->r.height = MT9M114_PIXEL_ARRAY_HEIGHT; | ||
| 1256 | return 0; | ||
| 1257 | |||
| 1258 | default: | ||
| 1259 | return -EINVAL; | ||
| 1260 | } | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | static int mt9m114_pa_set_selection(struct v4l2_subdev *sd, | ||
| 1264 | struct v4l2_subdev_state *state, | ||
| 1265 | struct v4l2_subdev_selection *sel) | ||
| 1266 | { | ||
| 1267 | struct mt9m114 *sensor = pa_to_mt9m114(sd); | ||
| 1268 | struct v4l2_mbus_framefmt *format; | ||
| 1269 | struct v4l2_rect *crop; | ||
| 1270 | |||
| 1271 | if (sel->target != V4L2_SEL_TGT_CROP) | ||
| 1272 | return -EINVAL; | ||
| 1273 | |||
| 1274 | crop = v4l2_subdev_get_pad_crop(sd, state, sel->pad); | ||
| 1275 | format = v4l2_subdev_get_pad_format(sd, state, sel->pad); | ||
| 1276 | |||
| 1277 | /* | ||
| 1278 | * Clamp the crop rectangle. The vertical coordinates must be even, and | ||
| 1279 | * the horizontal coordinates must be a multiple of 4. | ||
| 1280 | * | ||
| 1281 | * FIXME: The horizontal coordinates must be a multiple of 8 when | ||
| 1282 | * binning, but binning is configured after setting the selection, so | ||
| 1283 | * we can't know tell here if it will be used. | ||
| 1284 | */ | ||
| 1285 | crop->left = ALIGN(sel->r.left, 4); | ||
| 1286 | crop->top = ALIGN(sel->r.top, 2); | ||
| 1287 | crop->width = clamp_t(unsigned int, ALIGN(sel->r.width, 4), | ||
| 1288 | MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH, | ||
| 1289 | MT9M114_PIXEL_ARRAY_WIDTH - crop->left); | ||
| 1290 | crop->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), | ||
| 1291 | MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT, | ||
| 1292 | MT9M114_PIXEL_ARRAY_HEIGHT - crop->top); | ||
| 1293 | |||
| 1294 | sel->r = *crop; | ||
| 1295 | |||
| 1296 | /* Reset the format. */ | ||
| 1297 | format->width = crop->width; | ||
| 1298 | format->height = crop->height; | ||
| 1299 | |||
| 1300 | if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
| 1301 | mt9m114_pa_ctrl_update_blanking(sensor, format); | ||
| 1302 | |||
| 1303 | return 0; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | static const struct v4l2_subdev_pad_ops mt9m114_pa_pad_ops = { | ||
| 1307 | .init_cfg = mt9m114_pa_init_cfg, | ||
| 1308 | .enum_mbus_code = mt9m114_pa_enum_mbus_code, | ||
| 1309 | .enum_frame_size = mt9m114_pa_enum_framesizes, | ||
| 1310 | .get_fmt = v4l2_subdev_get_fmt, | ||
| 1311 | .set_fmt = mt9m114_pa_set_fmt, | ||
| 1312 | .get_selection = mt9m114_pa_get_selection, | ||
| 1313 | .set_selection = mt9m114_pa_set_selection, | ||
| 1314 | }; | ||
| 1315 | |||
| 1316 | static const struct v4l2_subdev_ops mt9m114_pa_ops = { | ||
| 1317 | .pad = &mt9m114_pa_pad_ops, | ||
| 1318 | }; | ||
| 1319 | |||
| 1320 | static int mt9m114_pa_init(struct mt9m114 *sensor) | ||
| 1321 | { | ||
| 1322 | struct v4l2_ctrl_handler *hdl = &sensor->pa.hdl; | ||
| 1323 | struct v4l2_subdev *sd = &sensor->pa.sd; | ||
| 1324 | struct media_pad *pads = &sensor->pa.pad; | ||
| 1325 | const struct v4l2_mbus_framefmt *format; | ||
| 1326 | struct v4l2_subdev_state *state; | ||
| 1327 | unsigned int max_exposure; | ||
| 1328 | int ret; | ||
| 1329 | |||
| 1330 | /* Initialize the subdev. */ | ||
| 1331 | v4l2_subdev_init(sd, &mt9m114_pa_ops); | ||
| 1332 | v4l2_i2c_subdev_set_name(sd, sensor->client, NULL, " pixel array"); | ||
| 1333 | |||
| 1334 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 1335 | sd->owner = THIS_MODULE; | ||
| 1336 | sd->dev = &sensor->client->dev; | ||
| 1337 | v4l2_set_subdevdata(sd, sensor->client); | ||
| 1338 | |||
| 1339 | /* Initialize the media entity. */ | ||
| 1340 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; | ||
| 1341 | sd->entity.ops = &mt9m114_entity_ops; | ||
| 1342 | pads[0].flags = MEDIA_PAD_FL_SOURCE; | ||
| 1343 | ret = media_entity_pads_init(&sd->entity, 1, pads); | ||
| 1344 | if (ret < 0) | ||
| 1345 | return ret; | ||
| 1346 | |||
| 1347 | /* Initialize the control handler. */ | ||
| 1348 | v4l2_ctrl_handler_init(hdl, 7); | ||
| 1349 | |||
| 1350 | /* The range of the HBLANK and VBLANK controls will be updated below. */ | ||
| 1351 | sensor->pa.hblank = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1352 | V4L2_CID_HBLANK, | ||
| 1353 | MT9M114_DEF_HBLANK, | ||
| 1354 | MT9M114_DEF_HBLANK, 1, | ||
| 1355 | MT9M114_DEF_HBLANK); | ||
| 1356 | sensor->pa.vblank = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1357 | V4L2_CID_VBLANK, | ||
| 1358 | MT9M114_DEF_VBLANK, | ||
| 1359 | MT9M114_DEF_VBLANK, 1, | ||
| 1360 | MT9M114_DEF_VBLANK); | ||
| 1361 | |||
| 1362 | /* | ||
| 1363 | * The maximum coarse integration time is the frame length in lines | ||
| 1364 | * minus two. The default is taken directly from the datasheet, but | ||
| 1365 | * makes little sense as auto-exposure is enabled by default. | ||
| 1366 | */ | ||
| 1367 | max_exposure = MT9M114_PIXEL_ARRAY_HEIGHT + MT9M114_MIN_VBLANK - 2; | ||
| 1368 | sensor->pa.exposure = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1369 | V4L2_CID_EXPOSURE, 1, | ||
| 1370 | max_exposure, 1, 16); | ||
| 1371 | if (sensor->pa.exposure) | ||
| 1372 | sensor->pa.exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
| 1373 | |||
| 1374 | sensor->pa.gain = v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1375 | V4L2_CID_ANALOGUE_GAIN, 1, | ||
| 1376 | 511, 1, 32); | ||
| 1377 | if (sensor->pa.gain) | ||
| 1378 | sensor->pa.gain->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
| 1379 | |||
| 1380 | v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1381 | V4L2_CID_PIXEL_RATE, | ||
| 1382 | sensor->pixrate, sensor->pixrate, 1, | ||
| 1383 | sensor->pixrate); | ||
| 1384 | |||
| 1385 | v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1386 | V4L2_CID_HFLIP, | ||
| 1387 | 0, 1, 1, 0); | ||
| 1388 | v4l2_ctrl_new_std(hdl, &mt9m114_pa_ctrl_ops, | ||
| 1389 | V4L2_CID_VFLIP, | ||
| 1390 | 0, 1, 1, 0); | ||
| 1391 | |||
| 1392 | if (hdl->error) { | ||
| 1393 | ret = hdl->error; | ||
| 1394 | goto error; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | sd->state_lock = hdl->lock; | ||
| 1398 | |||
| 1399 | ret = v4l2_subdev_init_finalize(sd); | ||
| 1400 | if (ret) | ||
| 1401 | goto error; | ||
| 1402 | |||
| 1403 | /* Update the range of the blanking controls based on the format. */ | ||
| 1404 | state = v4l2_subdev_lock_and_get_active_state(sd); | ||
| 1405 | format = v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1406 | mt9m114_pa_ctrl_update_blanking(sensor, format); | ||
| 1407 | v4l2_subdev_unlock_state(state); | ||
| 1408 | |||
| 1409 | sd->ctrl_handler = hdl; | ||
| 1410 | |||
| 1411 | return 0; | ||
| 1412 | |||
| 1413 | error: | ||
| 1414 | v4l2_ctrl_handler_free(&sensor->pa.hdl); | ||
| 1415 | media_entity_cleanup(&sensor->pa.sd.entity); | ||
| 1416 | return ret; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | static void mt9m114_pa_cleanup(struct mt9m114 *sensor) | ||
| 1420 | { | ||
| 1421 | v4l2_ctrl_handler_free(&sensor->pa.hdl); | ||
| 1422 | media_entity_cleanup(&sensor->pa.sd.entity); | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | /* ----------------------------------------------------------------------------- | ||
| 1426 | * Image Flow Processor Control Operations | ||
| 1427 | */ | ||
| 1428 | |||
| 1429 | static const char * const mt9m114_test_pattern_menu[] = { | ||
| 1430 | "Disabled", | ||
| 1431 | "Solid Color", | ||
| 1432 | "100% Color Bars", | ||
| 1433 | "Pseudo-Random", | ||
| 1434 | "Fade-to-Gray Color Bars", | ||
| 1435 | "Walking Ones 10-bit", | ||
| 1436 | "Walking Ones 8-bit", | ||
| 1437 | }; | ||
| 1438 | |||
| 1439 | /* Keep in sync with mt9m114_test_pattern_menu */ | ||
| 1440 | static const unsigned int mt9m114_test_pattern_value[] = { | ||
| 1441 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID, | ||
| 1442 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_SOLID_BARS, | ||
| 1443 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_RANDOM, | ||
| 1444 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_FADING_BARS, | ||
| 1445 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_10B, | ||
| 1446 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT_WALKING_1S_8B, | ||
| 1447 | }; | ||
| 1448 | |||
| 1449 | static inline struct mt9m114 *ifp_ctrl_to_mt9m114(struct v4l2_ctrl *ctrl) | ||
| 1450 | { | ||
| 1451 | return container_of(ctrl->handler, struct mt9m114, ifp.hdl); | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | static int mt9m114_ifp_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1455 | { | ||
| 1456 | struct mt9m114 *sensor = ifp_ctrl_to_mt9m114(ctrl); | ||
| 1457 | u32 value; | ||
| 1458 | int ret = 0; | ||
| 1459 | |||
| 1460 | if (ctrl->id == V4L2_CID_EXPOSURE_AUTO) | ||
| 1461 | mt9m114_pa_ctrl_update_exposure(sensor, | ||
| 1462 | ctrl->val != V4L2_EXPOSURE_AUTO); | ||
| 1463 | |||
| 1464 | /* V4L2 controls values are applied only when power is up. */ | ||
| 1465 | if (!pm_runtime_get_if_in_use(&sensor->client->dev)) | ||
| 1466 | return 0; | ||
| 1467 | |||
| 1468 | switch (ctrl->id) { | ||
| 1469 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
| 1470 | /* Control both the AWB mode and the CCM algorithm. */ | ||
| 1471 | if (ctrl->val) | ||
| 1472 | value = MT9M114_CAM_AWB_MODE_AUTO | ||
| 1473 | | MT9M114_CAM_AWB_MODE_EXCLUSIVE_AE; | ||
| 1474 | else | ||
| 1475 | value = 0; | ||
| 1476 | |||
| 1477 | cci_write(sensor->regmap, MT9M114_CAM_AWB_AWBMODE, value, &ret); | ||
| 1478 | |||
| 1479 | if (ctrl->val) | ||
| 1480 | value = MT9M114_CCM_EXEC_CALC_CCM_MATRIX | 0x22; | ||
| 1481 | else | ||
| 1482 | value = 0; | ||
| 1483 | |||
| 1484 | cci_write(sensor->regmap, MT9M114_CCM_ALGO, value, &ret); | ||
| 1485 | break; | ||
| 1486 | |||
| 1487 | case V4L2_CID_EXPOSURE_AUTO: | ||
| 1488 | if (ctrl->val == V4L2_EXPOSURE_AUTO) | ||
| 1489 | value = MT9M114_AE_TRACK_EXEC_AUTOMATIC_EXPOSURE | ||
| 1490 | | 0x00fe; | ||
| 1491 | else | ||
| 1492 | value = 0; | ||
| 1493 | |||
| 1494 | cci_write(sensor->regmap, MT9M114_AE_TRACK_ALGO, value, &ret); | ||
| 1495 | if (ret) | ||
| 1496 | break; | ||
| 1497 | |||
| 1498 | break; | ||
| 1499 | |||
| 1500 | case V4L2_CID_TEST_PATTERN: | ||
| 1501 | case V4L2_CID_TEST_PATTERN_RED: | ||
| 1502 | case V4L2_CID_TEST_PATTERN_GREENR: | ||
| 1503 | case V4L2_CID_TEST_PATTERN_BLUE: { | ||
| 1504 | unsigned int pattern = sensor->ifp.tpg[MT9M114_TPG_PATTERN]->val; | ||
| 1505 | |||
| 1506 | if (pattern) { | ||
| 1507 | cci_write(sensor->regmap, MT9M114_CAM_MODE_SELECT, | ||
| 1508 | MT9M114_CAM_MODE_SELECT_TEST_PATTERN, &ret); | ||
| 1509 | cci_write(sensor->regmap, | ||
| 1510 | MT9M114_CAM_MODE_TEST_PATTERN_SELECT, | ||
| 1511 | mt9m114_test_pattern_value[pattern - 1], &ret); | ||
| 1512 | cci_write(sensor->regmap, | ||
| 1513 | MT9M114_CAM_MODE_TEST_PATTERN_RED, | ||
| 1514 | sensor->ifp.tpg[MT9M114_TPG_RED]->val, &ret); | ||
| 1515 | cci_write(sensor->regmap, | ||
| 1516 | MT9M114_CAM_MODE_TEST_PATTERN_GREEN, | ||
| 1517 | sensor->ifp.tpg[MT9M114_TPG_GREEN]->val, &ret); | ||
| 1518 | cci_write(sensor->regmap, | ||
| 1519 | MT9M114_CAM_MODE_TEST_PATTERN_BLUE, | ||
| 1520 | sensor->ifp.tpg[MT9M114_TPG_BLUE]->val, &ret); | ||
| 1521 | } else { | ||
| 1522 | cci_write(sensor->regmap, MT9M114_CAM_MODE_SELECT, | ||
| 1523 | MT9M114_CAM_MODE_SELECT_NORMAL, &ret); | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | /* | ||
| 1527 | * A Config-Change needs to be issued for the change to take | ||
| 1528 | * effect. If we're not streaming ignore this, the change will | ||
| 1529 | * be applied when the stream is started. | ||
| 1530 | */ | ||
| 1531 | if (ret || !sensor->streaming) | ||
| 1532 | break; | ||
| 1533 | |||
| 1534 | ret = mt9m114_set_state(sensor, | ||
| 1535 | MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); | ||
| 1536 | break; | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | default: | ||
| 1540 | ret = -EINVAL; | ||
| 1541 | break; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | pm_runtime_mark_last_busy(&sensor->client->dev); | ||
| 1545 | pm_runtime_put_autosuspend(&sensor->client->dev); | ||
| 1546 | |||
| 1547 | return ret; | ||
| 1548 | } | ||
| 1549 | |||
| 1550 | static const struct v4l2_ctrl_ops mt9m114_ifp_ctrl_ops = { | ||
| 1551 | .s_ctrl = mt9m114_ifp_s_ctrl, | ||
| 1552 | }; | ||
| 1553 | |||
| 1554 | /* ----------------------------------------------------------------------------- | ||
| 1555 | * Image Flow Processor Subdev Operations | ||
| 1556 | */ | ||
| 1557 | |||
| 1558 | static inline struct mt9m114 *ifp_to_mt9m114(struct v4l2_subdev *sd) | ||
| 1559 | { | ||
| 1560 | return container_of(sd, struct mt9m114, ifp.sd); | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | static int mt9m114_ifp_s_stream(struct v4l2_subdev *sd, int enable) | ||
| 1564 | { | ||
| 1565 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1566 | struct v4l2_subdev_state *pa_state; | ||
| 1567 | struct v4l2_subdev_state *ifp_state; | ||
| 1568 | int ret; | ||
| 1569 | |||
| 1570 | if (!enable) | ||
| 1571 | return mt9m114_stop_streaming(sensor); | ||
| 1572 | |||
| 1573 | ifp_state = v4l2_subdev_lock_and_get_active_state(&sensor->ifp.sd); | ||
| 1574 | pa_state = v4l2_subdev_lock_and_get_active_state(&sensor->pa.sd); | ||
| 1575 | |||
| 1576 | ret = mt9m114_start_streaming(sensor, pa_state, ifp_state); | ||
| 1577 | |||
| 1578 | v4l2_subdev_unlock_state(pa_state); | ||
| 1579 | v4l2_subdev_unlock_state(ifp_state); | ||
| 1580 | |||
| 1581 | return ret; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | static int mt9m114_ifp_g_frame_interval(struct v4l2_subdev *sd, | ||
| 1585 | struct v4l2_subdev_frame_interval *interval) | ||
| 1586 | { | ||
| 1587 | struct v4l2_fract *ival = &interval->interval; | ||
| 1588 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1589 | |||
| 1590 | mutex_lock(sensor->ifp.hdl.lock); | ||
| 1591 | |||
| 1592 | ival->numerator = 1; | ||
| 1593 | ival->denominator = sensor->ifp.frame_rate; | ||
| 1594 | |||
| 1595 | mutex_unlock(sensor->ifp.hdl.lock); | ||
| 1596 | |||
| 1597 | return 0; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | static int mt9m114_ifp_s_frame_interval(struct v4l2_subdev *sd, | ||
| 1601 | struct v4l2_subdev_frame_interval *interval) | ||
| 1602 | { | ||
| 1603 | struct v4l2_fract *ival = &interval->interval; | ||
| 1604 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1605 | int ret = 0; | ||
| 1606 | |||
| 1607 | mutex_lock(sensor->ifp.hdl.lock); | ||
| 1608 | |||
| 1609 | if (ival->numerator != 0 && ival->denominator != 0) | ||
| 1610 | sensor->ifp.frame_rate = min_t(unsigned int, | ||
| 1611 | ival->denominator / ival->numerator, | ||
| 1612 | MT9M114_MAX_FRAME_RATE); | ||
| 1613 | else | ||
| 1614 | sensor->ifp.frame_rate = MT9M114_MAX_FRAME_RATE; | ||
| 1615 | |||
| 1616 | ival->numerator = 1; | ||
| 1617 | ival->denominator = sensor->ifp.frame_rate; | ||
| 1618 | |||
| 1619 | if (sensor->streaming) | ||
| 1620 | ret = mt9m114_set_frame_rate(sensor); | ||
| 1621 | |||
| 1622 | mutex_unlock(sensor->ifp.hdl.lock); | ||
| 1623 | |||
| 1624 | return ret; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | static int mt9m114_ifp_init_cfg(struct v4l2_subdev *sd, | ||
| 1628 | struct v4l2_subdev_state *state) | ||
| 1629 | { | ||
| 1630 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1631 | struct v4l2_mbus_framefmt *format; | ||
| 1632 | struct v4l2_rect *crop; | ||
| 1633 | struct v4l2_rect *compose; | ||
| 1634 | |||
| 1635 | format = v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1636 | |||
| 1637 | format->width = MT9M114_PIXEL_ARRAY_WIDTH; | ||
| 1638 | format->height = MT9M114_PIXEL_ARRAY_HEIGHT; | ||
| 1639 | format->code = MEDIA_BUS_FMT_SGRBG10_1X10; | ||
| 1640 | format->field = V4L2_FIELD_NONE; | ||
| 1641 | format->colorspace = V4L2_COLORSPACE_RAW; | ||
| 1642 | format->ycbcr_enc = V4L2_YCBCR_ENC_601; | ||
| 1643 | format->quantization = V4L2_QUANTIZATION_FULL_RANGE; | ||
| 1644 | format->xfer_func = V4L2_XFER_FUNC_NONE; | ||
| 1645 | |||
| 1646 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1647 | |||
| 1648 | crop->left = 4; | ||
| 1649 | crop->top = 4; | ||
| 1650 | crop->width = format->width - 8; | ||
| 1651 | crop->height = format->height - 8; | ||
| 1652 | |||
| 1653 | compose = v4l2_subdev_get_pad_compose(sd, state, 0); | ||
| 1654 | |||
| 1655 | compose->left = 0; | ||
| 1656 | compose->top = 0; | ||
| 1657 | compose->width = crop->width; | ||
| 1658 | compose->height = crop->height; | ||
| 1659 | |||
| 1660 | format = v4l2_subdev_get_pad_format(sd, state, 1); | ||
| 1661 | |||
| 1662 | format->width = compose->width; | ||
| 1663 | format->height = compose->height; | ||
| 1664 | format->code = mt9m114_default_format_info(sensor)->code; | ||
| 1665 | format->field = V4L2_FIELD_NONE; | ||
| 1666 | format->colorspace = V4L2_COLORSPACE_SRGB; | ||
| 1667 | format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | ||
| 1668 | format->quantization = V4L2_QUANTIZATION_DEFAULT; | ||
| 1669 | format->xfer_func = V4L2_XFER_FUNC_DEFAULT; | ||
| 1670 | |||
| 1671 | return 0; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | static int mt9m114_ifp_enum_mbus_code(struct v4l2_subdev *sd, | ||
| 1675 | struct v4l2_subdev_state *state, | ||
| 1676 | struct v4l2_subdev_mbus_code_enum *code) | ||
| 1677 | { | ||
| 1678 | const unsigned int num_formats = ARRAY_SIZE(mt9m114_format_infos); | ||
| 1679 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1680 | unsigned int index = 0; | ||
| 1681 | unsigned int flag; | ||
| 1682 | unsigned int i; | ||
| 1683 | |||
| 1684 | switch (code->pad) { | ||
| 1685 | case 0: | ||
| 1686 | if (code->index != 0) | ||
| 1687 | return -EINVAL; | ||
| 1688 | |||
| 1689 | code->code = mt9m114_format_infos[num_formats - 1].code; | ||
| 1690 | return 0; | ||
| 1691 | |||
| 1692 | case 1: | ||
| 1693 | if (sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY) | ||
| 1694 | flag = MT9M114_FMT_FLAG_CSI2; | ||
| 1695 | else | ||
| 1696 | flag = MT9M114_FMT_FLAG_PARALLEL; | ||
| 1697 | |||
| 1698 | for (i = 0; i < num_formats; ++i) { | ||
| 1699 | const struct mt9m114_format_info *info = | ||
| 1700 | &mt9m114_format_infos[i]; | ||
| 1701 | |||
| 1702 | if (info->flags & flag) { | ||
| 1703 | if (index == code->index) { | ||
| 1704 | code->code = info->code; | ||
| 1705 | return 0; | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | index++; | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | return -EINVAL; | ||
| 1713 | |||
| 1714 | default: | ||
| 1715 | return -EINVAL; | ||
| 1716 | } | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | static int mt9m114_ifp_enum_framesizes(struct v4l2_subdev *sd, | ||
| 1720 | struct v4l2_subdev_state *state, | ||
| 1721 | struct v4l2_subdev_frame_size_enum *fse) | ||
| 1722 | { | ||
| 1723 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1724 | const struct mt9m114_format_info *info; | ||
| 1725 | |||
| 1726 | if (fse->index > 0) | ||
| 1727 | return -EINVAL; | ||
| 1728 | |||
| 1729 | info = mt9m114_format_info(sensor, fse->pad, fse->code); | ||
| 1730 | if (!info || info->code != fse->code) | ||
| 1731 | return -EINVAL; | ||
| 1732 | |||
| 1733 | if (fse->pad == 0) { | ||
| 1734 | fse->min_width = MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH; | ||
| 1735 | fse->max_width = MT9M114_PIXEL_ARRAY_WIDTH; | ||
| 1736 | fse->min_height = MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT; | ||
| 1737 | fse->max_height = MT9M114_PIXEL_ARRAY_HEIGHT; | ||
| 1738 | } else { | ||
| 1739 | const struct v4l2_rect *crop; | ||
| 1740 | |||
| 1741 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1742 | |||
| 1743 | fse->max_width = crop->width; | ||
| 1744 | fse->max_height = crop->height; | ||
| 1745 | |||
| 1746 | fse->min_width = fse->max_width / 4; | ||
| 1747 | fse->min_height = fse->max_height / 4; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | return 0; | ||
| 1751 | } | ||
| 1752 | |||
| 1753 | static int mt9m114_ifp_enum_frameintervals(struct v4l2_subdev *sd, | ||
| 1754 | struct v4l2_subdev_state *state, | ||
| 1755 | struct v4l2_subdev_frame_interval_enum *fie) | ||
| 1756 | { | ||
| 1757 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1758 | const struct mt9m114_format_info *info; | ||
| 1759 | |||
| 1760 | if (fie->index > 0) | ||
| 1761 | return -EINVAL; | ||
| 1762 | |||
| 1763 | info = mt9m114_format_info(sensor, fie->pad, fie->code); | ||
| 1764 | if (!info || info->code != fie->code) | ||
| 1765 | return -EINVAL; | ||
| 1766 | |||
| 1767 | fie->interval.numerator = 1; | ||
| 1768 | fie->interval.denominator = MT9M114_MAX_FRAME_RATE; | ||
| 1769 | |||
| 1770 | return 0; | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | static int mt9m114_ifp_set_fmt(struct v4l2_subdev *sd, | ||
| 1774 | struct v4l2_subdev_state *state, | ||
| 1775 | struct v4l2_subdev_format *fmt) | ||
| 1776 | { | ||
| 1777 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1778 | struct v4l2_mbus_framefmt *format; | ||
| 1779 | |||
| 1780 | format = v4l2_subdev_get_pad_format(sd, state, fmt->pad); | ||
| 1781 | |||
| 1782 | if (fmt->pad == 0) { | ||
| 1783 | /* Only the size can be changed on the sink pad. */ | ||
| 1784 | format->width = clamp(ALIGN(fmt->format.width, 8), | ||
| 1785 | MT9M114_PIXEL_ARRAY_MIN_OUTPUT_WIDTH, | ||
| 1786 | MT9M114_PIXEL_ARRAY_WIDTH); | ||
| 1787 | format->height = clamp(ALIGN(fmt->format.height, 8), | ||
| 1788 | MT9M114_PIXEL_ARRAY_MIN_OUTPUT_HEIGHT, | ||
| 1789 | MT9M114_PIXEL_ARRAY_HEIGHT); | ||
| 1790 | } else { | ||
| 1791 | const struct mt9m114_format_info *info; | ||
| 1792 | |||
| 1793 | /* Only the media bus code can be changed on the source pad. */ | ||
| 1794 | info = mt9m114_format_info(sensor, 1, fmt->format.code); | ||
| 1795 | |||
| 1796 | format->code = info->code; | ||
| 1797 | |||
| 1798 | /* If the output format is RAW10, bypass the scaler. */ | ||
| 1799 | if (format->code == MEDIA_BUS_FMT_SGRBG10_1X10) | ||
| 1800 | *format = *v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | fmt->format = *format; | ||
| 1804 | |||
| 1805 | return 0; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd, | ||
| 1809 | struct v4l2_subdev_state *state, | ||
| 1810 | struct v4l2_subdev_selection *sel) | ||
| 1811 | { | ||
| 1812 | const struct v4l2_mbus_framefmt *format; | ||
| 1813 | const struct v4l2_rect *crop; | ||
| 1814 | int ret = 0; | ||
| 1815 | |||
| 1816 | /* Crop and compose are only supported on the sink pad. */ | ||
| 1817 | if (sel->pad != 0) | ||
| 1818 | return -EINVAL; | ||
| 1819 | |||
| 1820 | switch (sel->target) { | ||
| 1821 | case V4L2_SEL_TGT_CROP: | ||
| 1822 | sel->r = *v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1823 | break; | ||
| 1824 | |||
| 1825 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
| 1826 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
| 1827 | /* | ||
| 1828 | * The crop default and bounds are equal to the sink | ||
| 1829 | * format size minus 4 pixels on each side for demosaicing. | ||
| 1830 | */ | ||
| 1831 | format = v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1832 | |||
| 1833 | sel->r.left = 4; | ||
| 1834 | sel->r.top = 4; | ||
| 1835 | sel->r.width = format->width - 8; | ||
| 1836 | sel->r.height = format->height - 8; | ||
| 1837 | break; | ||
| 1838 | |||
| 1839 | case V4L2_SEL_TGT_COMPOSE: | ||
| 1840 | sel->r = *v4l2_subdev_get_pad_compose(sd, state, 0); | ||
| 1841 | break; | ||
| 1842 | |||
| 1843 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
| 1844 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
| 1845 | /* | ||
| 1846 | * The compose default and bounds sizes are equal to the sink | ||
| 1847 | * crop rectangle size. | ||
| 1848 | */ | ||
| 1849 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1850 | sel->r.left = 0; | ||
| 1851 | sel->r.top = 0; | ||
| 1852 | sel->r.width = crop->width; | ||
| 1853 | sel->r.height = crop->height; | ||
| 1854 | break; | ||
| 1855 | |||
| 1856 | default: | ||
| 1857 | ret = -EINVAL; | ||
| 1858 | break; | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | return ret; | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | static int mt9m114_ifp_set_selection(struct v4l2_subdev *sd, | ||
| 1865 | struct v4l2_subdev_state *state, | ||
| 1866 | struct v4l2_subdev_selection *sel) | ||
| 1867 | { | ||
| 1868 | struct v4l2_mbus_framefmt *format; | ||
| 1869 | struct v4l2_rect *crop; | ||
| 1870 | struct v4l2_rect *compose; | ||
| 1871 | |||
| 1872 | if (sel->target != V4L2_SEL_TGT_CROP && | ||
| 1873 | sel->target != V4L2_SEL_TGT_COMPOSE) | ||
| 1874 | return -EINVAL; | ||
| 1875 | |||
| 1876 | /* Crop and compose are only supported on the sink pad. */ | ||
| 1877 | if (sel->pad != 0) | ||
| 1878 | return -EINVAL; | ||
| 1879 | |||
| 1880 | format = v4l2_subdev_get_pad_format(sd, state, 0); | ||
| 1881 | crop = v4l2_subdev_get_pad_crop(sd, state, 0); | ||
| 1882 | compose = v4l2_subdev_get_pad_compose(sd, state, 0); | ||
| 1883 | |||
| 1884 | if (sel->target == V4L2_SEL_TGT_CROP) { | ||
| 1885 | /* | ||
| 1886 | * Clamp the crop rectangle. Demosaicing removes 4 pixels on | ||
| 1887 | * each side of the image. | ||
| 1888 | */ | ||
| 1889 | crop->left = clamp_t(unsigned int, ALIGN(sel->r.left, 2), 4, | ||
| 1890 | format->width - 4 - | ||
| 1891 | MT9M114_SCALER_CROPPED_INPUT_WIDTH); | ||
| 1892 | crop->top = clamp_t(unsigned int, ALIGN(sel->r.top, 2), 4, | ||
| 1893 | format->height - 4 - | ||
| 1894 | MT9M114_SCALER_CROPPED_INPUT_HEIGHT); | ||
| 1895 | crop->width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), | ||
| 1896 | MT9M114_SCALER_CROPPED_INPUT_WIDTH, | ||
| 1897 | format->width - 4 - crop->left); | ||
| 1898 | crop->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), | ||
| 1899 | MT9M114_SCALER_CROPPED_INPUT_HEIGHT, | ||
| 1900 | format->height - 4 - crop->top); | ||
| 1901 | |||
| 1902 | sel->r = *crop; | ||
| 1903 | |||
| 1904 | /* Propagate to the compose rectangle. */ | ||
| 1905 | compose->width = crop->width; | ||
| 1906 | compose->height = crop->height; | ||
| 1907 | } else { | ||
| 1908 | /* | ||
| 1909 | * Clamp the compose rectangle. The scaler can only downscale. | ||
| 1910 | */ | ||
| 1911 | compose->left = 0; | ||
| 1912 | compose->top = 0; | ||
| 1913 | compose->width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), | ||
| 1914 | MT9M114_SCALER_CROPPED_INPUT_WIDTH, | ||
| 1915 | crop->width); | ||
| 1916 | compose->height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), | ||
| 1917 | MT9M114_SCALER_CROPPED_INPUT_HEIGHT, | ||
| 1918 | crop->height); | ||
| 1919 | |||
| 1920 | sel->r = *compose; | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | /* Propagate the compose rectangle to the source format. */ | ||
| 1924 | format = v4l2_subdev_get_pad_format(sd, state, 1); | ||
| 1925 | format->width = compose->width; | ||
| 1926 | format->height = compose->height; | ||
| 1927 | |||
| 1928 | return 0; | ||
| 1929 | } | ||
| 1930 | |||
| 1931 | static void mt9m114_ifp_unregistered(struct v4l2_subdev *sd) | ||
| 1932 | { | ||
| 1933 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1934 | |||
| 1935 | v4l2_device_unregister_subdev(&sensor->pa.sd); | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | static int mt9m114_ifp_registered(struct v4l2_subdev *sd) | ||
| 1939 | { | ||
| 1940 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 1941 | int ret; | ||
| 1942 | |||
| 1943 | ret = v4l2_device_register_subdev(sd->v4l2_dev, &sensor->pa.sd); | ||
| 1944 | if (ret < 0) { | ||
| 1945 | dev_err(&sensor->client->dev, | ||
| 1946 | "Failed to register pixel array subdev\n"); | ||
| 1947 | return ret; | ||
| 1948 | } | ||
| 1949 | |||
| 1950 | ret = media_create_pad_link(&sensor->pa.sd.entity, 0, | ||
| 1951 | &sensor->ifp.sd.entity, 0, | ||
| 1952 | MEDIA_LNK_FL_ENABLED | | ||
| 1953 | MEDIA_LNK_FL_IMMUTABLE); | ||
| 1954 | if (ret < 0) { | ||
| 1955 | dev_err(&sensor->client->dev, | ||
| 1956 | "Failed to link pixel array to ifp\n"); | ||
| 1957 | v4l2_device_unregister_subdev(&sensor->pa.sd); | ||
| 1958 | return ret; | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | return 0; | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | static const struct v4l2_subdev_video_ops mt9m114_ifp_video_ops = { | ||
| 1965 | .s_stream = mt9m114_ifp_s_stream, | ||
| 1966 | .g_frame_interval = mt9m114_ifp_g_frame_interval, | ||
| 1967 | .s_frame_interval = mt9m114_ifp_s_frame_interval, | ||
| 1968 | }; | ||
| 1969 | |||
| 1970 | static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = { | ||
| 1971 | .init_cfg = mt9m114_ifp_init_cfg, | ||
| 1972 | .enum_mbus_code = mt9m114_ifp_enum_mbus_code, | ||
| 1973 | .enum_frame_size = mt9m114_ifp_enum_framesizes, | ||
| 1974 | .enum_frame_interval = mt9m114_ifp_enum_frameintervals, | ||
| 1975 | .get_fmt = v4l2_subdev_get_fmt, | ||
| 1976 | .set_fmt = mt9m114_ifp_set_fmt, | ||
| 1977 | .get_selection = mt9m114_ifp_get_selection, | ||
| 1978 | .set_selection = mt9m114_ifp_set_selection, | ||
| 1979 | }; | ||
| 1980 | |||
| 1981 | static const struct v4l2_subdev_ops mt9m114_ifp_ops = { | ||
| 1982 | .video = &mt9m114_ifp_video_ops, | ||
| 1983 | .pad = &mt9m114_ifp_pad_ops, | ||
| 1984 | }; | ||
| 1985 | |||
| 1986 | static const struct v4l2_subdev_internal_ops mt9m114_ifp_internal_ops = { | ||
| 1987 | .registered = mt9m114_ifp_registered, | ||
| 1988 | .unregistered = mt9m114_ifp_unregistered, | ||
| 1989 | }; | ||
| 1990 | |||
| 1991 | static int mt9m114_ifp_init(struct mt9m114 *sensor) | ||
| 1992 | { | ||
| 1993 | struct v4l2_subdev *sd = &sensor->ifp.sd; | ||
| 1994 | struct media_pad *pads = sensor->ifp.pads; | ||
| 1995 | struct v4l2_ctrl_handler *hdl = &sensor->ifp.hdl; | ||
| 1996 | struct v4l2_ctrl *link_freq; | ||
| 1997 | int ret; | ||
| 1998 | |||
| 1999 | /* Initialize the subdev. */ | ||
| 2000 | v4l2_i2c_subdev_init(sd, sensor->client, &mt9m114_ifp_ops); | ||
| 2001 | v4l2_i2c_subdev_set_name(sd, sensor->client, NULL, " ifp"); | ||
| 2002 | |||
| 2003 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
| 2004 | sd->internal_ops = &mt9m114_ifp_internal_ops; | ||
| 2005 | |||
| 2006 | /* Initialize the media entity. */ | ||
| 2007 | sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP; | ||
| 2008 | sd->entity.ops = &mt9m114_entity_ops; | ||
| 2009 | pads[0].flags = MEDIA_PAD_FL_SINK; | ||
| 2010 | pads[1].flags = MEDIA_PAD_FL_SOURCE; | ||
| 2011 | ret = media_entity_pads_init(&sd->entity, 2, pads); | ||
| 2012 | if (ret < 0) | ||
| 2013 | return ret; | ||
| 2014 | |||
| 2015 | sensor->ifp.frame_rate = MT9M114_DEF_FRAME_RATE; | ||
| 2016 | |||
| 2017 | /* Initialize the control handler. */ | ||
| 2018 | v4l2_ctrl_handler_init(hdl, 8); | ||
| 2019 | v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2020 | V4L2_CID_AUTO_WHITE_BALANCE, | ||
| 2021 | 0, 1, 1, 1); | ||
| 2022 | v4l2_ctrl_new_std_menu(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2023 | V4L2_CID_EXPOSURE_AUTO, | ||
| 2024 | V4L2_EXPOSURE_MANUAL, 0, | ||
| 2025 | V4L2_EXPOSURE_AUTO); | ||
| 2026 | |||
| 2027 | link_freq = v4l2_ctrl_new_int_menu(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2028 | V4L2_CID_LINK_FREQ, | ||
| 2029 | sensor->bus_cfg.nr_of_link_frequencies - 1, | ||
| 2030 | 0, sensor->bus_cfg.link_frequencies); | ||
| 2031 | if (link_freq) | ||
| 2032 | link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 2033 | |||
| 2034 | v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2035 | V4L2_CID_PIXEL_RATE, | ||
| 2036 | sensor->pixrate, sensor->pixrate, 1, | ||
| 2037 | sensor->pixrate); | ||
| 2038 | |||
| 2039 | sensor->ifp.tpg[MT9M114_TPG_PATTERN] = | ||
| 2040 | v4l2_ctrl_new_std_menu_items(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2041 | V4L2_CID_TEST_PATTERN, | ||
| 2042 | ARRAY_SIZE(mt9m114_test_pattern_menu) - 1, | ||
| 2043 | 0, 0, mt9m114_test_pattern_menu); | ||
| 2044 | sensor->ifp.tpg[MT9M114_TPG_RED] = | ||
| 2045 | v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2046 | V4L2_CID_TEST_PATTERN_RED, | ||
| 2047 | 0, 1023, 1, 1023); | ||
| 2048 | sensor->ifp.tpg[MT9M114_TPG_GREEN] = | ||
| 2049 | v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2050 | V4L2_CID_TEST_PATTERN_GREENR, | ||
| 2051 | 0, 1023, 1, 1023); | ||
| 2052 | sensor->ifp.tpg[MT9M114_TPG_BLUE] = | ||
| 2053 | v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops, | ||
| 2054 | V4L2_CID_TEST_PATTERN_BLUE, | ||
| 2055 | 0, 1023, 1, 1023); | ||
| 2056 | |||
| 2057 | v4l2_ctrl_cluster(ARRAY_SIZE(sensor->ifp.tpg), sensor->ifp.tpg); | ||
| 2058 | |||
| 2059 | if (hdl->error) { | ||
| 2060 | ret = hdl->error; | ||
| 2061 | goto error; | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | sd->ctrl_handler = hdl; | ||
| 2065 | sd->state_lock = hdl->lock; | ||
| 2066 | |||
| 2067 | ret = v4l2_subdev_init_finalize(sd); | ||
| 2068 | if (ret) | ||
| 2069 | goto error; | ||
| 2070 | |||
| 2071 | return 0; | ||
| 2072 | |||
| 2073 | error: | ||
| 2074 | v4l2_ctrl_handler_free(&sensor->ifp.hdl); | ||
| 2075 | media_entity_cleanup(&sensor->ifp.sd.entity); | ||
| 2076 | return ret; | ||
| 2077 | } | ||
| 2078 | |||
| 2079 | static void mt9m114_ifp_cleanup(struct mt9m114 *sensor) | ||
| 2080 | { | ||
| 2081 | v4l2_ctrl_handler_free(&sensor->ifp.hdl); | ||
| 2082 | media_entity_cleanup(&sensor->ifp.sd.entity); | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | /* ----------------------------------------------------------------------------- | ||
| 2086 | * Power Management | ||
| 2087 | */ | ||
| 2088 | |||
| 2089 | static int mt9m114_power_on(struct mt9m114 *sensor) | ||
| 2090 | { | ||
| 2091 | int ret; | ||
| 2092 | |||
| 2093 | /* Enable power and clocks. */ | ||
| 2094 | ret = regulator_bulk_enable(ARRAY_SIZE(sensor->supplies), | ||
| 2095 | sensor->supplies); | ||
| 2096 | if (ret < 0) | ||
| 2097 | return ret; | ||
| 2098 | |||
| 2099 | ret = clk_prepare_enable(sensor->clk); | ||
| 2100 | if (ret < 0) | ||
| 2101 | goto error_regulator; | ||
| 2102 | |||
| 2103 | /* Perform a hard reset if available, or a soft reset otherwise. */ | ||
| 2104 | if (sensor->reset) { | ||
| 2105 | long freq = clk_get_rate(sensor->clk); | ||
| 2106 | unsigned int duration; | ||
| 2107 | |||
| 2108 | /* | ||
| 2109 | * The minimum duration is 50 clock cycles, thus typically | ||
| 2110 | * around 2µs. Double it to be safe. | ||
| 2111 | */ | ||
| 2112 | duration = DIV_ROUND_UP(2 * 50 * 1000000, freq); | ||
| 2113 | |||
| 2114 | gpiod_set_value(sensor->reset, 1); | ||
| 2115 | udelay(duration); | ||
| 2116 | gpiod_set_value(sensor->reset, 0); | ||
| 2117 | } else { | ||
| 2118 | /* | ||
| 2119 | * The power may have just been turned on, we need to wait for | ||
| 2120 | * the sensor to be ready to accept I2C commands. | ||
| 2121 | */ | ||
| 2122 | usleep_range(44500, 50000); | ||
| 2123 | |||
| 2124 | cci_write(sensor->regmap, MT9M114_RESET_AND_MISC_CONTROL, | ||
| 2125 | MT9M114_RESET_SOC, &ret); | ||
| 2126 | cci_write(sensor->regmap, MT9M114_RESET_AND_MISC_CONTROL, 0, | ||
| 2127 | &ret); | ||
| 2128 | |||
| 2129 | if (ret < 0) { | ||
| 2130 | dev_err(&sensor->client->dev, "Soft reset failed\n"); | ||
| 2131 | goto error_clock; | ||
| 2132 | } | ||
| 2133 | } | ||
| 2134 | |||
| 2135 | /* | ||
| 2136 | * Wait for the sensor to be ready to accept I2C commands by polling the | ||
| 2137 | * command register to wait for initialization to complete. | ||
| 2138 | */ | ||
| 2139 | usleep_range(44500, 50000); | ||
| 2140 | |||
| 2141 | ret = mt9m114_poll_command(sensor, MT9M114_COMMAND_REGISTER_SET_STATE); | ||
| 2142 | if (ret < 0) | ||
| 2143 | goto error_clock; | ||
| 2144 | |||
| 2145 | if (sensor->bus_cfg.bus_type == V4L2_MBUS_PARALLEL) { | ||
| 2146 | /* | ||
| 2147 | * In parallel mode (OE set to low), the sensor will enter the | ||
| 2148 | * streaming state after initialization. Enter the standby | ||
| 2149 | * manually to stop streaming. | ||
| 2150 | */ | ||
| 2151 | ret = mt9m114_set_state(sensor, | ||
| 2152 | MT9M114_SYS_STATE_ENTER_STANDBY); | ||
| 2153 | if (ret < 0) | ||
| 2154 | goto error_clock; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | /* | ||
| 2158 | * Before issuing any Set-State command, we must ensure that the sensor | ||
| 2159 | * reaches the standby mode (either initiated manually above in | ||
| 2160 | * parallel mode, or automatically after reset in MIPI mode). | ||
| 2161 | */ | ||
| 2162 | ret = mt9m114_poll_state(sensor, MT9M114_SYS_STATE_STANDBY); | ||
| 2163 | if (ret < 0) | ||
| 2164 | goto error_clock; | ||
| 2165 | |||
| 2166 | return 0; | ||
| 2167 | |||
| 2168 | error_clock: | ||
| 2169 | clk_disable_unprepare(sensor->clk); | ||
| 2170 | error_regulator: | ||
| 2171 | regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies); | ||
| 2172 | return ret; | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | static void mt9m114_power_off(struct mt9m114 *sensor) | ||
| 2176 | { | ||
| 2177 | clk_disable_unprepare(sensor->clk); | ||
| 2178 | regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies); | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | static int __maybe_unused mt9m114_runtime_resume(struct device *dev) | ||
| 2182 | { | ||
| 2183 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2184 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 2185 | int ret; | ||
| 2186 | |||
| 2187 | ret = mt9m114_power_on(sensor); | ||
| 2188 | if (ret) | ||
| 2189 | return ret; | ||
| 2190 | |||
| 2191 | ret = mt9m114_initialize(sensor); | ||
| 2192 | if (ret) { | ||
| 2193 | mt9m114_power_off(sensor); | ||
| 2194 | return ret; | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | return 0; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | static int __maybe_unused mt9m114_runtime_suspend(struct device *dev) | ||
| 2201 | { | ||
| 2202 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2203 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 2204 | |||
| 2205 | mt9m114_power_off(sensor); | ||
| 2206 | |||
| 2207 | return 0; | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | static const struct dev_pm_ops mt9m114_pm_ops = { | ||
| 2211 | SET_RUNTIME_PM_OPS(mt9m114_runtime_suspend, mt9m114_runtime_resume, NULL) | ||
| 2212 | }; | ||
| 2213 | |||
| 2214 | /* ----------------------------------------------------------------------------- | ||
| 2215 | * Probe & Remove | ||
| 2216 | */ | ||
| 2217 | |||
| 2218 | static int mt9m114_clk_init(struct mt9m114 *sensor) | ||
| 2219 | { | ||
| 2220 | unsigned int link_freq; | ||
| 2221 | |||
| 2222 | /* Hardcode the PLL multiplier and dividers to default settings. */ | ||
| 2223 | sensor->pll.m = 32; | ||
| 2224 | sensor->pll.n = 1; | ||
| 2225 | sensor->pll.p = 7; | ||
| 2226 | |||
| 2227 | /* | ||
| 2228 | * Calculate the pixel rate and link frequency. The CSI-2 bus is clocked | ||
| 2229 | * for 16-bit per pixel, transmitted in DDR over a single lane. For | ||
| 2230 | * parallel mode, the sensor ouputs one pixel in two PIXCLK cycles. | ||
| 2231 | */ | ||
| 2232 | sensor->pixrate = clk_get_rate(sensor->clk) * sensor->pll.m | ||
| 2233 | / ((sensor->pll.n + 1) * (sensor->pll.p + 1)); | ||
| 2234 | |||
| 2235 | link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY | ||
| 2236 | ? sensor->pixrate * 8 : sensor->pixrate * 2; | ||
| 2237 | |||
| 2238 | if (sensor->bus_cfg.nr_of_link_frequencies != 1 || | ||
| 2239 | sensor->bus_cfg.link_frequencies[0] != link_freq) { | ||
| 2240 | dev_err(&sensor->client->dev, "Unsupported DT link-frequencies\n"); | ||
| 2241 | return -EINVAL; | ||
| 2242 | } | ||
| 2243 | |||
| 2244 | return 0; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | static int mt9m114_identify(struct mt9m114 *sensor) | ||
| 2248 | { | ||
| 2249 | u64 major, minor, release, customer; | ||
| 2250 | u64 value; | ||
| 2251 | int ret; | ||
| 2252 | |||
| 2253 | ret = cci_read(sensor->regmap, MT9M114_CHIP_ID, &value, NULL); | ||
| 2254 | if (ret) { | ||
| 2255 | dev_err(&sensor->client->dev, "Failed to read chip ID\n"); | ||
| 2256 | return -ENXIO; | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | if (value != 0x2481) { | ||
| 2260 | dev_err(&sensor->client->dev, "Invalid chip ID 0x%04llx\n", | ||
| 2261 | value); | ||
| 2262 | return -ENXIO; | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | cci_read(sensor->regmap, MT9M114_MON_MAJOR_VERSION, &major, &ret); | ||
| 2266 | cci_read(sensor->regmap, MT9M114_MON_MINOR_VERSION, &minor, &ret); | ||
| 2267 | cci_read(sensor->regmap, MT9M114_MON_RELEASE_VERSION, &release, &ret); | ||
| 2268 | cci_read(sensor->regmap, MT9M114_CUSTOMER_REV, &customer, &ret); | ||
| 2269 | if (ret) { | ||
| 2270 | dev_err(&sensor->client->dev, "Failed to read version\n"); | ||
| 2271 | return -ENXIO; | ||
| 2272 | } | ||
| 2273 | |||
| 2274 | dev_dbg(&sensor->client->dev, | ||
| 2275 | "monitor v%llu.%llu.%04llx customer rev 0x%04llx\n", | ||
| 2276 | major, minor, release, customer); | ||
| 2277 | |||
| 2278 | return 0; | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | static int mt9m114_parse_dt(struct mt9m114 *sensor) | ||
| 2282 | { | ||
| 2283 | struct fwnode_handle *fwnode = dev_fwnode(&sensor->client->dev); | ||
| 2284 | struct fwnode_handle *ep; | ||
| 2285 | int ret; | ||
| 2286 | |||
| 2287 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); | ||
| 2288 | if (!ep) { | ||
| 2289 | dev_err(&sensor->client->dev, "No endpoint found\n"); | ||
| 2290 | return -EINVAL; | ||
| 2291 | } | ||
| 2292 | |||
| 2293 | sensor->bus_cfg.bus_type = V4L2_MBUS_UNKNOWN; | ||
| 2294 | ret = v4l2_fwnode_endpoint_alloc_parse(ep, &sensor->bus_cfg); | ||
| 2295 | fwnode_handle_put(ep); | ||
| 2296 | if (ret < 0) { | ||
| 2297 | dev_err(&sensor->client->dev, "Failed to parse endpoint\n"); | ||
| 2298 | goto error; | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | switch (sensor->bus_cfg.bus_type) { | ||
| 2302 | case V4L2_MBUS_CSI2_DPHY: | ||
| 2303 | case V4L2_MBUS_PARALLEL: | ||
| 2304 | break; | ||
| 2305 | |||
| 2306 | default: | ||
| 2307 | dev_err(&sensor->client->dev, "unsupported bus type %u\n", | ||
| 2308 | sensor->bus_cfg.bus_type); | ||
| 2309 | ret = -EINVAL; | ||
| 2310 | goto error; | ||
| 2311 | } | ||
| 2312 | |||
| 2313 | return 0; | ||
| 2314 | |||
| 2315 | error: | ||
| 2316 | v4l2_fwnode_endpoint_free(&sensor->bus_cfg); | ||
| 2317 | return ret; | ||
| 2318 | } | ||
| 2319 | |||
| 2320 | static int mt9m114_probe(struct i2c_client *client) | ||
| 2321 | { | ||
| 2322 | struct device *dev = &client->dev; | ||
| 2323 | struct mt9m114 *sensor; | ||
| 2324 | int ret; | ||
| 2325 | |||
| 2326 | sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); | ||
| 2327 | if (!sensor) | ||
| 2328 | return -ENOMEM; | ||
| 2329 | |||
| 2330 | sensor->client = client; | ||
| 2331 | |||
| 2332 | sensor->regmap = devm_cci_regmap_init_i2c(client, 16); | ||
| 2333 | if (IS_ERR(sensor->regmap)) { | ||
| 2334 | dev_err(dev, "Unable to initialize I2C\n"); | ||
| 2335 | return -ENODEV; | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | ret = mt9m114_parse_dt(sensor); | ||
| 2339 | if (ret < 0) | ||
| 2340 | return ret; | ||
| 2341 | |||
| 2342 | /* Acquire clocks, GPIOs and regulators. */ | ||
| 2343 | sensor->clk = devm_clk_get(dev, NULL); | ||
| 2344 | if (IS_ERR(sensor->clk)) { | ||
| 2345 | ret = PTR_ERR(sensor->clk); | ||
| 2346 | dev_err_probe(dev, ret, "Failed to get clock\n"); | ||
| 2347 | goto error_ep_free; | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); | ||
| 2351 | if (IS_ERR(sensor->reset)) { | ||
| 2352 | ret = PTR_ERR(sensor->reset); | ||
| 2353 | dev_err_probe(dev, ret, "Failed to get reset GPIO\n"); | ||
| 2354 | goto error_ep_free; | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | sensor->supplies[0].supply = "vddio"; | ||
| 2358 | sensor->supplies[1].supply = "vdd"; | ||
| 2359 | sensor->supplies[2].supply = "vaa"; | ||
| 2360 | |||
| 2361 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sensor->supplies), | ||
| 2362 | sensor->supplies); | ||
| 2363 | if (ret < 0) { | ||
| 2364 | dev_err_probe(dev, ret, "Failed to get regulators\n"); | ||
| 2365 | goto error_ep_free; | ||
| 2366 | } | ||
| 2367 | |||
| 2368 | ret = mt9m114_clk_init(sensor); | ||
| 2369 | if (ret) | ||
| 2370 | goto error_ep_free; | ||
| 2371 | |||
| 2372 | /* | ||
| 2373 | * Identify the sensor. The driver supports runtime PM, but needs to | ||
| 2374 | * work when runtime PM is disabled in the kernel. To that end, power | ||
| 2375 | * the sensor on manually here, and initialize it after identification | ||
| 2376 | * to reach the same state as if resumed through runtime PM. | ||
| 2377 | */ | ||
| 2378 | ret = mt9m114_power_on(sensor); | ||
| 2379 | if (ret < 0) { | ||
| 2380 | dev_err_probe(dev, ret, "Could not power on the device\n"); | ||
| 2381 | goto error_ep_free; | ||
| 2382 | } | ||
| 2383 | |||
| 2384 | ret = mt9m114_identify(sensor); | ||
| 2385 | if (ret < 0) | ||
| 2386 | goto error_power_off; | ||
| 2387 | |||
| 2388 | ret = mt9m114_initialize(sensor); | ||
| 2389 | if (ret < 0) | ||
| 2390 | goto error_power_off; | ||
| 2391 | |||
| 2392 | /* | ||
| 2393 | * Enable runtime PM with autosuspend. As the device has been powered | ||
| 2394 | * manually, mark it as active, and increase the usage count without | ||
| 2395 | * resuming the device. | ||
| 2396 | */ | ||
| 2397 | pm_runtime_set_active(dev); | ||
| 2398 | pm_runtime_get_noresume(dev); | ||
| 2399 | pm_runtime_enable(dev); | ||
| 2400 | pm_runtime_set_autosuspend_delay(dev, 1000); | ||
| 2401 | pm_runtime_use_autosuspend(dev); | ||
| 2402 | |||
| 2403 | /* Initialize the subdevices. */ | ||
| 2404 | ret = mt9m114_pa_init(sensor); | ||
| 2405 | if (ret < 0) | ||
| 2406 | goto error_pm_cleanup; | ||
| 2407 | |||
| 2408 | ret = mt9m114_ifp_init(sensor); | ||
| 2409 | if (ret < 0) | ||
| 2410 | goto error_pa_cleanup; | ||
| 2411 | |||
| 2412 | ret = v4l2_async_register_subdev(&sensor->ifp.sd); | ||
| 2413 | if (ret < 0) | ||
| 2414 | goto error_ifp_cleanup; | ||
| 2415 | |||
| 2416 | /* | ||
| 2417 | * Decrease the PM usage count. The device will get suspended after the | ||
| 2418 | * autosuspend delay, turning the power off. | ||
| 2419 | */ | ||
| 2420 | pm_runtime_mark_last_busy(dev); | ||
| 2421 | pm_runtime_put_autosuspend(dev); | ||
| 2422 | |||
| 2423 | return 0; | ||
| 2424 | |||
| 2425 | error_ifp_cleanup: | ||
| 2426 | mt9m114_ifp_cleanup(sensor); | ||
| 2427 | error_pa_cleanup: | ||
| 2428 | mt9m114_pa_cleanup(sensor); | ||
| 2429 | error_pm_cleanup: | ||
| 2430 | pm_runtime_disable(dev); | ||
| 2431 | pm_runtime_put_noidle(dev); | ||
| 2432 | error_power_off: | ||
| 2433 | mt9m114_power_off(sensor); | ||
| 2434 | error_ep_free: | ||
| 2435 | v4l2_fwnode_endpoint_free(&sensor->bus_cfg); | ||
| 2436 | return ret; | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | static void mt9m114_remove(struct i2c_client *client) | ||
| 2440 | { | ||
| 2441 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 2442 | struct mt9m114 *sensor = ifp_to_mt9m114(sd); | ||
| 2443 | struct device *dev = &client->dev; | ||
| 2444 | |||
| 2445 | v4l2_async_unregister_subdev(&sensor->ifp.sd); | ||
| 2446 | |||
| 2447 | mt9m114_ifp_cleanup(sensor); | ||
| 2448 | mt9m114_pa_cleanup(sensor); | ||
| 2449 | v4l2_fwnode_endpoint_free(&sensor->bus_cfg); | ||
| 2450 | |||
| 2451 | /* | ||
| 2452 | * Disable runtime PM. In case runtime PM is disabled in the kernel, | ||
| 2453 | * make sure to turn power off manually. | ||
| 2454 | */ | ||
| 2455 | pm_runtime_disable(dev); | ||
| 2456 | if (!pm_runtime_status_suspended(dev)) | ||
| 2457 | mt9m114_power_off(sensor); | ||
| 2458 | pm_runtime_set_suspended(dev); | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | static const struct of_device_id mt9m114_of_ids[] = { | ||
| 2462 | { .compatible = "onnn,mt9m114" }, | ||
| 2463 | { /* sentinel */ }, | ||
| 2464 | }; | ||
| 2465 | MODULE_DEVICE_TABLE(of, mt9m114_of_ids); | ||
| 2466 | |||
| 2467 | static struct i2c_driver mt9m114_driver = { | ||
| 2468 | .driver = { | ||
| 2469 | .name = "mt9m114", | ||
| 2470 | .pm = &mt9m114_pm_ops, | ||
| 2471 | .of_match_table = mt9m114_of_ids, | ||
| 2472 | }, | ||
| 2473 | .probe = mt9m114_probe, | ||
| 2474 | .remove = mt9m114_remove, | ||
| 2475 | }; | ||
| 2476 | |||
| 2477 | module_i2c_driver(mt9m114_driver); | ||
| 2478 | |||
| 2479 | MODULE_DESCRIPTION("onsemi MT9M114 Sensor Driver"); | ||
| 2480 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
| 2481 | MODULE_LICENSE("GPL"); | ||
| @@ -49,9 +49,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); · 48 unmodified lines | |||
| 49 | 49 | ||
| 50 | struct mt9v011 { | 50 | struct mt9v011 { |
| 51 | struct v4l2_subdev sd; | 51 | struct v4l2_subdev sd; |
| 52 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 53 | struct media_pad pad; | 52 | struct media_pad pad; |
| 54 | #endif | ||
| 55 | struct v4l2_ctrl_handler ctrls; | 53 | struct v4l2_ctrl_handler ctrls; |
| 56 | unsigned width, height; | 54 | unsigned width, height; |
| 57 | unsigned xtal; | 55 | unsigned xtal; |
| @@ -483,9 +481,7 @@ static int mt9v011_probe(struct i2c_client *c) · 425 unmodified lines | |||
| 483 | u16 version; | 481 | u16 version; |
| 484 | struct mt9v011 *core; | 482 | struct mt9v011 *core; |
| 485 | struct v4l2_subdev *sd; | 483 | struct v4l2_subdev *sd; |
| 486 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 487 | int ret; | 484 | int ret; |
| 488 | #endif | ||
| 489 | 485 | ||
| 490 | /* Check if the adapter supports the needed features */ | 486 | /* Check if the adapter supports the needed features */ |
| 491 | if (!i2c_check_functionality(c->adapter, | 487 | if (!i2c_check_functionality(c->adapter, |
| @@ -499,14 +495,12 @@ static int mt9v011_probe(struct i2c_client *c) · 7 unmodified lines | |||
| 499 | sd = &core->sd; | 495 | sd = &core->sd; |
| 500 | v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); | 496 | v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); |
| 501 | 497 | ||
| 502 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 503 | core->pad.flags = MEDIA_PAD_FL_SOURCE; | 498 | core->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 504 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; | 499 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 505 | 500 | ||
| 506 | ret = media_entity_pads_init(&sd->entity, 1, &core->pad); | 501 | ret = media_entity_pads_init(&sd->entity, 1, &core->pad); |
| 507 | if (ret < 0) | 502 | if (ret < 0) |
| 508 | return ret; | 503 | return ret; |
| 509 | #endif | ||
| 510 | 504 | ||
| 511 | /* Check if the sensor is really a MT9V011 */ | 505 | /* Check if the sensor is really a MT9V011 */ |
| 512 | version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); | 506 | version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/gpio/consumer.h> | 14 | #include <linux/gpio/consumer.h> |
| 15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
| 16 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
| 17 | #include <linux/mod_devicetable.h> | ||
| 17 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| 18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
| 19 | #include <linux/of_graph.h> | 20 | #include <linux/of_graph.h> |
| @@ -1046,7 +1047,6 @@ done: · 1026 unmodified lines | |||
| 1046 | 1047 | ||
| 1047 | static int mt9v032_probe(struct i2c_client *client) | 1048 | static int mt9v032_probe(struct i2c_client *client) |
| 1048 | { | 1049 | { |
| 1049 | const struct i2c_device_id *did = i2c_client_get_device_id(client); | ||
| 1050 | struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client); | 1050 | struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client); |
| 1051 | struct mt9v032 *mt9v032; | 1051 | struct mt9v032 *mt9v032; |
| 1052 | unsigned int i; | 1052 | unsigned int i; |
| @@ -1076,7 +1076,7 @@ static int mt9v032_probe(struct i2c_client *client) · 23 unmodified lines | |||
| 1076 | 1076 | ||
| 1077 | mutex_init(&mt9v032->power_lock); | 1077 | mutex_init(&mt9v032->power_lock); |
| 1078 | mt9v032->pdata = pdata; | 1078 | mt9v032->pdata = pdata; |
| 1079 | mt9v032->model = (const void *)did->driver_data; | 1079 | mt9v032->model = i2c_get_match_data(client); |
| 1080 | 1080 | ||
| 1081 | v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 + | 1081 | v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 + |
| 1082 | ARRAY_SIZE(mt9v032_aegc_controls)); | 1082 | ARRAY_SIZE(mt9v032_aegc_controls)); |
| @@ -1272,29 +1272,27 @@ static const struct i2c_device_id mt9v032_id[] = { · 189 unmodified lines | |||
| 1272 | { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, | 1272 | { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, |
| 1273 | { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, | 1273 | { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, |
| 1274 | { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] }, | 1274 | { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] }, |
| 1275 | { } | 1275 | { /* Sentinel */ } |
| 1276 | }; | 1276 | }; |
| 1277 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); | 1277 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); |
| 1278 | 1278 | ||
| 1279 | #if IS_ENABLED(CONFIG_OF) | ||
| 1280 | static const struct of_device_id mt9v032_of_match[] = { | 1279 | static const struct of_device_id mt9v032_of_match[] = { |
| 1281 | { .compatible = "aptina,mt9v022" }, | 1280 | { .compatible = "aptina,mt9v022", .data = &mt9v032_models[MT9V032_MODEL_V022_COLOR] }, |
| 1282 | { .compatible = "aptina,mt9v022m" }, | 1281 | { .compatible = "aptina,mt9v022m", .data = &mt9v032_models[MT9V032_MODEL_V022_MONO] }, |
| 1283 | { .compatible = "aptina,mt9v024" }, | 1282 | { .compatible = "aptina,mt9v024", .data = &mt9v032_models[MT9V032_MODEL_V024_COLOR] }, |
| 1284 | { .compatible = "aptina,mt9v024m" }, | 1283 | { .compatible = "aptina,mt9v024m", .data = &mt9v032_models[MT9V032_MODEL_V024_MONO] }, |
| 1285 | { .compatible = "aptina,mt9v032" }, | 1284 | { .compatible = "aptina,mt9v032", .data = &mt9v032_models[MT9V032_MODEL_V032_COLOR] }, |
| 1286 | { .compatible = "aptina,mt9v032m" }, | 1285 | { .compatible = "aptina,mt9v032m", .data = &mt9v032_models[MT9V032_MODEL_V032_MONO] }, |
| 1287 | { .compatible = "aptina,mt9v034" }, | 1286 | { .compatible = "aptina,mt9v034", .data = &mt9v032_models[MT9V032_MODEL_V034_COLOR] }, |
| 1288 | { .compatible = "aptina,mt9v034m" }, | 1287 | { .compatible = "aptina,mt9v034m", .data = &mt9v032_models[MT9V032_MODEL_V034_MONO] }, |
| 1289 | { /* Sentinel */ } | 1288 | { /* Sentinel */ } |
| 1290 | }; | 1289 | }; |
| 1291 | MODULE_DEVICE_TABLE(of, mt9v032_of_match); | 1290 | MODULE_DEVICE_TABLE(of, mt9v032_of_match); |
| 1292 | #endif | ||
| 1293 | 1291 | ||
| 1294 | static struct i2c_driver mt9v032_driver = { | 1292 | static struct i2c_driver mt9v032_driver = { |
| 1295 | .driver = { | 1293 | .driver = { |
| 1296 | .name = "mt9v032", | 1294 | .name = "mt9v032", |
| 1297 | .of_match_table = of_match_ptr(mt9v032_of_match), | 1295 | .of_match_table = mt9v032_of_match, |
| 1298 | }, | 1296 | }, |
| 1299 | .probe = mt9v032_probe, | 1297 | .probe = mt9v032_probe, |
| 1300 | .remove = mt9v032_remove, | 1298 | .remove = mt9v032_remove, |
| @@ -121,9 +121,7 @@ struct mt9v111_dev { · 120 unmodified lines | |||
| 121 | u8 addr_space; | 121 | u8 addr_space; |
| 122 | 122 | ||
| 123 | struct v4l2_subdev sd; | 123 | struct v4l2_subdev sd; |
| 124 | #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | ||
| 125 | struct media_pad pad; | 124 | struct media_pad pad; |
| 126 | #endif | ||
| 127 | 125 | ||
| 128 | struct v4l2_ctrl *auto_awb; | 126 | struct v4l2_ctrl *auto_awb; |
| 129 | struct v4l2_ctrl *auto_exp; | 127 | struct v4l2_ctrl *auto_exp; |
| @@ -797,11 +795,7 @@ static struct v4l2_mbus_framefmt *__mt9v111_get_pad_format( · 667 unmodified lines | |||
| 797 | { | 795 | { |
| 798 | switch (which) { | 796 | switch (which) { |
| 799 | case V4L2_SUBDEV_FORMAT_TRY: | 797 | case V4L2_SUBDEV_FORMAT_TRY: |
| 800 | #if IS_ENABLED(CONFIG_VIDEO_V4L2_SUBDEV_API) | ||
| 801 | return v4l2_subdev_get_try_format(&mt9v111->sd, sd_state, pad); | 798 | return v4l2_subdev_get_try_format(&mt9v111->sd, sd_state, pad); |
| 802 | #else | ||
| 803 | return &sd_state->pads->try_fmt; | ||
| 804 | #endif | ||
| 805 | case V4L2_SUBDEV_FORMAT_ACTIVE: | 799 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
| 806 | return &mt9v111->fmt; | 800 | return &mt9v111->fmt; |
| 807 | default: | 801 | default: |
| @@ -987,11 +981,9 @@ static const struct v4l2_subdev_ops mt9v111_ops = { · 179 unmodified lines | |||
| 987 | .pad = &mt9v111_pad_ops, | 981 | .pad = &mt9v111_pad_ops, |
| 988 | }; | 982 | }; |
| 989 | 983 | ||
| 990 | #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | ||
| 991 | static const struct media_entity_operations mt9v111_subdev_entity_ops = { | 984 | static const struct media_entity_operations mt9v111_subdev_entity_ops = { |
| 992 | .link_validate = v4l2_subdev_link_validate, | 985 | .link_validate = v4l2_subdev_link_validate, |
| 993 | }; | 986 | }; |
| 994 | #endif | ||
| 995 | 987 | ||
| 996 | /* --- V4L2 ctrl --- */ | 988 | /* --- V4L2 ctrl --- */ |
| 997 | static int mt9v111_s_ctrl(struct v4l2_ctrl *ctrl) | 989 | static int mt9v111_s_ctrl(struct v4l2_ctrl *ctrl) |
| @@ -1203,7 +1195,6 @@ static int mt9v111_probe(struct i2c_client *client) · 205 unmodified lines | |||
| 1203 | 1195 | ||
| 1204 | v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops); | 1196 | v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops); |
| 1205 | 1197 | ||
| 1206 | #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | ||
| 1207 | mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1198 | mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1208 | mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops; | 1199 | mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops; |
| 1209 | mt9v111->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1200 | mt9v111->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| @@ -1212,7 +1203,6 @@ static int mt9v111_probe(struct i2c_client *client) · 2 unmodified lines | |||
| 1212 | ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad); | 1203 | ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad); |
| 1213 | if (ret) | 1204 | if (ret) |
| 1214 | goto error_free_entity; | 1205 | goto error_free_entity; |
| 1215 | #endif | ||
| 1216 | 1206 | ||
| 1217 | ret = mt9v111_chip_probe(mt9v111); | 1207 | ret = mt9v111_chip_probe(mt9v111); |
| 1218 | if (ret) | 1208 | if (ret) |
| @@ -1225,9 +1215,7 @@ static int mt9v111_probe(struct i2c_client *client) · 6 unmodified lines | |||
| 1225 | return 0; | 1215 | return 0; |
| 1226 | 1216 | ||
| 1227 | error_free_entity: | 1217 | error_free_entity: |
| 1228 | #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | ||
| 1229 | media_entity_cleanup(&mt9v111->sd.entity); | 1218 | media_entity_cleanup(&mt9v111->sd.entity); |
| 1230 | #endif | ||
| 1231 | 1219 | ||
| 1232 | error_free_ctrls: | 1220 | error_free_ctrls: |
| 1233 | v4l2_ctrl_handler_free(&mt9v111->ctrls); | 1221 | v4l2_ctrl_handler_free(&mt9v111->ctrls); |
| @@ -1245,9 +1233,7 @@ static void mt9v111_remove(struct i2c_client *client) · 11 unmodified lines | |||
| 1245 | 1233 | ||
| 1246 | v4l2_async_unregister_subdev(sd); | 1234 | v4l2_async_unregister_subdev(sd); |
| 1247 | 1235 | ||
| 1248 | #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | ||
| 1249 | media_entity_cleanup(&sd->entity); | 1236 | media_entity_cleanup(&sd->entity); |
| 1250 | #endif | ||
| 1251 | 1237 | ||
| 1252 | v4l2_ctrl_handler_free(&mt9v111->ctrls); | 1238 | v4l2_ctrl_handler_free(&mt9v111->ctrls); |
| 1253 | 1239 | ||
| @@ -434,9 +434,6 @@ struct og01a1b { · 433 unmodified lines | |||
| 434 | 434 | ||
| 435 | /* To serialize asynchronus callbacks */ | 435 | /* To serialize asynchronus callbacks */ |
| 436 | struct mutex mutex; | 436 | struct mutex mutex; |
| 437 | |||
| 438 | /* Streaming on/off */ | ||
| 439 | bool streaming; | ||
| 440 | }; | 437 | }; |
| 441 | 438 | ||
| 442 | static u64 to_pixel_rate(u32 f_index) | 439 | static u64 to_pixel_rate(u32 f_index) |
| @@ -732,14 +729,10 @@ static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable) · 289 unmodified lines | |||
| 732 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 729 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 733 | int ret = 0; | 730 | int ret = 0; |
| 734 | 731 | ||
| 735 | if (og01a1b->streaming == enable) | ||
| 736 | return 0; | ||
| 737 | |||
| 738 | mutex_lock(&og01a1b->mutex); | 732 | mutex_lock(&og01a1b->mutex); |
| 739 | if (enable) { | 733 | if (enable) { |
| 740 | ret = pm_runtime_get_sync(&client->dev); | 734 | ret = pm_runtime_resume_and_get(&client->dev); |
| 741 | if (ret < 0) { | 735 | if (ret) { |
| 742 | pm_runtime_put_noidle(&client->dev); | ||
| 743 | mutex_unlock(&og01a1b->mutex); | 736 | mutex_unlock(&og01a1b->mutex); |
| 744 | return ret; | 737 | return ret; |
| 745 | } | 738 | } |
| @@ -755,50 +748,11 @@ static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable) · 9 unmodified lines | |||
| 755 | pm_runtime_put(&client->dev); | 748 | pm_runtime_put(&client->dev); |
| 756 | } | 749 | } |
| 757 | 750 | ||
| 758 | og01a1b->streaming = enable; | ||
| 759 | mutex_unlock(&og01a1b->mutex); | 751 | mutex_unlock(&og01a1b->mutex); |
| 760 | 752 | ||
| 761 | return ret; | 753 | return ret; |
| 762 | } | 754 | } |
| 763 | 755 | ||
| 764 | static int __maybe_unused og01a1b_suspend(struct device *dev) | ||
| 765 | { | ||
| 766 | struct i2c_client *client = to_i2c_client(dev); | ||
| 767 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 768 | struct og01a1b *og01a1b = to_og01a1b(sd); | ||
| 769 | |||
| 770 | mutex_lock(&og01a1b->mutex); | ||
| 771 | if (og01a1b->streaming) | ||
| 772 | og01a1b_stop_streaming(og01a1b); | ||
| 773 | |||
| 774 | mutex_unlock(&og01a1b->mutex); | ||
| 775 | |||
| 776 | return 0; | ||
| 777 | } | ||
| 778 | |||
| 779 | static int __maybe_unused og01a1b_resume(struct device *dev) | ||
| 780 | { | ||
| 781 | struct i2c_client *client = to_i2c_client(dev); | ||
| 782 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 783 | struct og01a1b *og01a1b = to_og01a1b(sd); | ||
| 784 | int ret; | ||
| 785 | |||
| 786 | mutex_lock(&og01a1b->mutex); | ||
| 787 | if (og01a1b->streaming) { | ||
| 788 | ret = og01a1b_start_streaming(og01a1b); | ||
| 789 | if (ret) { | ||
| 790 | og01a1b->streaming = false; | ||
| 791 | og01a1b_stop_streaming(og01a1b); | ||
| 792 | mutex_unlock(&og01a1b->mutex); | ||
| 793 | return ret; | ||
| 794 | } | ||
| 795 | } | ||
| 796 | |||
| 797 | mutex_unlock(&og01a1b->mutex); | ||
| 798 | |||
| 799 | return 0; | ||
| 800 | } | ||
| 801 | |||
| 802 | static int og01a1b_set_format(struct v4l2_subdev *sd, | 756 | static int og01a1b_set_format(struct v4l2_subdev *sd, |
| 803 | struct v4l2_subdev_state *sd_state, | 757 | struct v4l2_subdev_state *sd_state, |
| 804 | struct v4l2_subdev_format *fmt) | 758 | struct v4l2_subdev_format *fmt) |
| @@ -1096,10 +1050,6 @@ probe_error_v4l2_ctrl_handler_free: · 291 unmodified lines | |||
| 1096 | return ret; | 1050 | return ret; |
| 1097 | } | 1051 | } |
| 1098 | 1052 | ||
| 1099 | static const struct dev_pm_ops og01a1b_pm_ops = { | ||
| 1100 | SET_SYSTEM_SLEEP_PM_OPS(og01a1b_suspend, og01a1b_resume) | ||
| 1101 | }; | ||
| 1102 | |||
| 1103 | #ifdef CONFIG_ACPI | 1053 | #ifdef CONFIG_ACPI |
| 1104 | static const struct acpi_device_id og01a1b_acpi_ids[] = { | 1054 | static const struct acpi_device_id og01a1b_acpi_ids[] = { |
| 1105 | {"OVTI01AC"}, | 1055 | {"OVTI01AC"}, |
| @@ -1112,7 +1062,6 @@ MODULE_DEVICE_TABLE(acpi, og01a1b_acpi_ids); · 6 unmodified lines | |||
| 1112 | static struct i2c_driver og01a1b_i2c_driver = { | 1062 | static struct i2c_driver og01a1b_i2c_driver = { |
| 1113 | .driver = { | 1063 | .driver = { |
| 1114 | .name = "og01a1b", | 1064 | .name = "og01a1b", |
| 1115 | .pm = &og01a1b_pm_ops, | ||
| 1116 | .acpi_match_table = ACPI_PTR(og01a1b_acpi_ids), | 1065 | .acpi_match_table = ACPI_PTR(og01a1b_acpi_ids), |
| 1117 | }, | 1066 | }, |
| 1118 | .probe = og01a1b_probe, | 1067 | .probe = og01a1b_probe, |
| @@ -287,9 +287,6 @@ struct ov01a10 { · 286 unmodified lines | |||
| 287 | struct v4l2_ctrl *exposure; | 287 | struct v4l2_ctrl *exposure; |
| 288 | 288 | ||
| 289 | const struct ov01a10_mode *cur_mode; | 289 | const struct ov01a10_mode *cur_mode; |
| 290 | |||
| 291 | /* streaming state */ | ||
| 292 | bool streaming; | ||
| 293 | }; | 290 | }; |
| 294 | 291 | ||
| 295 | static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev) | 292 | static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev) |
| @@ -672,8 +669,6 @@ static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable) · 376 unmodified lines | |||
| 672 | int ret = 0; | 669 | int ret = 0; |
| 673 | 670 | ||
| 674 | state = v4l2_subdev_lock_and_get_active_state(sd); | 671 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| 675 | if (ov01a10->streaming == enable) | ||
| 676 | goto unlock; | ||
| 677 | 672 | ||
| 678 | if (enable) { | 673 | if (enable) { |
| 679 | ret = pm_runtime_resume_and_get(&client->dev); | 674 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -685,55 +680,12 @@ static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable) · 5 unmodified lines | |||
| 685 | pm_runtime_put(&client->dev); | 680 | pm_runtime_put(&client->dev); |
| 686 | goto unlock; | 681 | goto unlock; |
| 687 | } | 682 | } |
| 688 | 683 | } else { | |
| 689 | goto done; | ||
| 690 | } | ||
| 691 | |||
| 692 | ov01a10_stop_streaming(ov01a10); | ||
| 693 | pm_runtime_put(&client->dev); | ||
| 694 | done: | ||
| 695 | ov01a10->streaming = enable; | ||
| 696 | unlock: | ||
| 697 | v4l2_subdev_unlock_state(state); | ||
| 698 | |||
| 699 | return ret; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int __maybe_unused ov01a10_suspend(struct device *dev) | ||
| 703 | { | ||
| 704 | struct i2c_client *client = to_i2c_client(dev); | ||
| 705 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 706 | struct ov01a10 *ov01a10 = to_ov01a10(sd); | ||
| 707 | struct v4l2_subdev_state *state; | ||
| 708 | |||
| 709 | state = v4l2_subdev_lock_and_get_active_state(sd); | ||
| 710 | if (ov01a10->streaming) | ||
| 711 | ov01a10_stop_streaming(ov01a10); | ||
| 712 | |||
| 713 | v4l2_subdev_unlock_state(state); | ||
| 714 | |||
| 715 | return 0; | ||
| 716 | } | ||
| 717 | |||
| 718 | static int __maybe_unused ov01a10_resume(struct device *dev) | ||
| 719 | { | ||
| 720 | struct i2c_client *client = to_i2c_client(dev); | ||
| 721 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 722 | struct ov01a10 *ov01a10 = to_ov01a10(sd); | ||
| 723 | struct v4l2_subdev_state *state; | ||
| 724 | int ret = 0; | ||
| 725 | |||
| 726 | state = v4l2_subdev_lock_and_get_active_state(sd); | ||
| 727 | if (!ov01a10->streaming) | ||
| 728 | goto exit; | ||
| 729 | |||
| 730 | ret = ov01a10_start_streaming(ov01a10); | ||
| 731 | if (ret) { | ||
| 732 | ov01a10->streaming = false; | ||
| 733 | ov01a10_stop_streaming(ov01a10); | 684 | ov01a10_stop_streaming(ov01a10); |
| 685 | pm_runtime_put(&client->dev); | ||
| 734 | } | 686 | } |
| 735 | 687 | ||
| 736 | exit: | 688 | unlock: |
| 737 | v4l2_subdev_unlock_state(state); | 689 | v4l2_subdev_unlock_state(state); |
| 738 | 690 | ||
| 739 | return ret; | 691 | return ret; |
| @@ -973,10 +925,6 @@ err_handler_free: · 233 unmodified lines | |||
| 973 | return ret; | 925 | return ret; |
| 974 | } | 926 | } |
| 975 | 927 | ||
| 976 | static const struct dev_pm_ops ov01a10_pm_ops = { | ||
| 977 | SET_SYSTEM_SLEEP_PM_OPS(ov01a10_suspend, ov01a10_resume) | ||
| 978 | }; | ||
| 979 | |||
| 980 | #ifdef CONFIG_ACPI | 928 | #ifdef CONFIG_ACPI |
| 981 | static const struct acpi_device_id ov01a10_acpi_ids[] = { | 929 | static const struct acpi_device_id ov01a10_acpi_ids[] = { |
| 982 | { "OVTI01A0" }, | 930 | { "OVTI01A0" }, |
| @@ -989,7 +937,6 @@ MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids); · 6 unmodified lines | |||
| 989 | static struct i2c_driver ov01a10_i2c_driver = { | 937 | static struct i2c_driver ov01a10_i2c_driver = { |
| 990 | .driver = { | 938 | .driver = { |
| 991 | .name = "ov01a10", | 939 | .name = "ov01a10", |
| 992 | .pm = &ov01a10_pm_ops, | ||
| 993 | .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids), | 940 | .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids), |
| 994 | }, | 941 | }, |
| 995 | .probe = ov01a10_probe, | 942 | .probe = ov01a10_probe, |
| @@ -570,8 +570,6 @@ unlock_and_return: · 569 unmodified lines | |||
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static const struct dev_pm_ops ov02a10_pm_ops = { | 572 | static const struct dev_pm_ops ov02a10_pm_ops = { |
| 573 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
| 574 | pm_runtime_force_resume) | ||
| 575 | SET_RUNTIME_PM_OPS(ov02a10_power_off, ov02a10_power_on, NULL) | 573 | SET_RUNTIME_PM_OPS(ov02a10_power_off, ov02a10_power_on, NULL) |
| 576 | }; | 574 | }; |
| 577 | 575 | ||
| @@ -536,9 +536,6 @@ struct ov08d10 { · 535 unmodified lines | |||
| 536 | /* To serialize asynchronus callbacks */ | 536 | /* To serialize asynchronus callbacks */ |
| 537 | struct mutex mutex; | 537 | struct mutex mutex; |
| 538 | 538 | ||
| 539 | /* Streaming on/off */ | ||
| 540 | bool streaming; | ||
| 541 | |||
| 542 | /* lanes index */ | 539 | /* lanes index */ |
| 543 | u8 nlanes; | 540 | u8 nlanes; |
| 544 | 541 | ||
| @@ -1103,9 +1100,6 @@ static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) · 558 unmodified lines | |||
| 1103 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1100 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 1104 | int ret = 0; | 1101 | int ret = 0; |
| 1105 | 1102 | ||
| 1106 | if (ov08d10->streaming == enable) | ||
| 1107 | return 0; | ||
| 1108 | |||
| 1109 | mutex_lock(&ov08d10->mutex); | 1103 | mutex_lock(&ov08d10->mutex); |
| 1110 | if (enable) { | 1104 | if (enable) { |
| 1111 | ret = pm_runtime_resume_and_get(&client->dev); | 1105 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -1125,8 +1119,6 @@ static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) · 13 unmodified lines | |||
| 1125 | pm_runtime_put(&client->dev); | 1119 | pm_runtime_put(&client->dev); |
| 1126 | } | 1120 | } |
| 1127 | 1121 | ||
| 1128 | ov08d10->streaming = enable; | ||
| 1129 | |||
| 1130 | /* vflip and hflip cannot change during streaming */ | 1122 | /* vflip and hflip cannot change during streaming */ |
| 1131 | __v4l2_ctrl_grab(ov08d10->vflip, enable); | 1123 | __v4l2_ctrl_grab(ov08d10->vflip, enable); |
| 1132 | __v4l2_ctrl_grab(ov08d10->hflip, enable); | 1124 | __v4l2_ctrl_grab(ov08d10->hflip, enable); |
| @@ -1136,45 +1128,6 @@ static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) · 3 unmodified lines | |||
| 1136 | return ret; | 1128 | return ret; |
| 1137 | } | 1129 | } |
| 1138 | 1130 | ||
| 1139 | static int __maybe_unused ov08d10_suspend(struct device *dev) | ||
| 1140 | { | ||
| 1141 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1142 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 1143 | struct ov08d10 *ov08d10 = to_ov08d10(sd); | ||
| 1144 | |||
| 1145 | mutex_lock(&ov08d10->mutex); | ||
| 1146 | if (ov08d10->streaming) | ||
| 1147 | ov08d10_stop_streaming(ov08d10); | ||
| 1148 | |||
| 1149 | mutex_unlock(&ov08d10->mutex); | ||
| 1150 | |||
| 1151 | return 0; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | static int __maybe_unused ov08d10_resume(struct device *dev) | ||
| 1155 | { | ||
| 1156 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1157 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 1158 | struct ov08d10 *ov08d10 = to_ov08d10(sd); | ||
| 1159 | int ret; | ||
| 1160 | |||
| 1161 | mutex_lock(&ov08d10->mutex); | ||
| 1162 | |||
| 1163 | if (ov08d10->streaming) { | ||
| 1164 | ret = ov08d10_start_streaming(ov08d10); | ||
| 1165 | if (ret) { | ||
| 1166 | ov08d10->streaming = false; | ||
| 1167 | ov08d10_stop_streaming(ov08d10); | ||
| 1168 | mutex_unlock(&ov08d10->mutex); | ||
| 1169 | return ret; | ||
| 1170 | } | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | mutex_unlock(&ov08d10->mutex); | ||
| 1174 | |||
| 1175 | return 0; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static int ov08d10_set_format(struct v4l2_subdev *sd, | 1131 | static int ov08d10_set_format(struct v4l2_subdev *sd, |
| 1179 | struct v4l2_subdev_state *sd_state, | 1132 | struct v4l2_subdev_state *sd_state, |
| 1180 | struct v4l2_subdev_format *fmt) | 1133 | struct v4l2_subdev_format *fmt) |
| @@ -1501,10 +1454,6 @@ probe_error_v4l2_ctrl_handler_free: · 320 unmodified lines | |||
| 1501 | return ret; | 1454 | return ret; |
| 1502 | } | 1455 | } |
| 1503 | 1456 | ||
| 1504 | static const struct dev_pm_ops ov08d10_pm_ops = { | ||
| 1505 | SET_SYSTEM_SLEEP_PM_OPS(ov08d10_suspend, ov08d10_resume) | ||
| 1506 | }; | ||
| 1507 | |||
| 1508 | #ifdef CONFIG_ACPI | 1457 | #ifdef CONFIG_ACPI |
| 1509 | static const struct acpi_device_id ov08d10_acpi_ids[] = { | 1458 | static const struct acpi_device_id ov08d10_acpi_ids[] = { |
| 1510 | { "OVTI08D1" }, | 1459 | { "OVTI08D1" }, |
| @@ -1517,7 +1466,6 @@ MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids); · 6 unmodified lines | |||
| 1517 | static struct i2c_driver ov08d10_i2c_driver = { | 1466 | static struct i2c_driver ov08d10_i2c_driver = { |
| 1518 | .driver = { | 1467 | .driver = { |
| 1519 | .name = "ov08d10", | 1468 | .name = "ov08d10", |
| 1520 | .pm = &ov08d10_pm_ops, | ||
| 1521 | .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), | 1469 | .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), |
| 1522 | }, | 1470 | }, |
| 1523 | .probe = ov08d10_probe, | 1471 | .probe = ov08d10_probe, |
| @@ -2432,9 +2432,6 @@ struct ov08x40 { · 2431 unmodified lines | |||
| 2432 | 2432 | ||
| 2433 | /* Mutex for serialized access */ | 2433 | /* Mutex for serialized access */ |
| 2434 | struct mutex mutex; | 2434 | struct mutex mutex; |
| 2435 | |||
| 2436 | /* Streaming on/off */ | ||
| 2437 | bool streaming; | ||
| 2438 | }; | 2435 | }; |
| 2439 | 2436 | ||
| 2440 | #define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd) | 2437 | #define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd) |
| @@ -2915,10 +2912,6 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable) · 474 unmodified lines | |||
| 2915 | int ret = 0; | 2912 | int ret = 0; |
| 2916 | 2913 | ||
| 2917 | mutex_lock(&ov08x->mutex); | 2914 | mutex_lock(&ov08x->mutex); |
| 2918 | if (ov08x->streaming == enable) { | ||
| 2919 | mutex_unlock(&ov08x->mutex); | ||
| 2920 | return 0; | ||
| 2921 | } | ||
| 2922 | 2915 | ||
| 2923 | if (enable) { | 2916 | if (enable) { |
| 2924 | ret = pm_runtime_resume_and_get(&client->dev); | 2917 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -2937,7 +2930,6 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 2937 | pm_runtime_put(&client->dev); | 2930 | pm_runtime_put(&client->dev); |
| 2938 | } | 2931 | } |
| 2939 | 2932 | ||
| 2940 | ov08x->streaming = enable; | ||
| 2941 | mutex_unlock(&ov08x->mutex); | 2933 | mutex_unlock(&ov08x->mutex); |
| 2942 | 2934 | ||
| 2943 | return ret; | 2935 | return ret; |
| @@ -2950,37 +2942,6 @@ err_unlock: · 6 unmodified lines | |||
| 2950 | return ret; | 2942 | return ret; |
| 2951 | } | 2943 | } |
| 2952 | 2944 | ||
| 2953 | static int __maybe_unused ov08x40_suspend(struct device *dev) | ||
| 2954 | { | ||
| 2955 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2956 | struct ov08x40 *ov08x = to_ov08x40(sd); | ||
| 2957 | |||
| 2958 | if (ov08x->streaming) | ||
| 2959 | ov08x40_stop_streaming(ov08x); | ||
| 2960 | |||
| 2961 | return 0; | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | static int __maybe_unused ov08x40_resume(struct device *dev) | ||
| 2965 | { | ||
| 2966 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2967 | struct ov08x40 *ov08x = to_ov08x40(sd); | ||
| 2968 | int ret; | ||
| 2969 | |||
| 2970 | if (ov08x->streaming) { | ||
| 2971 | ret = ov08x40_start_streaming(ov08x); | ||
| 2972 | if (ret) | ||
| 2973 | goto error; | ||
| 2974 | } | ||
| 2975 | |||
| 2976 | return 0; | ||
| 2977 | |||
| 2978 | error: | ||
| 2979 | ov08x40_stop_streaming(ov08x); | ||
| 2980 | ov08x->streaming = false; | ||
| 2981 | return ret; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | /* Verify chip ID */ | 2945 | /* Verify chip ID */ |
| 2985 | static int ov08x40_identify_module(struct ov08x40 *ov08x) | 2946 | static int ov08x40_identify_module(struct ov08x40 *ov08x) |
| 2986 | { | 2947 | { |
| @@ -3294,10 +3255,6 @@ static void ov08x40_remove(struct i2c_client *client) · 307 unmodified lines | |||
| 3294 | pm_runtime_set_suspended(&client->dev); | 3255 | pm_runtime_set_suspended(&client->dev); |
| 3295 | } | 3256 | } |
| 3296 | 3257 | ||
| 3297 | static const struct dev_pm_ops ov08x40_pm_ops = { | ||
| 3298 | SET_SYSTEM_SLEEP_PM_OPS(ov08x40_suspend, ov08x40_resume) | ||
| 3299 | }; | ||
| 3300 | |||
| 3301 | #ifdef CONFIG_ACPI | 3258 | #ifdef CONFIG_ACPI |
| 3302 | static const struct acpi_device_id ov08x40_acpi_ids[] = { | 3259 | static const struct acpi_device_id ov08x40_acpi_ids[] = { |
| 3303 | {"OVTI08F4"}, | 3260 | {"OVTI08F4"}, |
| @@ -3310,7 +3267,6 @@ MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids); · 6 unmodified lines | |||
| 3310 | static struct i2c_driver ov08x40_i2c_driver = { | 3267 | static struct i2c_driver ov08x40_i2c_driver = { |
| 3311 | .driver = { | 3268 | .driver = { |
| 3312 | .name = "ov08x40", | 3269 | .name = "ov08x40", |
| 3313 | .pm = &ov08x40_pm_ops, | ||
| 3314 | .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), | 3270 | .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), |
| 3315 | }, | 3271 | }, |
| 3316 | .probe = ov08x40_probe, | 3272 | .probe = ov08x40_probe, |
| @@ -1044,9 +1044,6 @@ struct ov13858 { · 1043 unmodified lines | |||
| 1044 | 1044 | ||
| 1045 | /* Mutex for serialized access */ | 1045 | /* Mutex for serialized access */ |
| 1046 | struct mutex mutex; | 1046 | struct mutex mutex; |
| 1047 | |||
| 1048 | /* Streaming on/off */ | ||
| 1049 | bool streaming; | ||
| 1050 | }; | 1047 | }; |
| 1051 | 1048 | ||
| 1052 | #define to_ov13858(_sd) container_of(_sd, struct ov13858, sd) | 1049 | #define to_ov13858(_sd) container_of(_sd, struct ov13858, sd) |
| @@ -1467,10 +1464,6 @@ static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) · 414 unmodified lines | |||
| 1467 | int ret = 0; | 1464 | int ret = 0; |
| 1468 | 1465 | ||
| 1469 | mutex_lock(&ov13858->mutex); | 1466 | mutex_lock(&ov13858->mutex); |
| 1470 | if (ov13858->streaming == enable) { | ||
| 1471 | mutex_unlock(&ov13858->mutex); | ||
| 1472 | return 0; | ||
| 1473 | } | ||
| 1474 | 1467 | ||
| 1475 | if (enable) { | 1468 | if (enable) { |
| 1476 | ret = pm_runtime_resume_and_get(&client->dev); | 1469 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -1489,7 +1482,6 @@ static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 1489 | pm_runtime_put(&client->dev); | 1482 | pm_runtime_put(&client->dev); |
| 1490 | } | 1483 | } |
| 1491 | 1484 | ||
| 1492 | ov13858->streaming = enable; | ||
| 1493 | mutex_unlock(&ov13858->mutex); | 1485 | mutex_unlock(&ov13858->mutex); |
| 1494 | 1486 | ||
| 1495 | return ret; | 1487 | return ret; |
| @@ -1502,37 +1494,6 @@ err_unlock: · 6 unmodified lines | |||
| 1502 | return ret; | 1494 | return ret; |
| 1503 | } | 1495 | } |
| 1504 | 1496 | ||
| 1505 | static int __maybe_unused ov13858_suspend(struct device *dev) | ||
| 1506 | { | ||
| 1507 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1508 | struct ov13858 *ov13858 = to_ov13858(sd); | ||
| 1509 | |||
| 1510 | if (ov13858->streaming) | ||
| 1511 | ov13858_stop_streaming(ov13858); | ||
| 1512 | |||
| 1513 | return 0; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static int __maybe_unused ov13858_resume(struct device *dev) | ||
| 1517 | { | ||
| 1518 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1519 | struct ov13858 *ov13858 = to_ov13858(sd); | ||
| 1520 | int ret; | ||
| 1521 | |||
| 1522 | if (ov13858->streaming) { | ||
| 1523 | ret = ov13858_start_streaming(ov13858); | ||
| 1524 | if (ret) | ||
| 1525 | goto error; | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | return 0; | ||
| 1529 | |||
| 1530 | error: | ||
| 1531 | ov13858_stop_streaming(ov13858); | ||
| 1532 | ov13858->streaming = false; | ||
| 1533 | return ret; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | /* Verify chip ID */ | 1497 | /* Verify chip ID */ |
| 1537 | static int ov13858_identify_module(struct ov13858 *ov13858) | 1498 | static int ov13858_identify_module(struct ov13858 *ov13858) |
| 1538 | { | 1499 | { |
| @@ -1787,10 +1748,6 @@ static const struct i2c_device_id ov13858_id_table[] = { · 248 unmodified lines | |||
| 1787 | 1748 | ||
| 1788 | MODULE_DEVICE_TABLE(i2c, ov13858_id_table); | 1749 | MODULE_DEVICE_TABLE(i2c, ov13858_id_table); |
| 1789 | 1750 | ||
| 1790 | static const struct dev_pm_ops ov13858_pm_ops = { | ||
| 1791 | SET_SYSTEM_SLEEP_PM_OPS(ov13858_suspend, ov13858_resume) | ||
| 1792 | }; | ||
| 1793 | |||
| 1794 | #ifdef CONFIG_ACPI | 1751 | #ifdef CONFIG_ACPI |
| 1795 | static const struct acpi_device_id ov13858_acpi_ids[] = { | 1752 | static const struct acpi_device_id ov13858_acpi_ids[] = { |
| 1796 | {"OVTID858"}, | 1753 | {"OVTID858"}, |
| @@ -1803,7 +1760,6 @@ MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids); · 6 unmodified lines | |||
| 1803 | static struct i2c_driver ov13858_i2c_driver = { | 1760 | static struct i2c_driver ov13858_i2c_driver = { |
| 1804 | .driver = { | 1761 | .driver = { |
| 1805 | .name = "ov13858", | 1762 | .name = "ov13858", |
| 1806 | .pm = &ov13858_pm_ops, | ||
| 1807 | .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), | 1763 | .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), |
| 1808 | }, | 1764 | }, |
| 1809 | .probe = ov13858_probe, | 1765 | .probe = ov13858_probe, |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #define OV13B10_REG_VTS 0x380e | 31 | #define OV13B10_REG_VTS 0x380e |
| 32 | #define OV13B10_VTS_30FPS 0x0c7c | 32 | #define OV13B10_VTS_30FPS 0x0c7c |
| 33 | #define OV13B10_VTS_60FPS 0x063e | 33 | #define OV13B10_VTS_60FPS 0x063e |
| 34 | #define OV13B10_VTS_120FPS 0x0320 | ||
| 34 | #define OV13B10_VTS_MAX 0x7fff | 35 | #define OV13B10_VTS_MAX 0x7fff |
| 35 | 36 | ||
| 36 | /* HBLANK control - read only */ | 37 | /* HBLANK control - read only */ |
| @@ -468,6 +469,50 @@ static const struct ov13b10_reg mode_2080x1170_regs[] = { · 431 unmodified lines | |||
| 468 | {0x5001, 0x0d}, | 469 | {0x5001, 0x0d}, |
| 469 | }; | 470 | }; |
| 470 | 471 | ||
| 472 | static const struct ov13b10_reg mode_1364x768_120fps_regs[] = { | ||
| 473 | {0x0305, 0xaf}, | ||
| 474 | {0x3011, 0x7c}, | ||
| 475 | {0x3501, 0x03}, | ||
| 476 | {0x3502, 0x00}, | ||
| 477 | {0x3662, 0x88}, | ||
| 478 | {0x3714, 0x28}, | ||
| 479 | {0x3739, 0x10}, | ||
| 480 | {0x37c2, 0x14}, | ||
| 481 | {0x37d9, 0x06}, | ||
| 482 | {0x37e2, 0x0c}, | ||
| 483 | {0x37e4, 0x00}, | ||
| 484 | {0x3800, 0x02}, | ||
| 485 | {0x3801, 0xe4}, | ||
| 486 | {0x3802, 0x03}, | ||
| 487 | {0x3803, 0x48}, | ||
| 488 | {0x3804, 0x0d}, | ||
| 489 | {0x3805, 0xab}, | ||
| 490 | {0x3806, 0x09}, | ||
| 491 | {0x3807, 0x60}, | ||
| 492 | {0x3808, 0x05}, | ||
| 493 | {0x3809, 0x54}, | ||
| 494 | {0x380a, 0x03}, | ||
| 495 | {0x380b, 0x00}, | ||
| 496 | {0x380c, 0x04}, | ||
| 497 | {0x380d, 0x8e}, | ||
| 498 | {0x380e, 0x03}, | ||
| 499 | {0x380f, 0x20}, | ||
| 500 | {0x3811, 0x07}, | ||
| 501 | {0x3813, 0x07}, | ||
| 502 | {0x3814, 0x03}, | ||
| 503 | {0x3816, 0x03}, | ||
| 504 | {0x3820, 0x8b}, | ||
| 505 | {0x3c8c, 0x18}, | ||
| 506 | {0x4008, 0x00}, | ||
| 507 | {0x4009, 0x05}, | ||
| 508 | {0x4050, 0x00}, | ||
| 509 | {0x4051, 0x05}, | ||
| 510 | {0x4501, 0x08}, | ||
| 511 | {0x4505, 0x04}, | ||
| 512 | {0x5000, 0xfd}, | ||
| 513 | {0x5001, 0x0d}, | ||
| 514 | }; | ||
| 515 | |||
| 471 | static const char * const ov13b10_test_pattern_menu[] = { | 516 | static const char * const ov13b10_test_pattern_menu[] = { |
| 472 | "Disabled", | 517 | "Disabled", |
| 473 | "Vertical Color Bar Type 1", | 518 | "Vertical Color Bar Type 1", |
| @@ -568,7 +613,18 @@ static const struct ov13b10_mode supported_modes[] = { · 94 unmodified lines | |||
| 568 | .regs = mode_2080x1170_regs, | 613 | .regs = mode_2080x1170_regs, |
| 569 | }, | 614 | }, |
| 570 | .link_freq_index = OV13B10_LINK_FREQ_INDEX_0, | 615 | .link_freq_index = OV13B10_LINK_FREQ_INDEX_0, |
| 571 | } | 616 | }, |
| 617 | { | ||
| 618 | .width = 1364, | ||
| 619 | .height = 768, | ||
| 620 | .vts_def = OV13B10_VTS_120FPS, | ||
| 621 | .vts_min = OV13B10_VTS_120FPS, | ||
| 622 | .link_freq_index = OV13B10_LINK_FREQ_INDEX_0, | ||
| 623 | .reg_list = { | ||
| 624 | .num_of_regs = ARRAY_SIZE(mode_1364x768_120fps_regs), | ||
| 625 | .regs = mode_1364x768_120fps_regs, | ||
| 626 | }, | ||
| 627 | }, | ||
| 572 | }; | 628 | }; |
| 573 | 629 | ||
| 574 | struct ov13b10 { | 630 | struct ov13b10 { |
| @@ -594,9 +650,6 @@ struct ov13b10 { · 19 unmodified lines | |||
| 594 | /* Mutex for serialized access */ | 650 | /* Mutex for serialized access */ |
| 595 | struct mutex mutex; | 651 | struct mutex mutex; |
| 596 | 652 | ||
| 597 | /* Streaming on/off */ | ||
| 598 | bool streaming; | ||
| 599 | |||
| 600 | /* True if the device has been identified */ | 653 | /* True if the device has been identified */ |
| 601 | bool identified; | 654 | bool identified; |
| 602 | }; | 655 | }; |
| @@ -1161,10 +1214,6 @@ static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) · 558 unmodified lines | |||
| 1161 | int ret = 0; | 1214 | int ret = 0; |
| 1162 | 1215 | ||
| 1163 | mutex_lock(&ov13b->mutex); | 1216 | mutex_lock(&ov13b->mutex); |
| 1164 | if (ov13b->streaming == enable) { | ||
| 1165 | mutex_unlock(&ov13b->mutex); | ||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | 1217 | ||
| 1169 | if (enable) { | 1218 | if (enable) { |
| 1170 | ret = pm_runtime_resume_and_get(&client->dev); | 1219 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -1183,7 +1232,6 @@ static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 1183 | pm_runtime_put(&client->dev); | 1232 | pm_runtime_put(&client->dev); |
| 1184 | } | 1233 | } |
| 1185 | 1234 | ||
| 1186 | ov13b->streaming = enable; | ||
| 1187 | mutex_unlock(&ov13b->mutex); | 1235 | mutex_unlock(&ov13b->mutex); |
| 1188 | 1236 | ||
| 1189 | return ret; | 1237 | return ret; |
| @@ -1198,12 +1246,6 @@ err_unlock: · 8 unmodified lines | |||
| 1198 | 1246 | ||
| 1199 | static int ov13b10_suspend(struct device *dev) | 1247 | static int ov13b10_suspend(struct device *dev) |
| 1200 | { | 1248 | { |
| 1201 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1202 | struct ov13b10 *ov13b = to_ov13b10(sd); | ||
| 1203 | |||
| 1204 | if (ov13b->streaming) | ||
| 1205 | ov13b10_stop_streaming(ov13b); | ||
| 1206 | |||
| 1207 | ov13b10_power_off(dev); | 1249 | ov13b10_power_off(dev); |
| 1208 | 1250 | ||
| 1209 | return 0; | 1251 | return 0; |
| @@ -1211,29 +1253,7 @@ static int ov13b10_suspend(struct device *dev) · 1 unmodified line | |||
| 1211 | 1253 | ||
| 1212 | static int ov13b10_resume(struct device *dev) | 1254 | static int ov13b10_resume(struct device *dev) |
| 1213 | { | 1255 | { |
| 1214 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | 1256 | return ov13b10_power_on(dev); |
| 1215 | struct ov13b10 *ov13b = to_ov13b10(sd); | ||
| 1216 | int ret; | ||
| 1217 | |||
| 1218 | ret = ov13b10_power_on(dev); | ||
| 1219 | if (ret) | ||
| 1220 | goto pm_fail; | ||
| 1221 | |||
| 1222 | if (ov13b->streaming) { | ||
| 1223 | ret = ov13b10_start_streaming(ov13b); | ||
| 1224 | if (ret) | ||
| 1225 | goto stop_streaming; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | return 0; | ||
| 1229 | |||
| 1230 | stop_streaming: | ||
| 1231 | ov13b10_stop_streaming(ov13b); | ||
| 1232 | ov13b10_power_off(dev); | ||
| 1233 | pm_fail: | ||
| 1234 | ov13b->streaming = false; | ||
| 1235 | |||
| 1236 | return ret; | ||
| 1237 | } | 1257 | } |
| 1238 | 1258 | ||
| 1239 | static const struct v4l2_subdev_video_ops ov13b10_video_ops = { | 1259 | static const struct v4l2_subdev_video_ops ov13b10_video_ops = { |
| @@ -1501,7 +1521,7 @@ static int ov13b10_probe(struct i2c_client *client) · 261 unmodified lines | |||
| 1501 | 1521 | ||
| 1502 | full_power = acpi_dev_state_d0(&client->dev); | 1522 | full_power = acpi_dev_state_d0(&client->dev); |
| 1503 | if (full_power) { | 1523 | if (full_power) { |
| 1504 | ov13b10_power_on(&client->dev); | 1524 | ret = ov13b10_power_on(&client->dev); |
| 1505 | if (ret) { | 1525 | if (ret) { |
| 1506 | dev_err(&client->dev, "failed to power on\n"); | 1526 | dev_err(&client->dev, "failed to power on\n"); |
| 1507 | return ret; | 1527 | return ret; |
| @@ -293,9 +293,7 @@ struct ov2640_win_size { · 292 unmodified lines | |||
| 293 | 293 | ||
| 294 | struct ov2640_priv { | 294 | struct ov2640_priv { |
| 295 | struct v4l2_subdev subdev; | 295 | struct v4l2_subdev subdev; |
| 296 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 297 | struct media_pad pad; | 296 | struct media_pad pad; |
| 298 | #endif | ||
| 299 | struct v4l2_ctrl_handler hdl; | 297 | struct v4l2_ctrl_handler hdl; |
| 300 | u32 cfmt_code; | 298 | u32 cfmt_code; |
| 301 | struct clk *clk; | 299 | struct clk *clk; |
| @@ -922,13 +920,9 @@ static int ov2640_get_fmt(struct v4l2_subdev *sd, · 620 unmodified lines | |||
| 922 | return -EINVAL; | 920 | return -EINVAL; |
| 923 | 921 | ||
| 924 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { | 922 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 925 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 926 | mf = v4l2_subdev_get_try_format(sd, sd_state, 0); | 923 | mf = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 927 | format->format = *mf; | 924 | format->format = *mf; |
| 928 | return 0; | 925 | return 0; |
| 929 | #else | ||
| 930 | return -EINVAL; | ||
| 931 | #endif | ||
| 932 | } | 926 | } |
| 933 | 927 | ||
| 934 | mf->width = priv->win->width; | 928 | mf->width = priv->win->width; |
| @@ -1005,7 +999,6 @@ out: · 70 unmodified lines | |||
| 1005 | static int ov2640_init_cfg(struct v4l2_subdev *sd, | 999 | static int ov2640_init_cfg(struct v4l2_subdev *sd, |
| 1006 | struct v4l2_subdev_state *sd_state) | 1000 | struct v4l2_subdev_state *sd_state) |
| 1007 | { | 1001 | { |
| 1008 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1009 | struct v4l2_mbus_framefmt *try_fmt = | 1002 | struct v4l2_mbus_framefmt *try_fmt = |
| 1010 | v4l2_subdev_get_try_format(sd, sd_state, 0); | 1003 | v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 1011 | const struct ov2640_win_size *win = | 1004 | const struct ov2640_win_size *win = |
| @@ -1019,7 +1012,7 @@ static int ov2640_init_cfg(struct v4l2_subdev *sd, · 7 unmodified lines | |||
| 1019 | try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | 1012 | try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
| 1020 | try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; | 1013 | try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; |
| 1021 | try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; | 1014 | try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
| 1022 | #endif | 1015 | |
| 1023 | return 0; | 1016 | return 0; |
| 1024 | } | 1017 | } |
| 1025 | 1018 | ||
| @@ -1205,17 +1198,14 @@ static int ov2640_probe(struct i2c_client *client) · 179 unmodified lines | |||
| 1205 | return -ENOMEM; | 1198 | return -ENOMEM; |
| 1206 | 1199 | ||
| 1207 | if (client->dev.of_node) { | 1200 | if (client->dev.of_node) { |
| 1208 | priv->clk = devm_clk_get(&client->dev, "xvclk"); | 1201 | priv->clk = devm_clk_get_enabled(&client->dev, "xvclk"); |
| 1209 | if (IS_ERR(priv->clk)) | 1202 | if (IS_ERR(priv->clk)) |
| 1210 | return PTR_ERR(priv->clk); | 1203 | return PTR_ERR(priv->clk); |
| 1211 | ret = clk_prepare_enable(priv->clk); | ||
| 1212 | if (ret) | ||
| 1213 | return ret; | ||
| 1214 | } | 1204 | } |
| 1215 | 1205 | ||
| 1216 | ret = ov2640_probe_dt(client, priv); | 1206 | ret = ov2640_probe_dt(client, priv); |
| 1217 | if (ret) | 1207 | if (ret) |
| 1218 | goto err_clk; | 1208 | return ret; |
| 1219 | 1209 | ||
| 1220 | priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); | 1210 | priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); |
| 1221 | priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8; | 1211 | priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8; |
| @@ -1239,13 +1229,11 @@ static int ov2640_probe(struct i2c_client *client) · 17 unmodified lines | |||
| 1239 | ret = priv->hdl.error; | 1229 | ret = priv->hdl.error; |
| 1240 | goto err_hdl; | 1230 | goto err_hdl; |
| 1241 | } | 1231 | } |
| 1242 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1243 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; | 1232 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1244 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1233 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1245 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); | 1234 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); |
| 1246 | if (ret < 0) | 1235 | if (ret < 0) |
| 1247 | goto err_hdl; | 1236 | goto err_hdl; |
| 1248 | #endif | ||
| 1249 | 1237 | ||
| 1250 | ret = ov2640_video_probe(client); | 1238 | ret = ov2640_video_probe(client); |
| 1251 | if (ret < 0) | 1239 | if (ret < 0) |
| @@ -1264,8 +1252,6 @@ err_videoprobe: · 12 unmodified lines | |||
| 1264 | err_hdl: | 1252 | err_hdl: |
| 1265 | v4l2_ctrl_handler_free(&priv->hdl); | 1253 | v4l2_ctrl_handler_free(&priv->hdl); |
| 1266 | mutex_destroy(&priv->lock); | 1254 | mutex_destroy(&priv->lock); |
| 1267 | err_clk: | ||
| 1268 | clk_disable_unprepare(priv->clk); | ||
| 1269 | return ret; | 1255 | return ret; |
| 1270 | } | 1256 | } |
| 1271 | 1257 | ||
| @@ -1278,7 +1264,6 @@ static void ov2640_remove(struct i2c_client *client) · 6 unmodified lines | |||
| 1278 | mutex_destroy(&priv->lock); | 1264 | mutex_destroy(&priv->lock); |
| 1279 | media_entity_cleanup(&priv->subdev.entity); | 1265 | media_entity_cleanup(&priv->subdev.entity); |
| 1280 | v4l2_device_unregister_subdev(&priv->subdev); | 1266 | v4l2_device_unregister_subdev(&priv->subdev); |
| 1281 | clk_disable_unprepare(priv->clk); | ||
| 1282 | } | 1267 | } |
| 1283 | 1268 | ||
| 1284 | static const struct i2c_device_id ov2640_id[] = { | 1269 | static const struct i2c_device_id ov2640_id[] = { |
| @@ -1031,7 +1031,6 @@ static int ov2659_get_fmt(struct v4l2_subdev *sd, · 1030 unmodified lines | |||
| 1031 | dev_dbg(&client->dev, "ov2659_get_fmt\n"); | 1031 | dev_dbg(&client->dev, "ov2659_get_fmt\n"); |
| 1032 | 1032 | ||
| 1033 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 1033 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1034 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1035 | struct v4l2_mbus_framefmt *mf; | 1034 | struct v4l2_mbus_framefmt *mf; |
| 1036 | 1035 | ||
| 1037 | mf = v4l2_subdev_get_try_format(sd, sd_state, 0); | 1036 | mf = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| @@ -1039,9 +1038,6 @@ static int ov2659_get_fmt(struct v4l2_subdev *sd, · 1 unmodified line | |||
| 1039 | fmt->format = *mf; | 1038 | fmt->format = *mf; |
| 1040 | mutex_unlock(&ov2659->lock); | 1039 | mutex_unlock(&ov2659->lock); |
| 1041 | return 0; | 1040 | return 0; |
| 1042 | #else | ||
| 1043 | return -EINVAL; | ||
| 1044 | #endif | ||
| 1045 | } | 1041 | } |
| 1046 | 1042 | ||
| 1047 | mutex_lock(&ov2659->lock); | 1043 | mutex_lock(&ov2659->lock); |
| @@ -1113,10 +1109,8 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, · 65 unmodified lines | |||
| 1113 | mutex_lock(&ov2659->lock); | 1109 | mutex_lock(&ov2659->lock); |
| 1114 | 1110 | ||
| 1115 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1116 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1117 | mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); | 1112 | mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); |
| 1118 | *mf = fmt->format; | 1113 | *mf = fmt->format; |
| 1119 | #endif | ||
| 1120 | } else { | 1114 | } else { |
| 1121 | s64 val; | 1115 | s64 val; |
| 1122 | 1116 | ||
| @@ -1306,7 +1300,6 @@ static int ov2659_power_on(struct device *dev) · 183 unmodified lines | |||
| 1306 | * V4L2 subdev internal operations | 1300 | * V4L2 subdev internal operations |
| 1307 | */ | 1301 | */ |
| 1308 | 1302 | ||
| 1309 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1310 | static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 1303 | static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1311 | { | 1304 | { |
| 1312 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1305 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| @@ -1319,7 +1312,6 @@ static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 6 unmodified lines | |||
| 1319 | 1312 | ||
| 1320 | return 0; | 1313 | return 0; |
| 1321 | } | 1314 | } |
| 1322 | #endif | ||
| 1323 | 1315 | ||
| 1324 | static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = { | 1316 | static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = { |
| 1325 | .log_status = v4l2_ctrl_subdev_log_status, | 1317 | .log_status = v4l2_ctrl_subdev_log_status, |
| @@ -1338,7 +1330,6 @@ static const struct v4l2_subdev_pad_ops ov2659_subdev_pad_ops = { · 12 unmodified lines | |||
| 1338 | .set_fmt = ov2659_set_fmt, | 1330 | .set_fmt = ov2659_set_fmt, |
| 1339 | }; | 1331 | }; |
| 1340 | 1332 | ||
| 1341 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1342 | static const struct v4l2_subdev_ops ov2659_subdev_ops = { | 1333 | static const struct v4l2_subdev_ops ov2659_subdev_ops = { |
| 1343 | .core = &ov2659_subdev_core_ops, | 1334 | .core = &ov2659_subdev_core_ops, |
| 1344 | .video = &ov2659_subdev_video_ops, | 1335 | .video = &ov2659_subdev_video_ops, |
| @@ -1348,7 +1339,6 @@ static const struct v4l2_subdev_ops ov2659_subdev_ops = { · 3 unmodified lines | |||
| 1348 | static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = { | 1339 | static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = { |
| 1349 | .open = ov2659_open, | 1340 | .open = ov2659_open, |
| 1350 | }; | 1341 | }; |
| 1351 | #endif | ||
| 1352 | 1342 | ||
| 1353 | static int ov2659_detect(struct v4l2_subdev *sd) | 1343 | static int ov2659_detect(struct v4l2_subdev *sd) |
| 1354 | { | 1344 | { |
| @@ -1489,15 +1479,12 @@ static int ov2659_probe(struct i2c_client *client) · 134 unmodified lines | |||
| 1489 | 1479 | ||
| 1490 | sd = &ov2659->sd; | 1480 | sd = &ov2659->sd; |
| 1491 | client->flags |= I2C_CLIENT_SCCB; | 1481 | client->flags |= I2C_CLIENT_SCCB; |
| 1492 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1493 | v4l2_i2c_subdev_init(sd, client, &ov2659_subdev_ops); | ||
| 1494 | 1482 | ||
| 1483 | v4l2_i2c_subdev_init(sd, client, &ov2659_subdev_ops); | ||
| 1495 | sd->internal_ops = &ov2659_subdev_internal_ops; | 1484 | sd->internal_ops = &ov2659_subdev_internal_ops; |
| 1496 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | | 1485 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
| 1497 | V4L2_SUBDEV_FL_HAS_EVENTS; | 1486 | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1498 | #endif | ||
| 1499 | 1487 | ||
| 1500 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1501 | ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; | 1488 | ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1502 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1489 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1503 | ret = media_entity_pads_init(&sd->entity, 1, &ov2659->pad); | 1490 | ret = media_entity_pads_init(&sd->entity, 1, &ov2659->pad); |
| @@ -1505,7 +1492,6 @@ static int ov2659_probe(struct i2c_client *client) · 1 unmodified line | |||
| 1505 | v4l2_ctrl_handler_free(&ov2659->ctrls); | 1492 | v4l2_ctrl_handler_free(&ov2659->ctrls); |
| 1506 | return ret; | 1493 | return ret; |
| 1507 | } | 1494 | } |
| 1508 | #endif | ||
| 1509 | 1495 | ||
| 1510 | mutex_init(&ov2659->lock); | 1496 | mutex_init(&ov2659->lock); |
| 1511 | 1497 | ||
| @@ -91,7 +91,6 @@ struct ov2685 { · 90 unmodified lines | |||
| 91 | struct gpio_desc *reset_gpio; | 91 | struct gpio_desc *reset_gpio; |
| 92 | struct regulator_bulk_data supplies[OV2685_NUM_SUPPLIES]; | 92 | struct regulator_bulk_data supplies[OV2685_NUM_SUPPLIES]; |
| 93 | 93 | ||
| 94 | bool streaming; | ||
| 95 | struct mutex mutex; | 94 | struct mutex mutex; |
| 96 | struct v4l2_subdev subdev; | 95 | struct v4l2_subdev subdev; |
| 97 | struct media_pad pad; | 96 | struct media_pad pad; |
| @@ -513,10 +512,6 @@ static int ov2685_s_stream(struct v4l2_subdev *sd, int on) · 415 unmodified lines | |||
| 513 | 512 | ||
| 514 | mutex_lock(&ov2685->mutex); | 513 | mutex_lock(&ov2685->mutex); |
| 515 | 514 | ||
| 516 | on = !!on; | ||
| 517 | if (on == ov2685->streaming) | ||
| 518 | goto unlock_and_return; | ||
| 519 | |||
| 520 | if (on) { | 515 | if (on) { |
| 521 | ret = pm_runtime_resume_and_get(&ov2685->client->dev); | 516 | ret = pm_runtime_resume_and_get(&ov2685->client->dev); |
| 522 | if (ret < 0) | 517 | if (ret < 0) |
| @@ -539,15 +534,12 @@ static int ov2685_s_stream(struct v4l2_subdev *sd, int on) · 16 unmodified lines | |||
| 539 | pm_runtime_put(&ov2685->client->dev); | 534 | pm_runtime_put(&ov2685->client->dev); |
| 540 | } | 535 | } |
| 541 | 536 | ||
| 542 | ov2685->streaming = on; | ||
| 543 | |||
| 544 | unlock_and_return: | 537 | unlock_and_return: |
| 545 | mutex_unlock(&ov2685->mutex); | 538 | mutex_unlock(&ov2685->mutex); |
| 546 | 539 | ||
| 547 | return ret; | 540 | return ret; |
| 548 | } | 541 | } |
| 549 | 542 | ||
| 550 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 551 | static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 543 | static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 552 | { | 544 | { |
| 553 | struct ov2685 *ov2685 = to_ov2685(sd); | 545 | struct ov2685 *ov2685 = to_ov2685(sd); |
| @@ -563,7 +555,6 @@ static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 9 unmodified lines | |||
| 563 | 555 | ||
| 564 | return 0; | 556 | return 0; |
| 565 | } | 557 | } |
| 566 | #endif | ||
| 567 | 558 | ||
| 568 | static int __maybe_unused ov2685_runtime_resume(struct device *dev) | 559 | static int __maybe_unused ov2685_runtime_resume(struct device *dev) |
| 569 | { | 560 | { |
| @@ -660,11 +651,9 @@ static const struct v4l2_subdev_ops ov2685_subdev_ops = { · 90 unmodified lines | |||
| 660 | .pad = &ov2685_pad_ops, | 651 | .pad = &ov2685_pad_ops, |
| 661 | }; | 652 | }; |
| 662 | 653 | ||
| 663 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 664 | static const struct v4l2_subdev_internal_ops ov2685_internal_ops = { | 654 | static const struct v4l2_subdev_internal_ops ov2685_internal_ops = { |
| 665 | .open = ov2685_open, | 655 | .open = ov2685_open, |
| 666 | }; | 656 | }; |
| 667 | #endif | ||
| 668 | 657 | ||
| 669 | static const struct v4l2_ctrl_ops ov2685_ctrl_ops = { | 658 | static const struct v4l2_ctrl_ops ov2685_ctrl_ops = { |
| 670 | .s_ctrl = ov2685_set_ctrl, | 659 | .s_ctrl = ov2685_set_ctrl, |
| @@ -833,17 +822,13 @@ static int ov2685_probe(struct i2c_client *client) · 162 unmodified lines | |||
| 833 | if (ret) | 822 | if (ret) |
| 834 | goto err_power_off; | 823 | goto err_power_off; |
| 835 | 824 | ||
| 836 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 837 | ov2685->subdev.internal_ops = &ov2685_internal_ops; | 825 | ov2685->subdev.internal_ops = &ov2685_internal_ops; |
| 838 | ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 826 | ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 839 | #endif | ||
| 840 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 841 | ov2685->pad.flags = MEDIA_PAD_FL_SOURCE; | 827 | ov2685->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 842 | ov2685->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 828 | ov2685->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 843 | ret = media_entity_pads_init(&ov2685->subdev.entity, 1, &ov2685->pad); | 829 | ret = media_entity_pads_init(&ov2685->subdev.entity, 1, &ov2685->pad); |
| 844 | if (ret < 0) | 830 | if (ret < 0) |
| 845 | goto err_power_off; | 831 | goto err_power_off; |
| 846 | #endif | ||
| 847 | 832 | ||
| 848 | ret = v4l2_async_register_subdev(&ov2685->subdev); | 833 | ret = v4l2_async_register_subdev(&ov2685->subdev); |
| 849 | if (ret) { | 834 | if (ret) { |
| @@ -858,9 +843,7 @@ static int ov2685_probe(struct i2c_client *client) · 8 unmodified lines | |||
| 858 | return 0; | 843 | return 0; |
| 859 | 844 | ||
| 860 | err_clean_entity: | 845 | err_clean_entity: |
| 861 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 862 | media_entity_cleanup(&ov2685->subdev.entity); | 846 | media_entity_cleanup(&ov2685->subdev.entity); |
| 863 | #endif | ||
| 864 | err_power_off: | 847 | err_power_off: |
| 865 | __ov2685_power_off(ov2685); | 848 | __ov2685_power_off(ov2685); |
| 866 | err_free_handler: | 849 | err_free_handler: |
| @@ -877,9 +860,7 @@ static void ov2685_remove(struct i2c_client *client) · 10 unmodified lines | |||
| 877 | struct ov2685 *ov2685 = to_ov2685(sd); | 860 | struct ov2685 *ov2685 = to_ov2685(sd); |
| 878 | 861 | ||
| 879 | v4l2_async_unregister_subdev(sd); | 862 | v4l2_async_unregister_subdev(sd); |
| 880 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 881 | media_entity_cleanup(&sd->entity); | 863 | media_entity_cleanup(&sd->entity); |
| 882 | #endif | ||
| 883 | v4l2_ctrl_handler_free(&ov2685->ctrl_handler); | 864 | v4l2_ctrl_handler_free(&ov2685->ctrl_handler); |
| 884 | mutex_destroy(&ov2685->mutex); | 865 | mutex_destroy(&ov2685->mutex); |
| 885 | 866 | ||
| @@ -336,12 +336,6 @@ struct ov2740 { · 335 unmodified lines | |||
| 336 | /* Current mode */ | 336 | /* Current mode */ |
| 337 | const struct ov2740_mode *cur_mode; | 337 | const struct ov2740_mode *cur_mode; |
| 338 | 338 | ||
| 339 | /* To serialize asynchronus callbacks */ | ||
| 340 | struct mutex mutex; | ||
| 341 | |||
| 342 | /* Streaming on/off */ | ||
| 343 | bool streaming; | ||
| 344 | |||
| 345 | /* NVM data inforamtion */ | 339 | /* NVM data inforamtion */ |
| 346 | struct nvm_data *nvm; | 340 | struct nvm_data *nvm; |
| 347 | 341 | ||
| @@ -582,7 +576,6 @@ static int ov2740_init_controls(struct ov2740 *ov2740) · 234 unmodified lines | |||
| 582 | if (ret) | 576 | if (ret) |
| 583 | return ret; | 577 | return ret; |
| 584 | 578 | ||
| 585 | ctrl_hdlr->lock = &ov2740->mutex; | ||
| 586 | cur_mode = ov2740->cur_mode; | 579 | cur_mode = ov2740->cur_mode; |
| 587 | size = ARRAY_SIZE(link_freq_menu_items); | 580 | size = ARRAY_SIZE(link_freq_menu_items); |
| 588 | 581 | ||
| @@ -792,18 +785,15 @@ static int ov2740_set_stream(struct v4l2_subdev *sd, int enable) · 203 unmodified lines | |||
| 792 | { | 785 | { |
| 793 | struct ov2740 *ov2740 = to_ov2740(sd); | 786 | struct ov2740 *ov2740 = to_ov2740(sd); |
| 794 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 787 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 788 | struct v4l2_subdev_state *sd_state; | ||
| 795 | int ret = 0; | 789 | int ret = 0; |
| 796 | 790 | ||
| 797 | if (ov2740->streaming == enable) | 791 | sd_state = v4l2_subdev_lock_and_get_active_state(&ov2740->sd); |
| 798 | return 0; | ||
| 799 | 792 | ||
| 800 | mutex_lock(&ov2740->mutex); | ||
| 801 | if (enable) { | 793 | if (enable) { |
| 802 | ret = pm_runtime_resume_and_get(&client->dev); | 794 | ret = pm_runtime_resume_and_get(&client->dev); |
| 803 | if (ret < 0) { | 795 | if (ret < 0) |
| 804 | mutex_unlock(&ov2740->mutex); | 796 | goto out_unlock; |
| 805 | return ret; | ||
| 806 | } | ||
| 807 | 797 | ||
| 808 | ret = ov2740_start_streaming(ov2740); | 798 | ret = ov2740_start_streaming(ov2740); |
| 809 | if (ret) { | 799 | if (ret) { |
| @@ -816,44 +806,9 @@ static int ov2740_set_stream(struct v4l2_subdev *sd, int enable) · 6 unmodified lines | |||
| 816 | pm_runtime_put(&client->dev); | 806 | pm_runtime_put(&client->dev); |
| 817 | } | 807 | } |
| 818 | 808 | ||
| 819 | ov2740->streaming = enable; | 809 | out_unlock: |
| 820 | mutex_unlock(&ov2740->mutex); | 810 | v4l2_subdev_unlock_state(sd_state); |
| 821 | |||
| 822 | return ret; | ||
| 823 | } | ||
| 824 | |||
| 825 | static int ov2740_suspend(struct device *dev) | ||
| 826 | { | ||
| 827 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 828 | struct ov2740 *ov2740 = to_ov2740(sd); | ||
| 829 | |||
| 830 | mutex_lock(&ov2740->mutex); | ||
| 831 | if (ov2740->streaming) | ||
| 832 | ov2740_stop_streaming(ov2740); | ||
| 833 | |||
| 834 | mutex_unlock(&ov2740->mutex); | ||
| 835 | |||
| 836 | return 0; | ||
| 837 | } | ||
| 838 | |||
| 839 | static int ov2740_resume(struct device *dev) | ||
| 840 | { | ||
| 841 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 842 | struct ov2740 *ov2740 = to_ov2740(sd); | ||
| 843 | int ret = 0; | ||
| 844 | |||
| 845 | mutex_lock(&ov2740->mutex); | ||
| 846 | if (!ov2740->streaming) | ||
| 847 | goto exit; | ||
| 848 | |||
| 849 | ret = ov2740_start_streaming(ov2740); | ||
| 850 | if (ret) { | ||
| 851 | ov2740->streaming = false; | ||
| 852 | ov2740_stop_streaming(ov2740); | ||
| 853 | } | ||
| 854 | 811 | ||
| 855 | exit: | ||
| 856 | mutex_unlock(&ov2740->mutex); | ||
| 857 | return ret; | 812 | return ret; |
| 858 | } | 813 | } |
| 859 | 814 | ||
| @@ -870,48 +825,26 @@ static int ov2740_set_format(struct v4l2_subdev *sd, · 10 unmodified lines | |||
| 870 | height, fmt->format.width, | 825 | height, fmt->format.width, |
| 871 | fmt->format.height); | 826 | fmt->format.height); |
| 872 | 827 | ||
| 873 | mutex_lock(&ov2740->mutex); | ||
| 874 | ov2740_update_pad_format(mode, &fmt->format); | 828 | ov2740_update_pad_format(mode, &fmt->format); |
| 875 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 829 | *v4l2_subdev_get_pad_format(sd, sd_state, fmt->pad) = fmt->format; |
| 876 | *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; | ||
| 877 | } else { | ||
| 878 | ov2740->cur_mode = mode; | ||
| 879 | __v4l2_ctrl_s_ctrl(ov2740->link_freq, mode->link_freq_index); | ||
| 880 | __v4l2_ctrl_s_ctrl_int64(ov2740->pixel_rate, | ||
| 881 | to_pixel_rate(mode->link_freq_index)); | ||
| 882 | |||
| 883 | /* Update limits and set FPS to default */ | ||
| 884 | vblank_def = mode->vts_def - mode->height; | ||
| 885 | __v4l2_ctrl_modify_range(ov2740->vblank, | ||
| 886 | mode->vts_min - mode->height, | ||
| 887 | OV2740_VTS_MAX - mode->height, 1, | ||
| 888 | vblank_def); | ||
| 889 | __v4l2_ctrl_s_ctrl(ov2740->vblank, vblank_def); | ||
| 890 | h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) - | ||
| 891 | mode->width; | ||
| 892 | __v4l2_ctrl_modify_range(ov2740->hblank, h_blank, h_blank, 1, | ||
| 893 | h_blank); | ||
| 894 | } | ||
| 895 | mutex_unlock(&ov2740->mutex); | ||
| 896 | |||
| 897 | return 0; | ||
| 898 | } | ||
| 899 | |||
| 900 | static int ov2740_get_format(struct v4l2_subdev *sd, | ||
| 901 | struct v4l2_subdev_state *sd_state, | ||
| 902 | struct v4l2_subdev_format *fmt) | ||
| 903 | { | ||
| 904 | struct ov2740 *ov2740 = to_ov2740(sd); | ||
| 905 | 830 | ||
| 906 | mutex_lock(&ov2740->mutex); | ||
| 907 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) | 831 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) |
| 908 | fmt->format = *v4l2_subdev_get_try_format(&ov2740->sd, | 832 | return 0; |
| 909 | sd_state, | ||
| 910 | fmt->pad); | ||
| 911 | else | ||
| 912 | ov2740_update_pad_format(ov2740->cur_mode, &fmt->format); | ||
| 913 | 833 | ||
| 914 | mutex_unlock(&ov2740->mutex); | 834 | ov2740->cur_mode = mode; |
| 835 | __v4l2_ctrl_s_ctrl(ov2740->link_freq, mode->link_freq_index); | ||
| 836 | __v4l2_ctrl_s_ctrl_int64(ov2740->pixel_rate, | ||
| 837 | to_pixel_rate(mode->link_freq_index)); | ||
| 838 | |||
| 839 | /* Update limits and set FPS to default */ | ||
| 840 | vblank_def = mode->vts_def - mode->height; | ||
| 841 | __v4l2_ctrl_modify_range(ov2740->vblank, | ||
| 842 | mode->vts_min - mode->height, | ||
| 843 | OV2740_VTS_MAX - mode->height, 1, vblank_def); | ||
| 844 | __v4l2_ctrl_s_ctrl(ov2740->vblank, vblank_def); | ||
| 845 | h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) - | ||
| 846 | mode->width; | ||
| 847 | __v4l2_ctrl_modify_range(ov2740->hblank, h_blank, h_blank, 1, h_blank); | ||
| 915 | 848 | ||
| 916 | return 0; | 849 | return 0; |
| 917 | } | 850 | } |
| @@ -946,14 +879,11 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd, · 28 unmodified lines | |||
| 946 | return 0; | 879 | return 0; |
| 947 | } | 880 | } |
| 948 | 881 | ||
| 949 | static int ov2740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 882 | static int ov2740_init_cfg(struct v4l2_subdev *sd, |
| 883 | struct v4l2_subdev_state *sd_state) | ||
| 950 | { | 884 | { |
| 951 | struct ov2740 *ov2740 = to_ov2740(sd); | ||
| 952 | |||
| 953 | mutex_lock(&ov2740->mutex); | ||
| 954 | ov2740_update_pad_format(&supported_modes[0], | 885 | ov2740_update_pad_format(&supported_modes[0], |
| 955 | v4l2_subdev_get_try_format(sd, fh->state, 0)); | 886 | v4l2_subdev_get_pad_format(sd, sd_state, 0)); |
| 956 | mutex_unlock(&ov2740->mutex); | ||
| 957 | 887 | ||
| 958 | return 0; | 888 | return 0; |
| 959 | } | 889 | } |
| @@ -963,10 +893,11 @@ static const struct v4l2_subdev_video_ops ov2740_video_ops = { · 3 unmodified lines | |||
| 963 | }; | 893 | }; |
| 964 | 894 | ||
| 965 | static const struct v4l2_subdev_pad_ops ov2740_pad_ops = { | 895 | static const struct v4l2_subdev_pad_ops ov2740_pad_ops = { |
| 896 | .get_fmt = v4l2_subdev_get_fmt, | ||
| 966 | .set_fmt = ov2740_set_format, | 897 | .set_fmt = ov2740_set_format, |
| 967 | .get_fmt = ov2740_get_format, | ||
| 968 | .enum_mbus_code = ov2740_enum_mbus_code, | 898 | .enum_mbus_code = ov2740_enum_mbus_code, |
| 969 | .enum_frame_size = ov2740_enum_frame_size, | 899 | .enum_frame_size = ov2740_enum_frame_size, |
| 900 | .init_cfg = ov2740_init_cfg, | ||
| 970 | }; | 901 | }; |
| 971 | 902 | ||
| 972 | static const struct v4l2_subdev_ops ov2740_subdev_ops = { | 903 | static const struct v4l2_subdev_ops ov2740_subdev_ops = { |
| @@ -978,10 +909,6 @@ static const struct media_entity_operations ov2740_subdev_entity_ops = { · 5 unmodified lines | |||
| 978 | .link_validate = v4l2_subdev_link_validate, | 909 | .link_validate = v4l2_subdev_link_validate, |
| 979 | }; | 910 | }; |
| 980 | 911 | ||
| 981 | static const struct v4l2_subdev_internal_ops ov2740_internal_ops = { | ||
| 982 | .open = ov2740_open, | ||
| 983 | }; | ||
| 984 | |||
| 985 | static int ov2740_check_hwcfg(struct device *dev) | 912 | static int ov2740_check_hwcfg(struct device *dev) |
| 986 | { | 913 | { |
| 987 | struct fwnode_handle *ep; | 914 | struct fwnode_handle *ep; |
| @@ -1004,7 +931,7 @@ static int ov2740_check_hwcfg(struct device *dev) · 16 unmodified lines | |||
| 1004 | 931 | ||
| 1005 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); | 932 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); |
| 1006 | if (!ep) | 933 | if (!ep) |
| 1007 | return -ENXIO; | 934 | return -EPROBE_DEFER; |
| 1008 | 935 | ||
| 1009 | ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); | 936 | ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); |
| 1010 | fwnode_handle_put(ep); | 937 | fwnode_handle_put(ep); |
| @@ -1047,13 +974,12 @@ check_hwcfg_error: · 36 unmodified lines | |||
| 1047 | static void ov2740_remove(struct i2c_client *client) | 974 | static void ov2740_remove(struct i2c_client *client) |
| 1048 | { | 975 | { |
| 1049 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 976 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1050 | struct ov2740 *ov2740 = to_ov2740(sd); | ||
| 1051 | 977 | ||
| 1052 | v4l2_async_unregister_subdev(sd); | 978 | v4l2_async_unregister_subdev(sd); |
| 1053 | media_entity_cleanup(&sd->entity); | 979 | media_entity_cleanup(&sd->entity); |
| 980 | v4l2_subdev_cleanup(sd); | ||
| 1054 | v4l2_ctrl_handler_free(sd->ctrl_handler); | 981 | v4l2_ctrl_handler_free(sd->ctrl_handler); |
| 1055 | pm_runtime_disable(&client->dev); | 982 | pm_runtime_disable(&client->dev); |
| 1056 | mutex_destroy(&ov2740->mutex); | ||
| 1057 | } | 983 | } |
| 1058 | 984 | ||
| 1059 | static int ov2740_nvmem_read(void *priv, unsigned int off, void *val, | 985 | static int ov2740_nvmem_read(void *priv, unsigned int off, void *val, |
| @@ -1062,9 +988,11 @@ static int ov2740_nvmem_read(void *priv, unsigned int off, void *val, · 2 unmodified lines | |||
| 1062 | struct nvm_data *nvm = priv; | 988 | struct nvm_data *nvm = priv; |
| 1063 | struct device *dev = regmap_get_device(nvm->regmap); | 989 | struct device *dev = regmap_get_device(nvm->regmap); |
| 1064 | struct ov2740 *ov2740 = to_ov2740(dev_get_drvdata(dev)); | 990 | struct ov2740 *ov2740 = to_ov2740(dev_get_drvdata(dev)); |
| 991 | struct v4l2_subdev_state *sd_state; | ||
| 1065 | int ret = 0; | 992 | int ret = 0; |
| 1066 | 993 | ||
| 1067 | mutex_lock(&ov2740->mutex); | 994 | /* Serialise sensor access */ |
| 995 | sd_state = v4l2_subdev_lock_and_get_active_state(&ov2740->sd); | ||
| 1068 | 996 | ||
| 1069 | if (nvm->nvm_buffer) { | 997 | if (nvm->nvm_buffer) { |
| 1070 | memcpy(val, nvm->nvm_buffer + off, count); | 998 | memcpy(val, nvm->nvm_buffer + off, count); |
| @@ -1082,7 +1010,7 @@ static int ov2740_nvmem_read(void *priv, unsigned int off, void *val, · 11 unmodified lines | |||
| 1082 | 1010 | ||
| 1083 | pm_runtime_put(dev); | 1011 | pm_runtime_put(dev); |
| 1084 | exit: | 1012 | exit: |
| 1085 | mutex_unlock(&ov2740->mutex); | 1013 | v4l2_subdev_unlock_state(sd_state); |
| 1086 | return ret; | 1014 | return ret; |
| 1087 | } | 1015 | } |
| 1088 | 1016 | ||
| @@ -1153,7 +1081,6 @@ static int ov2740_probe(struct i2c_client *client) · 64 unmodified lines | |||
| 1153 | return dev_err_probe(dev, ret, "failed to find sensor\n"); | 1081 | return dev_err_probe(dev, ret, "failed to find sensor\n"); |
| 1154 | } | 1082 | } |
| 1155 | 1083 | ||
| 1156 | mutex_init(&ov2740->mutex); | ||
| 1157 | ov2740->cur_mode = &supported_modes[0]; | 1084 | ov2740->cur_mode = &supported_modes[0]; |
| 1158 | ret = ov2740_init_controls(ov2740); | 1085 | ret = ov2740_init_controls(ov2740); |
| 1159 | if (ret) { | 1086 | if (ret) { |
| @@ -1161,7 +1088,7 @@ static int ov2740_probe(struct i2c_client *client) · 1 unmodified line | |||
| 1161 | goto probe_error_v4l2_ctrl_handler_free; | 1088 | goto probe_error_v4l2_ctrl_handler_free; |
| 1162 | } | 1089 | } |
| 1163 | 1090 | ||
| 1164 | ov2740->sd.internal_ops = &ov2740_internal_ops; | 1091 | ov2740->sd.state_lock = ov2740->ctrl_handler.lock; |
| 1165 | ov2740->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1092 | ov2740->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1166 | ov2740->sd.entity.ops = &ov2740_subdev_entity_ops; | 1093 | ov2740->sd.entity.ops = &ov2740_subdev_entity_ops; |
| 1167 | ov2740->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1094 | ov2740->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| @@ -1172,36 +1099,42 @@ static int ov2740_probe(struct i2c_client *client) · 4 unmodified lines | |||
| 1172 | goto probe_error_v4l2_ctrl_handler_free; | 1099 | goto probe_error_v4l2_ctrl_handler_free; |
| 1173 | } | 1100 | } |
| 1174 | 1101 | ||
| 1102 | ret = v4l2_subdev_init_finalize(&ov2740->sd); | ||
| 1103 | if (ret) | ||
| 1104 | goto probe_error_media_entity_cleanup; | ||
| 1105 | |||
| 1106 | /* Set the device's state to active if it's in D0 state. */ | ||
| 1107 | if (full_power) | ||
| 1108 | pm_runtime_set_active(&client->dev); | ||
| 1109 | pm_runtime_enable(&client->dev); | ||
| 1110 | pm_runtime_idle(&client->dev); | ||
| 1111 | |||
| 1175 | ret = v4l2_async_register_subdev_sensor(&ov2740->sd); | 1112 | ret = v4l2_async_register_subdev_sensor(&ov2740->sd); |
| 1176 | if (ret < 0) { | 1113 | if (ret < 0) { |
| 1177 | dev_err_probe(dev, ret, "failed to register V4L2 subdev\n"); | 1114 | dev_err_probe(dev, ret, "failed to register V4L2 subdev\n"); |
| 1178 | goto probe_error_media_entity_cleanup; | 1115 | goto probe_error_v4l2_subdev_cleanup; |
| 1179 | } | 1116 | } |
| 1180 | 1117 | ||
| 1181 | ret = ov2740_register_nvmem(client, ov2740); | 1118 | ret = ov2740_register_nvmem(client, ov2740); |
| 1182 | if (ret) | 1119 | if (ret) |
| 1183 | dev_warn(&client->dev, "register nvmem failed, ret %d\n", ret); | 1120 | dev_warn(&client->dev, "register nvmem failed, ret %d\n", ret); |
| 1184 | 1121 | ||
| 1185 | /* Set the device's state to active if it's in D0 state. */ | ||
| 1186 | if (full_power) | ||
| 1187 | pm_runtime_set_active(&client->dev); | ||
| 1188 | pm_runtime_enable(&client->dev); | ||
| 1189 | pm_runtime_idle(&client->dev); | ||
| 1190 | |||
| 1191 | return 0; | 1122 | return 0; |
| 1192 | 1123 | ||
| 1124 | probe_error_v4l2_subdev_cleanup: | ||
| 1125 | v4l2_subdev_cleanup(&ov2740->sd); | ||
| 1126 | |||
| 1193 | probe_error_media_entity_cleanup: | 1127 | probe_error_media_entity_cleanup: |
| 1194 | media_entity_cleanup(&ov2740->sd.entity); | 1128 | media_entity_cleanup(&ov2740->sd.entity); |
| 1129 | pm_runtime_disable(&client->dev); | ||
| 1130 | pm_runtime_set_suspended(&client->dev); | ||
| 1195 | 1131 | ||
| 1196 | probe_error_v4l2_ctrl_handler_free: | 1132 | probe_error_v4l2_ctrl_handler_free: |
| 1197 | v4l2_ctrl_handler_free(ov2740->sd.ctrl_handler); | 1133 | v4l2_ctrl_handler_free(ov2740->sd.ctrl_handler); |
| 1198 | mutex_destroy(&ov2740->mutex); | ||
| 1199 | 1134 | ||
| 1200 | return ret; | 1135 | return ret; |
| 1201 | } | 1136 | } |
| 1202 | 1137 | ||
| 1203 | static DEFINE_SIMPLE_DEV_PM_OPS(ov2740_pm_ops, ov2740_suspend, ov2740_resume); | ||
| 1204 | |||
| 1205 | static const struct acpi_device_id ov2740_acpi_ids[] = { | 1138 | static const struct acpi_device_id ov2740_acpi_ids[] = { |
| 1206 | {"INT3474"}, | 1139 | {"INT3474"}, |
| 1207 | {} | 1140 | {} |
| @@ -1212,7 +1145,6 @@ MODULE_DEVICE_TABLE(acpi, ov2740_acpi_ids); · 4 unmodified lines | |||
| 1212 | static struct i2c_driver ov2740_i2c_driver = { | 1145 | static struct i2c_driver ov2740_i2c_driver = { |
| 1213 | .driver = { | 1146 | .driver = { |
| 1214 | .name = "ov2740", | 1147 | .name = "ov2740", |
| 1215 | .pm = pm_sleep_ptr(&ov2740_pm_ops), | ||
| 1216 | .acpi_match_table = ov2740_acpi_ids, | 1148 | .acpi_match_table = ov2740_acpi_ids, |
| 1217 | }, | 1149 | }, |
| 1218 | .probe = ov2740_probe, | 1150 | .probe = ov2740_probe, |
| @@ -99,8 +99,7 @@ struct ov4689 { · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | u32 clock_rate; | 100 | u32 clock_rate; |
| 101 | 101 | ||
| 102 | struct mutex mutex; /* lock to protect streaming, ctrls and cur_mode */ | 102 | struct mutex mutex; /* lock to protect ctrls and cur_mode */ |
| 103 | bool streaming; | ||
| 104 | struct v4l2_ctrl_handler ctrl_handler; | 103 | struct v4l2_ctrl_handler ctrl_handler; |
| 105 | struct v4l2_ctrl *exposure; | 104 | struct v4l2_ctrl *exposure; |
| 106 | 105 | ||
| @@ -468,10 +467,6 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) · 361 unmodified lines | |||
| 468 | 467 | ||
| 469 | mutex_lock(&ov4689->mutex); | 468 | mutex_lock(&ov4689->mutex); |
| 470 | 469 | ||
| 471 | on = !!on; | ||
| 472 | if (on == ov4689->streaming) | ||
| 473 | goto unlock_and_return; | ||
| 474 | |||
| 475 | if (on) { | 470 | if (on) { |
| 476 | ret = pm_runtime_resume_and_get(&client->dev); | 471 | ret = pm_runtime_resume_and_get(&client->dev); |
| 477 | if (ret < 0) | 472 | if (ret < 0) |
| @@ -504,8 +499,6 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) · 26 unmodified lines | |||
| 504 | pm_runtime_put(&client->dev); | 499 | pm_runtime_put(&client->dev); |
| 505 | } | 500 | } |
| 506 | 501 | ||
| 507 | ov4689->streaming = on; | ||
| 508 | |||
| 509 | unlock_and_return: | 502 | unlock_and_return: |
| 510 | mutex_unlock(&ov4689->mutex); | 503 | mutex_unlock(&ov4689->mutex); |
| 511 | 504 | ||
| @@ -2850,12 +2850,22 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, · 2849 unmodified lines | |||
| 2850 | return 0; | 2850 | return 0; |
| 2851 | } | 2851 | } |
| 2852 | 2852 | ||
| 2853 | static void __v4l2_ctrl_vblank_update(struct ov5640_dev *sensor, u32 vblank) | ||
| 2854 | { | ||
| 2855 | const struct ov5640_mode_info *mode = sensor->current_mode; | ||
| 2856 | |||
| 2857 | __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK, | ||
| 2858 | OV5640_MAX_VTS - mode->height, 1, vblank); | ||
| 2859 | |||
| 2860 | __v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank); | ||
| 2861 | } | ||
| 2862 | |||
| 2853 | static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) | 2863 | static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) |
| 2854 | { | 2864 | { |
| 2855 | const struct ov5640_mode_info *mode = sensor->current_mode; | 2865 | const struct ov5640_mode_info *mode = sensor->current_mode; |
| 2856 | enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate; | 2866 | enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate; |
| 2857 | struct v4l2_mbus_framefmt *fmt = &sensor->fmt; | 2867 | struct v4l2_mbus_framefmt *fmt = &sensor->fmt; |
| 2858 | const struct ov5640_timings *timings; | 2868 | const struct ov5640_timings *timings = ov5640_timings(sensor, mode); |
| 2859 | s32 exposure_val, exposure_max; | 2869 | s32 exposure_val, exposure_max; |
| 2860 | unsigned int hblank; | 2870 | unsigned int hblank; |
| 2861 | unsigned int i = 0; | 2871 | unsigned int i = 0; |
| @@ -2874,6 +2884,8 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) · 12 unmodified lines | |||
| 2874 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, | 2884 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, |
| 2875 | ov5640_calc_pixel_rate(sensor)); | 2885 | ov5640_calc_pixel_rate(sensor)); |
| 2876 | 2886 | ||
| 2887 | __v4l2_ctrl_vblank_update(sensor, timings->vblank_def); | ||
| 2888 | |||
| 2877 | return 0; | 2889 | return 0; |
| 2878 | } | 2890 | } |
| 2879 | 2891 | ||
| @@ -2916,15 +2928,12 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) · 36 unmodified lines | |||
| 2916 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, pixel_rate); | 2928 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, pixel_rate); |
| 2917 | __v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, i); | 2929 | __v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, i); |
| 2918 | 2930 | ||
| 2919 | timings = ov5640_timings(sensor, mode); | ||
| 2920 | hblank = timings->htot - mode->width; | 2931 | hblank = timings->htot - mode->width; |
| 2921 | __v4l2_ctrl_modify_range(sensor->ctrls.hblank, | 2932 | __v4l2_ctrl_modify_range(sensor->ctrls.hblank, |
| 2922 | hblank, hblank, 1, hblank); | 2933 | hblank, hblank, 1, hblank); |
| 2923 | 2934 | ||
| 2924 | vblank = timings->vblank_def; | 2935 | vblank = timings->vblank_def; |
| 2925 | __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK, | 2936 | __v4l2_ctrl_vblank_update(sensor, vblank); |
| 2926 | OV5640_MAX_VTS - mode->height, 1, vblank); | ||
| 2927 | __v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank); | ||
| 2928 | 2937 | ||
| 2929 | exposure_max = timings->crop.height + vblank - 4; | 2938 | exposure_max = timings->crop.height + vblank - 4; |
| 2930 | exposure_val = clamp_t(s32, sensor->ctrls.exposure->val, | 2939 | exposure_val = clamp_t(s32, sensor->ctrls.exposure->val, |
| @@ -3919,7 +3928,7 @@ static int ov5640_probe(struct i2c_client *client) · 988 unmodified lines | |||
| 3919 | ret = ov5640_sensor_resume(dev); | 3928 | ret = ov5640_sensor_resume(dev); |
| 3920 | if (ret) { | 3929 | if (ret) { |
| 3921 | dev_err(dev, "failed to power on\n"); | 3930 | dev_err(dev, "failed to power on\n"); |
| 3922 | goto entity_cleanup; | 3931 | goto free_ctrls; |
| 3923 | } | 3932 | } |
| 3924 | 3933 | ||
| 3925 | pm_runtime_set_active(dev); | 3934 | pm_runtime_set_active(dev); |
| @@ -3944,8 +3953,9 @@ static int ov5640_probe(struct i2c_client *client) · 18 unmodified lines | |||
| 3944 | err_pm_runtime: | 3953 | err_pm_runtime: |
| 3945 | pm_runtime_put_noidle(dev); | 3954 | pm_runtime_put_noidle(dev); |
| 3946 | pm_runtime_disable(dev); | 3955 | pm_runtime_disable(dev); |
| 3947 | v4l2_ctrl_handler_free(&sensor->ctrls.handler); | ||
| 3948 | ov5640_sensor_suspend(dev); | 3956 | ov5640_sensor_suspend(dev); |
| 3957 | free_ctrls: | ||
| 3958 | v4l2_ctrl_handler_free(&sensor->ctrls.handler); | ||
| 3949 | entity_cleanup: | 3959 | entity_cleanup: |
| 3950 | media_entity_cleanup(&sensor->sd.entity); | 3960 | media_entity_cleanup(&sensor->sd.entity); |
| 3951 | mutex_destroy(&sensor->lock); | 3961 | mutex_destroy(&sensor->lock); |
| @@ -109,7 +109,6 @@ struct ov5647 { · 108 unmodified lines | |||
| 109 | struct v4l2_ctrl *hblank; | 109 | struct v4l2_ctrl *hblank; |
| 110 | struct v4l2_ctrl *vblank; | 110 | struct v4l2_ctrl *vblank; |
| 111 | struct v4l2_ctrl *exposure; | 111 | struct v4l2_ctrl *exposure; |
| 112 | bool streaming; | ||
| 113 | }; | 112 | }; |
| 114 | 113 | ||
| 115 | static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd) | 114 | static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd) |
| @@ -898,10 +897,6 @@ static int ov5647_s_stream(struct v4l2_subdev *sd, int enable) · 782 unmodified lines | |||
| 898 | int ret; | 897 | int ret; |
| 899 | 898 | ||
| 900 | mutex_lock(&sensor->lock); | 899 | mutex_lock(&sensor->lock); |
| 901 | if (sensor->streaming == enable) { | ||
| 902 | mutex_unlock(&sensor->lock); | ||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | 900 | ||
| 906 | if (enable) { | 901 | if (enable) { |
| 907 | ret = pm_runtime_resume_and_get(&client->dev); | 902 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -922,7 +917,6 @@ static int ov5647_s_stream(struct v4l2_subdev *sd, int enable) · 14 unmodified lines | |||
| 922 | pm_runtime_put(&client->dev); | 917 | pm_runtime_put(&client->dev); |
| 923 | } | 918 | } |
| 924 | 919 | ||
| 925 | sensor->streaming = enable; | ||
| 926 | mutex_unlock(&sensor->lock); | 920 | mutex_unlock(&sensor->lock); |
| 927 | 921 | ||
| 928 | return 0; | 922 | return 0; |
| @@ -1882,8 +1882,6 @@ struct ov5670 { · 1881 unmodified lines | |||
| 1882 | /* To serialize asynchronus callbacks */ | 1882 | /* To serialize asynchronus callbacks */ |
| 1883 | struct mutex mutex; | 1883 | struct mutex mutex; |
| 1884 | 1884 | ||
| 1885 | /* Streaming on/off */ | ||
| 1886 | bool streaming; | ||
| 1887 | /* True if the device has been identified */ | 1885 | /* True if the device has been identified */ |
| 1888 | bool identified; | 1886 | bool identified; |
| 1889 | }; | 1887 | }; |
| @@ -2471,8 +2469,6 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) · 581 unmodified lines | |||
| 2471 | int ret = 0; | 2469 | int ret = 0; |
| 2472 | 2470 | ||
| 2473 | mutex_lock(&ov5670->mutex); | 2471 | mutex_lock(&ov5670->mutex); |
| 2474 | if (ov5670->streaming == enable) | ||
| 2475 | goto unlock_and_return; | ||
| 2476 | 2472 | ||
| 2477 | if (enable) { | 2473 | if (enable) { |
| 2478 | ret = pm_runtime_resume_and_get(&client->dev); | 2474 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -2486,7 +2482,6 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 2486 | ret = ov5670_stop_streaming(ov5670); | 2482 | ret = ov5670_stop_streaming(ov5670); |
| 2487 | pm_runtime_put(&client->dev); | 2483 | pm_runtime_put(&client->dev); |
| 2488 | } | 2484 | } |
| 2489 | ov5670->streaming = enable; | ||
| 2490 | goto unlock_and_return; | 2485 | goto unlock_and_return; |
| 2491 | 2486 | ||
| 2492 | error: | 2487 | error: |
| @@ -2541,34 +2536,6 @@ static int __maybe_unused ov5670_runtime_suspend(struct device *dev) · 48 unmodified lines | |||
| 2541 | return 0; | 2536 | return 0; |
| 2542 | } | 2537 | } |
| 2543 | 2538 | ||
| 2544 | static int __maybe_unused ov5670_suspend(struct device *dev) | ||
| 2545 | { | ||
| 2546 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2547 | struct ov5670 *ov5670 = to_ov5670(sd); | ||
| 2548 | |||
| 2549 | if (ov5670->streaming) | ||
| 2550 | ov5670_stop_streaming(ov5670); | ||
| 2551 | |||
| 2552 | return 0; | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | static int __maybe_unused ov5670_resume(struct device *dev) | ||
| 2556 | { | ||
| 2557 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2558 | struct ov5670 *ov5670 = to_ov5670(sd); | ||
| 2559 | int ret; | ||
| 2560 | |||
| 2561 | if (ov5670->streaming) { | ||
| 2562 | ret = ov5670_start_streaming(ov5670); | ||
| 2563 | if (ret) { | ||
| 2564 | ov5670_stop_streaming(ov5670); | ||
| 2565 | return ret; | ||
| 2566 | } | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | return 0; | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | static const struct v4l2_subdev_core_ops ov5670_core_ops = { | 2539 | static const struct v4l2_subdev_core_ops ov5670_core_ops = { |
| 2573 | .log_status = v4l2_ctrl_subdev_log_status, | 2540 | .log_status = v4l2_ctrl_subdev_log_status, |
| 2574 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, | 2541 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
| @@ -2771,8 +2738,6 @@ static int ov5670_probe(struct i2c_client *client) · 196 unmodified lines | |||
| 2771 | goto error_handler_free; | 2738 | goto error_handler_free; |
| 2772 | } | 2739 | } |
| 2773 | 2740 | ||
| 2774 | ov5670->streaming = false; | ||
| 2775 | |||
| 2776 | /* Set the device's state to active if it's in D0 state. */ | 2741 | /* Set the device's state to active if it's in D0 state. */ |
| 2777 | if (full_power) | 2742 | if (full_power) |
| 2778 | pm_runtime_set_active(&client->dev); | 2743 | pm_runtime_set_active(&client->dev); |
| @@ -2827,7 +2792,6 @@ static void ov5670_remove(struct i2c_client *client) · 48 unmodified lines | |||
| 2827 | } | 2792 | } |
| 2828 | 2793 | ||
| 2829 | static const struct dev_pm_ops ov5670_pm_ops = { | 2794 | static const struct dev_pm_ops ov5670_pm_ops = { |
| 2830 | SET_SYSTEM_SLEEP_PM_OPS(ov5670_suspend, ov5670_resume) | ||
| 2831 | SET_RUNTIME_PM_OPS(ov5670_runtime_suspend, ov5670_runtime_resume, NULL) | 2795 | SET_RUNTIME_PM_OPS(ov5670_runtime_suspend, ov5670_runtime_resume, NULL) |
| 2832 | }; | 2796 | }; |
| 2833 | 2797 | ||
| @@ -513,9 +513,6 @@ struct ov5675 { · 512 unmodified lines | |||
| 513 | /* To serialize asynchronus callbacks */ | 513 | /* To serialize asynchronus callbacks */ |
| 514 | struct mutex mutex; | 514 | struct mutex mutex; |
| 515 | 515 | ||
| 516 | /* Streaming on/off */ | ||
| 517 | bool streaming; | ||
| 518 | |||
| 519 | /* True if the device has been identified */ | 516 | /* True if the device has been identified */ |
| 520 | bool identified; | 517 | bool identified; |
| 521 | }; | 518 | }; |
| @@ -949,9 +946,6 @@ static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) · 427 unmodified lines | |||
| 949 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 946 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 950 | int ret = 0; | 947 | int ret = 0; |
| 951 | 948 | ||
| 952 | if (ov5675->streaming == enable) | ||
| 953 | return 0; | ||
| 954 | |||
| 955 | mutex_lock(&ov5675->mutex); | 949 | mutex_lock(&ov5675->mutex); |
| 956 | if (enable) { | 950 | if (enable) { |
| 957 | ret = pm_runtime_resume_and_get(&client->dev); | 951 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -971,7 +965,6 @@ static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) · 13 unmodified lines | |||
| 971 | pm_runtime_put(&client->dev); | 965 | pm_runtime_put(&client->dev); |
| 972 | } | 966 | } |
| 973 | 967 | ||
| 974 | ov5675->streaming = enable; | ||
| 975 | mutex_unlock(&ov5675->mutex); | 968 | mutex_unlock(&ov5675->mutex); |
| 976 | 969 | ||
| 977 | return ret; | 970 | return ret; |
| @@ -1027,42 +1020,6 @@ static int ov5675_power_on(struct device *dev) · 49 unmodified lines | |||
| 1027 | return 0; | 1020 | return 0; |
| 1028 | } | 1021 | } |
| 1029 | 1022 | ||
| 1030 | static int __maybe_unused ov5675_suspend(struct device *dev) | ||
| 1031 | { | ||
| 1032 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1033 | struct ov5675 *ov5675 = to_ov5675(sd); | ||
| 1034 | |||
| 1035 | mutex_lock(&ov5675->mutex); | ||
| 1036 | if (ov5675->streaming) | ||
| 1037 | ov5675_stop_streaming(ov5675); | ||
| 1038 | |||
| 1039 | mutex_unlock(&ov5675->mutex); | ||
| 1040 | |||
| 1041 | return 0; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static int __maybe_unused ov5675_resume(struct device *dev) | ||
| 1045 | { | ||
| 1046 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 1047 | struct ov5675 *ov5675 = to_ov5675(sd); | ||
| 1048 | int ret; | ||
| 1049 | |||
| 1050 | mutex_lock(&ov5675->mutex); | ||
| 1051 | if (ov5675->streaming) { | ||
| 1052 | ret = ov5675_start_streaming(ov5675); | ||
| 1053 | if (ret) { | ||
| 1054 | ov5675->streaming = false; | ||
| 1055 | ov5675_stop_streaming(ov5675); | ||
| 1056 | mutex_unlock(&ov5675->mutex); | ||
| 1057 | return ret; | ||
| 1058 | } | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | mutex_unlock(&ov5675->mutex); | ||
| 1062 | |||
| 1063 | return 0; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | static int ov5675_set_format(struct v4l2_subdev *sd, | 1023 | static int ov5675_set_format(struct v4l2_subdev *sd, |
| 1067 | struct v4l2_subdev_state *sd_state, | 1024 | struct v4l2_subdev_state *sd_state, |
| 1068 | struct v4l2_subdev_format *fmt) | 1025 | struct v4l2_subdev_format *fmt) |
| @@ -1409,7 +1366,6 @@ probe_power_off: · 340 unmodified lines | |||
| 1409 | } | 1366 | } |
| 1410 | 1367 | ||
| 1411 | static const struct dev_pm_ops ov5675_pm_ops = { | 1368 | static const struct dev_pm_ops ov5675_pm_ops = { |
| 1412 | SET_SYSTEM_SLEEP_PM_OPS(ov5675_suspend, ov5675_resume) | ||
| 1413 | SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL) | 1369 | SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL) |
| 1414 | }; | 1370 | }; |
| 1415 | 1371 | ||
| @@ -154,7 +154,6 @@ struct ov5693_device { · 153 unmodified lines | |||
| 154 | unsigned int inc_y_odd; | 154 | unsigned int inc_y_odd; |
| 155 | unsigned int vts; | 155 | unsigned int vts; |
| 156 | } mode; | 156 | } mode; |
| 157 | bool streaming; | ||
| 158 | 157 | ||
| 159 | struct v4l2_subdev sd; | 158 | struct v4l2_subdev sd; |
| 160 | struct media_pad pad; | 159 | struct media_pad pad; |
| @@ -975,9 +974,9 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) · 814 unmodified lines | |||
| 975 | int ret; | 974 | int ret; |
| 976 | 975 | ||
| 977 | if (enable) { | 976 | if (enable) { |
| 978 | ret = pm_runtime_get_sync(ov5693->dev); | 977 | ret = pm_runtime_resume_and_get(ov5693->dev); |
| 979 | if (ret < 0) | 978 | if (ret) |
| 980 | goto err_power_down; | 979 | return ret; |
| 981 | 980 | ||
| 982 | mutex_lock(&ov5693->lock); | 981 | mutex_lock(&ov5693->lock); |
| 983 | ret = __v4l2_ctrl_handler_setup(&ov5693->ctrls.handler); | 982 | ret = __v4l2_ctrl_handler_setup(&ov5693->ctrls.handler); |
| @@ -996,8 +995,6 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) · 12 unmodified lines | |||
| 996 | if (ret) | 995 | if (ret) |
| 997 | goto err_power_down; | 996 | goto err_power_down; |
| 998 | 997 | ||
| 999 | ov5693->streaming = !!enable; | ||
| 1000 | |||
| 1001 | if (!enable) | 998 | if (!enable) |
| 1002 | pm_runtime_put(ov5693->dev); | 999 | pm_runtime_put(ov5693->dev); |
| 1003 | 1000 | ||
| @@ -108,7 +108,6 @@ struct ov5695 { · 107 unmodified lines | |||
| 108 | struct v4l2_ctrl *vblank; | 108 | struct v4l2_ctrl *vblank; |
| 109 | struct v4l2_ctrl *test_pattern; | 109 | struct v4l2_ctrl *test_pattern; |
| 110 | struct mutex mutex; | 110 | struct mutex mutex; |
| 111 | bool streaming; | ||
| 112 | const struct ov5695_mode *cur_mode; | 111 | const struct ov5695_mode *cur_mode; |
| 113 | }; | 112 | }; |
| 114 | 113 | ||
| @@ -821,9 +820,7 @@ static int ov5695_set_fmt(struct v4l2_subdev *sd, · 706 unmodified lines | |||
| 821 | fmt->format.height = mode->height; | 820 | fmt->format.height = mode->height; |
| 822 | fmt->format.field = V4L2_FIELD_NONE; | 821 | fmt->format.field = V4L2_FIELD_NONE; |
| 823 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 822 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 824 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 825 | *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; | 823 | *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; |
| 826 | #endif | ||
| 827 | } else { | 824 | } else { |
| 828 | ov5695->cur_mode = mode; | 825 | ov5695->cur_mode = mode; |
| 829 | h_blank = mode->hts_def - mode->width; | 826 | h_blank = mode->hts_def - mode->width; |
| @@ -849,13 +846,8 @@ static int ov5695_get_fmt(struct v4l2_subdev *sd, · 19 unmodified lines | |||
| 849 | 846 | ||
| 850 | mutex_lock(&ov5695->mutex); | 847 | mutex_lock(&ov5695->mutex); |
| 851 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | 848 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 852 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 853 | fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, | 849 | fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, |
| 854 | fmt->pad); | 850 | fmt->pad); |
| 855 | #else | ||
| 856 | mutex_unlock(&ov5695->mutex); | ||
| 857 | return -EINVAL; | ||
| 858 | #endif | ||
| 859 | } else { | 851 | } else { |
| 860 | fmt->format.width = mode->width; | 852 | fmt->format.width = mode->width; |
| 861 | fmt->format.height = mode->height; | 853 | fmt->format.height = mode->height; |
| @@ -942,9 +934,6 @@ static int ov5695_s_stream(struct v4l2_subdev *sd, int on) · 80 unmodified lines | |||
| 942 | int ret = 0; | 934 | int ret = 0; |
| 943 | 935 | ||
| 944 | mutex_lock(&ov5695->mutex); | 936 | mutex_lock(&ov5695->mutex); |
| 945 | on = !!on; | ||
| 946 | if (on == ov5695->streaming) | ||
| 947 | goto unlock_and_return; | ||
| 948 | 937 | ||
| 949 | if (on) { | 938 | if (on) { |
| 950 | ret = pm_runtime_resume_and_get(&client->dev); | 939 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -962,8 +951,6 @@ static int ov5695_s_stream(struct v4l2_subdev *sd, int on) · 11 unmodified lines | |||
| 962 | pm_runtime_put(&client->dev); | 951 | pm_runtime_put(&client->dev); |
| 963 | } | 952 | } |
| 964 | 953 | ||
| 965 | ov5695->streaming = on; | ||
| 966 | |||
| 967 | unlock_and_return: | 954 | unlock_and_return: |
| 968 | mutex_unlock(&ov5695->mutex); | 955 | mutex_unlock(&ov5695->mutex); |
| 969 | 956 | ||
| @@ -1048,7 +1035,6 @@ static int __maybe_unused ov5695_runtime_suspend(struct device *dev) · 78 unmodified lines | |||
| 1048 | return 0; | 1035 | return 0; |
| 1049 | } | 1036 | } |
| 1050 | 1037 | ||
| 1051 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1052 | static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 1038 | static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1053 | { | 1039 | { |
| 1054 | struct ov5695 *ov5695 = to_ov5695(sd); | 1040 | struct ov5695 *ov5695 = to_ov5695(sd); |
| @@ -1068,18 +1054,15 @@ static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 13 unmodified lines | |||
| 1068 | 1054 | ||
| 1069 | return 0; | 1055 | return 0; |
| 1070 | } | 1056 | } |
| 1071 | #endif | ||
| 1072 | 1057 | ||
| 1073 | static const struct dev_pm_ops ov5695_pm_ops = { | 1058 | static const struct dev_pm_ops ov5695_pm_ops = { |
| 1074 | SET_RUNTIME_PM_OPS(ov5695_runtime_suspend, | 1059 | SET_RUNTIME_PM_OPS(ov5695_runtime_suspend, |
| 1075 | ov5695_runtime_resume, NULL) | 1060 | ov5695_runtime_resume, NULL) |
| 1076 | }; | 1061 | }; |
| 1077 | 1062 | ||
| 1078 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1079 | static const struct v4l2_subdev_internal_ops ov5695_internal_ops = { | 1063 | static const struct v4l2_subdev_internal_ops ov5695_internal_ops = { |
| 1080 | .open = ov5695_open, | 1064 | .open = ov5695_open, |
| 1081 | }; | 1065 | }; |
| 1082 | #endif | ||
| 1083 | 1066 | ||
| 1084 | static const struct v4l2_subdev_video_ops ov5695_video_ops = { | 1067 | static const struct v4l2_subdev_video_ops ov5695_video_ops = { |
| 1085 | .s_stream = ov5695_s_stream, | 1068 | .s_stream = ov5695_s_stream, |
| @@ -1322,17 +1305,13 @@ static int ov5695_probe(struct i2c_client *client) · 236 unmodified lines | |||
| 1322 | if (ret) | 1305 | if (ret) |
| 1323 | goto err_power_off; | 1306 | goto err_power_off; |
| 1324 | 1307 | ||
| 1325 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1326 | sd->internal_ops = &ov5695_internal_ops; | 1308 | sd->internal_ops = &ov5695_internal_ops; |
| 1327 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1309 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1328 | #endif | ||
| 1329 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1330 | ov5695->pad.flags = MEDIA_PAD_FL_SOURCE; | 1310 | ov5695->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1331 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1311 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1332 | ret = media_entity_pads_init(&sd->entity, 1, &ov5695->pad); | 1312 | ret = media_entity_pads_init(&sd->entity, 1, &ov5695->pad); |
| 1333 | if (ret < 0) | 1313 | if (ret < 0) |
| 1334 | goto err_power_off; | 1314 | goto err_power_off; |
| 1335 | #endif | ||
| 1336 | 1315 | ||
| 1337 | ret = v4l2_async_register_subdev_sensor(sd); | 1316 | ret = v4l2_async_register_subdev_sensor(sd); |
| 1338 | if (ret) { | 1317 | if (ret) { |
| @@ -1347,9 +1326,7 @@ static int ov5695_probe(struct i2c_client *client) · 8 unmodified lines | |||
| 1347 | return 0; | 1326 | return 0; |
| 1348 | 1327 | ||
| 1349 | err_clean_entity: | 1328 | err_clean_entity: |
| 1350 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1351 | media_entity_cleanup(&sd->entity); | 1329 | media_entity_cleanup(&sd->entity); |
| 1352 | #endif | ||
| 1353 | err_power_off: | 1330 | err_power_off: |
| 1354 | __ov5695_power_off(ov5695); | 1331 | __ov5695_power_off(ov5695); |
| 1355 | err_free_handler: | 1332 | err_free_handler: |
| @@ -1366,9 +1343,7 @@ static void ov5695_remove(struct i2c_client *client) · 10 unmodified lines | |||
| 1366 | struct ov5695 *ov5695 = to_ov5695(sd); | 1343 | struct ov5695 *ov5695 = to_ov5695(sd); |
| 1367 | 1344 | ||
| 1368 | v4l2_async_unregister_subdev(sd); | 1345 | v4l2_async_unregister_subdev(sd); |
| 1369 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1370 | media_entity_cleanup(&sd->entity); | 1346 | media_entity_cleanup(&sd->entity); |
| 1371 | #endif | ||
| 1372 | v4l2_ctrl_handler_free(&ov5695->ctrl_handler); | 1347 | v4l2_ctrl_handler_free(&ov5695->ctrl_handler); |
| 1373 | mutex_destroy(&ov5695->mutex); | 1348 | mutex_destroy(&ov5695->mutex); |
| 1374 | 1349 | ||
| @@ -1340,9 +1340,11 @@ static int ov7251_s_stream(struct v4l2_subdev *subdev, int enable) · 1339 unmodified lines | |||
| 1340 | mutex_lock(&ov7251->lock); | 1340 | mutex_lock(&ov7251->lock); |
| 1341 | 1341 | ||
| 1342 | if (enable) { | 1342 | if (enable) { |
| 1343 | ret = pm_runtime_get_sync(ov7251->dev); | 1343 | ret = pm_runtime_resume_and_get(ov7251->dev); |
| 1344 | if (ret < 0) | 1344 | if (ret) { |
| 1345 | goto err_power_down; | 1345 | mutex_unlock(&ov7251->lock); |
| 1346 | return ret; | ||
| 1347 | } | ||
| 1346 | 1348 | ||
| 1347 | ret = ov7251_pll_configure(ov7251); | 1349 | ret = ov7251_pll_configure(ov7251); |
| 1348 | if (ret) { | 1350 | if (ret) { |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | */ | 10 | */ |
| 11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/mod_devicetable.h> | ||
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 15 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| @@ -186,11 +187,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); · 170 unmodified lines | |||
| 186 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ | 187 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ |
| 187 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ | 188 | #define REG_BD60MAX 0xab /* 60hz banding step limit */ |
| 188 | 189 | ||
| 189 | enum ov7670_model { | ||
| 190 | MODEL_OV7670 = 0, | ||
| 191 | MODEL_OV7675, | ||
| 192 | }; | ||
| 193 | |||
| 194 | struct ov7670_win_size { | 190 | struct ov7670_win_size { |
| 195 | int width; | 191 | int width; |
| 196 | int height; | 192 | int height; |
| @@ -217,9 +213,7 @@ struct ov7670_devtype { · 20 unmodified lines | |||
| 217 | struct ov7670_format_struct; /* coming later */ | 213 | struct ov7670_format_struct; /* coming later */ |
| 218 | struct ov7670_info { | 214 | struct ov7670_info { |
| 219 | struct v4l2_subdev sd; | 215 | struct v4l2_subdev sd; |
| 220 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 221 | struct media_pad pad; | 216 | struct media_pad pad; |
| 222 | #endif | ||
| 223 | struct v4l2_ctrl_handler hdl; | 217 | struct v4l2_ctrl_handler hdl; |
| 224 | struct { | 218 | struct { |
| 225 | /* gain cluster */ | 219 | /* gain cluster */ |
| @@ -1108,9 +1102,7 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, · 882 unmodified lines | |||
| 1108 | struct v4l2_subdev_format *format) | 1102 | struct v4l2_subdev_format *format) |
| 1109 | { | 1103 | { |
| 1110 | struct ov7670_info *info = to_state(sd); | 1104 | struct ov7670_info *info = to_state(sd); |
| 1111 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1112 | struct v4l2_mbus_framefmt *mbus_fmt; | 1105 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 1113 | #endif | ||
| 1114 | int ret; | 1106 | int ret; |
| 1115 | 1107 | ||
| 1116 | if (format->pad) | 1108 | if (format->pad) |
| @@ -1120,11 +1112,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, · 3 unmodified lines | |||
| 1120 | ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); | 1112 | ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); |
| 1121 | if (ret) | 1113 | if (ret) |
| 1122 | return ret; | 1114 | return ret; |
| 1123 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1124 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, | 1115 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, |
| 1125 | format->pad); | 1116 | format->pad); |
| 1126 | *mbus_fmt = format->format; | 1117 | *mbus_fmt = format->format; |
| 1127 | #endif | ||
| 1128 | return 0; | 1118 | return 0; |
| 1129 | } | 1119 | } |
| 1130 | 1120 | ||
| @@ -1148,18 +1138,12 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd, · 17 unmodified lines | |||
| 1148 | struct v4l2_subdev_format *format) | 1138 | struct v4l2_subdev_format *format) |
| 1149 | { | 1139 | { |
| 1150 | struct ov7670_info *info = to_state(sd); | 1140 | struct ov7670_info *info = to_state(sd); |
| 1151 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1152 | struct v4l2_mbus_framefmt *mbus_fmt; | 1141 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 1153 | #endif | ||
| 1154 | 1142 | ||
| 1155 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { | 1143 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1156 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1157 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); | 1144 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 1158 | format->format = *mbus_fmt; | 1145 | format->format = *mbus_fmt; |
| 1159 | return 0; | 1146 | return 0; |
| 1160 | #else | ||
| 1161 | return -EINVAL; | ||
| 1162 | #endif | ||
| 1163 | } else { | 1147 | } else { |
| 1164 | format->format = info->format; | 1148 | format->format = info->format; |
| 1165 | } | 1149 | } |
| @@ -1720,7 +1704,6 @@ static void ov7670_get_default_format(struct v4l2_subdev *sd, · 554 unmodified lines | |||
| 1720 | format->field = V4L2_FIELD_NONE; | 1704 | format->field = V4L2_FIELD_NONE; |
| 1721 | } | 1705 | } |
| 1722 | 1706 | ||
| 1723 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1724 | static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 1707 | static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1725 | { | 1708 | { |
| 1726 | struct v4l2_mbus_framefmt *format = | 1709 | struct v4l2_mbus_framefmt *format = |
| @@ -1730,7 +1713,6 @@ static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 3 unmodified lines | |||
| 1730 | 1713 | ||
| 1731 | return 0; | 1714 | return 0; |
| 1732 | } | 1715 | } |
| 1733 | #endif | ||
| 1734 | 1716 | ||
| 1735 | /* ----------------------------------------------------------------------- */ | 1717 | /* ----------------------------------------------------------------------- */ |
| 1736 | 1718 | ||
| @@ -1766,29 +1748,12 @@ static const struct v4l2_subdev_ops ov7670_ops = { · 29 unmodified lines | |||
| 1766 | .pad = &ov7670_pad_ops, | 1748 | .pad = &ov7670_pad_ops, |
| 1767 | }; | 1749 | }; |
| 1768 | 1750 | ||
| 1769 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1770 | static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { | 1751 | static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { |
| 1771 | .open = ov7670_open, | 1752 | .open = ov7670_open, |
| 1772 | }; | 1753 | }; |
| 1773 | #endif | ||
| 1774 | 1754 | ||
| 1775 | /* ----------------------------------------------------------------------- */ | 1755 | /* ----------------------------------------------------------------------- */ |
| 1776 | 1756 | ||
| 1777 | static const struct ov7670_devtype ov7670_devdata[] = { | ||
| 1778 | [MODEL_OV7670] = { | ||
| 1779 | .win_sizes = ov7670_win_sizes, | ||
| 1780 | .n_win_sizes = ARRAY_SIZE(ov7670_win_sizes), | ||
| 1781 | .set_framerate = ov7670_set_framerate_legacy, | ||
| 1782 | .get_framerate = ov7670_get_framerate_legacy, | ||
| 1783 | }, | ||
| 1784 | [MODEL_OV7675] = { | ||
| 1785 | .win_sizes = ov7675_win_sizes, | ||
| 1786 | .n_win_sizes = ARRAY_SIZE(ov7675_win_sizes), | ||
| 1787 | .set_framerate = ov7675_set_framerate, | ||
| 1788 | .get_framerate = ov7675_get_framerate, | ||
| 1789 | }, | ||
| 1790 | }; | ||
| 1791 | |||
| 1792 | static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info) | 1757 | static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info) |
| 1793 | { | 1758 | { |
| 1794 | info->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", | 1759 | info->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", |
| @@ -1849,7 +1814,6 @@ static int ov7670_parse_dt(struct device *dev, · 54 unmodified lines | |||
| 1849 | 1814 | ||
| 1850 | static int ov7670_probe(struct i2c_client *client) | 1815 | static int ov7670_probe(struct i2c_client *client) |
| 1851 | { | 1816 | { |
| 1852 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | ||
| 1853 | struct v4l2_fract tpf; | 1817 | struct v4l2_fract tpf; |
| 1854 | struct v4l2_subdev *sd; | 1818 | struct v4l2_subdev *sd; |
| 1855 | struct ov7670_info *info; | 1819 | struct ov7670_info *info; |
| @@ -1861,10 +1825,8 @@ static int ov7670_probe(struct i2c_client *client) · 5 unmodified lines | |||
| 1861 | sd = &info->sd; | 1825 | sd = &info->sd; |
| 1862 | v4l2_i2c_subdev_init(sd, client, &ov7670_ops); | 1826 | v4l2_i2c_subdev_init(sd, client, &ov7670_ops); |
| 1863 | 1827 | ||
| 1864 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1865 | sd->internal_ops = &ov7670_subdev_internal_ops; | 1828 | sd->internal_ops = &ov7670_subdev_internal_ops; |
| 1866 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; | 1829 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1867 | #endif | ||
| 1868 | 1830 | ||
| 1869 | info->clock_speed = 30; /* default: a guess */ | 1831 | info->clock_speed = 30; /* default: a guess */ |
| 1870 | 1832 | ||
| @@ -1923,7 +1885,7 @@ static int ov7670_probe(struct i2c_client *client) · 52 unmodified lines | |||
| 1923 | v4l_info(client, "chip found @ 0x%02x (%s)\n", | 1885 | v4l_info(client, "chip found @ 0x%02x (%s)\n", |
| 1924 | client->addr << 1, client->adapter->name); | 1886 | client->addr << 1, client->adapter->name); |
| 1925 | 1887 | ||
| 1926 | info->devtype = &ov7670_devdata[id->driver_data]; | 1888 | info->devtype = i2c_get_match_data(client); |
| 1927 | info->fmt = &ov7670_formats[0]; | 1889 | info->fmt = &ov7670_formats[0]; |
| 1928 | info->wsize = &info->devtype->win_sizes[0]; | 1890 | info->wsize = &info->devtype->win_sizes[0]; |
| 1929 | 1891 | ||
| @@ -1977,13 +1939,11 @@ static int ov7670_probe(struct i2c_client *client) · 47 unmodified lines | |||
| 1977 | V4L2_EXPOSURE_MANUAL, false); | 1939 | V4L2_EXPOSURE_MANUAL, false); |
| 1978 | v4l2_ctrl_cluster(2, &info->saturation); | 1940 | v4l2_ctrl_cluster(2, &info->saturation); |
| 1979 | 1941 | ||
| 1980 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1981 | info->pad.flags = MEDIA_PAD_FL_SOURCE; | 1942 | info->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1982 | info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1943 | info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1983 | ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); | 1944 | ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); |
| 1984 | if (ret < 0) | 1945 | if (ret < 0) |
| 1985 | goto hdl_free; | 1946 | goto hdl_free; |
| 1986 | #endif | ||
| 1987 | 1947 | ||
| 1988 | v4l2_ctrl_handler_setup(&info->hdl); | 1948 | v4l2_ctrl_handler_setup(&info->hdl); |
| 1989 | 1949 | ||
| @@ -2013,25 +1973,37 @@ static void ov7670_remove(struct i2c_client *client) · 23 unmodified lines | |||
| 2013 | media_entity_cleanup(&info->sd.entity); | 1973 | media_entity_cleanup(&info->sd.entity); |
| 2014 | } | 1974 | } |
| 2015 | 1975 | ||
| 1976 | static const struct ov7670_devtype ov7670_devdata = { | ||
| 1977 | .win_sizes = ov7670_win_sizes, | ||
| 1978 | .n_win_sizes = ARRAY_SIZE(ov7670_win_sizes), | ||
| 1979 | .set_framerate = ov7670_set_framerate_legacy, | ||
| 1980 | .get_framerate = ov7670_get_framerate_legacy, | ||
| 1981 | }; | ||
| 1982 | |||
| 1983 | static const struct ov7670_devtype ov7675_devdata = { | ||
| 1984 | .win_sizes = ov7675_win_sizes, | ||
| 1985 | .n_win_sizes = ARRAY_SIZE(ov7675_win_sizes), | ||
| 1986 | .set_framerate = ov7675_set_framerate, | ||
| 1987 | .get_framerate = ov7675_get_framerate, | ||
| 1988 | }; | ||
| 1989 | |||
| 2016 | static const struct i2c_device_id ov7670_id[] = { | 1990 | static const struct i2c_device_id ov7670_id[] = { |
| 2017 | { "ov7670", MODEL_OV7670 }, | 1991 | { "ov7670", (kernel_ulong_t)&ov7670_devdata }, |
| 2018 | { "ov7675", MODEL_OV7675 }, | 1992 | { "ov7675", (kernel_ulong_t)&ov7675_devdata }, |
| 2019 | { } | 1993 | { /* sentinel */ } |
| 2020 | }; | 1994 | }; |
| 2021 | MODULE_DEVICE_TABLE(i2c, ov7670_id); | 1995 | MODULE_DEVICE_TABLE(i2c, ov7670_id); |
| 2022 | 1996 | ||
| 2023 | #if IS_ENABLED(CONFIG_OF) | ||
| 2024 | static const struct of_device_id ov7670_of_match[] = { | 1997 | static const struct of_device_id ov7670_of_match[] = { |
| 2025 | { .compatible = "ovti,ov7670", }, | 1998 | { .compatible = "ovti,ov7670", &ov7670_devdata }, |
| 2026 | { /* sentinel */ }, | 1999 | { /* sentinel */ } |
| 2027 | }; | 2000 | }; |
| 2028 | MODULE_DEVICE_TABLE(of, ov7670_of_match); | 2001 | MODULE_DEVICE_TABLE(of, ov7670_of_match); |
| 2029 | #endif | ||
| 2030 | 2002 | ||
| 2031 | static struct i2c_driver ov7670_driver = { | 2003 | static struct i2c_driver ov7670_driver = { |
| 2032 | .driver = { | 2004 | .driver = { |
| 2033 | .name = "ov7670", | 2005 | .name = "ov7670", |
| 2034 | .of_match_table = of_match_ptr(ov7670_of_match), | 2006 | .of_match_table = ov7670_of_match, |
| 2035 | }, | 2007 | }, |
| 2036 | .probe = ov7670_probe, | 2008 | .probe = ov7670_probe, |
| 2037 | .remove = ov7670_remove, | 2009 | .remove = ov7670_remove, |
| @@ -433,9 +433,7 @@ struct ov772x_priv { · 432 unmodified lines | |||
| 433 | struct mutex lock; | 433 | struct mutex lock; |
| 434 | int power_count; | 434 | int power_count; |
| 435 | int streaming; | 435 | int streaming; |
| 436 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 437 | struct media_pad pad; | 436 | struct media_pad pad; |
| 438 | #endif | ||
| 439 | enum v4l2_mbus_type bus_type; | 437 | enum v4l2_mbus_type bus_type; |
| 440 | }; | 438 | }; |
| 441 | 439 | ||
| @@ -1488,13 +1486,11 @@ static int ov772x_probe(struct i2c_client *client) · 1046 unmodified lines | |||
| 1488 | if (ret < 0) | 1486 | if (ret < 0) |
| 1489 | goto error_gpio_put; | 1487 | goto error_gpio_put; |
| 1490 | 1488 | ||
| 1491 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 1492 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; | 1489 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1493 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1490 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1494 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); | 1491 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); |
| 1495 | if (ret < 0) | 1492 | if (ret < 0) |
| 1496 | goto error_gpio_put; | 1493 | goto error_gpio_put; |
| 1497 | #endif | ||
| 1498 | 1494 | ||
| 1499 | priv->cfmt = &ov772x_cfmts[0]; | 1495 | priv->cfmt = &ov772x_cfmts[0]; |
| 1500 | priv->win = &ov772x_win_sizes[0]; | 1496 | priv->win = &ov772x_win_sizes[0]; |
| @@ -83,9 +83,7 @@ · 82 unmodified lines | |||
| 83 | 83 | ||
| 84 | struct ov7740 { | 84 | struct ov7740 { |
| 85 | struct v4l2_subdev subdev; | 85 | struct v4l2_subdev subdev; |
| 86 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 87 | struct media_pad pad; | 86 | struct media_pad pad; |
| 88 | #endif | ||
| 89 | struct v4l2_mbus_framefmt format; | 87 | struct v4l2_mbus_framefmt format; |
| 90 | const struct ov7740_pixfmt *fmt; /* Current format */ | 88 | const struct ov7740_pixfmt *fmt; /* Current format */ |
| 91 | const struct ov7740_framesize *frmsize; | 89 | const struct ov7740_framesize *frmsize; |
| @@ -120,7 +118,6 @@ struct ov7740 { · 28 unmodified lines | |||
| 120 | struct v4l2_ctrl *contrast; | 118 | struct v4l2_ctrl *contrast; |
| 121 | 119 | ||
| 122 | struct mutex mutex; /* To serialize asynchronus callbacks */ | 120 | struct mutex mutex; /* To serialize asynchronus callbacks */ |
| 123 | bool streaming; /* Streaming on/off */ | ||
| 124 | 121 | ||
| 125 | struct gpio_desc *resetb_gpio; | 122 | struct gpio_desc *resetb_gpio; |
| 126 | struct gpio_desc *pwdn_gpio; | 123 | struct gpio_desc *pwdn_gpio; |
| @@ -618,10 +615,6 @@ static int ov7740_set_stream(struct v4l2_subdev *sd, int enable) · 491 unmodified lines | |||
| 618 | int ret = 0; | 615 | int ret = 0; |
| 619 | 616 | ||
| 620 | mutex_lock(&ov7740->mutex); | 617 | mutex_lock(&ov7740->mutex); |
| 621 | if (ov7740->streaming == enable) { | ||
| 622 | mutex_unlock(&ov7740->mutex); | ||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | 618 | ||
| 626 | if (enable) { | 619 | if (enable) { |
| 627 | ret = pm_runtime_resume_and_get(&client->dev); | 620 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -635,8 +628,6 @@ static int ov7740_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 635 | pm_runtime_put(&client->dev); | 628 | pm_runtime_put(&client->dev); |
| 636 | } | 629 | } |
| 637 | 630 | ||
| 638 | ov7740->streaming = enable; | ||
| 639 | |||
| 640 | mutex_unlock(&ov7740->mutex); | 631 | mutex_unlock(&ov7740->mutex); |
| 641 | return ret; | 632 | return ret; |
| 642 | 633 | ||
| @@ -807,9 +798,7 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd, · 164 unmodified lines | |||
| 807 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); | 798 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); |
| 808 | const struct ov7740_pixfmt *ovfmt; | 799 | const struct ov7740_pixfmt *ovfmt; |
| 809 | const struct ov7740_framesize *fsize; | 800 | const struct ov7740_framesize *fsize; |
| 810 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 811 | struct v4l2_mbus_framefmt *mbus_fmt; | 801 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 812 | #endif | ||
| 813 | int ret; | 802 | int ret; |
| 814 | 803 | ||
| 815 | mutex_lock(&ov7740->mutex); | 804 | mutex_lock(&ov7740->mutex); |
| @@ -822,11 +811,10 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd, · 6 unmodified lines | |||
| 822 | ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL); | 811 | ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL); |
| 823 | if (ret) | 812 | if (ret) |
| 824 | goto error; | 813 | goto error; |
| 825 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | 814 | |
| 826 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, | 815 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, |
| 827 | format->pad); | 816 | format->pad); |
| 828 | *mbus_fmt = format->format; | 817 | *mbus_fmt = format->format; |
| 829 | #endif | ||
| 830 | mutex_unlock(&ov7740->mutex); | 818 | mutex_unlock(&ov7740->mutex); |
| 831 | return 0; | 819 | return 0; |
| 832 | } | 820 | } |
| @@ -851,26 +839,18 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd, · 18 unmodified lines | |||
| 851 | struct v4l2_subdev_format *format) | 839 | struct v4l2_subdev_format *format) |
| 852 | { | 840 | { |
| 853 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); | 841 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); |
| 854 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 855 | struct v4l2_mbus_framefmt *mbus_fmt; | 842 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 856 | #endif | ||
| 857 | int ret = 0; | ||
| 858 | 843 | ||
| 859 | mutex_lock(&ov7740->mutex); | 844 | mutex_lock(&ov7740->mutex); |
| 860 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { | 845 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 861 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 862 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); | 846 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 863 | format->format = *mbus_fmt; | 847 | format->format = *mbus_fmt; |
| 864 | ret = 0; | ||
| 865 | #else | ||
| 866 | ret = -EINVAL; | ||
| 867 | #endif | ||
| 868 | } else { | 848 | } else { |
| 869 | format->format = ov7740->format; | 849 | format->format = ov7740->format; |
| 870 | } | 850 | } |
| 871 | mutex_unlock(&ov7740->mutex); | 851 | mutex_unlock(&ov7740->mutex); |
| 872 | 852 | ||
| 873 | return ret; | 853 | return 0; |
| 874 | } | 854 | } |
| 875 | 855 | ||
| 876 | static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = { | 856 | static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = { |
| @@ -899,7 +879,6 @@ static void ov7740_get_default_format(struct v4l2_subdev *sd, · 22 unmodified lines | |||
| 899 | format->field = V4L2_FIELD_NONE; | 879 | format->field = V4L2_FIELD_NONE; |
| 900 | } | 880 | } |
| 901 | 881 | ||
| 902 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 903 | static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | 882 | static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 904 | { | 883 | { |
| 905 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); | 884 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); |
| @@ -916,7 +895,6 @@ static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 10 unmodified lines | |||
| 916 | static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = { | 895 | static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = { |
| 917 | .open = ov7740_open, | 896 | .open = ov7740_open, |
| 918 | }; | 897 | }; |
| 919 | #endif | ||
| 920 | 898 | ||
| 921 | static int ov7740_probe_dt(struct i2c_client *client, | 899 | static int ov7740_probe_dt(struct i2c_client *client, |
| 922 | struct ov7740 *ov7740) | 900 | struct ov7740 *ov7740) |
| @@ -1094,18 +1072,14 @@ static int ov7740_probe(struct i2c_client *client) · 171 unmodified lines | |||
| 1094 | sd = &ov7740->subdev; | 1072 | sd = &ov7740->subdev; |
| 1095 | v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops); | 1073 | v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops); |
| 1096 | 1074 | ||
| 1097 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | ||
| 1098 | sd->internal_ops = &ov7740_subdev_internal_ops; | 1075 | sd->internal_ops = &ov7740_subdev_internal_ops; |
| 1099 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; | 1076 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1100 | #endif | ||
| 1101 | 1077 | ||
| 1102 | #if defined(CONFIG_MEDIA_CONTROLLER) | ||
| 1103 | ov7740->pad.flags = MEDIA_PAD_FL_SOURCE; | 1078 | ov7740->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1104 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; | 1079 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1105 | ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad); | 1080 | ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad); |
| 1106 | if (ret) | 1081 | if (ret) |
| 1107 | return ret; | 1082 | return ret; |
| 1108 | #endif | ||
| 1109 | 1083 | ||
| 1110 | ret = ov7740_set_power(ov7740, 1); | 1084 | ret = ov7740_set_power(ov7740, 1); |
| 1111 | if (ret) | 1085 | if (ret) |
| @@ -1438,9 +1438,6 @@ struct ov8856 { · 1437 unmodified lines | |||
| 1438 | /* To serialize asynchronus callbacks */ | 1438 | /* To serialize asynchronus callbacks */ |
| 1439 | struct mutex mutex; | 1439 | struct mutex mutex; |
| 1440 | 1440 | ||
| 1441 | /* Streaming on/off */ | ||
| 1442 | bool streaming; | ||
| 1443 | |||
| 1444 | /* lanes index */ | 1441 | /* lanes index */ |
| 1445 | u8 nlanes; | 1442 | u8 nlanes; |
| 1446 | 1443 | ||
| @@ -2042,9 +2039,6 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable) · 595 unmodified lines | |||
| 2042 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 2039 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 2043 | int ret = 0; | 2040 | int ret = 0; |
| 2044 | 2041 | ||
| 2045 | if (ov8856->streaming == enable) | ||
| 2046 | return 0; | ||
| 2047 | |||
| 2048 | mutex_lock(&ov8856->mutex); | 2042 | mutex_lock(&ov8856->mutex); |
| 2049 | if (enable) { | 2043 | if (enable) { |
| 2050 | ret = pm_runtime_resume_and_get(&client->dev); | 2044 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -2064,7 +2058,6 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable) · 13 unmodified lines | |||
| 2064 | pm_runtime_put(&client->dev); | 2058 | pm_runtime_put(&client->dev); |
| 2065 | } | 2059 | } |
| 2066 | 2060 | ||
| 2067 | ov8856->streaming = enable; | ||
| 2068 | mutex_unlock(&ov8856->mutex); | 2061 | mutex_unlock(&ov8856->mutex); |
| 2069 | 2062 | ||
| 2070 | return ret; | 2063 | return ret; |
| @@ -2125,45 +2118,6 @@ static int ov8856_power_off(struct device *dev) · 54 unmodified lines | |||
| 2125 | return 0; | 2118 | return 0; |
| 2126 | } | 2119 | } |
| 2127 | 2120 | ||
| 2128 | static int __maybe_unused ov8856_suspend(struct device *dev) | ||
| 2129 | { | ||
| 2130 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2131 | struct ov8856 *ov8856 = to_ov8856(sd); | ||
| 2132 | |||
| 2133 | mutex_lock(&ov8856->mutex); | ||
| 2134 | if (ov8856->streaming) | ||
| 2135 | ov8856_stop_streaming(ov8856); | ||
| 2136 | |||
| 2137 | ov8856_power_off(dev); | ||
| 2138 | mutex_unlock(&ov8856->mutex); | ||
| 2139 | |||
| 2140 | return 0; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | static int __maybe_unused ov8856_resume(struct device *dev) | ||
| 2144 | { | ||
| 2145 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
| 2146 | struct ov8856 *ov8856 = to_ov8856(sd); | ||
| 2147 | int ret; | ||
| 2148 | |||
| 2149 | mutex_lock(&ov8856->mutex); | ||
| 2150 | |||
| 2151 | ov8856_power_on(dev); | ||
| 2152 | if (ov8856->streaming) { | ||
| 2153 | ret = ov8856_start_streaming(ov8856); | ||
| 2154 | if (ret) { | ||
| 2155 | ov8856->streaming = false; | ||
| 2156 | ov8856_stop_streaming(ov8856); | ||
| 2157 | mutex_unlock(&ov8856->mutex); | ||
| 2158 | return ret; | ||
| 2159 | } | ||
| 2160 | } | ||
| 2161 | |||
| 2162 | mutex_unlock(&ov8856->mutex); | ||
| 2163 | |||
| 2164 | return 0; | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | static int ov8856_set_format(struct v4l2_subdev *sd, | 2121 | static int ov8856_set_format(struct v4l2_subdev *sd, |
| 2168 | struct v4l2_subdev_state *sd_state, | 2122 | struct v4l2_subdev_state *sd_state, |
| 2169 | struct v4l2_subdev_format *fmt) | 2123 | struct v4l2_subdev_format *fmt) |
| @@ -2501,7 +2455,6 @@ probe_power_off: · 331 unmodified lines | |||
| 2501 | } | 2455 | } |
| 2502 | 2456 | ||
| 2503 | static const struct dev_pm_ops ov8856_pm_ops = { | 2457 | static const struct dev_pm_ops ov8856_pm_ops = { |
| 2504 | SET_SYSTEM_SLEEP_PM_OPS(ov8856_suspend, ov8856_resume) | ||
| 2505 | SET_RUNTIME_PM_OPS(ov8856_power_off, ov8856_power_on, NULL) | 2458 | SET_RUNTIME_PM_OPS(ov8856_power_off, ov8856_power_on, NULL) |
| 2506 | }; | 2459 | }; |
| 2507 | 2460 | ||
| @@ -165,7 +165,6 @@ struct ov9282_mode { · 164 unmodified lines | |||
| 165 | * @cur_mode: Pointer to current selected sensor mode | 165 | * @cur_mode: Pointer to current selected sensor mode |
| 166 | * @code: Mbus code currently selected | 166 | * @code: Mbus code currently selected |
| 167 | * @mutex: Mutex for serializing sensor controls | 167 | * @mutex: Mutex for serializing sensor controls |
| 168 | * @streaming: Flag indicating streaming state | ||
| 169 | */ | 168 | */ |
| 170 | struct ov9282 { | 169 | struct ov9282 { |
| 171 | struct device *dev; | 170 | struct device *dev; |
| @@ -188,7 +187,6 @@ struct ov9282 { · 16 unmodified lines | |||
| 188 | const struct ov9282_mode *cur_mode; | 187 | const struct ov9282_mode *cur_mode; |
| 189 | u32 code; | 188 | u32 code; |
| 190 | struct mutex mutex; | 189 | struct mutex mutex; |
| 191 | bool streaming; | ||
| 192 | }; | 190 | }; |
| 193 | 191 | ||
| 194 | static const s64 link_freq[] = { | 192 | static const s64 link_freq[] = { |
| @@ -1037,11 +1035,6 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable) · 842 unmodified lines | |||
| 1037 | 1035 | ||
| 1038 | mutex_lock(&ov9282->mutex); | 1036 | mutex_lock(&ov9282->mutex); |
| 1039 | 1037 | ||
| 1040 | if (ov9282->streaming == enable) { | ||
| 1041 | mutex_unlock(&ov9282->mutex); | ||
| 1042 | return 0; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | if (enable) { | 1038 | if (enable) { |
| 1046 | ret = pm_runtime_resume_and_get(ov9282->dev); | 1039 | ret = pm_runtime_resume_and_get(ov9282->dev); |
| 1047 | if (ret) | 1040 | if (ret) |
| @@ -1055,8 +1048,6 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | |||
| 1055 | pm_runtime_put(ov9282->dev); | 1048 | pm_runtime_put(ov9282->dev); |
| 1056 | } | 1049 | } |
| 1057 | 1050 | ||
| 1058 | ov9282->streaming = enable; | ||
| 1059 | |||
| 1060 | mutex_unlock(&ov9282->mutex); | 1051 | mutex_unlock(&ov9282->mutex); |
| 1061 | 1052 | ||
| 1062 | return 0; | 1053 | return 0; |
| @@ -337,9 +337,6 @@ struct ov9734 { · 336 unmodified lines | |||
| 337 | 337 | ||
| 338 | /* To serialize asynchronus callbacks */ | 338 | /* To serialize asynchronus callbacks */ |
| 339 | struct mutex mutex; | 339 | struct mutex mutex; |
| 340 | |||
| 341 | /* Streaming on/off */ | ||
| 342 | bool streaming; | ||
| 343 | }; | 340 | }; |
| 344 | 341 | ||
| 345 | static inline struct ov9734 *to_ov9734(struct v4l2_subdev *subdev) | 342 | static inline struct ov9734 *to_ov9734(struct v4l2_subdev *subdev) |
| @@ -660,10 +657,6 @@ static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) · 314 unmodified lines | |||
| 660 | int ret = 0; | 657 | int ret = 0; |
| 661 | 658 | ||
| 662 | mutex_lock(&ov9734->mutex); | 659 | mutex_lock(&ov9734->mutex); |
| 663 | if (ov9734->streaming == enable) { | ||
| 664 | mutex_unlock(&ov9734->mutex); | ||
| 665 | return 0; | ||
| 666 | } | ||
| 667 | 660 | ||
| 668 | if (enable) { | 661 | if (enable) { |
| 669 | ret = pm_runtime_resume_and_get(&client->dev); | 662 | ret = pm_runtime_resume_and_get(&client->dev); |
| @@ -683,46 +676,8 @@ static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) · 13 unmodified lines | |||
| 683 | pm_runtime_put(&client->dev); | 676 | pm_runtime_put(&client->dev); |
| 684 | } | 677 | } |
| 685 | 678 | ||
| 686 | ov9734->streaming = enable; | ||
| 687 | mutex_unlock(&ov9734->mutex); | ||
| 688 | |||
| 689 | return ret; | ||
| 690 | } | ||
| 691 | |||
| 692 | static int __maybe_unused ov9734_suspend(struct device *dev) | ||
| 693 | { | ||
| 694 | struct i2c_client *client = to_i2c_client(dev); | ||
| 695 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 696 | struct ov9734 *ov9734 = to_ov9734(sd); | ||
| 697 | |||
| 698 | mutex_lock(&ov9734->mutex); | ||
| 699 | if (ov9734->streaming) | ||
| 700 | ov9734_stop_streaming(ov9734); | ||
| 701 | |||
| 702 | mutex_unlock(&ov9734->mutex); | 679 | mutex_unlock(&ov9734->mutex); |
| 703 | 680 | ||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | static int __maybe_unused ov9734_resume(struct device *dev) | ||
| 708 | { | ||
| 709 | struct i2c_client *client = to_i2c_client(dev); | ||
| 710 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
| 711 | struct ov9734 *ov9734 = to_ov9734(sd); | ||
| 712 | int ret = 0; | ||
| 713 | |||
| 714 | mutex_lock(&ov9734->mutex); | ||
| 715 | if (!ov9734->streaming) | ||
| 716 | goto exit; | ||
| 717 | |||
| 718 | ret = ov9734_start_streaming(ov9734); | ||
| 719 | if (ret) { | ||
| 720 | ov9734->streaming = false; | ||
| 721 | ov9734_stop_streaming(ov9734); | ||
| 722 | } | ||
| 723 | |||
| 724 | exit: | ||
| 725 | mutex_unlock(&ov9734->mutex); | ||
| 726 | return ret; | 681 | return ret; |
| 727 | } | 682 | } |
| 728 | 683 | ||
| @@ -1011,10 +966,6 @@ probe_error_v4l2_ctrl_handler_free: · 282 unmodified lines | |||
| 1011 | return ret; | 966 | return ret; |
| 1012 | } | 967 | } |
| 1013 | 968 | ||
| 1014 | static const struct dev_pm_ops ov9734_pm_ops = { | ||
| 1015 | SET_SYSTEM_SLEEP_PM_OPS(ov9734_suspend, ov9734_resume) | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | static const struct acpi_device_id ov9734_acpi_ids[] = { | 969 | static const struct acpi_device_id ov9734_acpi_ids[] = { |
| 1019 | { "OVTI9734", }, | 970 | { "OVTI9734", }, |
| 1020 | {} | 971 | {} |
| @@ -1025,7 +976,6 @@ MODULE_DEVICE_TABLE(acpi, ov9734_acpi_ids); · 4 unmodified lines | |||
| 1025 | static struct i2c_driver ov9734_i2c_driver = { | 976 | static struct i2c_driver ov9734_i2c_driver = { |
| 1026 | .driver = { | 977 | .driver = { |
| 1027 | .name = "ov9734", | 978 | .name = "ov9734", |
| 1028 | .pm = &ov9734_pm_ops, | ||
| 1029 | .acpi_match_table = ov9734_acpi_ids, | 979 | .acpi_match_table = ov9734_acpi_ids, |
| 1030 | }, | 980 | }, |
| 1031 | .probe = ov9734_probe, | 981 | .probe = ov9734_probe, |
| @@ -625,8 +625,7 @@ error_free_ctrls: · 624 unmodified lines | |||
| 625 | v4l2_ctrl_handler_free(&dev->ctrls); | 625 | v4l2_ctrl_handler_free(&dev->ctrls); |
| 626 | error: | 626 | error: |
| 627 | media_entity_cleanup(&dev->sd.entity); | 627 | media_entity_cleanup(&dev->sd.entity); |
| 628 | if (dev->sensor) | 628 | i2c_unregister_device(dev->sensor); |
| 629 | i2c_unregister_device(dev->sensor); | ||
| 630 | 629 | ||
| 631 | dev_err(&client->dev, "probe failed\n"); | 630 | dev_err(&client->dev, "probe failed\n"); |
| 632 | 631 | ||
| @@ -1170,14 +1170,9 @@ static int vgxy61_stream_enable(struct vgxy61_dev *sensor) · 1169 unmodified lines | |||
| 1170 | if (ret) | 1170 | if (ret) |
| 1171 | return ret; | 1171 | return ret; |
| 1172 | 1172 | ||
| 1173 | ret = pm_runtime_get_sync(&client->dev); | 1173 | ret = pm_runtime_resume_and_get(&client->dev); |
| 1174 | if (ret < 0) { | 1174 | if (ret) |
| 1175 | pm_runtime_put_autosuspend(&client->dev); | ||
| 1176 | return ret; | 1175 | return ret; |
| 1177 | } | ||
| 1178 | |||
| 1179 | /* pm_runtime_get_sync() can return 1 as a valid return code */ | ||
| 1180 | ret = 0; | ||
| 1181 | 1176 | ||
| 1182 | vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL, | 1177 | vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL, |
| 1183 | get_bpp_by_code(sensor->fmt.code), &ret); | 1178 | get_bpp_by_code(sensor->fmt.code), &ret); |
| @@ -784,8 +784,12 @@ static int tc358746_set_fmt(struct v4l2_subdev *sd, · 783 unmodified lines | |||
| 784 | sink_fmt = v4l2_subdev_get_pad_format(sd, sd_state, TC358746_SINK); | 784 | sink_fmt = v4l2_subdev_get_pad_format(sd, sd_state, TC358746_SINK); |
| 785 | 785 | ||
| 786 | fmt = tc358746_get_format_by_code(format->pad, format->format.code); | 786 | fmt = tc358746_get_format_by_code(format->pad, format->format.code); |
| 787 | if (IS_ERR(fmt)) | 787 | if (IS_ERR(fmt)) { |
| 788 | fmt = tc358746_get_format_by_code(format->pad, tc358746_def_fmt.code); | 788 | fmt = tc358746_get_format_by_code(format->pad, tc358746_def_fmt.code); |
| 789 | // Can't happen, but just in case... | ||
| 790 | if (WARN_ON(IS_ERR(fmt))) | ||
| 791 | return -EINVAL; | ||
| 792 | } | ||
| 789 | 793 | ||
| 790 | format->format.code = fmt->code; | 794 | format->format.code = fmt->code; |
| 791 | format->format.field = V4L2_FIELD_NONE; | 795 | format->format.field = V4L2_FIELD_NONE; |
| @@ -16,23 +16,24 @@ · 15 unmodified lines | |||
| 16 | * Prabhakar Lad <prabhakar.lad@ti.com> | 16 | * Prabhakar Lad <prabhakar.lad@ti.com> |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/i2c.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 22 | #include <linux/videodev2.h> | 20 | #include <linux/i2c.h> |
| 21 | #include <linux/mod_devicetable.h> | ||
| 23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 24 | #include <linux/v4l2-mediabus.h> | ||
| 25 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 26 | #include <linux/of_graph.h> | 24 | #include <linux/of_graph.h> |
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/v4l2-mediabus.h> | ||
| 27 | #include <linux/videodev2.h> | ||
| 27 | 28 | ||
| 29 | #include <media/i2c/tvp514x.h> | ||
| 30 | #include <media/media-entity.h> | ||
| 28 | #include <media/v4l2-async.h> | 31 | #include <media/v4l2-async.h> |
| 29 | #include <media/v4l2-device.h> | ||
| 30 | #include <media/v4l2-common.h> | 32 | #include <media/v4l2-common.h> |
| 31 | #include <media/v4l2-mediabus.h> | ||
| 32 | #include <media/v4l2-fwnode.h> | ||
| 33 | #include <media/v4l2-ctrls.h> | 33 | #include <media/v4l2-ctrls.h> |
| 34 | #include <media/i2c/tvp514x.h> | 34 | #include <media/v4l2-device.h> |
| 35 | #include <media/media-entity.h> | 35 | #include <media/v4l2-fwnode.h> |
| 36 | #include <media/v4l2-mediabus.h> | ||
| 36 | 37 | ||
| 37 | #include "tvp514x_regs.h" | 38 | #include "tvp514x_regs.h" |
| 38 | 39 | ||
| @@ -118,7 +119,7 @@ struct tvp514x_decoder { · 79 unmodified lines | |||
| 118 | struct media_pad pad; | 119 | struct media_pad pad; |
| 119 | struct v4l2_mbus_framefmt format; | 120 | struct v4l2_mbus_framefmt format; |
| 120 | 121 | ||
| 121 | struct tvp514x_reg *int_seq; | 122 | const struct tvp514x_reg *int_seq; |
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | /* TVP514x default register values */ | 125 | /* TVP514x default register values */ |
| @@ -1024,7 +1025,6 @@ done: · 899 unmodified lines | |||
| 1024 | static int | 1025 | static int |
| 1025 | tvp514x_probe(struct i2c_client *client) | 1026 | tvp514x_probe(struct i2c_client *client) |
| 1026 | { | 1027 | { |
| 1027 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | ||
| 1028 | struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); | 1028 | struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); |
| 1029 | struct tvp514x_decoder *decoder; | 1029 | struct tvp514x_decoder *decoder; |
| 1030 | struct v4l2_subdev *sd; | 1030 | struct v4l2_subdev *sd; |
| @@ -1049,7 +1049,7 @@ tvp514x_probe(struct i2c_client *client) · 18 unmodified lines | |||
| 1049 | memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, | 1049 | memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, |
| 1050 | sizeof(tvp514x_reg_list_default)); | 1050 | sizeof(tvp514x_reg_list_default)); |
| 1051 | 1051 | ||
| 1052 | decoder->int_seq = (struct tvp514x_reg *)id->driver_data; | 1052 | decoder->int_seq = i2c_get_match_data(client); |
| 1053 | 1053 | ||
| 1054 | /* Copy board specific information here */ | 1054 | /* Copy board specific information here */ |
| 1055 | decoder->pdata = pdata; | 1055 | decoder->pdata = pdata; |
| @@ -1183,29 +1183,26 @@ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { · 127 unmodified lines | |||
| 1183 | * driver_data - Driver data | 1183 | * driver_data - Driver data |
| 1184 | */ | 1184 | */ |
| 1185 | static const struct i2c_device_id tvp514x_id[] = { | 1185 | static const struct i2c_device_id tvp514x_id[] = { |
| 1186 | {"tvp5146", (unsigned long)tvp5146_init_reg_seq}, | 1186 | {"tvp5146", (kernel_ulong_t)tvp5146_init_reg_seq }, |
| 1187 | {"tvp5146m2", (unsigned long)tvp514xm_init_reg_seq}, | 1187 | {"tvp5146m2", (kernel_ulong_t)tvp514xm_init_reg_seq }, |
| 1188 | {"tvp5147", (unsigned long)tvp5147_init_reg_seq}, | 1188 | {"tvp5147", (kernel_ulong_t)tvp5147_init_reg_seq }, |
| 1189 | {"tvp5147m1", (unsigned long)tvp514xm_init_reg_seq}, | 1189 | {"tvp5147m1", (kernel_ulong_t)tvp514xm_init_reg_seq }, |
| 1190 | {}, | 1190 | { /* sentinel */ } |
| 1191 | }; | 1191 | }; |
| 1192 | |||
| 1193 | MODULE_DEVICE_TABLE(i2c, tvp514x_id); | 1192 | MODULE_DEVICE_TABLE(i2c, tvp514x_id); |
| 1194 | 1193 | ||
| 1195 | #if IS_ENABLED(CONFIG_OF) | ||
| 1196 | static const struct of_device_id tvp514x_of_match[] = { | 1194 | static const struct of_device_id tvp514x_of_match[] = { |
| 1197 | { .compatible = "ti,tvp5146", }, | 1195 | { .compatible = "ti,tvp5146", .data = tvp5146_init_reg_seq }, |
| 1198 | { .compatible = "ti,tvp5146m2", }, | 1196 | { .compatible = "ti,tvp5146m2", .data = tvp514xm_init_reg_seq }, |
| 1199 | { .compatible = "ti,tvp5147", }, | 1197 | { .compatible = "ti,tvp5147", .data = tvp5147_init_reg_seq }, |
| 1200 | { .compatible = "ti,tvp5147m1", }, | 1198 | { .compatible = "ti,tvp5147m1", .data = tvp514xm_init_reg_seq }, |
| 1201 | { /* sentinel */ }, | 1199 | { /* sentinel */ } |
| 1202 | }; | 1200 | }; |
| 1203 | MODULE_DEVICE_TABLE(of, tvp514x_of_match); | 1201 | MODULE_DEVICE_TABLE(of, tvp514x_of_match); |
| 1204 | #endif | ||
| 1205 | 1202 | ||
| 1206 | static struct i2c_driver tvp514x_driver = { | 1203 | static struct i2c_driver tvp514x_driver = { |
| 1207 | .driver = { | 1204 | .driver = { |
| 1208 | .of_match_table = of_match_ptr(tvp514x_of_match), | 1205 | .of_match_table = tvp514x_of_match, |
| 1209 | .name = TVP514X_MODULE_NAME, | 1206 | .name = TVP514X_MODULE_NAME, |
| 1210 | }, | 1207 | }, |
| 1211 | .probe = tvp514x_probe, | 1208 | .probe = tvp514x_probe, |
| @@ -759,7 +759,6 @@ static void video_i2c_release(struct video_device *vdev) · 758 unmodified lines | |||
| 759 | 759 | ||
| 760 | static int video_i2c_probe(struct i2c_client *client) | 760 | static int video_i2c_probe(struct i2c_client *client) |
| 761 | { | 761 | { |
| 762 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | ||
| 763 | struct video_i2c_data *data; | 762 | struct video_i2c_data *data; |
| 764 | struct v4l2_device *v4l2_dev; | 763 | struct v4l2_device *v4l2_dev; |
| 765 | struct vb2_queue *queue; | 764 | struct vb2_queue *queue; |
| @@ -769,11 +768,8 @@ static int video_i2c_probe(struct i2c_client *client) · 3 unmodified lines | |||
| 769 | if (!data) | 768 | if (!data) |
| 770 | return -ENOMEM; | 769 | return -ENOMEM; |
| 771 | 770 | ||
| 772 | if (dev_fwnode(&client->dev)) | 771 | data->chip = i2c_get_match_data(client); |
| 773 | data->chip = device_get_match_data(&client->dev); | 772 | if (!data->chip) |
| 774 | else if (id) | ||
| 775 | data->chip = &video_i2c_chip[id->driver_data]; | ||
| 776 | else | ||
| 777 | goto error_free_device; | 773 | goto error_free_device; |
| 778 | 774 | ||
| 779 | data->regmap = regmap_init_i2c(client, data->chip->regmap_config); | 775 | data->regmap = regmap_init_i2c(client, data->chip->regmap_config); |
| @@ -940,8 +936,8 @@ static const struct dev_pm_ops video_i2c_pm_ops = { · 160 unmodified lines | |||
| 940 | }; | 936 | }; |
| 941 | 937 | ||
| 942 | static const struct i2c_device_id video_i2c_id_table[] = { | 938 | static const struct i2c_device_id video_i2c_id_table[] = { |
| 943 | { "amg88xx", AMG88XX }, | 939 | { "amg88xx", (kernel_ulong_t)&video_i2c_chip[AMG88XX] }, |
| 944 | { "mlx90640", MLX90640 }, | 940 | { "mlx90640", (kernel_ulong_t)&video_i2c_chip[MLX90640] }, |
| 945 | {} | 941 | {} |
| 946 | }; | 942 | }; |
| 947 | MODULE_DEVICE_TABLE(i2c, video_i2c_id_table); | 943 | MODULE_DEVICE_TABLE(i2c, video_i2c_id_table); |
| @@ -197,6 +197,7 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, · 196 unmodified lines | |||
| 197 | struct media_device *mdev = entity->graph_obj.mdev; | 197 | struct media_device *mdev = entity->graph_obj.mdev; |
| 198 | struct media_pad *iter; | 198 | struct media_pad *iter; |
| 199 | unsigned int i = 0; | 199 | unsigned int i = 0; |
| 200 | int ret = 0; | ||
| 200 | 201 | ||
| 201 | if (num_pads >= MEDIA_ENTITY_MAX_PADS) | 202 | if (num_pads >= MEDIA_ENTITY_MAX_PADS) |
| 202 | return -E2BIG; | 203 | return -E2BIG; |
| @@ -210,15 +211,27 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, · 7 unmodified lines | |||
| 210 | media_entity_for_each_pad(entity, iter) { | 211 | media_entity_for_each_pad(entity, iter) { |
| 211 | iter->entity = entity; | 212 | iter->entity = entity; |
| 212 | iter->index = i++; | 213 | iter->index = i++; |
| 214 | |||
| 215 | if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK | | ||
| 216 | MEDIA_PAD_FL_SOURCE)) != 1) { | ||
| 217 | ret = -EINVAL; | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | |||
| 213 | if (mdev) | 221 | if (mdev) |
| 214 | media_gobj_create(mdev, MEDIA_GRAPH_PAD, | 222 | media_gobj_create(mdev, MEDIA_GRAPH_PAD, |
| 215 | &iter->graph_obj); | 223 | &iter->graph_obj); |
| 216 | } | 224 | } |
| 217 | 225 | ||
| 226 | if (ret && mdev) { | ||
| 227 | media_entity_for_each_pad(entity, iter) | ||
| 228 | media_gobj_destroy(&iter->graph_obj); | ||
| 229 | } | ||
| 230 | |||
| 218 | if (mdev) | 231 | if (mdev) |
| 219 | mutex_unlock(&mdev->graph_mutex); | 232 | mutex_unlock(&mdev->graph_mutex); |
| 220 | 233 | ||
| 221 | return 0; | 234 | return ret; |
| 222 | } | 235 | } |
| 223 | EXPORT_SYMBOL_GPL(media_entity_pads_init); | 236 | EXPORT_SYMBOL_GPL(media_entity_pads_init); |
| 224 | 237 | ||
| @@ -13,6 +13,7 @@ if MEDIA_PCI_SUPPORT · 12 unmodified lines | |||
| 13 | if MEDIA_CAMERA_SUPPORT | 13 | if MEDIA_CAMERA_SUPPORT |
| 14 | comment "Media capture support" | 14 | comment "Media capture support" |
| 15 | 15 | ||
| 16 | source "drivers/media/pci/mgb4/Kconfig" | ||
| 16 | source "drivers/media/pci/solo6x10/Kconfig" | 17 | source "drivers/media/pci/solo6x10/Kconfig" |
| 17 | source "drivers/media/pci/sta2x11/Kconfig" | 18 | source "drivers/media/pci/sta2x11/Kconfig" |
| 18 | source "drivers/media/pci/tw5864/Kconfig" | 19 | source "drivers/media/pci/tw5864/Kconfig" |
| @@ -32,6 +32,7 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ · 31 unmodified lines | |||
| 32 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 32 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
| 33 | obj-$(CONFIG_VIDEO_DT3155) += dt3155/ | 33 | obj-$(CONFIG_VIDEO_DT3155) += dt3155/ |
| 34 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | 34 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ |
| 35 | obj-$(CONFIG_VIDEO_MGB4) += mgb4/ | ||
| 35 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 36 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ |
| 36 | obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ | 37 | obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ |
| 37 | obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ | 38 | obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ |
| @@ -126,6 +126,7 @@ MODULE_PARM_DESC(audiodev, "specify audio device:\n" · 125 unmodified lines | |||
| 126 | "\t\t 3 = tvaudio"); | 126 | "\t\t 3 = tvaudio"); |
| 127 | MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); | 127 | MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); |
| 128 | 128 | ||
| 129 | MODULE_FIRMWARE("hcwamc.rbf"); | ||
| 129 | 130 | ||
| 130 | /* I2C addresses list */ | 131 | /* I2C addresses list */ |
| 131 | #define I2C_ADDR_TDA7432 0x8a | 132 | #define I2C_ADDR_TDA7432 0x8a |
| @@ -3474,6 +3474,7 @@ static void bttv_remove(struct pci_dev *pci_dev) · 3473 unmodified lines | |||
| 3474 | 3474 | ||
| 3475 | /* free resources */ | 3475 | /* free resources */ |
| 3476 | free_irq(btv->c.pci->irq,btv); | 3476 | free_irq(btv->c.pci->irq,btv); |
| 3477 | del_timer_sync(&btv->timeout); | ||
| 3477 | iounmap(btv->bt848_mmio); | 3478 | iounmap(btv->bt848_mmio); |
| 3478 | release_mem_region(pci_resource_start(btv->c.pci,0), | 3479 | release_mem_region(pci_resource_start(btv->c.pci,0), |
| 3479 | pci_resource_len(btv->c.pci,0)); | 3480 | pci_resource_len(btv->c.pci,0)); |
| @@ -190,11 +190,15 @@ static int cx24108_tuner_set_params(struct dvb_frontend *fe) · 189 unmodified lines | |||
| 190 | u32 freq = c->frequency; | 190 | u32 freq = c->frequency; |
| 191 | int i, a, n, pump; | 191 | int i, a, n, pump; |
| 192 | u32 band, pll; | 192 | u32 band, pll; |
| 193 | u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000, | 193 | static const u32 osci[] = { |
| 194 | 1576000,1718000,1856000,2036000,2150000}; | 194 | 950000, 1019000, 1075000, 1178000, 1296000, 1432000, |
| 195 | u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000, | 195 | 1576000, 1718000, 1856000, 2036000, 2150000 |
| 196 | 0x00102000,0x00104000,0x00108000,0x00110000, | 196 | }; |
| 197 | 0x00120000,0x00140000}; | 197 | static const u32 bandsel[] = { |
| 198 | 0, 0x00020000, 0x00040000, 0x00100800, 0x00101000, | ||
| 199 | 0x00102000, 0x00104000, 0x00108000, 0x00110000, | ||
| 200 | 0x00120000, 0x00140000 | ||
| 201 | }; | ||
| 198 | 202 | ||
| 199 | #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ | 203 | #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ |
| 200 | dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq); | 204 | dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq); |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | * All rights reserved. | 8 | * All rights reserved. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/bitfield.h> | ||
| 11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 12 | #include <media/i2c/adv7604.h> | 13 | #include <media/i2c/adv7604.h> |
| 13 | #include <media/i2c/adv7842.h> | 14 | #include <media/i2c/adv7842.h> |
| @@ -210,17 +211,17 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) · 196 unmodified lines | |||
| 210 | pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat); | 211 | pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat); |
| 211 | cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n", | 212 | cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n", |
| 212 | capa, get_link_speed(capa), | 213 | capa, get_link_speed(capa), |
| 213 | (capa & PCI_EXP_LNKCAP_MLW) >> 4); | 214 | FIELD_GET(PCI_EXP_LNKCAP_MLW, capa)); |
| 214 | cobalt_info("PCIe link control 0x%04x\n", ctrl); | 215 | cobalt_info("PCIe link control 0x%04x\n", ctrl); |
| 215 | cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n", | 216 | cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n", |
| 216 | stat, get_link_speed(stat), | 217 | stat, get_link_speed(stat), |
| 217 | (stat & PCI_EXP_LNKSTA_NLW) >> 4); | 218 | FIELD_GET(PCI_EXP_LNKSTA_NLW, stat)); |
| 218 | 219 | ||
| 219 | /* Bus */ | 220 | /* Bus */ |
| 220 | pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa); | 221 | pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa); |
| 221 | cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n", | 222 | cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n", |
| 222 | capa, get_link_speed(capa), | 223 | capa, get_link_speed(capa), |
| 223 | (capa & PCI_EXP_LNKCAP_MLW) >> 4); | 224 | FIELD_GET(PCI_EXP_LNKCAP_MLW, capa)); |
| 224 | 225 | ||
| 225 | /* Slot */ | 226 | /* Slot */ |
| 226 | pcie_capability_read_dword(pci_dev, PCI_EXP_SLTCAP, &capa); | 227 | pcie_capability_read_dword(pci_dev, PCI_EXP_SLTCAP, &capa); |
| @@ -239,7 +240,7 @@ static unsigned pcie_link_get_lanes(struct cobalt *cobalt) · 12 unmodified lines | |||
| 239 | if (!pci_is_pcie(pci_dev)) | 240 | if (!pci_is_pcie(pci_dev)) |
| 240 | return 0; | 241 | return 0; |
| 241 | pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &link); | 242 | pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &link); |
| 242 | return (link & PCI_EXP_LNKSTA_NLW) >> 4; | 243 | return FIELD_GET(PCI_EXP_LNKSTA_NLW, link); |
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt) | 246 | static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt) |
| @@ -250,7 +251,7 @@ static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt) · 4 unmodified lines | |||
| 250 | if (!pci_is_pcie(pci_dev)) | 251 | if (!pci_is_pcie(pci_dev)) |
| 251 | return 0; | 252 | return 0; |
| 252 | pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &link); | 253 | pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &link); |
| 253 | return (link & PCI_EXP_LNKCAP_MLW) >> 4; | 254 | return FIELD_GET(PCI_EXP_LNKCAP_MLW, link); |
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev) | 257 | static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev) |
| @@ -107,11 +107,9 @@ static void chain_all_buffers(struct cobalt_stream *s) · 106 unmodified lines | |||
| 107 | { | 107 | { |
| 108 | struct sg_dma_desc_info *desc[NR_BUFS]; | 108 | struct sg_dma_desc_info *desc[NR_BUFS]; |
| 109 | struct cobalt_buffer *cb; | 109 | struct cobalt_buffer *cb; |
| 110 | struct list_head *p; | ||
| 111 | int i = 0; | 110 | int i = 0; |
| 112 | 111 | ||
| 113 | list_for_each(p, &s->bufs) { | 112 | list_for_each_entry(cb, &s->bufs, list) { |
| 114 | cb = list_entry(p, struct cobalt_buffer, list); | ||
| 115 | desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index]; | 113 | desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index]; |
| 116 | if (i > 0) | 114 | if (i > 0) |
| 117 | descriptor_list_chain(desc[i-1], desc[i]); | 115 | descriptor_list_chain(desc[i-1], desc[i]); |
| @@ -348,7 +346,6 @@ static void cobalt_dma_stop_streaming(struct cobalt_stream *s) · 230 unmodified lines | |||
| 348 | struct cobalt *cobalt = s->cobalt; | 346 | struct cobalt *cobalt = s->cobalt; |
| 349 | struct sg_dma_desc_info *desc; | 347 | struct sg_dma_desc_info *desc; |
| 350 | struct cobalt_buffer *cb; | 348 | struct cobalt_buffer *cb; |
| 351 | struct list_head *p; | ||
| 352 | unsigned long flags; | 349 | unsigned long flags; |
| 353 | int timeout_msec = 100; | 350 | int timeout_msec = 100; |
| 354 | int rx = s->video_channel; | 351 | int rx = s->video_channel; |
| @@ -367,8 +364,7 @@ static void cobalt_dma_stop_streaming(struct cobalt_stream *s) · 12 unmodified lines | |||
| 367 | 364 | ||
| 368 | /* Try to stop the DMA engine gracefully */ | 365 | /* Try to stop the DMA engine gracefully */ |
| 369 | spin_lock_irqsave(&s->irqlock, flags); | 366 | spin_lock_irqsave(&s->irqlock, flags); |
| 370 | list_for_each(p, &s->bufs) { | 367 | list_for_each_entry(cb, &s->bufs, list) { |
| 371 | cb = list_entry(p, struct cobalt_buffer, list); | ||
| 372 | desc = &s->dma_desc_info[cb->vb.vb2_buf.index]; | 368 | desc = &s->dma_desc_info[cb->vb.vb2_buf.index]; |
| 373 | /* Stop DMA after this descriptor chain */ | 369 | /* Stop DMA after this descriptor chain */ |
| 374 | descriptor_list_end_of_chain(desc); | 370 | descriptor_list_end_of_chain(desc); |
| @@ -631,7 +631,7 @@ struct cx18 { · 630 unmodified lines | |||
| 631 | u32 hw2_irq_mask; | 631 | u32 hw2_irq_mask; |
| 632 | 632 | ||
| 633 | struct workqueue_struct *in_work_queue; | 633 | struct workqueue_struct *in_work_queue; |
| 634 | char in_workq_name[11]; /* "cx18-NN-in" */ | 634 | char in_workq_name[39]; /* "cx18-NN-in" */ |
| 635 | struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; | 635 | struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; |
| 636 | char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ | 636 | char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ |
| 637 | 637 | ||
| @@ -831,7 +831,7 @@ int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...) · 830 unmodified lines | |||
| 831 | int i; | 831 | int i; |
| 832 | 832 | ||
| 833 | if (cx == NULL) { | 833 | if (cx == NULL) { |
| 834 | CX18_ERR("cx == NULL (cmd=%x)\n", cmd); | 834 | pr_err("cx == NULL (cmd=%x)\n", cmd); |
| 835 | return 0; | 835 | return 0; |
| 836 | } | 836 | } |
| 837 | if (args > MAX_MB_ARGUMENTS) { | 837 | if (args > MAX_MB_ARGUMENTS) { |
| @@ -10,6 +10,12 @@ config INTEL_VSC · 9 unmodified lines | |||
| 10 | help | 10 | help |
| 11 | This adds support for Intel Visual Sensing Controller (IVSC). | 11 | This adds support for Intel Visual Sensing Controller (IVSC). |
| 12 | 12 | ||
| 13 | Enables the IVSC firmware services required for controlling | 13 | The IVSC support is split into two devices, ACE (Algorithm |
| 14 | camera sensor ownership and CSI-2 link through Image Processing | 14 | Context Engine) and CSI (Camera Serial Interface), each of which |
| 15 | Unit(IPU) driver of Intel. | 15 | have their own drivers. The ACE is used to select the ownership |
| 16 | of the sensor between the IVSC and the host CPU while the CSI is | ||
| 17 | used to both select the routing destination for the data the | ||
| 18 | sensor transmits over the CSI-2 bus between the IVSC and the | ||
| 19 | host CPU and to configure the CSI-2 bus itself. | ||
| 20 | |||
| 21 | The modules will be called ivsc-ace and ivsc-csi. | ||
| @@ -30,8 +30,6 @@ · 29 unmodified lines | |||
| 30 | #include <linux/uuid.h> | 30 | #include <linux/uuid.h> |
| 31 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
| 32 | 32 | ||
| 33 | #define MEI_ACE_DRIVER_NAME "ivsc_ace" | ||
| 34 | |||
| 35 | /* indicating driver message */ | 33 | /* indicating driver message */ |
| 36 | #define ACE_DRV_MSG 1 | 34 | #define ACE_DRV_MSG 1 |
| 37 | /* indicating set command */ | 35 | /* indicating set command */ |
| @@ -408,6 +406,9 @@ static int mei_ace_setup_dev_link(struct mei_ace *ace) · 370 unmodified lines | |||
| 408 | if (!csi_dev) { | 406 | if (!csi_dev) { |
| 409 | ret = -EPROBE_DEFER; | 407 | ret = -EPROBE_DEFER; |
| 410 | goto err; | 408 | goto err; |
| 409 | } else if (!dev_fwnode(csi_dev)) { | ||
| 410 | ret = -EPROBE_DEFER; | ||
| 411 | goto err_put; | ||
| 411 | } | 412 | } |
| 412 | 413 | ||
| 413 | /* setup link between mei_ace and mei_csi */ | 414 | /* setup link between mei_ace and mei_csi */ |
| @@ -554,14 +555,14 @@ static const struct dev_pm_ops mei_ace_pm_ops = { · 140 unmodified lines | |||
| 554 | 0x9B, 0x78, 0x03, 0x61, 0x63, 0x5E, 0x24, 0x47) | 555 | 0x9B, 0x78, 0x03, 0x61, 0x63, 0x5E, 0x24, 0x47) |
| 555 | 556 | ||
| 556 | static const struct mei_cl_device_id mei_ace_tbl[] = { | 557 | static const struct mei_cl_device_id mei_ace_tbl[] = { |
| 557 | { MEI_ACE_DRIVER_NAME, MEI_ACE_UUID, MEI_CL_VERSION_ANY }, | 558 | { .uuid = MEI_ACE_UUID, .version = MEI_CL_VERSION_ANY }, |
| 558 | { /* sentinel */ } | 559 | { /* sentinel */ } |
| 559 | }; | 560 | }; |
| 560 | MODULE_DEVICE_TABLE(mei, mei_ace_tbl); | 561 | MODULE_DEVICE_TABLE(mei, mei_ace_tbl); |
| 561 | 562 | ||
| 562 | static struct mei_cl_driver mei_ace_driver = { | 563 | static struct mei_cl_driver mei_ace_driver = { |
| 563 | .id_table = mei_ace_tbl, | 564 | .id_table = mei_ace_tbl, |
| 564 | .name = MEI_ACE_DRIVER_NAME, | 565 | .name = KBUILD_MODNAME, |
| 565 | 566 | ||
| 566 | .probe = mei_ace_probe, | 567 | .probe = mei_ace_probe, |
| 567 | .remove = mei_ace_remove, | 568 | .remove = mei_ace_remove, |
| @@ -30,7 +30,6 @@ · 29 unmodified lines | |||
| 30 | #include <media/v4l2-fwnode.h> | 30 | #include <media/v4l2-fwnode.h> |
| 31 | #include <media/v4l2-subdev.h> | 31 | #include <media/v4l2-subdev.h> |
| 32 | 32 | ||
| 33 | #define MEI_CSI_DRIVER_NAME "ivsc_csi" | ||
| 34 | #define MEI_CSI_ENTITY_NAME "Intel IVSC CSI" | 33 | #define MEI_CSI_ENTITY_NAME "Intel IVSC CSI" |
| 35 | 34 | ||
| 36 | #define MEI_CSI_LINK_FREQ_400MHZ 400000000ULL | 35 | #define MEI_CSI_LINK_FREQ_400MHZ 400000000ULL |
| @@ -804,14 +803,14 @@ static void mei_csi_remove(struct mei_cl_device *cldev) · 767 unmodified lines | |||
| 804 | 0xAF, 0x93, 0x7b, 0x44, 0x53, 0xAC, 0x29, 0xDA) | 803 | 0xAF, 0x93, 0x7b, 0x44, 0x53, 0xAC, 0x29, 0xDA) |
| 805 | 804 | ||
| 806 | static const struct mei_cl_device_id mei_csi_tbl[] = { | 805 | static const struct mei_cl_device_id mei_csi_tbl[] = { |
| 807 | { MEI_CSI_DRIVER_NAME, MEI_CSI_UUID, MEI_CL_VERSION_ANY }, | 806 | { .uuid = MEI_CSI_UUID, .version = MEI_CL_VERSION_ANY }, |
| 808 | { /* sentinel */ } | 807 | { /* sentinel */ } |
| 809 | }; | 808 | }; |
| 810 | MODULE_DEVICE_TABLE(mei, mei_csi_tbl); | 809 | MODULE_DEVICE_TABLE(mei, mei_csi_tbl); |
| 811 | 810 | ||
| 812 | static struct mei_cl_driver mei_csi_driver = { | 811 | static struct mei_cl_driver mei_csi_driver = { |
| 813 | .id_table = mei_csi_tbl, | 812 | .id_table = mei_csi_tbl, |
| 814 | .name = MEI_CSI_DRIVER_NAME, | 813 | .name = KBUILD_MODNAME, |
| 815 | 814 | ||
| 816 | .probe = mei_csi_probe, | 815 | .probe = mei_csi_probe, |
| 817 | .remove = mei_csi_remove, | 816 | .remove = mei_csi_remove, |
| @@ -0,0 +1,17 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | config VIDEO_MGB4 | ||
| 3 | tristate "Digiteq Automotive MGB4 support" | ||
| 4 | depends on VIDEO_DEV && PCI && I2C && DMADEVICES && SPI && MTD && IIO | ||
| 5 | select VIDEOBUF2_DMA_SG | ||
| 6 | select IIO_BUFFER | ||
| 7 | select IIO_TRIGGERED_BUFFER | ||
| 8 | select I2C_XILINX | ||
| 9 | select SPI_XILINX | ||
| 10 | select MTD_SPI_NOR | ||
| 11 | select XILINX_XDMA | ||
| 12 | help | ||
| 13 | This is a video4linux driver for Digiteq Automotive MGB4 grabber | ||
| 14 | cards. | ||
| 15 | |||
| 16 | To compile this driver as a module, choose M here: the | ||
| 17 | module will be called mgb4. | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | mgb4-objs := mgb4_regs.o mgb4_core.o mgb4_vin.o mgb4_vout.o \ | ||
| 3 | mgb4_sysfs_pci.o mgb4_sysfs_in.o mgb4_sysfs_out.o \ | ||
| 4 | mgb4_i2c.o mgb4_cmt.o mgb4_trigger.o mgb4_dma.o | ||
| 5 | |||
| 6 | obj-$(CONFIG_VIDEO_MGB4) += mgb4.o | ||
| @@ -0,0 +1,244 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * The CMT module configures the FPGA Clock Management Tile (CMT) registers. For | ||
| 7 | * different video signal frequencies (FPGA input signal frequencies), the FPGA | ||
| 8 | * CMT registers need to be adjusted for the FPGA to work properly. The values | ||
| 9 | * are precomputed based on formulas given by Xilinx in their FPGA documentation | ||
| 10 | * (which are in turn full of some magic values/tables...). | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include "mgb4_core.h" | ||
| 16 | #include "mgb4_cmt.h" | ||
| 17 | |||
| 18 | static const u16 cmt_vals_out[][15] = { | ||
| 19 | {0x1208, 0x0000, 0x171C, 0x0000, 0x1E38, 0x0000, 0x11C7, 0x0000, 0x1041, 0x01BC, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 20 | {0x11C7, 0x0000, 0x1619, 0x0080, 0x1C71, 0x0000, 0x130D, 0x0080, 0x0041, 0x0090, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x9000, }, | ||
| 21 | {0x11C7, 0x0000, 0x1619, 0x0080, 0x1C71, 0x0000, 0x165A, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 22 | {0x11C7, 0x0000, 0x1619, 0x0080, 0x1C71, 0x0000, 0x1187, 0x0080, 0x1041, 0x01EE, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 23 | {0x1186, 0x0000, 0x1555, 0x0000, 0x1AAA, 0x0000, 0x1451, 0x0000, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 24 | {0x11C7, 0x0000, 0x1619, 0x0080, 0x1C71, 0x0000, 0x134E, 0x0080, 0x0041, 0x005E, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 25 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x1619, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 26 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x179E, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 27 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x179F, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 28 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x17DF, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x8800, }, | ||
| 29 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x128B, 0x0080, 0x0041, 0x00DB, 0x7C01, 0x7DE9, 0xFFFF, 0x9000, 0x0100, }, | ||
| 30 | {0x1186, 0x0000, 0x1555, 0x0000, 0x1AAA, 0x0000, 0x1820, 0x0000, 0x0083, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 31 | {0x1186, 0x0000, 0x1555, 0x0000, 0x1AAA, 0x0000, 0x1187, 0x0080, 0x1041, 0x01EE, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 32 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x169B, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 33 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x171C, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 34 | {0x1186, 0x0000, 0x1555, 0x0000, 0x1AAA, 0x0000, 0x1515, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 35 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x1493, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 36 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x15D8, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 37 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x124A, 0x0080, 0x0041, 0x010D, 0x7C01, 0x7DE9, 0xFFFF, 0x9000, 0x0100, }, | ||
| 38 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x175D, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 39 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x1619, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 40 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x17DF, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x8800, }, | ||
| 41 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x17E0, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x9000, }, | ||
| 42 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x1820, 0x0000, 0x0083, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 43 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x13D0, 0x0080, 0x0042, 0x002C, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 44 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x128B, 0x0080, 0x0041, 0x00DB, 0x7C01, 0x7DE9, 0xFFFF, 0x9000, 0x0100, }, | ||
| 45 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x1820, 0x0000, 0x00C3, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 46 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x134E, 0x0080, 0x0041, 0x005E, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 47 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x1515, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 48 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x175D, 0x0000, 0x00C4, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 49 | {0x1145, 0x0000, 0x1452, 0x0080, 0x18E3, 0x0000, 0x11C7, 0x0000, 0x1041, 0x01BC, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 50 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1209, 0x0080, 0x0041, 0x013F, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x1100, }, | ||
| 51 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1556, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x8000, }, | ||
| 52 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x179F, 0x0080, 0x00C4, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 53 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x15D8, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 54 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1105, 0x0080, 0x1041, 0x01E8, 0x6401, 0x65E9, 0xFFFF, 0x9800, 0x1100, }, | ||
| 55 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1820, 0x0000, 0x00C4, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 56 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x1493, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 57 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x138E, 0x0000, 0x0042, 0x005E, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 58 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x17E0, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x9000, }, | ||
| 59 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x165A, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 60 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x175D, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 61 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x1187, 0x0080, 0x1041, 0x01EE, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 62 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x175E, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 63 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x179E, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 64 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x134E, 0x0080, 0x0041, 0x005E, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 65 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x165A, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 66 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x16DC, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 67 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x169A, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 68 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x11C7, 0x0000, 0x1041, 0x01BC, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 69 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x169B, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 70 | {0x1104, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x171D, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 71 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x16DB, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 72 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1146, 0x0080, 0x1041, 0x0184, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 73 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x171C, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 74 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1451, 0x0000, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 75 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x171D, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 76 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x175D, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 77 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1452, 0x0080, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 78 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x15D8, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 79 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1104, 0x0000, 0x1041, 0x01E8, 0x5801, 0x59E9, 0xFFFF, 0x9900, 0x0900, }, | ||
| 80 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x179F, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 81 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1515, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 82 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x17DF, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x8800, }, | ||
| 83 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1659, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 84 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1555, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x8000, }, | ||
| 85 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x14D3, 0x0000, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 86 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1820, 0x0000, 0x0083, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 87 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1556, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x8000, }, | ||
| 88 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1187, 0x0080, 0x1041, 0x01EE, 0x7C01, 0x7DE9, 0xFFFF, 0x9900, 0x8100, }, | ||
| 89 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1452, 0x0080, 0x0082, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 90 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x169B, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 91 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1514, 0x0000, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 92 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x17E0, 0x0080, 0x00C4, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x9000, }, | ||
| 93 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x1515, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 94 | {0x10C3, 0x0000, 0x128B, 0x0080, 0x1555, 0x0000, 0x16DC, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 95 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1493, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 96 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 97 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x15D8, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 98 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x171D, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 99 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1618, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 100 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x175D, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 101 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x14D4, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 102 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1619, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 103 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x179E, 0x0000, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 104 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x179F, 0x0080, 0x00C3, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 105 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1515, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 106 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x13D0, 0x0080, 0x0042, 0x002C, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 107 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x169A, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 108 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x128B, 0x0080, 0x0041, 0x00DB, 0x7C01, 0x7DE9, 0xFFFF, 0x9000, 0x0100, }, | ||
| 109 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x169B, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 110 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1820, 0x0000, 0x00C3, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 111 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1556, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x8000, }, | ||
| 112 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x16DB, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 113 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1411, 0x0080, 0x0042, 0x002C, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 114 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x171C, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 115 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1597, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x8000, }, | ||
| 116 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1451, 0x0000, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 117 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x171D, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x1800, }, | ||
| 118 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x12CC, 0x0080, 0x0041, 0x00A9, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x9000, }, | ||
| 119 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x175D, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 120 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1452, 0x0080, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 121 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x15D8, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1900, 0x0100, }, | ||
| 122 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x175E, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 123 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1492, 0x0000, 0x0042, 0x0013, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 124 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x179F, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0800, 0x1000, }, | ||
| 125 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1619, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 126 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1493, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 127 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x17DF, 0x0000, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x8800, }, | ||
| 128 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x130D, 0x0080, 0x0041, 0x0090, 0x7C01, 0x7DE9, 0xFFFF, 0x1100, 0x9000, }, | ||
| 129 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x17E0, 0x0080, 0x0083, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x9000, }, | ||
| 130 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x14D3, 0x0000, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 131 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x165A, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1000, 0x9000, }, | ||
| 132 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x1820, 0x0000, 0x0083, 0x00FA, 0x7DE9, 0x7DE8, 0xFFFF, 0x0900, 0x9000, }, | ||
| 133 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x14D4, 0x0080, 0x0042, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x0900, 0x1000, }, | ||
| 134 | {0x1082, 0x0000, 0x11C7, 0x0000, 0x138E, 0x0000, 0x169B, 0x0080, 0x0082, 0x00FA, 0x7C01, 0x7DE9, 0xFFFF, 0x1800, 0x0100, }, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static const u16 cmt_vals_in[][13] = { | ||
| 138 | {0x1082, 0x0000, 0x5104, 0x0000, 0x11C7, 0x0000, 0x1041, 0x02BC, 0x7C01, 0xFFE9, 0x9900, 0x9908, 0x8100}, | ||
| 139 | {0x1104, 0x0000, 0x9208, 0x0000, 0x138E, 0x0000, 0x1041, 0x015E, 0x7C01, 0xFFE9, 0x0100, 0x0908, 0x1000}, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static const u32 cmt_addrs_out[][15] = { | ||
| 143 | {0x420, 0x424, 0x428, 0x42C, 0x430, 0x434, 0x450, 0x454, 0x458, 0x460, 0x464, 0x468, 0x4A0, 0x538, 0x53C}, | ||
| 144 | {0x620, 0x624, 0x628, 0x62C, 0x630, 0x634, 0x650, 0x654, 0x658, 0x660, 0x664, 0x668, 0x6A0, 0x738, 0x73C}, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static const u32 cmt_addrs_in[][13] = { | ||
| 148 | {0x020, 0x024, 0x028, 0x02C, 0x050, 0x054, 0x058, 0x060, 0x064, 0x068, 0x0A0, 0x138, 0x13C}, | ||
| 149 | {0x220, 0x224, 0x228, 0x22C, 0x250, 0x254, 0x258, 0x260, 0x264, 0x268, 0x2A0, 0x338, 0x33C}, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static const u32 cmt_freq[] = { | ||
| 153 | 25000, 25510, 26020, 26530, 26983, 27551, 28000, 28570, | ||
| 154 | 29046, 29522, 30000, 30476, 30952, 31546, 32000, 32539, | ||
| 155 | 33035, 33571, 33928, 34522, 35000, 35428, 36000, 36571, | ||
| 156 | 36904, 37500, 38093, 38571, 39047, 39453, 40000, 40476, | ||
| 157 | 40952, 41494, 41964, 42857, 43535, 44047, 44444, 45000, | ||
| 158 | 45535, 46029, 46428, 46823, 47617, 48214, 48571, 49107, | ||
| 159 | 49523, 50000, 50476, 50892, 51428, 52380, 53333, 53967, | ||
| 160 | 54285, 55238, 55555, 55952, 57142, 58095, 58571, 59047, | ||
| 161 | 59521, 60000, 60316, 60952, 61428, 61904, 62500, 63092, | ||
| 162 | 63491, 64282, 65078, 65476, 66071, 66664, 67142, 67854, | ||
| 163 | 68571, 69044, 69642, 70000, 71425, 72616, 73214, 73808, | ||
| 164 | 74285, 75000, 75714, 76187, 76785, 77142, 78570, 80000, | ||
| 165 | 80357, 80951, 81428, 82142, 82857, 83332, 83928, 84285, | ||
| 166 | 85713, 87142, 87500, 88094, 88571, 89285, 90000, 90475, | ||
| 167 | 91071, 91428, 92856, 94642, | ||
| 168 | }; | ||
| 169 | |||
| 170 | static size_t freq_srch(u32 key, const u32 *array, size_t size) | ||
| 171 | { | ||
| 172 | int l = 0; | ||
| 173 | int r = size - 1; | ||
| 174 | int m = 0; | ||
| 175 | |||
| 176 | while (l <= r) { | ||
| 177 | m = (l + r) / 2; | ||
| 178 | if (array[m] < key) | ||
| 179 | l = m + 1; | ||
| 180 | else if (array[m] > key) | ||
| 181 | r = m - 1; | ||
| 182 | else | ||
| 183 | return m; | ||
| 184 | } | ||
| 185 | |||
| 186 | if (r < 0 || l > size - 1) | ||
| 187 | return m; | ||
| 188 | else | ||
| 189 | return (abs(key - array[l]) < abs(key - array[r])) ? l : r; | ||
| 190 | } | ||
| 191 | |||
| 192 | u32 mgb4_cmt_set_vout_freq(struct mgb4_vout_dev *voutdev, unsigned int freq) | ||
| 193 | { | ||
| 194 | struct mgb4_regs *video = &voutdev->mgbdev->video; | ||
| 195 | const struct mgb4_vout_regs *regs = &voutdev->config->regs; | ||
| 196 | const u16 *reg_set; | ||
| 197 | const u32 *addr; | ||
| 198 | u32 config; | ||
| 199 | size_t i, index; | ||
| 200 | |||
| 201 | index = freq_srch(freq, cmt_freq, ARRAY_SIZE(cmt_freq)); | ||
| 202 | addr = cmt_addrs_out[voutdev->config->id]; | ||
| 203 | reg_set = cmt_vals_out[index]; | ||
| 204 | |||
| 205 | config = mgb4_read_reg(video, regs->config); | ||
| 206 | |||
| 207 | mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3)); | ||
| 208 | |||
| 209 | for (i = 0; i < ARRAY_SIZE(cmt_addrs_out[0]); i++) | ||
| 210 | mgb4_write_reg(&voutdev->mgbdev->cmt, addr[i], reg_set[i]); | ||
| 211 | |||
| 212 | mgb4_mask_reg(video, regs->config, 0x100, 0x100); | ||
| 213 | mgb4_mask_reg(video, regs->config, 0x100, 0x0); | ||
| 214 | |||
| 215 | mgb4_write_reg(video, regs->config, config & ~0x1); | ||
| 216 | |||
| 217 | return cmt_freq[index]; | ||
| 218 | } | ||
| 219 | |||
| 220 | void mgb4_cmt_set_vin_freq_range(struct mgb4_vin_dev *vindev, | ||
| 221 | unsigned int freq_range) | ||
| 222 | { | ||
| 223 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 224 | const struct mgb4_vin_regs *regs = &vindev->config->regs; | ||
| 225 | const u16 *reg_set; | ||
| 226 | const u32 *addr; | ||
| 227 | u32 config; | ||
| 228 | size_t i; | ||
| 229 | |||
| 230 | addr = cmt_addrs_in[vindev->config->id]; | ||
| 231 | reg_set = cmt_vals_in[freq_range]; | ||
| 232 | |||
| 233 | config = mgb4_read_reg(video, regs->config); | ||
| 234 | |||
| 235 | mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3)); | ||
| 236 | |||
| 237 | for (i = 0; i < ARRAY_SIZE(cmt_addrs_in[0]); i++) | ||
| 238 | mgb4_write_reg(&vindev->mgbdev->cmt, addr[i], reg_set[i]); | ||
| 239 | |||
| 240 | mgb4_mask_reg(video, regs->config, 0x1000, 0x1000); | ||
| 241 | mgb4_mask_reg(video, regs->config, 0x1000, 0x0); | ||
| 242 | |||
| 243 | mgb4_write_reg(video, regs->config, config & ~0x1); | ||
| 244 | } | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_CMT_H__ | ||
| 8 | #define __MGB4_CMT_H__ | ||
| 9 | |||
| 10 | #include "mgb4_vout.h" | ||
| 11 | #include "mgb4_vin.h" | ||
| 12 | |||
| 13 | u32 mgb4_cmt_set_vout_freq(struct mgb4_vout_dev *voutdev, unsigned int freq); | ||
| 14 | void mgb4_cmt_set_vin_freq_range(struct mgb4_vin_dev *vindev, | ||
| 15 | unsigned int freq_range); | ||
| 16 | |||
| 17 | #endif | ||
| @@ -0,0 +1,686 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * This is the driver for the MGB4 video grabber card by Digiteq Automotive. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 6 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 7 | * | ||
| 8 | * This is the main driver module. The DMA, I2C and SPI sub-drivers are | ||
| 9 | * initialized here and the input/output v4l2 devices are created. | ||
| 10 | * | ||
| 11 | * The mgb4 card uses different expansion modules for different video sources | ||
| 12 | * (GMSL and FPDL3 for now) so in probe() we detect the module type based on | ||
| 13 | * what we see on the I2C bus and check if it matches the FPGA bitstream (there | ||
| 14 | * are different bitstreams for different expansion modules). When no expansion | ||
| 15 | * module is present, we still let the driver initialize to allow flashing of | ||
| 16 | * the FPGA firmware using the SPI FLASH device. No v4l2 video devices are | ||
| 17 | * created in this case. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/pci.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/clk.h> | ||
| 25 | #include <linux/clk-provider.h> | ||
| 26 | #include <linux/clkdev.h> | ||
| 27 | #include <linux/i2c.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/dma/amd_xdma.h> | ||
| 30 | #include <linux/platform_data/amd_xdma.h> | ||
| 31 | #include <linux/spi/xilinx_spi.h> | ||
| 32 | #include <linux/mtd/mtd.h> | ||
| 33 | #include <linux/hwmon.h> | ||
| 34 | #include <linux/debugfs.h> | ||
| 35 | #include "mgb4_dma.h" | ||
| 36 | #include "mgb4_i2c.h" | ||
| 37 | #include "mgb4_sysfs.h" | ||
| 38 | #include "mgb4_vout.h" | ||
| 39 | #include "mgb4_vin.h" | ||
| 40 | #include "mgb4_trigger.h" | ||
| 41 | #include "mgb4_core.h" | ||
| 42 | |||
| 43 | #define MGB4_USER_IRQS 16 | ||
| 44 | |||
| 45 | ATTRIBUTE_GROUPS(mgb4_pci); | ||
| 46 | |||
| 47 | static int flashid; | ||
| 48 | |||
| 49 | static struct xdma_chan_info h2c_chan_info = { | ||
| 50 | .dir = DMA_MEM_TO_DEV, | ||
| 51 | }; | ||
| 52 | |||
| 53 | static struct xdma_chan_info c2h_chan_info = { | ||
| 54 | .dir = DMA_DEV_TO_MEM, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static struct xspi_platform_data spi_platform_data = { | ||
| 58 | .num_chipselect = 1, | ||
| 59 | .bits_per_word = 8 | ||
| 60 | }; | ||
| 61 | |||
| 62 | static const struct i2c_board_info extender_info = { | ||
| 63 | I2C_BOARD_INFO("extender", 0x21) | ||
| 64 | }; | ||
| 65 | |||
| 66 | #if IS_REACHABLE(CONFIG_HWMON) | ||
| 67 | static umode_t temp_is_visible(const void *data, enum hwmon_sensor_types type, | ||
| 68 | u32 attr, int channel) | ||
| 69 | { | ||
| 70 | if (type == hwmon_temp && | ||
| 71 | (attr == hwmon_temp_input || attr == hwmon_temp_label)) | ||
| 72 | return 0444; | ||
| 73 | else | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int temp_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, | ||
| 78 | int channel, long *val) | ||
| 79 | { | ||
| 80 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 81 | u32 val10, raw; | ||
| 82 | |||
| 83 | if (type != hwmon_temp || attr != hwmon_temp_input) | ||
| 84 | return -EOPNOTSUPP; | ||
| 85 | |||
| 86 | raw = mgb4_read_reg(&mgbdev->video, 0xD0); | ||
| 87 | /* register value -> Celsius degrees formula given by Xilinx */ | ||
| 88 | val10 = ((((raw >> 20) & 0xFFF) * 503975) - 1118822400) / 409600; | ||
| 89 | *val = val10 * 100; | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int temp_read_string(struct device *dev, enum hwmon_sensor_types type, | ||
| 95 | u32 attr, int channel, const char **str) | ||
| 96 | { | ||
| 97 | if (type != hwmon_temp || attr != hwmon_temp_label) | ||
| 98 | return -EOPNOTSUPP; | ||
| 99 | |||
| 100 | *str = "FPGA Temperature"; | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static const struct hwmon_ops temp_ops = { | ||
| 106 | .is_visible = temp_is_visible, | ||
| 107 | .read = temp_read, | ||
| 108 | .read_string = temp_read_string | ||
| 109 | }; | ||
| 110 | |||
| 111 | static const struct hwmon_channel_info *temp_channel_info[] = { | ||
| 112 | HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL), | ||
| 113 | NULL | ||
| 114 | }; | ||
| 115 | |||
| 116 | static const struct hwmon_chip_info temp_chip_info = { | ||
| 117 | .ops = &temp_ops, | ||
| 118 | .info = temp_channel_info, | ||
| 119 | }; | ||
| 120 | #endif | ||
| 121 | |||
| 122 | static int match_i2c_adap(struct device *dev, void *data) | ||
| 123 | { | ||
| 124 | return i2c_verify_adapter(dev) ? 1 : 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static struct i2c_adapter *get_i2c_adap(struct platform_device *pdev) | ||
| 128 | { | ||
| 129 | struct device *dev; | ||
| 130 | |||
| 131 | mutex_lock(&pdev->dev.mutex); | ||
| 132 | dev = device_find_child(&pdev->dev, NULL, match_i2c_adap); | ||
| 133 | mutex_unlock(&pdev->dev.mutex); | ||
| 134 | |||
| 135 | return dev ? to_i2c_adapter(dev) : NULL; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int match_spi_adap(struct device *dev, void *data) | ||
| 139 | { | ||
| 140 | return to_spi_device(dev) ? 1 : 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static struct spi_master *get_spi_adap(struct platform_device *pdev) | ||
| 144 | { | ||
| 145 | struct device *dev; | ||
| 146 | |||
| 147 | mutex_lock(&pdev->dev.mutex); | ||
| 148 | dev = device_find_child(&pdev->dev, NULL, match_spi_adap); | ||
| 149 | mutex_unlock(&pdev->dev.mutex); | ||
| 150 | |||
| 151 | return dev ? container_of(dev, struct spi_master, dev) : NULL; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int init_spi(struct mgb4_dev *mgbdev) | ||
| 155 | { | ||
| 156 | struct resource spi_resources[] = { | ||
| 157 | { | ||
| 158 | .start = 0x400, | ||
| 159 | .end = 0x47f, | ||
| 160 | .flags = IORESOURCE_MEM, | ||
| 161 | .name = "io-memory", | ||
| 162 | }, | ||
| 163 | { | ||
| 164 | .start = 14, | ||
| 165 | .end = 14, | ||
| 166 | .flags = IORESOURCE_IRQ, | ||
| 167 | .name = "irq", | ||
| 168 | }, | ||
| 169 | }; | ||
| 170 | struct spi_board_info spi_info = { | ||
| 171 | .max_speed_hz = 10000000, | ||
| 172 | .modalias = "m25p80", | ||
| 173 | .chip_select = 0, | ||
| 174 | .mode = SPI_MODE_3, | ||
| 175 | }; | ||
| 176 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 177 | struct device *dev = &pdev->dev; | ||
| 178 | struct spi_master *master; | ||
| 179 | struct spi_device *spi_dev; | ||
| 180 | u32 irq; | ||
| 181 | int rv, id; | ||
| 182 | resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID); | ||
| 183 | |||
| 184 | request_module("platform:xilinx_spi"); | ||
| 185 | |||
| 186 | irq = xdma_get_user_irq(mgbdev->xdev, 14); | ||
| 187 | xdma_enable_user_irq(mgbdev->xdev, irq); | ||
| 188 | |||
| 189 | spi_resources[0].parent = &pdev->resource[MGB4_MGB4_BAR_ID]; | ||
| 190 | spi_resources[0].start += mapbase; | ||
| 191 | spi_resources[0].end += mapbase; | ||
| 192 | spi_resources[1].start = irq; | ||
| 193 | spi_resources[1].end = irq; | ||
| 194 | |||
| 195 | id = pci_dev_id(pdev); | ||
| 196 | mgbdev->spi_pdev = platform_device_register_resndata(dev, "xilinx_spi", | ||
| 197 | id, spi_resources, | ||
| 198 | ARRAY_SIZE(spi_resources), | ||
| 199 | &spi_platform_data, | ||
| 200 | sizeof(spi_platform_data)); | ||
| 201 | if (IS_ERR(mgbdev->spi_pdev)) { | ||
| 202 | dev_err(dev, "failed to register SPI device\n"); | ||
| 203 | return PTR_ERR(mgbdev->spi_pdev); | ||
| 204 | } | ||
| 205 | |||
| 206 | master = get_spi_adap(mgbdev->spi_pdev); | ||
| 207 | if (!master) { | ||
| 208 | dev_err(dev, "failed to get SPI adapter\n"); | ||
| 209 | rv = -EINVAL; | ||
| 210 | goto err_pdev; | ||
| 211 | } | ||
| 212 | |||
| 213 | snprintf(mgbdev->fw_part_name, sizeof(mgbdev->fw_part_name), | ||
| 214 | "mgb4-fw.%d", flashid); | ||
| 215 | mgbdev->partitions[0].name = mgbdev->fw_part_name; | ||
| 216 | mgbdev->partitions[0].size = 0x400000; | ||
| 217 | mgbdev->partitions[0].offset = 0x400000; | ||
| 218 | mgbdev->partitions[0].mask_flags = 0; | ||
| 219 | |||
| 220 | snprintf(mgbdev->data_part_name, sizeof(mgbdev->data_part_name), | ||
| 221 | "mgb4-data.%d", flashid); | ||
| 222 | mgbdev->partitions[1].name = mgbdev->data_part_name; | ||
| 223 | mgbdev->partitions[1].size = 0x10000; | ||
| 224 | mgbdev->partitions[1].offset = 0xFF0000; | ||
| 225 | mgbdev->partitions[1].mask_flags = MTD_CAP_NORFLASH; | ||
| 226 | |||
| 227 | snprintf(mgbdev->flash_name, sizeof(mgbdev->flash_name), | ||
| 228 | "mgb4-flash.%d", flashid); | ||
| 229 | mgbdev->flash_data.name = mgbdev->flash_name; | ||
| 230 | mgbdev->flash_data.parts = mgbdev->partitions; | ||
| 231 | mgbdev->flash_data.nr_parts = ARRAY_SIZE(mgbdev->partitions); | ||
| 232 | mgbdev->flash_data.type = "spi-nor"; | ||
| 233 | |||
| 234 | spi_info.platform_data = &mgbdev->flash_data; | ||
| 235 | |||
| 236 | spi_dev = spi_new_device(master, &spi_info); | ||
| 237 | put_device(&master->dev); | ||
| 238 | if (!spi_dev) { | ||
| 239 | dev_err(dev, "failed to create MTD device\n"); | ||
| 240 | rv = -EINVAL; | ||
| 241 | goto err_pdev; | ||
| 242 | } | ||
| 243 | |||
| 244 | return 0; | ||
| 245 | |||
| 246 | err_pdev: | ||
| 247 | platform_device_unregister(mgbdev->spi_pdev); | ||
| 248 | |||
| 249 | return rv; | ||
| 250 | } | ||
| 251 | |||
| 252 | static void free_spi(struct mgb4_dev *mgbdev) | ||
| 253 | { | ||
| 254 | platform_device_unregister(mgbdev->spi_pdev); | ||
| 255 | } | ||
| 256 | |||
| 257 | static int init_i2c(struct mgb4_dev *mgbdev) | ||
| 258 | { | ||
| 259 | struct resource i2c_resources[] = { | ||
| 260 | { | ||
| 261 | .start = 0x200, | ||
| 262 | .end = 0x3ff, | ||
| 263 | .flags = IORESOURCE_MEM, | ||
| 264 | .name = "io-memory", | ||
| 265 | }, | ||
| 266 | { | ||
| 267 | .start = 15, | ||
| 268 | .end = 15, | ||
| 269 | .flags = IORESOURCE_IRQ, | ||
| 270 | .name = "irq", | ||
| 271 | }, | ||
| 272 | }; | ||
| 273 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 274 | struct device *dev = &pdev->dev; | ||
| 275 | char clk_name[16]; | ||
| 276 | u32 irq; | ||
| 277 | int rv, id; | ||
| 278 | resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID); | ||
| 279 | |||
| 280 | request_module("platform:xiic-i2c"); | ||
| 281 | |||
| 282 | irq = xdma_get_user_irq(mgbdev->xdev, 15); | ||
| 283 | xdma_enable_user_irq(mgbdev->xdev, irq); | ||
| 284 | |||
| 285 | i2c_resources[0].parent = &pdev->resource[MGB4_MGB4_BAR_ID]; | ||
| 286 | i2c_resources[0].start += mapbase; | ||
| 287 | i2c_resources[0].end += mapbase; | ||
| 288 | i2c_resources[1].start = irq; | ||
| 289 | i2c_resources[1].end = irq; | ||
| 290 | |||
| 291 | id = pci_dev_id(pdev); | ||
| 292 | |||
| 293 | /* create dummy clock required by the xiic-i2c adapter */ | ||
| 294 | snprintf(clk_name, sizeof(clk_name), "xiic-i2c.%d", id); | ||
| 295 | mgbdev->i2c_clk = clk_hw_register_fixed_rate(NULL, clk_name, NULL, | ||
| 296 | 0, 125000000); | ||
| 297 | if (IS_ERR(mgbdev->i2c_clk)) { | ||
| 298 | dev_err(dev, "failed to register I2C clock\n"); | ||
| 299 | return PTR_ERR(mgbdev->i2c_clk); | ||
| 300 | } | ||
| 301 | mgbdev->i2c_cl = clkdev_hw_create(mgbdev->i2c_clk, NULL, "xiic-i2c.%d", | ||
| 302 | id); | ||
| 303 | if (!mgbdev->i2c_cl) { | ||
| 304 | dev_err(dev, "failed to register I2C clockdev\n"); | ||
| 305 | rv = -ENOMEM; | ||
| 306 | goto err_clk; | ||
| 307 | } | ||
| 308 | |||
| 309 | mgbdev->i2c_pdev = platform_device_register_resndata(dev, "xiic-i2c", | ||
| 310 | id, i2c_resources, | ||
| 311 | ARRAY_SIZE(i2c_resources), | ||
| 312 | NULL, 0); | ||
| 313 | if (IS_ERR(mgbdev->i2c_pdev)) { | ||
| 314 | dev_err(dev, "failed to register I2C device\n"); | ||
| 315 | rv = PTR_ERR(mgbdev->i2c_pdev); | ||
| 316 | goto err_clkdev; | ||
| 317 | } | ||
| 318 | |||
| 319 | mgbdev->i2c_adap = get_i2c_adap(mgbdev->i2c_pdev); | ||
| 320 | if (!mgbdev->i2c_adap) { | ||
| 321 | dev_err(dev, "failed to get I2C adapter\n"); | ||
| 322 | rv = -EINVAL; | ||
| 323 | goto err_pdev; | ||
| 324 | } | ||
| 325 | |||
| 326 | mutex_init(&mgbdev->i2c_lock); | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | |||
| 330 | err_pdev: | ||
| 331 | platform_device_unregister(mgbdev->i2c_pdev); | ||
| 332 | err_clkdev: | ||
| 333 | clkdev_drop(mgbdev->i2c_cl); | ||
| 334 | err_clk: | ||
| 335 | clk_hw_unregister(mgbdev->i2c_clk); | ||
| 336 | |||
| 337 | return rv; | ||
| 338 | } | ||
| 339 | |||
| 340 | static void free_i2c(struct mgb4_dev *mgbdev) | ||
| 341 | { | ||
| 342 | put_device(&mgbdev->i2c_adap->dev); | ||
| 343 | platform_device_unregister(mgbdev->i2c_pdev); | ||
| 344 | clkdev_drop(mgbdev->i2c_cl); | ||
| 345 | clk_hw_unregister(mgbdev->i2c_clk); | ||
| 346 | } | ||
| 347 | |||
| 348 | static int get_serial_number(struct mgb4_dev *mgbdev) | ||
| 349 | { | ||
| 350 | struct device *dev = &mgbdev->pdev->dev; | ||
| 351 | struct mtd_info *mtd; | ||
| 352 | size_t rs; | ||
| 353 | int rv; | ||
| 354 | |||
| 355 | mgbdev->serial_number = 0; | ||
| 356 | |||
| 357 | mtd = get_mtd_device_nm(mgbdev->data_part_name); | ||
| 358 | if (IS_ERR(mtd)) { | ||
| 359 | dev_warn(dev, "failed to get data MTD device\n"); | ||
| 360 | return -ENOENT; | ||
| 361 | } | ||
| 362 | rv = mtd_read(mtd, 0, sizeof(mgbdev->serial_number), &rs, | ||
| 363 | (u_char *)&mgbdev->serial_number); | ||
| 364 | put_mtd_device(mtd); | ||
| 365 | if (rv < 0 || rs != sizeof(mgbdev->serial_number)) { | ||
| 366 | dev_warn(dev, "error reading MTD device\n"); | ||
| 367 | return -EIO; | ||
| 368 | } | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int get_module_version(struct mgb4_dev *mgbdev) | ||
| 374 | { | ||
| 375 | struct device *dev = &mgbdev->pdev->dev; | ||
| 376 | struct mgb4_i2c_client extender; | ||
| 377 | s32 version; | ||
| 378 | u32 fw_version; | ||
| 379 | int rv; | ||
| 380 | |||
| 381 | rv = mgb4_i2c_init(&extender, mgbdev->i2c_adap, &extender_info, 8); | ||
| 382 | if (rv < 0) { | ||
| 383 | dev_err(dev, "failed to create extender I2C device\n"); | ||
| 384 | return rv; | ||
| 385 | } | ||
| 386 | version = mgb4_i2c_read_byte(&extender, 0x00); | ||
| 387 | mgb4_i2c_free(&extender); | ||
| 388 | if (version < 0) { | ||
| 389 | dev_err(dev, "error reading module version\n"); | ||
| 390 | return -EIO; | ||
| 391 | } | ||
| 392 | |||
| 393 | mgbdev->module_version = ~((u32)version) & 0xff; | ||
| 394 | if (!(MGB4_IS_FPDL3(mgbdev) || MGB4_IS_GMSL(mgbdev))) { | ||
| 395 | dev_err(dev, "unknown module type\n"); | ||
| 396 | return -EINVAL; | ||
| 397 | } | ||
| 398 | fw_version = mgb4_read_reg(&mgbdev->video, 0xC4); | ||
| 399 | if (fw_version >> 24 != mgbdev->module_version >> 4) { | ||
| 400 | dev_err(dev, "module/firmware type mismatch\n"); | ||
| 401 | return -EINVAL; | ||
| 402 | } | ||
| 403 | |||
| 404 | dev_info(dev, "%s module detected\n", | ||
| 405 | MGB4_IS_FPDL3(mgbdev) ? "FPDL3" : "GMSL"); | ||
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int map_regs(struct pci_dev *pdev, struct resource *res, | ||
| 411 | struct mgb4_regs *regs) | ||
| 412 | { | ||
| 413 | int rv; | ||
| 414 | resource_size_t mapbase = pci_resource_start(pdev, MGB4_MGB4_BAR_ID); | ||
| 415 | |||
| 416 | res->start += mapbase; | ||
| 417 | res->end += mapbase; | ||
| 418 | |||
| 419 | rv = mgb4_regs_map(res, regs); | ||
| 420 | if (rv < 0) { | ||
| 421 | dev_err(&pdev->dev, "failed to map %s registers\n", res->name); | ||
| 422 | return rv; | ||
| 423 | } | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static int init_xdma(struct mgb4_dev *mgbdev) | ||
| 429 | { | ||
| 430 | struct xdma_platdata data; | ||
| 431 | struct resource res[2] = { 0 }; | ||
| 432 | struct dma_slave_map *map; | ||
| 433 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 434 | struct device *dev = &pdev->dev; | ||
| 435 | int i; | ||
| 436 | |||
| 437 | res[0].start = pci_resource_start(pdev, MGB4_XDMA_BAR_ID); | ||
| 438 | res[0].end = pci_resource_end(pdev, MGB4_XDMA_BAR_ID); | ||
| 439 | res[0].flags = IORESOURCE_MEM; | ||
| 440 | res[0].parent = &pdev->resource[MGB4_XDMA_BAR_ID]; | ||
| 441 | res[1].start = pci_irq_vector(pdev, 0); | ||
| 442 | res[1].end = res[1].start + MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES | ||
| 443 | + MGB4_USER_IRQS - 1; | ||
| 444 | res[1].flags = IORESOURCE_IRQ; | ||
| 445 | |||
| 446 | data.max_dma_channels = MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES; | ||
| 447 | data.device_map = mgbdev->slave_map; | ||
| 448 | data.device_map_cnt = MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES; | ||
| 449 | |||
| 450 | for (i = 0; i < MGB4_VIN_DEVICES; i++) { | ||
| 451 | sprintf(mgbdev->channel_names[i], "c2h%d", i); | ||
| 452 | map = &data.device_map[i]; | ||
| 453 | map->slave = mgbdev->channel_names[i]; | ||
| 454 | map->devname = dev_name(dev); | ||
| 455 | map->param = XDMA_FILTER_PARAM(&c2h_chan_info); | ||
| 456 | } | ||
| 457 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) { | ||
| 458 | sprintf(mgbdev->channel_names[i + MGB4_VIN_DEVICES], "h2c%d", i); | ||
| 459 | map = &data.device_map[i + MGB4_VIN_DEVICES]; | ||
| 460 | map->slave = mgbdev->channel_names[i + MGB4_VIN_DEVICES]; | ||
| 461 | map->devname = dev_name(dev); | ||
| 462 | map->param = XDMA_FILTER_PARAM(&h2c_chan_info); | ||
| 463 | } | ||
| 464 | |||
| 465 | mgbdev->xdev = platform_device_register_resndata(dev, "xdma", | ||
| 466 | PLATFORM_DEVID_AUTO, res, | ||
| 467 | 2, &data, sizeof(data)); | ||
| 468 | if (IS_ERR(mgbdev->xdev)) { | ||
| 469 | dev_err(dev, "failed to register XDMA device\n"); | ||
| 470 | return PTR_ERR(mgbdev->xdev); | ||
| 471 | } | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static void free_xdma(struct mgb4_dev *mgbdev) | ||
| 477 | { | ||
| 478 | platform_device_unregister(mgbdev->xdev); | ||
| 479 | } | ||
| 480 | |||
| 481 | static int mgb4_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 482 | { | ||
| 483 | int i, rv; | ||
| 484 | struct mgb4_dev *mgbdev; | ||
| 485 | struct resource video = { | ||
| 486 | .start = 0x0, | ||
| 487 | .end = 0x100, | ||
| 488 | .flags = IORESOURCE_MEM, | ||
| 489 | .name = "mgb4-video", | ||
| 490 | }; | ||
| 491 | struct resource cmt = { | ||
| 492 | .start = 0x1000, | ||
| 493 | .end = 0x1800, | ||
| 494 | .flags = IORESOURCE_MEM, | ||
| 495 | .name = "mgb4-cmt", | ||
| 496 | }; | ||
| 497 | int irqs = pci_msix_vec_count(pdev); | ||
| 498 | |||
| 499 | mgbdev = kzalloc(sizeof(*mgbdev), GFP_KERNEL); | ||
| 500 | if (!mgbdev) | ||
| 501 | return -ENOMEM; | ||
| 502 | |||
| 503 | mgbdev->pdev = pdev; | ||
| 504 | pci_set_drvdata(pdev, mgbdev); | ||
| 505 | |||
| 506 | /* PCIe related stuff */ | ||
| 507 | rv = pci_enable_device(pdev); | ||
| 508 | if (rv) { | ||
| 509 | dev_err(&pdev->dev, "error enabling PCI device\n"); | ||
| 510 | goto err_mgbdev; | ||
| 511 | } | ||
| 512 | |||
| 513 | rv = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN); | ||
| 514 | if (rv) | ||
| 515 | dev_warn(&pdev->dev, "error enabling PCIe relaxed ordering\n"); | ||
| 516 | rv = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_EXT_TAG); | ||
| 517 | if (rv) | ||
| 518 | dev_warn(&pdev->dev, "error enabling PCIe extended tag field\n"); | ||
| 519 | rv = pcie_set_readrq(pdev, 512); | ||
| 520 | if (rv) | ||
| 521 | dev_warn(&pdev->dev, "error setting PCIe max. memory read size\n"); | ||
| 522 | pci_set_master(pdev); | ||
| 523 | |||
| 524 | rv = pci_alloc_irq_vectors(pdev, irqs, irqs, PCI_IRQ_MSIX); | ||
| 525 | if (rv < 0) { | ||
| 526 | dev_err(&pdev->dev, "error allocating MSI-X IRQs\n"); | ||
| 527 | goto err_enable_pci; | ||
| 528 | } | ||
| 529 | |||
| 530 | rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | ||
| 531 | if (rv) { | ||
| 532 | dev_err(&pdev->dev, "error setting DMA mask\n"); | ||
| 533 | goto err_enable_pci; | ||
| 534 | } | ||
| 535 | |||
| 536 | /* DMA + IRQ engine */ | ||
| 537 | rv = init_xdma(mgbdev); | ||
| 538 | if (rv) | ||
| 539 | goto err_alloc_irq; | ||
| 540 | rv = mgb4_dma_channel_init(mgbdev); | ||
| 541 | if (rv) | ||
| 542 | goto err_dma_chan; | ||
| 543 | |||
| 544 | /* mgb4 video registers */ | ||
| 545 | rv = map_regs(pdev, &video, &mgbdev->video); | ||
| 546 | if (rv < 0) | ||
| 547 | goto err_dma_chan; | ||
| 548 | /* mgb4 cmt registers */ | ||
| 549 | rv = map_regs(pdev, &cmt, &mgbdev->cmt); | ||
| 550 | if (rv < 0) | ||
| 551 | goto err_video_regs; | ||
| 552 | |||
| 553 | /* SPI FLASH */ | ||
| 554 | rv = init_spi(mgbdev); | ||
| 555 | if (rv < 0) | ||
| 556 | goto err_cmt_regs; | ||
| 557 | |||
| 558 | /* I2C controller */ | ||
| 559 | rv = init_i2c(mgbdev); | ||
| 560 | if (rv < 0) | ||
| 561 | goto err_spi; | ||
| 562 | |||
| 563 | /* PCI card related sysfs attributes */ | ||
| 564 | rv = device_add_groups(&pdev->dev, mgb4_pci_groups); | ||
| 565 | if (rv < 0) | ||
| 566 | goto err_i2c; | ||
| 567 | |||
| 568 | #if IS_REACHABLE(CONFIG_HWMON) | ||
| 569 | /* HWmon (card temperature) */ | ||
| 570 | mgbdev->hwmon_dev = hwmon_device_register_with_info(&pdev->dev, "mgb4", | ||
| 571 | mgbdev, | ||
| 572 | &temp_chip_info, | ||
| 573 | NULL); | ||
| 574 | #endif | ||
| 575 | |||
| 576 | #ifdef CONFIG_DEBUG_FS | ||
| 577 | mgbdev->debugfs = debugfs_create_dir(dev_name(&pdev->dev), NULL); | ||
| 578 | #endif | ||
| 579 | |||
| 580 | /* Get card serial number. On systems without MTD flash support we may | ||
| 581 | * get an error thus ignore the return value. An invalid serial number | ||
| 582 | * should not break anything... | ||
| 583 | */ | ||
| 584 | if (get_serial_number(mgbdev) < 0) | ||
| 585 | dev_warn(&pdev->dev, "error reading card serial number\n"); | ||
| 586 | |||
| 587 | /* Get module type. If no valid module is found, skip the video device | ||
| 588 | * creation part but do not exit with error to allow flashing the card. | ||
| 589 | */ | ||
| 590 | rv = get_module_version(mgbdev); | ||
| 591 | if (rv < 0) | ||
| 592 | goto exit; | ||
| 593 | |||
| 594 | /* Video input v4l2 devices */ | ||
| 595 | for (i = 0; i < MGB4_VIN_DEVICES; i++) | ||
| 596 | mgbdev->vin[i] = mgb4_vin_create(mgbdev, i); | ||
| 597 | |||
| 598 | /* Video output v4l2 devices */ | ||
| 599 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) | ||
| 600 | mgbdev->vout[i] = mgb4_vout_create(mgbdev, i); | ||
| 601 | |||
| 602 | /* Triggers */ | ||
| 603 | mgbdev->indio_dev = mgb4_trigger_create(mgbdev); | ||
| 604 | |||
| 605 | exit: | ||
| 606 | flashid++; | ||
| 607 | |||
| 608 | return 0; | ||
| 609 | |||
| 610 | err_i2c: | ||
| 611 | free_i2c(mgbdev); | ||
| 612 | err_spi: | ||
| 613 | free_spi(mgbdev); | ||
| 614 | err_cmt_regs: | ||
| 615 | mgb4_regs_free(&mgbdev->cmt); | ||
| 616 | err_video_regs: | ||
| 617 | mgb4_regs_free(&mgbdev->video); | ||
| 618 | err_dma_chan: | ||
| 619 | mgb4_dma_channel_free(mgbdev); | ||
| 620 | free_xdma(mgbdev); | ||
| 621 | err_alloc_irq: | ||
| 622 | pci_disable_msix(pdev); | ||
| 623 | err_enable_pci: | ||
| 624 | pci_disable_device(pdev); | ||
| 625 | err_mgbdev: | ||
| 626 | kfree(mgbdev); | ||
| 627 | |||
| 628 | return rv; | ||
| 629 | } | ||
| 630 | |||
| 631 | static void mgb4_remove(struct pci_dev *pdev) | ||
| 632 | { | ||
| 633 | struct mgb4_dev *mgbdev = pci_get_drvdata(pdev); | ||
| 634 | int i; | ||
| 635 | |||
| 636 | #ifdef CONFIG_DEBUG_FS | ||
| 637 | debugfs_remove_recursive(mgbdev->debugfs); | ||
| 638 | #endif | ||
| 639 | #if IS_REACHABLE(CONFIG_HWMON) | ||
| 640 | hwmon_device_unregister(mgbdev->hwmon_dev); | ||
| 641 | #endif | ||
| 642 | |||
| 643 | if (mgbdev->indio_dev) | ||
| 644 | mgb4_trigger_free(mgbdev->indio_dev); | ||
| 645 | |||
| 646 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) | ||
| 647 | if (mgbdev->vout[i]) | ||
| 648 | mgb4_vout_free(mgbdev->vout[i]); | ||
| 649 | for (i = 0; i < MGB4_VIN_DEVICES; i++) | ||
| 650 | if (mgbdev->vin[i]) | ||
| 651 | mgb4_vin_free(mgbdev->vin[i]); | ||
| 652 | |||
| 653 | device_remove_groups(&mgbdev->pdev->dev, mgb4_pci_groups); | ||
| 654 | free_spi(mgbdev); | ||
| 655 | free_i2c(mgbdev); | ||
| 656 | mgb4_regs_free(&mgbdev->video); | ||
| 657 | mgb4_regs_free(&mgbdev->cmt); | ||
| 658 | |||
| 659 | mgb4_dma_channel_free(mgbdev); | ||
| 660 | free_xdma(mgbdev); | ||
| 661 | |||
| 662 | pci_disable_msix(mgbdev->pdev); | ||
| 663 | pci_disable_device(mgbdev->pdev); | ||
| 664 | |||
| 665 | kfree(mgbdev); | ||
| 666 | } | ||
| 667 | |||
| 668 | static const struct pci_device_id mgb4_pci_ids[] = { | ||
| 669 | { PCI_DEVICE(0x1ed8, 0x0101), }, | ||
| 670 | { 0, } | ||
| 671 | }; | ||
| 672 | MODULE_DEVICE_TABLE(pci, mgb4_pci_ids); | ||
| 673 | |||
| 674 | static struct pci_driver mgb4_pci_driver = { | ||
| 675 | .name = KBUILD_MODNAME, | ||
| 676 | .id_table = mgb4_pci_ids, | ||
| 677 | .probe = mgb4_probe, | ||
| 678 | .remove = mgb4_remove, | ||
| 679 | }; | ||
| 680 | |||
| 681 | module_pci_driver(mgb4_pci_driver); | ||
| 682 | |||
| 683 | MODULE_AUTHOR("Digiteq Automotive s.r.o."); | ||
| 684 | MODULE_DESCRIPTION("Digiteq Automotive MGB4 Driver"); | ||
| 685 | MODULE_LICENSE("GPL"); | ||
| 686 | MODULE_SOFTDEP("pre: platform:xiic-i2c platform:xilinx_spi spi-nor"); | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_CORE_H__ | ||
| 8 | #define __MGB4_CORE_H__ | ||
| 9 | |||
| 10 | #include <linux/spi/flash.h> | ||
| 11 | #include <linux/mtd/partitions.h> | ||
| 12 | #include <linux/mutex.h> | ||
| 13 | #include <linux/dmaengine.h> | ||
| 14 | #include "mgb4_regs.h" | ||
| 15 | |||
| 16 | #define MGB4_VIN_DEVICES 2 | ||
| 17 | #define MGB4_VOUT_DEVICES 2 | ||
| 18 | |||
| 19 | #define MGB4_MGB4_BAR_ID 0 | ||
| 20 | #define MGB4_XDMA_BAR_ID 1 | ||
| 21 | |||
| 22 | #define MGB4_IS_GMSL(mgbdev) \ | ||
| 23 | ((mgbdev)->module_version >> 4 == 2) | ||
| 24 | #define MGB4_IS_FPDL3(mgbdev) \ | ||
| 25 | ((mgbdev)->module_version >> 4 == 1) | ||
| 26 | |||
| 27 | struct mgb4_dma_channel { | ||
| 28 | struct dma_chan *chan; | ||
| 29 | struct completion req_compl; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct mgb4_dev { | ||
| 33 | struct pci_dev *pdev; | ||
| 34 | struct platform_device *xdev; | ||
| 35 | struct mgb4_vin_dev *vin[MGB4_VIN_DEVICES]; | ||
| 36 | struct mgb4_vout_dev *vout[MGB4_VOUT_DEVICES]; | ||
| 37 | |||
| 38 | struct mgb4_dma_channel c2h_chan[MGB4_VIN_DEVICES]; | ||
| 39 | struct mgb4_dma_channel h2c_chan[MGB4_VOUT_DEVICES]; | ||
| 40 | struct dma_slave_map slave_map[MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES]; | ||
| 41 | |||
| 42 | struct mgb4_regs video; | ||
| 43 | struct mgb4_regs cmt; | ||
| 44 | |||
| 45 | struct clk_hw *i2c_clk; | ||
| 46 | struct clk_lookup *i2c_cl; | ||
| 47 | struct platform_device *i2c_pdev; | ||
| 48 | struct i2c_adapter *i2c_adap; | ||
| 49 | struct mutex i2c_lock; /* I2C bus access lock */ | ||
| 50 | |||
| 51 | struct platform_device *spi_pdev; | ||
| 52 | struct flash_platform_data flash_data; | ||
| 53 | struct mtd_partition partitions[2]; | ||
| 54 | char flash_name[16]; | ||
| 55 | char fw_part_name[16]; | ||
| 56 | char data_part_name[16]; | ||
| 57 | char channel_names[MGB4_VIN_DEVICES + MGB4_VOUT_DEVICES][16]; | ||
| 58 | |||
| 59 | struct iio_dev *indio_dev; | ||
| 60 | #if IS_REACHABLE(CONFIG_HWMON) | ||
| 61 | struct device *hwmon_dev; | ||
| 62 | #endif | ||
| 63 | |||
| 64 | unsigned long io_reconfig; | ||
| 65 | |||
| 66 | u8 module_version; | ||
| 67 | u32 serial_number; | ||
| 68 | |||
| 69 | #ifdef CONFIG_DEBUG_FS | ||
| 70 | struct dentry *debugfs; | ||
| 71 | #endif | ||
| 72 | }; | ||
| 73 | |||
| 74 | #endif | ||
| @@ -0,0 +1,123 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This module handles the DMA transfers. A standard dmaengine API as provided | ||
| 7 | * by the XDMA module is used. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/pci.h> | ||
| 11 | #include <linux/dma-direction.h> | ||
| 12 | #include "mgb4_core.h" | ||
| 13 | #include "mgb4_dma.h" | ||
| 14 | |||
| 15 | static void chan_irq(void *param) | ||
| 16 | { | ||
| 17 | struct mgb4_dma_channel *chan = param; | ||
| 18 | |||
| 19 | complete(&chan->req_compl); | ||
| 20 | } | ||
| 21 | |||
| 22 | int mgb4_dma_transfer(struct mgb4_dev *mgbdev, u32 channel, bool write, | ||
| 23 | u64 paddr, struct sg_table *sgt) | ||
| 24 | { | ||
| 25 | struct dma_slave_config cfg; | ||
| 26 | struct mgb4_dma_channel *chan; | ||
| 27 | struct dma_async_tx_descriptor *tx; | ||
| 28 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 29 | int ret; | ||
| 30 | |||
| 31 | memset(&cfg, 0, sizeof(cfg)); | ||
| 32 | |||
| 33 | if (write) { | ||
| 34 | cfg.direction = DMA_MEM_TO_DEV; | ||
| 35 | cfg.dst_addr = paddr; | ||
| 36 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
| 37 | chan = &mgbdev->h2c_chan[channel]; | ||
| 38 | } else { | ||
| 39 | cfg.direction = DMA_DEV_TO_MEM; | ||
| 40 | cfg.src_addr = paddr; | ||
| 41 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
| 42 | chan = &mgbdev->c2h_chan[channel]; | ||
| 43 | } | ||
| 44 | |||
| 45 | ret = dmaengine_slave_config(chan->chan, &cfg); | ||
| 46 | if (ret) { | ||
| 47 | dev_err(&pdev->dev, "failed to config dma: %d\n", ret); | ||
| 48 | return ret; | ||
| 49 | } | ||
| 50 | |||
| 51 | tx = dmaengine_prep_slave_sg(chan->chan, sgt->sgl, sgt->nents, | ||
| 52 | cfg.direction, 0); | ||
| 53 | if (!tx) { | ||
| 54 | dev_err(&pdev->dev, "failed to prep slave sg\n"); | ||
| 55 | return -EIO; | ||
| 56 | } | ||
| 57 | |||
| 58 | tx->callback = chan_irq; | ||
| 59 | tx->callback_param = chan; | ||
| 60 | |||
| 61 | ret = dma_submit_error(dmaengine_submit(tx)); | ||
| 62 | if (ret) { | ||
| 63 | dev_err(&pdev->dev, "failed to submit sg\n"); | ||
| 64 | return -EIO; | ||
| 65 | } | ||
| 66 | |||
| 67 | dma_async_issue_pending(chan->chan); | ||
| 68 | |||
| 69 | if (!wait_for_completion_timeout(&chan->req_compl, | ||
| 70 | msecs_to_jiffies(10000))) { | ||
| 71 | dev_err(&pdev->dev, "dma timeout\n"); | ||
| 72 | dmaengine_terminate_sync(chan->chan); | ||
| 73 | return -EIO; | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | int mgb4_dma_channel_init(struct mgb4_dev *mgbdev) | ||
| 80 | { | ||
| 81 | int i, ret; | ||
| 82 | char name[16]; | ||
| 83 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 84 | |||
| 85 | for (i = 0; i < MGB4_VIN_DEVICES; i++) { | ||
| 86 | sprintf(name, "c2h%d", i); | ||
| 87 | mgbdev->c2h_chan[i].chan = dma_request_chan(&pdev->dev, name); | ||
| 88 | if (IS_ERR(mgbdev->c2h_chan[i].chan)) { | ||
| 89 | dev_err(&pdev->dev, "failed to initialize %s", name); | ||
| 90 | ret = PTR_ERR(mgbdev->c2h_chan[i].chan); | ||
| 91 | mgbdev->c2h_chan[i].chan = NULL; | ||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | init_completion(&mgbdev->c2h_chan[i].req_compl); | ||
| 95 | } | ||
| 96 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) { | ||
| 97 | sprintf(name, "h2c%d", i); | ||
| 98 | mgbdev->h2c_chan[i].chan = dma_request_chan(&pdev->dev, name); | ||
| 99 | if (IS_ERR(mgbdev->h2c_chan[i].chan)) { | ||
| 100 | dev_err(&pdev->dev, "failed to initialize %s", name); | ||
| 101 | ret = PTR_ERR(mgbdev->h2c_chan[i].chan); | ||
| 102 | mgbdev->h2c_chan[i].chan = NULL; | ||
| 103 | return ret; | ||
| 104 | } | ||
| 105 | init_completion(&mgbdev->h2c_chan[i].req_compl); | ||
| 106 | } | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | void mgb4_dma_channel_free(struct mgb4_dev *mgbdev) | ||
| 112 | { | ||
| 113 | int i; | ||
| 114 | |||
| 115 | for (i = 0; i < MGB4_VIN_DEVICES; i++) { | ||
| 116 | if (mgbdev->c2h_chan[i].chan) | ||
| 117 | dma_release_channel(mgbdev->c2h_chan[i].chan); | ||
| 118 | } | ||
| 119 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) { | ||
| 120 | if (mgbdev->h2c_chan[i].chan) | ||
| 121 | dma_release_channel(mgbdev->h2c_chan[i].chan); | ||
| 122 | } | ||
| 123 | } | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_DMA_H__ | ||
| 8 | #define __MGB4_DMA_H__ | ||
| 9 | |||
| 10 | #include "mgb4_core.h" | ||
| 11 | |||
| 12 | int mgb4_dma_channel_init(struct mgb4_dev *mgbdev); | ||
| 13 | void mgb4_dma_channel_free(struct mgb4_dev *mgbdev); | ||
| 14 | |||
| 15 | int mgb4_dma_transfer(struct mgb4_dev *mgbdev, u32 channel, bool write, | ||
| 16 | u64 paddr, struct sg_table *sgt); | ||
| 17 | |||
| 18 | #endif | ||
| @@ -0,0 +1,140 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * The i2c module unifies the I2C access to the serializes/deserializes. The I2C | ||
| 7 | * chips on the GMSL module use 16b addressing, the FPDL3 chips use standard | ||
| 8 | * 8b addressing. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include "mgb4_i2c.h" | ||
| 12 | |||
| 13 | static int read_r16(struct i2c_client *client, u16 reg, u8 *val, int len) | ||
| 14 | { | ||
| 15 | int ret; | ||
| 16 | u8 buf[2]; | ||
| 17 | struct i2c_msg msg[2] = { | ||
| 18 | { | ||
| 19 | .addr = client->addr, | ||
| 20 | .flags = 0, | ||
| 21 | .len = 2, | ||
| 22 | .buf = buf, | ||
| 23 | }, { | ||
| 24 | .addr = client->addr, | ||
| 25 | .flags = I2C_M_RD, | ||
| 26 | .len = len, | ||
| 27 | .buf = val, | ||
| 28 | } | ||
| 29 | }; | ||
| 30 | |||
| 31 | buf[0] = (reg >> 8) & 0xff; | ||
| 32 | buf[1] = (reg >> 0) & 0xff; | ||
| 33 | |||
| 34 | ret = i2c_transfer(client->adapter, msg, 2); | ||
| 35 | if (ret < 0) | ||
| 36 | return ret; | ||
| 37 | else if (ret != 2) | ||
| 38 | return -EREMOTEIO; | ||
| 39 | else | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int write_r16(struct i2c_client *client, u16 reg, const u8 *val, int len) | ||
| 44 | { | ||
| 45 | int ret; | ||
| 46 | u8 buf[4]; | ||
| 47 | struct i2c_msg msg[1] = { | ||
| 48 | { | ||
| 49 | .addr = client->addr, | ||
| 50 | .flags = 0, | ||
| 51 | .len = 2 + len, | ||
| 52 | .buf = buf, | ||
| 53 | } | ||
| 54 | }; | ||
| 55 | |||
| 56 | if (2 + len > sizeof(buf)) | ||
| 57 | return -EINVAL; | ||
| 58 | |||
| 59 | buf[0] = (reg >> 8) & 0xff; | ||
| 60 | buf[1] = (reg >> 0) & 0xff; | ||
| 61 | memcpy(&buf[2], val, len); | ||
| 62 | |||
| 63 | ret = i2c_transfer(client->adapter, msg, 1); | ||
| 64 | if (ret < 0) | ||
| 65 | return ret; | ||
| 66 | else if (ret != 1) | ||
| 67 | return -EREMOTEIO; | ||
| 68 | else | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | int mgb4_i2c_init(struct mgb4_i2c_client *client, struct i2c_adapter *adap, | ||
| 73 | struct i2c_board_info const *info, int addr_size) | ||
| 74 | { | ||
| 75 | client->client = i2c_new_client_device(adap, info); | ||
| 76 | if (IS_ERR(client->client)) | ||
| 77 | return PTR_ERR(client->client); | ||
| 78 | |||
| 79 | client->addr_size = addr_size; | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | void mgb4_i2c_free(struct mgb4_i2c_client *client) | ||
| 85 | { | ||
| 86 | i2c_unregister_device(client->client); | ||
| 87 | } | ||
| 88 | |||
| 89 | s32 mgb4_i2c_read_byte(struct mgb4_i2c_client *client, u16 reg) | ||
| 90 | { | ||
| 91 | int ret; | ||
| 92 | u8 b; | ||
| 93 | |||
| 94 | if (client->addr_size == 8) | ||
| 95 | return i2c_smbus_read_byte_data(client->client, reg); | ||
| 96 | |||
| 97 | ret = read_r16(client->client, reg, &b, 1); | ||
| 98 | if (ret < 0) | ||
| 99 | return ret; | ||
| 100 | |||
| 101 | return (s32)b; | ||
| 102 | } | ||
| 103 | |||
| 104 | s32 mgb4_i2c_write_byte(struct mgb4_i2c_client *client, u16 reg, u8 val) | ||
| 105 | { | ||
| 106 | if (client->addr_size == 8) | ||
| 107 | return i2c_smbus_write_byte_data(client->client, reg, val); | ||
| 108 | else | ||
| 109 | return write_r16(client->client, reg, &val, 1); | ||
| 110 | } | ||
| 111 | |||
| 112 | s32 mgb4_i2c_mask_byte(struct mgb4_i2c_client *client, u16 reg, u8 mask, u8 val) | ||
| 113 | { | ||
| 114 | s32 ret; | ||
| 115 | |||
| 116 | if (mask != 0xFF) { | ||
| 117 | ret = mgb4_i2c_read_byte(client, reg); | ||
| 118 | if (ret < 0) | ||
| 119 | return ret; | ||
| 120 | val |= (u8)ret & ~mask; | ||
| 121 | } | ||
| 122 | |||
| 123 | return mgb4_i2c_write_byte(client, reg, val); | ||
| 124 | } | ||
| 125 | |||
| 126 | int mgb4_i2c_configure(struct mgb4_i2c_client *client, | ||
| 127 | const struct mgb4_i2c_kv *values, size_t count) | ||
| 128 | { | ||
| 129 | size_t i; | ||
| 130 | s32 res; | ||
| 131 | |||
| 132 | for (i = 0; i < count; i++) { | ||
| 133 | res = mgb4_i2c_mask_byte(client, values[i].reg, values[i].mask, | ||
| 134 | values[i].val); | ||
| 135 | if (res < 0) | ||
| 136 | return res; | ||
| 137 | } | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_I2C_H__ | ||
| 8 | #define __MGB4_I2C_H__ | ||
| 9 | |||
| 10 | #include <linux/i2c.h> | ||
| 11 | |||
| 12 | struct mgb4_i2c_client { | ||
| 13 | struct i2c_client *client; | ||
| 14 | int addr_size; | ||
| 15 | }; | ||
| 16 | |||
| 17 | struct mgb4_i2c_kv { | ||
| 18 | u16 reg; | ||
| 19 | u8 mask; | ||
| 20 | u8 val; | ||
| 21 | }; | ||
| 22 | |||
| 23 | int mgb4_i2c_init(struct mgb4_i2c_client *client, struct i2c_adapter *adap, | ||
| 24 | struct i2c_board_info const *info, int addr_size); | ||
| 25 | void mgb4_i2c_free(struct mgb4_i2c_client *client); | ||
| 26 | |||
| 27 | s32 mgb4_i2c_read_byte(struct mgb4_i2c_client *client, u16 reg); | ||
| 28 | s32 mgb4_i2c_write_byte(struct mgb4_i2c_client *client, u16 reg, u8 val); | ||
| 29 | s32 mgb4_i2c_mask_byte(struct mgb4_i2c_client *client, u16 reg, u8 mask, | ||
| 30 | u8 val); | ||
| 31 | |||
| 32 | int mgb4_i2c_configure(struct mgb4_i2c_client *client, | ||
| 33 | const struct mgb4_i2c_kv *values, size_t count); | ||
| 34 | |||
| 35 | #endif | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_IO_H__ | ||
| 8 | #define __MGB4_IO_H__ | ||
| 9 | |||
| 10 | #include <media/v4l2-dev.h> | ||
| 11 | |||
| 12 | #define MGB4_DEFAULT_WIDTH 1280 | ||
| 13 | #define MGB4_DEFAULT_HEIGHT 640 | ||
| 14 | #define MGB4_DEFAULT_PERIOD (125000000 / 60) | ||
| 15 | |||
| 16 | /* Register access error indication */ | ||
| 17 | #define MGB4_ERR_NO_REG 0xFFFFFFFE | ||
| 18 | /* Frame buffer addresses greater than 0xFFFFFFFA indicate HW errors */ | ||
| 19 | #define MGB4_ERR_QUEUE_TIMEOUT 0xFFFFFFFD | ||
| 20 | #define MGB4_ERR_QUEUE_EMPTY 0xFFFFFFFC | ||
| 21 | #define MGB4_ERR_QUEUE_FULL 0xFFFFFFFB | ||
| 22 | |||
| 23 | struct mgb4_frame_buffer { | ||
| 24 | struct vb2_v4l2_buffer vb; | ||
| 25 | struct list_head list; | ||
| 26 | }; | ||
| 27 | |||
| 28 | static inline struct mgb4_frame_buffer *to_frame_buffer(struct vb2_v4l2_buffer *vbuf) | ||
| 29 | { | ||
| 30 | return container_of(vbuf, struct mgb4_frame_buffer, vb); | ||
| 31 | } | ||
| 32 | |||
| 33 | #endif | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/ioport.h> | ||
| 8 | #include "mgb4_regs.h" | ||
| 9 | |||
| 10 | int mgb4_regs_map(struct resource *res, struct mgb4_regs *regs) | ||
| 11 | { | ||
| 12 | regs->mapbase = res->start; | ||
| 13 | regs->mapsize = res->end - res->start; | ||
| 14 | |||
| 15 | if (!request_mem_region(regs->mapbase, regs->mapsize, res->name)) | ||
| 16 | return -EINVAL; | ||
| 17 | regs->membase = ioremap(regs->mapbase, regs->mapsize); | ||
| 18 | if (!regs->membase) { | ||
| 19 | release_mem_region(regs->mapbase, regs->mapsize); | ||
| 20 | return -EINVAL; | ||
| 21 | } | ||
| 22 | |||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | void mgb4_regs_free(struct mgb4_regs *regs) | ||
| 27 | { | ||
| 28 | iounmap(regs->membase); | ||
| 29 | release_mem_region(regs->mapbase, regs->mapsize); | ||
| 30 | } | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_REGS_H__ | ||
| 8 | #define __MGB4_REGS_H__ | ||
| 9 | |||
| 10 | #include <linux/io.h> | ||
| 11 | |||
| 12 | struct mgb4_regs { | ||
| 13 | resource_size_t mapbase; | ||
| 14 | resource_size_t mapsize; | ||
| 15 | void __iomem *membase; | ||
| 16 | }; | ||
| 17 | |||
| 18 | #define mgb4_write_reg(regs, offset, val) \ | ||
| 19 | iowrite32(val, (regs)->membase + (offset)) | ||
| 20 | #define mgb4_read_reg(regs, offset) \ | ||
| 21 | ioread32((regs)->membase + (offset)) | ||
| 22 | |||
| 23 | static inline void mgb4_mask_reg(struct mgb4_regs *regs, u32 reg, u32 mask, | ||
| 24 | u32 val) | ||
| 25 | { | ||
| 26 | u32 ret = mgb4_read_reg(regs, reg); | ||
| 27 | |||
| 28 | val |= ret & ~mask; | ||
| 29 | mgb4_write_reg(regs, reg, val); | ||
| 30 | } | ||
| 31 | |||
| 32 | int mgb4_regs_map(struct resource *res, struct mgb4_regs *regs); | ||
| 33 | void mgb4_regs_free(struct mgb4_regs *regs); | ||
| 34 | |||
| 35 | #endif | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __MGB4_SYSFS_H__ | ||
| 8 | #define __MGB4_SYSFS_H__ | ||
| 9 | |||
| 10 | #include <linux/sysfs.h> | ||
| 11 | |||
| 12 | extern struct attribute *mgb4_pci_attrs[]; | ||
| 13 | extern struct attribute *mgb4_fpdl3_in_attrs[]; | ||
| 14 | extern struct attribute *mgb4_gmsl_in_attrs[]; | ||
| 15 | extern struct attribute *mgb4_fpdl3_out_attrs[]; | ||
| 16 | extern struct attribute *mgb4_gmsl_out_attrs[]; | ||
| 17 | |||
| 18 | #endif | ||
| @@ -0,0 +1,772 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This module handles all the sysfs info/configuration that is related to the | ||
| 7 | * v4l2 input devices. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/device.h> | ||
| 11 | #include "mgb4_core.h" | ||
| 12 | #include "mgb4_i2c.h" | ||
| 13 | #include "mgb4_vin.h" | ||
| 14 | #include "mgb4_cmt.h" | ||
| 15 | #include "mgb4_sysfs.h" | ||
| 16 | |||
| 17 | /* Common for both FPDL3 and GMSL */ | ||
| 18 | |||
| 19 | static ssize_t input_id_show(struct device *dev, | ||
| 20 | struct device_attribute *attr, char *buf) | ||
| 21 | { | ||
| 22 | struct video_device *vdev = to_video_device(dev); | ||
| 23 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 24 | |||
| 25 | return sprintf(buf, "%d\n", vindev->config->id); | ||
| 26 | } | ||
| 27 | |||
| 28 | static ssize_t oldi_lane_width_show(struct device *dev, | ||
| 29 | struct device_attribute *attr, char *buf) | ||
| 30 | { | ||
| 31 | struct video_device *vdev = to_video_device(dev); | ||
| 32 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 33 | struct mgb4_dev *mgbdev = vindev->mgbdev; | ||
| 34 | u16 i2c_reg; | ||
| 35 | u8 i2c_mask, i2c_single_val, i2c_dual_val; | ||
| 36 | u32 config; | ||
| 37 | int ret; | ||
| 38 | |||
| 39 | i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49; | ||
| 40 | i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03; | ||
| 41 | i2c_single_val = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02; | ||
| 42 | i2c_dual_val = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00; | ||
| 43 | |||
| 44 | mutex_lock(&mgbdev->i2c_lock); | ||
| 45 | ret = mgb4_i2c_read_byte(&vindev->deser, i2c_reg); | ||
| 46 | mutex_unlock(&mgbdev->i2c_lock); | ||
| 47 | if (ret < 0) | ||
| 48 | return -EIO; | ||
| 49 | |||
| 50 | config = mgb4_read_reg(&mgbdev->video, vindev->config->regs.config); | ||
| 51 | |||
| 52 | if (((config & (1U << 9)) && ((ret & i2c_mask) != i2c_dual_val)) || | ||
| 53 | (!(config & (1U << 9)) && ((ret & i2c_mask) != i2c_single_val))) { | ||
| 54 | dev_err(dev, "I2C/FPGA register value mismatch\n"); | ||
| 55 | return -EINVAL; | ||
| 56 | } | ||
| 57 | |||
| 58 | return sprintf(buf, "%s\n", config & (1U << 9) ? "1" : "0"); | ||
| 59 | } | ||
| 60 | |||
| 61 | /* | ||
| 62 | * OLDI lane width change is expected to be called on live streams. Video device | ||
| 63 | * locking/queue check is not needed. | ||
| 64 | */ | ||
| 65 | static ssize_t oldi_lane_width_store(struct device *dev, | ||
| 66 | struct device_attribute *attr, | ||
| 67 | const char *buf, size_t count) | ||
| 68 | { | ||
| 69 | struct video_device *vdev = to_video_device(dev); | ||
| 70 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 71 | struct mgb4_dev *mgbdev = vindev->mgbdev; | ||
| 72 | u32 fpga_data; | ||
| 73 | u16 i2c_reg; | ||
| 74 | u8 i2c_mask, i2c_data; | ||
| 75 | unsigned long val; | ||
| 76 | int ret; | ||
| 77 | |||
| 78 | ret = kstrtoul(buf, 10, &val); | ||
| 79 | if (ret) | ||
| 80 | return ret; | ||
| 81 | |||
| 82 | switch (val) { | ||
| 83 | case 0: /* single */ | ||
| 84 | fpga_data = 0; | ||
| 85 | i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02; | ||
| 86 | break; | ||
| 87 | case 1: /* dual */ | ||
| 88 | fpga_data = 1U << 9; | ||
| 89 | i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00; | ||
| 90 | break; | ||
| 91 | default: | ||
| 92 | return -EINVAL; | ||
| 93 | } | ||
| 94 | |||
| 95 | i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49; | ||
| 96 | i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03; | ||
| 97 | |||
| 98 | mutex_lock(&mgbdev->i2c_lock); | ||
| 99 | ret = mgb4_i2c_mask_byte(&vindev->deser, i2c_reg, i2c_mask, i2c_data); | ||
| 100 | mutex_unlock(&mgbdev->i2c_lock); | ||
| 101 | if (ret < 0) | ||
| 102 | return -EIO; | ||
| 103 | mgb4_mask_reg(&mgbdev->video, vindev->config->regs.config, 1U << 9, | ||
| 104 | fpga_data); | ||
| 105 | if (MGB4_IS_GMSL(mgbdev)) { | ||
| 106 | /* reset input link */ | ||
| 107 | mutex_lock(&mgbdev->i2c_lock); | ||
| 108 | ret = mgb4_i2c_mask_byte(&vindev->deser, 0x10, 1U << 5, 1U << 5); | ||
| 109 | mutex_unlock(&mgbdev->i2c_lock); | ||
| 110 | if (ret < 0) | ||
| 111 | return -EIO; | ||
| 112 | } | ||
| 113 | |||
| 114 | return count; | ||
| 115 | } | ||
| 116 | |||
| 117 | static ssize_t color_mapping_show(struct device *dev, | ||
| 118 | struct device_attribute *attr, char *buf) | ||
| 119 | { | ||
| 120 | struct video_device *vdev = to_video_device(dev); | ||
| 121 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 122 | u32 config = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 123 | vindev->config->regs.config); | ||
| 124 | |||
| 125 | return sprintf(buf, "%s\n", config & (1U << 8) ? "0" : "1"); | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Color mapping change is expected to be called on live streams. Video device | ||
| 130 | * locking/queue check is not needed. | ||
| 131 | */ | ||
| 132 | static ssize_t color_mapping_store(struct device *dev, | ||
| 133 | struct device_attribute *attr, | ||
| 134 | const char *buf, size_t count) | ||
| 135 | { | ||
| 136 | struct video_device *vdev = to_video_device(dev); | ||
| 137 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 138 | u32 fpga_data; | ||
| 139 | unsigned long val; | ||
| 140 | int ret; | ||
| 141 | |||
| 142 | ret = kstrtoul(buf, 10, &val); | ||
| 143 | if (ret) | ||
| 144 | return ret; | ||
| 145 | |||
| 146 | switch (val) { | ||
| 147 | case 0: /* OLDI/JEIDA */ | ||
| 148 | fpga_data = (1U << 8); | ||
| 149 | break; | ||
| 150 | case 1: /* SPWG/VESA */ | ||
| 151 | fpga_data = 0; | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | return -EINVAL; | ||
| 155 | } | ||
| 156 | |||
| 157 | mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.config, | ||
| 158 | 1U << 8, fpga_data); | ||
| 159 | |||
| 160 | return count; | ||
| 161 | } | ||
| 162 | |||
| 163 | static ssize_t link_status_show(struct device *dev, | ||
| 164 | struct device_attribute *attr, char *buf) | ||
| 165 | { | ||
| 166 | struct video_device *vdev = to_video_device(dev); | ||
| 167 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 168 | u32 status = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 169 | vindev->config->regs.status); | ||
| 170 | |||
| 171 | return sprintf(buf, "%s\n", status & (1U << 2) ? "1" : "0"); | ||
| 172 | } | ||
| 173 | |||
| 174 | static ssize_t stream_status_show(struct device *dev, | ||
| 175 | struct device_attribute *attr, char *buf) | ||
| 176 | { | ||
| 177 | struct video_device *vdev = to_video_device(dev); | ||
| 178 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 179 | u32 status = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 180 | vindev->config->regs.status); | ||
| 181 | |||
| 182 | return sprintf(buf, "%s\n", ((status & (1 << 14)) && | ||
| 183 | (status & (1 << 2)) && (status & (3 << 9))) ? "1" : "0"); | ||
| 184 | } | ||
| 185 | |||
| 186 | static ssize_t video_width_show(struct device *dev, | ||
| 187 | struct device_attribute *attr, char *buf) | ||
| 188 | { | ||
| 189 | struct video_device *vdev = to_video_device(dev); | ||
| 190 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 191 | u32 config = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 192 | vindev->config->regs.resolution); | ||
| 193 | |||
| 194 | return sprintf(buf, "%u\n", config >> 16); | ||
| 195 | } | ||
| 196 | |||
| 197 | static ssize_t video_height_show(struct device *dev, | ||
| 198 | struct device_attribute *attr, char *buf) | ||
| 199 | { | ||
| 200 | struct video_device *vdev = to_video_device(dev); | ||
| 201 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 202 | u32 config = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 203 | vindev->config->regs.resolution); | ||
| 204 | |||
| 205 | return sprintf(buf, "%u\n", config & 0xFFFF); | ||
| 206 | } | ||
| 207 | |||
| 208 | static ssize_t hsync_status_show(struct device *dev, | ||
| 209 | struct device_attribute *attr, char *buf) | ||
| 210 | { | ||
| 211 | struct video_device *vdev = to_video_device(dev); | ||
| 212 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 213 | u32 status = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 214 | vindev->config->regs.status); | ||
| 215 | u32 res; | ||
| 216 | |||
| 217 | if (!(status & (1U << 11))) | ||
| 218 | res = 0x02; // not available | ||
| 219 | else if (status & (1U << 12)) | ||
| 220 | res = 0x01; // active high | ||
| 221 | else | ||
| 222 | res = 0x00; // active low | ||
| 223 | |||
| 224 | return sprintf(buf, "%u\n", res); | ||
| 225 | } | ||
| 226 | |||
| 227 | static ssize_t vsync_status_show(struct device *dev, | ||
| 228 | struct device_attribute *attr, char *buf) | ||
| 229 | { | ||
| 230 | struct video_device *vdev = to_video_device(dev); | ||
| 231 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 232 | u32 status = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 233 | vindev->config->regs.status); | ||
| 234 | u32 res; | ||
| 235 | |||
| 236 | if (!(status & (1U << 11))) | ||
| 237 | res = 0x02; // not available | ||
| 238 | else if (status & (1U << 13)) | ||
| 239 | res = 0x01; // active high | ||
| 240 | else | ||
| 241 | res = 0x00; // active low | ||
| 242 | |||
| 243 | return sprintf(buf, "%u\n", res); | ||
| 244 | } | ||
| 245 | |||
| 246 | static ssize_t hsync_gap_length_show(struct device *dev, | ||
| 247 | struct device_attribute *attr, | ||
| 248 | char *buf) | ||
| 249 | { | ||
| 250 | struct video_device *vdev = to_video_device(dev); | ||
| 251 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 252 | u32 sync = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 253 | vindev->config->regs.sync); | ||
| 254 | |||
| 255 | return sprintf(buf, "%u\n", sync >> 16); | ||
| 256 | } | ||
| 257 | |||
| 258 | /* | ||
| 259 | * HSYNC gap length change is expected to be called on live streams. Video | ||
| 260 | * device locking/queue check is not needed. | ||
| 261 | */ | ||
| 262 | static ssize_t hsync_gap_length_store(struct device *dev, | ||
| 263 | struct device_attribute *attr, | ||
| 264 | const char *buf, size_t count) | ||
| 265 | { | ||
| 266 | struct video_device *vdev = to_video_device(dev); | ||
| 267 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 268 | unsigned long val; | ||
| 269 | int ret; | ||
| 270 | |||
| 271 | ret = kstrtoul(buf, 10, &val); | ||
| 272 | if (ret) | ||
| 273 | return ret; | ||
| 274 | if (val > 0xFFFF) | ||
| 275 | return -EINVAL; | ||
| 276 | |||
| 277 | mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync, | ||
| 278 | 0xFFFF0000, val << 16); | ||
| 279 | |||
| 280 | return count; | ||
| 281 | } | ||
| 282 | |||
| 283 | static ssize_t vsync_gap_length_show(struct device *dev, | ||
| 284 | struct device_attribute *attr, char *buf) | ||
| 285 | { | ||
| 286 | struct video_device *vdev = to_video_device(dev); | ||
| 287 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 288 | u32 sync = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 289 | vindev->config->regs.sync); | ||
| 290 | |||
| 291 | return sprintf(buf, "%u\n", sync & 0xFFFF); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * VSYNC gap length change is expected to be called on live streams. Video | ||
| 296 | * device locking/queue check is not needed. | ||
| 297 | */ | ||
| 298 | static ssize_t vsync_gap_length_store(struct device *dev, | ||
| 299 | struct device_attribute *attr, | ||
| 300 | const char *buf, size_t count) | ||
| 301 | { | ||
| 302 | struct video_device *vdev = to_video_device(dev); | ||
| 303 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 304 | unsigned long val; | ||
| 305 | int ret; | ||
| 306 | |||
| 307 | ret = kstrtoul(buf, 10, &val); | ||
| 308 | if (ret) | ||
| 309 | return ret; | ||
| 310 | if (val > 0xFFFF) | ||
| 311 | return -EINVAL; | ||
| 312 | |||
| 313 | mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync, 0xFFFF, | ||
| 314 | val); | ||
| 315 | |||
| 316 | return count; | ||
| 317 | } | ||
| 318 | |||
| 319 | static ssize_t pclk_frequency_show(struct device *dev, | ||
| 320 | struct device_attribute *attr, char *buf) | ||
| 321 | { | ||
| 322 | struct video_device *vdev = to_video_device(dev); | ||
| 323 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 324 | u32 freq = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 325 | vindev->config->regs.pclk); | ||
| 326 | |||
| 327 | return sprintf(buf, "%u\n", freq); | ||
| 328 | } | ||
| 329 | |||
| 330 | static ssize_t hsync_width_show(struct device *dev, | ||
| 331 | struct device_attribute *attr, char *buf) | ||
| 332 | { | ||
| 333 | struct video_device *vdev = to_video_device(dev); | ||
| 334 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 335 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 336 | vindev->config->regs.signal); | ||
| 337 | |||
| 338 | return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); | ||
| 339 | } | ||
| 340 | |||
| 341 | static ssize_t vsync_width_show(struct device *dev, | ||
| 342 | struct device_attribute *attr, char *buf) | ||
| 343 | { | ||
| 344 | struct video_device *vdev = to_video_device(dev); | ||
| 345 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 346 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 347 | vindev->config->regs.signal2); | ||
| 348 | |||
| 349 | return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); | ||
| 350 | } | ||
| 351 | |||
| 352 | static ssize_t hback_porch_show(struct device *dev, | ||
| 353 | struct device_attribute *attr, char *buf) | ||
| 354 | { | ||
| 355 | struct video_device *vdev = to_video_device(dev); | ||
| 356 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 357 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 358 | vindev->config->regs.signal); | ||
| 359 | |||
| 360 | return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); | ||
| 361 | } | ||
| 362 | |||
| 363 | static ssize_t hfront_porch_show(struct device *dev, | ||
| 364 | struct device_attribute *attr, char *buf) | ||
| 365 | { | ||
| 366 | struct video_device *vdev = to_video_device(dev); | ||
| 367 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 368 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 369 | vindev->config->regs.signal); | ||
| 370 | |||
| 371 | return sprintf(buf, "%u\n", (sig & 0x000000FF)); | ||
| 372 | } | ||
| 373 | |||
| 374 | static ssize_t vback_porch_show(struct device *dev, | ||
| 375 | struct device_attribute *attr, char *buf) | ||
| 376 | { | ||
| 377 | struct video_device *vdev = to_video_device(dev); | ||
| 378 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 379 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 380 | vindev->config->regs.signal2); | ||
| 381 | |||
| 382 | return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); | ||
| 383 | } | ||
| 384 | |||
| 385 | static ssize_t vfront_porch_show(struct device *dev, | ||
| 386 | struct device_attribute *attr, char *buf) | ||
| 387 | { | ||
| 388 | struct video_device *vdev = to_video_device(dev); | ||
| 389 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 390 | u32 sig = mgb4_read_reg(&vindev->mgbdev->video, | ||
| 391 | vindev->config->regs.signal2); | ||
| 392 | |||
| 393 | return sprintf(buf, "%u\n", (sig & 0x000000FF)); | ||
| 394 | } | ||
| 395 | |||
| 396 | static ssize_t frequency_range_show(struct device *dev, | ||
| 397 | struct device_attribute *attr, char *buf) | ||
| 398 | { | ||
| 399 | struct video_device *vdev = to_video_device(dev); | ||
| 400 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 401 | |||
| 402 | return sprintf(buf, "%d\n", vindev->freq_range); | ||
| 403 | } | ||
| 404 | |||
| 405 | static ssize_t frequency_range_store(struct device *dev, | ||
| 406 | struct device_attribute *attr, | ||
| 407 | const char *buf, size_t count) | ||
| 408 | { | ||
| 409 | struct video_device *vdev = to_video_device(dev); | ||
| 410 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 411 | unsigned long val; | ||
| 412 | int ret; | ||
| 413 | |||
| 414 | ret = kstrtoul(buf, 10, &val); | ||
| 415 | if (ret) | ||
| 416 | return ret; | ||
| 417 | if (val > 1) | ||
| 418 | return -EINVAL; | ||
| 419 | |||
| 420 | mutex_lock(vindev->vdev.lock); | ||
| 421 | if (vb2_is_busy(vindev->vdev.queue)) { | ||
| 422 | mutex_unlock(vindev->vdev.lock); | ||
| 423 | return -EBUSY; | ||
| 424 | } | ||
| 425 | |||
| 426 | mgb4_cmt_set_vin_freq_range(vindev, val); | ||
| 427 | vindev->freq_range = val; | ||
| 428 | |||
| 429 | mutex_unlock(vindev->vdev.lock); | ||
| 430 | |||
| 431 | return count; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* FPDL3 only */ | ||
| 435 | |||
| 436 | static ssize_t fpdl3_input_width_show(struct device *dev, | ||
| 437 | struct device_attribute *attr, char *buf) | ||
| 438 | { | ||
| 439 | struct video_device *vdev = to_video_device(dev); | ||
| 440 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 441 | s32 ret; | ||
| 442 | |||
| 443 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 444 | ret = mgb4_i2c_read_byte(&vindev->deser, 0x34); | ||
| 445 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 446 | if (ret < 0) | ||
| 447 | return -EIO; | ||
| 448 | |||
| 449 | switch ((u8)ret & 0x18) { | ||
| 450 | case 0: | ||
| 451 | return sprintf(buf, "0\n"); | ||
| 452 | case 0x10: | ||
| 453 | return sprintf(buf, "1\n"); | ||
| 454 | case 0x08: | ||
| 455 | return sprintf(buf, "2\n"); | ||
| 456 | default: | ||
| 457 | return -EINVAL; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | /* | ||
| 462 | * FPD-Link width change is expected to be called on live streams. Video device | ||
| 463 | * locking/queue check is not needed. | ||
| 464 | */ | ||
| 465 | static ssize_t fpdl3_input_width_store(struct device *dev, | ||
| 466 | struct device_attribute *attr, | ||
| 467 | const char *buf, size_t count) | ||
| 468 | { | ||
| 469 | struct video_device *vdev = to_video_device(dev); | ||
| 470 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 471 | u8 i2c_data; | ||
| 472 | unsigned long val; | ||
| 473 | int ret; | ||
| 474 | |||
| 475 | ret = kstrtoul(buf, 10, &val); | ||
| 476 | if (ret) | ||
| 477 | return ret; | ||
| 478 | |||
| 479 | switch (val) { | ||
| 480 | case 0: /* auto */ | ||
| 481 | i2c_data = 0x00; | ||
| 482 | break; | ||
| 483 | case 1: /* single */ | ||
| 484 | i2c_data = 0x10; | ||
| 485 | break; | ||
| 486 | case 2: /* dual */ | ||
| 487 | i2c_data = 0x08; | ||
| 488 | break; | ||
| 489 | default: | ||
| 490 | return -EINVAL; | ||
| 491 | } | ||
| 492 | |||
| 493 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 494 | ret = mgb4_i2c_mask_byte(&vindev->deser, 0x34, 0x18, i2c_data); | ||
| 495 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 496 | if (ret < 0) | ||
| 497 | return -EIO; | ||
| 498 | |||
| 499 | return count; | ||
| 500 | } | ||
| 501 | |||
| 502 | /* GMSL only */ | ||
| 503 | |||
| 504 | static ssize_t gmsl_mode_show(struct device *dev, | ||
| 505 | struct device_attribute *attr, char *buf) | ||
| 506 | { | ||
| 507 | struct video_device *vdev = to_video_device(dev); | ||
| 508 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 509 | s32 r1, r300, r3; | ||
| 510 | |||
| 511 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 512 | r1 = mgb4_i2c_read_byte(&vindev->deser, 0x01); | ||
| 513 | r300 = mgb4_i2c_read_byte(&vindev->deser, 0x300); | ||
| 514 | r3 = mgb4_i2c_read_byte(&vindev->deser, 0x03); | ||
| 515 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 516 | if (r1 < 0 || r300 < 0 || r3 < 0) | ||
| 517 | return -EIO; | ||
| 518 | |||
| 519 | if ((r1 & 0x03) == 0x03 && (r300 & 0x0C) == 0x0C && (r3 & 0xC0) == 0xC0) | ||
| 520 | return sprintf(buf, "0\n"); | ||
| 521 | else if ((r1 & 0x03) == 0x02 && (r300 & 0x0C) == 0x08 && (r3 & 0xC0) == 0x00) | ||
| 522 | return sprintf(buf, "1\n"); | ||
| 523 | else if ((r1 & 0x03) == 0x01 && (r300 & 0x0C) == 0x04 && (r3 & 0xC0) == 0x00) | ||
| 524 | return sprintf(buf, "2\n"); | ||
| 525 | else if ((r1 & 0x03) == 0x00 && (r300 & 0x0C) == 0x00 && (r3 & 0xC0) == 0x00) | ||
| 526 | return sprintf(buf, "3\n"); | ||
| 527 | else | ||
| 528 | return -EINVAL; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* | ||
| 532 | * GMSL mode change is expected to be called on live streams. Video device | ||
| 533 | * locking/queue check is not needed. | ||
| 534 | */ | ||
| 535 | static ssize_t gmsl_mode_store(struct device *dev, | ||
| 536 | struct device_attribute *attr, const char *buf, | ||
| 537 | size_t count) | ||
| 538 | { | ||
| 539 | static const struct mgb4_i2c_kv G12[] = { | ||
| 540 | {0x01, 0x03, 0x03}, {0x300, 0x0C, 0x0C}, {0x03, 0xC0, 0xC0}}; | ||
| 541 | static const struct mgb4_i2c_kv G6[] = { | ||
| 542 | {0x01, 0x03, 0x02}, {0x300, 0x0C, 0x08}, {0x03, 0xC0, 0x00}}; | ||
| 543 | static const struct mgb4_i2c_kv G3[] = { | ||
| 544 | {0x01, 0x03, 0x01}, {0x300, 0x0C, 0x04}, {0x03, 0xC0, 0x00}}; | ||
| 545 | static const struct mgb4_i2c_kv G1[] = { | ||
| 546 | {0x01, 0x03, 0x00}, {0x300, 0x0C, 0x00}, {0x03, 0xC0, 0x00}}; | ||
| 547 | static const struct mgb4_i2c_kv reset[] = { | ||
| 548 | {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}}; | ||
| 549 | struct video_device *vdev = to_video_device(dev); | ||
| 550 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 551 | const struct mgb4_i2c_kv *values; | ||
| 552 | unsigned long val; | ||
| 553 | int ret; | ||
| 554 | |||
| 555 | ret = kstrtoul(buf, 10, &val); | ||
| 556 | if (ret) | ||
| 557 | return ret; | ||
| 558 | |||
| 559 | switch (val) { | ||
| 560 | case 0: /* 12Gb/s */ | ||
| 561 | values = G12; | ||
| 562 | break; | ||
| 563 | case 1: /* 6Gb/s */ | ||
| 564 | values = G6; | ||
| 565 | break; | ||
| 566 | case 2: /* 3Gb/s */ | ||
| 567 | values = G3; | ||
| 568 | break; | ||
| 569 | case 3: /* 1.5Gb/s */ | ||
| 570 | values = G1; | ||
| 571 | break; | ||
| 572 | default: | ||
| 573 | return -EINVAL; | ||
| 574 | } | ||
| 575 | |||
| 576 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 577 | ret = mgb4_i2c_configure(&vindev->deser, values, 3); | ||
| 578 | ret |= mgb4_i2c_configure(&vindev->deser, reset, 2); | ||
| 579 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 580 | if (ret < 0) | ||
| 581 | return -EIO; | ||
| 582 | |||
| 583 | return count; | ||
| 584 | } | ||
| 585 | |||
| 586 | static ssize_t gmsl_stream_id_show(struct device *dev, | ||
| 587 | struct device_attribute *attr, char *buf) | ||
| 588 | { | ||
| 589 | struct video_device *vdev = to_video_device(dev); | ||
| 590 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 591 | s32 ret; | ||
| 592 | |||
| 593 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 594 | ret = mgb4_i2c_read_byte(&vindev->deser, 0xA0); | ||
| 595 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 596 | if (ret < 0) | ||
| 597 | return -EIO; | ||
| 598 | |||
| 599 | return sprintf(buf, "%d\n", ret & 0x03); | ||
| 600 | } | ||
| 601 | |||
| 602 | static ssize_t gmsl_stream_id_store(struct device *dev, | ||
| 603 | struct device_attribute *attr, | ||
| 604 | const char *buf, size_t count) | ||
| 605 | { | ||
| 606 | struct video_device *vdev = to_video_device(dev); | ||
| 607 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 608 | unsigned long val; | ||
| 609 | int ret; | ||
| 610 | |||
| 611 | ret = kstrtoul(buf, 10, &val); | ||
| 612 | if (ret) | ||
| 613 | return ret; | ||
| 614 | if (val > 3) | ||
| 615 | return -EINVAL; | ||
| 616 | |||
| 617 | mutex_lock(vindev->vdev.lock); | ||
| 618 | if (vb2_is_busy(vindev->vdev.queue)) { | ||
| 619 | mutex_unlock(vindev->vdev.lock); | ||
| 620 | return -EBUSY; | ||
| 621 | } | ||
| 622 | |||
| 623 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 624 | ret = mgb4_i2c_mask_byte(&vindev->deser, 0xA0, 0x03, (u8)val); | ||
| 625 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 626 | |||
| 627 | mutex_unlock(vindev->vdev.lock); | ||
| 628 | |||
| 629 | return (ret < 0) ? -EIO : count; | ||
| 630 | } | ||
| 631 | |||
| 632 | static ssize_t gmsl_fec_show(struct device *dev, struct device_attribute *attr, | ||
| 633 | char *buf) | ||
| 634 | { | ||
| 635 | struct video_device *vdev = to_video_device(dev); | ||
| 636 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 637 | s32 r3e0, r308; | ||
| 638 | |||
| 639 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 640 | r3e0 = mgb4_i2c_read_byte(&vindev->deser, 0x3E0); | ||
| 641 | r308 = mgb4_i2c_read_byte(&vindev->deser, 0x308); | ||
| 642 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 643 | if (r3e0 < 0 || r308 < 0) | ||
| 644 | return -EIO; | ||
| 645 | |||
| 646 | if ((r3e0 & 0x07) == 0x00 && (r308 & 0x01) == 0x00) | ||
| 647 | return sprintf(buf, "0\n"); | ||
| 648 | else if ((r3e0 & 0x07) == 0x07 && (r308 & 0x01) == 0x01) | ||
| 649 | return sprintf(buf, "1\n"); | ||
| 650 | else | ||
| 651 | return -EINVAL; | ||
| 652 | } | ||
| 653 | |||
| 654 | /* | ||
| 655 | * GMSL FEC change is expected to be called on live streams. Video device | ||
| 656 | * locking/queue check is not needed. | ||
| 657 | */ | ||
| 658 | static ssize_t gmsl_fec_store(struct device *dev, struct device_attribute *attr, | ||
| 659 | const char *buf, size_t count) | ||
| 660 | { | ||
| 661 | struct video_device *vdev = to_video_device(dev); | ||
| 662 | struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); | ||
| 663 | static const struct mgb4_i2c_kv enable[] = { | ||
| 664 | {0x3E0, 0x07, 0x07}, {0x308, 0x01, 0x01}}; | ||
| 665 | static const struct mgb4_i2c_kv disable[] = { | ||
| 666 | {0x3E0, 0x07, 0x00}, {0x308, 0x01, 0x00}}; | ||
| 667 | static const struct mgb4_i2c_kv reset[] = { | ||
| 668 | {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}}; | ||
| 669 | const struct mgb4_i2c_kv *values; | ||
| 670 | unsigned long val; | ||
| 671 | int ret; | ||
| 672 | |||
| 673 | ret = kstrtoul(buf, 10, &val); | ||
| 674 | if (ret) | ||
| 675 | return ret; | ||
| 676 | |||
| 677 | switch (val) { | ||
| 678 | case 0: /* disabled */ | ||
| 679 | values = disable; | ||
| 680 | break; | ||
| 681 | case 1: /* enabled */ | ||
| 682 | values = enable; | ||
| 683 | break; | ||
| 684 | default: | ||
| 685 | return -EINVAL; | ||
| 686 | } | ||
| 687 | |||
| 688 | mutex_lock(&vindev->mgbdev->i2c_lock); | ||
| 689 | ret = mgb4_i2c_configure(&vindev->deser, values, 2); | ||
| 690 | ret |= mgb4_i2c_configure(&vindev->deser, reset, 2); | ||
| 691 | mutex_unlock(&vindev->mgbdev->i2c_lock); | ||
| 692 | if (ret < 0) | ||
| 693 | return -EIO; | ||
| 694 | |||
| 695 | return count; | ||
| 696 | } | ||
| 697 | |||
| 698 | static DEVICE_ATTR_RO(input_id); | ||
| 699 | static DEVICE_ATTR_RW(oldi_lane_width); | ||
| 700 | static DEVICE_ATTR_RW(color_mapping); | ||
| 701 | static DEVICE_ATTR_RO(link_status); | ||
| 702 | static DEVICE_ATTR_RO(stream_status); | ||
| 703 | static DEVICE_ATTR_RO(video_width); | ||
| 704 | static DEVICE_ATTR_RO(video_height); | ||
| 705 | static DEVICE_ATTR_RO(hsync_status); | ||
| 706 | static DEVICE_ATTR_RO(vsync_status); | ||
| 707 | static DEVICE_ATTR_RW(hsync_gap_length); | ||
| 708 | static DEVICE_ATTR_RW(vsync_gap_length); | ||
| 709 | static DEVICE_ATTR_RO(pclk_frequency); | ||
| 710 | static DEVICE_ATTR_RO(hsync_width); | ||
| 711 | static DEVICE_ATTR_RO(vsync_width); | ||
| 712 | static DEVICE_ATTR_RO(hback_porch); | ||
| 713 | static DEVICE_ATTR_RO(hfront_porch); | ||
| 714 | static DEVICE_ATTR_RO(vback_porch); | ||
| 715 | static DEVICE_ATTR_RO(vfront_porch); | ||
| 716 | static DEVICE_ATTR_RW(frequency_range); | ||
| 717 | |||
| 718 | static DEVICE_ATTR_RW(fpdl3_input_width); | ||
| 719 | |||
| 720 | static DEVICE_ATTR_RW(gmsl_mode); | ||
| 721 | static DEVICE_ATTR_RW(gmsl_stream_id); | ||
| 722 | static DEVICE_ATTR_RW(gmsl_fec); | ||
| 723 | |||
| 724 | struct attribute *mgb4_fpdl3_in_attrs[] = { | ||
| 725 | &dev_attr_input_id.attr, | ||
| 726 | &dev_attr_link_status.attr, | ||
| 727 | &dev_attr_stream_status.attr, | ||
| 728 | &dev_attr_video_width.attr, | ||
| 729 | &dev_attr_video_height.attr, | ||
| 730 | &dev_attr_hsync_status.attr, | ||
| 731 | &dev_attr_vsync_status.attr, | ||
| 732 | &dev_attr_oldi_lane_width.attr, | ||
| 733 | &dev_attr_color_mapping.attr, | ||
| 734 | &dev_attr_hsync_gap_length.attr, | ||
| 735 | &dev_attr_vsync_gap_length.attr, | ||
| 736 | &dev_attr_pclk_frequency.attr, | ||
| 737 | &dev_attr_hsync_width.attr, | ||
| 738 | &dev_attr_vsync_width.attr, | ||
| 739 | &dev_attr_hback_porch.attr, | ||
| 740 | &dev_attr_hfront_porch.attr, | ||
| 741 | &dev_attr_vback_porch.attr, | ||
| 742 | &dev_attr_vfront_porch.attr, | ||
| 743 | &dev_attr_frequency_range.attr, | ||
| 744 | &dev_attr_fpdl3_input_width.attr, | ||
| 745 | NULL | ||
| 746 | }; | ||
| 747 | |||
| 748 | struct attribute *mgb4_gmsl_in_attrs[] = { | ||
| 749 | &dev_attr_input_id.attr, | ||
| 750 | &dev_attr_link_status.attr, | ||
| 751 | &dev_attr_stream_status.attr, | ||
| 752 | &dev_attr_video_width.attr, | ||
| 753 | &dev_attr_video_height.attr, | ||
| 754 | &dev_attr_hsync_status.attr, | ||
| 755 | &dev_attr_vsync_status.attr, | ||
| 756 | &dev_attr_oldi_lane_width.attr, | ||
| 757 | &dev_attr_color_mapping.attr, | ||
| 758 | &dev_attr_hsync_gap_length.attr, | ||
| 759 | &dev_attr_vsync_gap_length.attr, | ||
| 760 | &dev_attr_pclk_frequency.attr, | ||
| 761 | &dev_attr_hsync_width.attr, | ||
| 762 | &dev_attr_vsync_width.attr, | ||
| 763 | &dev_attr_hback_porch.attr, | ||
| 764 | &dev_attr_hfront_porch.attr, | ||
| 765 | &dev_attr_vback_porch.attr, | ||
| 766 | &dev_attr_vfront_porch.attr, | ||
| 767 | &dev_attr_frequency_range.attr, | ||
| 768 | &dev_attr_gmsl_mode.attr, | ||
| 769 | &dev_attr_gmsl_stream_id.attr, | ||
| 770 | &dev_attr_gmsl_fec.attr, | ||
| 771 | NULL | ||
| 772 | }; | ||
| @@ -0,0 +1,740 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This module handles all the sysfs info/configuration that is related to the | ||
| 7 | * v4l2 output devices. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/device.h> | ||
| 11 | #include <linux/nospec.h> | ||
| 12 | #include "mgb4_core.h" | ||
| 13 | #include "mgb4_i2c.h" | ||
| 14 | #include "mgb4_vout.h" | ||
| 15 | #include "mgb4_vin.h" | ||
| 16 | #include "mgb4_cmt.h" | ||
| 17 | #include "mgb4_sysfs.h" | ||
| 18 | |||
| 19 | static int loopin_cnt(struct mgb4_vin_dev *vindev) | ||
| 20 | { | ||
| 21 | struct mgb4_vout_dev *voutdev; | ||
| 22 | u32 config; | ||
| 23 | int i, cnt = 0; | ||
| 24 | |||
| 25 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) { | ||
| 26 | voutdev = vindev->mgbdev->vout[i]; | ||
| 27 | if (!voutdev) | ||
| 28 | continue; | ||
| 29 | |||
| 30 | config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 31 | voutdev->config->regs.config); | ||
| 32 | if ((config & 0xc) >> 2 == vindev->config->id) | ||
| 33 | cnt++; | ||
| 34 | } | ||
| 35 | |||
| 36 | return cnt; | ||
| 37 | } | ||
| 38 | |||
| 39 | static bool is_busy(struct video_device *dev) | ||
| 40 | { | ||
| 41 | bool ret; | ||
| 42 | |||
| 43 | mutex_lock(dev->lock); | ||
| 44 | ret = vb2_is_busy(dev->queue); | ||
| 45 | mutex_unlock(dev->lock); | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* Common for both FPDL3 and GMSL */ | ||
| 51 | |||
| 52 | static ssize_t output_id_show(struct device *dev, | ||
| 53 | struct device_attribute *attr, char *buf) | ||
| 54 | { | ||
| 55 | struct video_device *vdev = to_video_device(dev); | ||
| 56 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 57 | |||
| 58 | return sprintf(buf, "%d\n", voutdev->config->id); | ||
| 59 | } | ||
| 60 | |||
| 61 | static ssize_t video_source_show(struct device *dev, | ||
| 62 | struct device_attribute *attr, char *buf) | ||
| 63 | { | ||
| 64 | struct video_device *vdev = to_video_device(dev); | ||
| 65 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 66 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 67 | voutdev->config->regs.config); | ||
| 68 | |||
| 69 | return sprintf(buf, "%u\n", (config & 0xc) >> 2); | ||
| 70 | } | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Video source change may affect the buffer queue of ANY video input/output on | ||
| 74 | * the card thus if any of the inputs/outputs is in use, we do not allow | ||
| 75 | * the change. | ||
| 76 | * | ||
| 77 | * As we do not want to lock all the video devices at the same time, a two-stage | ||
| 78 | * locking strategy is used. In addition to the video device locking there is | ||
| 79 | * a global (PCI device) variable "io_reconfig" atomically checked/set when | ||
| 80 | * the reconfiguration is running. All the video devices check the variable in | ||
| 81 | * their queue_setup() functions and do not allow to start the queue when | ||
| 82 | * the reconfiguration has started. | ||
| 83 | */ | ||
| 84 | static ssize_t video_source_store(struct device *dev, | ||
| 85 | struct device_attribute *attr, | ||
| 86 | const char *buf, size_t count) | ||
| 87 | { | ||
| 88 | struct video_device *vdev = to_video_device(dev); | ||
| 89 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 90 | struct mgb4_dev *mgbdev = voutdev->mgbdev; | ||
| 91 | struct mgb4_vin_dev *loopin_new = NULL, *loopin_old = NULL; | ||
| 92 | unsigned long val; | ||
| 93 | ssize_t ret; | ||
| 94 | u32 config; | ||
| 95 | int i; | ||
| 96 | |||
| 97 | ret = kstrtoul(buf, 10, &val); | ||
| 98 | if (ret) | ||
| 99 | return ret; | ||
| 100 | if (val > 3) | ||
| 101 | return -EINVAL; | ||
| 102 | |||
| 103 | if (test_and_set_bit(0, &mgbdev->io_reconfig)) | ||
| 104 | return -EBUSY; | ||
| 105 | |||
| 106 | ret = -EBUSY; | ||
| 107 | for (i = 0; i < MGB4_VIN_DEVICES; i++) | ||
| 108 | if (mgbdev->vin[i] && is_busy(&mgbdev->vin[i]->vdev)) | ||
| 109 | goto end; | ||
| 110 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) | ||
| 111 | if (mgbdev->vout[i] && is_busy(&mgbdev->vout[i]->vdev)) | ||
| 112 | goto end; | ||
| 113 | |||
| 114 | config = mgb4_read_reg(&mgbdev->video, voutdev->config->regs.config); | ||
| 115 | |||
| 116 | if (((config & 0xc) >> 2) < MGB4_VIN_DEVICES) | ||
| 117 | loopin_old = mgbdev->vin[(config & 0xc) >> 2]; | ||
| 118 | if (val < MGB4_VIN_DEVICES) { | ||
| 119 | val = array_index_nospec(val, MGB4_VIN_DEVICES); | ||
| 120 | loopin_new = mgbdev->vin[val]; | ||
| 121 | } | ||
| 122 | if (loopin_old && loopin_cnt(loopin_old) == 1) | ||
| 123 | mgb4_mask_reg(&mgbdev->video, loopin_old->config->regs.config, | ||
| 124 | 0x2, 0x0); | ||
| 125 | if (loopin_new) | ||
| 126 | mgb4_mask_reg(&mgbdev->video, loopin_new->config->regs.config, | ||
| 127 | 0x2, 0x2); | ||
| 128 | |||
| 129 | if (val == voutdev->config->id + MGB4_VIN_DEVICES) | ||
| 130 | mgb4_write_reg(&mgbdev->video, voutdev->config->regs.config, | ||
| 131 | config & ~(1 << 1)); | ||
| 132 | else | ||
| 133 | mgb4_write_reg(&mgbdev->video, voutdev->config->regs.config, | ||
| 134 | config | (1U << 1)); | ||
| 135 | |||
| 136 | mgb4_mask_reg(&mgbdev->video, voutdev->config->regs.config, 0xc, | ||
| 137 | val << 2); | ||
| 138 | |||
| 139 | ret = count; | ||
| 140 | end: | ||
| 141 | clear_bit(0, &mgbdev->io_reconfig); | ||
| 142 | |||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | static ssize_t display_width_show(struct device *dev, | ||
| 147 | struct device_attribute *attr, char *buf) | ||
| 148 | { | ||
| 149 | struct video_device *vdev = to_video_device(dev); | ||
| 150 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 151 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 152 | voutdev->config->regs.resolution); | ||
| 153 | |||
| 154 | return sprintf(buf, "%u\n", config >> 16); | ||
| 155 | } | ||
| 156 | |||
| 157 | static ssize_t display_width_store(struct device *dev, | ||
| 158 | struct device_attribute *attr, | ||
| 159 | const char *buf, size_t count) | ||
| 160 | { | ||
| 161 | struct video_device *vdev = to_video_device(dev); | ||
| 162 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 163 | unsigned long val; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | ret = kstrtoul(buf, 10, &val); | ||
| 167 | if (ret) | ||
| 168 | return ret; | ||
| 169 | if (val > 0xFFFF) | ||
| 170 | return -EINVAL; | ||
| 171 | |||
| 172 | mutex_lock(voutdev->vdev.lock); | ||
| 173 | if (vb2_is_busy(voutdev->vdev.queue)) { | ||
| 174 | mutex_unlock(voutdev->vdev.lock); | ||
| 175 | return -EBUSY; | ||
| 176 | } | ||
| 177 | |||
| 178 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.resolution, | ||
| 179 | 0xFFFF0000, val << 16); | ||
| 180 | |||
| 181 | mutex_unlock(voutdev->vdev.lock); | ||
| 182 | |||
| 183 | return count; | ||
| 184 | } | ||
| 185 | |||
| 186 | static ssize_t display_height_show(struct device *dev, | ||
| 187 | struct device_attribute *attr, char *buf) | ||
| 188 | { | ||
| 189 | struct video_device *vdev = to_video_device(dev); | ||
| 190 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 191 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 192 | voutdev->config->regs.resolution); | ||
| 193 | |||
| 194 | return sprintf(buf, "%u\n", config & 0xFFFF); | ||
| 195 | } | ||
| 196 | |||
| 197 | static ssize_t display_height_store(struct device *dev, | ||
| 198 | struct device_attribute *attr, | ||
| 199 | const char *buf, size_t count) | ||
| 200 | { | ||
| 201 | struct video_device *vdev = to_video_device(dev); | ||
| 202 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 203 | unsigned long val; | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | ret = kstrtoul(buf, 10, &val); | ||
| 207 | if (ret) | ||
| 208 | return ret; | ||
| 209 | if (val > 0xFFFF) | ||
| 210 | return -EINVAL; | ||
| 211 | |||
| 212 | mutex_lock(voutdev->vdev.lock); | ||
| 213 | if (vb2_is_busy(voutdev->vdev.queue)) { | ||
| 214 | mutex_unlock(voutdev->vdev.lock); | ||
| 215 | return -EBUSY; | ||
| 216 | } | ||
| 217 | |||
| 218 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.resolution, | ||
| 219 | 0xFFFF, val); | ||
| 220 | |||
| 221 | mutex_unlock(voutdev->vdev.lock); | ||
| 222 | |||
| 223 | return count; | ||
| 224 | } | ||
| 225 | |||
| 226 | static ssize_t frame_rate_show(struct device *dev, | ||
| 227 | struct device_attribute *attr, char *buf) | ||
| 228 | { | ||
| 229 | struct video_device *vdev = to_video_device(dev); | ||
| 230 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 231 | u32 period = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 232 | voutdev->config->regs.frame_period); | ||
| 233 | |||
| 234 | return sprintf(buf, "%u\n", 125000000 / period); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Frame rate change is expected to be called on live streams. Video device | ||
| 239 | * locking/queue check is not needed. | ||
| 240 | */ | ||
| 241 | static ssize_t frame_rate_store(struct device *dev, | ||
| 242 | struct device_attribute *attr, const char *buf, | ||
| 243 | size_t count) | ||
| 244 | { | ||
| 245 | struct video_device *vdev = to_video_device(dev); | ||
| 246 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 247 | unsigned long val; | ||
| 248 | int ret; | ||
| 249 | |||
| 250 | ret = kstrtoul(buf, 10, &val); | ||
| 251 | if (ret) | ||
| 252 | return ret; | ||
| 253 | |||
| 254 | mgb4_write_reg(&voutdev->mgbdev->video, | ||
| 255 | voutdev->config->regs.frame_period, 125000000 / val); | ||
| 256 | |||
| 257 | return count; | ||
| 258 | } | ||
| 259 | |||
| 260 | static ssize_t hsync_width_show(struct device *dev, | ||
| 261 | struct device_attribute *attr, char *buf) | ||
| 262 | { | ||
| 263 | struct video_device *vdev = to_video_device(dev); | ||
| 264 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 265 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 266 | voutdev->config->regs.hsync); | ||
| 267 | |||
| 268 | return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); | ||
| 269 | } | ||
| 270 | |||
| 271 | /* | ||
| 272 | * HSYNC width change is expected to be called on live streams. Video device | ||
| 273 | * locking/queue check is not needed. | ||
| 274 | */ | ||
| 275 | static ssize_t hsync_width_store(struct device *dev, | ||
| 276 | struct device_attribute *attr, const char *buf, | ||
| 277 | size_t count) | ||
| 278 | { | ||
| 279 | struct video_device *vdev = to_video_device(dev); | ||
| 280 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 281 | unsigned long val; | ||
| 282 | int ret; | ||
| 283 | |||
| 284 | ret = kstrtoul(buf, 10, &val); | ||
| 285 | if (ret) | ||
| 286 | return ret; | ||
| 287 | if (val > 0xFF) | ||
| 288 | return -EINVAL; | ||
| 289 | |||
| 290 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, | ||
| 291 | 0x00FF0000, val << 16); | ||
| 292 | |||
| 293 | return count; | ||
| 294 | } | ||
| 295 | |||
| 296 | static ssize_t vsync_width_show(struct device *dev, | ||
| 297 | struct device_attribute *attr, char *buf) | ||
| 298 | { | ||
| 299 | struct video_device *vdev = to_video_device(dev); | ||
| 300 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 301 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 302 | voutdev->config->regs.vsync); | ||
| 303 | |||
| 304 | return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); | ||
| 305 | } | ||
| 306 | |||
| 307 | /* | ||
| 308 | * VSYNC vidth change is expected to be called on live streams. Video device | ||
| 309 | * locking/queue check is not needed. | ||
| 310 | */ | ||
| 311 | static ssize_t vsync_width_store(struct device *dev, | ||
| 312 | struct device_attribute *attr, const char *buf, | ||
| 313 | size_t count) | ||
| 314 | { | ||
| 315 | struct video_device *vdev = to_video_device(dev); | ||
| 316 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 317 | unsigned long val; | ||
| 318 | int ret; | ||
| 319 | |||
| 320 | ret = kstrtoul(buf, 10, &val); | ||
| 321 | if (ret) | ||
| 322 | return ret; | ||
| 323 | if (val > 0xFF) | ||
| 324 | return -EINVAL; | ||
| 325 | |||
| 326 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, | ||
| 327 | 0x00FF0000, val << 16); | ||
| 328 | |||
| 329 | return count; | ||
| 330 | } | ||
| 331 | |||
| 332 | static ssize_t hback_porch_show(struct device *dev, | ||
| 333 | struct device_attribute *attr, char *buf) | ||
| 334 | { | ||
| 335 | struct video_device *vdev = to_video_device(dev); | ||
| 336 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 337 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 338 | voutdev->config->regs.hsync); | ||
| 339 | |||
| 340 | return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); | ||
| 341 | } | ||
| 342 | |||
| 343 | /* | ||
| 344 | * hback porch change is expected to be called on live streams. Video device | ||
| 345 | * locking/queue check is not needed. | ||
| 346 | */ | ||
| 347 | static ssize_t hback_porch_store(struct device *dev, | ||
| 348 | struct device_attribute *attr, const char *buf, | ||
| 349 | size_t count) | ||
| 350 | { | ||
| 351 | struct video_device *vdev = to_video_device(dev); | ||
| 352 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 353 | unsigned long val; | ||
| 354 | int ret; | ||
| 355 | |||
| 356 | ret = kstrtoul(buf, 10, &val); | ||
| 357 | if (ret) | ||
| 358 | return ret; | ||
| 359 | if (val > 0xFF) | ||
| 360 | return -EINVAL; | ||
| 361 | |||
| 362 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, | ||
| 363 | 0x0000FF00, val << 8); | ||
| 364 | |||
| 365 | return count; | ||
| 366 | } | ||
| 367 | |||
| 368 | static ssize_t vback_porch_show(struct device *dev, | ||
| 369 | struct device_attribute *attr, char *buf) | ||
| 370 | { | ||
| 371 | struct video_device *vdev = to_video_device(dev); | ||
| 372 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 373 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 374 | voutdev->config->regs.vsync); | ||
| 375 | |||
| 376 | return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); | ||
| 377 | } | ||
| 378 | |||
| 379 | /* | ||
| 380 | * vback porch change is expected to be called on live streams. Video device | ||
| 381 | * locking/queue check is not needed. | ||
| 382 | */ | ||
| 383 | static ssize_t vback_porch_store(struct device *dev, | ||
| 384 | struct device_attribute *attr, const char *buf, | ||
| 385 | size_t count) | ||
| 386 | { | ||
| 387 | struct video_device *vdev = to_video_device(dev); | ||
| 388 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 389 | unsigned long val; | ||
| 390 | int ret; | ||
| 391 | |||
| 392 | ret = kstrtoul(buf, 10, &val); | ||
| 393 | if (ret) | ||
| 394 | return ret; | ||
| 395 | if (val > 0xFF) | ||
| 396 | return -EINVAL; | ||
| 397 | |||
| 398 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, | ||
| 399 | 0x0000FF00, val << 8); | ||
| 400 | |||
| 401 | return count; | ||
| 402 | } | ||
| 403 | |||
| 404 | static ssize_t hfront_porch_show(struct device *dev, | ||
| 405 | struct device_attribute *attr, char *buf) | ||
| 406 | { | ||
| 407 | struct video_device *vdev = to_video_device(dev); | ||
| 408 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 409 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 410 | voutdev->config->regs.hsync); | ||
| 411 | |||
| 412 | return sprintf(buf, "%u\n", (sig & 0x000000FF)); | ||
| 413 | } | ||
| 414 | |||
| 415 | /* | ||
| 416 | * hfront porch change is expected to be called on live streams. Video device | ||
| 417 | * locking/queue check is not needed. | ||
| 418 | */ | ||
| 419 | static ssize_t hfront_porch_store(struct device *dev, | ||
| 420 | struct device_attribute *attr, | ||
| 421 | const char *buf, size_t count) | ||
| 422 | { | ||
| 423 | struct video_device *vdev = to_video_device(dev); | ||
| 424 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 425 | unsigned long val; | ||
| 426 | int ret; | ||
| 427 | |||
| 428 | ret = kstrtoul(buf, 10, &val); | ||
| 429 | if (ret) | ||
| 430 | return ret; | ||
| 431 | if (val > 0xFF) | ||
| 432 | return -EINVAL; | ||
| 433 | |||
| 434 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, | ||
| 435 | 0x000000FF, val); | ||
| 436 | |||
| 437 | return count; | ||
| 438 | } | ||
| 439 | |||
| 440 | static ssize_t vfront_porch_show(struct device *dev, | ||
| 441 | struct device_attribute *attr, char *buf) | ||
| 442 | { | ||
| 443 | struct video_device *vdev = to_video_device(dev); | ||
| 444 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 445 | u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 446 | voutdev->config->regs.vsync); | ||
| 447 | |||
| 448 | return sprintf(buf, "%u\n", (sig & 0x000000FF)); | ||
| 449 | } | ||
| 450 | |||
| 451 | /* | ||
| 452 | * vfront porch change is expected to be called on live streams. Video device | ||
| 453 | * locking/queue check is not needed. | ||
| 454 | */ | ||
| 455 | static ssize_t vfront_porch_store(struct device *dev, | ||
| 456 | struct device_attribute *attr, const char *buf, | ||
| 457 | size_t count) | ||
| 458 | { | ||
| 459 | struct video_device *vdev = to_video_device(dev); | ||
| 460 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 461 | unsigned long val; | ||
| 462 | int ret; | ||
| 463 | |||
| 464 | ret = kstrtoul(buf, 10, &val); | ||
| 465 | if (ret) | ||
| 466 | return ret; | ||
| 467 | if (val > 0xFF) | ||
| 468 | return -EINVAL; | ||
| 469 | |||
| 470 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, | ||
| 471 | 0x000000FF, val); | ||
| 472 | |||
| 473 | return count; | ||
| 474 | } | ||
| 475 | |||
| 476 | /* FPDL3 only */ | ||
| 477 | |||
| 478 | static ssize_t hsync_polarity_show(struct device *dev, | ||
| 479 | struct device_attribute *attr, char *buf) | ||
| 480 | { | ||
| 481 | struct video_device *vdev = to_video_device(dev); | ||
| 482 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 483 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 484 | voutdev->config->regs.hsync); | ||
| 485 | |||
| 486 | return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31); | ||
| 487 | } | ||
| 488 | |||
| 489 | /* | ||
| 490 | * HSYNC polarity change is expected to be called on live streams. Video device | ||
| 491 | * locking/queue check is not needed. | ||
| 492 | */ | ||
| 493 | static ssize_t hsync_polarity_store(struct device *dev, | ||
| 494 | struct device_attribute *attr, | ||
| 495 | const char *buf, size_t count) | ||
| 496 | { | ||
| 497 | struct video_device *vdev = to_video_device(dev); | ||
| 498 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 499 | unsigned long val; | ||
| 500 | int ret; | ||
| 501 | |||
| 502 | ret = kstrtoul(buf, 10, &val); | ||
| 503 | if (ret) | ||
| 504 | return ret; | ||
| 505 | if (val > 1) | ||
| 506 | return -EINVAL; | ||
| 507 | |||
| 508 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, | ||
| 509 | (1U << 31), val << 31); | ||
| 510 | |||
| 511 | return count; | ||
| 512 | } | ||
| 513 | |||
| 514 | static ssize_t vsync_polarity_show(struct device *dev, | ||
| 515 | struct device_attribute *attr, char *buf) | ||
| 516 | { | ||
| 517 | struct video_device *vdev = to_video_device(dev); | ||
| 518 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 519 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 520 | voutdev->config->regs.vsync); | ||
| 521 | |||
| 522 | return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31); | ||
| 523 | } | ||
| 524 | |||
| 525 | /* | ||
| 526 | * VSYNC polarity change is expected to be called on live streams. Video device | ||
| 527 | * locking/queue check is not needed. | ||
| 528 | */ | ||
| 529 | static ssize_t vsync_polarity_store(struct device *dev, | ||
| 530 | struct device_attribute *attr, | ||
| 531 | const char *buf, size_t count) | ||
| 532 | { | ||
| 533 | struct video_device *vdev = to_video_device(dev); | ||
| 534 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 535 | unsigned long val; | ||
| 536 | int ret; | ||
| 537 | |||
| 538 | ret = kstrtoul(buf, 10, &val); | ||
| 539 | if (ret) | ||
| 540 | return ret; | ||
| 541 | if (val > 1) | ||
| 542 | return -EINVAL; | ||
| 543 | |||
| 544 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, | ||
| 545 | (1U << 31), val << 31); | ||
| 546 | |||
| 547 | return count; | ||
| 548 | } | ||
| 549 | |||
| 550 | static ssize_t de_polarity_show(struct device *dev, | ||
| 551 | struct device_attribute *attr, char *buf) | ||
| 552 | { | ||
| 553 | struct video_device *vdev = to_video_device(dev); | ||
| 554 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 555 | u32 config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 556 | voutdev->config->regs.vsync); | ||
| 557 | |||
| 558 | return sprintf(buf, "%u\n", (config & (1U << 30)) >> 30); | ||
| 559 | } | ||
| 560 | |||
| 561 | /* | ||
| 562 | * DE polarity change is expected to be called on live streams. Video device | ||
| 563 | * locking/queue check is not needed. | ||
| 564 | */ | ||
| 565 | static ssize_t de_polarity_store(struct device *dev, | ||
| 566 | struct device_attribute *attr, const char *buf, | ||
| 567 | size_t count) | ||
| 568 | { | ||
| 569 | struct video_device *vdev = to_video_device(dev); | ||
| 570 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 571 | unsigned long val; | ||
| 572 | int ret; | ||
| 573 | |||
| 574 | ret = kstrtoul(buf, 10, &val); | ||
| 575 | if (ret) | ||
| 576 | return ret; | ||
| 577 | if (val > 1) | ||
| 578 | return -EINVAL; | ||
| 579 | |||
| 580 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, | ||
| 581 | (1U << 30), val << 30); | ||
| 582 | |||
| 583 | return count; | ||
| 584 | } | ||
| 585 | |||
| 586 | static ssize_t fpdl3_output_width_show(struct device *dev, | ||
| 587 | struct device_attribute *attr, char *buf) | ||
| 588 | { | ||
| 589 | struct video_device *vdev = to_video_device(dev); | ||
| 590 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 591 | s32 ret; | ||
| 592 | |||
| 593 | mutex_lock(&voutdev->mgbdev->i2c_lock); | ||
| 594 | ret = mgb4_i2c_read_byte(&voutdev->ser, 0x5B); | ||
| 595 | mutex_unlock(&voutdev->mgbdev->i2c_lock); | ||
| 596 | if (ret < 0) | ||
| 597 | return -EIO; | ||
| 598 | |||
| 599 | switch ((u8)ret & 0x03) { | ||
| 600 | case 0: | ||
| 601 | return sprintf(buf, "0\n"); | ||
| 602 | case 1: | ||
| 603 | return sprintf(buf, "1\n"); | ||
| 604 | case 3: | ||
| 605 | return sprintf(buf, "2\n"); | ||
| 606 | default: | ||
| 607 | return -EINVAL; | ||
| 608 | } | ||
| 609 | } | ||
| 610 | |||
| 611 | /* | ||
| 612 | * FPD-Link width change is expected to be called on live streams. Video device | ||
| 613 | * locking/queue check is not needed. | ||
| 614 | */ | ||
| 615 | static ssize_t fpdl3_output_width_store(struct device *dev, | ||
| 616 | struct device_attribute *attr, | ||
| 617 | const char *buf, size_t count) | ||
| 618 | { | ||
| 619 | struct video_device *vdev = to_video_device(dev); | ||
| 620 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 621 | u8 i2c_data; | ||
| 622 | unsigned long val; | ||
| 623 | int ret; | ||
| 624 | |||
| 625 | ret = kstrtoul(buf, 10, &val); | ||
| 626 | if (ret) | ||
| 627 | return ret; | ||
| 628 | |||
| 629 | switch (val) { | ||
| 630 | case 0: /* auto */ | ||
| 631 | i2c_data = 0x00; | ||
| 632 | break; | ||
| 633 | case 1: /* single */ | ||
| 634 | i2c_data = 0x01; | ||
| 635 | break; | ||
| 636 | case 2: /* dual */ | ||
| 637 | i2c_data = 0x03; | ||
| 638 | break; | ||
| 639 | default: | ||
| 640 | return -EINVAL; | ||
| 641 | } | ||
| 642 | |||
| 643 | mutex_lock(&voutdev->mgbdev->i2c_lock); | ||
| 644 | ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x5B, 0x03, i2c_data); | ||
| 645 | mutex_unlock(&voutdev->mgbdev->i2c_lock); | ||
| 646 | if (ret < 0) | ||
| 647 | return -EIO; | ||
| 648 | |||
| 649 | return count; | ||
| 650 | } | ||
| 651 | |||
| 652 | static ssize_t pclk_frequency_show(struct device *dev, | ||
| 653 | struct device_attribute *attr, char *buf) | ||
| 654 | { | ||
| 655 | struct video_device *vdev = to_video_device(dev); | ||
| 656 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 657 | |||
| 658 | return sprintf(buf, "%u\n", voutdev->freq); | ||
| 659 | } | ||
| 660 | |||
| 661 | static ssize_t pclk_frequency_store(struct device *dev, | ||
| 662 | struct device_attribute *attr, | ||
| 663 | const char *buf, size_t count) | ||
| 664 | { | ||
| 665 | struct video_device *vdev = to_video_device(dev); | ||
| 666 | struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); | ||
| 667 | unsigned long val; | ||
| 668 | int ret; | ||
| 669 | unsigned int dp; | ||
| 670 | |||
| 671 | ret = kstrtoul(buf, 10, &val); | ||
| 672 | if (ret) | ||
| 673 | return ret; | ||
| 674 | |||
| 675 | mutex_lock(voutdev->vdev.lock); | ||
| 676 | if (vb2_is_busy(voutdev->vdev.queue)) { | ||
| 677 | mutex_unlock(voutdev->vdev.lock); | ||
| 678 | return -EBUSY; | ||
| 679 | } | ||
| 680 | |||
| 681 | dp = (val > 50000) ? 1 : 0; | ||
| 682 | voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, val >> dp) << dp; | ||
| 683 | |||
| 684 | mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.config, | ||
| 685 | 0x10, dp << 4); | ||
| 686 | mutex_lock(&voutdev->mgbdev->i2c_lock); | ||
| 687 | ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x4F, 1 << 6, ((~dp) & 1) << 6); | ||
| 688 | mutex_unlock(&voutdev->mgbdev->i2c_lock); | ||
| 689 | |||
| 690 | mutex_unlock(voutdev->vdev.lock); | ||
| 691 | |||
| 692 | return (ret < 0) ? -EIO : count; | ||
| 693 | } | ||
| 694 | |||
| 695 | static DEVICE_ATTR_RO(output_id); | ||
| 696 | static DEVICE_ATTR_RW(video_source); | ||
| 697 | static DEVICE_ATTR_RW(display_width); | ||
| 698 | static DEVICE_ATTR_RW(display_height); | ||
| 699 | static DEVICE_ATTR_RW(frame_rate); | ||
| 700 | static DEVICE_ATTR_RW(hsync_polarity); | ||
| 701 | static DEVICE_ATTR_RW(vsync_polarity); | ||
| 702 | static DEVICE_ATTR_RW(de_polarity); | ||
| 703 | static DEVICE_ATTR_RW(pclk_frequency); | ||
| 704 | static DEVICE_ATTR_RW(hsync_width); | ||
| 705 | static DEVICE_ATTR_RW(vsync_width); | ||
| 706 | static DEVICE_ATTR_RW(hback_porch); | ||
| 707 | static DEVICE_ATTR_RW(hfront_porch); | ||
| 708 | static DEVICE_ATTR_RW(vback_porch); | ||
| 709 | static DEVICE_ATTR_RW(vfront_porch); | ||
| 710 | |||
| 711 | static DEVICE_ATTR_RW(fpdl3_output_width); | ||
| 712 | |||
| 713 | struct attribute *mgb4_fpdl3_out_attrs[] = { | ||
| 714 | &dev_attr_output_id.attr, | ||
| 715 | &dev_attr_video_source.attr, | ||
| 716 | &dev_attr_display_width.attr, | ||
| 717 | &dev_attr_display_height.attr, | ||
| 718 | &dev_attr_frame_rate.attr, | ||
| 719 | &dev_attr_hsync_polarity.attr, | ||
| 720 | &dev_attr_vsync_polarity.attr, | ||
| 721 | &dev_attr_de_polarity.attr, | ||
| 722 | &dev_attr_pclk_frequency.attr, | ||
| 723 | &dev_attr_hsync_width.attr, | ||
| 724 | &dev_attr_vsync_width.attr, | ||
| 725 | &dev_attr_hback_porch.attr, | ||
| 726 | &dev_attr_hfront_porch.attr, | ||
| 727 | &dev_attr_vback_porch.attr, | ||
| 728 | &dev_attr_vfront_porch.attr, | ||
| 729 | &dev_attr_fpdl3_output_width.attr, | ||
| 730 | NULL | ||
| 731 | }; | ||
| 732 | |||
| 733 | struct attribute *mgb4_gmsl_out_attrs[] = { | ||
| 734 | &dev_attr_output_id.attr, | ||
| 735 | &dev_attr_video_source.attr, | ||
| 736 | &dev_attr_display_width.attr, | ||
| 737 | &dev_attr_display_height.attr, | ||
| 738 | &dev_attr_frame_rate.attr, | ||
| 739 | NULL | ||
| 740 | }; | ||
| @@ -0,0 +1,71 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This module handles all the sysfs info/configuration that is related to the | ||
| 7 | * PCI card device. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/device.h> | ||
| 11 | #include "mgb4_core.h" | ||
| 12 | #include "mgb4_sysfs.h" | ||
| 13 | |||
| 14 | static ssize_t module_version_show(struct device *dev, | ||
| 15 | struct device_attribute *attr, char *buf) | ||
| 16 | { | ||
| 17 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 18 | |||
| 19 | return sprintf(buf, "%u\n", mgbdev->module_version & 0x0F); | ||
| 20 | } | ||
| 21 | |||
| 22 | static ssize_t module_type_show(struct device *dev, | ||
| 23 | struct device_attribute *attr, char *buf) | ||
| 24 | { | ||
| 25 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 26 | |||
| 27 | return sprintf(buf, "%u\n", mgbdev->module_version >> 4); | ||
| 28 | } | ||
| 29 | |||
| 30 | static ssize_t fw_version_show(struct device *dev, | ||
| 31 | struct device_attribute *attr, char *buf) | ||
| 32 | { | ||
| 33 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 34 | u32 config = mgb4_read_reg(&mgbdev->video, 0xC4); | ||
| 35 | |||
| 36 | return sprintf(buf, "%u\n", config & 0xFFFF); | ||
| 37 | } | ||
| 38 | |||
| 39 | static ssize_t fw_type_show(struct device *dev, | ||
| 40 | struct device_attribute *attr, char *buf) | ||
| 41 | { | ||
| 42 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 43 | u32 config = mgb4_read_reg(&mgbdev->video, 0xC4); | ||
| 44 | |||
| 45 | return sprintf(buf, "%u\n", config >> 24); | ||
| 46 | } | ||
| 47 | |||
| 48 | static ssize_t serial_number_show(struct device *dev, | ||
| 49 | struct device_attribute *attr, char *buf) | ||
| 50 | { | ||
| 51 | struct mgb4_dev *mgbdev = dev_get_drvdata(dev); | ||
| 52 | u32 sn = mgbdev->serial_number; | ||
| 53 | |||
| 54 | return sprintf(buf, "%03d-%03d-%03d-%03d\n", sn >> 24, (sn >> 16) & 0xFF, | ||
| 55 | (sn >> 8) & 0xFF, sn & 0xFF); | ||
| 56 | } | ||
| 57 | |||
| 58 | static DEVICE_ATTR_RO(module_version); | ||
| 59 | static DEVICE_ATTR_RO(module_type); | ||
| 60 | static DEVICE_ATTR_RO(fw_version); | ||
| 61 | static DEVICE_ATTR_RO(fw_type); | ||
| 62 | static DEVICE_ATTR_RO(serial_number); | ||
| 63 | |||
| 64 | struct attribute *mgb4_pci_attrs[] = { | ||
| 65 | &dev_attr_module_type.attr, | ||
| 66 | &dev_attr_module_version.attr, | ||
| 67 | &dev_attr_fw_type.attr, | ||
| 68 | &dev_attr_fw_version.attr, | ||
| 69 | &dev_attr_serial_number.attr, | ||
| 70 | NULL | ||
| 71 | }; | ||
| @@ -0,0 +1,208 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This module handles the IIO trigger device. The card has two signal inputs | ||
| 7 | * for event triggers that can be used to record events related to the video | ||
| 8 | * stream. A standard linux IIO device with triggered buffer capability is | ||
| 9 | * created and configured that can be used to fetch the events with the same | ||
| 10 | * clock source as the video frames. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/iio/iio.h> | ||
| 14 | #include <linux/iio/buffer.h> | ||
| 15 | #include <linux/iio/trigger.h> | ||
| 16 | #include <linux/iio/trigger_consumer.h> | ||
| 17 | #include <linux/iio/triggered_buffer.h> | ||
| 18 | #include <linux/pci.h> | ||
| 19 | #include <linux/dma/amd_xdma.h> | ||
| 20 | #include "mgb4_core.h" | ||
| 21 | #include "mgb4_trigger.h" | ||
| 22 | |||
| 23 | struct trigger_data { | ||
| 24 | struct mgb4_dev *mgbdev; | ||
| 25 | struct iio_trigger *trig; | ||
| 26 | }; | ||
| 27 | |||
| 28 | static int trigger_read_raw(struct iio_dev *indio_dev, | ||
| 29 | struct iio_chan_spec const *chan, int *val, | ||
| 30 | int *val2, long mask) | ||
| 31 | { | ||
| 32 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 33 | |||
| 34 | switch (mask) { | ||
| 35 | case IIO_CHAN_INFO_RAW: | ||
| 36 | if (iio_buffer_enabled(indio_dev)) | ||
| 37 | return -EBUSY; | ||
| 38 | *val = mgb4_read_reg(&st->mgbdev->video, 0xA0); | ||
| 39 | |||
| 40 | return IIO_VAL_INT; | ||
| 41 | } | ||
| 42 | |||
| 43 | return -EINVAL; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int trigger_set_state(struct iio_trigger *trig, bool state) | ||
| 47 | { | ||
| 48 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
| 49 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 50 | int irq = xdma_get_user_irq(st->mgbdev->xdev, 11); | ||
| 51 | |||
| 52 | if (state) | ||
| 53 | xdma_enable_user_irq(st->mgbdev->xdev, irq); | ||
| 54 | else | ||
| 55 | xdma_disable_user_irq(st->mgbdev->xdev, irq); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static const struct iio_trigger_ops trigger_ops = { | ||
| 61 | .set_trigger_state = &trigger_set_state, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static const struct iio_info trigger_info = { | ||
| 65 | .read_raw = trigger_read_raw, | ||
| 66 | }; | ||
| 67 | |||
| 68 | #define TRIGGER_CHANNEL(_si) { \ | ||
| 69 | .type = IIO_ACTIVITY, \ | ||
| 70 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 71 | .scan_index = _si, \ | ||
| 72 | .scan_type = { \ | ||
| 73 | .sign = 'u', \ | ||
| 74 | .realbits = 32, \ | ||
| 75 | .storagebits = 32, \ | ||
| 76 | .shift = 0, \ | ||
| 77 | .endianness = IIO_CPU \ | ||
| 78 | }, \ | ||
| 79 | } | ||
| 80 | |||
| 81 | static const struct iio_chan_spec trigger_channels[] = { | ||
| 82 | TRIGGER_CHANNEL(0), | ||
| 83 | IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 84 | }; | ||
| 85 | |||
| 86 | static irqreturn_t trigger_handler(int irq, void *p) | ||
| 87 | { | ||
| 88 | struct iio_poll_func *pf = p; | ||
| 89 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 90 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 91 | struct { | ||
| 92 | u32 data; | ||
| 93 | s64 ts __aligned(8); | ||
| 94 | } scan; | ||
| 95 | |||
| 96 | scan.data = mgb4_read_reg(&st->mgbdev->video, 0xA0); | ||
| 97 | mgb4_write_reg(&st->mgbdev->video, 0xA0, scan.data); | ||
| 98 | |||
| 99 | iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); | ||
| 100 | iio_trigger_notify_done(indio_dev->trig); | ||
| 101 | |||
| 102 | mgb4_write_reg(&st->mgbdev->video, 0xB4, 1U << 11); | ||
| 103 | |||
| 104 | return IRQ_HANDLED; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int probe_trigger(struct iio_dev *indio_dev, int irq) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 111 | |||
| 112 | st->trig = iio_trigger_alloc(&st->mgbdev->pdev->dev, "%s-dev%d", | ||
| 113 | indio_dev->name, iio_device_id(indio_dev)); | ||
| 114 | if (!st->trig) | ||
| 115 | return -ENOMEM; | ||
| 116 | |||
| 117 | ret = request_irq(irq, &iio_trigger_generic_data_rdy_poll, 0, | ||
| 118 | "mgb4-trigger", st->trig); | ||
| 119 | if (ret) | ||
| 120 | goto error_free_trig; | ||
| 121 | |||
| 122 | st->trig->ops = &trigger_ops; | ||
| 123 | iio_trigger_set_drvdata(st->trig, indio_dev); | ||
| 124 | ret = iio_trigger_register(st->trig); | ||
| 125 | if (ret) | ||
| 126 | goto error_free_irq; | ||
| 127 | |||
| 128 | indio_dev->trig = iio_trigger_get(st->trig); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | |||
| 132 | error_free_irq: | ||
| 133 | free_irq(irq, st->trig); | ||
| 134 | error_free_trig: | ||
| 135 | iio_trigger_free(st->trig); | ||
| 136 | |||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void remove_trigger(struct iio_dev *indio_dev, int irq) | ||
| 141 | { | ||
| 142 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 143 | |||
| 144 | iio_trigger_unregister(st->trig); | ||
| 145 | free_irq(irq, st->trig); | ||
| 146 | iio_trigger_free(st->trig); | ||
| 147 | } | ||
| 148 | |||
| 149 | struct iio_dev *mgb4_trigger_create(struct mgb4_dev *mgbdev) | ||
| 150 | { | ||
| 151 | struct iio_dev *indio_dev; | ||
| 152 | struct trigger_data *data; | ||
| 153 | struct pci_dev *pdev = mgbdev->pdev; | ||
| 154 | struct device *dev = &pdev->dev; | ||
| 155 | int rv, irq; | ||
| 156 | |||
| 157 | indio_dev = iio_device_alloc(dev, sizeof(*data)); | ||
| 158 | if (!indio_dev) | ||
| 159 | return NULL; | ||
| 160 | |||
| 161 | indio_dev->info = &trigger_info; | ||
| 162 | indio_dev->name = "mgb4"; | ||
| 163 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 164 | indio_dev->channels = trigger_channels; | ||
| 165 | indio_dev->num_channels = ARRAY_SIZE(trigger_channels); | ||
| 166 | |||
| 167 | data = iio_priv(indio_dev); | ||
| 168 | data->mgbdev = mgbdev; | ||
| 169 | |||
| 170 | irq = xdma_get_user_irq(mgbdev->xdev, 11); | ||
| 171 | rv = probe_trigger(indio_dev, irq); | ||
| 172 | if (rv < 0) { | ||
| 173 | dev_err(dev, "iio triggered setup failed\n"); | ||
| 174 | goto error_alloc; | ||
| 175 | } | ||
| 176 | rv = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | ||
| 177 | trigger_handler, NULL); | ||
| 178 | if (rv < 0) { | ||
| 179 | dev_err(dev, "iio triggered buffer setup failed\n"); | ||
| 180 | goto error_trigger; | ||
| 181 | } | ||
| 182 | rv = iio_device_register(indio_dev); | ||
| 183 | if (rv < 0) { | ||
| 184 | dev_err(dev, "iio device register failed\n"); | ||
| 185 | goto error_buffer; | ||
| 186 | } | ||
| 187 | |||
| 188 | return indio_dev; | ||
| 189 | |||
| 190 | error_buffer: | ||
| 191 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 192 | error_trigger: | ||
| 193 | remove_trigger(indio_dev, irq); | ||
| 194 | error_alloc: | ||
| 195 | iio_device_free(indio_dev); | ||
| 196 | |||
| 197 | return NULL; | ||
| 198 | } | ||
| 199 | |||
| 200 | void mgb4_trigger_free(struct iio_dev *indio_dev) | ||
| 201 | { | ||
| 202 | struct trigger_data *st = iio_priv(indio_dev); | ||
| 203 | |||
| 204 | iio_device_unregister(indio_dev); | ||
| 205 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 206 | remove_trigger(indio_dev, xdma_get_user_irq(st->mgbdev->xdev, 11)); | ||
| 207 | iio_device_free(indio_dev); | ||
| 208 | } | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2022 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | struct iio_dev *mgb4_trigger_create(struct mgb4_dev *mgbdev); | ||
| 8 | void mgb4_trigger_free(struct iio_dev *indio_dev); | ||
| @@ -0,0 +1,939 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 Digiteq Automotive | ||
| 4 | * author: Martin Tuma <martin.tuma@digiteqautomotive.com> | ||
| 5 | * | ||
| 6 | * This is the v4l2 input device module. It initializes the signal deserializers | ||
| 7 | * and creates the v4l2 video devices. The input signal can change at any time | ||
| 8 | * which is handled by the "timings" callbacks and an IRQ based watcher, that | ||
| 9 | * emits the V4L2_EVENT_SOURCE_CHANGE event in case of a signal source change. | ||
| 10 | * | ||
| 11 | * When the device is in loopback mode (a direct, in HW, in->out frame passing | ||
| 12 | * mode) the card's frame queue must be running regardless of whether a v4l2 | ||
| 13 | * stream is running and the output parameters like frame buffers padding must | ||
| 14 | * be in sync with the input parameters. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/pci.h> | ||
| 18 | #include <linux/workqueue.h> | ||
| 19 | #include <linux/align.h> | ||
| 20 | #include <linux/dma/amd_xdma.h> | ||
| 21 | #include <media/v4l2-ioctl.h> | ||
| 22 | #include <media/videobuf2-v4l2.h> | ||
| 23 | #include <media/videobuf2-dma-sg.h> | ||
| 24 | #include <media/v4l2-dv-timings.h> | ||
| 25 | #include <media/v4l2-event.h> | ||
| 26 | #include "mgb4_core.h" | ||
| 27 | #include "mgb4_dma.h" | ||
| 28 | #include "mgb4_sysfs.h" | ||
| 29 | #include "mgb4_io.h" | ||
| 30 | #include "mgb4_vout.h" | ||
| 31 | #include "mgb4_vin.h" | ||
| 32 | |||
| 33 | ATTRIBUTE_GROUPS(mgb4_fpdl3_in); | ||
| 34 | ATTRIBUTE_GROUPS(mgb4_gmsl_in); | ||
| 35 | |||
| 36 | static const struct mgb4_vin_config vin_cfg[] = { | ||
| 37 | {0, 0, 0, 6, {0x10, 0x00, 0x04, 0x08, 0x1C, 0x14, 0x18, 0x20, 0x24, 0x28}}, | ||
| 38 | {1, 1, 1, 7, {0x40, 0x30, 0x34, 0x38, 0x4C, 0x44, 0x48, 0x50, 0x54, 0x58}} | ||
| 39 | }; | ||
| 40 | |||
| 41 | static const struct i2c_board_info fpdl3_deser_info[] = { | ||
| 42 | {I2C_BOARD_INFO("deserializer1", 0x38)}, | ||
| 43 | {I2C_BOARD_INFO("deserializer2", 0x36)}, | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const struct i2c_board_info gmsl_deser_info[] = { | ||
| 47 | {I2C_BOARD_INFO("deserializer1", 0x4C)}, | ||
| 48 | {I2C_BOARD_INFO("deserializer2", 0x2A)}, | ||
| 49 | }; | ||
| 50 | |||
| 51 | static const struct mgb4_i2c_kv fpdl3_i2c[] = { | ||
| 52 | {0x06, 0xFF, 0x04}, {0x07, 0xFF, 0x01}, {0x45, 0xFF, 0xE8}, | ||
| 53 | {0x49, 0xFF, 0x00}, {0x34, 0xFF, 0x00}, {0x23, 0xFF, 0x00} | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const struct mgb4_i2c_kv gmsl_i2c[] = { | ||
| 57 | {0x01, 0x03, 0x03}, {0x300, 0x0C, 0x0C}, {0x03, 0xC0, 0xC0}, | ||
| 58 | {0x1CE, 0x0E, 0x0E}, {0x11, 0x05, 0x00}, {0x05, 0xC0, 0x40}, | ||
| 59 | {0x307, 0x0F, 0x00}, {0xA0, 0x03, 0x00}, {0x3E0, 0x07, 0x07}, | ||
| 60 | {0x308, 0x01, 0x01}, {0x10, 0x20, 0x20}, {0x300, 0x40, 0x40} | ||
| 61 | }; | ||
| 62 | |||
| 63 | static const struct v4l2_dv_timings_cap video_timings_cap = { | ||
| 64 | .type = V4L2_DV_BT_656_1120, | ||
| 65 | .bt = { | ||
| 66 | .min_width = 320, | ||
| 67 | .max_width = 4096, | ||
| 68 | .min_height = 240, | ||
| 69 | .max_height = 2160, | ||
| 70 | .min_pixelclock = 1843200, /* 320 x 240 x 24Hz */ | ||
| 71 | .max_pixelclock = 530841600, /* 4096 x 2160 x 60Hz */ | ||
| 72 | .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
| 73 | V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF, | ||
| 74 | .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | | ||
| 75 | V4L2_DV_BT_CAP_CUSTOM, | ||
| 76 | }, | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Returns the video output connected with the given video input if the input | ||
| 81 | * is in loopback mode. | ||
| 82 | */ | ||
| 83 | static struct mgb4_vout_dev *loopback_dev(struct mgb4_vin_dev *vindev, int i) | ||
| 84 | { | ||
| 85 | struct mgb4_vout_dev *voutdev; | ||
| 86 | u32 config; | ||
| 87 | |||
| 88 | voutdev = vindev->mgbdev->vout[i]; | ||
| 89 | if (!voutdev) | ||
| 90 | return NULL; | ||
| 91 | |||
| 92 | config = mgb4_read_reg(&voutdev->mgbdev->video, | ||
| 93 | voutdev->config->regs.config); | ||
| 94 | if ((config & 0xc) >> 2 == vindev->config->id) | ||
| 95 | return voutdev; | ||
| 96 | |||
| 97 | return NULL; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Check, whether the loopback mode - a HW INPUT->OUTPUT transmission - is | ||
| 102 | * enabled on the given input. | ||
| 103 | */ | ||
| 104 | static int loopback_active(struct mgb4_vin_dev *vindev) | ||
| 105 | { | ||
| 106 | int i; | ||
| 107 | |||
| 108 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) | ||
| 109 | if (loopback_dev(vindev, i)) | ||
| 110 | return 1; | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* | ||
| 116 | * Set the output frame buffer padding of all outputs connected with the given | ||
| 117 | * input when the video input is set to loopback mode. The paddings must be | ||
| 118 | * the same for the loopback to work properly. | ||
| 119 | */ | ||
| 120 | static void set_loopback_padding(struct mgb4_vin_dev *vindev, u32 padding) | ||
| 121 | { | ||
| 122 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 123 | struct mgb4_vout_dev *voutdev; | ||
| 124 | int i; | ||
| 125 | |||
| 126 | for (i = 0; i < MGB4_VOUT_DEVICES; i++) { | ||
| 127 | voutdev = loopback_dev(vindev, i); | ||
| 128 | if (voutdev) | ||
| 129 | mgb4_write_reg(video, voutdev->config->regs.padding, | ||
| 130 | padding); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static int get_timings(struct mgb4_vin_dev *vindev, | ||
| 135 | struct v4l2_dv_timings *timings) | ||
| 136 | { | ||
| 137 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 138 | const struct mgb4_vin_regs *regs = &vindev->config->regs; | ||
| 139 | |||
| 140 | u32 status = mgb4_read_reg(video, regs->status); | ||
| 141 | u32 pclk = mgb4_read_reg(video, regs->pclk); | ||
| 142 | u32 signal = mgb4_read_reg(video, regs->signal); | ||
| 143 | u32 signal2 = mgb4_read_reg(video, regs->signal2); | ||
| 144 | u32 resolution = mgb4_read_reg(video, regs->resolution); | ||
| 145 | |||
| 146 | if (!(status & (1U << 2))) | ||
| 147 | return -ENOLCK; | ||
| 148 | if (!(status & (3 << 9))) | ||
| 149 | return -ENOLINK; | ||
| 150 | |||
| 151 | memset(timings, 0, sizeof(*timings)); | ||
| 152 | timings->type = V4L2_DV_BT_656_1120; | ||
| 153 | timings->bt.width = resolution >> 16; | ||
| 154 | timings->bt.height = resolution & 0xFFFF; | ||
| 155 | if (status & (1U << 12)) | ||
| 156 | timings->bt.polarities |= V4L2_DV_HSYNC_POS_POL; | ||
| 157 | if (status & (1U << 13)) | ||
| 158 | timings->bt.polarities |= V4L2_DV_VSYNC_POS_POL; | ||
| 159 | timings->bt.pixelclock = pclk * 1000; | ||
| 160 | timings->bt.hsync = (signal & 0x00FF0000) >> 16; | ||
| 161 | timings->bt.vsync = (signal2 & 0x00FF0000) >> 16; | ||
| 162 | timings->bt.hbackporch = (signal & 0x0000FF00) >> 8; | ||
| 163 | timings->bt.hfrontporch = signal & 0x000000FF; | ||
| 164 | timings->bt.vbackporch = (signal2 & 0x0000FF00) >> 8; | ||
| 165 | timings->bt.vfrontporch = signal2 & 0x000000FF; | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static void return_all_buffers(struct mgb4_vin_dev *vindev, | ||
| 171 | enum vb2_buffer_state state) | ||
| 172 | { | ||
| 173 | struct mgb4_frame_buffer *buf, *node; | ||
| 174 | unsigned long flags; | ||
| 175 | |||
| 176 | spin_lock_irqsave(&vindev->qlock, flags); | ||
| 177 | list_for_each_entry_safe(buf, node, &vindev->buf_list, list) { | ||
| 178 | vb2_buffer_done(&buf->vb.vb2_buf, state); | ||
| 179 | list_del(&buf->list); | ||
| 180 | } | ||
| 181 | spin_unlock_irqrestore(&vindev->qlock, flags); | ||
| 182 | } | ||
| 183 | |||
| 184 | static int queue_setup(struct vb2_queue *q, unsigned int *nbuffers, | ||
| 185 | unsigned int *nplanes, unsigned int sizes[], | ||
| 186 | struct device *alloc_devs[]) | ||
| 187 | { | ||
| 188 | struct mgb4_vin_dev *vindev = vb2_get_drv_priv(q); | ||
| 189 | unsigned int size = (vindev->timings.bt.width + vindev->padding) | ||
| 190 | * vindev->timings.bt.height * 4; | ||
| 191 | |||
| 192 | /* | ||
| 193 | * If I/O reconfiguration is in process, do not allow to start | ||
| 194 | * the queue. See video_source_store() in mgb4_sysfs_out.c for | ||
| 195 | * details. | ||
| 196 | */ | ||
| 197 | if (test_bit(0, &vindev->mgbdev->io_reconfig)) | ||
| 198 | return -EBUSY; | ||
| 199 | |||
| 200 | if (!size) | ||
| 201 | return -EINVAL; | ||
| 202 | if (*nplanes) | ||
| 203 | return sizes[0] < size ? -EINVAL : 0; | ||
| 204 | *nplanes = 1; | ||
| 205 | sizes[0] = size; | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int buffer_init(struct vb2_buffer *vb) | ||
| 211 | { | ||
| 212 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
| 213 | struct mgb4_frame_buffer *buf = to_frame_buffer(vbuf); | ||
| 214 | |||
| 215 | INIT_LIST_HEAD(&buf->list); | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int buffer_prepare(struct vb2_buffer *vb) | ||
| 221 | { | ||
| 222 | struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vb->vb2_queue); | ||
| 223 | struct device *dev = &vindev->mgbdev->pdev->dev; | ||
| 224 | unsigned int size = (vindev->timings.bt.width + vindev->padding) | ||
| 225 | * vindev->timings.bt.height * 4; | ||
| 226 | |||
| 227 | if (vb2_plane_size(vb, 0) < size) { | ||
| 228 | dev_err(dev, "buffer too small (%lu < %u)\n", | ||
| 229 | vb2_plane_size(vb, 0), size); | ||
| 230 | return -EINVAL; | ||
| 231 | } | ||
| 232 | |||
| 233 | vb2_set_plane_payload(vb, 0, size); | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static void buffer_queue(struct vb2_buffer *vb) | ||
| 239 | { | ||
| 240 | struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vb->vb2_queue); | ||
| 241 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||
| 242 | struct mgb4_frame_buffer *buf = to_frame_buffer(vbuf); | ||
| 243 | unsigned long flags; | ||
| 244 | |||
| 245 | spin_lock_irqsave(&vindev->qlock, flags); | ||
| 246 | list_add_tail(&buf->list, &vindev->buf_list); | ||
| 247 | spin_unlock_irqrestore(&vindev->qlock, flags); | ||
| 248 | } | ||
| 249 | |||
| 250 | static void stop_streaming(struct vb2_queue *vq) | ||
| 251 | { | ||
| 252 | struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vq); | ||
| 253 | const struct mgb4_vin_config *config = vindev->config; | ||
| 254 | int irq = xdma_get_user_irq(vindev->mgbdev->xdev, config->vin_irq); | ||
| 255 | |||
| 256 | xdma_disable_user_irq(vindev->mgbdev->xdev, irq); | ||
| 257 | |||
| 258 | /* | ||
| 259 | * In loopback mode, the HW frame queue must be left running for | ||
| 260 | * the IN->OUT transmission to work! | ||
| 261 | */ | ||
| 262 | if (!loopback_active(vindev)) | ||
| 263 | mgb4_mask_reg(&vindev->mgbdev->video, config->regs.config, 0x2, | ||
| 264 | 0x0); | ||
| 265 | |||
| 266 | cancel_work_sync(&vindev->dma_work); | ||
| 267 | return_all_buffers(vindev, VB2_BUF_STATE_ERROR); | ||
| 268 | } | ||
| 269 | |||
| 270 | static int start_streaming(struct vb2_queue *vq, unsigned int count) | ||
| 271 | { | ||
| 272 | struct mgb4_vin_dev *vindev = vb2_get_drv_priv(vq); | ||
| 273 | const struct mgb4_vin_config *config = vindev->config; | ||
| 274 | int irq = xdma_get_user_irq(vindev->mgbdev->xdev, config->vin_irq); | ||
| 275 | |||
| 276 | vindev->sequence = 0; | ||
| 277 | |||
| 278 | /* | ||
| 279 | * In loopback mode, the HW frame queue is already running. | ||
| 280 | */ | ||
| 281 | if (!loopback_active(vindev)) | ||
| 282 | mgb4_mask_reg(&vindev->mgbdev->video, config->regs.config, 0x2, | ||
| 283 | 0x2); | ||
| 284 | |||
| 285 | xdma_enable_user_irq(vindev->mgbdev->xdev, irq); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static const struct vb2_ops queue_ops = { | ||
| 291 | .queue_setup = queue_setup, | ||
| 292 | .buf_init = buffer_init, | ||
| 293 | .buf_prepare = buffer_prepare, | ||
| 294 | .buf_queue = buffer_queue, | ||
| 295 | .start_streaming = start_streaming, | ||
| 296 | .stop_streaming = stop_streaming, | ||
| 297 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 298 | .wait_finish = vb2_ops_wait_finish | ||
| 299 | }; | ||
| 300 | |||
| 301 | static int fh_open(struct file *file) | ||
| 302 | { | ||
| 303 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 304 | int rv; | ||
| 305 | |||
| 306 | mutex_lock(&vindev->lock); | ||
| 307 | |||
| 308 | rv = v4l2_fh_open(file); | ||
| 309 | if (rv) | ||
| 310 | goto out; | ||
| 311 | |||
| 312 | if (!v4l2_fh_is_singular_file(file)) | ||
| 313 | goto out; | ||
| 314 | |||
| 315 | get_timings(vindev, &vindev->timings); | ||
| 316 | set_loopback_padding(vindev, vindev->padding); | ||
| 317 | |||
| 318 | out: | ||
| 319 | mutex_unlock(&vindev->lock); | ||
| 320 | return rv; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int fh_release(struct file *file) | ||
| 324 | { | ||
| 325 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 326 | int rv; | ||
| 327 | |||
| 328 | mutex_lock(&vindev->lock); | ||
| 329 | |||
| 330 | if (v4l2_fh_is_singular_file(file)) | ||
| 331 | set_loopback_padding(vindev, 0); | ||
| 332 | |||
| 333 | rv = _vb2_fop_release(file, NULL); | ||
| 334 | |||
| 335 | mutex_unlock(&vindev->lock); | ||
| 336 | |||
| 337 | return rv; | ||
| 338 | } | ||
| 339 | |||
| 340 | static const struct v4l2_file_operations video_fops = { | ||
| 341 | .owner = THIS_MODULE, | ||
| 342 | .open = fh_open, | ||
| 343 | .release = fh_release, | ||
| 344 | .unlocked_ioctl = video_ioctl2, | ||
| 345 | .read = vb2_fop_read, | ||
| 346 | .mmap = vb2_fop_mmap, | ||
| 347 | .poll = vb2_fop_poll, | ||
| 348 | }; | ||
| 349 | |||
| 350 | static int vidioc_querycap(struct file *file, void *priv, | ||
| 351 | struct v4l2_capability *cap) | ||
| 352 | { | ||
| 353 | strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | ||
| 354 | strscpy(cap->card, "MGB4 PCIe Card", sizeof(cap->card)); | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int vidioc_enum_fmt(struct file *file, void *priv, | ||
| 360 | struct v4l2_fmtdesc *f) | ||
| 361 | { | ||
| 362 | if (f->index != 0) | ||
| 363 | return -EINVAL; | ||
| 364 | |||
| 365 | f->pixelformat = V4L2_PIX_FMT_ABGR32; | ||
| 366 | |||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | static int vidioc_enum_frameintervals(struct file *file, void *priv, | ||
| 371 | struct v4l2_frmivalenum *ival) | ||
| 372 | { | ||
| 373 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 374 | |||
| 375 | if (ival->index != 0) | ||
| 376 | return -EINVAL; | ||
| 377 | if (ival->pixel_format != V4L2_PIX_FMT_ABGR32) | ||
| 378 | return -EINVAL; | ||
| 379 | if (ival->width != vindev->timings.bt.width || | ||
| 380 | ival->height != vindev->timings.bt.height) | ||
| 381 | return -EINVAL; | ||
| 382 | |||
| 383 | ival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; | ||
| 384 | ival->stepwise.min.denominator = 60; | ||
| 385 | ival->stepwise.min.numerator = 1; | ||
| 386 | ival->stepwise.max.denominator = 1; | ||
| 387 | ival->stepwise.max.numerator = 1; | ||
| 388 | ival->stepwise.step = ival->stepwise.max; | ||
| 389 | |||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
| 394 | { | ||
| 395 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 396 | |||
| 397 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_ABGR32; | ||
| 398 | f->fmt.pix.width = vindev->timings.bt.width; | ||
| 399 | f->fmt.pix.height = vindev->timings.bt.height; | ||
| 400 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 401 | f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; | ||
| 402 | f->fmt.pix.bytesperline = (f->fmt.pix.width + vindev->padding) * 4; | ||
| 403 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
| 409 | { | ||
| 410 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 411 | |||
| 412 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_ABGR32; | ||
| 413 | f->fmt.pix.width = vindev->timings.bt.width; | ||
| 414 | f->fmt.pix.height = vindev->timings.bt.height; | ||
| 415 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 416 | f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; | ||
| 417 | f->fmt.pix.bytesperline = max(f->fmt.pix.width * 4, | ||
| 418 | ALIGN_DOWN(f->fmt.pix.bytesperline, 4)); | ||
| 419 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; | ||
| 420 | |||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
| 425 | { | ||
| 426 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 427 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 428 | |||
| 429 | if (vb2_is_busy(&vindev->queue)) | ||
| 430 | return -EBUSY; | ||
| 431 | |||
| 432 | vidioc_try_fmt(file, priv, f); | ||
| 433 | |||
| 434 | vindev->padding = (f->fmt.pix.bytesperline - (f->fmt.pix.width * 4)) / 4; | ||
| 435 | mgb4_write_reg(video, vindev->config->regs.padding, vindev->padding); | ||
| 436 | set_loopback_padding(vindev, vindev->padding); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | static int vidioc_enum_input(struct file *file, void *priv, | ||
| 442 | struct v4l2_input *i) | ||
| 443 | { | ||
| 444 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 445 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 446 | u32 status; | ||
| 447 | |||
| 448 | if (i->index != 0) | ||
| 449 | return -EINVAL; | ||
| 450 | |||
| 451 | strscpy(i->name, "MGB4", sizeof(i->name)); | ||
| 452 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
| 453 | i->capabilities = V4L2_IN_CAP_DV_TIMINGS; | ||
| 454 | i->status = 0; | ||
| 455 | |||
| 456 | status = mgb4_read_reg(video, vindev->config->regs.status); | ||
| 457 | if (!(status & (1U << 2))) | ||
| 458 | i->status |= V4L2_IN_ST_NO_SYNC; | ||
| 459 | if (!(status & (3 << 9))) | ||
| 460 | i->status |= V4L2_IN_ST_NO_SIGNAL; | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | static int vidioc_enum_framesizes(struct file *file, void *fh, | ||
| 466 | struct v4l2_frmsizeenum *fsize) | ||
| 467 | { | ||
| 468 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 469 | |||
| 470 | if (fsize->index != 0 || fsize->pixel_format != V4L2_PIX_FMT_ABGR32) | ||
| 471 | return -EINVAL; | ||
| 472 | |||
| 473 | fsize->discrete.width = vindev->timings.bt.width; | ||
| 474 | fsize->discrete.height = vindev->timings.bt.height; | ||
| 475 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
| 476 | |||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
| 481 | { | ||
| 482 | return (i == 0) ? 0 : -EINVAL; | ||
| 483 | } | ||
| 484 | |||
| 485 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
| 486 | { | ||
| 487 | *i = 0; | ||
| 488 | return 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int vidioc_parm(struct file *file, void *priv, | ||
| 492 | struct v4l2_streamparm *parm) | ||
| 493 | { | ||
| 494 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 495 | struct mgb4_regs *video = &vindev->mgbdev->video; | ||
| 496 | const struct mgb4_vin_regs *regs = &vindev->config->regs; | ||
| 497 | struct v4l2_fract timeperframe = { | ||
| 498 | .numerator = mgb4_read_reg(video, regs->frame_period), | ||
| 499 | .denominator = 125000000, | ||
| 500 | }; | ||
| 501 | |||
| 502 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 503 | return -EINVAL; | ||
| 504 | |||
| 505 | parm->parm.capture.readbuffers = 2; | ||
| 506 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
| 507 | parm->parm.capture.timeperframe = timeperframe; | ||
| 508 | |||
| 509 | return 0; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int vidioc_s_dv_timings(struct file *file, void *fh, | ||
| 513 | struct v4l2_dv_timings *timings) | ||
| 514 | { | ||
| 515 | struct mgb4_vin_dev *vindev = video_drvdata(file); | ||
| 516 | |||
| 517 | if (timings->bt.width < video_timings_cap.bt.min_width || | ||
| 518 | timings->bt.width > video_timings_cap.bt.max_width || | ||
| 519 | timings->bt.height < video_timings_cap.bt.min_height || | ||
| 520 | timings->bt.height > video_timings_cap.bt.max_height) | ||
| 521 | return -EINVAL; | ||
| 522 | if (timings->bt.width == vindev->timings.bt.width && | ||
| 523 | timings->bt.height == vindev->timings.bt.height) | ||
| 524 | return 0; | ||
| 525 | if (vb2_is_busy(&vindev->queue)) | ||
| 526 | return -EBUSY; | ||
413 more lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 603 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 309 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 1832 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 173 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 423 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 1164 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 262 lines aren’t shown here.
This diff is large: its 555 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 1190 lines aren’t shown here.
This diff is large: its 511 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 1160 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 286 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 607 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 1199 lines aren’t shown here.
This diff is large: its 403 lines aren’t shown here.
This diff is large: its 682 lines aren’t shown here.
This diff is large: its 327 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 1764 lines aren’t shown here.
This diff is large: its 1332 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 478 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 1565 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 322 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 522 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 234 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.