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 | 77 | ivtv Conexant cx23416/cx23415 MPEG encoder/decoder |
| 78 | 78 | ivtvfb Conexant cx23415 framebuffer |
| 79 | 79 | mantis MANTIS based cards |
| 80 | +mgb4 Digiteq Automotive MGB4 frame grabber | |
| 80 | 81 | mxb Siemens-Nixdorf 'Multimedia eXtension Board' |
| 81 | 82 | netup-unidvb NetUP Universal DVB card |
| 82 | 83 | ngene Micronas nGene |
| @@ -17,6 +17,7 @@ Video4Linux (V4L) driver-specific documentation · 16 unmodified lines | ||
| 17 | 17 | imx7 |
| 18 | 18 | ipu3 |
| 19 | 19 | ivtv |
| 20 | + mgb4 | |
| 20 | 21 | omap3isp |
| 21 | 22 | omap4_camera |
| 22 | 23 | philips |
| @@ -78,7 +78,7 @@ The trace events are defined on a per-codec basis, e.g.: · 77 unmodified lines | ||
| 78 | 78 | |
| 79 | 79 | .. code-block:: bash |
| 80 | 80 | |
| 81 | − $ ls /sys/kernel/debug/tracing/events/ | grep visl | |
| 81 | + $ ls /sys/kernel/tracing/events/ | grep visl | |
| 82 | 82 | visl_fwht_controls |
| 83 | 83 | visl_h264_controls |
| 84 | 84 | visl_hevc_controls |
| @@ -90,13 +90,13 @@ For example, in order to dump HEVC SPS data: · 5 unmodified lines | ||
| 90 | 90 | |
| 91 | 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 | 95 | The SPS data will be dumped to the trace buffer, i.e.: |
| 96 | 96 | |
| 97 | 97 | .. code-block:: bash |
| 98 | 98 | |
| 99 | − $ cat /sys/kernel/debug/tracing/trace | |
| 99 | + $ cat /sys/kernel/tracing/trace | |
| 100 | 100 | video_parameter_set_id 0 |
| 101 | 101 | seq_parameter_set_id 0 |
| 102 | 102 | pic_width_in_luma_samples 1920 |
| @@ -15,7 +15,10 @@ description: · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | properties: |
| 17 | 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 | 23 | pwms: |
| 21 | 24 | maxItems: 1 |
| @@ -19,6 +19,7 @@ properties: · 18 unmodified lines | ||
| 19 | 19 | - amlogic,meson6-ir |
| 20 | 20 | - amlogic,meson8b-ir |
| 21 | 21 | - amlogic,meson-gxbb-ir |
| 22 | + - amlogic,meson-s4-ir | |
| 22 | 23 | - items: |
| 23 | 24 | - const: amlogic,meson-gx-ir |
| 24 | 25 | - const: amlogic,meson-gxbb-ir |
| @@ -18,6 +18,7 @@ properties: · 17 unmodified lines | ||
| 18 | 18 | items: |
| 19 | 19 | - enum: |
| 20 | 20 | - starfive,jh7110-csi2rx |
| 21 | + - ti,j721e-csi2rx | |
| 21 | 22 | - const: cdns,csi2rx |
| 22 | 23 | |
| 23 | 24 | reg: |
| @@ -14,6 +14,9 @@ description: |- · 13 unmodified lines | ||
| 14 | 14 | interface and CCI (I2C compatible) control bus. The output format |
| 15 | 15 | is raw Bayer. |
| 16 | 16 | |
| 17 | +allOf: | |
| 18 | + - $ref: /schemas/media/video-interface-devices.yaml# | |
| 19 | + | |
| 17 | 20 | properties: |
| 18 | 21 | compatible: |
| 19 | 22 | const: hynix,hi846 |
| @@ -86,7 +89,7 @@ required: · 66 unmodified lines | ||
| 86 | 89 | - vddd-supply |
| 87 | 90 | - port |
| 88 | 91 | |
| 89 | −additionalProperties: false | |
| 92 | +unevaluatedProperties: false | |
| 90 | 93 | |
| 91 | 94 | examples: |
| 92 | 95 | - | |
| @@ -109,6 +112,8 @@ examples: · 16 unmodified lines | ||
| 109 | 112 | vddio-supply = <®_camera_vddio>; |
| 110 | 113 | reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; |
| 111 | 114 | shutdown-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>; |
| 115 | + orientation = <0>; | |
| 116 | + rotation = <0>; | |
| 112 | 117 | |
| 113 | 118 | port { |
| 114 | 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 | 68 | marked GPIO_ACTIVE_LOW. |
| 69 | 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 | 71 | port: |
| 78 | 72 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 79 | 73 | additionalProperties: false |
| @@ -114,7 +108,7 @@ required: · 34 unmodified lines | ||
| 114 | 108 | - reset-gpios |
| 115 | 109 | - port |
| 116 | 110 | |
| 117 | −additionalProperties: false | |
| 111 | +unevaluatedProperties: false | |
| 118 | 112 | |
| 119 | 113 | examples: |
| 120 | 114 | - | |
| @@ -52,10 +52,6 @@ properties: · 51 unmodified lines | ||
| 52 | 52 | description: |
| 53 | 53 | GPIO connected to the reset pin (active low) |
| 54 | 54 | |
| 55 | − orientation: true | |
| 56 | − | |
| 57 | − rotation: true | |
| 58 | − | |
| 59 | 55 | port: |
| 60 | 56 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 61 | 57 | additionalProperties: false |
| @@ -95,7 +91,7 @@ required: · 33 unmodified lines | ||
| 95 | 91 | - dvdd-supply |
| 96 | 92 | - port |
| 97 | 93 | |
| 98 | −additionalProperties: false | |
| 94 | +unevaluatedProperties: false | |
| 99 | 95 | |
| 100 | 96 | examples: |
| 101 | 97 | - | |
| @@ -44,11 +44,6 @@ properties: · 43 unmodified lines | ||
| 44 | 44 | description: > |
| 45 | 45 | Reference to the GPIO connected to the reset pin, if any. |
| 46 | 46 | |
| 47 | − rotation: | |
| 48 | − enum: | |
| 49 | − - 0 | |
| 50 | − - 180 | |
| 51 | − | |
| 52 | 47 | port: |
| 53 | 48 | description: Digital Output Port |
| 54 | 49 | $ref: /schemas/graph.yaml#/$defs/port-base |
| @@ -85,7 +80,7 @@ required: · 30 unmodified lines | ||
| 85 | 80 | - DOVDD-supply |
| 86 | 81 | - port |
| 87 | 82 | |
| 88 | −additionalProperties: false | |
| 83 | +unevaluatedProperties: false | |
| 89 | 84 | |
| 90 | 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 | 8 | title: Omnivision OV5693/OV5695 CMOS Sensors |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | − - Tommaso Merciai <tommaso.merciai@amarulasolutions.com> | |
| 11 | + - Tommaso Merciai <tomm.merciai@gmail.com> | |
| 12 | 12 | |
| 13 | 13 | description: | |
| 14 | 14 | The Omnivision OV5693/OV5695 are high performance, 1/4-inch, 5 megapixel, CMOS |
| @@ -91,7 +91,7 @@ required: · 90 unmodified lines | ||
| 91 | 91 | - vddd-supply |
| 92 | 92 | - port |
| 93 | 93 | |
| 94 | −additionalProperties: false | |
| 94 | +unevaluatedProperties: false | |
| 95 | 95 | |
| 96 | 96 | examples: |
| 97 | 97 | - | |
| @@ -44,14 +44,6 @@ properties: · 43 unmodified lines | ||
| 44 | 44 | description: Sensor reset (XCLR) GPIO |
| 45 | 45 | maxItems: 1 |
| 46 | 46 | |
| 47 | − flash-leds: true | |
| 48 | − | |
| 49 | − lens-focus: true | |
| 50 | − | |
| 51 | − orientation: true | |
| 52 | − | |
| 53 | − rotation: true | |
| 54 | − | |
| 55 | 47 | port: |
| 56 | 48 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 57 | 49 | unevaluatedProperties: false |
| @@ -89,7 +81,7 @@ required: · 31 unmodified lines | ||
| 89 | 81 | - ovdd-supply |
| 90 | 82 | - port |
| 91 | 83 | |
| 92 | −additionalProperties: false | |
| 84 | +unevaluatedProperties: false | |
| 93 | 85 | |
| 94 | 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 | 48 | iommus: |
| 49 | 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 | 59 | operating-points-v2: true |
| 52 | 60 | opp-table: |
| 53 | 61 | type: object |
| @@ -68,6 +68,13 @@ properties: · 67 unmodified lines | ||
| 68 | 68 | iommus: |
| 69 | 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 | 78 | required: |
| 72 | 79 | - compatible |
| 73 | 80 | - reg |
| @@ -75,13 +75,20 @@ properties: · 74 unmodified lines | ||
| 75 | 75 | power-domains: |
| 76 | 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 | 84 | patternProperties: |
| 79 | 85 | "^pmu@[0-9a-f]+$": |
| 80 | 86 | type: object |
| 81 | 87 | additionalProperties: false |
| 88 | + deprecated: true | |
| 82 | 89 | description: |
| 83 | 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 | 93 | properties: |
| 87 | 94 | reg: |
| @@ -131,6 +138,7 @@ required: · 43 unmodified lines | ||
| 131 | 138 | - clock-names |
| 132 | 139 | - interrupts |
| 133 | 140 | - ranges |
| 141 | + - samsung,pmu-syscon | |
| 134 | 142 | - '#size-cells' |
| 135 | 143 | |
| 136 | 144 | additionalProperties: false |
| @@ -179,15 +187,12 @@ examples: · 42 unmodified lines | ||
| 179 | 187 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; |
| 180 | 188 | iommu-names = "isp", "drc", "fd", "mcuctl"; |
| 181 | 189 | power-domains = <&pd_isp>; |
| 190 | + samsung,pmu-syscon = <&pmu_system_controller>; | |
| 182 | 191 | |
| 183 | 192 | #address-cells = <1>; |
| 184 | 193 | #size-cells = <1>; |
| 185 | 194 | ranges; |
| 186 | 195 | |
| 187 | − pmu@10020000 { | |
| 188 | − reg = <0x10020000 0x3000>; | |
| 189 | − }; | |
| 190 | − | |
| 191 | 196 | i2c-isp@12140000 { |
| 192 | 197 | compatible = "samsung,exynos4212-i2c-isp"; |
| 193 | 198 | reg = <0x12140000 0x100>; |
| @@ -118,7 +118,7 @@ examples: · 117 unmodified lines | ||
| 118 | 118 | #clock-cells = <1>; |
| 119 | 119 | #address-cells = <1>; |
| 120 | 120 | #size-cells = <1>; |
| 121 | − ranges = <0x0 0x0 0x18000000>; | |
| 121 | + ranges = <0x0 0x0 0xba1000>; | |
| 122 | 122 | |
| 123 | 123 | clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>, |
| 124 | 124 | <&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>; |
| @@ -133,9 +133,9 @@ examples: · 8 unmodified lines | ||
| 133 | 133 | pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; |
| 134 | 134 | pinctrl-names = "default"; |
| 135 | 135 | |
| 136 | − fimc@11800000 { | |
| 136 | + fimc@0 { | |
| 137 | 137 | compatible = "samsung,exynos4212-fimc"; |
| 138 | − reg = <0x11800000 0x1000>; | |
| 138 | + reg = <0x00000000 0x1000>; | |
| 139 | 139 | interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; |
| 140 | 140 | clocks = <&clock CLK_FIMC0>, |
| 141 | 141 | <&clock CLK_SCLK_FIMC0>; |
| @@ -152,9 +152,9 @@ examples: · 10 unmodified lines | ||
| 152 | 152 | |
| 153 | 153 | /* ... FIMC 1-3 */ |
| 154 | 154 | |
| 155 | − csis@11880000 { | |
| 155 | + csis@80000 { | |
| 156 | 156 | compatible = "samsung,exynos4210-csis"; |
| 157 | − reg = <0x11880000 0x4000>; | |
| 157 | + reg = <0x00080000 0x4000>; | |
| 158 | 158 | interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; |
| 159 | 159 | clocks = <&clock CLK_CSIS0>, |
| 160 | 160 | <&clock CLK_SCLK_CSIS0>; |
| @@ -187,9 +187,9 @@ examples: · 26 unmodified lines | ||
| 187 | 187 | |
| 188 | 188 | /* ... CSIS 1 */ |
| 189 | 189 | |
| 190 | − fimc-lite@12390000 { | |
| 190 | + fimc-lite@b90000 { | |
| 191 | 191 | compatible = "samsung,exynos4212-fimc-lite"; |
| 192 | − reg = <0x12390000 0x1000>; | |
| 192 | + reg = <0xb90000 0x1000>; | |
| 193 | 193 | interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; |
| 194 | 194 | power-domains = <&pd_isp>; |
| 195 | 195 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>; |
| @@ -199,9 +199,9 @@ examples: · 3 unmodified lines | ||
| 199 | 199 | |
| 200 | 200 | /* ... FIMC-LITE 1 */ |
| 201 | 201 | |
| 202 | − fimc-is@12000000 { | |
| 202 | + fimc-is@800000 { | |
| 203 | 203 | compatible = "samsung,exynos4212-fimc-is"; |
| 204 | − reg = <0x12000000 0x260000>; | |
| 204 | + reg = <0x00800000 0x260000>; | |
| 205 | 205 | interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, |
| 206 | 206 | <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; |
| 207 | 207 | clocks = <&isp_clock CLK_ISP_FIMC_LITE0>, |
| @@ -237,18 +237,15 @@ examples: · 29 unmodified lines | ||
| 237 | 237 | <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>; |
| 238 | 238 | iommu-names = "isp", "drc", "fd", "mcuctl"; |
| 239 | 239 | power-domains = <&pd_isp>; |
| 240 | + samsung,pmu-syscon = <&pmu_system_controller>; | |
| 240 | 241 | |
| 241 | 242 | #address-cells = <1>; |
| 242 | 243 | #size-cells = <1>; |
| 243 | 244 | ranges; |
| 244 | 245 | |
| 245 | − pmu@10020000 { | |
| 246 | − reg = <0x10020000 0x3000>; | |
| 247 | − }; | |
| 248 | − | |
| 249 | − i2c-isp@12140000 { | |
| 246 | + i2c-isp@940000 { | |
| 250 | 247 | compatible = "samsung,exynos4212-i2c-isp"; |
| 251 | − reg = <0x12140000 0x100>; | |
| 248 | + reg = <0x00940000 0x100>; | |
| 252 | 249 | clocks = <&isp_clock CLK_ISP_I2C1_ISP>; |
| 253 | 250 | clock-names = "i2c_isp"; |
| 254 | 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 | 160 | $ref: /schemas/types.yaml#/definitions/uint32-array |
| 161 | 161 | minItems: 1 |
| 162 | 162 | maxItems: 8 |
| 163 | + uniqueItems: true | |
| 163 | 164 | items: |
| 164 | 165 | # Assume up to 9 physical lane indices |
| 165 | 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 | 309 | - nuvoton,w83773g |
| 310 | 310 | # OKI ML86V7667 video decoder |
| 311 | 311 | - oki,ml86v7667 |
| 312 | − # OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus | |
| 313 | − - ovti,ov5642 | |
| 314 | 312 | # 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch |
| 315 | 313 | - plx,pex8648 |
| 316 | 314 | # Pulsedlight LIDAR range-finding sensor |
| @@ -1,8 +1,14 @@ | ||
| 1 | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | +.. _media_writing_camera_sensor_drivers: | |
| 4 | + | |
| 3 | 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 | 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 | 20 | Camera sensors have an internal clock tree including a PLL and a number of |
| 15 | 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 | 23 | and the link frequency. The two parameters generally are obtained from system |
| 18 | 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 | 38 | Devicetree |
| 33 | 39 | ~~~~~~~~~~ |
| 34 | 40 | |
| 35 | −The currently preferred way to achieve this is using ``assigned-clocks``, | |
| 36 | −``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See | |
| 37 | −``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more | |
| 38 | −information. The driver then gets the frequency using ``clk_get_rate()``. | |
| 41 | +The preferred way to achieve this is using ``assigned-clocks``, | |
| 42 | +``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See the | |
| 43 | +`clock device tree bindings | |
| 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 | 48 | This approach has the drawback that there's no guarantee that the frequency |
| 41 | 49 | hasn't been modified directly or indirectly by another driver, or supported by |
| 42 | 50 | the board's clock tree to begin with. Changes to the Common Clock Framework API |
| 43 | 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 | 53 | Power management |
| 121 | 54 | ---------------- |
| 122 | 55 | |
| 123 | −Always use runtime PM to manage the power states of your device. Camera sensor | |
| 124 | −drivers are in no way special in this respect: they are responsible for | |
| 125 | −controlling the power state of the device they otherwise control as well. In | |
| 126 | −general, the device must be powered on at least when its registers are being | |
| 127 | −accessed and when it is streaming. | |
| 128 | − | |
| 129 | −Existing camera sensor drivers may rely on the old | |
| 130 | −struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to | |
| 131 | −manage their power state. This is however **deprecated**. If you feel you need | |
| 132 | −to begin calling an s_power from an ISP or a bridge driver, instead please add | |
| 133 | −runtime PM support to the sensor driver you are using. Likewise, new drivers | |
| 134 | −should not use s_power. | |
| 135 | − | |
| 136 | −Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and | |
| 137 | −``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI | |
| 138 | −and DT based systems. | |
| 56 | +Camera sensors are used in conjunction with other devices to form a camera | |
| 57 | +pipeline. They must obey the rules listed herein to ensure coherent power | |
| 58 | +management over the pipeline. | |
| 59 | + | |
| 60 | +Camera sensor drivers are responsible for controlling the power state of the | |
| 61 | +device they otherwise control as well. They shall use runtime PM to manage | |
| 62 | +power states. Runtime PM shall be enabled at probe time and disabled at remove | |
| 63 | +time. Drivers should enable runtime PM autosuspend. | |
| 64 | + | |
| 65 | +The runtime PM handlers shall handle clocks, regulators, GPIOs, and other | |
| 66 | +system resources required to power the sensor up and down. For drivers that | |
| 67 | +don't use any of those resources (such as drivers that support ACPI systems | |
| 68 | +only), the runtime PM handlers may be left unimplemented. | |
| 69 | + | |
| 70 | +In general, the device shall be powered on at least when its registers are | |
| 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 | 97 | Control framework |
| 141 | 98 | ~~~~~~~~~~~~~~~~~ |
| @@ -155,21 +112,36 @@ access the device. · 13 unmodified lines | ||
| 155 | 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 | 115 | Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation |
| 167 | 116 | information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to |
| 168 | 117 | register the appropriate controls. |
| 169 | 118 | |
| 170 | −Sensor drivers that have any vertical or horizontal flips embedded in the | |
| 171 | −register programming sequences shall initialize the V4L2_CID_HFLIP and | |
| 172 | −V4L2_CID_VFLIP controls with the values programmed by the register sequences. | |
| 173 | −The default values of these controls shall be 0 (disabled). Especially these | |
| 174 | −controls shall not be inverted, independently of the sensor's mounting | |
| 175 | −rotation. | |
| 119 | +.. _media-camera-sensor-examples: | |
| 120 | + | |
| 121 | +Example drivers | |
| 122 | +--------------- | |
| 123 | + | |
| 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 | 30 | sink pad (0). |
| 31 | 31 | |
| 32 | 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 | 34 | crop at the end of the lines and frames. |
| 35 | 35 | |
| 36 | 36 | Scaler |
| @@ -78,6 +78,14 @@ For SMIA (non-++) compliant devices the static data file name is · 41 unmodified lines | ||
| 78 | 78 | vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID |
| 79 | 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 | 89 | Register definition generator |
| 82 | 90 | ----------------------------- |
| 83 | 91 | |
| @@ -13,7 +13,6 @@ Video4Linux devices · 12 unmodified lines | ||
| 13 | 13 | v4l2-subdev |
| 14 | 14 | v4l2-event |
| 15 | 15 | v4l2-controls |
| 16 | − v4l2-videobuf | |
| 17 | 16 | v4l2-videobuf2 |
| 18 | 17 | v4l2-dv-timings |
| 19 | 18 | v4l2-flash-led-class |
| @@ -157,14 +157,6 @@ changing the e.g. exposure of the webcam. · 156 unmodified lines | ||
| 157 | 157 | Of course, you can always do all the locking yourself by leaving both lock |
| 158 | 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 | 160 | In the case of :ref:`videobuf2 <vb2_framework>` you will need to implement the |
| 169 | 161 | ``wait_prepare()`` and ``wait_finish()`` callbacks to unlock/lock if applicable. |
| 170 | 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 | 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 | 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 | 32 | :numbered: |
| 33 | 33 | |
| 34 | 34 | aspeed-video |
| 35 | + camera-sensor | |
| 35 | 36 | ccs |
| 36 | 37 | cx2341x-uapi |
| 37 | 38 | dw100 |
| 38 | 39 | imx-uapi |
| 39 | 40 | max2175 |
| 41 | + npcm-video | |
| 40 | 42 | omap3isp-uapi |
| 41 | 43 | st-vgxy61 |
| 42 | 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 | 60 | - - ``ENOTTY`` |
| 61 | 61 | |
| 62 | − - The ioctl is not supported by the driver, actually meaning that | |
| 63 | − the required functionality is not available, or the file | |
| 64 | − descriptor is not for a media device. | |
| 62 | + - The ioctl is not supported by the file descriptor. | |
| 65 | 63 | |
| 66 | 64 | - - ``ENOSPC`` |
| 67 | 65 | |
| @@ -549,9 +549,9 @@ Buffer Flags · 548 unmodified lines | ||
| 549 | 549 | - 0x00000400 |
| 550 | 550 | - The buffer has been prepared for I/O and can be queued by the |
| 551 | 551 | application. Drivers set or clear this flag when the |
| 552 | − :ref:`VIDIOC_QUERYBUF`, | |
| 552 | + :ref:`VIDIOC_QUERYBUF <VIDIOC_QUERYBUF>`, | |
| 553 | 553 | :ref:`VIDIOC_PREPARE_BUF <VIDIOC_QBUF>`, |
| 554 | − :ref:`VIDIOC_QBUF` or | |
| 554 | + :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` or | |
| 555 | 555 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl is called. |
| 556 | 556 | * .. _`V4L2-BUF-FLAG-NO-CACHE-INVALIDATE`: |
| 557 | 557 | |
| @@ -143,9 +143,13 @@ Control IDs · 142 unmodified lines | ||
| 143 | 143 | recognise the difference between digital and analogue gain use |
| 144 | 144 | controls ``V4L2_CID_DIGITAL_GAIN`` and ``V4L2_CID_ANALOGUE_GAIN``. |
| 145 | 145 | |
| 146 | +.. _v4l2-cid-hflip: | |
| 147 | + | |
| 146 | 148 | ``V4L2_CID_HFLIP`` ``(boolean)`` |
| 147 | 149 | Mirror the picture horizontally. |
| 148 | 150 | |
| 151 | +.. _v4l2-cid-vflip: | |
| 152 | + | |
| 149 | 153 | ``V4L2_CID_VFLIP`` ``(boolean)`` |
| 150 | 154 | Mirror the picture vertically. |
| 151 | 155 | |
| @@ -579,20 +579,19 @@ is started. · 578 unmodified lines | ||
| 579 | 579 | |
| 580 | 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 | |
| 583 | −Controller API <media_controller>` | |
| 582 | +1. Set up links. Connect the pads between sub-devices using the | |
| 583 | + :ref:`Media Controller API <media_controller>` | |
| 584 | 584 | |
| 585 | −2) Streams. Streams are declared and their routing is configured by | |
| 586 | −setting the routing table for the sub-device using | |
| 587 | −:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that | |
| 588 | −setting the routing table will reset formats and selections in the | |
| 589 | −sub-device to default values. | |
| 585 | +2. Streams. Streams are declared and their routing is configured by setting the | |
| 586 | + routing table for the sub-device using :ref:`VIDIOC_SUBDEV_S_ROUTING | |
| 587 | + <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that setting the routing table will | |
| 588 | + reset formats and selections in the sub-device to default values. | |
| 590 | 589 | |
| 591 | −3) Configure formats and selections. Formats and selections of each stream | |
| 592 | −are configured separately as documented for plain sub-devices in | |
| 593 | −: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 | |
| 595 | −:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. | |
| 590 | +3. Configure formats and selections. Formats and selections of each stream are | |
| 591 | + configured separately as documented for plain sub-devices in | |
| 592 | + :ref:`format-propagation`. The stream ID is set to the same stream ID | |
| 593 | + associated with either sink or source pads of routes configured using the | |
| 594 | + :ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. | |
| 596 | 595 | |
| 597 | 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 | 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, | |
| 622 | −bridge to the receiver, and the receiver to the DMA engines. This step does | |
| 623 | −not differ from normal non-multiplexed media controller setup. | |
| 620 | +1. Set up media links between entities: connect the sensors to the bridge, | |
| 621 | + bridge to the receiver, and the receiver to the DMA engines. This step does | |
| 622 | + not differ from normal non-multiplexed media controller setup. | |
| 624 | 623 | |
| 625 | −2) Configure routing | |
| 624 | +2. Configure routing | |
| 626 | 625 | |
| 627 | 626 | .. flat-table:: Bridge routing table |
| 628 | 627 | :header-rows: 1 |
| @@ -656,14 +655,14 @@ not differ from normal non-multiplexed media controller setup. · 27 unmodified lines | ||
| 656 | 655 | - V4L2_SUBDEV_ROUTE_FL_ACTIVE |
| 657 | 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 | |
| 662 | −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 | |
| 664 | −to the value of the stream ID. | |
| 660 | + After configuring routing, the next step is configuring the formats and | |
| 661 | + selections for the streams. This is similar to performing this step without | |
| 662 | + streams, with just one exception: the ``stream`` field needs to be assigned | |
| 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 | |
| 667 | −configurations along the stream towards the receiver, | |
| 668 | −using :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each | |
| 669 | −stream endpoint in each sub-device. | |
| 665 | + A common way to accomplish this is to start from the sensors and propagate | |
| 666 | + the configurations along the stream towards the receiver, using | |
| 667 | + :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each | |
| 668 | + stream endpoint in each sub-device. | |
| @@ -33,6 +33,27 @@ current DV timings they use the · 32 unmodified lines | ||
| 33 | 33 | the DV timings as seen by the video receiver applications use the |
| 34 | 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 | 57 | Applications can make use of the :ref:`input-capabilities` and |
| 37 | 58 | :ref:`output-capabilities` flags to determine whether the digital |
| 38 | 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 | 288 | - 'MT2110R' |
| 289 | 289 | - This format is two-planar 10-Bit raster mode and having similitude with |
| 290 | 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 | 298 | .. raw:: latex |
| 292 | 299 | |
| 293 | 300 | \normalsize |
| @@ -60,7 +60,7 @@ Each cell is one byte. · 59 unmodified lines | ||
| 60 | 60 | G\ :sub:`10low`\ (bits 3--0) |
| 61 | 61 | - G\ :sub:`12high` |
| 62 | 62 | - R\ :sub:`13high` |
| 63 | − - R\ :sub:`13low`\ (bits 3--2) | |
| 63 | + - R\ :sub:`13low`\ (bits 7--4) | |
| 64 | 64 | |
| 65 | 65 | G\ :sub:`12low`\ (bits 3--0) |
| 66 | 66 | - - start + 12: |
| @@ -82,6 +82,6 @@ Each cell is one byte. · 15 unmodified lines | ||
| 82 | 82 | G\ :sub:`30low`\ (bits 3--0) |
| 83 | 83 | - G\ :sub:`32high` |
| 84 | 84 | - R\ :sub:`33high` |
| 85 | − - R\ :sub:`33low`\ (bits 3--2) | |
| 85 | + - R\ :sub:`33low`\ (bits 7--4) | |
| 86 | 86 | |
| 87 | 87 | G\ :sub:`32low`\ (bits 3--0) |
| @@ -2510,6 +2510,18 @@ F: drivers/rtc/rtc-nct3018y.c · 2509 unmodified lines | ||
| 2510 | 2510 | F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h |
| 2511 | 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 | 2525 | ARM/NUVOTON WPCM450 ARCHITECTURE |
| 2514 | 2526 | M: Jonathan Neuschäfer <j.neuschaefer@gmx.net> |
| 2515 | 2527 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) |
| @@ -6143,6 +6155,13 @@ L: linux-gpio@vger.kernel.org · 3627 unmodified lines | ||
| 6143 | 6155 | S: Maintained |
| 6144 | 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 | 6165 | DIOLAN U2C-12 I2C DRIVER |
| 6147 | 6166 | M: Guenter Roeck <linux@roeck-us.net> |
| 6148 | 6167 | L: linux-i2c@vger.kernel.org |
| @@ -14684,6 +14703,14 @@ L: linux-mtd@lists.infradead.org · 8535 unmodified lines | ||
| 14684 | 14703 | S: Maintained |
| 14685 | 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 | 14714 | MT9P031 APTINA CAMERA SENSOR |
| 14688 | 14715 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 14689 | 14716 | L: linux-media@vger.kernel.org |
| @@ -15926,7 +15953,7 @@ L: linux-media@vger.kernel.org · 1236 unmodified lines | ||
| 15926 | 15953 | S: Maintained |
| 15927 | 15954 | T: git git://linuxtv.org/media_tree.git |
| 15928 | 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 | 15958 | OMNIVISION OV5640 SENSOR DRIVER |
| 15932 | 15959 | M: Steve Longerbeam <slongerbeam@gmail.com> |
| @@ -16016,8 +16043,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov8858.yaml · 83 unmodified lines | ||
| 16016 | 16043 | F: drivers/media/i2c/ov8858.c |
| 16017 | 16044 | |
| 16018 | 16045 | OMNIVISION OV9282 SENSOR DRIVER |
| 16019 | −M: Paul J. Murphy <paul.j.murphy@intel.com> | |
| 16020 | −M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | |
| 16046 | +M: Dave Stevenson <dave.stevenson@raspberrypi.com> | |
| 16021 | 16047 | L: linux-media@vger.kernel.org |
| 16022 | 16048 | S: Maintained |
| 16023 | 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 | 18693 | ROCKCHIP ISP V1 DRIVER |
| 18668 | 18694 | M: Dafna Hirschfeld <dafna@fastmail.com> |
| 18695 | +M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | |
| 18669 | 18696 | L: linux-media@vger.kernel.org |
| 18670 | 18697 | L: linux-rockchip@lists.infradead.org |
| 18671 | 18698 | S: Maintained |
| @@ -20160,19 +20187,15 @@ T: git git://linuxtv.org/media_tree.git · 1488 unmodified lines | ||
| 20160 | 20187 | F: drivers/media/i2c/imx319.c |
| 20161 | 20188 | |
| 20162 | 20189 | SONY IMX334 SENSOR DRIVER |
| 20163 | −M: Paul J. Murphy <paul.j.murphy@intel.com> | |
| 20164 | −M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | |
| 20165 | 20190 | L: linux-media@vger.kernel.org |
| 20166 | −S: Maintained | |
| 20191 | +S: Orphan | |
| 20167 | 20192 | T: git git://linuxtv.org/media_tree.git |
| 20168 | 20193 | F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml |
| 20169 | 20194 | F: drivers/media/i2c/imx334.c |
| 20170 | 20195 | |
| 20171 | 20196 | SONY IMX335 SENSOR DRIVER |
| 20172 | −M: Paul J. Murphy <paul.j.murphy@intel.com> | |
| 20173 | −M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | |
| 20174 | 20197 | L: linux-media@vger.kernel.org |
| 20175 | −S: Maintained | |
| 20198 | +S: Orphan | |
| 20176 | 20199 | T: git git://linuxtv.org/media_tree.git |
| 20177 | 20200 | F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml |
| 20178 | 20201 | F: drivers/media/i2c/imx335.c |
| @@ -20185,10 +20208,8 @@ T: git git://linuxtv.org/media_tree.git · 6 unmodified lines | ||
| 20185 | 20208 | F: drivers/media/i2c/imx355.c |
| 20186 | 20209 | |
| 20187 | 20210 | SONY IMX412 SENSOR DRIVER |
| 20188 | −M: Paul J. Murphy <paul.j.murphy@intel.com> | |
| 20189 | −M: Daniele Alessandrelli <daniele.alessandrelli@intel.com> | |
| 20190 | 20211 | L: linux-media@vger.kernel.org |
| 20191 | −S: Maintained | |
| 20212 | +S: Orphan | |
| 20192 | 20213 | T: git git://linuxtv.org/media_tree.git |
| 20193 | 20214 | F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml |
| 20194 | 20215 | F: drivers/media/i2c/imx412.c |
| @@ -21752,6 +21773,13 @@ F: Documentation/devicetree/bindings/media/i2c/ti,ds90* · 1557 unmodified lines | ||
| 21752 | 21773 | F: drivers/media/i2c/ds90* |
| 21753 | 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 | 21783 | TI KEYSTONE MULTICORE NAVIGATOR DRIVERS |
| 21756 | 21784 | M: Nishanth Menon <nm@ti.com> |
| 21757 | 21785 | M: Santosh Shilimkar <ssantosh@kernel.org> |
| @@ -477,7 +477,6 @@ CONFIG_LIRC=y · 476 unmodified lines | ||
| 477 | 477 | CONFIG_RC_DEVICES=y |
| 478 | 478 | CONFIG_IR_GPIO_TX=m |
| 479 | 479 | CONFIG_IR_PWM_TX=m |
| 480 | −CONFIG_IR_RX51=m | |
| 481 | 480 | CONFIG_IR_SPI=m |
| 482 | 481 | CONFIG_MEDIA_SUPPORT=m |
| 483 | 482 | CONFIG_V4L_PLATFORM_DRIVERS=y |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | # Please keep it in alphabetic order |
| 7 | 7 | obj-$(CONFIG_CEC_CROS_EC) += cros-ec/ |
| 8 | 8 | obj-$(CONFIG_CEC_GPIO) += cec-gpio/ |
| 9 | −obj-$(CONFIG_CEC_MESON_AO) += meson/ | |
| 9 | +obj-y += meson/ | |
| 10 | 10 | obj-$(CONFIG_CEC_SAMSUNG_S5P) += s5p/ |
| 11 | 11 | obj-$(CONFIG_CEC_SECO) += seco/ |
| 12 | 12 | obj-$(CONFIG_CEC_STI) += sti/ |
| @@ -22,50 +22,124 @@ · 21 unmodified lines | ||
| 22 | 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 | |
| 28 | − * @notifier: Notifier info for responding to EC events | |
| 27 | + * @port_num: port number | |
| 29 | 28 | * @adap: CEC adapter |
| 30 | 29 | * @notify: CEC notifier pointer |
| 31 | 30 | * @rx_msg: storage for a received message |
| 31 | + * @cros_ec_cec: pointer to the parent struct | |
| 32 | 32 | */ |
| 33 | −struct cros_ec_cec { | |
| 34 | − struct cros_ec_device *cros_ec; | |
| 35 | − struct notifier_block notifier; | |
| 33 | +struct cros_ec_cec_port { | |
| 34 | + int port_num; | |
| 36 | 35 | struct cec_adapter *adap; |
| 37 | 36 | struct cec_notifier *notify; |
| 38 | 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 | 70 | static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) |
| 42 | 71 | { |
| 43 | 72 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 44 | 73 | uint8_t *cec_message = cros_ec->event_data.data.cec_message; |
| 45 | 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) | |
| 48 | − len = CEC_MAX_MSG_SIZE; | |
| 49 | − cros_ec_cec->rx_msg.len = len; | |
| 50 | − memcpy(cros_ec_cec->rx_msg.msg, cec_message, len); | |
| 94 | + cros_ec_cec_received_message(port, cec_message, len); | |
| 95 | +} | |
| 96 | + | |
| 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 | 117 | static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) |
| 56 | 118 | { |
| 57 | 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 | 132 | if (events & EC_MKBP_CEC_SEND_OK) |
| 61 | − cec_transmit_attempt_done(cros_ec_cec->adap, | |
| 62 | − CEC_TX_STATUS_OK); | |
| 133 | + cec_transmit_attempt_done(port->adap, CEC_TX_STATUS_OK); | |
| 63 | 134 | |
| 64 | 135 | /* FW takes care of all retries, tell core to avoid more retries */ |
| 65 | 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 | 138 | CEC_TX_STATUS_MAX_RETRIES | |
| 68 | 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 | 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 | 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 | 172 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 98 | − struct { | |
| 99 | − struct cros_ec_command msg; | |
| 100 | − struct ec_params_cec_set data; | |
| 101 | − } __packed msg = {}; | |
| 173 | + struct ec_params_cec_set params = { | |
| 174 | + .cmd = CEC_CMD_LOGICAL_ADDRESS, | |
| 175 | + .port = port->port_num, | |
| 176 | + .val = logical_addr, | |
| 177 | + }; | |
| 102 | 178 | int ret; |
| 103 | 179 | |
| 104 | − msg.msg.command = EC_CMD_CEC_SET; | |
| 105 | − msg.msg.outsize = sizeof(msg.data); | |
| 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); | |
| 180 | + ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), | |
| 181 | + NULL, 0); | |
| 110 | 182 | if (ret < 0) { |
| 111 | 183 | dev_err(cros_ec->dev, |
| 112 | 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 | 191 | static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, |
| 120 | 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 | 196 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 124 | − struct { | |
| 125 | − struct cros_ec_command msg; | |
| 126 | − struct ec_params_cec_write data; | |
| 127 | − } __packed msg = {}; | |
| 197 | + struct ec_params_cec_write params; | |
| 198 | + struct ec_params_cec_write_v1 params_v1; | |
| 128 | 199 | int ret; |
| 129 | 200 | |
| 130 | − msg.msg.command = EC_CMD_CEC_WRITE_MSG; | |
| 131 | − msg.msg.outsize = cec_msg->len; | |
| 132 | − memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); | |
| 201 | + if (cros_ec_cec->write_cmd_version == 0) { | |
| 202 | + memcpy(params.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 | 214 | if (ret < 0) { |
| 136 | 215 | dev_err(cros_ec->dev, |
| 137 | 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 | 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 | 227 | struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; |
| 148 | − struct { | |
| 149 | − struct cros_ec_command msg; | |
| 150 | − struct ec_params_cec_set data; | |
| 151 | − } __packed msg = {}; | |
| 228 | + struct ec_params_cec_set params = { | |
| 229 | + .cmd = CEC_CMD_ENABLE, | |
| 230 | + .port = port->port_num, | |
| 231 | + .val = enable, | |
| 232 | + }; | |
| 152 | 233 | int ret; |
| 153 | 234 | |
| 154 | − msg.msg.command = EC_CMD_CEC_SET; | |
| 155 | − msg.msg.outsize = sizeof(msg.data); | |
| 156 | − msg.data.cmd = CEC_CMD_ENABLE; | |
| 157 | − msg.data.val = enable; | |
| 158 | − | |
| 159 | − ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); | |
| 235 | + ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), | |
| 236 | + NULL, 0); | |
| 160 | 237 | if (ret < 0) { |
| 161 | 238 | dev_err(cros_ec->dev, |
| 162 | 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 | 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 | |
| 207 | − * connector we specify along with the DRM device name handling the HDMI output | |
| 283 | + * Specify the DRM device name handling the HDMI output and the HDMI connector | |
| 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 | 290 | struct cec_dmi_match { |
| 211 | 291 | const char *sys_vendor; |
| 212 | 292 | const char *product_name; |
| 213 | 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 | 302 | static const struct cec_dmi_match cec_dmi_match_table[] = { |
| 218 | 303 | /* Google Fizz */ |
| 219 | − { "Google", "Fizz", "0000:00:02.0", "Port B" }, | |
| 304 | + { "Google", "Fizz", "0000:00:02.0", port_b_conns }, | |
| 220 | 305 | /* Google Brask */ |
| 221 | − { "Google", "Brask", "0000:00:02.0", "Port B" }, | |
| 306 | + { "Google", "Brask", "0000:00:02.0", port_b_conns }, | |
| 222 | 307 | /* Google Moli */ |
| 223 | − { "Google", "Moli", "0000:00:02.0", "Port B" }, | |
| 308 | + { "Google", "Moli", "0000:00:02.0", port_b_conns }, | |
| 224 | 309 | /* Google Kinox */ |
| 225 | − { "Google", "Kinox", "0000:00:02.0", "Port B" }, | |
| 310 | + { "Google", "Kinox", "0000:00:02.0", port_b_conns }, | |
| 226 | 311 | /* Google Kuldax */ |
| 227 | − { "Google", "Kuldax", "0000:00:02.0", "Port B" }, | |
| 312 | + { "Google", "Kuldax", "0000:00:02.0", port_b_conns }, | |
| 228 | 313 | /* Google Aurash */ |
| 229 | − { "Google", "Aurash", "0000:00:02.0", "Port B" }, | |
| 314 | + { "Google", "Aurash", "0000:00:02.0", port_b_conns }, | |
| 230 | 315 | /* Google Gladios */ |
| 231 | − { "Google", "Gladios", "0000:00:02.0", "Port B" }, | |
| 316 | + { "Google", "Gladios", "0000:00:02.0", port_b_conns }, | |
| 232 | 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 | 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 | 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 | 344 | if (!d) |
| 252 | 345 | return ERR_PTR(-EPROBE_DEFER); |
| 253 | 346 | put_device(d); |
| 254 | − *conn = m->conn; | |
| 347 | + *conns = m->conns; | |
| 255 | 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 | 358 | #else |
| 266 | 359 | |
| 267 | 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 | 363 | return ERR_PTR(-ENODEV); |
| 271 | 364 | } |
| 272 | 365 | |
| 273 | 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 | 481 | static int cros_ec_cec_probe(struct platform_device *pdev) |
| 276 | 482 | { |
| 277 | 483 | struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); |
| 278 | 484 | struct cros_ec_device *cros_ec = ec_dev->ec_dev; |
| 279 | 485 | struct cros_ec_cec *cros_ec_cec; |
| 486 | + struct cros_ec_cec_port *port; | |
| 280 | 487 | struct device *hdmi_dev; |
| 281 | − const char *conn = NULL; | |
| 488 | + const char * const *conns = NULL; | |
| 282 | 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 | 492 | if (IS_ERR(hdmi_dev)) |
| 286 | 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 | 503 | device_init_wakeup(&pdev->dev, 1); |
| 297 | 504 | |
| 298 | − cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, | |
| 299 | − DRV_NAME, | |
| 300 | − CEC_CAP_DEFAULTS | | |
| 301 | − CEC_CAP_CONNECTOR_INFO, 1); | |
| 302 | − if (IS_ERR(cros_ec_cec->adap)) | |
| 303 | − return PTR_ERR(cros_ec_cec->adap); | |
| 505 | + ret = cros_ec_cec_get_num_ports(cros_ec_cec); | |
| 506 | + if (ret) | |
| 507 | + return ret; | |
| 304 | 508 | |
| 305 | − cros_ec_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, conn, | |
| 306 | − cros_ec_cec->adap); | |
| 307 | − if (!cros_ec_cec->notify) { | |
| 308 | − ret = -ENOMEM; | |
| 309 | − goto out_probe_adapter; | |
| 509 | + ret = cros_ec_cec_get_write_cmd_version(cros_ec_cec); | |
| 510 | + if (ret) | |
| 511 | + return ret; | |
| 512 | + | |
| 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 | 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 | 523 | &cros_ec_cec->notifier); |
| 316 | 524 | if (ret) { |
| 317 | 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 | 529 | return 0; |
| 326 | 530 | |
| 327 | −out_probe_notify: | |
| 328 | − cec_notifier_cec_adap_unregister(cros_ec_cec->notify, | |
| 329 | − cros_ec_cec->adap); | |
| 330 | −out_probe_adapter: | |
| 331 | − cec_delete_adapter(cros_ec_cec->adap); | |
| 531 | +unregister_ports: | |
| 532 | + /* | |
| 533 | + * Unregister any adapters which have been registered. We don't add the | |
| 534 | + * port to the array until the adapter has been registered successfully, | |
| 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 | 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 | 549 | struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); |
| 338 | 550 | struct device *dev = &pdev->dev; |
| 551 | + struct cros_ec_cec_port *port; | |
| 339 | 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 | 562 | if (ret) |
| 350 | 563 | dev_err(dev, "failed to unregister notifier\n"); |
| 351 | 564 | |
| 352 | − cec_notifier_cec_adap_unregister(cros_ec_cec->notify, | |
| 353 | − cros_ec_cec->adap); | |
| 354 | − cec_unregister_adapter(cros_ec_cec->adap); | |
| 565 | + for (int i = 0; i < cros_ec_cec->num_ports; i++) { | |
| 566 | + port = cros_ec_cec->ports[i]; | |
| 567 | + cec_notifier_cec_adap_unregister(port->notify, port->adap); | |
| 568 | + cec_unregister_adapter(port->adap); | |
| 569 | + } | |
| 355 | 570 | } |
| 356 | 571 | |
| 357 | 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 | 353 | int smsdvb_debugfs_create(struct smsdvb_client_t *client) |
| 354 | 354 | { |
| 355 | 355 | struct smscore_device_t *coredev = client->coredev; |
| 356 | − struct dentry *d; | |
| 357 | 356 | struct smsdvb_debugfs *debug_data; |
| 358 | 357 | |
| 359 | 358 | if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device) |
| 360 | 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 | 361 | debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL); |
| 378 | 362 | if (!debug_data) |
| 379 | 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 | 371 | client->debug_data = debug_data; |
| 382 | 372 | client->prt_dvb_stats = smsdvb_print_dvb_stats; |
| 383 | 373 | client->prt_isdb_stats = smsdvb_print_isdb_stats; |
| @@ -159,7 +159,7 @@ EXPORT_SYMBOL(frame_vector_to_pfns); · 158 unmodified lines | ||
| 159 | 159 | struct frame_vector *frame_vector_create(unsigned int nr_frames) |
| 160 | 160 | { |
| 161 | 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 | 164 | if (WARN_ON_ONCE(nr_frames == 0)) |
| 165 | 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 | 2890 | if (copy_timestamp) |
| 2891 | 2891 | b->timestamp = ktime_get_ns(); |
| 2892 | 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 | 2894 | if (ret) |
| 2895 | 2895 | return ret; |
| 2896 | 2896 | |
| @@ -542,13 +542,14 @@ static void vb2_dc_put_userptr(void *buf_priv) · 541 unmodified lines | ||
| 542 | 542 | */ |
| 543 | 543 | dma_unmap_sgtable(buf->dev, sgt, buf->dma_dir, |
| 544 | 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 | 545 | if (buf->dma_dir == DMA_FROM_DEVICE || |
| 549 | − buf->dma_dir == DMA_BIDIRECTIONAL) | |
| 550 | − for (i = 0; i < frame_vector_count(buf->vec); i++) | |
| 551 | − set_page_dirty_lock(pages[i]); | |
| 546 | + buf->dma_dir == DMA_BIDIRECTIONAL) { | |
| 547 | + pages = frame_vector_pages(buf->vec); | |
| 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 | 553 | sg_free_table(sgt); |
| 553 | 554 | kfree(sgt); |
| 554 | 555 | } else { |
| @@ -133,13 +133,15 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) · 132 unmodified lines | ||
| 133 | 133 | |
| 134 | 134 | if (!buf->vec->is_pfns) { |
| 135 | 135 | n_pages = frame_vector_count(buf->vec); |
| 136 | − pages = frame_vector_pages(buf->vec); | |
| 137 | 136 | if (vaddr) |
| 138 | 137 | vm_unmap_ram((void *)vaddr, n_pages); |
| 139 | 138 | if (buf->dma_dir == DMA_FROM_DEVICE || |
| 140 | − buf->dma_dir == DMA_BIDIRECTIONAL) | |
| 141 | − for (i = 0; i < n_pages; i++) | |
| 142 | − set_page_dirty_lock(pages[i]); | |
| 139 | + buf->dma_dir == DMA_BIDIRECTIONAL) { | |
| 140 | + pages = frame_vector_pages(buf->vec); | |
| 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 | 145 | } else { |
| 144 | 146 | iounmap((__force void __iomem *)buf->vaddr); |
| 145 | 147 | } |
| @@ -4779,8 +4779,8 @@ set_frequency(struct drx_demod_instance *demod, · 4778 unmodified lines | ||
| 4779 | 4779 | bool image_to_select; |
| 4780 | 4780 | s32 fm_frequency_shift = 0; |
| 4781 | 4781 | |
| 4782 | − rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false; | |
| 4783 | − tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true; | |
| 4782 | + rf_mirror = ext_attr->mirror == DRX_MIRROR_YES; | |
| 4783 | + tuner_mirror = !demod->my_common_attr->mirror_freq_spect; | |
| 4784 | 4784 | /* |
| 4785 | 4785 | Program frequency shifter |
| 4786 | 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 | 8765 | goto rw_error; |
| 8766 | 8766 | } |
| 8767 | 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 | 8770 | /* freeze dq/fq updating */ |
| 8771 | 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 | 1921 | dev_dbg(&client->dev, "\n"); |
| 1922 | 1922 | |
| 1923 | − if (dev->dt_client) | |
| 1924 | − i2c_unregister_device(dev->dt_client); | |
| 1923 | + i2c_unregister_device(dev->dt_client); | |
| 1925 | 1924 | |
| 1926 | 1925 | i2c_mux_del_adapters(dev->muxc); |
| 1927 | 1926 | |
| @@ -99,6 +99,7 @@ config VIDEO_IMX214 · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 100 | config VIDEO_IMX219 |
| 101 | 101 | tristate "Sony IMX219 sensor support" |
| 102 | + select V4L2_CCI_I2C | |
| 102 | 103 | help |
| 103 | 104 | This is a Video4Linux2 sensor driver for the Sony |
| 104 | 105 | IMX219 camera. |
| @@ -215,6 +216,16 @@ config VIDEO_MT9M111 · 110 unmodified lines | ||
| 215 | 216 | This driver supports MT9M111, MT9M112 and MT9M131 cameras from |
| 216 | 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 | 229 | config VIDEO_MT9P031 |
| 219 | 230 | tristate "Aptina MT9P031 support" |
| 220 | 231 | select VIDEO_APTINA_PLL |
| @@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o · 64 unmodified lines | ||
| 65 | 65 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
| 66 | 66 | obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o |
| 67 | 67 | obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o |
| 68 | +obj-$(CONFIG_VIDEO_MT9M114) += mt9m114.o | |
| 68 | 69 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o |
| 69 | 70 | obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o |
| 70 | 71 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o |
| @@ -411,43 +411,44 @@ static int adp1653_of_init(struct i2c_client *client, · 410 unmodified lines | ||
| 411 | 411 | struct device_node *node) |
| 412 | 412 | { |
| 413 | 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 | 417 | pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL); |
| 417 | 418 | if (!pd) |
| 418 | 419 | return -ENOMEM; |
| 419 | 420 | flash->platform_data = pd; |
| 420 | 421 | |
| 421 | − child = of_get_child_by_name(node, "flash"); | |
| 422 | − if (!child) | |
| 422 | + node_flash = of_get_child_by_name(node, "flash"); | |
| 423 | + if (!node_flash) | |
| 423 | 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 | 427 | &pd->max_flash_timeout)) |
| 427 | 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 | 431 | &pd->max_flash_intensity)) |
| 431 | 432 | goto err; |
| 432 | 433 | |
| 433 | 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 | 437 | &pd->max_torch_intensity)) |
| 437 | 438 | goto err; |
| 438 | 439 | |
| 439 | 440 | pd->max_torch_intensity /= 1000; |
| 440 | − of_node_put(child); | |
| 441 | 441 | |
| 442 | − child = of_get_child_by_name(node, "indicator"); | |
| 443 | − if (!child) | |
| 444 | − return -EINVAL; | |
| 442 | + node_indicator = of_get_child_by_name(node, "indicator"); | |
| 443 | + if (!node_indicator) | |
| 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 | 447 | &pd->max_indicator_intensity)) |
| 448 | 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 | 453 | pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); |
| 453 | 454 | if (IS_ERR(pd->enable_gpio)) { |
| @@ -458,7 +459,8 @@ static int adp1653_of_init(struct i2c_client *client, · 4 unmodified lines | ||
| 458 | 459 | return 0; |
| 459 | 460 | err: |
| 460 | 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 | 464 | return -EINVAL; |
| 463 | 465 | } |
| 464 | 466 | |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * Copyright (C) 2013 Cogent Embedded, Inc. |
| 6 | 6 | * Copyright (C) 2013 Renesas Solutions Corp. |
| 7 | 7 | */ |
| 8 | +#include <linux/mod_devicetable.h> | |
| 8 | 9 | #include <linux/module.h> |
| 9 | 10 | #include <linux/init.h> |
| 10 | 11 | #include <linux/errno.h> |
| @@ -1395,7 +1396,6 @@ out_unlock: · 1384 unmodified lines | ||
| 1395 | 1396 | |
| 1396 | 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 | 1399 | struct device_node *np = client->dev.of_node; |
| 1400 | 1400 | struct adv7180_state *state; |
| 1401 | 1401 | struct v4l2_subdev *sd; |
| @@ -1411,7 +1411,7 @@ static int adv7180_probe(struct i2c_client *client) · 9 unmodified lines | ||
| 1411 | 1411 | |
| 1412 | 1412 | state->client = client; |
| 1413 | 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 | 1416 | state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", |
| 1417 | 1417 | GPIOD_OUT_HIGH); |
| @@ -1536,22 +1536,6 @@ static void adv7180_remove(struct i2c_client *client) · 118 unmodified lines | ||
| 1536 | 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 | 1539 | #ifdef CONFIG_PM_SLEEP |
| 1556 | 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 | 1569 | #define ADV7180_PM_OPS NULL |
| 1586 | 1570 | #endif |
| 1587 | 1571 | |
| 1588 | −#ifdef CONFIG_OF | |
| 1589 | −static const struct of_device_id adv7180_of_id[] = { | |
| 1590 | − { .compatible = "adi,adv7180", }, | |
| 1591 | − { .compatible = "adi,adv7180cp", }, | |
| 1592 | − { .compatible = "adi,adv7180st", }, | |
| 1593 | − { .compatible = "adi,adv7182", }, | |
| 1594 | − { .compatible = "adi,adv7280", }, | |
| 1595 | − { .compatible = "adi,adv7280-m", }, | |
| 1596 | − { .compatible = "adi,adv7281", }, | |
| 1597 | − { .compatible = "adi,adv7281-m", }, | |
| 1598 | − { .compatible = "adi,adv7281-ma", }, | |
| 1599 | − { .compatible = "adi,adv7282", }, | |
| 1600 | − { .compatible = "adi,adv7282-m", }, | |
| 1601 | − { }, | |
| 1572 | +static const struct i2c_device_id adv7180_id[] = { | |
| 1573 | + { "adv7180", (kernel_ulong_t)&adv7180_info }, | |
| 1574 | + { "adv7180cp", (kernel_ulong_t)&adv7180_info }, | |
| 1575 | + { "adv7180st", (kernel_ulong_t)&adv7180_info }, | |
| 1576 | + { "adv7182", (kernel_ulong_t)&adv7182_info }, | |
| 1577 | + { "adv7280", (kernel_ulong_t)&adv7280_info }, | |
| 1578 | + { "adv7280-m", (kernel_ulong_t)&adv7280_m_info }, | |
| 1579 | + { "adv7281", (kernel_ulong_t)&adv7281_info }, | |
| 1580 | + { "adv7281-m", (kernel_ulong_t)&adv7281_m_info }, | |
| 1581 | + { "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info }, | |
| 1582 | + { "adv7282", (kernel_ulong_t)&adv7282_info }, | |
| 1583 | + { "adv7282-m", (kernel_ulong_t)&adv7282_m_info }, | |
| 1584 | + {} | |
| 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 | 1602 | MODULE_DEVICE_TABLE(of, adv7180_of_id); |
| 1605 | −#endif | |
| 1606 | 1603 | |
| 1607 | 1604 | static struct i2c_driver adv7180_driver = { |
| 1608 | 1605 | .driver = { |
| 1609 | 1606 | .name = KBUILD_MODNAME, |
| 1610 | 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 | 1610 | .probe = adv7180_probe, |
| 1614 | 1611 | .remove = adv7180_remove, |
| @@ -133,8 +133,6 @@ struct ar0521_dev { · 132 unmodified lines | ||
| 133 | 133 | u16 mult2; |
| 134 | 134 | u16 vt_pix; |
| 135 | 135 | } pll; |
| 136 | − | |
| 137 | − bool streaming; | |
| 138 | 136 | }; |
| 139 | 137 | |
| 140 | 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 | 989 | int ret; |
| 992 | 990 | |
| 993 | 991 | mutex_lock(&sensor->lock); |
| 994 | − | |
| 995 | 992 | ret = ar0521_set_stream(sensor, enable); |
| 996 | − if (!ret) | |
| 997 | − sensor->streaming = enable; | |
| 998 | − | |
| 999 | 993 | mutex_unlock(&sensor->lock); |
| 994 | + | |
| 1000 | 995 | return ret; |
| 1001 | 996 | } |
| 1002 | 997 | |
| @@ -1023,28 +1018,6 @@ static const struct v4l2_subdev_ops ar0521_subdev_ops = { · 20 unmodified lines | ||
| 1023 | 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 | 1021 | static int ar0521_probe(struct i2c_client *client) |
| 1049 | 1022 | { |
| 1050 | 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 | 1158 | static const struct dev_pm_ops ar0521_pm_ops = { |
| 1186 | − SET_SYSTEM_SLEEP_PM_OPS(ar0521_suspend, ar0521_resume) | |
| 1187 | 1159 | SET_RUNTIME_PM_OPS(ar0521_power_off, ar0521_power_on, NULL) |
| 1188 | 1160 | }; |
| 1189 | 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 | 508 | struct v4l2_ctrl *ctrl = sensor->exposure; |
| 509 | 509 | int max; |
| 510 | 510 | |
| 511 | − max = sensor->pixel_array->crop[CCS_PA_PAD_SRC].height | |
| 512 | − + sensor->vblank->val | |
| 513 | − - CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); | |
| 511 | + max = sensor->pa_src.height + sensor->vblank->val - | |
| 512 | + CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); | |
| 514 | 513 | |
| 515 | 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 | 727 | break; |
| 729 | 728 | case V4L2_CID_VBLANK: |
| 730 | 729 | rval = ccs_write(sensor, FRAME_LENGTH_LINES, |
| 731 | − sensor->pixel_array->crop[ | |
| 732 | − CCS_PA_PAD_SRC].height | |
| 733 | − + ctrl->val); | |
| 730 | + sensor->pa_src.height + ctrl->val); | |
| 734 | 731 | |
| 735 | 732 | break; |
| 736 | 733 | case V4L2_CID_HBLANK: |
| 737 | 734 | rval = ccs_write(sensor, LINE_LENGTH_PCK, |
| 738 | − sensor->pixel_array->crop[CCS_PA_PAD_SRC].width | |
| 739 | − + ctrl->val); | |
| 735 | + sensor->pa_src.width + ctrl->val); | |
| 740 | 736 | |
| 741 | 737 | break; |
| 742 | 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 | 1211 | min = max_t(int, |
| 1216 | 1212 | CCS_LIM(sensor, MIN_FRAME_BLANKING_LINES), |
| 1217 | − min_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height); | |
| 1218 | − max = max_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height; | |
| 1213 | + min_fll - sensor->pa_src.height); | |
| 1214 | + max = max_fll - sensor->pa_src.height; | |
| 1219 | 1215 | |
| 1220 | 1216 | __v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); |
| 1221 | 1217 | |
| 1222 | − min = max_t(int, | |
| 1223 | − min_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width, | |
| 1224 | − min_lbp); | |
| 1225 | − max = max_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width; | |
| 1218 | + min = max_t(int, min_llp - sensor->pa_src.width, min_lbp); | |
| 1219 | + max = max_llp - sensor->pa_src.width; | |
| 1226 | 1220 | |
| 1227 | 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 | 1241 | dev_dbg(&client->dev, "real timeperframe\t100/%d\n", |
| 1248 | 1242 | sensor->pll.pixel_rate_pixel_array / |
| 1249 | − ((sensor->pixel_array->crop[CCS_PA_PAD_SRC].width | |
| 1250 | − + sensor->hblank->val) * | |
| 1251 | − (sensor->pixel_array->crop[CCS_PA_PAD_SRC].height | |
| 1252 | − + sensor->vblank->val) / 100)); | |
| 1243 | + ((sensor->pa_src.width + sensor->hblank->val) * | |
| 1244 | + (sensor->pa_src.height + sensor->vblank->val) / 100)); | |
| 1253 | 1245 | |
| 1254 | 1246 | return 0; |
| 1255 | 1247 | } |
| @@ -1756,28 +1748,22 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) · 500 unmodified lines | ||
| 1756 | 1748 | goto out; |
| 1757 | 1749 | |
| 1758 | 1750 | /* Analog crop start coordinates */ |
| 1759 | − rval = ccs_write(sensor, X_ADDR_START, | |
| 1760 | − sensor->pixel_array->crop[CCS_PA_PAD_SRC].left); | |
| 1751 | + rval = ccs_write(sensor, X_ADDR_START, sensor->pa_src.left); | |
| 1761 | 1752 | if (rval < 0) |
| 1762 | 1753 | goto out; |
| 1763 | 1754 | |
| 1764 | − rval = ccs_write(sensor, Y_ADDR_START, | |
| 1765 | − sensor->pixel_array->crop[CCS_PA_PAD_SRC].top); | |
| 1755 | + rval = ccs_write(sensor, Y_ADDR_START, sensor->pa_src.top); | |
| 1766 | 1756 | if (rval < 0) |
| 1767 | 1757 | goto out; |
| 1768 | 1758 | |
| 1769 | 1759 | /* Analog crop end coordinates */ |
| 1770 | − rval = ccs_write( | |
| 1771 | − sensor, X_ADDR_END, | |
| 1772 | − sensor->pixel_array->crop[CCS_PA_PAD_SRC].left | |
| 1773 | − + sensor->pixel_array->crop[CCS_PA_PAD_SRC].width - 1); | |
| 1760 | + rval = ccs_write(sensor, X_ADDR_END, | |
| 1761 | + sensor->pa_src.left + sensor->pa_src.width - 1); | |
| 1774 | 1762 | if (rval < 0) |
| 1775 | 1763 | goto out; |
| 1776 | 1764 | |
| 1777 | − rval = ccs_write( | |
| 1778 | − sensor, Y_ADDR_END, | |
| 1779 | − sensor->pixel_array->crop[CCS_PA_PAD_SRC].top | |
| 1780 | − + sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - 1); | |
| 1765 | + rval = ccs_write(sensor, Y_ADDR_END, | |
| 1766 | + sensor->pa_src.top + sensor->pa_src.height - 1); | |
| 1781 | 1767 | if (rval < 0) |
| 1782 | 1768 | goto out; |
| 1783 | 1769 | |
| @@ -1789,27 +1775,23 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) · 5 unmodified lines | ||
| 1789 | 1775 | /* Digital crop */ |
| 1790 | 1776 | if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) |
| 1791 | 1777 | == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { |
| 1792 | − rval = ccs_write( | |
| 1793 | − sensor, DIGITAL_CROP_X_OFFSET, | |
| 1794 | − sensor->scaler->crop[CCS_PAD_SINK].left); | |
| 1778 | + rval = ccs_write(sensor, DIGITAL_CROP_X_OFFSET, | |
| 1779 | + sensor->scaler_sink.left); | |
| 1795 | 1780 | if (rval < 0) |
| 1796 | 1781 | goto out; |
| 1797 | 1782 | |
| 1798 | − rval = ccs_write( | |
| 1799 | − sensor, DIGITAL_CROP_Y_OFFSET, | |
| 1800 | − sensor->scaler->crop[CCS_PAD_SINK].top); | |
| 1783 | + rval = ccs_write(sensor, DIGITAL_CROP_Y_OFFSET, | |
| 1784 | + sensor->scaler_sink.top); | |
| 1801 | 1785 | if (rval < 0) |
| 1802 | 1786 | goto out; |
| 1803 | 1787 | |
| 1804 | − rval = ccs_write( | |
| 1805 | − sensor, DIGITAL_CROP_IMAGE_WIDTH, | |
| 1806 | − sensor->scaler->crop[CCS_PAD_SINK].width); | |
| 1788 | + rval = ccs_write(sensor, DIGITAL_CROP_IMAGE_WIDTH, | |
| 1789 | + sensor->scaler_sink.width); | |
| 1807 | 1790 | if (rval < 0) |
| 1808 | 1791 | goto out; |
| 1809 | 1792 | |
| 1810 | − rval = ccs_write( | |
| 1811 | − sensor, DIGITAL_CROP_IMAGE_HEIGHT, | |
| 1812 | − sensor->scaler->crop[CCS_PAD_SINK].height); | |
| 1793 | + rval = ccs_write(sensor, DIGITAL_CROP_IMAGE_HEIGHT, | |
| 1794 | + sensor->scaler_sink.height); | |
| 1813 | 1795 | if (rval < 0) |
| 1814 | 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 | 1811 | /* Output size from sensor */ |
| 1830 | − rval = ccs_write(sensor, X_OUTPUT_SIZE, | |
| 1831 | − sensor->src->crop[CCS_PAD_SRC].width); | |
| 1812 | + rval = ccs_write(sensor, X_OUTPUT_SIZE, sensor->src_src.width); | |
| 1832 | 1813 | if (rval < 0) |
| 1833 | 1814 | goto out; |
| 1834 | − rval = ccs_write(sensor, Y_OUTPUT_SIZE, | |
| 1835 | − sensor->src->crop[CCS_PAD_SRC].height); | |
| 1815 | + rval = ccs_write(sensor, Y_OUTPUT_SIZE, sensor->src_src.height); | |
| 1836 | 1816 | if (rval < 0) |
| 1837 | 1817 | goto out; |
| 1838 | 1818 | |
| @@ -1923,9 +1903,6 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) · 84 unmodified lines | ||
| 1923 | 1903 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 1924 | 1904 | int rval; |
| 1925 | 1905 | |
| 1926 | − if (sensor->streaming == enable) | |
| 1927 | − return 0; | |
| 1928 | − | |
| 1929 | 1906 | if (!enable) { |
| 1930 | 1907 | ccs_stop_streaming(sensor); |
| 1931 | 1908 | sensor->streaming = false; |
| @@ -2053,24 +2030,8 @@ static int __ccs_get_format(struct v4l2_subdev *subdev, · 121 unmodified lines | ||
| 2053 | 2030 | struct v4l2_subdev_state *sd_state, |
| 2054 | 2031 | struct v4l2_subdev_format *fmt) |
| 2055 | 2032 | { |
| 2056 | − struct ccs_subdev *ssd = to_ccs_subdev(subdev); | |
| 2057 | − | |
| 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 | − } | |
| 2033 | + fmt->format = *v4l2_subdev_get_pad_format(subdev, sd_state, fmt->pad); | |
| 2034 | + fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); | |
| 2074 | 2035 | |
| 2075 | 2036 | return 0; |
| 2076 | 2037 | } |
| @@ -2092,28 +2053,18 @@ static int ccs_get_format(struct v4l2_subdev *subdev, · 15 unmodified lines | ||
| 2092 | 2053 | static void ccs_get_crop_compose(struct v4l2_subdev *subdev, |
| 2093 | 2054 | struct v4l2_subdev_state *sd_state, |
| 2094 | 2055 | struct v4l2_rect **crops, |
| 2095 | − struct v4l2_rect **comps, int which) | |
| 2056 | + struct v4l2_rect **comps) | |
| 2096 | 2057 | { |
| 2097 | 2058 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2098 | 2059 | unsigned int i; |
| 2099 | 2060 | |
| 2100 | − if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { | |
| 2101 | − if (crops) | |
| 2102 | − for (i = 0; i < subdev->entity.num_pads; i++) | |
| 2103 | − crops[i] = &ssd->crop[i]; | |
| 2104 | − if (comps) | |
| 2105 | − *comps = &ssd->compose; | |
| 2106 | − } else { | |
| 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 | − } | |
| 2061 | + if (crops) | |
| 2062 | + for (i = 0; i < subdev->entity.num_pads; i++) | |
| 2063 | + crops[i] = | |
| 2064 | + v4l2_subdev_get_pad_crop(subdev, sd_state, i); | |
| 2065 | + if (comps) | |
| 2066 | + *comps = v4l2_subdev_get_pad_compose(subdev, sd_state, | |
| 2067 | + ssd->sink_pad); | |
| 2117 | 2068 | } |
| 2118 | 2069 | |
| 2119 | 2070 | /* Changes require propagation only on sink pad. */ |
| @@ -2124,8 +2075,9 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 4 unmodified lines | ||
| 2124 | 2075 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2125 | 2076 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2126 | 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 | 2082 | switch (target) { |
| 2131 | 2083 | case V4L2_SEL_TGT_CROP: |
| @@ -2136,6 +2088,7 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 4 unmodified lines | ||
| 2136 | 2088 | sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); |
| 2137 | 2089 | sensor->scaling_mode = |
| 2138 | 2090 | CCS_SCALING_MODE_NO_SCALING; |
| 2091 | + sensor->scaler_sink = *comp; | |
| 2139 | 2092 | } else if (ssd == sensor->binner) { |
| 2140 | 2093 | sensor->binning_horizontal = 1; |
| 2141 | 2094 | sensor->binning_vertical = 1; |
| @@ -2144,6 +2097,11 @@ static void ccs_propagate(struct v4l2_subdev *subdev, · 2 unmodified lines | ||
| 2144 | 2097 | fallthrough; |
| 2145 | 2098 | case V4L2_SEL_TGT_COMPOSE: |
| 2146 | 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 | 2105 | break; |
| 2148 | 2106 | default: |
| 2149 | 2107 | WARN_ON_ONCE(1); |
| @@ -2252,14 +2210,12 @@ static int ccs_set_format(struct v4l2_subdev *subdev, · 102 unmodified lines | ||
| 2252 | 2210 | CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), |
| 2253 | 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 | 2215 | crops[ssd->sink_pad]->left = 0; |
| 2258 | 2216 | crops[ssd->sink_pad]->top = 0; |
| 2259 | 2217 | crops[ssd->sink_pad]->width = fmt->format.width; |
| 2260 | 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 | 2219 | ccs_propagate(subdev, sd_state, fmt->which, V4L2_SEL_TGT_CROP); |
| 2264 | 2220 | |
| 2265 | 2221 | mutex_unlock(&sensor->mutex); |
| @@ -2482,7 +2438,7 @@ static int ccs_set_compose(struct v4l2_subdev *subdev, · 216 unmodified lines | ||
| 2482 | 2438 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2483 | 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 | 2443 | sel->r.top = 0; |
| 2488 | 2444 | sel->r.left = 0; |
| @@ -2501,8 +2457,8 @@ static int ccs_set_compose(struct v4l2_subdev *subdev, · 12 unmodified lines | ||
| 2501 | 2457 | return 0; |
| 2502 | 2458 | } |
| 2503 | 2459 | |
| 2504 | −static int __ccs_sel_supported(struct v4l2_subdev *subdev, | |
| 2505 | − struct v4l2_subdev_selection *sel) | |
| 2460 | +static int ccs_sel_supported(struct v4l2_subdev *subdev, | |
| 2461 | + struct v4l2_subdev_selection *sel) | |
| 2506 | 2462 | { |
| 2507 | 2463 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2508 | 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 | 2502 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2547 | 2503 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2548 | − struct v4l2_rect *src_size, *crops[CCS_PADS]; | |
| 2549 | − struct v4l2_rect _r; | |
| 2504 | + struct v4l2_rect src_size = { 0 }, *crops[CCS_PADS], *comp; | |
| 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) { | |
| 2554 | − if (sel->pad == ssd->sink_pad) | |
| 2555 | − src_size = &ssd->sink_fmt; | |
| 2556 | − else | |
| 2557 | − src_size = &ssd->compose; | |
| 2508 | + if (sel->pad == ssd->sink_pad) { | |
| 2509 | + struct v4l2_mbus_framefmt *mfmt = | |
| 2510 | + v4l2_subdev_get_pad_format(subdev, sd_state, sel->pad); | |
| 2511 | + | |
| 2512 | + src_size.width = mfmt->width; | |
| 2513 | + src_size.height = mfmt->height; | |
| 2558 | 2514 | } else { |
| 2559 | − if (sel->pad == ssd->sink_pad) { | |
| 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 | − } | |
| 2515 | + src_size = *comp; | |
| 2575 | 2516 | } |
| 2576 | 2517 | |
| 2577 | 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 | 2520 | sel->r.top = 0; |
| 2580 | 2521 | } |
| 2581 | 2522 | |
| 2582 | − sel->r.width = min(sel->r.width, src_size->width); | |
| 2583 | − sel->r.height = min(sel->r.height, src_size->height); | |
| 2523 | + sel->r.width = min(sel->r.width, src_size.width); | |
| 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); | |
| 2586 | − sel->r.top = min_t(int, sel->r.top, src_size->height - sel->r.height); | |
| 2526 | + sel->r.left = min_t(int, sel->r.left, src_size.width - sel->r.width); | |
| 2527 | + sel->r.top = min_t(int, sel->r.top, src_size.height - sel->r.height); | |
| 2587 | 2528 | |
| 2588 | 2529 | *crops[sel->pad] = sel->r; |
| 2589 | 2530 | |
| 2590 | 2531 | if (ssd != sensor->pixel_array && sel->pad == CCS_PAD_SINK) |
| 2591 | 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 | 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 | 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, | |
| 2605 | − struct v4l2_subdev_state *sd_state, | |
| 2606 | − struct v4l2_subdev_selection *sel) | |
| 2548 | +static int ccs_get_selection(struct v4l2_subdev *subdev, | |
| 2549 | + struct v4l2_subdev_state *sd_state, | |
| 2550 | + struct v4l2_subdev_selection *sel) | |
| 2607 | 2551 | { |
| 2608 | 2552 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2609 | 2553 | struct ccs_subdev *ssd = to_ccs_subdev(subdev); |
| 2610 | 2554 | struct v4l2_rect *comp, *crops[CCS_PADS]; |
| 2611 | − struct v4l2_rect sink_fmt; | |
| 2612 | 2555 | int ret; |
| 2613 | 2556 | |
| 2614 | − ret = __ccs_sel_supported(subdev, sel); | |
| 2557 | + ret = ccs_sel_supported(subdev, sel); | |
| 2615 | 2558 | if (ret) |
| 2616 | 2559 | return ret; |
| 2617 | 2560 | |
| 2618 | − ccs_get_crop_compose(subdev, sd_state, crops, &comp, sel->which); | |
| 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 | − } | |
| 2561 | + ccs_get_crop_compose(subdev, sd_state, crops, &comp); | |
| 2632 | 2562 | |
| 2633 | 2563 | switch (sel->target) { |
| 2634 | 2564 | case V4L2_SEL_TGT_CROP_BOUNDS: |
| 2635 | 2565 | case V4L2_SEL_TGT_NATIVE_SIZE: |
| 2636 | − if (ssd == sensor->pixel_array) | |
| 2566 | + if (ssd == sensor->pixel_array) { | |
| 2637 | 2567 | ccs_get_native_size(ssd, &sel->r); |
| 2638 | − else if (sel->pad == ssd->sink_pad) | |
| 2639 | − sel->r = sink_fmt; | |
| 2640 | − else | |
| 2568 | + } else if (sel->pad == ssd->sink_pad) { | |
| 2569 | + struct v4l2_mbus_framefmt *sink_fmt = | |
| 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 | 2576 | sel->r = *comp; |
| 2577 | + } | |
| 2642 | 2578 | break; |
| 2643 | 2579 | case V4L2_SEL_TGT_CROP: |
| 2644 | 2580 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
| @@ -2652,20 +2588,6 @@ static int __ccs_get_selection(struct v4l2_subdev *subdev, · 7 unmodified lines | ||
| 2652 | 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 | 2591 | static int ccs_set_selection(struct v4l2_subdev *subdev, |
| 2670 | 2592 | struct v4l2_subdev_state *sd_state, |
| 2671 | 2593 | struct v4l2_subdev_selection *sel) |
| @@ -2673,7 +2595,7 @@ static int ccs_set_selection(struct v4l2_subdev *subdev, · 1 unmodified line | ||
| 2673 | 2595 | struct ccs_sensor *sensor = to_ccs_sensor(subdev); |
| 2674 | 2596 | int ret; |
| 2675 | 2597 | |
| 2676 | − ret = __ccs_sel_supported(subdev, sel); | |
| 2598 | + ret = ccs_sel_supported(subdev, sel); | |
| 2677 | 2599 | if (ret) |
| 2678 | 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 | 2869 | static const struct v4l2_subdev_ops ccs_ops; |
| 2948 | −static const struct v4l2_subdev_internal_ops ccs_internal_ops; | |
| 2949 | 2870 | static const struct media_entity_operations ccs_entity_ops; |
| 2950 | 2871 | |
| 2951 | 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 | 2880 | if (!sink_ssd) |
| 2960 | 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 | 2883 | rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, &ssd->sd); |
| 2969 | 2884 | if (rval) { |
| 2970 | 2885 | dev_err(&client->dev, "v4l2_device_register_subdev failed\n"); |
| @@ -3025,6 +2940,12 @@ out_err: · 54 unmodified lines | ||
| 3025 | 2940 | static void ccs_cleanup(struct ccs_sensor *sensor) |
| 3026 | 2941 | { |
| 3027 | 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 | 2950 | device_remove_file(&client->dev, &dev_attr_nvm); |
| 3030 | 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 | 2953 | ccs_free_controls(sensor); |
| 3033 | 2954 | } |
| 3034 | 2955 | |
| 3035 | −static void ccs_create_subdev(struct ccs_sensor *sensor, | |
| 3036 | − struct ccs_subdev *ssd, const char *name, | |
| 3037 | − unsigned short num_pads, u32 function) | |
| 2956 | +static int ccs_init_subdev(struct ccs_sensor *sensor, | |
| 2957 | + struct ccs_subdev *ssd, const char *name, | |
| 2958 | + unsigned short num_pads, u32 function, | |
| 2959 | + const char *lock_name, | |
| 2960 | + struct lock_class_key *lock_key) | |
| 3038 | 2961 | { |
| 3039 | 2962 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 2963 | + int rval; | |
| 3040 | 2964 | |
| 3041 | 2965 | if (!ssd) |
| 3042 | − return; | |
| 2966 | + return 0; | |
| 3043 | 2967 | |
| 3044 | 2968 | if (ssd != sensor->src) |
| 3045 | 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 | 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 | 2980 | ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE; |
| 3062 | − if (ssd != sensor->pixel_array) { | |
| 3063 | − ssd->crop[ssd->sink_pad] = ssd->compose; | |
| 2981 | + if (ssd != sensor->pixel_array) | |
| 3064 | 2982 | ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK; |
| 3065 | − } | |
| 3066 | 2983 | |
| 3067 | 2984 | ssd->sd.entity.ops = &ccs_entity_ops; |
| 3068 | 2985 | |
| 3069 | − if (ssd == sensor->src) | |
| 3070 | − return; | |
| 2986 | + if (ssd != sensor->src) { | |
| 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; | |
| 3073 | − ssd->sd.owner = THIS_MODULE; | |
| 3074 | − ssd->sd.dev = &client->dev; | |
| 3075 | − v4l2_set_subdevdata(&ssd->sd, client); | |
| 2998 | + rval = __v4l2_subdev_init_finalize(&ssd->sd, lock_name, lock_key); | |
| 2999 | + if (rval) { | |
| 3000 | + media_entity_cleanup(&ssd->sd.entity); | |
| 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 | 3010 | struct ccs_subdev *ssd = to_ccs_subdev(sd); |
| 3081 | 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 | 3020 | mutex_lock(&sensor->mutex); |
| 3085 | 3021 | |
| 3086 | − for (i = 0; i < ssd->npads; i++) { | |
| 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; | |
| 3022 | + ccs_get_native_size(ssd, crop); | |
| 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; | |
| 3096 | − try_fmt->height = try_crop->height; | |
| 3097 | − try_fmt->code = sensor->internal_csi_format->code; | |
| 3098 | − try_fmt->field = V4L2_FIELD_NONE; | |
| 3029 | + if (ssd == sensor->pixel_array) { | |
| 3030 | + if (is_active) | |
| 3031 | + sensor->pa_src = *crop; | |
| 3099 | 3032 | |
| 3100 | − if (ssd != sensor->pixel_array) | |
| 3101 | − continue; | |
| 3102 | − | |
| 3103 | − try_comp = v4l2_subdev_get_try_compose(sd, fh->state, i); | |
| 3104 | − *try_comp = *try_crop; | |
| 3033 | + mutex_unlock(&sensor->mutex); | |
| 3034 | + return 0; | |
| 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 | 3044 | mutex_unlock(&sensor->mutex); |
| 3108 | 3045 | |
| 3109 | 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 | 3055 | static const struct v4l2_subdev_pad_ops ccs_pad_ops = { |
| 3056 | + .init_cfg = ccs_init_cfg, | |
| 3119 | 3057 | .enum_mbus_code = ccs_enum_mbus_code, |
| 3120 | 3058 | .get_fmt = ccs_get_format, |
| 3121 | 3059 | .set_fmt = ccs_set_format, |
| @@ -3141,53 +3079,12 @@ static const struct media_entity_operations ccs_entity_ops = { · 19 unmodified lines | ||
| 3141 | 3079 | static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { |
| 3142 | 3080 | .registered = ccs_registered, |
| 3143 | 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 | 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 | 3088 | static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) |
| 3192 | 3089 | { |
| 3193 | 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 | 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 | 3213 | const struct ccs_device *ccsdev = device_get_match_data(&client->dev); |
| 3315 | 3214 | struct ccs_sensor *sensor; |
| 3316 | 3215 | const struct firmware *fw; |
| @@ -3587,12 +3486,27 @@ static int ccs_probe(struct i2c_client *client) · 270 unmodified lines | ||
| 3587 | 3486 | sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; |
| 3588 | 3487 | sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); |
| 3589 | 3488 | |
| 3590 | − ccs_create_subdev(sensor, sensor->scaler, " scaler", 2, | |
| 3591 | − MEDIA_ENT_F_PROC_VIDEO_SCALER); | |
| 3592 | − ccs_create_subdev(sensor, sensor->binner, " binner", 2, | |
| 3593 | − MEDIA_ENT_F_PROC_VIDEO_SCALER); | |
| 3594 | − ccs_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1, | |
| 3595 | − MEDIA_ENT_F_CAM_SENSOR); | |
| 3489 | + rval = ccs_get_mbus_formats(sensor); | |
| 3490 | + if (rval) { | |
| 3491 | + rval = -ENODEV; | |
| 3492 | + goto out_cleanup; | |
| 3493 | + } | |
| 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 | 3511 | rval = ccs_init_controls(sensor); |
| 3598 | 3512 | if (rval < 0) |
| @@ -3602,12 +3516,6 @@ static int ccs_probe(struct i2c_client *client) · 3 unmodified lines | ||
| 3602 | 3516 | if (rval) |
| 3603 | 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 | 3519 | rval = ccs_init_late_controls(sensor); |
| 3612 | 3520 | if (rval) { |
| 3613 | 3521 | rval = -ENODEV; |
| @@ -3625,14 +3533,9 @@ static int ccs_probe(struct i2c_client *client) · 11 unmodified lines | ||
| 3625 | 3533 | sensor->streaming = false; |
| 3626 | 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 | 3536 | rval = ccs_write_msr_regs(sensor); |
| 3634 | 3537 | if (rval) |
| 3635 | − goto out_media_entity_cleanup; | |
| 3538 | + goto out_cleanup; | |
| 3636 | 3539 | |
| 3637 | 3540 | pm_runtime_set_active(&client->dev); |
| 3638 | 3541 | pm_runtime_get_noresume(&client->dev); |
| @@ -3652,9 +3555,6 @@ out_disable_runtime_pm: · 13 unmodified lines | ||
| 3652 | 3555 | pm_runtime_put_noidle(&client->dev); |
| 3653 | 3556 | pm_runtime_disable(&client->dev); |
| 3654 | 3557 | |
| 3655 | −out_media_entity_cleanup: | |
| 3656 | − media_entity_cleanup(&sensor->src->sd.entity); | |
| 3657 | − | |
| 3658 | 3558 | out_cleanup: |
| 3659 | 3559 | ccs_cleanup(sensor); |
| 3660 | 3560 | |
| @@ -3687,10 +3587,8 @@ static void ccs_remove(struct i2c_client *client) · 26 unmodified lines | ||
| 3687 | 3587 | ccs_power_off(&client->dev); |
| 3688 | 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 | 3591 | v4l2_device_unregister_subdev(&sensor->ssds[i].sd); |
| 3692 | − media_entity_cleanup(&sensor->ssds[i].sd.entity); | |
| 3693 | − } | |
| 3694 | 3592 | ccs_cleanup(sensor); |
| 3695 | 3593 | mutex_destroy(&sensor->mutex); |
| 3696 | 3594 | kfree(sensor->ccs_limits); |
| @@ -3720,7 +3618,6 @@ static const struct of_device_id ccs_of_table[] = { · 23 unmodified lines | ||
| 3720 | 3618 | MODULE_DEVICE_TABLE(of, ccs_of_table); |
| 3721 | 3619 | |
| 3722 | 3620 | static const struct dev_pm_ops ccs_pm_ops = { |
| 3723 | − SET_SYSTEM_SLEEP_PM_OPS(ccs_suspend, ccs_resume) | |
| 3724 | 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 | 32 | * @reg: Pointer to the register to access |
| 33 | 33 | * @value: Register value, set by the caller on write, or |
| 34 | 34 | * by the quirk on read |
| 35 | − * | |
| 36 | − * @flags: Quirk flags | |
| 37 | − * | |
| 38 | 35 | * @return: 0 on success, -ENOIOCTLCMD if no register |
| 39 | 36 | * access may be done by the caller (default read |
| 40 | 37 | * value is zero), else negative error code on error |
| 38 | + * @flags: Quirk flags | |
| 41 | 39 | */ |
| 42 | 40 | struct ccs_quirk { |
| 43 | 41 | int (*limits)(struct ccs_sensor *sensor); |
| @@ -182,9 +182,6 @@ struct ccs_binning_subtype { · 181 unmodified lines | ||
| 182 | 182 | struct ccs_subdev { |
| 183 | 183 | struct v4l2_subdev sd; |
| 184 | 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 | 185 | unsigned short sink_pad; |
| 189 | 186 | unsigned short source_pad; |
| 190 | 187 | int npads; |
| @@ -220,6 +217,7 @@ struct ccs_sensor { · 29 unmodified lines | ||
| 220 | 217 | u32 mbus_frame_fmts; |
| 221 | 218 | const struct ccs_csi_data_format *csi_format; |
| 222 | 219 | const struct ccs_csi_data_format *internal_csi_format; |
| 220 | + struct v4l2_rect pa_src, scaler_sink, src_src; | |
| 223 | 221 | u32 default_mbus_frame_fmts; |
| 224 | 222 | int default_pixel_order; |
| 225 | 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 | 2738 | #define DIF_BPF_COEFF3435 (0x38c) |
| 2739 | 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 | 3531 | static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) |
| 2742 | 3532 | { |
| 2743 | 3533 | u64 pll_freq; |
| 2744 | 3534 | u32 pll_freq_word; |
| 3535 | + const u32 *coeffs; | |
| 2745 | 3536 | |
| 2746 | 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 | 3555 | v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz); |
| 2765 | 3556 | |
| 2766 | − switch (ifHz) { | |
| 2767 | − case 3000000: | |
| 2768 | − cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | |
| 2769 | − cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012); | |
| 2770 | − cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024); | |
| 2771 | − cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8); | |
| 2772 | − cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50); | |
| 2773 | − cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68); | |
| 2774 | − cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34); | |
| 2775 | − cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7); | |
| 2776 | − cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f); | |
| 2777 | − cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d); | |
| 2778 | − cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688); | |
| 2779 | − cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6); | |
| 2780 | − cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3); | |
| 2781 | − cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342); | |
| 2782 | − cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337); | |
| 2783 | − cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22); | |
| 2784 | − cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f); | |
| 2785 | − cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce); | |
| 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 | − } | |
| 3557 | + coeffs = ifhz_coeffs[(ifHz - 3000000) / 100000]; | |
| 3558 | + cx25840_write4(client, DIF_BPF_COEFF01, coeffs[0]); | |
| 3559 | + cx25840_write4(client, DIF_BPF_COEFF23, coeffs[1]); | |
| 3560 | + cx25840_write4(client, DIF_BPF_COEFF45, coeffs[2]); | |
| 3561 | + cx25840_write4(client, DIF_BPF_COEFF67, coeffs[3]); | |
| 3562 | + cx25840_write4(client, DIF_BPF_COEFF89, coeffs[4]); | |
| 3563 | + cx25840_write4(client, DIF_BPF_COEFF1011, coeffs[5]); | |
| 3564 | + cx25840_write4(client, DIF_BPF_COEFF1213, coeffs[6]); | |
| 3565 | + cx25840_write4(client, DIF_BPF_COEFF1415, coeffs[7]); | |
| 3566 | + cx25840_write4(client, DIF_BPF_COEFF1617, coeffs[8]); | |
| 3567 | + cx25840_write4(client, DIF_BPF_COEFF1819, coeffs[9]); | |
| 3568 | + cx25840_write4(client, DIF_BPF_COEFF2021, coeffs[10]); | |
| 3569 | + cx25840_write4(client, DIF_BPF_COEFF2223, coeffs[11]); | |
| 3570 | + cx25840_write4(client, DIF_BPF_COEFF2425, coeffs[12]); | |
| 3571 | + cx25840_write4(client, DIF_BPF_COEFF2627, coeffs[13]); | |
| 3572 | + cx25840_write4(client, DIF_BPF_COEFF2829, coeffs[14]); | |
| 3573 | + cx25840_write4(client, DIF_BPF_COEFF3031, coeffs[15]); | |
| 3574 | + cx25840_write4(client, DIF_BPF_COEFF3233, coeffs[16]); | |
| 3575 | + cx25840_write4(client, DIF_BPF_COEFF3435, coeffs[17]); | |
| 3576 | + cx25840_write4(client, DIF_BPF_COEFF36, coeffs[18]); | |
| 5649 | 3577 | } |
| 5650 | 3578 | |
| 5651 | 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 | 362 | if (ret) |
| 363 | 363 | return ret; |
| 364 | 364 | |
| 365 | − memset(fd, 0, sizeof(*fd)); | |
| 366 | − | |
| 367 | 365 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL; |
| 368 | 366 | |
| 369 | 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 | 499 | if (ret) |
| 500 | 500 | return ret; |
| 501 | 501 | |
| 502 | − memset(fd, 0, sizeof(*fd)); | |
| 503 | − | |
| 504 | 502 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; |
| 505 | 503 | |
| 506 | 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 | 2786 | if (!ub960_pad_is_source(priv, pad)) |
| 2787 | 2787 | return -EINVAL; |
| 2788 | 2788 | |
| 2789 | − memset(fd, 0, sizeof(*fd)); | |
| 2790 | − | |
| 2791 | 2789 | fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; |
| 2792 | 2790 | |
| 2793 | 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 | 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 | 524 | static const char * const hi556_test_pattern_menu[] = { |
| 481 | 525 | "Disabled", |
| 482 | 526 | "Solid Colour", |
| @@ -556,7 +600,25 @@ static const struct hi556_mode supported_modes[] = { · 73 unmodified lines | ||
| 556 | 600 | .regs = mode_1296x972_regs, |
| 557 | 601 | }, |
| 558 | 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 | 624 | struct hi556 { |
| @@ -577,9 +639,6 @@ struct hi556 { · 14 unmodified lines | ||
| 577 | 639 | /* To serialize asynchronus callbacks */ |
| 578 | 640 | struct mutex mutex; |
| 579 | 641 | |
| 580 | − /* Streaming on/off */ | |
| 581 | − bool streaming; | |
| 582 | − | |
| 583 | 642 | /* True if the device has been identified */ |
| 584 | 643 | bool identified; |
| 585 | 644 | }; |
| @@ -976,9 +1035,6 @@ static int hi556_set_stream(struct v4l2_subdev *sd, int enable) · 390 unmodified lines | ||
| 976 | 1035 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 977 | 1036 | int ret = 0; |
| 978 | 1037 | |
| 979 | − if (hi556->streaming == enable) | |
| 980 | − return 0; | |
| 981 | − | |
| 982 | 1038 | mutex_lock(&hi556->mutex); |
| 983 | 1039 | if (enable) { |
| 984 | 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 | 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 | 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 | 1059 | return ret; |
| 1043 | 1060 | } |
| 1044 | 1061 | |
| @@ -1331,10 +1348,6 @@ probe_error_v4l2_ctrl_handler_free: · 286 unmodified lines | ||
| 1331 | 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 | 1351 | #ifdef CONFIG_ACPI |
| 1339 | 1352 | static const struct acpi_device_id hi556_acpi_ids[] = { |
| 1340 | 1353 | {"INT3537"}, |
| @@ -1347,7 +1360,6 @@ MODULE_DEVICE_TABLE(acpi, hi556_acpi_ids); · 6 unmodified lines | ||
| 1347 | 1360 | static struct i2c_driver hi556_i2c_driver = { |
| 1348 | 1361 | .driver = { |
| 1349 | 1362 | .name = "hi556", |
| 1350 | − .pm = &hi556_pm_ops, | |
| 1351 | 1363 | .acpi_match_table = ACPI_PTR(hi556_acpi_ids), |
| 1352 | 1364 | }, |
| 1353 | 1365 | .probe = hi556_probe, |
| @@ -1607,17 +1607,12 @@ static int hi846_set_stream(struct v4l2_subdev *sd, int enable) · 1606 unmodified lines | ||
| 1607 | 1607 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 1608 | 1608 | int ret = 0; |
| 1609 | 1609 | |
| 1610 | − if (hi846->streaming == enable) | |
| 1611 | − return 0; | |
| 1612 | − | |
| 1613 | 1610 | mutex_lock(&hi846->mutex); |
| 1614 | 1611 | |
| 1615 | 1612 | if (enable) { |
| 1616 | − ret = pm_runtime_get_sync(&client->dev); | |
| 1617 | − if (ret < 0) { | |
| 1618 | − pm_runtime_put_noidle(&client->dev); | |
| 1613 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 1614 | + if (ret) | |
| 1619 | 1615 | goto out; |
| 1620 | − } | |
| 1621 | 1616 | |
| 1622 | 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 | 1675 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1681 | 1676 | struct hi846 *hi846 = to_hi846(sd); |
| 1682 | 1677 | |
| 1683 | − if (hi846->streaming) | |
| 1684 | − hi846_stop_streaming(hi846); | |
| 1685 | − | |
| 1686 | 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 | 1683 | struct i2c_client *client = to_i2c_client(dev); |
| 1692 | 1684 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1693 | 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) { | |
| 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; | |
| 1687 | + return hi846_power_on(hi846); | |
| 1714 | 1688 | } |
| 1715 | 1689 | |
| 1716 | 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 | 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 | 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 | 2185 | /* To serialize asynchronus callbacks */ |
| 2186 | 2186 | struct mutex mutex; |
| 2187 | − | |
| 2188 | − /* Streaming on/off */ | |
| 2189 | − bool streaming; | |
| 2190 | 2187 | }; |
| 2191 | 2188 | |
| 2192 | 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 | 2615 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 2619 | 2616 | int ret = 0; |
| 2620 | 2617 | |
| 2621 | − if (hi847->streaming == enable) | |
| 2622 | − return 0; | |
| 2623 | − | |
| 2624 | 2618 | mutex_lock(&hi847->mutex); |
| 2625 | 2619 | if (enable) { |
| 2626 | − ret = pm_runtime_get_sync(&client->dev); | |
| 2627 | − if (ret < 0) { | |
| 2628 | − pm_runtime_put_noidle(&client->dev); | |
| 2620 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 2621 | + if (ret) { | |
| 2629 | 2622 | mutex_unlock(&hi847->mutex); |
| 2630 | 2623 | return ret; |
| 2631 | 2624 | } |
| @@ -2641,49 +2634,8 @@ static int hi847_set_stream(struct v4l2_subdev *sd, int enable) · 9 unmodified lines | ||
| 2641 | 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 | 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 | 2639 | return ret; |
| 2688 | 2640 | } |
| 2689 | 2641 | |
| @@ -2980,10 +2932,6 @@ probe_error_v4l2_ctrl_handler_free: · 290 unmodified lines | ||
| 2980 | 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 | 2935 | #ifdef CONFIG_ACPI |
| 2988 | 2936 | static const struct acpi_device_id hi847_acpi_ids[] = { |
| 2989 | 2937 | {"HYV0847"}, |
| @@ -2996,7 +2944,6 @@ MODULE_DEVICE_TABLE(acpi, hi847_acpi_ids); · 6 unmodified lines | ||
| 2996 | 2944 | static struct i2c_driver hi847_i2c_driver = { |
| 2997 | 2945 | .driver = { |
| 2998 | 2946 | .name = "hi847", |
| 2999 | − .pm = &hi847_pm_ops, | |
| 3000 | 2947 | .acpi_match_table = ACPI_PTR(hi847_acpi_ids), |
| 3001 | 2948 | }, |
| 3002 | 2949 | .probe = hi847_probe, |
| @@ -290,9 +290,6 @@ struct imx208 { · 289 unmodified lines | ||
| 290 | 290 | */ |
| 291 | 291 | struct mutex imx208_mx; |
| 292 | 292 | |
| 293 | − /* Streaming on/off */ | |
| 294 | − bool streaming; | |
| 295 | − | |
| 296 | 293 | /* OTP data */ |
| 297 | 294 | bool otp_read; |
| 298 | 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 | 711 | int ret = 0; |
| 715 | 712 | |
| 716 | 713 | mutex_lock(&imx208->imx208_mx); |
| 717 | − if (imx208->streaming == enable) { | |
| 718 | − mutex_unlock(&imx208->imx208_mx); | |
| 719 | − return 0; | |
| 720 | − } | |
| 721 | 714 | |
| 722 | 715 | if (enable) { |
| 723 | − ret = pm_runtime_get_sync(&client->dev); | |
| 724 | − if (ret < 0) | |
| 725 | − goto err_rpm_put; | |
| 716 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 717 | + if (ret) { | |
| 718 | + mutex_unlock(&imx208->imx208_mx); | |
| 719 | + return ret; | |
| 720 | + } | |
| 726 | 721 | |
| 727 | 722 | /* |
| 728 | 723 | * Apply default & customized values |
| @@ -736,7 +731,6 @@ static int imx208_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | ||
| 736 | 731 | pm_runtime_put(&client->dev); |
| 737 | 732 | } |
| 738 | 733 | |
| 739 | − imx208->streaming = enable; | |
| 740 | 734 | mutex_unlock(&imx208->imx208_mx); |
| 741 | 735 | |
| 742 | 736 | /* vflip and hflip cannot change during streaming */ |
| @@ -752,40 +746,6 @@ err_rpm_put: · 9 unmodified lines | ||
| 752 | 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 | 749 | /* Verify chip ID */ |
| 790 | 750 | static const struct v4l2_subdev_video_ops imx208_video_ops = { |
| 791 | 751 | .s_stream = imx208_set_stream, |
| @@ -819,11 +779,9 @@ static int imx208_read_otp(struct imx208 *imx208) · 27 unmodified lines | ||
| 819 | 779 | if (imx208->otp_read) |
| 820 | 780 | goto out_unlock; |
| 821 | 781 | |
| 822 | − ret = pm_runtime_get_sync(&client->dev); | |
| 823 | − if (ret < 0) { | |
| 824 | − pm_runtime_put_noidle(&client->dev); | |
| 782 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 783 | + if (ret) | |
| 825 | 784 | goto out_unlock; |
| 826 | − } | |
| 827 | 785 | |
| 828 | 786 | ret = imx208_identify_module(imx208); |
| 829 | 787 | if (ret) |
| @@ -1081,10 +1039,6 @@ static void imx208_remove(struct i2c_client *client) · 251 unmodified lines | ||
| 1081 | 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 | 1042 | #ifdef CONFIG_ACPI |
| 1089 | 1043 | static const struct acpi_device_id imx208_acpi_ids[] = { |
| 1090 | 1044 | { "INT3478" }, |
| @@ -1097,7 +1051,6 @@ MODULE_DEVICE_TABLE(acpi, imx208_acpi_ids); · 6 unmodified lines | ||
| 1097 | 1051 | static struct i2c_driver imx208_i2c_driver = { |
| 1098 | 1052 | .driver = { |
| 1099 | 1053 | .name = "imx208", |
| 1100 | − .pm = &imx208_pm_ops, | |
| 1101 | 1054 | .acpi_match_table = ACPI_PTR(imx208_acpi_ids), |
| 1102 | 1055 | }, |
| 1103 | 1056 | .probe = imx208_probe, |
| @@ -58,8 +58,6 @@ struct imx214 { · 57 unmodified lines | ||
| 58 | 58 | * and start streaming. |
| 59 | 59 | */ |
| 60 | 60 | struct mutex mutex; |
| 61 | − | |
| 62 | − bool streaming; | |
| 63 | 61 | }; |
| 64 | 62 | |
| 65 | 63 | struct reg_8 { |
| @@ -775,9 +773,6 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) · 709 unmodified lines | ||
| 775 | 773 | struct imx214 *imx214 = to_imx214(subdev); |
| 776 | 774 | int ret; |
| 777 | 775 | |
| 778 | − if (imx214->streaming == enable) | |
| 779 | − return 0; | |
| 780 | − | |
| 781 | 776 | if (enable) { |
| 782 | 777 | ret = pm_runtime_resume_and_get(imx214->dev); |
| 783 | 778 | if (ret < 0) |
| @@ -793,7 +788,6 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) · 9 unmodified lines | ||
| 793 | 788 | pm_runtime_put(imx214->dev); |
| 794 | 789 | } |
| 795 | 790 | |
| 796 | − imx214->streaming = enable; | |
| 797 | 791 | return 0; |
| 798 | 792 | |
| 799 | 793 | err_rpm_put: |
| @@ -909,39 +903,6 @@ done: · 109 unmodified lines | ||
| 909 | 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 | 906 | static int imx214_probe(struct i2c_client *client) |
| 946 | 907 | { |
| 947 | 908 | struct device *dev = &client->dev; |
| @@ -1102,7 +1063,6 @@ static const struct of_device_id imx214_of_match[] = { · 154 unmodified lines | ||
| 1102 | 1063 | MODULE_DEVICE_TABLE(of, imx214_of_match); |
| 1103 | 1064 | |
| 1104 | 1065 | static const struct dev_pm_ops imx214_pm_ops = { |
| 1105 | − SET_SYSTEM_SLEEP_PM_OPS(imx214_suspend, imx214_resume) | |
| 1106 | 1066 | SET_RUNTIME_PM_OPS(imx214_power_off, imx214_power_on, NULL) |
| 1107 | 1067 | }; |
| 1108 | 1068 | |
| @@ -18,91 +18,99 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/delay.h> |
| 19 | 19 | #include <linux/gpio/consumer.h> |
| 20 | 20 | #include <linux/i2c.h> |
| 21 | +#include <linux/minmax.h> | |
| 21 | 22 | #include <linux/module.h> |
| 22 | 23 | #include <linux/pm_runtime.h> |
| 23 | 24 | #include <linux/regulator/consumer.h> |
| 25 | + | |
| 26 | +#include <media/v4l2-cci.h> | |
| 24 | 27 | #include <media/v4l2-ctrls.h> |
| 25 | 28 | #include <media/v4l2-device.h> |
| 26 | 29 | #include <media/v4l2-event.h> |
| 27 | 30 | #include <media/v4l2-fwnode.h> |
| 28 | 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 | 33 | /* Chip ID */ |
| 39 | −#define IMX219_REG_CHIP_ID 0x0000 | |
| 34 | +#define IMX219_REG_CHIP_ID CCI_REG16(0x0000) | |
| 40 | 35 | #define IMX219_CHIP_ID 0x0219 |
| 41 | 36 | |
| 42 | −/* External clock frequency is 24.0M */ | |
| 43 | −#define IMX219_XCLK_FREQ 24000000 | |
| 44 | − | |
| 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 | |
| 37 | +#define IMX219_REG_MODE_SELECT CCI_REG8(0x0100) | |
| 38 | +#define IMX219_MODE_STANDBY 0x00 | |
| 39 | +#define IMX219_MODE_STREAMING 0x01 | |
| 51 | 40 | |
| 52 | −#define IMX219_REG_CSI_LANE_MODE 0x0114 | |
| 41 | +#define IMX219_REG_CSI_LANE_MODE CCI_REG8(0x0114) | |
| 53 | 42 | #define IMX219_CSI_2_LANE_MODE 0x01 |
| 54 | 43 | #define IMX219_CSI_4_LANE_MODE 0x03 |
| 55 | 44 | |
| 56 | −/* V_TIMING internal */ | |
| 57 | −#define IMX219_REG_VTS 0x0160 | |
| 58 | −#define IMX219_VTS_15FPS 0x0dc6 | |
| 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 | |
| 45 | +#define IMX219_REG_DPHY_CTRL CCI_REG8(0x0128) | |
| 46 | +#define IMX219_DPHY_CTRL_TIMING_AUTO 0 | |
| 47 | +#define IMX219_DPHY_CTRL_TIMING_MANUAL 1 | |
| 74 | 48 | |
| 75 | −/* Exposure control */ | |
| 76 | −#define IMX219_REG_EXPOSURE 0x015a | |
| 77 | −#define IMX219_EXPOSURE_MIN 4 | |
| 78 | −#define IMX219_EXPOSURE_STEP 1 | |
| 79 | −#define IMX219_EXPOSURE_DEFAULT 0x640 | |
| 80 | −#define IMX219_EXPOSURE_MAX 65535 | |
| 49 | +#define IMX219_REG_EXCK_FREQ CCI_REG16(0x012a) | |
| 50 | +#define IMX219_EXCK_FREQ(n) ((n) * 256) /* n expressed in MHz */ | |
| 81 | 51 | |
| 82 | 52 | /* Analog gain control */ |
| 83 | −#define IMX219_REG_ANALOG_GAIN 0x0157 | |
| 53 | +#define IMX219_REG_ANALOG_GAIN CCI_REG8(0x0157) | |
| 84 | 54 | #define IMX219_ANA_GAIN_MIN 0 |
| 85 | 55 | #define IMX219_ANA_GAIN_MAX 232 |
| 86 | 56 | #define IMX219_ANA_GAIN_STEP 1 |
| 87 | 57 | #define IMX219_ANA_GAIN_DEFAULT 0x0 |
| 88 | 58 | |
| 89 | 59 | /* Digital gain control */ |
| 90 | −#define IMX219_REG_DIGITAL_GAIN 0x0158 | |
| 60 | +#define IMX219_REG_DIGITAL_GAIN CCI_REG16(0x0158) | |
| 91 | 61 | #define IMX219_DGTL_GAIN_MIN 0x0100 |
| 92 | 62 | #define IMX219_DGTL_GAIN_MAX 0x0fff |
| 93 | 63 | #define IMX219_DGTL_GAIN_DEFAULT 0x0100 |
| 94 | 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 | 93 | /* Binning Mode */ |
| 99 | −#define IMX219_REG_BINNING_MODE 0x0174 | |
| 100 | −#define IMX219_BINNING_NONE 0x0000 | |
| 101 | −#define IMX219_BINNING_2X2 0x0101 | |
| 102 | −#define IMX219_BINNING_2X2_ANALOG 0x0303 | |
| 94 | +#define IMX219_REG_BINNING_MODE_H CCI_REG8(0x0174) | |
| 95 | +#define IMX219_REG_BINNING_MODE_V CCI_REG8(0x0175) | |
| 96 | +#define IMX219_BINNING_NONE 0x00 | |
| 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 | 112 | /* Test Pattern Control */ |
| 105 | −#define IMX219_REG_TEST_PATTERN 0x0600 | |
| 113 | +#define IMX219_REG_TEST_PATTERN CCI_REG16(0x0600) | |
| 106 | 114 | #define IMX219_TEST_PATTERN_DISABLE 0 |
| 107 | 115 | #define IMX219_TEST_PATTERN_SOLID_COLOR 1 |
| 108 | 116 | #define IMX219_TEST_PATTERN_COLOR_BARS 2 |
| @@ -110,17 +118,26 @@ · 1 unmodified line | ||
| 110 | 118 | #define IMX219_TEST_PATTERN_PN9 4 |
| 111 | 119 | |
| 112 | 120 | /* Test pattern colour components */ |
| 113 | −#define IMX219_REG_TESTP_RED 0x0602 | |
| 114 | −#define IMX219_REG_TESTP_GREENR 0x0604 | |
| 115 | −#define IMX219_REG_TESTP_BLUE 0x0606 | |
| 116 | −#define IMX219_REG_TESTP_GREENB 0x0608 | |
| 121 | +#define IMX219_REG_TESTP_RED CCI_REG16(0x0602) | |
| 122 | +#define IMX219_REG_TESTP_GREENR CCI_REG16(0x0604) | |
| 123 | +#define IMX219_REG_TESTP_BLUE CCI_REG16(0x0606) | |
| 124 | +#define IMX219_REG_TESTP_GREENB CCI_REG16(0x0608) | |
| 117 | 125 | #define IMX219_TESTP_COLOUR_MIN 0 |
| 118 | 126 | #define IMX219_TESTP_COLOUR_MAX 0x03ff |
| 119 | 127 | #define IMX219_TESTP_COLOUR_STEP 1 |
| 120 | −#define IMX219_TESTP_RED_DEFAULT IMX219_TESTP_COLOUR_MAX | |
| 121 | −#define IMX219_TESTP_GREENR_DEFAULT 0 | |
| 122 | −#define IMX219_TESTP_BLUE_DEFAULT 0 | |
| 123 | −#define IMX219_TESTP_GREENB_DEFAULT 0 | |
| 128 | + | |
| 129 | +#define IMX219_REG_TP_WINDOW_WIDTH CCI_REG16(0x0624) | |
| 130 | +#define IMX219_REG_TP_WINDOW_HEIGHT CCI_REG16(0x0626) | |
| 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 | 142 | /* IMX219 native and active pixel array size. */ |
| 126 | 143 | #define IMX219_NATIVE_WIDTH 3296U |
| @@ -130,16 +147,6 @@ · 3 unmodified lines | ||
| 130 | 147 | #define IMX219_PIXEL_ARRAY_WIDTH 3280U |
| 131 | 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 | 150 | /* Mode : resolution and related config&values */ |
| 144 | 151 | struct imx219_mode { |
| 145 | 152 | /* Frame width */ |
| @@ -147,159 +154,52 @@ struct imx219_mode { · 1 unmodified line | ||
| 147 | 154 | /* Frame height */ |
| 148 | 155 | unsigned int height; |
| 149 | 156 | |
| 150 | − /* Analog crop rectangle. */ | |
| 151 | − struct v4l2_rect crop; | |
| 152 | − | |
| 153 | 157 | /* V-timing */ |
| 154 | 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[] = { | |
| 164 | − {0x0100, 0x00}, /* Mode Select */ | |
| 161 | +static const struct cci_reg_sequence imx219_common_regs[] = { | |
| 162 | + { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */ | |
| 165 | 163 | |
| 166 | 164 | /* To Access Addresses 3000-5fff, send the following commands */ |
| 167 | − {0x30eb, 0x0c}, | |
| 168 | − {0x30eb, 0x05}, | |
| 169 | − {0x300a, 0xff}, | |
| 170 | − {0x300b, 0xff}, | |
| 171 | − {0x30eb, 0x05}, | |
| 172 | − {0x30eb, 0x09}, | |
| 165 | + { CCI_REG8(0x30eb), 0x0c }, | |
| 166 | + { CCI_REG8(0x30eb), 0x05 }, | |
| 167 | + { CCI_REG8(0x300a), 0xff }, | |
| 168 | + { CCI_REG8(0x300b), 0xff }, | |
| 169 | + { CCI_REG8(0x30eb), 0x05 }, | |
| 170 | + { CCI_REG8(0x30eb), 0x09 }, | |
| 173 | 171 | |
| 174 | 172 | /* PLL Clock Table */ |
| 175 | − {0x0301, 0x05}, /* VTPXCK_DIV */ | |
| 176 | − {0x0303, 0x01}, /* VTSYSCK_DIV */ | |
| 177 | − {0x0304, 0x03}, /* PREPLLCK_VT_DIV 0x03 = AUTO set */ | |
| 178 | − {0x0305, 0x03}, /* PREPLLCK_OP_DIV 0x03 = AUTO set */ | |
| 179 | − {0x0306, 0x00}, /* PLL_VT_MPY */ | |
| 180 | − {0x0307, 0x39}, | |
| 181 | − {0x030b, 0x01}, /* OP_SYS_CLK_DIV */ | |
| 182 | − {0x030c, 0x00}, /* PLL_OP_MPY */ | |
| 183 | − {0x030d, 0x72}, | |
| 173 | + { IMX219_REG_VTPXCK_DIV, 5 }, | |
| 174 | + { IMX219_REG_VTSYCK_DIV, 1 }, | |
| 175 | + { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ | |
| 176 | + { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ | |
| 177 | + { IMX219_REG_PLL_VT_MPY, 57 }, | |
| 178 | + { IMX219_REG_OPSYCK_DIV, 1 }, | |
| 179 | + { IMX219_REG_PLL_OP_MPY, 114 }, | |
| 184 | 180 | |
| 185 | 181 | /* Undocumented registers */ |
| 186 | − {0x455e, 0x00}, | |
| 187 | − {0x471e, 0x4b}, | |
| 188 | − {0x4767, 0x0f}, | |
| 189 | − {0x4750, 0x14}, | |
| 190 | − {0x4540, 0x00}, | |
| 191 | − {0x47b4, 0x14}, | |
| 192 | − {0x4713, 0x30}, | |
| 193 | − {0x478b, 0x10}, | |
| 194 | − {0x478f, 0x10}, | |
| 195 | − {0x4793, 0x10}, | |
| 196 | − {0x4797, 0x0e}, | |
| 197 | − {0x479b, 0x0e}, | |
| 182 | + { CCI_REG8(0x455e), 0x00 }, | |
| 183 | + { CCI_REG8(0x471e), 0x4b }, | |
| 184 | + { CCI_REG8(0x4767), 0x0f }, | |
| 185 | + { CCI_REG8(0x4750), 0x14 }, | |
| 186 | + { CCI_REG8(0x4540), 0x00 }, | |
| 187 | + { CCI_REG8(0x47b4), 0x14 }, | |
| 188 | + { CCI_REG8(0x4713), 0x30 }, | |
| 189 | + { CCI_REG8(0x478b), 0x10 }, | |
| 190 | + { CCI_REG8(0x478f), 0x10 }, | |
| 191 | + { CCI_REG8(0x4793), 0x10 }, | |
| 192 | + { CCI_REG8(0x4797), 0x0e }, | |
| 193 | + { CCI_REG8(0x479b), 0x0e }, | |
| 198 | 194 | |
| 199 | 195 | /* Frame Bank Register Group "A" */ |
| 200 | − {0x0162, 0x0d}, /* Line_Length_A */ | |
| 201 | − {0x0163, 0x78}, | |
| 202 | − {0x0170, 0x01}, /* X_ODD_INC_A */ | |
| 203 | − {0x0171, 0x01}, /* Y_ODD_INC_A */ | |
| 196 | + { IMX219_REG_LINE_LENGTH_A, 3448 }, | |
| 197 | + { IMX219_REG_X_ODD_INC_A, 1 }, | |
| 198 | + { IMX219_REG_Y_ODD_INC_A, 1 }, | |
| 204 | 199 | |
| 205 | 200 | /* Output setup registers */ |
| 206 | − {0x0114, 0x01}, /* CSI 2-Lane Mode */ | |
| 207 | − {0x0128, 0x00}, /* DPHY Auto Mode */ | |
| 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}, | |
| 201 | + { IMX219_REG_DPHY_CTRL, IMX219_DPHY_CTRL_TIMING_AUTO }, | |
| 202 | + { IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) }, | |
| 303 | 203 | }; |
| 304 | 204 | |
| 305 | 205 | static const s64 imx219_link_freq_menu[] = { |
| @@ -390,69 +290,25 @@ static const struct imx219_mode supported_modes[] = { · 84 unmodified lines | ||
| 390 | 290 | /* 8MPix 15fps mode */ |
| 391 | 291 | .width = 3280, |
| 392 | 292 | .height = 2464, |
| 393 | − .crop = { | |
| 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, | |
| 293 | + .vts_def = 3526, | |
| 405 | 294 | }, |
| 406 | 295 | { |
| 407 | 296 | /* 1080P 30fps cropped */ |
| 408 | 297 | .width = 1920, |
| 409 | 298 | .height = 1080, |
| 410 | − .crop = { | |
| 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, | |
| 299 | + .vts_def = 1763, | |
| 422 | 300 | }, |
| 423 | 301 | { |
| 424 | 302 | /* 2x2 binned 30fps mode */ |
| 425 | 303 | .width = 1640, |
| 426 | 304 | .height = 1232, |
| 427 | − .crop = { | |
| 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, | |
| 305 | + .vts_def = 1763, | |
| 439 | 306 | }, |
| 440 | 307 | { |
| 441 | 308 | /* 640x480 30fps mode */ |
| 442 | 309 | .width = 640, |
| 443 | 310 | .height = 480, |
| 444 | − .crop = { | |
| 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, | |
| 311 | + .vts_def = 1763, | |
| 456 | 312 | }, |
| 457 | 313 | }; |
| 458 | 314 | |
| @@ -460,6 +316,7 @@ struct imx219 { · 1 unmodified line | ||
| 460 | 316 | struct v4l2_subdev sd; |
| 461 | 317 | struct media_pad pad; |
| 462 | 318 | |
| 319 | + struct regmap *regmap; | |
| 463 | 320 | struct clk *xclk; /* system clock to IMX219 */ |
| 464 | 321 | u32 xclk_freq; |
| 465 | 322 | |
| @@ -476,12 +333,6 @@ struct imx219 { · 10 unmodified lines | ||
| 476 | 333 | struct v4l2_ctrl *vblank; |
| 477 | 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 | 336 | /* Two or Four lanes */ |
| 486 | 337 | u8 lanes; |
| 487 | 338 | }; |
| @@ -491,78 +342,6 @@ static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd) · 3 unmodified lines | ||
| 491 | 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 | 345 | /* Get bayer order based on flip setting. */ |
| 567 | 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 | 360 | return imx219_mbus_formats[i]; |
| 582 | 361 | } |
| 583 | 362 | |
| 363 | +/* ----------------------------------------------------------------------------- | |
| 364 | + * Controls | |
| 365 | + */ | |
| 366 | + | |
| 584 | 367 | static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) |
| 585 | 368 | { |
| 586 | 369 | struct imx219 *imx219 = |
| 587 | 370 | container_of(ctrl->handler, struct imx219, ctrl_handler); |
| 588 | 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 | 379 | if (ctrl->id == V4L2_CID_VBLANK) { |
| 592 | 380 | int exposure_max, exposure_def; |
| 593 | 381 | |
| 594 | 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 | 384 | exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? |
| 597 | 385 | exposure_max : IMX219_EXPOSURE_DEFAULT; |
| 598 | 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 | 399 | switch (ctrl->id) { |
| 612 | 400 | case V4L2_CID_ANALOGUE_GAIN: |
| 613 | − ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN, | |
| 614 | − IMX219_REG_VALUE_08BIT, ctrl->val); | |
| 401 | + cci_write(imx219->regmap, IMX219_REG_ANALOG_GAIN, | |
| 402 | + ctrl->val, &ret); | |
| 615 | 403 | break; |
| 616 | 404 | case V4L2_CID_EXPOSURE: |
| 617 | − ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE, | |
| 618 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 405 | + cci_write(imx219->regmap, IMX219_REG_EXPOSURE, | |
| 406 | + ctrl->val, &ret); | |
| 619 | 407 | break; |
| 620 | 408 | case V4L2_CID_DIGITAL_GAIN: |
| 621 | − ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN, | |
| 622 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 409 | + cci_write(imx219->regmap, IMX219_REG_DIGITAL_GAIN, | |
| 410 | + ctrl->val, &ret); | |
| 623 | 411 | break; |
| 624 | 412 | case V4L2_CID_TEST_PATTERN: |
| 625 | − ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN, | |
| 626 | − IMX219_REG_VALUE_16BIT, | |
| 627 | − imx219_test_pattern_val[ctrl->val]); | |
| 413 | + cci_write(imx219->regmap, IMX219_REG_TEST_PATTERN, | |
| 414 | + imx219_test_pattern_val[ctrl->val], &ret); | |
| 628 | 415 | break; |
| 629 | 416 | case V4L2_CID_HFLIP: |
| 630 | 417 | case V4L2_CID_VFLIP: |
| 631 | − ret = imx219_write_reg(imx219, IMX219_REG_ORIENTATION, 1, | |
| 632 | − imx219->hflip->val | | |
| 633 | − imx219->vflip->val << 1); | |
| 418 | + cci_write(imx219->regmap, IMX219_REG_ORIENTATION, | |
| 419 | + imx219->hflip->val | imx219->vflip->val << 1, &ret); | |
| 634 | 420 | break; |
| 635 | 421 | case V4L2_CID_VBLANK: |
| 636 | − ret = imx219_write_reg(imx219, IMX219_REG_VTS, | |
| 637 | − IMX219_REG_VALUE_16BIT, | |
| 638 | − imx219->mode->height + ctrl->val); | |
| 422 | + cci_write(imx219->regmap, IMX219_REG_VTS, | |
| 423 | + format->height + ctrl->val, &ret); | |
| 639 | 424 | break; |
| 640 | 425 | case V4L2_CID_TEST_PATTERN_RED: |
| 641 | − ret = imx219_write_reg(imx219, IMX219_REG_TESTP_RED, | |
| 642 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 426 | + cci_write(imx219->regmap, IMX219_REG_TESTP_RED, | |
| 427 | + ctrl->val, &ret); | |
| 643 | 428 | break; |
| 644 | 429 | case V4L2_CID_TEST_PATTERN_GREENR: |
| 645 | − ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENR, | |
| 646 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 430 | + cci_write(imx219->regmap, IMX219_REG_TESTP_GREENR, | |
| 431 | + ctrl->val, &ret); | |
| 647 | 432 | break; |
| 648 | 433 | case V4L2_CID_TEST_PATTERN_BLUE: |
| 649 | − ret = imx219_write_reg(imx219, IMX219_REG_TESTP_BLUE, | |
| 650 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 434 | + cci_write(imx219->regmap, IMX219_REG_TESTP_BLUE, | |
| 435 | + ctrl->val, &ret); | |
| 651 | 436 | break; |
| 652 | 437 | case V4L2_CID_TEST_PATTERN_GREENB: |
| 653 | − ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENB, | |
| 654 | − IMX219_REG_VALUE_16BIT, ctrl->val); | |
| 438 | + cci_write(imx219->regmap, IMX219_REG_TESTP_GREENB, | |
| 439 | + ctrl->val, &ret); | |
| 655 | 440 | break; |
| 656 | 441 | default: |
| 657 | 442 | dev_info(&client->dev, |
| @@ -670,226 +455,224 @@ static const struct v4l2_ctrl_ops imx219_ctrl_ops = { · 12 unmodified lines | ||
| 670 | 455 | .s_ctrl = imx219_set_ctrl, |
| 671 | 456 | }; |
| 672 | 457 | |
| 673 | −static void imx219_update_pad_format(struct imx219 *imx219, | |
| 674 | − const struct imx219_mode *mode, | |
| 675 | − struct v4l2_mbus_framefmt *fmt, u32 code) | |
| 458 | +static unsigned long imx219_get_pixel_rate(struct imx219 *imx219) | |
| 676 | 459 | { |
| 677 | − /* Bayer order varies with flips */ | |
| 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; | |
| 460 | + return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; | |
| 685 | 461 | } |
| 686 | 462 | |
| 687 | −static int imx219_init_cfg(struct v4l2_subdev *sd, | |
| 688 | − struct v4l2_subdev_state *state) | |
| 463 | +/* Initialize control handlers */ | |
| 464 | +static int imx219_init_controls(struct imx219 *imx219) | |
| 689 | 465 | { |
| 690 | − struct imx219 *imx219 = to_imx219(sd); | |
| 691 | − struct v4l2_mbus_framefmt *format; | |
| 692 | − struct v4l2_rect *crop; | |
| 466 | + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | |
| 467 | + const struct imx219_mode *mode = &supported_modes[0]; | |
| 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. */ | |
| 695 | − format = v4l2_subdev_get_pad_format(sd, state, 0); | |
| 696 | − imx219_update_pad_format(imx219, &supported_modes[0], format, | |
| 697 | − MEDIA_BUS_FMT_SRGGB10_1X10); | |
| 473 | + ctrl_hdlr = &imx219->ctrl_handler; | |
| 474 | + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); | |
| 475 | + if (ret) | |
| 476 | + return ret; | |
| 698 | 477 | |
| 699 | − /* Initialize the crop rectangle. */ | |
| 700 | − crop = v4l2_subdev_get_pad_crop(sd, state, 0); | |
| 701 | − crop->top = IMX219_PIXEL_ARRAY_TOP; | |
| 702 | − crop->left = IMX219_PIXEL_ARRAY_LEFT; | |
| 703 | − crop->width = IMX219_PIXEL_ARRAY_WIDTH; | |
| 704 | − crop->height = IMX219_PIXEL_ARRAY_HEIGHT; | |
| 478 | + /* By default, PIXEL_RATE is read only */ | |
| 479 | + imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 480 | + V4L2_CID_PIXEL_RATE, | |
| 481 | + imx219_get_pixel_rate(imx219), | |
| 482 | + imx219_get_pixel_rate(imx219), 1, | |
| 483 | + imx219_get_pixel_rate(imx219)); | |
| 705 | 484 | |
| 706 | − return 0; | |
| 707 | −} | |
| 485 | + imx219->link_freq = | |
| 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, | |
| 710 | − struct v4l2_subdev_state *sd_state, | |
| 711 | − struct v4l2_subdev_mbus_code_enum *code) | |
| 712 | −{ | |
| 713 | − struct imx219 *imx219 = to_imx219(sd); | |
| 494 | + /* Initial vblank/hblank/exposure parameters based on current mode */ | |
| 495 | + imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 496 | + V4L2_CID_VBLANK, IMX219_VBLANK_MIN, | |
| 497 | + IMX219_VTS_MAX - mode->height, 1, | |
| 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)) | |
| 716 | − return -EINVAL; | |
| 514 | + v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, | |
| 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; | |
| 721 | −} | |
| 522 | + imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 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, | |
| 724 | − struct v4l2_subdev_state *sd_state, | |
| 725 | − struct v4l2_subdev_frame_size_enum *fse) | |
| 726 | −{ | |
| 727 | − struct imx219 *imx219 = to_imx219(sd); | |
| 728 | − u32 code; | |
| 527 | + imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 528 | + V4L2_CID_VFLIP, 0, 1, 1, 0); | |
| 529 | + if (imx219->vflip) | |
| 530 | + imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | |
| 729 | 531 | |
| 730 | − if (fse->index >= ARRAY_SIZE(supported_modes)) | |
| 731 | − return -EINVAL; | |
| 532 | + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, | |
| 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); | |
| 734 | − if (fse->code != code) | |
| 735 | − return -EINVAL; | |
| 552 | + if (ctrl_hdlr->error) { | |
| 553 | + ret = ctrl_hdlr->error; | |
| 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; | |
| 738 | − fse->max_width = fse->min_width; | |
| 739 | − fse->min_height = supported_modes[fse->index].height; | |
| 740 | − fse->max_height = fse->min_height; | |
| 559 | + ret = v4l2_fwnode_device_parse(&client->dev, &props); | |
| 560 | + if (ret) | |
| 561 | + goto error; | |
| 741 | 562 | |
| 742 | − return 0; | |
| 743 | −} | |
| 744 | − | |
| 745 | −static int imx219_set_pad_format(struct v4l2_subdev *sd, | |
| 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); | |
| 563 | + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, | |
| 564 | + &props); | |
| 565 | + if (ret) | |
| 566 | + goto error; | |
| 761 | 567 | |
| 762 | − format = v4l2_subdev_get_pad_format(sd, sd_state, 0); | |
| 763 | − crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); | |
| 568 | + imx219->sd.ctrl_handler = ctrl_hdlr; | |
| 764 | 569 | |
| 765 | − *format = fmt->format; | |
| 766 | − *crop = mode->crop; | |
| 570 | + return 0; | |
| 767 | 571 | |
| 768 | − if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | |
| 769 | − imx219->mode = mode; | |
| 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 | − } | |
| 572 | +error: | |
| 573 | + v4l2_ctrl_handler_free(ctrl_hdlr); | |
| 793 | 574 | |
| 794 | − return 0; | |
| 575 | + return ret; | |
| 795 | 576 | } |
| 796 | 577 | |
| 797 | −static int imx219_set_framefmt(struct imx219 *imx219, | |
| 798 | − const struct v4l2_mbus_framefmt *format) | |
| 578 | +static void imx219_free_controls(struct imx219 *imx219) | |
| 799 | 579 | { |
| 800 | − switch (format->code) { | |
| 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; | |
| 580 | + v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); | |
| 817 | 581 | } |
| 818 | 582 | |
| 819 | −static int imx219_set_binning(struct imx219 *imx219, | |
| 820 | − const struct v4l2_mbus_framefmt *format) | |
| 583 | +/* ----------------------------------------------------------------------------- | |
| 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) { | |
| 823 | − return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | |
| 824 | − IMX219_REG_VALUE_16BIT, | |
| 825 | − IMX219_BINNING_NONE); | |
| 826 | − } | |
| 590 | + const struct v4l2_mbus_framefmt *format; | |
| 591 | + const struct v4l2_rect *crop; | |
| 592 | + unsigned int bpp; | |
| 593 | + u64 bin_h, bin_v; | |
| 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 | 599 | switch (format->code) { |
| 829 | 600 | case MEDIA_BUS_FMT_SRGGB8_1X8: |
| 830 | 601 | case MEDIA_BUS_FMT_SGRBG8_1X8: |
| 831 | 602 | case MEDIA_BUS_FMT_SGBRG8_1X8: |
| 832 | 603 | case MEDIA_BUS_FMT_SBGGR8_1X8: |
| 833 | − return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | |
| 834 | − IMX219_REG_VALUE_16BIT, | |
| 835 | − IMX219_BINNING_2X2_ANALOG); | |
| 604 | + bpp = 8; | |
| 605 | + break; | |
| 836 | 606 | |
| 837 | 607 | case MEDIA_BUS_FMT_SRGGB10_1X10: |
| 838 | 608 | case MEDIA_BUS_FMT_SGRBG10_1X10: |
| 839 | 609 | case MEDIA_BUS_FMT_SGBRG10_1X10: |
| 840 | 610 | case MEDIA_BUS_FMT_SBGGR10_1X10: |
| 841 | − return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, | |
| 842 | − IMX219_REG_VALUE_16BIT, | |
| 843 | − IMX219_BINNING_2X2); | |
| 611 | + default: | |
| 612 | + bpp = 10; | |
| 613 | + break; | |
| 844 | 614 | } |
| 845 | 615 | |
| 846 | − return -EINVAL; | |
| 847 | −} | |
| 616 | + cci_write(imx219->regmap, IMX219_REG_X_ADD_STA_A, | |
| 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, | |
| 850 | − struct v4l2_subdev_state *sd_state, | |
| 851 | − struct v4l2_subdev_selection *sel) | |
| 852 | −{ | |
| 853 | − switch (sel->target) { | |
| 854 | − case V4L2_SEL_TGT_CROP: { | |
| 855 | − sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); | |
| 856 | − return 0; | |
| 635 | + switch (crop->height / format->height) { | |
| 636 | + case 1: | |
| 637 | + default: | |
| 638 | + bin_v = IMX219_BINNING_NONE; | |
| 639 | + break; | |
| 640 | + case 2: | |
| 641 | + bin_v = bpp == 8 ? IMX219_BINNING_X2_ANALOG : IMX219_BINNING_X2; | |
| 642 | + break; | |
| 857 | 643 | } |
| 858 | 644 | |
| 859 | − case V4L2_SEL_TGT_NATIVE_SIZE: | |
| 860 | − sel->r.top = 0; | |
| 861 | − sel->r.left = 0; | |
| 862 | − sel->r.width = IMX219_NATIVE_WIDTH; | |
| 863 | − sel->r.height = IMX219_NATIVE_HEIGHT; | |
| 645 | + cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H, bin_h, &ret); | |
| 646 | + cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V, bin_v, &ret); | |
| 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: | |
| 868 | − case V4L2_SEL_TGT_CROP_BOUNDS: | |
| 869 | − sel->r.top = IMX219_PIXEL_ARRAY_TOP; | |
| 870 | − sel->r.left = IMX219_PIXEL_ARRAY_LEFT; | |
| 871 | − sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; | |
| 872 | − sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; | |
| 653 | + cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_WIDTH, | |
| 654 | + format->width, &ret); | |
| 655 | + cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_HEIGHT, | |
| 656 | + format->height, &ret); | |
| 873 | 657 | |
| 874 | − return 0; | |
| 875 | − } | |
| 658 | + cci_write(imx219->regmap, IMX219_REG_CSI_DATA_FORMAT_A, | |
| 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 | 665 | static int imx219_configure_lanes(struct imx219 *imx219) |
| 881 | 666 | { |
| 882 | − return imx219_write_reg(imx219, IMX219_REG_CSI_LANE_MODE, | |
| 883 | − IMX219_REG_VALUE_08BIT, (imx219->lanes == 2) ? | |
| 884 | − IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE); | |
| 667 | + return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE, | |
| 668 | + imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE : | |
| 669 | + IMX219_CSI_4_LANE_MODE, NULL); | |
| 885 | 670 | }; |
| 886 | 671 | |
| 887 | 672 | static int imx219_start_streaming(struct imx219 *imx219, |
| 888 | 673 | struct v4l2_subdev_state *state) |
| 889 | 674 | { |
| 890 | 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 | 676 | int ret; |
| 894 | 677 | |
| 895 | 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 | 680 | return ret; |
| 898 | 681 | |
| 899 | 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 | 685 | if (ret) { |
| 902 | 686 | dev_err(&client->dev, "%s failed to send mfg header\n", __func__); |
| 903 | 687 | goto err_rpm_put; |
| @@ -910,37 +694,22 @@ static int imx219_start_streaming(struct imx219 *imx219, · 6 unmodified lines | ||
| 910 | 694 | goto err_rpm_put; |
| 911 | 695 | } |
| 912 | 696 | |
| 913 | − /* Apply default values of current mode */ | |
| 914 | − reg_list = &imx219->mode->reg_list; | |
| 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); | |
| 697 | + /* Apply format and crop settings. */ | |
| 698 | + ret = imx219_set_framefmt(imx219, state); | |
| 923 | 699 | if (ret) { |
| 924 | 700 | dev_err(&client->dev, "%s failed to set frame format: %d\n", |
| 925 | 701 | __func__, ret); |
| 926 | 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 | 705 | /* Apply customized values from user */ |
| 937 | 706 | ret = __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler); |
| 938 | 707 | if (ret) |
| 939 | 708 | goto err_rpm_put; |
| 940 | 709 | |
| 941 | 710 | /* set stream on register */ |
| 942 | − ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | |
| 943 | − IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING); | |
| 711 | + ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, | |
| 712 | + IMX219_MODE_STREAMING, NULL); | |
| 944 | 713 | if (ret) |
| 945 | 714 | goto err_rpm_put; |
| 946 | 715 | |
| @@ -961,8 +730,8 @@ static void imx219_stop_streaming(struct imx219 *imx219) · 14 unmodified lines | ||
| 961 | 730 | int ret; |
| 962 | 731 | |
| 963 | 732 | /* set stream off register */ |
| 964 | − ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | |
| 965 | − IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY); | |
| 733 | + ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, | |
| 734 | + IMX219_MODE_STANDBY, NULL); | |
| 966 | 735 | if (ret) |
| 967 | 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 | 750 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| 982 | 751 | |
| 983 | − if (imx219->streaming == enable) | |
| 984 | − goto unlock; | |
| 985 | − | |
| 986 | − if (enable) { | |
| 987 | − /* | |
| 988 | − * Apply default & customized values | |
| 989 | − * and then start streaming. | |
| 990 | − */ | |
| 752 | + if (enable) | |
| 991 | 753 | ret = imx219_start_streaming(imx219, state); |
| 992 | − if (ret) | |
| 993 | − goto unlock; | |
| 994 | − } else { | |
| 754 | + else | |
| 995 | 755 | imx219_stop_streaming(imx219); |
| 996 | − } | |
| 997 | − | |
| 998 | − imx219->streaming = enable; | |
| 999 | 756 | |
| 1000 | −unlock: | |
| 1001 | 757 | v4l2_subdev_unlock_state(state); |
| 1002 | 758 | return ret; |
| 1003 | 759 | } |
| 1004 | 760 | |
| 1005 | −/* Power/clock management functions */ | |
| 1006 | −static int imx219_power_on(struct device *dev) | |
| 761 | +static void imx219_update_pad_format(struct imx219 *imx219, | |
| 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); | |
| 1009 | − struct imx219 *imx219 = to_imx219(sd); | |
| 1010 | − int ret; | |
| 765 | + /* Bayer order varies with flips */ | |
| 766 | + fmt->code = imx219_get_format_code(imx219, code); | |
| 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, | |
| 1013 | − imx219->supplies); | |
| 1014 | − if (ret) { | |
| 1015 | − dev_err(dev, "%s: failed to enable regulators\n", | |
| 1016 | − __func__); | |
| 1017 | − return ret; | |
| 1018 | − } | |
| 776 | +static int imx219_enum_mbus_code(struct v4l2_subdev *sd, | |
| 777 | + struct v4l2_subdev_state *state, | |
| 778 | + struct v4l2_subdev_mbus_code_enum *code) | |
| 779 | +{ | |
| 780 | + struct imx219 *imx219 = to_imx219(sd); | |
| 1019 | 781 | |
| 1020 | − ret = clk_prepare_enable(imx219->xclk); | |
| 1021 | − if (ret) { | |
| 1022 | − dev_err(dev, "%s: failed to enable clock\n", | |
| 1023 | − __func__); | |
| 1024 | − goto reg_off; | |
| 1025 | − } | |
| 782 | + if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4)) | |
| 783 | + return -EINVAL; | |
| 1026 | 784 | |
| 1027 | − gpiod_set_value_cansleep(imx219->reset_gpio, 1); | |
| 1028 | − usleep_range(IMX219_XCLR_MIN_DELAY_US, | |
| 1029 | − IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US); | |
| 785 | + code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]); | |
| 1030 | 786 | |
| 1031 | 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 | 794 | struct imx219 *imx219 = to_imx219(sd); |
| 795 | + u32 code; | |
| 1043 | 796 | |
| 1044 | − gpiod_set_value_cansleep(imx219->reset_gpio, 0); | |
| 1045 | − regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); | |
| 1046 | − clk_disable_unprepare(imx219->xclk); | |
| 797 | + if (fse->index >= ARRAY_SIZE(supported_modes)) | |
| 798 | + return -EINVAL; | |
| 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 | 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 | 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) | |
| 1057 | − imx219_stop_streaming(imx219); | |
| 822 | + mode = v4l2_find_nearest_size(supported_modes, | |
| 823 | + ARRAY_SIZE(supported_modes), | |
| 824 | + width, height, | |
| 825 | + fmt->format.width, fmt->format.height); | |
| 1058 | 826 | |
| 1059 | − return 0; | |
| 1060 | −} | |
| 827 | + imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); | |
| 1061 | 828 | |
| 1062 | −static int __maybe_unused imx219_resume(struct device *dev) | |
| 1063 | −{ | |
| 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; | |
| 829 | + format = v4l2_subdev_get_pad_format(sd, state, 0); | |
| 830 | + *format = fmt->format; | |
| 1068 | 831 | |
| 1069 | − if (imx219->streaming) { | |
| 1070 | − state = v4l2_subdev_lock_and_get_active_state(sd); | |
| 1071 | − ret = imx219_start_streaming(imx219, state); | |
| 1072 | − v4l2_subdev_unlock_state(state); | |
| 1073 | − if (ret) | |
| 1074 | − goto error; | |
| 1075 | − } | |
| 832 | + /* | |
| 833 | + * Use binning to maximize the crop rectangle size, and centre it in the | |
| 834 | + * sensor. | |
| 835 | + */ | |
| 836 | + bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U); | |
| 837 | + bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U); | |
| 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: | |
| 1080 | − imx219_stop_streaming(imx219); | |
| 1081 | − imx219->streaming = false; | |
| 845 | + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | |
| 846 | + int exposure_max; | |
| 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); | |
| 1089 | − unsigned int i; | |
| 881 | + switch (sel->target) { | |
| 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++) | |
| 1092 | − imx219->supplies[i].supply = imx219_supply_name[i]; | |
| 887 | + case V4L2_SEL_TGT_NATIVE_SIZE: | |
| 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, | |
| 1095 | − IMX219_NUM_SUPPLIES, | |
| 1096 | − imx219->supplies); | |
| 1097 | −} | |
| 893 | + return 0; | |
| 1098 | 894 | |
| 1099 | −/* Verify chip ID */ | |
| 1100 | −static int imx219_identify_module(struct imx219 *imx219) | |
| 1101 | −{ | |
| 1102 | − struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | |
| 1103 | − int ret; | |
| 1104 | − u32 val; | |
| 895 | + case V4L2_SEL_TGT_CROP_DEFAULT: | |
| 896 | + case V4L2_SEL_TGT_CROP_BOUNDS: | |
| 897 | + sel->r.top = IMX219_PIXEL_ARRAY_TOP; | |
| 898 | + sel->r.left = IMX219_PIXEL_ARRAY_LEFT; | |
| 899 | + sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; | |
| 900 | + sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; | |
| 1105 | 901 | |
| 1106 | − ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID, | |
| 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; | |
| 902 | + return 0; | |
| 1112 | 903 | } |
| 1113 | 904 | |
| 1114 | − if (val != IMX219_CHIP_ID) { | |
| 1115 | − dev_err(&client->dev, "chip id mismatch: %x!=%x\n", | |
| 1116 | − IMX219_CHIP_ID, val); | |
| 1117 | − return -EIO; | |
| 1118 | − } | |
| 905 | + return -EINVAL; | |
| 906 | +} | |
| 907 | + | |
| 908 | +static int imx219_init_cfg(struct v4l2_subdev *sd, | |
| 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 | 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) | |
| 1149 | −{ | |
| 1150 | − return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; | |
| 1151 | −} | |
| 951 | +/* ----------------------------------------------------------------------------- | |
| 952 | + * Power management | |
| 953 | + */ | |
| 1152 | 954 | |
| 1153 | −/* Initialize control handlers */ | |
| 1154 | −static int imx219_init_controls(struct imx219 *imx219) | |
| 955 | +static int imx219_power_on(struct device *dev) | |
| 1155 | 956 | { |
| 1156 | − struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); | |
| 1157 | − struct v4l2_ctrl_handler *ctrl_hdlr; | |
| 1158 | − unsigned int height = imx219->mode->height; | |
| 1159 | − struct v4l2_fwnode_device_properties props; | |
| 1160 | − int exposure_max, exposure_def, hblank; | |
| 1161 | − int i, ret; | |
| 957 | + struct v4l2_subdev *sd = dev_get_drvdata(dev); | |
| 958 | + struct imx219 *imx219 = to_imx219(sd); | |
| 959 | + int ret; | |
| 1162 | 960 | |
| 1163 | − ctrl_hdlr = &imx219->ctrl_handler; | |
| 1164 | − ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); | |
| 1165 | − if (ret) | |
| 961 | + ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES, | |
| 962 | + imx219->supplies); | |
| 963 | + if (ret) { | |
| 964 | + dev_err(dev, "%s: failed to enable regulators\n", | |
| 965 | + __func__); | |
| 1166 | 966 | return ret; |
| 967 | + } | |
| 1167 | 968 | |
| 1168 | − /* By default, PIXEL_RATE is read only */ | |
| 1169 | − imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 1170 | − V4L2_CID_PIXEL_RATE, | |
| 1171 | − imx219_get_pixel_rate(imx219), | |
| 1172 | − imx219_get_pixel_rate(imx219), 1, | |
| 1173 | − imx219_get_pixel_rate(imx219)); | |
| 969 | + ret = clk_prepare_enable(imx219->xclk); | |
| 970 | + if (ret) { | |
| 971 | + dev_err(dev, "%s: failed to enable clock\n", | |
| 972 | + __func__); | |
| 973 | + goto reg_off; | |
| 974 | + } | |
| 1174 | 975 | |
| 1175 | − imx219->link_freq = | |
| 1176 | − v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, | |
| 1177 | − V4L2_CID_LINK_FREQ, | |
| 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; | |
| 976 | + gpiod_set_value_cansleep(imx219->reset_gpio, 1); | |
| 977 | + usleep_range(IMX219_XCLR_MIN_DELAY_US, | |
| 978 | + IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US); | |
| 1183 | 979 | |
| 1184 | − /* Initial vblank/hblank/exposure parameters based on current mode */ | |
| 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); | |
| 980 | + return 0; | |
| 1203 | 981 | |
| 1204 | − v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, | |
| 1205 | − IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX, | |
| 1206 | − IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT); | |
| 982 | +reg_off: | |
| 983 | + regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); | |
| 1207 | 984 | |
| 1208 | − v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN, | |
| 1209 | − IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX, | |
| 1210 | − IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT); | |
| 985 | + return ret; | |
| 986 | +} | |
| 1211 | 987 | |
| 1212 | − imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 1213 | − V4L2_CID_HFLIP, 0, 1, 1, 0); | |
| 1214 | − if (imx219->hflip) | |
| 1215 | − imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | |
| 988 | +static int imx219_power_off(struct device *dev) | |
| 989 | +{ | |
| 990 | + struct v4l2_subdev *sd = dev_get_drvdata(dev); | |
| 991 | + struct imx219 *imx219 = to_imx219(sd); | |
| 1216 | 992 | |
| 1217 | − imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, | |
| 1218 | − V4L2_CID_VFLIP, 0, 1, 1, 0); | |
| 1219 | − if (imx219->vflip) | |
| 1220 | − imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; | |
| 993 | + gpiod_set_value_cansleep(imx219->reset_gpio, 0); | |
| 994 | + regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies); | |
| 995 | + clk_disable_unprepare(imx219->xclk); | |
| 1221 | 996 | |
| 1222 | − v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, | |
| 1223 | − V4L2_CID_TEST_PATTERN, | |
| 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 | − } | |
| 997 | + return 0; | |
| 998 | +} | |
| 1241 | 999 | |
| 1242 | − if (ctrl_hdlr->error) { | |
| 1243 | − ret = ctrl_hdlr->error; | |
| 1244 | − dev_err(&client->dev, "%s control init failed (%d)\n", | |
| 1245 | − __func__, ret); | |
| 1246 | − goto error; | |
| 1247 | − } | |
| 1000 | +/* ----------------------------------------------------------------------------- | |
| 1001 | + * Probe & remove | |
| 1002 | + */ | |
| 1248 | 1003 | |
| 1249 | − ret = v4l2_fwnode_device_parse(&client->dev, &props); | |
| 1250 | − if (ret) | |
| 1251 | − goto error; | |
| 1004 | +static int imx219_get_regulators(struct imx219 *imx219) | |
| 1005 | +{ | |
| 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, | |
| 1254 | − &props); | |
| 1255 | − if (ret) | |
| 1256 | − goto error; | |
| 1009 | + for (i = 0; i < IMX219_NUM_SUPPLIES; i++) | |
| 1010 | + imx219->supplies[i].supply = imx219_supply_name[i]; | |
| 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: | |
| 1263 | − v4l2_ctrl_handler_free(ctrl_hdlr); | |
| 1024 | + ret = cci_read(imx219->regmap, IMX219_REG_CHIP_ID, &val, NULL); | |
| 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; | |
| 1266 | −} | |
| 1031 | + if (val != IMX219_CHIP_ID) { | |
| 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) | |
| 1269 | −{ | |
| 1270 | − v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); | |
| 1037 | + return 0; | |
| 1271 | 1038 | } |
| 1272 | 1039 | |
| 1273 | 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 | 1103 | if (imx219_check_hwcfg(dev, imx219)) |
| 1337 | 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 | 1113 | /* Get system clock (xclk) */ |
| 1340 | 1114 | imx219->xclk = devm_clk_get(dev, NULL); |
| 1341 | 1115 | if (IS_ERR(imx219->xclk)) { |
| @@ -1372,24 +1146,24 @@ static int imx219_probe(struct i2c_client *client) · 30 unmodified lines | ||
| 1372 | 1146 | if (ret) |
| 1373 | 1147 | goto error_power_off; |
| 1374 | 1148 | |
| 1375 | − /* Set default mode to max resolution */ | |
| 1376 | − imx219->mode = &supported_modes[0]; | |
| 1377 | − | |
| 1378 | − /* sensor doesn't enter LP-11 state upon power up until and unless | |
| 1149 | + /* | |
| 1150 | + * Sensor doesn't enter LP-11 state upon power up until and unless | |
| 1379 | 1151 | * streaming is started, so upon power up switch the modes to: |
| 1380 | 1152 | * streaming -> standby |
| 1381 | 1153 | */ |
| 1382 | − ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | |
| 1383 | − IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING); | |
| 1154 | + ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, | |
| 1155 | + IMX219_MODE_STREAMING, NULL); | |
| 1384 | 1156 | if (ret < 0) |
| 1385 | 1157 | goto error_power_off; |
| 1158 | + | |
| 1386 | 1159 | usleep_range(100, 110); |
| 1387 | 1160 | |
| 1388 | 1161 | /* put sensor back to standby mode */ |
| 1389 | − ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT, | |
| 1390 | − IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY); | |
| 1162 | + ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT, | |
| 1163 | + IMX219_MODE_STANDBY, NULL); | |
| 1391 | 1164 | if (ret < 0) |
| 1392 | 1165 | goto error_power_off; |
| 1166 | + | |
| 1393 | 1167 | usleep_range(100, 110); |
| 1394 | 1168 | |
| 1395 | 1169 | ret = imx219_init_controls(imx219); |
| @@ -1468,7 +1242,6 @@ static const struct of_device_id imx219_dt_ids[] = { · 72 unmodified lines | ||
| 1468 | 1242 | MODULE_DEVICE_TABLE(of, imx219_dt_ids); |
| 1469 | 1243 | |
| 1470 | 1244 | static const struct dev_pm_ops imx219_pm_ops = { |
| 1471 | − SET_SYSTEM_SLEEP_PM_OPS(imx219_suspend, imx219_resume) | |
| 1472 | 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 | 623 | struct mutex mutex; |
| 624 | 624 | |
| 625 | − /* Streaming on/off */ | |
| 626 | − bool streaming; | |
| 627 | − | |
| 628 | 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 | 1032 | int ret = 0; |
| 1036 | 1033 | |
| 1037 | 1034 | mutex_lock(&imx258->mutex); |
| 1038 | − if (imx258->streaming == enable) { | |
| 1039 | − mutex_unlock(&imx258->mutex); | |
| 1040 | − return 0; | |
| 1041 | − } | |
| 1042 | 1035 | |
| 1043 | 1036 | if (enable) { |
| 1044 | 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 | 1050 | pm_runtime_put(&client->dev); |
| 1058 | 1051 | } |
| 1059 | 1052 | |
| 1060 | − imx258->streaming = enable; | |
| 1061 | 1053 | mutex_unlock(&imx258->mutex); |
| 1062 | 1054 | |
| 1063 | 1055 | return ret; |
| @@ -1070,37 +1062,6 @@ err_unlock: · 6 unmodified lines | ||
| 1070 | 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 | 1065 | /* Verify chip ID */ |
| 1105 | 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 | 1332 | static const struct dev_pm_ops imx258_pm_ops = { |
| 1372 | − SET_SYSTEM_SLEEP_PM_OPS(imx258_suspend, imx258_resume) | |
| 1373 | 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 | 201 | const struct imx296_clk_params *clk_params; |
| 202 | 202 | bool mono; |
| 203 | 203 | |
| 204 | − bool streaming; | |
| 205 | − | |
| 206 | 204 | struct v4l2_subdev subdev; |
| 207 | 205 | struct media_pad pad; |
| 208 | 206 | |
| @@ -321,7 +319,7 @@ static int imx296_s_ctrl(struct v4l2_ctrl *ctrl) · 112 unmodified lines | ||
| 321 | 319 | unsigned int vmax; |
| 322 | 320 | int ret = 0; |
| 323 | 321 | |
| 324 | − if (!sensor->streaming) | |
| 322 | + if (!pm_runtime_get_if_in_use(sensor->dev)) | |
| 325 | 323 | return 0; |
| 326 | 324 | |
| 327 | 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 | 374 | break; |
| 377 | 375 | } |
| 378 | 376 | |
| 377 | + pm_runtime_put(sensor->dev); | |
| 378 | + | |
| 379 | 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 | 607 | pm_runtime_mark_last_busy(sensor->dev); |
| 608 | 608 | pm_runtime_put_autosuspend(sensor->dev); |
| 609 | 609 | |
| 610 | − sensor->streaming = false; | |
| 611 | − | |
| 612 | 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 | 618 | if (ret < 0) |
| 621 | 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 | 621 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); |
| 631 | 622 | if (ret < 0) |
| 632 | 623 | goto err_pm; |
| @@ -646,7 +637,6 @@ err_pm: · 13 unmodified lines | ||
| 646 | 637 | * likely has no other chance to recover. |
| 647 | 638 | */ |
| 648 | 639 | pm_runtime_put_sync(sensor->dev); |
| 649 | − sensor->streaming = false; | |
| 650 | 640 | |
| 651 | 641 | goto unlock; |
| 652 | 642 | } |
| @@ -138,8 +138,6 @@ struct imx319 { · 137 unmodified lines | ||
| 138 | 138 | */ |
| 139 | 139 | struct mutex mutex; |
| 140 | 140 | |
| 141 | − /* Streaming on/off */ | |
| 142 | − bool streaming; | |
| 143 | 141 | /* True if the device has been identified */ |
| 144 | 142 | bool identified; |
| 145 | 143 | }; |
| @@ -2166,10 +2164,6 @@ static int imx319_set_stream(struct v4l2_subdev *sd, int enable) · 2020 unmodified lines | ||
| 2166 | 2164 | int ret = 0; |
| 2167 | 2165 | |
| 2168 | 2166 | mutex_lock(&imx319->mutex); |
| 2169 | − if (imx319->streaming == enable) { | |
| 2170 | − mutex_unlock(&imx319->mutex); | |
| 2171 | − return 0; | |
| 2172 | − } | |
| 2173 | 2167 | |
| 2174 | 2168 | if (enable) { |
| 2175 | 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 | 2182 | pm_runtime_put(&client->dev); |
| 2189 | 2183 | } |
| 2190 | 2184 | |
| 2191 | − imx319->streaming = enable; | |
| 2192 | − | |
| 2193 | 2185 | /* vflip and hflip cannot change during streaming */ |
| 2194 | 2186 | __v4l2_ctrl_grab(imx319->vflip, enable); |
| 2195 | 2187 | __v4l2_ctrl_grab(imx319->hflip, enable); |
| @@ -2206,37 +2198,6 @@ err_unlock: · 10 unmodified lines | ||
| 2206 | 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 | 2201 | static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = { |
| 2241 | 2202 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
| 2242 | 2203 | .unsubscribe_event = v4l2_event_subdev_unsubscribe, |
| @@ -2542,10 +2503,6 @@ static void imx319_remove(struct i2c_client *client) · 299 unmodified lines | ||
| 2542 | 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 | 2506 | static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = { |
| 2550 | 2507 | { "SONY319A" }, |
| 2551 | 2508 | { /* sentinel */ } |
| @@ -2555,7 +2512,6 @@ MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids); · 3 unmodified lines | ||
| 2555 | 2512 | static struct i2c_driver imx319_i2c_driver = { |
| 2556 | 2513 | .driver = { |
| 2557 | 2514 | .name = "imx319", |
| 2558 | − .pm = &imx319_pm_ops, | |
| 2559 | 2515 | .acpi_match_table = ACPI_PTR(imx319_acpi_ids), |
| 2560 | 2516 | }, |
| 2561 | 2517 | .probe = imx319_probe, |
| @@ -56,6 +56,24 @@ · 55 unmodified lines | ||
| 56 | 56 | #define IMX334_REG_MIN 0x00 |
| 57 | 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 | 78 | * struct imx334_reg - imx334 sensor register |
| 61 | 79 | * @address: Register address |
| @@ -120,7 +138,6 @@ struct imx334_mode { · 58 unmodified lines | ||
| 120 | 138 | * @mutex: Mutex for serializing sensor controls |
| 121 | 139 | * @menu_skip_mask: Menu skip mask for link_freq_ctrl |
| 122 | 140 | * @cur_code: current selected format code |
| 123 | − * @streaming: Flag indicating streaming state | |
| 124 | 141 | */ |
| 125 | 142 | struct imx334 { |
| 126 | 143 | struct device *dev; |
| @@ -143,7 +160,6 @@ struct imx334 { · 16 unmodified lines | ||
| 143 | 160 | struct mutex mutex; |
| 144 | 161 | unsigned long menu_skip_mask; |
| 145 | 162 | u32 cur_code; |
| 146 | − bool streaming; | |
| 147 | 163 | }; |
| 148 | 164 | |
| 149 | 165 | static const s64 link_freq[] = { |
| @@ -430,6 +446,18 @@ static const struct imx334_reg mode_3840x2160_regs[] = { · 280 unmodified lines | ||
| 430 | 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 | 461 | static const struct imx334_reg raw10_framefmt_regs[] = { |
| 434 | 462 | {0x3050, 0x00}, |
| 435 | 463 | {0x319d, 0x00}, |
| @@ -716,6 +744,26 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) · 280 unmodified lines | ||
| 716 | 744 | case V4L2_CID_HBLANK: |
| 717 | 745 | ret = 0; |
| 718 | 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 | 767 | default: |
| 720 | 768 | dev_err(imx334->dev, "Invalid control %d", ctrl->id); |
| 721 | 769 | ret = -EINVAL; |
| @@ -1001,11 +1049,6 @@ static int imx334_set_stream(struct v4l2_subdev *sd, int enable) · 279 unmodified lines | ||
| 1001 | 1049 | |
| 1002 | 1050 | mutex_lock(&imx334->mutex); |
| 1003 | 1051 | |
| 1004 | − if (imx334->streaming == enable) { | |
| 1005 | − mutex_unlock(&imx334->mutex); | |
| 1006 | − return 0; | |
| 1007 | − } | |
| 1008 | − | |
| 1009 | 1052 | if (enable) { |
| 1010 | 1053 | ret = pm_runtime_resume_and_get(imx334->dev); |
| 1011 | 1054 | if (ret < 0) |
| @@ -1019,8 +1062,6 @@ static int imx334_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | ||
| 1019 | 1062 | pm_runtime_put(imx334->dev); |
| 1020 | 1063 | } |
| 1021 | 1064 | |
| 1022 | − imx334->streaming = enable; | |
| 1023 | − | |
| 1024 | 1065 | mutex_unlock(&imx334->mutex); |
| 1025 | 1066 | |
| 1026 | 1067 | return 0; |
| @@ -1222,7 +1263,7 @@ static int imx334_init_controls(struct imx334 *imx334) · 195 unmodified lines | ||
| 1222 | 1263 | u32 lpfr; |
| 1223 | 1264 | int ret; |
| 1224 | 1265 | |
| 1225 | − ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); | |
| 1266 | + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 7); | |
| 1226 | 1267 | if (ret) |
| 1227 | 1268 | return ret; |
| 1228 | 1269 | |
| @@ -1282,6 +1323,11 @@ static int imx334_init_controls(struct imx334 *imx334) · 53 unmodified lines | ||
| 1282 | 1323 | if (imx334->hblank_ctrl) |
| 1283 | 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 | 1331 | if (ctrl_hdlr->error) { |
| 1286 | 1332 | dev_err(imx334->dev, "control init failed: %d", |
| 1287 | 1333 | ctrl_hdlr->error); |
| @@ -119,7 +119,6 @@ struct imx335_mode { · 118 unmodified lines | ||
| 119 | 119 | * @vblank: Vertical blanking in lines |
| 120 | 120 | * @cur_mode: Pointer to current selected sensor mode |
| 121 | 121 | * @mutex: Mutex for serializing sensor controls |
| 122 | − * @streaming: Flag indicating streaming state | |
| 123 | 122 | */ |
| 124 | 123 | struct imx335 { |
| 125 | 124 | struct device *dev; |
| @@ -140,7 +139,6 @@ struct imx335 { · 14 unmodified lines | ||
| 140 | 139 | u32 vblank; |
| 141 | 140 | const struct imx335_mode *cur_mode; |
| 142 | 141 | struct mutex mutex; |
| 143 | − bool streaming; | |
| 144 | 142 | }; |
| 145 | 143 | |
| 146 | 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 | 704 | mutex_lock(&imx335->mutex); |
| 707 | 705 | |
| 708 | − if (imx335->streaming == enable) { | |
| 709 | − mutex_unlock(&imx335->mutex); | |
| 710 | − return 0; | |
| 711 | − } | |
| 712 | − | |
| 713 | 706 | if (enable) { |
| 714 | 707 | ret = pm_runtime_resume_and_get(imx335->dev); |
| 715 | 708 | if (ret) |
| @@ -723,8 +716,6 @@ static int imx335_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | ||
| 723 | 716 | pm_runtime_put(imx335->dev); |
| 724 | 717 | } |
| 725 | 718 | |
| 726 | − imx335->streaming = enable; | |
| 727 | − | |
| 728 | 719 | mutex_unlock(&imx335->mutex); |
| 729 | 720 | |
| 730 | 721 | return 0; |
| @@ -123,9 +123,6 @@ struct imx355 { · 122 unmodified lines | ||
| 123 | 123 | * Protect access to sensor v4l2 controls. |
| 124 | 124 | */ |
| 125 | 125 | struct mutex mutex; |
| 126 | − | |
| 127 | − /* Streaming on/off */ | |
| 128 | − bool streaming; | |
| 129 | 126 | }; |
| 130 | 127 | |
| 131 | 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 | 1433 | int ret = 0; |
| 1437 | 1434 | |
| 1438 | 1435 | mutex_lock(&imx355->mutex); |
| 1439 | − if (imx355->streaming == enable) { | |
| 1440 | − mutex_unlock(&imx355->mutex); | |
| 1441 | − return 0; | |
| 1442 | − } | |
| 1443 | 1436 | |
| 1444 | 1437 | if (enable) { |
| 1445 | 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 | 1451 | pm_runtime_put(&client->dev); |
| 1459 | 1452 | } |
| 1460 | 1453 | |
| 1461 | − imx355->streaming = enable; | |
| 1462 | − | |
| 1463 | 1454 | /* vflip and hflip cannot change during streaming */ |
| 1464 | 1455 | __v4l2_ctrl_grab(imx355->vflip, enable); |
| 1465 | 1456 | __v4l2_ctrl_grab(imx355->hflip, enable); |
| @@ -1476,37 +1467,6 @@ err_unlock: · 10 unmodified lines | ||
| 1476 | 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 | 1470 | /* Verify chip ID */ |
| 1511 | 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 | 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 | 1792 | static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = { |
| 1837 | 1793 | { "SONY355A" }, |
| 1838 | 1794 | { /* sentinel */ } |
| @@ -1842,7 +1798,6 @@ MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids); · 3 unmodified lines | ||
| 1842 | 1798 | static struct i2c_driver imx355_i2c_driver = { |
| 1843 | 1799 | .driver = { |
| 1844 | 1800 | .name = "imx355", |
| 1845 | − .pm = &imx355_pm_ops, | |
| 1846 | 1801 | .acpi_match_table = ACPI_PTR(imx355_acpi_ids), |
| 1847 | 1802 | }, |
| 1848 | 1803 | .probe = imx355_probe, |
| @@ -127,7 +127,6 @@ static const char * const imx412_supply_names[] = { · 126 unmodified lines | ||
| 127 | 127 | * @vblank: Vertical blanking in lines |
| 128 | 128 | * @cur_mode: Pointer to current selected sensor mode |
| 129 | 129 | * @mutex: Mutex for serializing sensor controls |
| 130 | − * @streaming: Flag indicating streaming state | |
| 131 | 130 | */ |
| 132 | 131 | struct imx412 { |
| 133 | 132 | struct device *dev; |
| @@ -149,7 +148,6 @@ struct imx412 { · 15 unmodified lines | ||
| 149 | 148 | u32 vblank; |
| 150 | 149 | const struct imx412_mode *cur_mode; |
| 151 | 150 | struct mutex mutex; |
| 152 | − bool streaming; | |
| 153 | 151 | }; |
| 154 | 152 | |
| 155 | 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 | 856 | mutex_lock(&imx412->mutex); |
| 859 | 857 | |
| 860 | − if (imx412->streaming == enable) { | |
| 861 | − mutex_unlock(&imx412->mutex); | |
| 862 | − return 0; | |
| 863 | − } | |
| 864 | − | |
| 865 | 858 | if (enable) { |
| 866 | 859 | ret = pm_runtime_resume_and_get(imx412->dev); |
| 867 | 860 | if (ret) |
| @@ -875,8 +868,6 @@ static int imx412_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | ||
| 875 | 868 | pm_runtime_put(imx412->dev); |
| 876 | 869 | } |
| 877 | 870 | |
| 878 | − imx412->streaming = enable; | |
| 879 | − | |
| 880 | 871 | mutex_unlock(&imx412->mutex); |
| 881 | 872 | |
| 882 | 873 | return 0; |
| @@ -353,8 +353,6 @@ struct imx415 { · 352 unmodified lines | ||
| 353 | 353 | |
| 354 | 354 | const struct imx415_clk_params *clk_params; |
| 355 | 355 | |
| 356 | − bool streaming; | |
| 357 | − | |
| 358 | 356 | struct v4l2_subdev subdev; |
| 359 | 357 | struct media_pad pad; |
| 360 | 358 | |
| @@ -542,8 +540,9 @@ static int imx415_s_ctrl(struct v4l2_ctrl *ctrl) · 181 unmodified lines | ||
| 542 | 540 | struct v4l2_subdev_state *state; |
| 543 | 541 | unsigned int vmax; |
| 544 | 542 | unsigned int flip; |
| 543 | + int ret; | |
| 545 | 544 | |
| 546 | − if (!sensor->streaming) | |
| 545 | + if (!pm_runtime_get_if_in_use(sensor->dev)) | |
| 547 | 546 | return 0; |
| 548 | 547 | |
| 549 | 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 | 553 | /* clamp the exposure value to VMAX. */ |
| 555 | 554 | vmax = format->height + sensor->vblank->cur.val; |
| 556 | 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 | 559 | case V4L2_CID_ANALOGUE_GAIN: |
| 560 | 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 | 564 | case V4L2_CID_HFLIP: |
| 564 | 565 | case V4L2_CID_VFLIP: |
| 565 | 566 | flip = (sensor->hflip->val << IMX415_HREVERSE_SHIFT) | |
| 566 | 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 | 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 | 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 | 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 | 774 | pm_runtime_mark_last_busy(sensor->dev); |
| 767 | 775 | pm_runtime_put_autosuspend(sensor->dev); |
| 768 | 776 | |
| 769 | − sensor->streaming = false; | |
| 770 | − | |
| 771 | 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 | 785 | if (ret) |
| 780 | 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 | 788 | ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); |
| 790 | 789 | if (ret < 0) |
| 791 | 790 | goto err_pm; |
| @@ -807,7 +806,6 @@ err_pm: · 15 unmodified lines | ||
| 807 | 806 | * likely has no other chance to recover. |
| 808 | 807 | */ |
| 809 | 808 | pm_runtime_put_sync(sensor->dev); |
| 810 | − sensor->streaming = false; | |
| 811 | 809 | |
| 812 | 810 | goto unlock; |
| 813 | 811 | } |
| @@ -842,15 +840,6 @@ static int imx415_enum_frame_size(struct v4l2_subdev *sd, · 28 unmodified lines | ||
| 842 | 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 | 843 | static int imx415_set_format(struct v4l2_subdev *sd, |
| 855 | 844 | struct v4l2_subdev_state *state, |
| 856 | 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 | 902 | static const struct v4l2_subdev_pad_ops imx415_subdev_pad_ops = { |
| 914 | 903 | .enum_mbus_code = imx415_enum_mbus_code, |
| 915 | 904 | .enum_frame_size = imx415_enum_frame_size, |
| 916 | − .get_fmt = imx415_get_format, | |
| 905 | + .get_fmt = v4l2_subdev_get_fmt, | |
| 917 | 906 | .set_fmt = imx415_set_format, |
| 918 | 907 | .get_selection = imx415_get_selection, |
| 919 | 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 | 1450 | i2c_mux_mask |= BIT(id); |
| 1451 | 1451 | } |
| 1452 | − of_node_put(node); | |
| 1453 | 1452 | of_node_put(i2c_mux); |
| 1454 | 1453 | |
| 1455 | 1454 | /* Parse the endpoints */ |
| @@ -1513,7 +1512,6 @@ static int max9286_parse_dt(struct max9286_priv *priv) · 57 unmodified lines | ||
| 1513 | 1512 | priv->source_mask |= BIT(ep.port); |
| 1514 | 1513 | priv->nsources++; |
| 1515 | 1514 | } |
| 1516 | − of_node_put(node); | |
| 1517 | 1515 | |
| 1518 | 1516 | of_property_read_u32(dev->of_node, "maxim,bus-width", &priv->bus_width); |
| 1519 | 1517 | switch (priv->bus_width) { |
| @@ -561,7 +561,7 @@ static int msp_log_status(struct v4l2_subdev *sd) · 560 unmodified lines | ||
| 561 | 561 | struct msp_state *state = to_state(sd); |
| 562 | 562 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 563 | 563 | const char *p; |
| 564 | − char prefix[V4L2_SUBDEV_NAME_SIZE + 20]; | |
| 564 | + char prefix[sizeof(sd->name) + 20]; | |
| 565 | 565 | |
| 566 | 566 | if (state->opmode == OPMODE_AUTOSELECT) |
| 567 | 567 | msp_detect_stereo(client); |
| @@ -93,7 +93,6 @@ struct mt9m001 { · 92 unmodified lines | ||
| 93 | 93 | struct v4l2_ctrl *autoexposure; |
| 94 | 94 | struct v4l2_ctrl *exposure; |
| 95 | 95 | }; |
| 96 | − bool streaming; | |
| 97 | 96 | struct mutex mutex; |
| 98 | 97 | struct v4l2_rect rect; /* Sensor window */ |
| 99 | 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 | 213 | mutex_lock(&mt9m001->mutex); |
| 215 | 214 | |
| 216 | − if (mt9m001->streaming == enable) | |
| 217 | − goto done; | |
| 218 | − | |
| 219 | 215 | if (enable) { |
| 220 | 216 | ret = pm_runtime_resume_and_get(&client->dev); |
| 221 | 217 | if (ret < 0) |
| @@ -239,8 +235,6 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) · 17 unmodified lines | ||
| 239 | 235 | pm_runtime_put(&client->dev); |
| 240 | 236 | } |
| 241 | 237 | |
| 242 | − mt9m001->streaming = enable; | |
| 243 | −done: | |
| 244 | 238 | mutex_unlock(&mt9m001->mutex); |
| 245 | 239 | |
| 246 | 240 | return 0; |
| @@ -244,9 +244,7 @@ struct mt9m111 { · 243 unmodified lines | ||
| 244 | 244 | bool is_streaming; |
| 245 | 245 | /* user point of view - 0: falling 1: rising edge */ |
| 246 | 246 | unsigned int pclk_sample:1; |
| 247 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 248 | 247 | struct media_pad pad; |
| 249 | −#endif | |
| 250 | 248 | }; |
| 251 | 249 | |
| 252 | 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 | 525 | return -EINVAL; |
| 528 | 526 | |
| 529 | 527 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 530 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 531 | 528 | mf = v4l2_subdev_get_try_format(sd, sd_state, format->pad); |
| 532 | 529 | format->format = *mf; |
| 533 | 530 | return 0; |
| 534 | −#else | |
| 535 | − return -EINVAL; | |
| 536 | −#endif | |
| 537 | 531 | } |
| 538 | 532 | |
| 539 | 533 | mf->width = mt9m111->width; |
| @@ -1120,7 +1114,6 @@ static int mt9m111_s_stream(struct v4l2_subdev *sd, int enable) · 580 unmodified lines | ||
| 1120 | 1114 | static int mt9m111_init_cfg(struct v4l2_subdev *sd, |
| 1121 | 1115 | struct v4l2_subdev_state *sd_state) |
| 1122 | 1116 | { |
| 1123 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1124 | 1117 | struct v4l2_mbus_framefmt *format = |
| 1125 | 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 | 1125 | format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
| 1133 | 1126 | format->quantization = V4L2_QUANTIZATION_DEFAULT; |
| 1134 | 1127 | format->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
| 1135 | −#endif | |
| 1128 | + | |
| 1136 | 1129 | return 0; |
| 1137 | 1130 | } |
| 1138 | 1131 | |
| @@ -1315,13 +1308,11 @@ static int mt9m111_probe(struct i2c_client *client) · 176 unmodified lines | ||
| 1315 | 1308 | return ret; |
| 1316 | 1309 | } |
| 1317 | 1310 | |
| 1318 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 1319 | 1311 | mt9m111->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1320 | 1312 | mt9m111->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1321 | 1313 | ret = media_entity_pads_init(&mt9m111->subdev.entity, 1, &mt9m111->pad); |
| 1322 | 1314 | if (ret < 0) |
| 1323 | 1315 | goto out_hdlfree; |
| 1324 | −#endif | |
| 1325 | 1316 | |
| 1326 | 1317 | mt9m111->current_mode = &mt9m111_mode_data[MT9M111_MODE_SXGA_15FPS]; |
| 1327 | 1318 | mt9m111->frame_interval.numerator = 1; |
| @@ -1350,10 +1341,8 @@ static int mt9m111_probe(struct i2c_client *client) · 22 unmodified lines | ||
| 1350 | 1341 | return 0; |
| 1351 | 1342 | |
| 1352 | 1343 | out_entityclean: |
| 1353 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 1354 | 1344 | media_entity_cleanup(&mt9m111->subdev.entity); |
| 1355 | 1345 | out_hdlfree: |
| 1356 | −#endif | |
| 1357 | 1346 | v4l2_ctrl_handler_free(&mt9m111->hdl); |
| 1358 | 1347 | |
| 1359 | 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 | 50 | struct mt9v011 { |
| 51 | 51 | struct v4l2_subdev sd; |
| 52 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 53 | 52 | struct media_pad pad; |
| 54 | −#endif | |
| 55 | 53 | struct v4l2_ctrl_handler ctrls; |
| 56 | 54 | unsigned width, height; |
| 57 | 55 | unsigned xtal; |
| @@ -483,9 +481,7 @@ static int mt9v011_probe(struct i2c_client *c) · 425 unmodified lines | ||
| 483 | 481 | u16 version; |
| 484 | 482 | struct mt9v011 *core; |
| 485 | 483 | struct v4l2_subdev *sd; |
| 486 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 487 | 484 | int ret; |
| 488 | −#endif | |
| 489 | 485 | |
| 490 | 486 | /* Check if the adapter supports the needed features */ |
| 491 | 487 | if (!i2c_check_functionality(c->adapter, |
| @@ -499,14 +495,12 @@ static int mt9v011_probe(struct i2c_client *c) · 7 unmodified lines | ||
| 499 | 495 | sd = &core->sd; |
| 500 | 496 | v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); |
| 501 | 497 | |
| 502 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 503 | 498 | core->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 504 | 499 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 505 | 500 | |
| 506 | 501 | ret = media_entity_pads_init(&sd->entity, 1, &core->pad); |
| 507 | 502 | if (ret < 0) |
| 508 | 503 | return ret; |
| 509 | −#endif | |
| 510 | 504 | |
| 511 | 505 | /* Check if the sensor is really a MT9V011 */ |
| 512 | 506 | version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/gpio/consumer.h> |
| 15 | 15 | #include <linux/i2c.h> |
| 16 | 16 | #include <linux/log2.h> |
| 17 | +#include <linux/mod_devicetable.h> | |
| 17 | 18 | #include <linux/mutex.h> |
| 18 | 19 | #include <linux/of.h> |
| 19 | 20 | #include <linux/of_graph.h> |
| @@ -1046,7 +1047,6 @@ done: · 1026 unmodified lines | ||
| 1046 | 1047 | |
| 1047 | 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 | 1050 | struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client); |
| 1051 | 1051 | struct mt9v032 *mt9v032; |
| 1052 | 1052 | unsigned int i; |
| @@ -1076,7 +1076,7 @@ static int mt9v032_probe(struct i2c_client *client) · 23 unmodified lines | ||
| 1076 | 1076 | |
| 1077 | 1077 | mutex_init(&mt9v032->power_lock); |
| 1078 | 1078 | mt9v032->pdata = pdata; |
| 1079 | − mt9v032->model = (const void *)did->driver_data; | |
| 1079 | + mt9v032->model = i2c_get_match_data(client); | |
| 1080 | 1080 | |
| 1081 | 1081 | v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 + |
| 1082 | 1082 | ARRAY_SIZE(mt9v032_aegc_controls)); |
| @@ -1272,29 +1272,27 @@ static const struct i2c_device_id mt9v032_id[] = { · 189 unmodified lines | ||
| 1272 | 1272 | { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, |
| 1273 | 1273 | { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, |
| 1274 | 1274 | { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] }, |
| 1275 | − { } | |
| 1275 | + { /* Sentinel */ } | |
| 1276 | 1276 | }; |
| 1277 | 1277 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); |
| 1278 | 1278 | |
| 1279 | −#if IS_ENABLED(CONFIG_OF) | |
| 1280 | 1279 | static const struct of_device_id mt9v032_of_match[] = { |
| 1281 | − { .compatible = "aptina,mt9v022" }, | |
| 1282 | − { .compatible = "aptina,mt9v022m" }, | |
| 1283 | − { .compatible = "aptina,mt9v024" }, | |
| 1284 | − { .compatible = "aptina,mt9v024m" }, | |
| 1285 | − { .compatible = "aptina,mt9v032" }, | |
| 1286 | − { .compatible = "aptina,mt9v032m" }, | |
| 1287 | − { .compatible = "aptina,mt9v034" }, | |
| 1288 | − { .compatible = "aptina,mt9v034m" }, | |
| 1280 | + { .compatible = "aptina,mt9v022", .data = &mt9v032_models[MT9V032_MODEL_V022_COLOR] }, | |
| 1281 | + { .compatible = "aptina,mt9v022m", .data = &mt9v032_models[MT9V032_MODEL_V022_MONO] }, | |
| 1282 | + { .compatible = "aptina,mt9v024", .data = &mt9v032_models[MT9V032_MODEL_V024_COLOR] }, | |
| 1283 | + { .compatible = "aptina,mt9v024m", .data = &mt9v032_models[MT9V032_MODEL_V024_MONO] }, | |
| 1284 | + { .compatible = "aptina,mt9v032", .data = &mt9v032_models[MT9V032_MODEL_V032_COLOR] }, | |
| 1285 | + { .compatible = "aptina,mt9v032m", .data = &mt9v032_models[MT9V032_MODEL_V032_MONO] }, | |
| 1286 | + { .compatible = "aptina,mt9v034", .data = &mt9v032_models[MT9V032_MODEL_V034_COLOR] }, | |
| 1287 | + { .compatible = "aptina,mt9v034m", .data = &mt9v032_models[MT9V032_MODEL_V034_MONO] }, | |
| 1289 | 1288 | { /* Sentinel */ } |
| 1290 | 1289 | }; |
| 1291 | 1290 | MODULE_DEVICE_TABLE(of, mt9v032_of_match); |
| 1292 | −#endif | |
| 1293 | 1291 | |
| 1294 | 1292 | static struct i2c_driver mt9v032_driver = { |
| 1295 | 1293 | .driver = { |
| 1296 | 1294 | .name = "mt9v032", |
| 1297 | − .of_match_table = of_match_ptr(mt9v032_of_match), | |
| 1295 | + .of_match_table = mt9v032_of_match, | |
| 1298 | 1296 | }, |
| 1299 | 1297 | .probe = mt9v032_probe, |
| 1300 | 1298 | .remove = mt9v032_remove, |
| @@ -121,9 +121,7 @@ struct mt9v111_dev { · 120 unmodified lines | ||
| 121 | 121 | u8 addr_space; |
| 122 | 122 | |
| 123 | 123 | struct v4l2_subdev sd; |
| 124 | −#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | |
| 125 | 124 | struct media_pad pad; |
| 126 | −#endif | |
| 127 | 125 | |
| 128 | 126 | struct v4l2_ctrl *auto_awb; |
| 129 | 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 | 796 | switch (which) { |
| 799 | 797 | case V4L2_SUBDEV_FORMAT_TRY: |
| 800 | −#if IS_ENABLED(CONFIG_VIDEO_V4L2_SUBDEV_API) | |
| 801 | 798 | return v4l2_subdev_get_try_format(&mt9v111->sd, sd_state, pad); |
| 802 | −#else | |
| 803 | − return &sd_state->pads->try_fmt; | |
| 804 | −#endif | |
| 805 | 799 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
| 806 | 800 | return &mt9v111->fmt; |
| 807 | 801 | default: |
| @@ -987,11 +981,9 @@ static const struct v4l2_subdev_ops mt9v111_ops = { · 179 unmodified lines | ||
| 987 | 981 | .pad = &mt9v111_pad_ops, |
| 988 | 982 | }; |
| 989 | 983 | |
| 990 | −#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | |
| 991 | 984 | static const struct media_entity_operations mt9v111_subdev_entity_ops = { |
| 992 | 985 | .link_validate = v4l2_subdev_link_validate, |
| 993 | 986 | }; |
| 994 | −#endif | |
| 995 | 987 | |
| 996 | 988 | /* --- V4L2 ctrl --- */ |
| 997 | 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 | 1196 | v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops); |
| 1205 | 1197 | |
| 1206 | −#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | |
| 1207 | 1198 | mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1208 | 1199 | mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops; |
| 1209 | 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 | 1203 | ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad); |
| 1213 | 1204 | if (ret) |
| 1214 | 1205 | goto error_free_entity; |
| 1215 | −#endif | |
| 1216 | 1206 | |
| 1217 | 1207 | ret = mt9v111_chip_probe(mt9v111); |
| 1218 | 1208 | if (ret) |
| @@ -1225,9 +1215,7 @@ static int mt9v111_probe(struct i2c_client *client) · 6 unmodified lines | ||
| 1225 | 1215 | return 0; |
| 1226 | 1216 | |
| 1227 | 1217 | error_free_entity: |
| 1228 | −#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | |
| 1229 | 1218 | media_entity_cleanup(&mt9v111->sd.entity); |
| 1230 | −#endif | |
| 1231 | 1219 | |
| 1232 | 1220 | error_free_ctrls: |
| 1233 | 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 | 1234 | v4l2_async_unregister_subdev(sd); |
| 1247 | 1235 | |
| 1248 | −#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) | |
| 1249 | 1236 | media_entity_cleanup(&sd->entity); |
| 1250 | −#endif | |
| 1251 | 1237 | |
| 1252 | 1238 | v4l2_ctrl_handler_free(&mt9v111->ctrls); |
| 1253 | 1239 | |
| @@ -434,9 +434,6 @@ struct og01a1b { · 433 unmodified lines | ||
| 434 | 434 | |
| 435 | 435 | /* To serialize asynchronus callbacks */ |
| 436 | 436 | struct mutex mutex; |
| 437 | − | |
| 438 | − /* Streaming on/off */ | |
| 439 | − bool streaming; | |
| 440 | 437 | }; |
| 441 | 438 | |
| 442 | 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 | 729 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 733 | 730 | int ret = 0; |
| 734 | 731 | |
| 735 | − if (og01a1b->streaming == enable) | |
| 736 | − return 0; | |
| 737 | − | |
| 738 | 732 | mutex_lock(&og01a1b->mutex); |
| 739 | 733 | if (enable) { |
| 740 | − ret = pm_runtime_get_sync(&client->dev); | |
| 741 | − if (ret < 0) { | |
| 742 | − pm_runtime_put_noidle(&client->dev); | |
| 734 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 735 | + if (ret) { | |
| 743 | 736 | mutex_unlock(&og01a1b->mutex); |
| 744 | 737 | return ret; |
| 745 | 738 | } |
| @@ -755,50 +748,11 @@ static int og01a1b_set_stream(struct v4l2_subdev *sd, int enable) · 9 unmodified lines | ||
| 755 | 748 | pm_runtime_put(&client->dev); |
| 756 | 749 | } |
| 757 | 750 | |
| 758 | − og01a1b->streaming = enable; | |
| 759 | 751 | mutex_unlock(&og01a1b->mutex); |
| 760 | 752 | |
| 761 | 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 | 756 | static int og01a1b_set_format(struct v4l2_subdev *sd, |
| 803 | 757 | struct v4l2_subdev_state *sd_state, |
| 804 | 758 | struct v4l2_subdev_format *fmt) |
| @@ -1096,10 +1050,6 @@ probe_error_v4l2_ctrl_handler_free: · 291 unmodified lines | ||
| 1096 | 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 | 1053 | #ifdef CONFIG_ACPI |
| 1104 | 1054 | static const struct acpi_device_id og01a1b_acpi_ids[] = { |
| 1105 | 1055 | {"OVTI01AC"}, |
| @@ -1112,7 +1062,6 @@ MODULE_DEVICE_TABLE(acpi, og01a1b_acpi_ids); · 6 unmodified lines | ||
| 1112 | 1062 | static struct i2c_driver og01a1b_i2c_driver = { |
| 1113 | 1063 | .driver = { |
| 1114 | 1064 | .name = "og01a1b", |
| 1115 | − .pm = &og01a1b_pm_ops, | |
| 1116 | 1065 | .acpi_match_table = ACPI_PTR(og01a1b_acpi_ids), |
| 1117 | 1066 | }, |
| 1118 | 1067 | .probe = og01a1b_probe, |
| @@ -287,9 +287,6 @@ struct ov01a10 { · 286 unmodified lines | ||
| 287 | 287 | struct v4l2_ctrl *exposure; |
| 288 | 288 | |
| 289 | 289 | const struct ov01a10_mode *cur_mode; |
| 290 | − | |
| 291 | − /* streaming state */ | |
| 292 | − bool streaming; | |
| 293 | 290 | }; |
| 294 | 291 | |
| 295 | 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 | 669 | int ret = 0; |
| 673 | 670 | |
| 674 | 671 | state = v4l2_subdev_lock_and_get_active_state(sd); |
| 675 | − if (ov01a10->streaming == enable) | |
| 676 | − goto unlock; | |
| 677 | 672 | |
| 678 | 673 | if (enable) { |
| 679 | 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 | 680 | pm_runtime_put(&client->dev); |
| 686 | 681 | goto unlock; |
| 687 | 682 | } |
| 688 | − | |
| 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; | |
| 683 | + } else { | |
| 733 | 684 | ov01a10_stop_streaming(ov01a10); |
| 685 | + pm_runtime_put(&client->dev); | |
| 734 | 686 | } |
| 735 | 687 | |
| 736 | −exit: | |
| 688 | +unlock: | |
| 737 | 689 | v4l2_subdev_unlock_state(state); |
| 738 | 690 | |
| 739 | 691 | return ret; |
| @@ -973,10 +925,6 @@ err_handler_free: · 233 unmodified lines | ||
| 973 | 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 | 928 | #ifdef CONFIG_ACPI |
| 981 | 929 | static const struct acpi_device_id ov01a10_acpi_ids[] = { |
| 982 | 930 | { "OVTI01A0" }, |
| @@ -989,7 +937,6 @@ MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids); · 6 unmodified lines | ||
| 989 | 937 | static struct i2c_driver ov01a10_i2c_driver = { |
| 990 | 938 | .driver = { |
| 991 | 939 | .name = "ov01a10", |
| 992 | − .pm = &ov01a10_pm_ops, | |
| 993 | 940 | .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids), |
| 994 | 941 | }, |
| 995 | 942 | .probe = ov01a10_probe, |
| @@ -570,8 +570,6 @@ unlock_and_return: · 569 unmodified lines | ||
| 570 | 570 | } |
| 571 | 571 | |
| 572 | 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 | 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 | 536 | /* To serialize asynchronus callbacks */ |
| 537 | 537 | struct mutex mutex; |
| 538 | 538 | |
| 539 | − /* Streaming on/off */ | |
| 540 | − bool streaming; | |
| 541 | − | |
| 542 | 539 | /* lanes index */ |
| 543 | 540 | u8 nlanes; |
| 544 | 541 | |
| @@ -1103,9 +1100,6 @@ static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable) · 558 unmodified lines | ||
| 1103 | 1100 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 1104 | 1101 | int ret = 0; |
| 1105 | 1102 | |
| 1106 | − if (ov08d10->streaming == enable) | |
| 1107 | − return 0; | |
| 1108 | − | |
| 1109 | 1103 | mutex_lock(&ov08d10->mutex); |
| 1110 | 1104 | if (enable) { |
| 1111 | 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 | 1119 | pm_runtime_put(&client->dev); |
| 1126 | 1120 | } |
| 1127 | 1121 | |
| 1128 | − ov08d10->streaming = enable; | |
| 1129 | − | |
| 1130 | 1122 | /* vflip and hflip cannot change during streaming */ |
| 1131 | 1123 | __v4l2_ctrl_grab(ov08d10->vflip, enable); |
| 1132 | 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 | 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 | 1131 | static int ov08d10_set_format(struct v4l2_subdev *sd, |
| 1179 | 1132 | struct v4l2_subdev_state *sd_state, |
| 1180 | 1133 | struct v4l2_subdev_format *fmt) |
| @@ -1501,10 +1454,6 @@ probe_error_v4l2_ctrl_handler_free: · 320 unmodified lines | ||
| 1501 | 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 | 1457 | #ifdef CONFIG_ACPI |
| 1509 | 1458 | static const struct acpi_device_id ov08d10_acpi_ids[] = { |
| 1510 | 1459 | { "OVTI08D1" }, |
| @@ -1517,7 +1466,6 @@ MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids); · 6 unmodified lines | ||
| 1517 | 1466 | static struct i2c_driver ov08d10_i2c_driver = { |
| 1518 | 1467 | .driver = { |
| 1519 | 1468 | .name = "ov08d10", |
| 1520 | − .pm = &ov08d10_pm_ops, | |
| 1521 | 1469 | .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), |
| 1522 | 1470 | }, |
| 1523 | 1471 | .probe = ov08d10_probe, |
| @@ -2432,9 +2432,6 @@ struct ov08x40 { · 2431 unmodified lines | ||
| 2432 | 2432 | |
| 2433 | 2433 | /* Mutex for serialized access */ |
| 2434 | 2434 | struct mutex mutex; |
| 2435 | − | |
| 2436 | − /* Streaming on/off */ | |
| 2437 | − bool streaming; | |
| 2438 | 2435 | }; |
| 2439 | 2436 | |
| 2440 | 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 | 2912 | int ret = 0; |
| 2916 | 2913 | |
| 2917 | 2914 | mutex_lock(&ov08x->mutex); |
| 2918 | − if (ov08x->streaming == enable) { | |
| 2919 | − mutex_unlock(&ov08x->mutex); | |
| 2920 | − return 0; | |
| 2921 | − } | |
| 2922 | 2915 | |
| 2923 | 2916 | if (enable) { |
| 2924 | 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 | 2930 | pm_runtime_put(&client->dev); |
| 2938 | 2931 | } |
| 2939 | 2932 | |
| 2940 | − ov08x->streaming = enable; | |
| 2941 | 2933 | mutex_unlock(&ov08x->mutex); |
| 2942 | 2934 | |
| 2943 | 2935 | return ret; |
| @@ -2950,37 +2942,6 @@ err_unlock: · 6 unmodified lines | ||
| 2950 | 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 | 2945 | /* Verify chip ID */ |
| 2985 | 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 | 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 | 3258 | #ifdef CONFIG_ACPI |
| 3302 | 3259 | static const struct acpi_device_id ov08x40_acpi_ids[] = { |
| 3303 | 3260 | {"OVTI08F4"}, |
| @@ -3310,7 +3267,6 @@ MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids); · 6 unmodified lines | ||
| 3310 | 3267 | static struct i2c_driver ov08x40_i2c_driver = { |
| 3311 | 3268 | .driver = { |
| 3312 | 3269 | .name = "ov08x40", |
| 3313 | − .pm = &ov08x40_pm_ops, | |
| 3314 | 3270 | .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), |
| 3315 | 3271 | }, |
| 3316 | 3272 | .probe = ov08x40_probe, |
| @@ -1044,9 +1044,6 @@ struct ov13858 { · 1043 unmodified lines | ||
| 1044 | 1044 | |
| 1045 | 1045 | /* Mutex for serialized access */ |
| 1046 | 1046 | struct mutex mutex; |
| 1047 | − | |
| 1048 | − /* Streaming on/off */ | |
| 1049 | − bool streaming; | |
| 1050 | 1047 | }; |
| 1051 | 1048 | |
| 1052 | 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 | 1464 | int ret = 0; |
| 1468 | 1465 | |
| 1469 | 1466 | mutex_lock(&ov13858->mutex); |
| 1470 | − if (ov13858->streaming == enable) { | |
| 1471 | − mutex_unlock(&ov13858->mutex); | |
| 1472 | − return 0; | |
| 1473 | − } | |
| 1474 | 1467 | |
| 1475 | 1468 | if (enable) { |
| 1476 | 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 | 1482 | pm_runtime_put(&client->dev); |
| 1490 | 1483 | } |
| 1491 | 1484 | |
| 1492 | − ov13858->streaming = enable; | |
| 1493 | 1485 | mutex_unlock(&ov13858->mutex); |
| 1494 | 1486 | |
| 1495 | 1487 | return ret; |
| @@ -1502,37 +1494,6 @@ err_unlock: · 6 unmodified lines | ||
| 1502 | 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 | 1497 | /* Verify chip ID */ |
| 1537 | 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 | 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 | 1751 | #ifdef CONFIG_ACPI |
| 1795 | 1752 | static const struct acpi_device_id ov13858_acpi_ids[] = { |
| 1796 | 1753 | {"OVTID858"}, |
| @@ -1803,7 +1760,6 @@ MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids); · 6 unmodified lines | ||
| 1803 | 1760 | static struct i2c_driver ov13858_i2c_driver = { |
| 1804 | 1761 | .driver = { |
| 1805 | 1762 | .name = "ov13858", |
| 1806 | − .pm = &ov13858_pm_ops, | |
| 1807 | 1763 | .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), |
| 1808 | 1764 | }, |
| 1809 | 1765 | .probe = ov13858_probe, |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #define OV13B10_REG_VTS 0x380e |
| 32 | 32 | #define OV13B10_VTS_30FPS 0x0c7c |
| 33 | 33 | #define OV13B10_VTS_60FPS 0x063e |
| 34 | +#define OV13B10_VTS_120FPS 0x0320 | |
| 34 | 35 | #define OV13B10_VTS_MAX 0x7fff |
| 35 | 36 | |
| 36 | 37 | /* HBLANK control - read only */ |
| @@ -468,6 +469,50 @@ static const struct ov13b10_reg mode_2080x1170_regs[] = { · 431 unmodified lines | ||
| 468 | 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 | 516 | static const char * const ov13b10_test_pattern_menu[] = { |
| 472 | 517 | "Disabled", |
| 473 | 518 | "Vertical Color Bar Type 1", |
| @@ -568,7 +613,18 @@ static const struct ov13b10_mode supported_modes[] = { · 94 unmodified lines | ||
| 568 | 613 | .regs = mode_2080x1170_regs, |
| 569 | 614 | }, |
| 570 | 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 | 630 | struct ov13b10 { |
| @@ -594,9 +650,6 @@ struct ov13b10 { · 19 unmodified lines | ||
| 594 | 650 | /* Mutex for serialized access */ |
| 595 | 651 | struct mutex mutex; |
| 596 | 652 | |
| 597 | − /* Streaming on/off */ | |
| 598 | − bool streaming; | |
| 599 | − | |
| 600 | 653 | /* True if the device has been identified */ |
| 601 | 654 | bool identified; |
| 602 | 655 | }; |
| @@ -1161,10 +1214,6 @@ static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable) · 558 unmodified lines | ||
| 1161 | 1214 | int ret = 0; |
| 1162 | 1215 | |
| 1163 | 1216 | mutex_lock(&ov13b->mutex); |
| 1164 | − if (ov13b->streaming == enable) { | |
| 1165 | − mutex_unlock(&ov13b->mutex); | |
| 1166 | − return 0; | |
| 1167 | − } | |
| 1168 | 1217 | |
| 1169 | 1218 | if (enable) { |
| 1170 | 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 | 1232 | pm_runtime_put(&client->dev); |
| 1184 | 1233 | } |
| 1185 | 1234 | |
| 1186 | − ov13b->streaming = enable; | |
| 1187 | 1235 | mutex_unlock(&ov13b->mutex); |
| 1188 | 1236 | |
| 1189 | 1237 | return ret; |
| @@ -1198,12 +1246,6 @@ err_unlock: · 8 unmodified lines | ||
| 1198 | 1246 | |
| 1199 | 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 | 1249 | ov13b10_power_off(dev); |
| 1208 | 1250 | |
| 1209 | 1251 | return 0; |
| @@ -1211,29 +1253,7 @@ static int ov13b10_suspend(struct device *dev) · 1 unmodified line | ||
| 1211 | 1253 | |
| 1212 | 1254 | static int ov13b10_resume(struct device *dev) |
| 1213 | 1255 | { |
| 1214 | − struct v4l2_subdev *sd = dev_get_drvdata(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; | |
| 1256 | + return ov13b10_power_on(dev); | |
| 1237 | 1257 | } |
| 1238 | 1258 | |
| 1239 | 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 | 1522 | full_power = acpi_dev_state_d0(&client->dev); |
| 1503 | 1523 | if (full_power) { |
| 1504 | − ov13b10_power_on(&client->dev); | |
| 1524 | + ret = ov13b10_power_on(&client->dev); | |
| 1505 | 1525 | if (ret) { |
| 1506 | 1526 | dev_err(&client->dev, "failed to power on\n"); |
| 1507 | 1527 | return ret; |
| @@ -293,9 +293,7 @@ struct ov2640_win_size { · 292 unmodified lines | ||
| 293 | 293 | |
| 294 | 294 | struct ov2640_priv { |
| 295 | 295 | struct v4l2_subdev subdev; |
| 296 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 297 | 296 | struct media_pad pad; |
| 298 | −#endif | |
| 299 | 297 | struct v4l2_ctrl_handler hdl; |
| 300 | 298 | u32 cfmt_code; |
| 301 | 299 | struct clk *clk; |
| @@ -922,13 +920,9 @@ static int ov2640_get_fmt(struct v4l2_subdev *sd, · 620 unmodified lines | ||
| 922 | 920 | return -EINVAL; |
| 923 | 921 | |
| 924 | 922 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 925 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 926 | 923 | mf = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 927 | 924 | format->format = *mf; |
| 928 | 925 | return 0; |
| 929 | −#else | |
| 930 | − return -EINVAL; | |
| 931 | −#endif | |
| 932 | 926 | } |
| 933 | 927 | |
| 934 | 928 | mf->width = priv->win->width; |
| @@ -1005,7 +999,6 @@ out: · 70 unmodified lines | ||
| 1005 | 999 | static int ov2640_init_cfg(struct v4l2_subdev *sd, |
| 1006 | 1000 | struct v4l2_subdev_state *sd_state) |
| 1007 | 1001 | { |
| 1008 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1009 | 1002 | struct v4l2_mbus_framefmt *try_fmt = |
| 1010 | 1003 | v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 1011 | 1004 | const struct ov2640_win_size *win = |
| @@ -1019,7 +1012,7 @@ static int ov2640_init_cfg(struct v4l2_subdev *sd, · 7 unmodified lines | ||
| 1019 | 1012 | try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
| 1020 | 1013 | try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; |
| 1021 | 1014 | try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; |
| 1022 | −#endif | |
| 1015 | + | |
| 1023 | 1016 | return 0; |
| 1024 | 1017 | } |
| 1025 | 1018 | |
| @@ -1205,17 +1198,14 @@ static int ov2640_probe(struct i2c_client *client) · 179 unmodified lines | ||
| 1205 | 1198 | return -ENOMEM; |
| 1206 | 1199 | |
| 1207 | 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 | 1202 | if (IS_ERR(priv->clk)) |
| 1210 | 1203 | return PTR_ERR(priv->clk); |
| 1211 | − ret = clk_prepare_enable(priv->clk); | |
| 1212 | − if (ret) | |
| 1213 | − return ret; | |
| 1214 | 1204 | } |
| 1215 | 1205 | |
| 1216 | 1206 | ret = ov2640_probe_dt(client, priv); |
| 1217 | 1207 | if (ret) |
| 1218 | − goto err_clk; | |
| 1208 | + return ret; | |
| 1219 | 1209 | |
| 1220 | 1210 | priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT); |
| 1221 | 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 | 1229 | ret = priv->hdl.error; |
| 1240 | 1230 | goto err_hdl; |
| 1241 | 1231 | } |
| 1242 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1243 | 1232 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1244 | 1233 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1245 | 1234 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); |
| 1246 | 1235 | if (ret < 0) |
| 1247 | 1236 | goto err_hdl; |
| 1248 | −#endif | |
| 1249 | 1237 | |
| 1250 | 1238 | ret = ov2640_video_probe(client); |
| 1251 | 1239 | if (ret < 0) |
| @@ -1264,8 +1252,6 @@ err_videoprobe: · 12 unmodified lines | ||
| 1264 | 1252 | err_hdl: |
| 1265 | 1253 | v4l2_ctrl_handler_free(&priv->hdl); |
| 1266 | 1254 | mutex_destroy(&priv->lock); |
| 1267 | −err_clk: | |
| 1268 | − clk_disable_unprepare(priv->clk); | |
| 1269 | 1255 | return ret; |
| 1270 | 1256 | } |
| 1271 | 1257 | |
| @@ -1278,7 +1264,6 @@ static void ov2640_remove(struct i2c_client *client) · 6 unmodified lines | ||
| 1278 | 1264 | mutex_destroy(&priv->lock); |
| 1279 | 1265 | media_entity_cleanup(&priv->subdev.entity); |
| 1280 | 1266 | v4l2_device_unregister_subdev(&priv->subdev); |
| 1281 | − clk_disable_unprepare(priv->clk); | |
| 1282 | 1267 | } |
| 1283 | 1268 | |
| 1284 | 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 | 1031 | dev_dbg(&client->dev, "ov2659_get_fmt\n"); |
| 1032 | 1032 | |
| 1033 | 1033 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1034 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1035 | 1034 | struct v4l2_mbus_framefmt *mf; |
| 1036 | 1035 | |
| 1037 | 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 | 1038 | fmt->format = *mf; |
| 1040 | 1039 | mutex_unlock(&ov2659->lock); |
| 1041 | 1040 | return 0; |
| 1042 | −#else | |
| 1043 | − return -EINVAL; | |
| 1044 | −#endif | |
| 1045 | 1041 | } |
| 1046 | 1042 | |
| 1047 | 1043 | mutex_lock(&ov2659->lock); |
| @@ -1113,10 +1109,8 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, · 65 unmodified lines | ||
| 1113 | 1109 | mutex_lock(&ov2659->lock); |
| 1114 | 1110 | |
| 1115 | 1111 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1116 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1117 | 1112 | mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); |
| 1118 | 1113 | *mf = fmt->format; |
| 1119 | −#endif | |
| 1120 | 1114 | } else { |
| 1121 | 1115 | s64 val; |
| 1122 | 1116 | |
| @@ -1306,7 +1300,6 @@ static int ov2659_power_on(struct device *dev) · 183 unmodified lines | ||
| 1306 | 1300 | * V4L2 subdev internal operations |
| 1307 | 1301 | */ |
| 1308 | 1302 | |
| 1309 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1310 | 1303 | static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1311 | 1304 | { |
| 1312 | 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 | 1313 | return 0; |
| 1321 | 1314 | } |
| 1322 | −#endif | |
| 1323 | 1315 | |
| 1324 | 1316 | static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = { |
| 1325 | 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 | 1330 | .set_fmt = ov2659_set_fmt, |
| 1339 | 1331 | }; |
| 1340 | 1332 | |
| 1341 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1342 | 1333 | static const struct v4l2_subdev_ops ov2659_subdev_ops = { |
| 1343 | 1334 | .core = &ov2659_subdev_core_ops, |
| 1344 | 1335 | .video = &ov2659_subdev_video_ops, |
| @@ -1348,7 +1339,6 @@ static const struct v4l2_subdev_ops ov2659_subdev_ops = { · 3 unmodified lines | ||
| 1348 | 1339 | static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = { |
| 1349 | 1340 | .open = ov2659_open, |
| 1350 | 1341 | }; |
| 1351 | −#endif | |
| 1352 | 1342 | |
| 1353 | 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 | 1480 | sd = &ov2659->sd; |
| 1491 | 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 | 1484 | sd->internal_ops = &ov2659_subdev_internal_ops; |
| 1496 | 1485 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
| 1497 | 1486 | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1498 | −#endif | |
| 1499 | 1487 | |
| 1500 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1501 | 1488 | ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1502 | 1489 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1503 | 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 | 1492 | v4l2_ctrl_handler_free(&ov2659->ctrls); |
| 1506 | 1493 | return ret; |
| 1507 | 1494 | } |
| 1508 | −#endif | |
| 1509 | 1495 | |
| 1510 | 1496 | mutex_init(&ov2659->lock); |
| 1511 | 1497 | |
| @@ -91,7 +91,6 @@ struct ov2685 { · 90 unmodified lines | ||
| 91 | 91 | struct gpio_desc *reset_gpio; |
| 92 | 92 | struct regulator_bulk_data supplies[OV2685_NUM_SUPPLIES]; |
| 93 | 93 | |
| 94 | − bool streaming; | |
| 95 | 94 | struct mutex mutex; |
| 96 | 95 | struct v4l2_subdev subdev; |
| 97 | 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 | 513 | mutex_lock(&ov2685->mutex); |
| 515 | 514 | |
| 516 | − on = !!on; | |
| 517 | − if (on == ov2685->streaming) | |
| 518 | − goto unlock_and_return; | |
| 519 | − | |
| 520 | 515 | if (on) { |
| 521 | 516 | ret = pm_runtime_resume_and_get(&ov2685->client->dev); |
| 522 | 517 | if (ret < 0) |
| @@ -539,15 +534,12 @@ static int ov2685_s_stream(struct v4l2_subdev *sd, int on) · 16 unmodified lines | ||
| 539 | 534 | pm_runtime_put(&ov2685->client->dev); |
| 540 | 535 | } |
| 541 | 536 | |
| 542 | − ov2685->streaming = on; | |
| 543 | − | |
| 544 | 537 | unlock_and_return: |
| 545 | 538 | mutex_unlock(&ov2685->mutex); |
| 546 | 539 | |
| 547 | 540 | return ret; |
| 548 | 541 | } |
| 549 | 542 | |
| 550 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 551 | 543 | static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 552 | 544 | { |
| 553 | 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 | 556 | return 0; |
| 565 | 557 | } |
| 566 | −#endif | |
| 567 | 558 | |
| 568 | 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 | 651 | .pad = &ov2685_pad_ops, |
| 661 | 652 | }; |
| 662 | 653 | |
| 663 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 664 | 654 | static const struct v4l2_subdev_internal_ops ov2685_internal_ops = { |
| 665 | 655 | .open = ov2685_open, |
| 666 | 656 | }; |
| 667 | −#endif | |
| 668 | 657 | |
| 669 | 658 | static const struct v4l2_ctrl_ops ov2685_ctrl_ops = { |
| 670 | 659 | .s_ctrl = ov2685_set_ctrl, |
| @@ -833,17 +822,13 @@ static int ov2685_probe(struct i2c_client *client) · 162 unmodified lines | ||
| 833 | 822 | if (ret) |
| 834 | 823 | goto err_power_off; |
| 835 | 824 | |
| 836 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 837 | 825 | ov2685->subdev.internal_ops = &ov2685_internal_ops; |
| 838 | 826 | ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 839 | −#endif | |
| 840 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 841 | 827 | ov2685->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 842 | 828 | ov2685->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 843 | 829 | ret = media_entity_pads_init(&ov2685->subdev.entity, 1, &ov2685->pad); |
| 844 | 830 | if (ret < 0) |
| 845 | 831 | goto err_power_off; |
| 846 | −#endif | |
| 847 | 832 | |
| 848 | 833 | ret = v4l2_async_register_subdev(&ov2685->subdev); |
| 849 | 834 | if (ret) { |
| @@ -858,9 +843,7 @@ static int ov2685_probe(struct i2c_client *client) · 8 unmodified lines | ||
| 858 | 843 | return 0; |
| 859 | 844 | |
| 860 | 845 | err_clean_entity: |
| 861 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 862 | 846 | media_entity_cleanup(&ov2685->subdev.entity); |
| 863 | −#endif | |
| 864 | 847 | err_power_off: |
| 865 | 848 | __ov2685_power_off(ov2685); |
| 866 | 849 | err_free_handler: |
| @@ -877,9 +860,7 @@ static void ov2685_remove(struct i2c_client *client) · 10 unmodified lines | ||
| 877 | 860 | struct ov2685 *ov2685 = to_ov2685(sd); |
| 878 | 861 | |
| 879 | 862 | v4l2_async_unregister_subdev(sd); |
| 880 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 881 | 863 | media_entity_cleanup(&sd->entity); |
| 882 | −#endif | |
| 883 | 864 | v4l2_ctrl_handler_free(&ov2685->ctrl_handler); |
| 884 | 865 | mutex_destroy(&ov2685->mutex); |
| 885 | 866 | |
| @@ -336,12 +336,6 @@ struct ov2740 { · 335 unmodified lines | ||
| 336 | 336 | /* Current mode */ |
| 337 | 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 | 339 | /* NVM data inforamtion */ |
| 346 | 340 | struct nvm_data *nvm; |
| 347 | 341 | |
| @@ -582,7 +576,6 @@ static int ov2740_init_controls(struct ov2740 *ov2740) · 234 unmodified lines | ||
| 582 | 576 | if (ret) |
| 583 | 577 | return ret; |
| 584 | 578 | |
| 585 | − ctrl_hdlr->lock = &ov2740->mutex; | |
| 586 | 579 | cur_mode = ov2740->cur_mode; |
| 587 | 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 | 786 | struct ov2740 *ov2740 = to_ov2740(sd); |
| 794 | 787 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 788 | + struct v4l2_subdev_state *sd_state; | |
| 795 | 789 | int ret = 0; |
| 796 | 790 | |
| 797 | − if (ov2740->streaming == enable) | |
| 798 | − return 0; | |
| 791 | + sd_state = v4l2_subdev_lock_and_get_active_state(&ov2740->sd); | |
| 799 | 792 | |
| 800 | − mutex_lock(&ov2740->mutex); | |
| 801 | 793 | if (enable) { |
| 802 | 794 | ret = pm_runtime_resume_and_get(&client->dev); |
| 803 | − if (ret < 0) { | |
| 804 | − mutex_unlock(&ov2740->mutex); | |
| 805 | − return ret; | |
| 806 | − } | |
| 795 | + if (ret < 0) | |
| 796 | + goto out_unlock; | |
| 807 | 797 | |
| 808 | 798 | ret = ov2740_start_streaming(ov2740); |
| 809 | 799 | if (ret) { |
| @@ -816,44 +806,9 @@ static int ov2740_set_stream(struct v4l2_subdev *sd, int enable) · 6 unmodified lines | ||
| 816 | 806 | pm_runtime_put(&client->dev); |
| 817 | 807 | } |
| 818 | 808 | |
| 819 | − ov2740->streaming = enable; | |
| 820 | − mutex_unlock(&ov2740->mutex); | |
| 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 | − } | |
| 809 | +out_unlock: | |
| 810 | + v4l2_subdev_unlock_state(sd_state); | |
| 854 | 811 | |
| 855 | −exit: | |
| 856 | − mutex_unlock(&ov2740->mutex); | |
| 857 | 812 | return ret; |
| 858 | 813 | } |
| 859 | 814 | |
| @@ -870,48 +825,26 @@ static int ov2740_set_format(struct v4l2_subdev *sd, · 10 unmodified lines | ||
| 870 | 825 | height, fmt->format.width, |
| 871 | 826 | fmt->format.height); |
| 872 | 827 | |
| 873 | − mutex_lock(&ov2740->mutex); | |
| 874 | 828 | ov2740_update_pad_format(mode, &fmt->format); |
| 875 | − if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { | |
| 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); | |
| 829 | + *v4l2_subdev_get_pad_format(sd, sd_state, fmt->pad) = fmt->format; | |
| 905 | 830 | |
| 906 | − mutex_lock(&ov2740->mutex); | |
| 907 | 831 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) |
| 908 | − fmt->format = *v4l2_subdev_get_try_format(&ov2740->sd, | |
| 909 | − sd_state, | |
| 910 | − fmt->pad); | |
| 911 | − else | |
| 912 | − ov2740_update_pad_format(ov2740->cur_mode, &fmt->format); | |
| 832 | + return 0; | |
| 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 | 849 | return 0; |
| 917 | 850 | } |
| @@ -946,14 +879,11 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd, · 28 unmodified lines | ||
| 946 | 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 | 885 | ov2740_update_pad_format(&supported_modes[0], |
| 955 | − v4l2_subdev_get_try_format(sd, fh->state, 0)); | |
| 956 | − mutex_unlock(&ov2740->mutex); | |
| 886 | + v4l2_subdev_get_pad_format(sd, sd_state, 0)); | |
| 957 | 887 | |
| 958 | 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 | 895 | static const struct v4l2_subdev_pad_ops ov2740_pad_ops = { |
| 896 | + .get_fmt = v4l2_subdev_get_fmt, | |
| 966 | 897 | .set_fmt = ov2740_set_format, |
| 967 | − .get_fmt = ov2740_get_format, | |
| 968 | 898 | .enum_mbus_code = ov2740_enum_mbus_code, |
| 969 | 899 | .enum_frame_size = ov2740_enum_frame_size, |
| 900 | + .init_cfg = ov2740_init_cfg, | |
| 970 | 901 | }; |
| 971 | 902 | |
| 972 | 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 | 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 | 912 | static int ov2740_check_hwcfg(struct device *dev) |
| 986 | 913 | { |
| 987 | 914 | struct fwnode_handle *ep; |
| @@ -1004,7 +931,7 @@ static int ov2740_check_hwcfg(struct device *dev) · 16 unmodified lines | ||
| 1004 | 931 | |
| 1005 | 932 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); |
| 1006 | 933 | if (!ep) |
| 1007 | − return -ENXIO; | |
| 934 | + return -EPROBE_DEFER; | |
| 1008 | 935 | |
| 1009 | 936 | ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); |
| 1010 | 937 | fwnode_handle_put(ep); |
| @@ -1047,13 +974,12 @@ check_hwcfg_error: · 36 unmodified lines | ||
| 1047 | 974 | static void ov2740_remove(struct i2c_client *client) |
| 1048 | 975 | { |
| 1049 | 976 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
| 1050 | − struct ov2740 *ov2740 = to_ov2740(sd); | |
| 1051 | 977 | |
| 1052 | 978 | v4l2_async_unregister_subdev(sd); |
| 1053 | 979 | media_entity_cleanup(&sd->entity); |
| 980 | + v4l2_subdev_cleanup(sd); | |
| 1054 | 981 | v4l2_ctrl_handler_free(sd->ctrl_handler); |
| 1055 | 982 | pm_runtime_disable(&client->dev); |
| 1056 | − mutex_destroy(&ov2740->mutex); | |
| 1057 | 983 | } |
| 1058 | 984 | |
| 1059 | 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 | 988 | struct nvm_data *nvm = priv; |
| 1063 | 989 | struct device *dev = regmap_get_device(nvm->regmap); |
| 1064 | 990 | struct ov2740 *ov2740 = to_ov2740(dev_get_drvdata(dev)); |
| 991 | + struct v4l2_subdev_state *sd_state; | |
| 1065 | 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 | 997 | if (nvm->nvm_buffer) { |
| 1070 | 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 | 1011 | pm_runtime_put(dev); |
| 1084 | 1012 | exit: |
| 1085 | − mutex_unlock(&ov2740->mutex); | |
| 1013 | + v4l2_subdev_unlock_state(sd_state); | |
| 1086 | 1014 | return ret; |
| 1087 | 1015 | } |
| 1088 | 1016 | |
| @@ -1153,7 +1081,6 @@ static int ov2740_probe(struct i2c_client *client) · 64 unmodified lines | ||
| 1153 | 1081 | return dev_err_probe(dev, ret, "failed to find sensor\n"); |
| 1154 | 1082 | } |
| 1155 | 1083 | |
| 1156 | − mutex_init(&ov2740->mutex); | |
| 1157 | 1084 | ov2740->cur_mode = &supported_modes[0]; |
| 1158 | 1085 | ret = ov2740_init_controls(ov2740); |
| 1159 | 1086 | if (ret) { |
| @@ -1161,7 +1088,7 @@ static int ov2740_probe(struct i2c_client *client) · 1 unmodified line | ||
| 1161 | 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 | 1092 | ov2740->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1166 | 1093 | ov2740->sd.entity.ops = &ov2740_subdev_entity_ops; |
| 1167 | 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 | 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 | 1112 | ret = v4l2_async_register_subdev_sensor(&ov2740->sd); |
| 1176 | 1113 | if (ret < 0) { |
| 1177 | 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 | 1118 | ret = ov2740_register_nvmem(client, ov2740); |
| 1182 | 1119 | if (ret) |
| 1183 | 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 | 1122 | return 0; |
| 1192 | 1123 | |
| 1124 | +probe_error_v4l2_subdev_cleanup: | |
| 1125 | + v4l2_subdev_cleanup(&ov2740->sd); | |
| 1126 | + | |
| 1193 | 1127 | probe_error_media_entity_cleanup: |
| 1194 | 1128 | media_entity_cleanup(&ov2740->sd.entity); |
| 1129 | + pm_runtime_disable(&client->dev); | |
| 1130 | + pm_runtime_set_suspended(&client->dev); | |
| 1195 | 1131 | |
| 1196 | 1132 | probe_error_v4l2_ctrl_handler_free: |
| 1197 | 1133 | v4l2_ctrl_handler_free(ov2740->sd.ctrl_handler); |
| 1198 | − mutex_destroy(&ov2740->mutex); | |
| 1199 | 1134 | |
| 1200 | 1135 | return ret; |
| 1201 | 1136 | } |
| 1202 | 1137 | |
| 1203 | −static DEFINE_SIMPLE_DEV_PM_OPS(ov2740_pm_ops, ov2740_suspend, ov2740_resume); | |
| 1204 | − | |
| 1205 | 1138 | static const struct acpi_device_id ov2740_acpi_ids[] = { |
| 1206 | 1139 | {"INT3474"}, |
| 1207 | 1140 | {} |
| @@ -1212,7 +1145,6 @@ MODULE_DEVICE_TABLE(acpi, ov2740_acpi_ids); · 4 unmodified lines | ||
| 1212 | 1145 | static struct i2c_driver ov2740_i2c_driver = { |
| 1213 | 1146 | .driver = { |
| 1214 | 1147 | .name = "ov2740", |
| 1215 | − .pm = pm_sleep_ptr(&ov2740_pm_ops), | |
| 1216 | 1148 | .acpi_match_table = ov2740_acpi_ids, |
| 1217 | 1149 | }, |
| 1218 | 1150 | .probe = ov2740_probe, |
| @@ -99,8 +99,7 @@ struct ov4689 { · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 100 | u32 clock_rate; |
| 101 | 101 | |
| 102 | − struct mutex mutex; /* lock to protect streaming, ctrls and cur_mode */ | |
| 103 | − bool streaming; | |
| 102 | + struct mutex mutex; /* lock to protect ctrls and cur_mode */ | |
| 104 | 103 | struct v4l2_ctrl_handler ctrl_handler; |
| 105 | 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 | 468 | mutex_lock(&ov4689->mutex); |
| 470 | 469 | |
| 471 | − on = !!on; | |
| 472 | − if (on == ov4689->streaming) | |
| 473 | − goto unlock_and_return; | |
| 474 | − | |
| 475 | 470 | if (on) { |
| 476 | 471 | ret = pm_runtime_resume_and_get(&client->dev); |
| 477 | 472 | if (ret < 0) |
| @@ -504,8 +499,6 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) · 26 unmodified lines | ||
| 504 | 499 | pm_runtime_put(&client->dev); |
| 505 | 500 | } |
| 506 | 501 | |
| 507 | − ov4689->streaming = on; | |
| 508 | − | |
| 509 | 502 | unlock_and_return: |
| 510 | 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 | 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 | 2863 | static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) |
| 2854 | 2864 | { |
| 2855 | 2865 | const struct ov5640_mode_info *mode = sensor->current_mode; |
| 2856 | 2866 | enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate; |
| 2857 | 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 | 2869 | s32 exposure_val, exposure_max; |
| 2860 | 2870 | unsigned int hblank; |
| 2861 | 2871 | unsigned int i = 0; |
| @@ -2874,6 +2884,8 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) · 12 unmodified lines | ||
| 2874 | 2884 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, |
| 2875 | 2885 | ov5640_calc_pixel_rate(sensor)); |
| 2876 | 2886 | |
| 2887 | + __v4l2_ctrl_vblank_update(sensor, timings->vblank_def); | |
| 2888 | + | |
| 2877 | 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 | 2928 | __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, pixel_rate); |
| 2917 | 2929 | __v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, i); |
| 2918 | 2930 | |
| 2919 | − timings = ov5640_timings(sensor, mode); | |
| 2920 | 2931 | hblank = timings->htot - mode->width; |
| 2921 | 2932 | __v4l2_ctrl_modify_range(sensor->ctrls.hblank, |
| 2922 | 2933 | hblank, hblank, 1, hblank); |
| 2923 | 2934 | |
| 2924 | 2935 | vblank = timings->vblank_def; |
| 2925 | − __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK, | |
| 2926 | − OV5640_MAX_VTS - mode->height, 1, vblank); | |
| 2927 | − __v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank); | |
| 2936 | + __v4l2_ctrl_vblank_update(sensor, vblank); | |
| 2928 | 2937 | |
| 2929 | 2938 | exposure_max = timings->crop.height + vblank - 4; |
| 2930 | 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 | 3928 | ret = ov5640_sensor_resume(dev); |
| 3920 | 3929 | if (ret) { |
| 3921 | 3930 | dev_err(dev, "failed to power on\n"); |
| 3922 | − goto entity_cleanup; | |
| 3931 | + goto free_ctrls; | |
| 3923 | 3932 | } |
| 3924 | 3933 | |
| 3925 | 3934 | pm_runtime_set_active(dev); |
| @@ -3944,8 +3953,9 @@ static int ov5640_probe(struct i2c_client *client) · 18 unmodified lines | ||
| 3944 | 3953 | err_pm_runtime: |
| 3945 | 3954 | pm_runtime_put_noidle(dev); |
| 3946 | 3955 | pm_runtime_disable(dev); |
| 3947 | − v4l2_ctrl_handler_free(&sensor->ctrls.handler); | |
| 3948 | 3956 | ov5640_sensor_suspend(dev); |
| 3957 | +free_ctrls: | |
| 3958 | + v4l2_ctrl_handler_free(&sensor->ctrls.handler); | |
| 3949 | 3959 | entity_cleanup: |
| 3950 | 3960 | media_entity_cleanup(&sensor->sd.entity); |
| 3951 | 3961 | mutex_destroy(&sensor->lock); |
| @@ -109,7 +109,6 @@ struct ov5647 { · 108 unmodified lines | ||
| 109 | 109 | struct v4l2_ctrl *hblank; |
| 110 | 110 | struct v4l2_ctrl *vblank; |
| 111 | 111 | struct v4l2_ctrl *exposure; |
| 112 | − bool streaming; | |
| 113 | 112 | }; |
| 114 | 113 | |
| 115 | 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 | 897 | int ret; |
| 899 | 898 | |
| 900 | 899 | mutex_lock(&sensor->lock); |
| 901 | − if (sensor->streaming == enable) { | |
| 902 | − mutex_unlock(&sensor->lock); | |
| 903 | − return 0; | |
| 904 | − } | |
| 905 | 900 | |
| 906 | 901 | if (enable) { |
| 907 | 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 | 917 | pm_runtime_put(&client->dev); |
| 923 | 918 | } |
| 924 | 919 | |
| 925 | − sensor->streaming = enable; | |
| 926 | 920 | mutex_unlock(&sensor->lock); |
| 927 | 921 | |
| 928 | 922 | return 0; |
| @@ -1882,8 +1882,6 @@ struct ov5670 { · 1881 unmodified lines | ||
| 1882 | 1882 | /* To serialize asynchronus callbacks */ |
| 1883 | 1883 | struct mutex mutex; |
| 1884 | 1884 | |
| 1885 | − /* Streaming on/off */ | |
| 1886 | − bool streaming; | |
| 1887 | 1885 | /* True if the device has been identified */ |
| 1888 | 1886 | bool identified; |
| 1889 | 1887 | }; |
| @@ -2471,8 +2469,6 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) · 581 unmodified lines | ||
| 2471 | 2469 | int ret = 0; |
| 2472 | 2470 | |
| 2473 | 2471 | mutex_lock(&ov5670->mutex); |
| 2474 | − if (ov5670->streaming == enable) | |
| 2475 | − goto unlock_and_return; | |
| 2476 | 2472 | |
| 2477 | 2473 | if (enable) { |
| 2478 | 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 | 2482 | ret = ov5670_stop_streaming(ov5670); |
| 2487 | 2483 | pm_runtime_put(&client->dev); |
| 2488 | 2484 | } |
| 2489 | − ov5670->streaming = enable; | |
| 2490 | 2485 | goto unlock_and_return; |
| 2491 | 2486 | |
| 2492 | 2487 | error: |
| @@ -2541,34 +2536,6 @@ static int __maybe_unused ov5670_runtime_suspend(struct device *dev) · 48 unmodified lines | ||
| 2541 | 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 | 2539 | static const struct v4l2_subdev_core_ops ov5670_core_ops = { |
| 2573 | 2540 | .log_status = v4l2_ctrl_subdev_log_status, |
| 2574 | 2541 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
| @@ -2771,8 +2738,6 @@ static int ov5670_probe(struct i2c_client *client) · 196 unmodified lines | ||
| 2771 | 2738 | goto error_handler_free; |
| 2772 | 2739 | } |
| 2773 | 2740 | |
| 2774 | − ov5670->streaming = false; | |
| 2775 | − | |
| 2776 | 2741 | /* Set the device's state to active if it's in D0 state. */ |
| 2777 | 2742 | if (full_power) |
| 2778 | 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 | 2794 | static const struct dev_pm_ops ov5670_pm_ops = { |
| 2830 | − SET_SYSTEM_SLEEP_PM_OPS(ov5670_suspend, ov5670_resume) | |
| 2831 | 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 | 513 | /* To serialize asynchronus callbacks */ |
| 514 | 514 | struct mutex mutex; |
| 515 | 515 | |
| 516 | − /* Streaming on/off */ | |
| 517 | − bool streaming; | |
| 518 | − | |
| 519 | 516 | /* True if the device has been identified */ |
| 520 | 517 | bool identified; |
| 521 | 518 | }; |
| @@ -949,9 +946,6 @@ static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) · 427 unmodified lines | ||
| 949 | 946 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 950 | 947 | int ret = 0; |
| 951 | 948 | |
| 952 | − if (ov5675->streaming == enable) | |
| 953 | − return 0; | |
| 954 | − | |
| 955 | 949 | mutex_lock(&ov5675->mutex); |
| 956 | 950 | if (enable) { |
| 957 | 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 | 965 | pm_runtime_put(&client->dev); |
| 972 | 966 | } |
| 973 | 967 | |
| 974 | − ov5675->streaming = enable; | |
| 975 | 968 | mutex_unlock(&ov5675->mutex); |
| 976 | 969 | |
| 977 | 970 | return ret; |
| @@ -1027,42 +1020,6 @@ static int ov5675_power_on(struct device *dev) · 49 unmodified lines | ||
| 1027 | 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 | 1023 | static int ov5675_set_format(struct v4l2_subdev *sd, |
| 1067 | 1024 | struct v4l2_subdev_state *sd_state, |
| 1068 | 1025 | struct v4l2_subdev_format *fmt) |
| @@ -1409,7 +1366,6 @@ probe_power_off: · 340 unmodified lines | ||
| 1409 | 1366 | } |
| 1410 | 1367 | |
| 1411 | 1368 | static const struct dev_pm_ops ov5675_pm_ops = { |
| 1412 | − SET_SYSTEM_SLEEP_PM_OPS(ov5675_suspend, ov5675_resume) | |
| 1413 | 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 | 154 | unsigned int inc_y_odd; |
| 155 | 155 | unsigned int vts; |
| 156 | 156 | } mode; |
| 157 | − bool streaming; | |
| 158 | 157 | |
| 159 | 158 | struct v4l2_subdev sd; |
| 160 | 159 | struct media_pad pad; |
| @@ -975,9 +974,9 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) · 814 unmodified lines | ||
| 975 | 974 | int ret; |
| 976 | 975 | |
| 977 | 976 | if (enable) { |
| 978 | − ret = pm_runtime_get_sync(ov5693->dev); | |
| 979 | − if (ret < 0) | |
| 980 | − goto err_power_down; | |
| 977 | + ret = pm_runtime_resume_and_get(ov5693->dev); | |
| 978 | + if (ret) | |
| 979 | + return ret; | |
| 981 | 980 | |
| 982 | 981 | mutex_lock(&ov5693->lock); |
| 983 | 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 | 995 | if (ret) |
| 997 | 996 | goto err_power_down; |
| 998 | 997 | |
| 999 | − ov5693->streaming = !!enable; | |
| 1000 | − | |
| 1001 | 998 | if (!enable) |
| 1002 | 999 | pm_runtime_put(ov5693->dev); |
| 1003 | 1000 | |
| @@ -108,7 +108,6 @@ struct ov5695 { · 107 unmodified lines | ||
| 108 | 108 | struct v4l2_ctrl *vblank; |
| 109 | 109 | struct v4l2_ctrl *test_pattern; |
| 110 | 110 | struct mutex mutex; |
| 111 | − bool streaming; | |
| 112 | 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 | 820 | fmt->format.height = mode->height; |
| 822 | 821 | fmt->format.field = V4L2_FIELD_NONE; |
| 823 | 822 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 824 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 825 | 823 | *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; |
| 826 | −#endif | |
| 827 | 824 | } else { |
| 828 | 825 | ov5695->cur_mode = mode; |
| 829 | 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 | 847 | mutex_lock(&ov5695->mutex); |
| 851 | 848 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 852 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 853 | 849 | fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, |
| 854 | 850 | fmt->pad); |
| 855 | −#else | |
| 856 | − mutex_unlock(&ov5695->mutex); | |
| 857 | − return -EINVAL; | |
| 858 | −#endif | |
| 859 | 851 | } else { |
| 860 | 852 | fmt->format.width = mode->width; |
| 861 | 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 | 934 | int ret = 0; |
| 943 | 935 | |
| 944 | 936 | mutex_lock(&ov5695->mutex); |
| 945 | − on = !!on; | |
| 946 | − if (on == ov5695->streaming) | |
| 947 | − goto unlock_and_return; | |
| 948 | 937 | |
| 949 | 938 | if (on) { |
| 950 | 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 | 951 | pm_runtime_put(&client->dev); |
| 963 | 952 | } |
| 964 | 953 | |
| 965 | − ov5695->streaming = on; | |
| 966 | − | |
| 967 | 954 | unlock_and_return: |
| 968 | 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 | 1035 | return 0; |
| 1049 | 1036 | } |
| 1050 | 1037 | |
| 1051 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1052 | 1038 | static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1053 | 1039 | { |
| 1054 | 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 | 1055 | return 0; |
| 1070 | 1056 | } |
| 1071 | −#endif | |
| 1072 | 1057 | |
| 1073 | 1058 | static const struct dev_pm_ops ov5695_pm_ops = { |
| 1074 | 1059 | SET_RUNTIME_PM_OPS(ov5695_runtime_suspend, |
| 1075 | 1060 | ov5695_runtime_resume, NULL) |
| 1076 | 1061 | }; |
| 1077 | 1062 | |
| 1078 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1079 | 1063 | static const struct v4l2_subdev_internal_ops ov5695_internal_ops = { |
| 1080 | 1064 | .open = ov5695_open, |
| 1081 | 1065 | }; |
| 1082 | −#endif | |
| 1083 | 1066 | |
| 1084 | 1067 | static const struct v4l2_subdev_video_ops ov5695_video_ops = { |
| 1085 | 1068 | .s_stream = ov5695_s_stream, |
| @@ -1322,17 +1305,13 @@ static int ov5695_probe(struct i2c_client *client) · 236 unmodified lines | ||
| 1322 | 1305 | if (ret) |
| 1323 | 1306 | goto err_power_off; |
| 1324 | 1307 | |
| 1325 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1326 | 1308 | sd->internal_ops = &ov5695_internal_ops; |
| 1327 | 1309 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
| 1328 | −#endif | |
| 1329 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1330 | 1310 | ov5695->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1331 | 1311 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1332 | 1312 | ret = media_entity_pads_init(&sd->entity, 1, &ov5695->pad); |
| 1333 | 1313 | if (ret < 0) |
| 1334 | 1314 | goto err_power_off; |
| 1335 | −#endif | |
| 1336 | 1315 | |
| 1337 | 1316 | ret = v4l2_async_register_subdev_sensor(sd); |
| 1338 | 1317 | if (ret) { |
| @@ -1347,9 +1326,7 @@ static int ov5695_probe(struct i2c_client *client) · 8 unmodified lines | ||
| 1347 | 1326 | return 0; |
| 1348 | 1327 | |
| 1349 | 1328 | err_clean_entity: |
| 1350 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1351 | 1329 | media_entity_cleanup(&sd->entity); |
| 1352 | −#endif | |
| 1353 | 1330 | err_power_off: |
| 1354 | 1331 | __ov5695_power_off(ov5695); |
| 1355 | 1332 | err_free_handler: |
| @@ -1366,9 +1343,7 @@ static void ov5695_remove(struct i2c_client *client) · 10 unmodified lines | ||
| 1366 | 1343 | struct ov5695 *ov5695 = to_ov5695(sd); |
| 1367 | 1344 | |
| 1368 | 1345 | v4l2_async_unregister_subdev(sd); |
| 1369 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1370 | 1346 | media_entity_cleanup(&sd->entity); |
| 1371 | −#endif | |
| 1372 | 1347 | v4l2_ctrl_handler_free(&ov5695->ctrl_handler); |
| 1373 | 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 | 1340 | mutex_lock(&ov7251->lock); |
| 1341 | 1341 | |
| 1342 | 1342 | if (enable) { |
| 1343 | − ret = pm_runtime_get_sync(ov7251->dev); | |
| 1344 | − if (ret < 0) | |
| 1345 | − goto err_power_down; | |
| 1343 | + ret = pm_runtime_resume_and_get(ov7251->dev); | |
| 1344 | + if (ret) { | |
| 1345 | + mutex_unlock(&ov7251->lock); | |
| 1346 | + return ret; | |
| 1347 | + } | |
| 1346 | 1348 | |
| 1347 | 1349 | ret = ov7251_pll_configure(ov7251); |
| 1348 | 1350 | if (ret) { |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | */ |
| 11 | 11 | #include <linux/clk.h> |
| 12 | 12 | #include <linux/init.h> |
| 13 | +#include <linux/mod_devicetable.h> | |
| 13 | 14 | #include <linux/module.h> |
| 14 | 15 | #include <linux/slab.h> |
| 15 | 16 | #include <linux/i2c.h> |
| @@ -186,11 +187,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); · 170 unmodified lines | ||
| 186 | 187 | #define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ |
| 187 | 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 | 190 | struct ov7670_win_size { |
| 195 | 191 | int width; |
| 196 | 192 | int height; |
| @@ -217,9 +213,7 @@ struct ov7670_devtype { · 20 unmodified lines | ||
| 217 | 213 | struct ov7670_format_struct; /* coming later */ |
| 218 | 214 | struct ov7670_info { |
| 219 | 215 | struct v4l2_subdev sd; |
| 220 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 221 | 216 | struct media_pad pad; |
| 222 | −#endif | |
| 223 | 217 | struct v4l2_ctrl_handler hdl; |
| 224 | 218 | struct { |
| 225 | 219 | /* gain cluster */ |
| @@ -1108,9 +1102,7 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, · 882 unmodified lines | ||
| 1108 | 1102 | struct v4l2_subdev_format *format) |
| 1109 | 1103 | { |
| 1110 | 1104 | struct ov7670_info *info = to_state(sd); |
| 1111 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1112 | 1105 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 1113 | −#endif | |
| 1114 | 1106 | int ret; |
| 1115 | 1107 | |
| 1116 | 1108 | if (format->pad) |
| @@ -1120,11 +1112,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, · 3 unmodified lines | ||
| 1120 | 1112 | ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); |
| 1121 | 1113 | if (ret) |
| 1122 | 1114 | return ret; |
| 1123 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1124 | 1115 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, |
| 1125 | 1116 | format->pad); |
| 1126 | 1117 | *mbus_fmt = format->format; |
| 1127 | −#endif | |
| 1128 | 1118 | return 0; |
| 1129 | 1119 | } |
| 1130 | 1120 | |
| @@ -1148,18 +1138,12 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd, · 17 unmodified lines | ||
| 1148 | 1138 | struct v4l2_subdev_format *format) |
| 1149 | 1139 | { |
| 1150 | 1140 | struct ov7670_info *info = to_state(sd); |
| 1151 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1152 | 1141 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 1153 | −#endif | |
| 1154 | 1142 | |
| 1155 | 1143 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 1156 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1157 | 1144 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 1158 | 1145 | format->format = *mbus_fmt; |
| 1159 | 1146 | return 0; |
| 1160 | −#else | |
| 1161 | − return -EINVAL; | |
| 1162 | −#endif | |
| 1163 | 1147 | } else { |
| 1164 | 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 | 1704 | format->field = V4L2_FIELD_NONE; |
| 1721 | 1705 | } |
| 1722 | 1706 | |
| 1723 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1724 | 1707 | static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 1725 | 1708 | { |
| 1726 | 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 | 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 | 1748 | .pad = &ov7670_pad_ops, |
| 1767 | 1749 | }; |
| 1768 | 1750 | |
| 1769 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1770 | 1751 | static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { |
| 1771 | 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 | 1757 | static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info) |
| 1793 | 1758 | { |
| 1794 | 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 | 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 | 1817 | struct v4l2_fract tpf; |
| 1854 | 1818 | struct v4l2_subdev *sd; |
| 1855 | 1819 | struct ov7670_info *info; |
| @@ -1861,10 +1825,8 @@ static int ov7670_probe(struct i2c_client *client) · 5 unmodified lines | ||
| 1861 | 1825 | sd = &info->sd; |
| 1862 | 1826 | v4l2_i2c_subdev_init(sd, client, &ov7670_ops); |
| 1863 | 1827 | |
| 1864 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1865 | 1828 | sd->internal_ops = &ov7670_subdev_internal_ops; |
| 1866 | 1829 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1867 | −#endif | |
| 1868 | 1830 | |
| 1869 | 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 | 1885 | v4l_info(client, "chip found @ 0x%02x (%s)\n", |
| 1924 | 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 | 1889 | info->fmt = &ov7670_formats[0]; |
| 1928 | 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 | 1939 | V4L2_EXPOSURE_MANUAL, false); |
| 1978 | 1940 | v4l2_ctrl_cluster(2, &info->saturation); |
| 1979 | 1941 | |
| 1980 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1981 | 1942 | info->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1982 | 1943 | info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1983 | 1944 | ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); |
| 1984 | 1945 | if (ret < 0) |
| 1985 | 1946 | goto hdl_free; |
| 1986 | −#endif | |
| 1987 | 1947 | |
| 1988 | 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 | 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 | 1990 | static const struct i2c_device_id ov7670_id[] = { |
| 2017 | − { "ov7670", MODEL_OV7670 }, | |
| 2018 | − { "ov7675", MODEL_OV7675 }, | |
| 2019 | − { } | |
| 1991 | + { "ov7670", (kernel_ulong_t)&ov7670_devdata }, | |
| 1992 | + { "ov7675", (kernel_ulong_t)&ov7675_devdata }, | |
| 1993 | + { /* sentinel */ } | |
| 2020 | 1994 | }; |
| 2021 | 1995 | MODULE_DEVICE_TABLE(i2c, ov7670_id); |
| 2022 | 1996 | |
| 2023 | −#if IS_ENABLED(CONFIG_OF) | |
| 2024 | 1997 | static const struct of_device_id ov7670_of_match[] = { |
| 2025 | − { .compatible = "ovti,ov7670", }, | |
| 2026 | − { /* sentinel */ }, | |
| 1998 | + { .compatible = "ovti,ov7670", &ov7670_devdata }, | |
| 1999 | + { /* sentinel */ } | |
| 2027 | 2000 | }; |
| 2028 | 2001 | MODULE_DEVICE_TABLE(of, ov7670_of_match); |
| 2029 | −#endif | |
| 2030 | 2002 | |
| 2031 | 2003 | static struct i2c_driver ov7670_driver = { |
| 2032 | 2004 | .driver = { |
| 2033 | 2005 | .name = "ov7670", |
| 2034 | − .of_match_table = of_match_ptr(ov7670_of_match), | |
| 2006 | + .of_match_table = ov7670_of_match, | |
| 2035 | 2007 | }, |
| 2036 | 2008 | .probe = ov7670_probe, |
| 2037 | 2009 | .remove = ov7670_remove, |
| @@ -433,9 +433,7 @@ struct ov772x_priv { · 432 unmodified lines | ||
| 433 | 433 | struct mutex lock; |
| 434 | 434 | int power_count; |
| 435 | 435 | int streaming; |
| 436 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 437 | 436 | struct media_pad pad; |
| 438 | −#endif | |
| 439 | 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 | 1486 | if (ret < 0) |
| 1489 | 1487 | goto error_gpio_put; |
| 1490 | 1488 | |
| 1491 | −#ifdef CONFIG_MEDIA_CONTROLLER | |
| 1492 | 1489 | priv->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1493 | 1490 | priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1494 | 1491 | ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); |
| 1495 | 1492 | if (ret < 0) |
| 1496 | 1493 | goto error_gpio_put; |
| 1497 | −#endif | |
| 1498 | 1494 | |
| 1499 | 1495 | priv->cfmt = &ov772x_cfmts[0]; |
| 1500 | 1496 | priv->win = &ov772x_win_sizes[0]; |
| @@ -83,9 +83,7 @@ · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | struct ov7740 { |
| 85 | 85 | struct v4l2_subdev subdev; |
| 86 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 87 | 86 | struct media_pad pad; |
| 88 | −#endif | |
| 89 | 87 | struct v4l2_mbus_framefmt format; |
| 90 | 88 | const struct ov7740_pixfmt *fmt; /* Current format */ |
| 91 | 89 | const struct ov7740_framesize *frmsize; |
| @@ -120,7 +118,6 @@ struct ov7740 { · 28 unmodified lines | ||
| 120 | 118 | struct v4l2_ctrl *contrast; |
| 121 | 119 | |
| 122 | 120 | struct mutex mutex; /* To serialize asynchronus callbacks */ |
| 123 | − bool streaming; /* Streaming on/off */ | |
| 124 | 121 | |
| 125 | 122 | struct gpio_desc *resetb_gpio; |
| 126 | 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 | 615 | int ret = 0; |
| 619 | 616 | |
| 620 | 617 | mutex_lock(&ov7740->mutex); |
| 621 | − if (ov7740->streaming == enable) { | |
| 622 | − mutex_unlock(&ov7740->mutex); | |
| 623 | − return 0; | |
| 624 | − } | |
| 625 | 618 | |
| 626 | 619 | if (enable) { |
| 627 | 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 | 628 | pm_runtime_put(&client->dev); |
| 636 | 629 | } |
| 637 | 630 | |
| 638 | − ov7740->streaming = enable; | |
| 639 | − | |
| 640 | 631 | mutex_unlock(&ov7740->mutex); |
| 641 | 632 | return ret; |
| 642 | 633 | |
| @@ -807,9 +798,7 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd, · 164 unmodified lines | ||
| 807 | 798 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); |
| 808 | 799 | const struct ov7740_pixfmt *ovfmt; |
| 809 | 800 | const struct ov7740_framesize *fsize; |
| 810 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 811 | 801 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 812 | −#endif | |
| 813 | 802 | int ret; |
| 814 | 803 | |
| 815 | 804 | mutex_lock(&ov7740->mutex); |
| @@ -822,11 +811,10 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd, · 6 unmodified lines | ||
| 822 | 811 | ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL); |
| 823 | 812 | if (ret) |
| 824 | 813 | goto error; |
| 825 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 814 | + | |
| 826 | 815 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, |
| 827 | 816 | format->pad); |
| 828 | 817 | *mbus_fmt = format->format; |
| 829 | −#endif | |
| 830 | 818 | mutex_unlock(&ov7740->mutex); |
| 831 | 819 | return 0; |
| 832 | 820 | } |
| @@ -851,26 +839,18 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd, · 18 unmodified lines | ||
| 851 | 839 | struct v4l2_subdev_format *format) |
| 852 | 840 | { |
| 853 | 841 | struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); |
| 854 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 855 | 842 | struct v4l2_mbus_framefmt *mbus_fmt; |
| 856 | −#endif | |
| 857 | − int ret = 0; | |
| 858 | 843 | |
| 859 | 844 | mutex_lock(&ov7740->mutex); |
| 860 | 845 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| 861 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 862 | 846 | mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); |
| 863 | 847 | format->format = *mbus_fmt; |
| 864 | − ret = 0; | |
| 865 | −#else | |
| 866 | − ret = -EINVAL; | |
| 867 | −#endif | |
| 868 | 848 | } else { |
| 869 | 849 | format->format = ov7740->format; |
| 870 | 850 | } |
| 871 | 851 | mutex_unlock(&ov7740->mutex); |
| 872 | 852 | |
| 873 | − return ret; | |
| 853 | + return 0; | |
| 874 | 854 | } |
| 875 | 855 | |
| 876 | 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 | 879 | format->field = V4L2_FIELD_NONE; |
| 900 | 880 | } |
| 901 | 881 | |
| 902 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 903 | 882 | static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 904 | 883 | { |
| 905 | 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 | 895 | static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = { |
| 917 | 896 | .open = ov7740_open, |
| 918 | 897 | }; |
| 919 | −#endif | |
| 920 | 898 | |
| 921 | 899 | static int ov7740_probe_dt(struct i2c_client *client, |
| 922 | 900 | struct ov7740 *ov7740) |
| @@ -1094,18 +1072,14 @@ static int ov7740_probe(struct i2c_client *client) · 171 unmodified lines | ||
| 1094 | 1072 | sd = &ov7740->subdev; |
| 1095 | 1073 | v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops); |
| 1096 | 1074 | |
| 1097 | −#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API | |
| 1098 | 1075 | sd->internal_ops = &ov7740_subdev_internal_ops; |
| 1099 | 1076 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| 1100 | −#endif | |
| 1101 | 1077 | |
| 1102 | −#if defined(CONFIG_MEDIA_CONTROLLER) | |
| 1103 | 1078 | ov7740->pad.flags = MEDIA_PAD_FL_SOURCE; |
| 1104 | 1079 | sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; |
| 1105 | 1080 | ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad); |
| 1106 | 1081 | if (ret) |
| 1107 | 1082 | return ret; |
| 1108 | −#endif | |
| 1109 | 1083 | |
| 1110 | 1084 | ret = ov7740_set_power(ov7740, 1); |
| 1111 | 1085 | if (ret) |
| @@ -1438,9 +1438,6 @@ struct ov8856 { · 1437 unmodified lines | ||
| 1438 | 1438 | /* To serialize asynchronus callbacks */ |
| 1439 | 1439 | struct mutex mutex; |
| 1440 | 1440 | |
| 1441 | − /* Streaming on/off */ | |
| 1442 | − bool streaming; | |
| 1443 | − | |
| 1444 | 1441 | /* lanes index */ |
| 1445 | 1442 | u8 nlanes; |
| 1446 | 1443 | |
| @@ -2042,9 +2039,6 @@ static int ov8856_set_stream(struct v4l2_subdev *sd, int enable) · 595 unmodified lines | ||
| 2042 | 2039 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 2043 | 2040 | int ret = 0; |
| 2044 | 2041 | |
| 2045 | − if (ov8856->streaming == enable) | |
| 2046 | − return 0; | |
| 2047 | − | |
| 2048 | 2042 | mutex_lock(&ov8856->mutex); |
| 2049 | 2043 | if (enable) { |
| 2050 | 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 | 2058 | pm_runtime_put(&client->dev); |
| 2065 | 2059 | } |
| 2066 | 2060 | |
| 2067 | − ov8856->streaming = enable; | |
| 2068 | 2061 | mutex_unlock(&ov8856->mutex); |
| 2069 | 2062 | |
| 2070 | 2063 | return ret; |
| @@ -2125,45 +2118,6 @@ static int ov8856_power_off(struct device *dev) · 54 unmodified lines | ||
| 2125 | 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 | 2121 | static int ov8856_set_format(struct v4l2_subdev *sd, |
| 2168 | 2122 | struct v4l2_subdev_state *sd_state, |
| 2169 | 2123 | struct v4l2_subdev_format *fmt) |
| @@ -2501,7 +2455,6 @@ probe_power_off: · 331 unmodified lines | ||
| 2501 | 2455 | } |
| 2502 | 2456 | |
| 2503 | 2457 | static const struct dev_pm_ops ov8856_pm_ops = { |
| 2504 | − SET_SYSTEM_SLEEP_PM_OPS(ov8856_suspend, ov8856_resume) | |
| 2505 | 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 | 165 | * @cur_mode: Pointer to current selected sensor mode |
| 166 | 166 | * @code: Mbus code currently selected |
| 167 | 167 | * @mutex: Mutex for serializing sensor controls |
| 168 | − * @streaming: Flag indicating streaming state | |
| 169 | 168 | */ |
| 170 | 169 | struct ov9282 { |
| 171 | 170 | struct device *dev; |
| @@ -188,7 +187,6 @@ struct ov9282 { · 16 unmodified lines | ||
| 188 | 187 | const struct ov9282_mode *cur_mode; |
| 189 | 188 | u32 code; |
| 190 | 189 | struct mutex mutex; |
| 191 | − bool streaming; | |
| 192 | 190 | }; |
| 193 | 191 | |
| 194 | 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 | 1036 | mutex_lock(&ov9282->mutex); |
| 1039 | 1037 | |
| 1040 | − if (ov9282->streaming == enable) { | |
| 1041 | − mutex_unlock(&ov9282->mutex); | |
| 1042 | − return 0; | |
| 1043 | − } | |
| 1044 | − | |
| 1045 | 1038 | if (enable) { |
| 1046 | 1039 | ret = pm_runtime_resume_and_get(ov9282->dev); |
| 1047 | 1040 | if (ret) |
| @@ -1055,8 +1048,6 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable) · 7 unmodified lines | ||
| 1055 | 1048 | pm_runtime_put(ov9282->dev); |
| 1056 | 1049 | } |
| 1057 | 1050 | |
| 1058 | − ov9282->streaming = enable; | |
| 1059 | − | |
| 1060 | 1051 | mutex_unlock(&ov9282->mutex); |
| 1061 | 1052 | |
| 1062 | 1053 | return 0; |
| @@ -337,9 +337,6 @@ struct ov9734 { · 336 unmodified lines | ||
| 337 | 337 | |
| 338 | 338 | /* To serialize asynchronus callbacks */ |
| 339 | 339 | struct mutex mutex; |
| 340 | − | |
| 341 | − /* Streaming on/off */ | |
| 342 | − bool streaming; | |
| 343 | 340 | }; |
| 344 | 341 | |
| 345 | 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 | 657 | int ret = 0; |
| 661 | 658 | |
| 662 | 659 | mutex_lock(&ov9734->mutex); |
| 663 | − if (ov9734->streaming == enable) { | |
| 664 | − mutex_unlock(&ov9734->mutex); | |
| 665 | − return 0; | |
| 666 | − } | |
| 667 | 660 | |
| 668 | 661 | if (enable) { |
| 669 | 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 | 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 | 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 | 681 | return ret; |
| 727 | 682 | } |
| 728 | 683 | |
| @@ -1011,10 +966,6 @@ probe_error_v4l2_ctrl_handler_free: · 282 unmodified lines | ||
| 1011 | 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 | 969 | static const struct acpi_device_id ov9734_acpi_ids[] = { |
| 1019 | 970 | { "OVTI9734", }, |
| 1020 | 971 | {} |
| @@ -1025,7 +976,6 @@ MODULE_DEVICE_TABLE(acpi, ov9734_acpi_ids); · 4 unmodified lines | ||
| 1025 | 976 | static struct i2c_driver ov9734_i2c_driver = { |
| 1026 | 977 | .driver = { |
| 1027 | 978 | .name = "ov9734", |
| 1028 | − .pm = &ov9734_pm_ops, | |
| 1029 | 979 | .acpi_match_table = ov9734_acpi_ids, |
| 1030 | 980 | }, |
| 1031 | 981 | .probe = ov9734_probe, |
| @@ -625,8 +625,7 @@ error_free_ctrls: · 624 unmodified lines | ||
| 625 | 625 | v4l2_ctrl_handler_free(&dev->ctrls); |
| 626 | 626 | error: |
| 627 | 627 | media_entity_cleanup(&dev->sd.entity); |
| 628 | − if (dev->sensor) | |
| 629 | − i2c_unregister_device(dev->sensor); | |
| 628 | + i2c_unregister_device(dev->sensor); | |
| 630 | 629 | |
| 631 | 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 | 1170 | if (ret) |
| 1171 | 1171 | return ret; |
| 1172 | 1172 | |
| 1173 | − ret = pm_runtime_get_sync(&client->dev); | |
| 1174 | − if (ret < 0) { | |
| 1175 | − pm_runtime_put_autosuspend(&client->dev); | |
| 1173 | + ret = pm_runtime_resume_and_get(&client->dev); | |
| 1174 | + if (ret) | |
| 1176 | 1175 | return ret; |
| 1177 | − } | |
| 1178 | − | |
| 1179 | − /* pm_runtime_get_sync() can return 1 as a valid return code */ | |
| 1180 | − ret = 0; | |
| 1181 | 1176 | |
| 1182 | 1177 | vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL, |
| 1183 | 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 | 784 | sink_fmt = v4l2_subdev_get_pad_format(sd, sd_state, TC358746_SINK); |
| 785 | 785 | |
| 786 | 786 | fmt = tc358746_get_format_by_code(format->pad, format->format.code); |
| 787 | − if (IS_ERR(fmt)) | |
| 787 | + if (IS_ERR(fmt)) { | |
| 788 | 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 | 794 | format->format.code = fmt->code; |
| 791 | 795 | format->format.field = V4L2_FIELD_NONE; |
| @@ -16,23 +16,24 @@ · 15 unmodified lines | ||
| 16 | 16 | * Prabhakar Lad <prabhakar.lad@ti.com> |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | −#include <linux/i2c.h> | |
| 20 | −#include <linux/slab.h> | |
| 21 | 19 | #include <linux/delay.h> |
| 22 | −#include <linux/videodev2.h> | |
| 20 | +#include <linux/i2c.h> | |
| 21 | +#include <linux/mod_devicetable.h> | |
| 23 | 22 | #include <linux/module.h> |
| 24 | −#include <linux/v4l2-mediabus.h> | |
| 25 | 23 | #include <linux/of.h> |
| 26 | 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 | 31 | #include <media/v4l2-async.h> |
| 29 | −#include <media/v4l2-device.h> | |
| 30 | 32 | #include <media/v4l2-common.h> |
| 31 | −#include <media/v4l2-mediabus.h> | |
| 32 | −#include <media/v4l2-fwnode.h> | |
| 33 | 33 | #include <media/v4l2-ctrls.h> |
| 34 | −#include <media/i2c/tvp514x.h> | |
| 35 | −#include <media/media-entity.h> | |
| 34 | +#include <media/v4l2-device.h> | |
| 35 | +#include <media/v4l2-fwnode.h> | |
| 36 | +#include <media/v4l2-mediabus.h> | |
| 36 | 37 | |
| 37 | 38 | #include "tvp514x_regs.h" |
| 38 | 39 | |
| @@ -118,7 +119,7 @@ struct tvp514x_decoder { · 79 unmodified lines | ||
| 118 | 119 | struct media_pad pad; |
| 119 | 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 | 125 | /* TVP514x default register values */ |
| @@ -1024,7 +1025,6 @@ done: · 899 unmodified lines | ||
| 1024 | 1025 | static int |
| 1025 | 1026 | tvp514x_probe(struct i2c_client *client) |
| 1026 | 1027 | { |
| 1027 | − const struct i2c_device_id *id = i2c_client_get_device_id(client); | |
| 1028 | 1028 | struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); |
| 1029 | 1029 | struct tvp514x_decoder *decoder; |
| 1030 | 1030 | struct v4l2_subdev *sd; |
| @@ -1049,7 +1049,7 @@ tvp514x_probe(struct i2c_client *client) · 18 unmodified lines | ||
| 1049 | 1049 | memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, |
| 1050 | 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 | 1054 | /* Copy board specific information here */ |
| 1055 | 1055 | decoder->pdata = pdata; |
| @@ -1183,29 +1183,26 @@ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { · 127 unmodified lines | ||
| 1183 | 1183 | * driver_data - Driver data |
| 1184 | 1184 | */ |
| 1185 | 1185 | static const struct i2c_device_id tvp514x_id[] = { |
| 1186 | − {"tvp5146", (unsigned long)tvp5146_init_reg_seq}, | |
| 1187 | − {"tvp5146m2", (unsigned long)tvp514xm_init_reg_seq}, | |
| 1188 | − {"tvp5147", (unsigned long)tvp5147_init_reg_seq}, | |
| 1189 | − {"tvp5147m1", (unsigned long)tvp514xm_init_reg_seq}, | |
| 1190 | − {}, | |
| 1186 | + {"tvp5146", (kernel_ulong_t)tvp5146_init_reg_seq }, | |
| 1187 | + {"tvp5146m2", (kernel_ulong_t)tvp514xm_init_reg_seq }, | |
| 1188 | + {"tvp5147", (kernel_ulong_t)tvp5147_init_reg_seq }, | |
| 1189 | + {"tvp5147m1", (kernel_ulong_t)tvp514xm_init_reg_seq }, | |
| 1190 | + { /* sentinel */ } | |
| 1191 | 1191 | }; |
| 1192 | − | |
| 1193 | 1192 | MODULE_DEVICE_TABLE(i2c, tvp514x_id); |
| 1194 | 1193 | |
| 1195 | −#if IS_ENABLED(CONFIG_OF) | |
| 1196 | 1194 | static const struct of_device_id tvp514x_of_match[] = { |
| 1197 | − { .compatible = "ti,tvp5146", }, | |
| 1198 | − { .compatible = "ti,tvp5146m2", }, | |
| 1199 | − { .compatible = "ti,tvp5147", }, | |
| 1200 | − { .compatible = "ti,tvp5147m1", }, | |
| 1201 | − { /* sentinel */ }, | |
| 1195 | + { .compatible = "ti,tvp5146", .data = tvp5146_init_reg_seq }, | |
| 1196 | + { .compatible = "ti,tvp5146m2", .data = tvp514xm_init_reg_seq }, | |
| 1197 | + { .compatible = "ti,tvp5147", .data = tvp5147_init_reg_seq }, | |
| 1198 | + { .compatible = "ti,tvp5147m1", .data = tvp514xm_init_reg_seq }, | |
| 1199 | + { /* sentinel */ } | |
| 1202 | 1200 | }; |
| 1203 | 1201 | MODULE_DEVICE_TABLE(of, tvp514x_of_match); |
| 1204 | −#endif | |
| 1205 | 1202 | |
| 1206 | 1203 | static struct i2c_driver tvp514x_driver = { |
| 1207 | 1204 | .driver = { |
| 1208 | − .of_match_table = of_match_ptr(tvp514x_of_match), | |
| 1205 | + .of_match_table = tvp514x_of_match, | |
| 1209 | 1206 | .name = TVP514X_MODULE_NAME, |
| 1210 | 1207 | }, |
| 1211 | 1208 | .probe = tvp514x_probe, |
| @@ -759,7 +759,6 @@ static void video_i2c_release(struct video_device *vdev) · 758 unmodified lines | ||
| 759 | 759 | |
| 760 | 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 | 762 | struct video_i2c_data *data; |
| 764 | 763 | struct v4l2_device *v4l2_dev; |
| 765 | 764 | struct vb2_queue *queue; |
| @@ -769,11 +768,8 @@ static int video_i2c_probe(struct i2c_client *client) · 3 unmodified lines | ||
| 769 | 768 | if (!data) |
| 770 | 769 | return -ENOMEM; |
| 771 | 770 | |
| 772 | − if (dev_fwnode(&client->dev)) | |
| 773 | − data->chip = device_get_match_data(&client->dev); | |
| 774 | − else if (id) | |
| 775 | − data->chip = &video_i2c_chip[id->driver_data]; | |
| 776 | − else | |
| 771 | + data->chip = i2c_get_match_data(client); | |
| 772 | + if (!data->chip) | |
| 777 | 773 | goto error_free_device; |
| 778 | 774 | |
| 779 | 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 | 938 | static const struct i2c_device_id video_i2c_id_table[] = { |
| 943 | − { "amg88xx", AMG88XX }, | |
| 944 | − { "mlx90640", MLX90640 }, | |
| 939 | + { "amg88xx", (kernel_ulong_t)&video_i2c_chip[AMG88XX] }, | |
| 940 | + { "mlx90640", (kernel_ulong_t)&video_i2c_chip[MLX90640] }, | |
| 945 | 941 | {} |
| 946 | 942 | }; |
| 947 | 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 | 197 | struct media_device *mdev = entity->graph_obj.mdev; |
| 198 | 198 | struct media_pad *iter; |
| 199 | 199 | unsigned int i = 0; |
| 200 | + int ret = 0; | |
| 200 | 201 | |
| 201 | 202 | if (num_pads >= MEDIA_ENTITY_MAX_PADS) |
| 202 | 203 | return -E2BIG; |
| @@ -210,15 +211,27 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, · 7 unmodified lines | ||
| 210 | 211 | media_entity_for_each_pad(entity, iter) { |
| 211 | 212 | iter->entity = entity; |
| 212 | 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 | 221 | if (mdev) |
| 214 | 222 | media_gobj_create(mdev, MEDIA_GRAPH_PAD, |
| 215 | 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 | 231 | if (mdev) |
| 219 | 232 | mutex_unlock(&mdev->graph_mutex); |
| 220 | 233 | |
| 221 | − return 0; | |
| 234 | + return ret; | |
| 222 | 235 | } |
| 223 | 236 | EXPORT_SYMBOL_GPL(media_entity_pads_init); |
| 224 | 237 | |
| @@ -13,6 +13,7 @@ if MEDIA_PCI_SUPPORT · 12 unmodified lines | ||
| 13 | 13 | if MEDIA_CAMERA_SUPPORT |
| 14 | 14 | comment "Media capture support" |
| 15 | 15 | |
| 16 | +source "drivers/media/pci/mgb4/Kconfig" | |
| 16 | 17 | source "drivers/media/pci/solo6x10/Kconfig" |
| 17 | 18 | source "drivers/media/pci/sta2x11/Kconfig" |
| 18 | 19 | source "drivers/media/pci/tw5864/Kconfig" |
| @@ -32,6 +32,7 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ · 31 unmodified lines | ||
| 32 | 32 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
| 33 | 33 | obj-$(CONFIG_VIDEO_DT3155) += dt3155/ |
| 34 | 34 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ |
| 35 | +obj-$(CONFIG_VIDEO_MGB4) += mgb4/ | |
| 35 | 36 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ |
| 36 | 37 | obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ |
| 37 | 38 | obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ |
| @@ -126,6 +126,7 @@ MODULE_PARM_DESC(audiodev, "specify audio device:\n" · 125 unmodified lines | ||
| 126 | 126 | "\t\t 3 = tvaudio"); |
| 127 | 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 | 131 | /* I2C addresses list */ |
| 131 | 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 | 3475 | /* free resources */ |
| 3476 | 3476 | free_irq(btv->c.pci->irq,btv); |
| 3477 | + del_timer_sync(&btv->timeout); | |
| 3477 | 3478 | iounmap(btv->bt848_mmio); |
| 3478 | 3479 | release_mem_region(pci_resource_start(btv->c.pci,0), |
| 3479 | 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 | 190 | u32 freq = c->frequency; |
| 191 | 191 | int i, a, n, pump; |
| 192 | 192 | u32 band, pll; |
| 193 | − u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000, | |
| 194 | − 1576000,1718000,1856000,2036000,2150000}; | |
| 195 | − u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000, | |
| 196 | − 0x00102000,0x00104000,0x00108000,0x00110000, | |
| 197 | − 0x00120000,0x00140000}; | |
| 193 | + static const u32 osci[] = { | |
| 194 | + 950000, 1019000, 1075000, 1178000, 1296000, 1432000, | |
| 195 | + 1576000, 1718000, 1856000, 2036000, 2150000 | |
| 196 | + }; | |
| 197 | + static const u32 bandsel[] = { | |
| 198 | + 0, 0x00020000, 0x00040000, 0x00100800, 0x00101000, | |
| 199 | + 0x00102000, 0x00104000, 0x00108000, 0x00110000, | |
| 200 | + 0x00120000, 0x00140000 | |
| 201 | + }; | |
| 198 | 202 | |
| 199 | 203 | #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ |
| 200 | 204 | dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq); |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | * All rights reserved. |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | +#include <linux/bitfield.h> | |
| 11 | 12 | #include <linux/delay.h> |
| 12 | 13 | #include <media/i2c/adv7604.h> |
| 13 | 14 | #include <media/i2c/adv7842.h> |
| @@ -210,17 +211,17 @@ void cobalt_pcie_status_show(struct cobalt *cobalt) · 196 unmodified lines | ||
| 210 | 211 | pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat); |
| 211 | 212 | cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n", |
| 212 | 213 | capa, get_link_speed(capa), |
| 213 | − (capa & PCI_EXP_LNKCAP_MLW) >> 4); | |
| 214 | + FIELD_GET(PCI_EXP_LNKCAP_MLW, capa)); | |
| 214 | 215 | cobalt_info("PCIe link control 0x%04x\n", ctrl); |
| 215 | 216 | cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n", |
| 216 | 217 | stat, get_link_speed(stat), |
| 217 | − (stat & PCI_EXP_LNKSTA_NLW) >> 4); | |
| 218 | + FIELD_GET(PCI_EXP_LNKSTA_NLW, stat)); | |
| 218 | 219 | |
| 219 | 220 | /* Bus */ |
| 220 | 221 | pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa); |
| 221 | 222 | cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n", |
| 222 | 223 | capa, get_link_speed(capa), |
| 223 | − (capa & PCI_EXP_LNKCAP_MLW) >> 4); | |
| 224 | + FIELD_GET(PCI_EXP_LNKCAP_MLW, capa)); | |
| 224 | 225 | |
| 225 | 226 | /* Slot */ |
| 226 | 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 | 240 | if (!pci_is_pcie(pci_dev)) |
| 240 | 241 | return 0; |
| 241 | 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 | 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 | 251 | if (!pci_is_pcie(pci_dev)) |
| 251 | 252 | return 0; |
| 252 | 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 | 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 | 108 | struct sg_dma_desc_info *desc[NR_BUFS]; |
| 109 | 109 | struct cobalt_buffer *cb; |
| 110 | − struct list_head *p; | |
| 111 | 110 | int i = 0; |
| 112 | 111 | |
| 113 | − list_for_each(p, &s->bufs) { | |
| 114 | − cb = list_entry(p, struct cobalt_buffer, list); | |
| 112 | + list_for_each_entry(cb, &s->bufs, list) { | |
| 115 | 113 | desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index]; |
| 116 | 114 | if (i > 0) |
| 117 | 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 | 346 | struct cobalt *cobalt = s->cobalt; |
| 349 | 347 | struct sg_dma_desc_info *desc; |
| 350 | 348 | struct cobalt_buffer *cb; |
| 351 | − struct list_head *p; | |
| 352 | 349 | unsigned long flags; |
| 353 | 350 | int timeout_msec = 100; |
| 354 | 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 | 365 | /* Try to stop the DMA engine gracefully */ |
| 369 | 366 | spin_lock_irqsave(&s->irqlock, flags); |
| 370 | − list_for_each(p, &s->bufs) { | |
| 371 | − cb = list_entry(p, struct cobalt_buffer, list); | |
| 367 | + list_for_each_entry(cb, &s->bufs, list) { | |
| 372 | 368 | desc = &s->dma_desc_info[cb->vb.vb2_buf.index]; |
| 373 | 369 | /* Stop DMA after this descriptor chain */ |
| 374 | 370 | descriptor_list_end_of_chain(desc); |
| @@ -631,7 +631,7 @@ struct cx18 { · 630 unmodified lines | ||
| 631 | 631 | u32 hw2_irq_mask; |
| 632 | 632 | |
| 633 | 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 | 635 | struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; |
| 636 | 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 | 831 | int i; |
| 832 | 832 | |
| 833 | 833 | if (cx == NULL) { |
| 834 | − CX18_ERR("cx == NULL (cmd=%x)\n", cmd); | |
| 834 | + pr_err("cx == NULL (cmd=%x)\n", cmd); | |
| 835 | 835 | return 0; |
| 836 | 836 | } |
| 837 | 837 | if (args > MAX_MB_ARGUMENTS) { |
| @@ -10,6 +10,12 @@ config INTEL_VSC · 9 unmodified lines | ||
| 10 | 10 | help |
| 11 | 11 | This adds support for Intel Visual Sensing Controller (IVSC). |
| 12 | 12 | |
| 13 | − Enables the IVSC firmware services required for controlling | |
| 14 | − camera sensor ownership and CSI-2 link through Image Processing | |
| 15 | − Unit(IPU) driver of Intel. | |
| 13 | + The IVSC support is split into two devices, ACE (Algorithm | |
| 14 | + Context Engine) and CSI (Camera Serial Interface), each of which | |
| 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 | 30 | #include <linux/uuid.h> |
| 31 | 31 | #include <linux/workqueue.h> |
| 32 | 32 | |
| 33 | −#define MEI_ACE_DRIVER_NAME "ivsc_ace" | |
| 34 | − | |
| 35 | 33 | /* indicating driver message */ |
| 36 | 34 | #define ACE_DRV_MSG 1 |
| 37 | 35 | /* indicating set command */ |
| @@ -408,6 +406,9 @@ static int mei_ace_setup_dev_link(struct mei_ace *ace) · 370 unmodified lines | ||
| 408 | 406 | if (!csi_dev) { |
| 409 | 407 | ret = -EPROBE_DEFER; |
| 410 | 408 | goto err; |
| 409 | + } else if (!dev_fwnode(csi_dev)) { | |
| 410 | + ret = -EPROBE_DEFER; | |
| 411 | + goto err_put; | |
| 411 | 412 | } |
| 412 | 413 | |
| 413 | 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 | 555 | 0x9B, 0x78, 0x03, 0x61, 0x63, 0x5E, 0x24, 0x47) |
| 555 | 556 | |
| 556 | 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 | 559 | { /* sentinel */ } |
| 559 | 560 | }; |
| 560 | 561 | MODULE_DEVICE_TABLE(mei, mei_ace_tbl); |
| 561 | 562 | |
| 562 | 563 | static struct mei_cl_driver mei_ace_driver = { |
| 563 | 564 | .id_table = mei_ace_tbl, |
| 564 | − .name = MEI_ACE_DRIVER_NAME, | |
| 565 | + .name = KBUILD_MODNAME, | |
| 565 | 566 | |
| 566 | 567 | .probe = mei_ace_probe, |
| 567 | 568 | .remove = mei_ace_remove, |
| @@ -30,7 +30,6 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <media/v4l2-fwnode.h> |
| 31 | 31 | #include <media/v4l2-subdev.h> |
| 32 | 32 | |
| 33 | −#define MEI_CSI_DRIVER_NAME "ivsc_csi" | |
| 34 | 33 | #define MEI_CSI_ENTITY_NAME "Intel IVSC CSI" |
| 35 | 34 | |
| 36 | 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 | 803 | 0xAF, 0x93, 0x7b, 0x44, 0x53, 0xAC, 0x29, 0xDA) |
| 805 | 804 | |
| 806 | 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 | 807 | { /* sentinel */ } |
| 809 | 808 | }; |
| 810 | 809 | MODULE_DEVICE_TABLE(mei, mei_csi_tbl); |
| 811 | 810 | |
| 812 | 811 | static struct mei_cl_driver mei_csi_driver = { |
| 813 | 812 | .id_table = mei_csi_tbl, |
| 814 | − .name = MEI_CSI_DRIVER_NAME, | |
| 813 | + .name = KBUILD_MODNAME, | |
| 815 | 814 | |
| 816 | 815 | .probe = mei_csi_probe, |
| 817 | 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.