media updates for v3.18-rc1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUNr9iAAoJEAhfPr2O5OEVSygP/iVpHK7JZCFSvy1ly67gUcIw zeO2q0Exm3WwApchaCNX0b9qB9A6jeaRiJtuqOgR7L8ksYorku7k12g0IrveK8e4 UhwscWw1HkYvTR3JG4Z2a8LoYiUatQCgcknICgjJ12fo2fCg2SnzbGp9jKiLqJew dx1zOgn5Hslqy+PWQULtkLo/XxdlAX8YNUhXU5q5gxCfhciaJ7Kq+tvM9NodobHG u94b10fmOclLug37b+Vpg01pxjqe+X+HbrHzbOsL7dvxW84igqzpyb9+WNH8FGZZ +oSu66faokH8rVxzkPyODT8TSwHuqafVF1IFafsFFJpYYfRWiY0SttMACVMuuB3z m6kVM9pTApmh736xvzB4JP4i/+aIu2qQftYTybQkTpn1AIy2kw8b09pOWbhEgdjl 5CfI7I2iSkSviZXMrIe51znIhdxohF7gEN8PyaPto3N1LHVnHAd7/J43nolSSnke DE0lQGk+NaGFv/MiESiKC8lSiEGzqpMkrxpOIeDZAsKxQ3ihxKai3kqAYYiPt2+n 2HVhLsmfMqdd23DGSf7LjhhLqjXKhEC/+LDsLl105keRYLN/TYZuQxieJEDikRF/ NLJcuuXUQkcsdgrAChAonu1K3roAsgZ8E6BP+814CWZ5LM4xW0kQqqKN6S88eKx2 HcIz2xwveR6sZBNZE7Kl =DUbD -----END PGP SIGNATURE----- Merge tag 'media/v3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - new IR driver: hix5hd2-ir - the virtual test driver (vivi) was replaced by vivid, with has an almost complete set of features to emulate most v4l2 devices and properly test all sorts of userspace apps - the as102 driver had several bugs fixed and was properly split into a frontend and a core driver. With that, it got promoted from staging into mainstream - one new CI driver got added for CIMaX SP2/SP2HF (sp2 driver) - one new frontend driver for Toshiba ISDB-T/ISDB-S demod (tc90522) - one new PCI driver for ISDB-T/ISDB-S (pt3 driver) - saa7134 driver got support for go7007-based devices - added a new PCI driver for Techwell 68xx chipsets (tw68) - a new platform driver was added (coda) - new tuner drivers: mxl301rf and qm1d1c0042 - a new DVB USB driver was added for DVBSky S860 & similar devices - added a new SDR driver (hackrf) - usbtv got audio support - several platform drivers are now compiled with COMPILE_TEST - a series of compiler fixup patches, making sparse/spatch happier with the media stuff and removing several warnings, especially on those platform drivers that didn't use to compile on x86 - Support for several new modern devices got added - lots of other fixes, improvements and cleanups * tag 'media/v3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (544 commits) [media] ir-hix5hd2: fix build on c6x arch [media] pt3: fix DTV FE I2C driver load error paths Revert "[media] media: em28xx - remove reset_resume interface" [media] exynos4-is: fix some warnings when compiling on arm64 [media] usb drivers: use %zu instead of %zd [media] pci drivers: use %zu instead of %zd [media] dvb-frontends: use %zu instead of %zd [media] s5p-mfc: Fix several printk warnings [media] s5p_mfc_opr: Fix warnings [media] ti-vpe: Fix typecast [media] s3c-camif: fix dma_addr_t printks [media] s5p_mfc_opr_v6: get rid of warnings when compiled with 64 bits [media] s5p_mfc_opr_v5: Fix lots of warnings on x86_64 [media] em28xx: Fix identation [media] drxd: remove a dead code [media] saa7146: remove return after BUG() [media] cx88: remove return after BUG() [media] cx88: fix cards table CodingStyle [media] radio-sf16fmr2: declare some structs as static [media] radio-sf16fmi: declare pnp_attached as static ...
This commit is contained in:
		
				commit
				
					
						4d9708ea5e
					
				
			
		
					 474 changed files with 36226 additions and 13063 deletions
				
			
		|  | @ -2566,6 +2566,12 @@ fields changed from _s32 to _u32. | ||||||
| 	  <para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;. | 	  <para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;. | ||||||
| 	  </para> | 	  </para> | ||||||
|         </listitem> |         </listitem> | ||||||
|  |       <title>V4L2 in Linux 3.18</title> | ||||||
|  |       <orderedlist> | ||||||
|  | 	<listitem> | ||||||
|  | 	  <para>Added <constant>V4L2_CID_PAN_SPEED</constant> and | ||||||
|  |  <constant>V4L2_CID_TILT_SPEED</constant> camera controls.</para> | ||||||
|  | 	</listitem> | ||||||
|       </orderedlist> |       </orderedlist> | ||||||
|     </section> |     </section> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3965,6 +3965,27 @@ by exposure, white balance or focus controls.</entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row><entry></entry></row> | 	  <row><entry></entry></row> | ||||||
| 
 | 
 | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_PAN_SPEED</constant> </entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row><row><entry spanname="descr">This control turns the | ||||||
|  | camera horizontally at the specific speed. The unit is undefined. A | ||||||
|  | positive value moves the camera to the right (clockwise when viewed | ||||||
|  | from above), a negative value to the left. A value of zero stops the motion | ||||||
|  | if one is in progress and has no effect otherwise.</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row><entry></entry></row> | ||||||
|  | 
 | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_TILT_SPEED</constant> </entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row><row><entry spanname="descr">This control turns the | ||||||
|  | camera vertically at the specified speed. The unit is undefined. A | ||||||
|  | positive value moves the camera up, a negative value down. A value of zero | ||||||
|  | stops the motion if one is in progress and has no effect otherwise.</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row><entry></entry></row> | ||||||
|  | 
 | ||||||
| 	</tbody> | 	</tbody> | ||||||
|       </tgroup> |       </tgroup> | ||||||
|     </table> |     </table> | ||||||
|  | @ -4790,6 +4811,40 @@ interface and may change in the future.</para> | ||||||
| 	    conversion. | 	    conversion. | ||||||
| 	    </entry> | 	    </entry> | ||||||
| 	  </row> | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_RED</constant></entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="descr">Test pattern red colour component. | ||||||
|  | 	    </entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENR</constant></entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="descr">Test pattern green (next to red) | ||||||
|  | 	    colour component. | ||||||
|  | 	    </entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_BLUE</constant></entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="descr">Test pattern blue colour component. | ||||||
|  | 	    </entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENB</constant></entry> | ||||||
|  | 	    <entry>integer</entry> | ||||||
|  | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry spanname="descr">Test pattern green (next to blue) | ||||||
|  | 	    colour component. | ||||||
|  | 	    </entry> | ||||||
|  | 	  </row> | ||||||
| 	  <row><entry></entry></row> | 	  <row><entry></entry></row> | ||||||
| 	</tbody> | 	</tbody> | ||||||
|       </tgroup> |       </tgroup> | ||||||
|  |  | ||||||
|  | @ -237,9 +237,9 @@ for a pixel lie next to each other in memory.</para> | ||||||
| 	    <entry>g<subscript>4</subscript></entry> | 	    <entry>g<subscript>4</subscript></entry> | ||||||
| 	    <entry>g<subscript>3</subscript></entry> | 	    <entry>g<subscript>3</subscript></entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row id="V4L2-PIX-FMT-RGB555X"> | 	  <row id="V4L2-PIX-FMT-ARGB555X"> | ||||||
| 	    <entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry> | 	    <entry><constant>V4L2_PIX_FMT_ARGB555X</constant></entry> | ||||||
| 	    <entry>'RGBQ'</entry> | 	    <entry>'AR15' | (1 << 31)</entry> | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
| 	    <entry>a</entry> | 	    <entry>a</entry> | ||||||
| 	    <entry>r<subscript>4</subscript></entry> | 	    <entry>r<subscript>4</subscript></entry> | ||||||
|  | @ -259,6 +259,28 @@ for a pixel lie next to each other in memory.</para> | ||||||
| 	    <entry>b<subscript>1</subscript></entry> | 	    <entry>b<subscript>1</subscript></entry> | ||||||
| 	    <entry>b<subscript>0</subscript></entry> | 	    <entry>b<subscript>0</subscript></entry> | ||||||
| 	  </row> | 	  </row> | ||||||
|  | 	  <row id="V4L2-PIX-FMT-XRGB555X"> | ||||||
|  | 	    <entry><constant>V4L2_PIX_FMT_XRGB555X</constant></entry> | ||||||
|  | 	    <entry>'XR15' | (1 << 31)</entry> | ||||||
|  | 	    <entry></entry> | ||||||
|  | 	    <entry>-</entry> | ||||||
|  | 	    <entry>r<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>3</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>0</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>3</subscript></entry> | ||||||
|  | 	    <entry></entry> | ||||||
|  | 	    <entry>g<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>0</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>3</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>0</subscript></entry> | ||||||
|  | 	  </row> | ||||||
| 	  <row id="V4L2-PIX-FMT-RGB565X"> | 	  <row id="V4L2-PIX-FMT-RGB565X"> | ||||||
| 	    <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry> | 	    <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry> | ||||||
| 	    <entry>'RGBR'</entry> | 	    <entry>'RGBR'</entry> | ||||||
|  | @ -464,7 +486,7 @@ for a pixel lie next to each other in memory.</para> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row id="V4L2-PIX-FMT-ARGB32"> | 	  <row id="V4L2-PIX-FMT-ARGB32"> | ||||||
| 	    <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry> | 	    <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry> | ||||||
| 	    <entry>'AX24'</entry> | 	    <entry>'BA24'</entry> | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
| 	    <entry>a<subscript>7</subscript></entry> | 	    <entry>a<subscript>7</subscript></entry> | ||||||
| 	    <entry>a<subscript>6</subscript></entry> | 	    <entry>a<subscript>6</subscript></entry> | ||||||
|  | @ -800,6 +822,28 @@ image</title> | ||||||
| 	    <entry>g<subscript>4</subscript></entry> | 	    <entry>g<subscript>4</subscript></entry> | ||||||
| 	    <entry>g<subscript>3</subscript></entry> | 	    <entry>g<subscript>3</subscript></entry> | ||||||
| 	  </row> | 	  </row> | ||||||
|  | 	  <row id="V4L2-PIX-FMT-RGB555X"> | ||||||
|  | 	    <entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry> | ||||||
|  | 	    <entry>'RGBQ'</entry> | ||||||
|  | 	    <entry></entry> | ||||||
|  | 	    <entry>a</entry> | ||||||
|  | 	    <entry>r<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>3</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>r<subscript>0</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>3</subscript></entry> | ||||||
|  | 	    <entry></entry> | ||||||
|  | 	    <entry>g<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>g<subscript>0</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>4</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>3</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>2</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>1</subscript></entry> | ||||||
|  | 	    <entry>b<subscript>0</subscript></entry> | ||||||
|  | 	  </row> | ||||||
| 	  <row id="V4L2-PIX-FMT-BGR32"> | 	  <row id="V4L2-PIX-FMT-BGR32"> | ||||||
| 	    <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry> | 	    <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry> | ||||||
| 	    <entry>'BGR4'</entry> | 	    <entry>'BGR4'</entry> | ||||||
|  |  | ||||||
|  | @ -76,21 +76,22 @@ | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
| 	    <entry>&v4l2-event-vsync;</entry> | 	    <entry>&v4l2-event-vsync;</entry> | ||||||
|             <entry><structfield>vsync</structfield></entry> |             <entry><structfield>vsync</structfield></entry> | ||||||
| 	    <entry>Event data for event V4L2_EVENT_VSYNC. | 	    <entry>Event data for event <constant>V4L2_EVENT_VSYNC</constant>. | ||||||
|             </entry> |             </entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row> | 	  <row> | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
| 	    <entry>&v4l2-event-ctrl;</entry> | 	    <entry>&v4l2-event-ctrl;</entry> | ||||||
|             <entry><structfield>ctrl</structfield></entry> |             <entry><structfield>ctrl</structfield></entry> | ||||||
| 	    <entry>Event data for event V4L2_EVENT_CTRL. | 	    <entry>Event data for event <constant>V4L2_EVENT_CTRL</constant>. | ||||||
|             </entry> |             </entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row> | 	  <row> | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
| 	    <entry>&v4l2-event-frame-sync;</entry> | 	    <entry>&v4l2-event-frame-sync;</entry> | ||||||
|             <entry><structfield>frame_sync</structfield></entry> |             <entry><structfield>frame_sync</structfield></entry> | ||||||
| 	    <entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry> | 	    <entry>Event data for event | ||||||
|  | 	    <constant>V4L2_EVENT_FRAME_SYNC</constant>.</entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row> | 	  <row> | ||||||
| 	    <entry></entry> | 	    <entry></entry> | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ | ||||||
| 	<funcdef>int <function>ioctl</function></funcdef> | 	<funcdef>int <function>ioctl</function></funcdef> | ||||||
| 	<paramdef>int <parameter>fd</parameter></paramdef> | 	<paramdef>int <parameter>fd</parameter></paramdef> | ||||||
| 	<paramdef>int <parameter>request</parameter></paramdef> | 	<paramdef>int <parameter>request</parameter></paramdef> | ||||||
| 	<paramdef>const struct v4l2_edid *<parameter>argp</parameter></paramdef> | 	<paramdef>struct v4l2_edid *<parameter>argp</parameter></paramdef> | ||||||
|       </funcprototype> |       </funcprototype> | ||||||
|     </funcsynopsis> |     </funcsynopsis> | ||||||
|   </refsynopsisdiv> |   </refsynopsisdiv> | ||||||
|  | @ -124,18 +124,18 @@ | ||||||
| 	    maximum number of blocks as defined by the standard). When you set the EDID and | 	    maximum number of blocks as defined by the standard). When you set the EDID and | ||||||
| 	    <structfield>blocks</structfield> is 0, then the EDID is disabled or erased.</entry> | 	    <structfield>blocks</structfield> is 0, then the EDID is disabled or erased.</entry> | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row> |  | ||||||
| 	    <entry>__u8 *</entry> |  | ||||||
| 	    <entry><structfield>edid</structfield></entry> |  | ||||||
| 	    <entry>Pointer to memory that contains the EDID. The minimum size is |  | ||||||
| 	    <structfield>blocks</structfield> * 128.</entry> |  | ||||||
| 	  </row> |  | ||||||
| 	  <row> | 	  <row> | ||||||
| 	    <entry>__u32</entry> | 	    <entry>__u32</entry> | ||||||
| 	    <entry><structfield>reserved</structfield>[5]</entry> | 	    <entry><structfield>reserved</structfield>[5]</entry> | ||||||
| 	    <entry>Reserved for future extensions. Applications and drivers must | 	    <entry>Reserved for future extensions. Applications and drivers must | ||||||
| 	    set the array to zero.</entry> | 	    set the array to zero.</entry> | ||||||
| 	  </row> | 	  </row> | ||||||
|  | 	  <row> | ||||||
|  | 	    <entry>__u8 *</entry> | ||||||
|  | 	    <entry><structfield>edid</structfield></entry> | ||||||
|  | 	    <entry>Pointer to memory that contains the EDID. The minimum size is | ||||||
|  | 	    <structfield>blocks</structfield> * 128.</entry> | ||||||
|  | 	  </row> | ||||||
| 	</tbody> | 	</tbody> | ||||||
|       </tgroup> |       </tgroup> | ||||||
|     </table> |     </table> | ||||||
|  |  | ||||||
|  | @ -176,7 +176,7 @@ | ||||||
| 	  </row> | 	  </row> | ||||||
| 	  <row> | 	  <row> | ||||||
| 	    <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry> | 	    <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry> | ||||||
| 	    <entry>5</entry> | 	    <entry>6</entry> | ||||||
| 	    <entry> | 	    <entry> | ||||||
| 	      <para>Triggered whenever the motion detection state for one or more of the regions | 	      <para>Triggered whenever the motion detection state for one or more of the regions | ||||||
| 	      changes. This event has a &v4l2-event-motion-det; associated with it.</para> | 	      changes. This event has a &v4l2-event-motion-det; associated with it.</para> | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								Documentation/devicetree/bindings/media/hix5hd2-ir.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Documentation/devicetree/bindings/media/hix5hd2-ir.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | Device-Tree bindings for hix5hd2 ir IP | ||||||
|  | 
 | ||||||
|  | Required properties: | ||||||
|  | 	- compatible: Should contain "hisilicon,hix5hd2-ir". | ||||||
|  | 	- reg: Base physical address of the controller and length of memory | ||||||
|  | 	  mapped region. | ||||||
|  | 	- interrupts: interrupt-specifier for the sole interrupt generated by | ||||||
|  | 	  the device. The interrupt specifier format depends on the interrupt | ||||||
|  | 	  controller parent. | ||||||
|  | 	- clocks: clock phandle and specifier pair. | ||||||
|  | 	- hisilicon,power-syscon: phandle of syscon used to control power. | ||||||
|  | 
 | ||||||
|  | Optional properties: | ||||||
|  | 	- linux,rc-map-name : Remote control map name. | ||||||
|  | 
 | ||||||
|  | Example node: | ||||||
|  | 
 | ||||||
|  | 	ir: ir@f8001000 { | ||||||
|  | 		compatible = "hisilicon,hix5hd2-ir"; | ||||||
|  | 		reg = <0xf8001000 0x1000>; | ||||||
|  | 		interrupts = <0 47 4>; | ||||||
|  | 		clocks = <&clock HIX5HD2_FIXED_24M>; | ||||||
|  | 		hisilicon,power-syscon = <&sysctrl>; | ||||||
|  | 		linux,rc-map-name = "rc-tivo"; | ||||||
|  | 	}; | ||||||
|  | @ -708,23 +708,25 @@ sub drxk_terratec_htc_stick { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub it9135 { | sub it9135 { | ||||||
| 	my $sourcefile = "dvb-usb-it9135.zip"; | 	my $url = "http://www.ite.com.tw/uploads/firmware/v3.25.0.0/"; | ||||||
| 	my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile"; | 	my $file1 = "dvb-usb-it9135-01.zip"; | ||||||
| 	my $hash = "1e55f6c8833f1d0ae067c2bb2953e6a9"; |  | ||||||
| 	my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0); |  | ||||||
| 	my $outfile = "dvb-usb-it9135.fw"; |  | ||||||
| 	my $fwfile1 = "dvb-usb-it9135-01.fw"; | 	my $fwfile1 = "dvb-usb-it9135-01.fw"; | ||||||
|  | 	my $hash1 = "02fcf11174eda84745dae7e61c5ff9ba"; | ||||||
|  | 	my $file2 = "dvb-usb-it9135-02.zip"; | ||||||
| 	my $fwfile2 = "dvb-usb-it9135-02.fw"; | 	my $fwfile2 = "dvb-usb-it9135-02.fw"; | ||||||
|  | 	my $hash2 = "d5e1437dc24358578e07999475d4cac9"; | ||||||
| 
 | 
 | ||||||
| 	checkstandard(); | 	checkstandard(); | ||||||
| 
 | 
 | ||||||
| 	wgetfile($sourcefile, $url); | 	wgetfile($file1, $url . $file1); | ||||||
| 	unzip($sourcefile, $tmpdir); | 	unzip($file1, ""); | ||||||
| 	verify("$tmpdir/$outfile", $hash); | 	verify("$fwfile1", $hash1); | ||||||
| 	extract("$tmpdir/$outfile", 64, 8128, "$fwfile1"); |  | ||||||
| 	extract("$tmpdir/$outfile", 12866, 5817, "$fwfile2"); |  | ||||||
| 
 | 
 | ||||||
| 	"$fwfile1 $fwfile2" | 	wgetfile($file2, $url . $file2); | ||||||
|  | 	unzip($file2, ""); | ||||||
|  | 	verify("$fwfile2", $hash2); | ||||||
|  | 
 | ||||||
|  | 	"$file1 $file2" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub tda10071 { | sub tda10071 { | ||||||
|  |  | ||||||
							
								
								
									
										1111
									
								
								Documentation/video4linux/vivid.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1111
									
								
								Documentation/video4linux/vivid.txt
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										28
									
								
								MAINTAINERS
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								MAINTAINERS
									
										
									
									
									
								
							|  | @ -4233,6 +4233,16 @@ L:	linuxppc-dev@lists.ozlabs.org | ||||||
| S:	Odd Fixes | S:	Odd Fixes | ||||||
| F:	drivers/tty/hvc/ | F:	drivers/tty/hvc/ | ||||||
| 
 | 
 | ||||||
|  | HACKRF MEDIA DRIVER | ||||||
|  | M:	Antti Palosaari <crope@iki.fi> | ||||||
|  | L:	linux-media@vger.kernel.org | ||||||
|  | W:	http://linuxtv.org/ | ||||||
|  | W:	http://palosaari.fi/linux/ | ||||||
|  | Q:	http://patchwork.linuxtv.org/project/linux-media/list/ | ||||||
|  | T:	git git://linuxtv.org/anttip/media_tree.git | ||||||
|  | S:	Maintained | ||||||
|  | F:	drivers/media/usb/hackrf/ | ||||||
|  | 
 | ||||||
| HARDWARE MONITORING | HARDWARE MONITORING | ||||||
| M:	Jean Delvare <jdelvare@suse.de> | M:	Jean Delvare <jdelvare@suse.de> | ||||||
| M:	Guenter Roeck <linux@roeck-us.net> | M:	Guenter Roeck <linux@roeck-us.net> | ||||||
|  | @ -5131,7 +5141,7 @@ W:	http://palosaari.fi/linux/ | ||||||
| Q:	http://patchwork.linuxtv.org/project/linux-media/list/ | Q:	http://patchwork.linuxtv.org/project/linux-media/list/ | ||||||
| T:	git git://linuxtv.org/anttip/media_tree.git | T:	git git://linuxtv.org/anttip/media_tree.git | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	drivers/media/tuners/tuner_it913x* | F:	drivers/media/tuners/it913x* | ||||||
| 
 | 
 | ||||||
| IVTV VIDEO4LINUX DRIVER | IVTV VIDEO4LINUX DRIVER | ||||||
| M:	Andy Walls <awalls@md.metrocast.net> | M:	Andy Walls <awalls@md.metrocast.net> | ||||||
|  | @ -8672,6 +8682,14 @@ F:	include/sound/dmaengine_pcm.h | ||||||
| F:	sound/core/pcm_dmaengine.c | F:	sound/core/pcm_dmaengine.c | ||||||
| F:	sound/soc/soc-generic-dmaengine-pcm.c | F:	sound/soc/soc-generic-dmaengine-pcm.c | ||||||
| 
 | 
 | ||||||
|  | SP2 MEDIA DRIVER | ||||||
|  | M:	Olli Salonen <olli.salonen@iki.fi> | ||||||
|  | L:	linux-media@vger.kernel.org | ||||||
|  | W:	http://linuxtv.org/ | ||||||
|  | Q:	http://patchwork.linuxtv.org/project/linux-media/list/ | ||||||
|  | S:	Maintained | ||||||
|  | F:	drivers/media/dvb-frontends/sp2* | ||||||
|  | 
 | ||||||
| SPARC + UltraSPARC (sparc/sparc64) | SPARC + UltraSPARC (sparc/sparc64) | ||||||
| M:	"David S. Miller" <davem@davemloft.net> | M:	"David S. Miller" <davem@davemloft.net> | ||||||
| L:	sparclinux@vger.kernel.org | L:	sparclinux@vger.kernel.org | ||||||
|  | @ -9375,6 +9393,14 @@ T:	git git://linuxtv.org/media_tree.git | ||||||
| S:	Odd fixes | S:	Odd fixes | ||||||
| F:	drivers/media/usb/tm6000/ | F:	drivers/media/usb/tm6000/ | ||||||
| 
 | 
 | ||||||
|  | TW68 VIDEO4LINUX DRIVER | ||||||
|  | M:	Hans Verkuil <hverkuil@xs4all.nl> | ||||||
|  | L:	linux-media@vger.kernel.org | ||||||
|  | T:	git git://linuxtv.org/media_tree.git | ||||||
|  | W:	http://linuxtv.org | ||||||
|  | S:	Odd Fixes | ||||||
|  | F:	drivers/media/pci/tw68/ | ||||||
|  | 
 | ||||||
| TPM DEVICE DRIVER | TPM DEVICE DRIVER | ||||||
| M:	Peter Huewe <peterhuewe@gmx.de> | M:	Peter Huewe <peterhuewe@gmx.de> | ||||||
| M:	Ashley Lai <ashley@ashleylai.com> | M:	Ashley Lai <ashley@ashleylai.com> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|  * see flexcop.c for copyright information |  * see flexcop.c for copyright information | ||||||
|  */ |  */ | ||||||
| #ifndef __FLEXCOP_H__ | #ifndef __FLEXCOP_H__ | ||||||
| #define __FLEXCOP_H___ | #define __FLEXCOP_H__ | ||||||
| 
 | 
 | ||||||
| #define FC_LOG_PREFIX "b2c2-flexcop" | #define FC_LOG_PREFIX "b2c2-flexcop" | ||||||
| #include "flexcop-common.h" | #include "flexcop-common.h" | ||||||
|  |  | ||||||
|  | @ -311,7 +311,6 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) | ||||||
| 		} | 		} | ||||||
| 	default: | 	default: | ||||||
| 		BUG(); | 		BUG(); | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (mutex_lock_interruptible(vdev->lock)) | 	if (mutex_lock_interruptible(vdev->lock)) | ||||||
|  | @ -399,7 +398,6 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	default: | 	default: | ||||||
| 		BUG(); | 		BUG(); | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -423,7 +421,6 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	default: | 	default: | ||||||
| 		BUG(); | 		BUG(); | ||||||
| 		return -EINVAL; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -157,6 +157,12 @@ static struct sms_board sms_boards[] = { | ||||||
| 		.type = SMS_DENVER_2160, | 		.type = SMS_DENVER_2160, | ||||||
| 		.default_mode = DEVICE_MODE_DAB_TDMB, | 		.default_mode = DEVICE_MODE_DAB_TDMB, | ||||||
| 	}, | 	}, | ||||||
|  | 	[SMS1XXX_BOARD_PCTV_77E] = { | ||||||
|  | 		.name	= "Hauppauge microStick 77e", | ||||||
|  | 		.type	= SMS_NOVA_B0, | ||||||
|  | 		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVB_NOVA_12MHZ_B0, | ||||||
|  | 		.default_mode = DEVICE_MODE_DVBT_BDA, | ||||||
|  | 	}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct sms_board *sms_get_board(unsigned id) | struct sms_board *sms_get_board(unsigned id) | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ | ||||||
| #define SMS1XXX_BOARD_SIANO_RIO		18 | #define SMS1XXX_BOARD_SIANO_RIO		18 | ||||||
| #define SMS1XXX_BOARD_SIANO_DENVER_1530	19 | #define SMS1XXX_BOARD_SIANO_DENVER_1530	19 | ||||||
| #define SMS1XXX_BOARD_SIANO_DENVER_2160 20 | #define SMS1XXX_BOARD_SIANO_DENVER_2160 20 | ||||||
|  | #define SMS1XXX_BOARD_PCTV_77E		21 | ||||||
| 
 | 
 | ||||||
| struct sms_board_gpio_cfg { | struct sms_board_gpio_cfg { | ||||||
| 	int lna_vhf_exist; | 	int lna_vhf_exist; | ||||||
|  |  | ||||||
|  | @ -2129,8 +2129,6 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num, | ||||||
| 
 | 
 | ||||||
| static int __init smscore_module_init(void) | static int __init smscore_module_init(void) | ||||||
| { | { | ||||||
| 	int rc = 0; |  | ||||||
| 
 |  | ||||||
| 	INIT_LIST_HEAD(&g_smscore_notifyees); | 	INIT_LIST_HEAD(&g_smscore_notifyees); | ||||||
| 	INIT_LIST_HEAD(&g_smscore_devices); | 	INIT_LIST_HEAD(&g_smscore_devices); | ||||||
| 	kmutex_init(&g_smscore_deviceslock); | 	kmutex_init(&g_smscore_deviceslock); | ||||||
|  | @ -2138,7 +2136,7 @@ static int __init smscore_module_init(void) | ||||||
| 	INIT_LIST_HEAD(&g_smscore_registry); | 	INIT_LIST_HEAD(&g_smscore_registry); | ||||||
| 	kmutex_init(&g_smscore_registrylock); | 	kmutex_init(&g_smscore_registrylock); | ||||||
| 
 | 
 | ||||||
| 	return rc; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __exit smscore_module_exit(void) | static void __exit smscore_module_exit(void) | ||||||
|  |  | ||||||
|  | @ -1087,8 +1087,8 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) | ||||||
| 	struct dmxdev_filter *dmxdevfilter = file->private_data; | 	struct dmxdev_filter *dmxdevfilter = file->private_data; | ||||||
| 	unsigned int mask = 0; | 	unsigned int mask = 0; | ||||||
| 
 | 
 | ||||||
| 	if (!dmxdevfilter) | 	if ((!dmxdevfilter) || dmxdevfilter->dev->exit) | ||||||
| 		return -EINVAL; | 		return POLLERR; | ||||||
| 
 | 
 | ||||||
| 	poll_wait(file, &dmxdevfilter->buffer.queue, wait); | 	poll_wait(file, &dmxdevfilter->buffer.queue, wait); | ||||||
| 
 | 
 | ||||||
|  | @ -1181,6 +1181,9 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) | ||||||
| 
 | 
 | ||||||
| 	dprintk("function : %s\n", __func__); | 	dprintk("function : %s\n", __func__); | ||||||
| 
 | 
 | ||||||
|  | 	if (dmxdev->exit) | ||||||
|  | 		return POLLERR; | ||||||
|  | 
 | ||||||
| 	poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | 	poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | ||||||
| 
 | 
 | ||||||
| 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||||||
|  |  | ||||||
|  | @ -144,6 +144,7 @@ | ||||||
| #define USB_PID_ITETECH_IT9135				0x9135 | #define USB_PID_ITETECH_IT9135				0x9135 | ||||||
| #define USB_PID_ITETECH_IT9135_9005			0x9005 | #define USB_PID_ITETECH_IT9135_9005			0x9005 | ||||||
| #define USB_PID_ITETECH_IT9135_9006			0x9006 | #define USB_PID_ITETECH_IT9135_9006			0x9006 | ||||||
|  | #define USB_PID_ITETECH_IT9303				0x9306 | ||||||
| #define USB_PID_KWORLD_399U				0xe399 | #define USB_PID_KWORLD_399U				0xe399 | ||||||
| #define USB_PID_KWORLD_399U_2				0xe400 | #define USB_PID_KWORLD_399U_2				0xe400 | ||||||
| #define USB_PID_KWORLD_395U				0xe396 | #define USB_PID_KWORLD_395U				0xe396 | ||||||
|  | @ -244,6 +245,7 @@ | ||||||
| #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006 | #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006 | ||||||
| #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM	0x3009 | #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM	0x3009 | ||||||
| #define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d | #define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d | ||||||
|  | #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI		0x3012 | ||||||
| #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400		0x3014 | #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400		0x3014 | ||||||
| #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a | ||||||
| #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081 | ||||||
|  |  | ||||||
|  | @ -1934,15 +1934,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, | ||||||
| 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||||
| 	int err = 0; | 	int err = 0; | ||||||
| 
 | 
 | ||||||
| 	struct dtv_properties *tvps = NULL; | 	struct dtv_properties *tvps = parg; | ||||||
| 	struct dtv_property *tvp = NULL; | 	struct dtv_property *tvp = NULL; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(fe->dvb->device, "%s:\n", __func__); | 	dev_dbg(fe->dvb->device, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	if(cmd == FE_SET_PROPERTY) { | 	if (cmd == FE_SET_PROPERTY) { | ||||||
| 		tvps = (struct dtv_properties __user *)parg; |  | ||||||
| 
 |  | ||||||
| 		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); | 		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); | ||||||
| 		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); | 		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); | ||||||
| 
 | 
 | ||||||
|  | @ -1957,7 +1955,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | 		if (copy_from_user(tvp, (void __user *)tvps->props, | ||||||
|  | 				   tvps->num * sizeof(struct dtv_property))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -1972,10 +1971,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, | ||||||
| 		if (c->state == DTV_TUNE) | 		if (c->state == DTV_TUNE) | ||||||
| 			dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); | 			dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	} else | 	} else if (cmd == FE_GET_PROPERTY) { | ||||||
| 	if(cmd == FE_GET_PROPERTY) { |  | ||||||
| 		tvps = (struct dtv_properties __user *)parg; |  | ||||||
| 
 |  | ||||||
| 		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); | 		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); | ||||||
| 		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); | 		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); | ||||||
| 
 | 
 | ||||||
|  | @ -1990,7 +1986,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | 		if (copy_from_user(tvp, (void __user *)tvps->props, | ||||||
|  | 				   tvps->num * sizeof(struct dtv_property))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -2012,7 +2009,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, | ||||||
| 			(tvp + i)->result = err; | 			(tvp + i)->result = err; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | 		if (copy_to_user((void __user *)tvps->props, tvp, | ||||||
|  | 				 tvps->num * sizeof(struct dtv_property))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -2072,6 +2070,23 @@ static int dtv_set_frontend(struct dvb_frontend *fe) | ||||||
| 	case SYS_DVBC_ANNEX_C: | 	case SYS_DVBC_ANNEX_C: | ||||||
| 		rolloff = 113; | 		rolloff = 113; | ||||||
| 		break; | 		break; | ||||||
|  | 	case SYS_DVBS: | ||||||
|  | 	case SYS_TURBO: | ||||||
|  | 		rolloff = 135; | ||||||
|  | 		break; | ||||||
|  | 	case SYS_DVBS2: | ||||||
|  | 		switch (c->rolloff) { | ||||||
|  | 		case ROLLOFF_20: | ||||||
|  | 			rolloff = 120; | ||||||
|  | 			break; | ||||||
|  | 		case ROLLOFF_25: | ||||||
|  | 			rolloff = 125; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 		case ROLLOFF_35: | ||||||
|  | 			rolloff = 135; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  | @ -2550,7 +2565,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe) | ||||||
| 	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num, | 	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num, | ||||||
| 			fe->id); | 			fe->id); | ||||||
| 
 | 
 | ||||||
| 	if (fe->ops.tuner_ops.sleep) | 	if (fe->ops.tuner_ops.suspend) | ||||||
|  | 		ret = fe->ops.tuner_ops.suspend(fe); | ||||||
|  | 	else if (fe->ops.tuner_ops.sleep) | ||||||
| 		ret = fe->ops.tuner_ops.sleep(fe); | 		ret = fe->ops.tuner_ops.sleep(fe); | ||||||
| 
 | 
 | ||||||
| 	if (fe->ops.sleep) | 	if (fe->ops.sleep) | ||||||
|  | @ -2572,7 +2589,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe) | ||||||
| 	if (fe->ops.init) | 	if (fe->ops.init) | ||||||
| 		ret = fe->ops.init(fe); | 		ret = fe->ops.init(fe); | ||||||
| 
 | 
 | ||||||
| 	if (fe->ops.tuner_ops.init) | 	if (fe->ops.tuner_ops.resume) | ||||||
|  | 		ret = fe->ops.tuner_ops.resume(fe); | ||||||
|  | 	else if (fe->ops.tuner_ops.init) | ||||||
| 		ret = fe->ops.tuner_ops.init(fe); | 		ret = fe->ops.tuner_ops.init(fe); | ||||||
| 
 | 
 | ||||||
| 	fe->exit = DVB_FE_NO_EXIT; | 	fe->exit = DVB_FE_NO_EXIT; | ||||||
|  |  | ||||||
|  | @ -201,6 +201,8 @@ struct dvb_tuner_ops { | ||||||
| 	int (*release)(struct dvb_frontend *fe); | 	int (*release)(struct dvb_frontend *fe); | ||||||
| 	int (*init)(struct dvb_frontend *fe); | 	int (*init)(struct dvb_frontend *fe); | ||||||
| 	int (*sleep)(struct dvb_frontend *fe); | 	int (*sleep)(struct dvb_frontend *fe); | ||||||
|  | 	int (*suspend)(struct dvb_frontend *fe); | ||||||
|  | 	int (*resume)(struct dvb_frontend *fe); | ||||||
| 
 | 
 | ||||||
| 	/** This is for simple PLLs - set all parameters in one go. */ | 	/** This is for simple PLLs - set all parameters in one go. */ | ||||||
| 	int (*set_params)(struct dvb_frontend *fe); | 	int (*set_params)(struct dvb_frontend *fe); | ||||||
|  |  | ||||||
|  | @ -166,6 +166,31 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t | ||||||
| 	return len; | 	return len; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, | ||||||
|  | 				  const u8 __user *buf, size_t len) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | 	size_t todo = len; | ||||||
|  | 	size_t split; | ||||||
|  | 
 | ||||||
|  | 	split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; | ||||||
|  | 
 | ||||||
|  | 	if (split > 0) { | ||||||
|  | 		status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split); | ||||||
|  | 		if (status) | ||||||
|  | 			return len - todo; | ||||||
|  | 		buf += split; | ||||||
|  | 		todo -= split; | ||||||
|  | 		rbuf->pwrite = 0; | ||||||
|  | 	} | ||||||
|  | 	status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); | ||||||
|  | 	if (status) | ||||||
|  | 		return len - todo; | ||||||
|  | 	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; | ||||||
|  | 
 | ||||||
|  | 	return len; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) | ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) | ||||||
| { | { | ||||||
| 	int status; | 	int status; | ||||||
|  | @ -297,3 +322,4 @@ EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); | ||||||
| EXPORT_SYMBOL(dvb_ringbuffer_read_user); | EXPORT_SYMBOL(dvb_ringbuffer_read_user); | ||||||
| EXPORT_SYMBOL(dvb_ringbuffer_read); | EXPORT_SYMBOL(dvb_ringbuffer_read); | ||||||
| EXPORT_SYMBOL(dvb_ringbuffer_write); | EXPORT_SYMBOL(dvb_ringbuffer_write); | ||||||
|  | EXPORT_SYMBOL(dvb_ringbuffer_write_user); | ||||||
|  |  | ||||||
|  | @ -133,6 +133,8 @@ extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, | ||||||
| */ | */ | ||||||
| extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, | extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, | ||||||
| 				    size_t len); | 				    size_t len); | ||||||
|  | extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, | ||||||
|  | 				         const u8 __user *buf, size_t len); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -471,6 +471,11 @@ config DVB_SI2168 | ||||||
| 	help | 	help | ||||||
| 	  Say Y when you want to support this frontend. | 	  Say Y when you want to support this frontend. | ||||||
| 
 | 
 | ||||||
|  | config DVB_AS102_FE | ||||||
|  | 	tristate | ||||||
|  | 	depends on DVB_CORE | ||||||
|  | 	default DVB_AS102 | ||||||
|  | 
 | ||||||
| comment "DVB-C (cable) frontends" | comment "DVB-C (cable) frontends" | ||||||
| 	depends on DVB_CORE | 	depends on DVB_CORE | ||||||
| 
 | 
 | ||||||
|  | @ -643,6 +648,14 @@ config DVB_MB86A20S | ||||||
| 	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. | 	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. | ||||||
| 	  Say Y when you want to support this frontend. | 	  Say Y when you want to support this frontend. | ||||||
| 
 | 
 | ||||||
|  | config DVB_TC90522 | ||||||
|  | 	tristate "Toshiba TC90522" | ||||||
|  | 	depends on DVB_CORE && I2C | ||||||
|  | 	default m if !MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	help | ||||||
|  | 	  A Toshiba TC90522 2xISDB-T + 2xISDB-S demodulator. | ||||||
|  | 	  Say Y when you want to support this frontend. | ||||||
|  | 
 | ||||||
| comment "Digital terrestrial only tuners/PLL" | comment "Digital terrestrial only tuners/PLL" | ||||||
| 	depends on DVB_CORE | 	depends on DVB_CORE | ||||||
| 
 | 
 | ||||||
|  | @ -720,6 +733,13 @@ config DVB_A8293 | ||||||
| 	depends on DVB_CORE && I2C | 	depends on DVB_CORE && I2C | ||||||
| 	default m if !MEDIA_SUBDRV_AUTOSELECT | 	default m if !MEDIA_SUBDRV_AUTOSELECT | ||||||
| 
 | 
 | ||||||
|  | config DVB_SP2 | ||||||
|  | 	tristate "CIMaX SP2" | ||||||
|  | 	depends on DVB_CORE && I2C | ||||||
|  | 	default m if !MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	help | ||||||
|  | 	  CIMaX SP2/SP2HF Common Interface module. | ||||||
|  | 
 | ||||||
| config DVB_LGS8GL5 | config DVB_LGS8GL5 | ||||||
| 	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" | 	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" | ||||||
| 	depends on DVB_CORE && I2C | 	depends on DVB_CORE && I2C | ||||||
|  |  | ||||||
|  | @ -107,10 +107,12 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o | ||||||
| obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o | obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o | ||||||
| obj-$(CONFIG_DVB_SI2165) += si2165.o | obj-$(CONFIG_DVB_SI2165) += si2165.o | ||||||
| obj-$(CONFIG_DVB_A8293) += a8293.o | obj-$(CONFIG_DVB_A8293) += a8293.o | ||||||
|  | obj-$(CONFIG_DVB_SP2) += sp2.o | ||||||
| obj-$(CONFIG_DVB_TDA10071) += tda10071.o | obj-$(CONFIG_DVB_TDA10071) += tda10071.o | ||||||
| obj-$(CONFIG_DVB_RTL2830) += rtl2830.o | obj-$(CONFIG_DVB_RTL2830) += rtl2830.o | ||||||
| obj-$(CONFIG_DVB_RTL2832) += rtl2832.o | obj-$(CONFIG_DVB_RTL2832) += rtl2832.o | ||||||
| obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o | obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o | ||||||
| obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o | obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o | ||||||
| obj-$(CONFIG_DVB_AF9033) += af9033.o | obj-$(CONFIG_DVB_AF9033) += af9033.o | ||||||
| 
 | obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o | ||||||
|  | obj-$(CONFIG_DVB_TC90522) += tc90522.o | ||||||
|  |  | ||||||
|  | @ -683,7 +683,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	switch (c->transmission_mode) { | 	switch (c->transmission_mode) { | ||||||
| 	case TRANSMISSION_MODE_AUTO: | 	case TRANSMISSION_MODE_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case TRANSMISSION_MODE_2K: | 	case TRANSMISSION_MODE_2K: | ||||||
| 		break; | 		break; | ||||||
|  | @ -693,12 +693,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n", | 		dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n", | ||||||
| 				__func__); | 				__func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (c->guard_interval) { | 	switch (c->guard_interval) { | ||||||
| 	case GUARD_INTERVAL_AUTO: | 	case GUARD_INTERVAL_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case GUARD_INTERVAL_1_32: | 	case GUARD_INTERVAL_1_32: | ||||||
| 		break; | 		break; | ||||||
|  | @ -714,12 +714,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n", | 		dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n", | ||||||
| 				__func__); | 				__func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (c->hierarchy) { | 	switch (c->hierarchy) { | ||||||
| 	case HIERARCHY_AUTO: | 	case HIERARCHY_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case HIERARCHY_NONE: | 	case HIERARCHY_NONE: | ||||||
| 		break; | 		break; | ||||||
|  | @ -734,12 +734,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); | 		dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (c->modulation) { | 	switch (c->modulation) { | ||||||
| 	case QAM_AUTO: | 	case QAM_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case QPSK: | 	case QPSK: | ||||||
| 		break; | 		break; | ||||||
|  | @ -751,7 +751,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__); | 		dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Use HP. How and which case we can switch to LP? */ | 	/* Use HP. How and which case we can switch to LP? */ | ||||||
|  | @ -759,7 +759,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	switch (c->code_rate_HP) { | 	switch (c->code_rate_HP) { | ||||||
| 	case FEC_AUTO: | 	case FEC_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case FEC_1_2: | 	case FEC_1_2: | ||||||
| 		break; | 		break; | ||||||
|  | @ -778,12 +778,12 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n", | 		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n", | ||||||
| 				__func__); | 				__func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (c->code_rate_LP) { | 	switch (c->code_rate_LP) { | ||||||
| 	case FEC_AUTO: | 	case FEC_AUTO: | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 		break; | 		break; | ||||||
| 	case FEC_1_2: | 	case FEC_1_2: | ||||||
| 		break; | 		break; | ||||||
|  | @ -804,7 +804,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n", | 		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n", | ||||||
| 				__func__); | 				__func__); | ||||||
| 		auto_mode = 1; | 		auto_mode = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (c->bandwidth_hz) { | 	switch (c->bandwidth_hz) { | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -24,12 +24,11 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/kconfig.h> | #include <linux/kconfig.h> | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * I2C address (TODO: are these in 8-bit format?) | ||||||
|  |  * 0x38, 0x3a, 0x3c, 0x3e | ||||||
|  |  */ | ||||||
| struct af9033_config { | struct af9033_config { | ||||||
| 	/*
 |  | ||||||
| 	 * I2C address |  | ||||||
| 	 */ |  | ||||||
| 	u8 i2c_addr; |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * clock Hz | 	 * clock Hz | ||||||
| 	 * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, | 	 * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, | ||||||
|  | @ -75,8 +74,23 @@ struct af9033_config { | ||||||
| 	 * input spectrum inversion | 	 * input spectrum inversion | ||||||
| 	 */ | 	 */ | ||||||
| 	bool spec_inv; | 	bool spec_inv; | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	bool dyn0_clk; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * PID filter ops | ||||||
|  | 	 */ | ||||||
|  | 	struct af9033_ops *ops; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * frontend | ||||||
|  | 	 * returned by that driver | ||||||
|  | 	 */ | ||||||
|  | 	struct dvb_frontend **fe; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| struct af9033_ops { | struct af9033_ops { | ||||||
| 	int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff); | 	int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff); | ||||||
|  | @ -84,36 +98,4 @@ struct af9033_ops { | ||||||
| 			  int onoff); | 			  int onoff); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #if IS_ENABLED(CONFIG_DVB_AF9033) |  | ||||||
| extern |  | ||||||
| struct dvb_frontend *af9033_attach(const struct af9033_config *config, |  | ||||||
| 				   struct i2c_adapter *i2c, |  | ||||||
| 				   struct af9033_ops *ops); |  | ||||||
| 
 |  | ||||||
| #else |  | ||||||
| static inline |  | ||||||
| struct dvb_frontend *af9033_attach(const struct af9033_config *config, |  | ||||||
| 				   struct i2c_adapter *i2c, |  | ||||||
| 				   struct af9033_ops *ops) |  | ||||||
| { |  | ||||||
| 	pr_warn("%s: driver disabled by Kconfig\n", __func__); |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) |  | ||||||
| { |  | ||||||
| 	pr_warn("%s: driver disabled by Kconfig\n", __func__); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid, |  | ||||||
| 	int onoff) |  | ||||||
| { |  | ||||||
| 	pr_warn("%s: driver disabled by Kconfig\n", __func__); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif /* AF9033_H */ | #endif /* AF9033_H */ | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "dvb_frontend.h" | #include "dvb_frontend.h" | ||||||
| #include "af9033.h" | #include "af9033.h" | ||||||
|  | #include <linux/math64.h> | ||||||
| 
 | 
 | ||||||
| struct reg_val { | struct reg_val { | ||||||
| 	u32 reg; | 	u32 reg; | ||||||
|  |  | ||||||
							
								
								
									
										480
									
								
								drivers/media/dvb-frontends/as102_fe.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										480
									
								
								drivers/media/dvb-frontends/as102_fe.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,480 @@ | ||||||
|  | /*
 | ||||||
|  |  * Abilis Systems Single DVB-T Receiver | ||||||
|  |  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com> | ||||||
|  |  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2, or (at your option) | ||||||
|  |  * any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <dvb_frontend.h> | ||||||
|  | 
 | ||||||
|  | #include "as102_fe.h" | ||||||
|  | 
 | ||||||
|  | struct as102_state { | ||||||
|  | 	struct dvb_frontend frontend; | ||||||
|  | 	struct as10x_demod_stats demod_stats; | ||||||
|  | 
 | ||||||
|  | 	const struct as102_fe_ops *ops; | ||||||
|  | 	void *priv; | ||||||
|  | 	uint8_t elna_cfg; | ||||||
|  | 
 | ||||||
|  | 	/* signal strength */ | ||||||
|  | 	uint16_t signal_strength; | ||||||
|  | 	/* bit error rate */ | ||||||
|  | 	uint32_t ber; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg) | ||||||
|  | { | ||||||
|  | 	uint8_t c; | ||||||
|  | 
 | ||||||
|  | 	switch (arg) { | ||||||
|  | 	case FEC_1_2: | ||||||
|  | 		c = CODE_RATE_1_2; | ||||||
|  | 		break; | ||||||
|  | 	case FEC_2_3: | ||||||
|  | 		c = CODE_RATE_2_3; | ||||||
|  | 		break; | ||||||
|  | 	case FEC_3_4: | ||||||
|  | 		c = CODE_RATE_3_4; | ||||||
|  | 		break; | ||||||
|  | 	case FEC_5_6: | ||||||
|  | 		c = CODE_RATE_5_6; | ||||||
|  | 		break; | ||||||
|  | 	case FEC_7_8: | ||||||
|  | 		c = CODE_RATE_7_8; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		c = CODE_RATE_UNKNOWN; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_set_frontend(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||||
|  | 	struct as10x_tune_args tune_args = { 0 }; | ||||||
|  | 
 | ||||||
|  | 	/* set frequency */ | ||||||
|  | 	tune_args.freq = c->frequency / 1000; | ||||||
|  | 
 | ||||||
|  | 	/* fix interleaving_mode */ | ||||||
|  | 	tune_args.interleaving_mode = INTLV_NATIVE; | ||||||
|  | 
 | ||||||
|  | 	switch (c->bandwidth_hz) { | ||||||
|  | 	case 8000000: | ||||||
|  | 		tune_args.bandwidth = BW_8_MHZ; | ||||||
|  | 		break; | ||||||
|  | 	case 7000000: | ||||||
|  | 		tune_args.bandwidth = BW_7_MHZ; | ||||||
|  | 		break; | ||||||
|  | 	case 6000000: | ||||||
|  | 		tune_args.bandwidth = BW_6_MHZ; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		tune_args.bandwidth = BW_8_MHZ; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (c->guard_interval) { | ||||||
|  | 	case GUARD_INTERVAL_1_32: | ||||||
|  | 		tune_args.guard_interval = GUARD_INT_1_32; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INTERVAL_1_16: | ||||||
|  | 		tune_args.guard_interval = GUARD_INT_1_16; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INTERVAL_1_8: | ||||||
|  | 		tune_args.guard_interval = GUARD_INT_1_8; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INTERVAL_1_4: | ||||||
|  | 		tune_args.guard_interval = GUARD_INT_1_4; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INTERVAL_AUTO: | ||||||
|  | 	default: | ||||||
|  | 		tune_args.guard_interval = GUARD_UNKNOWN; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (c->modulation) { | ||||||
|  | 	case QPSK: | ||||||
|  | 		tune_args.modulation = CONST_QPSK; | ||||||
|  | 		break; | ||||||
|  | 	case QAM_16: | ||||||
|  | 		tune_args.modulation = CONST_QAM16; | ||||||
|  | 		break; | ||||||
|  | 	case QAM_64: | ||||||
|  | 		tune_args.modulation = CONST_QAM64; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		tune_args.modulation = CONST_UNKNOWN; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (c->transmission_mode) { | ||||||
|  | 	case TRANSMISSION_MODE_2K: | ||||||
|  | 		tune_args.transmission_mode = TRANS_MODE_2K; | ||||||
|  | 		break; | ||||||
|  | 	case TRANSMISSION_MODE_8K: | ||||||
|  | 		tune_args.transmission_mode = TRANS_MODE_8K; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		tune_args.transmission_mode = TRANS_MODE_UNKNOWN; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (c->hierarchy) { | ||||||
|  | 	case HIERARCHY_NONE: | ||||||
|  | 		tune_args.hierarchy = HIER_NONE; | ||||||
|  | 		break; | ||||||
|  | 	case HIERARCHY_1: | ||||||
|  | 		tune_args.hierarchy = HIER_ALPHA_1; | ||||||
|  | 		break; | ||||||
|  | 	case HIERARCHY_2: | ||||||
|  | 		tune_args.hierarchy = HIER_ALPHA_2; | ||||||
|  | 		break; | ||||||
|  | 	case HIERARCHY_4: | ||||||
|  | 		tune_args.hierarchy = HIER_ALPHA_4; | ||||||
|  | 		break; | ||||||
|  | 	case HIERARCHY_AUTO: | ||||||
|  | 		tune_args.hierarchy = HIER_UNKNOWN; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pr_debug("as102: tuner parameters: freq: %d  bw: 0x%02x  gi: 0x%02x\n", | ||||||
|  | 			c->frequency, | ||||||
|  | 			tune_args.bandwidth, | ||||||
|  | 			tune_args.guard_interval); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Detect a hierarchy selection | ||||||
|  | 	 * if HP/LP are both set to FEC_NONE, HP will be selected. | ||||||
|  | 	 */ | ||||||
|  | 	if ((tune_args.hierarchy != HIER_NONE) && | ||||||
|  | 		       ((c->code_rate_LP == FEC_NONE) || | ||||||
|  | 			(c->code_rate_HP == FEC_NONE))) { | ||||||
|  | 
 | ||||||
|  | 		if (c->code_rate_LP == FEC_NONE) { | ||||||
|  | 			tune_args.hier_select = HIER_HIGH_PRIORITY; | ||||||
|  | 			tune_args.code_rate = | ||||||
|  | 			   as102_fe_get_code_rate(c->code_rate_HP); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (c->code_rate_HP == FEC_NONE) { | ||||||
|  | 			tune_args.hier_select = HIER_LOW_PRIORITY; | ||||||
|  | 			tune_args.code_rate = | ||||||
|  | 			   as102_fe_get_code_rate(c->code_rate_LP); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		pr_debug("as102: \thierarchy: 0x%02x  selected: %s  code_rate_%s: 0x%02x\n", | ||||||
|  | 			tune_args.hierarchy, | ||||||
|  | 			tune_args.hier_select == HIER_HIGH_PRIORITY ? | ||||||
|  | 			"HP" : "LP", | ||||||
|  | 			tune_args.hier_select == HIER_HIGH_PRIORITY ? | ||||||
|  | 			"HP" : "LP", | ||||||
|  | 			tune_args.code_rate); | ||||||
|  | 	} else { | ||||||
|  | 		tune_args.code_rate = | ||||||
|  | 			as102_fe_get_code_rate(c->code_rate_HP); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Set frontend arguments */ | ||||||
|  | 	return state->ops->set_tune(state->priv, &tune_args); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_get_frontend(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||||
|  | 	int ret = 0; | ||||||
|  | 	struct as10x_tps tps = { 0 }; | ||||||
|  | 
 | ||||||
|  | 	/* send abilis command: GET_TPS */ | ||||||
|  | 	ret = state->ops->get_tps(state->priv, &tps); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	/* extract constellation */ | ||||||
|  | 	switch (tps.modulation) { | ||||||
|  | 	case CONST_QPSK: | ||||||
|  | 		c->modulation = QPSK; | ||||||
|  | 		break; | ||||||
|  | 	case CONST_QAM16: | ||||||
|  | 		c->modulation = QAM_16; | ||||||
|  | 		break; | ||||||
|  | 	case CONST_QAM64: | ||||||
|  | 		c->modulation = QAM_64; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* extract hierarchy */ | ||||||
|  | 	switch (tps.hierarchy) { | ||||||
|  | 	case HIER_NONE: | ||||||
|  | 		c->hierarchy = HIERARCHY_NONE; | ||||||
|  | 		break; | ||||||
|  | 	case HIER_ALPHA_1: | ||||||
|  | 		c->hierarchy = HIERARCHY_1; | ||||||
|  | 		break; | ||||||
|  | 	case HIER_ALPHA_2: | ||||||
|  | 		c->hierarchy = HIERARCHY_2; | ||||||
|  | 		break; | ||||||
|  | 	case HIER_ALPHA_4: | ||||||
|  | 		c->hierarchy = HIERARCHY_4; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* extract code rate HP */ | ||||||
|  | 	switch (tps.code_rate_HP) { | ||||||
|  | 	case CODE_RATE_1_2: | ||||||
|  | 		c->code_rate_HP = FEC_1_2; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_2_3: | ||||||
|  | 		c->code_rate_HP = FEC_2_3; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_3_4: | ||||||
|  | 		c->code_rate_HP = FEC_3_4; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_5_6: | ||||||
|  | 		c->code_rate_HP = FEC_5_6; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_7_8: | ||||||
|  | 		c->code_rate_HP = FEC_7_8; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* extract code rate LP */ | ||||||
|  | 	switch (tps.code_rate_LP) { | ||||||
|  | 	case CODE_RATE_1_2: | ||||||
|  | 		c->code_rate_LP = FEC_1_2; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_2_3: | ||||||
|  | 		c->code_rate_LP = FEC_2_3; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_3_4: | ||||||
|  | 		c->code_rate_LP = FEC_3_4; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_5_6: | ||||||
|  | 		c->code_rate_LP = FEC_5_6; | ||||||
|  | 		break; | ||||||
|  | 	case CODE_RATE_7_8: | ||||||
|  | 		c->code_rate_LP = FEC_7_8; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* extract guard interval */ | ||||||
|  | 	switch (tps.guard_interval) { | ||||||
|  | 	case GUARD_INT_1_32: | ||||||
|  | 		c->guard_interval = GUARD_INTERVAL_1_32; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INT_1_16: | ||||||
|  | 		c->guard_interval = GUARD_INTERVAL_1_16; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INT_1_8: | ||||||
|  | 		c->guard_interval = GUARD_INTERVAL_1_8; | ||||||
|  | 		break; | ||||||
|  | 	case GUARD_INT_1_4: | ||||||
|  | 		c->guard_interval = GUARD_INTERVAL_1_4; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* extract transmission mode */ | ||||||
|  | 	switch (tps.transmission_mode) { | ||||||
|  | 	case TRANS_MODE_2K: | ||||||
|  | 		c->transmission_mode = TRANSMISSION_MODE_2K; | ||||||
|  | 		break; | ||||||
|  | 	case TRANS_MODE_8K: | ||||||
|  | 		c->transmission_mode = TRANSMISSION_MODE_8K; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_get_tune_settings(struct dvb_frontend *fe, | ||||||
|  | 			struct dvb_frontend_tune_settings *settings) { | ||||||
|  | 
 | ||||||
|  | 	settings->min_delay_ms = 1000; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||||||
|  | { | ||||||
|  | 	int ret = 0; | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 	struct as10x_tune_status tstate = { 0 }; | ||||||
|  | 
 | ||||||
|  | 	/* send abilis command: GET_TUNE_STATUS */ | ||||||
|  | 	ret = state->ops->get_status(state->priv, &tstate); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	state->signal_strength  = tstate.signal_strength; | ||||||
|  | 	state->ber  = tstate.BER; | ||||||
|  | 
 | ||||||
|  | 	switch (tstate.tune_state) { | ||||||
|  | 	case TUNE_STATUS_SIGNAL_DVB_OK: | ||||||
|  | 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||||||
|  | 		break; | ||||||
|  | 	case TUNE_STATUS_STREAM_DETECTED: | ||||||
|  | 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | | ||||||
|  | 			  FE_HAS_VITERBI; | ||||||
|  | 		break; | ||||||
|  | 	case TUNE_STATUS_STREAM_TUNED: | ||||||
|  | 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | | ||||||
|  | 			  FE_HAS_LOCK | FE_HAS_VITERBI; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		*status = TUNE_STATUS_NOT_TUNED; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pr_debug("as102: tuner status: 0x%02x, strength %d, per: %d, ber: %d\n", | ||||||
|  | 		 tstate.tune_state, tstate.signal_strength, | ||||||
|  | 		 tstate.PER, tstate.BER); | ||||||
|  | 
 | ||||||
|  | 	if (!(*status & FE_HAS_LOCK)) { | ||||||
|  | 		memset(&state->demod_stats, 0, sizeof(state->demod_stats)); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = state->ops->get_stats(state->priv, &state->demod_stats); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		memset(&state->demod_stats, 0, sizeof(state->demod_stats)); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Note: | ||||||
|  |  * - in AS102 SNR=MER | ||||||
|  |  *   - the SNR will be returned in linear terms, i.e. not in dB | ||||||
|  |  *   - the accuracy equals ±2dB for a SNR range from 4dB to 30dB | ||||||
|  |  *   - the accuracy is >2dB for SNR values outside this range | ||||||
|  |  */ | ||||||
|  | static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	*snr = state->demod_stats.mer; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	*ber = state->ber; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_read_signal_strength(struct dvb_frontend *fe, | ||||||
|  | 					 u16 *strength) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	*strength = (((0xffff * 400) * state->signal_strength + 41000) * 2); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	if (state->demod_stats.has_started) | ||||||
|  | 		*ucblocks = state->demod_stats.bad_frame_count; | ||||||
|  | 	else | ||||||
|  | 		*ucblocks = 0; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	return state->ops->stream_ctrl(state->priv, acquire, | ||||||
|  | 				      state->elna_cfg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void as102_fe_release(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	kfree(state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static struct dvb_frontend_ops as102_fe_ops = { | ||||||
|  | 	.delsys = { SYS_DVBT }, | ||||||
|  | 	.info = { | ||||||
|  | 		.name			= "Abilis AS102 DVB-T", | ||||||
|  | 		.frequency_min		= 174000000, | ||||||
|  | 		.frequency_max		= 862000000, | ||||||
|  | 		.frequency_stepsize	= 166667, | ||||||
|  | 		.caps = FE_CAN_INVERSION_AUTO | ||||||
|  | 			| FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||||||
|  | 			| FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ||||||
|  | 			| FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK | ||||||
|  | 			| FE_CAN_QAM_AUTO | ||||||
|  | 			| FE_CAN_TRANSMISSION_MODE_AUTO | ||||||
|  | 			| FE_CAN_GUARD_INTERVAL_AUTO | ||||||
|  | 			| FE_CAN_HIERARCHY_AUTO | ||||||
|  | 			| FE_CAN_RECOVER | ||||||
|  | 			| FE_CAN_MUTE_TS | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	.set_frontend		= as102_fe_set_frontend, | ||||||
|  | 	.get_frontend		= as102_fe_get_frontend, | ||||||
|  | 	.get_tune_settings	= as102_fe_get_tune_settings, | ||||||
|  | 
 | ||||||
|  | 	.read_status		= as102_fe_read_status, | ||||||
|  | 	.read_snr		= as102_fe_read_snr, | ||||||
|  | 	.read_ber		= as102_fe_read_ber, | ||||||
|  | 	.read_signal_strength	= as102_fe_read_signal_strength, | ||||||
|  | 	.read_ucblocks		= as102_fe_read_ucblocks, | ||||||
|  | 	.ts_bus_ctrl		= as102_fe_ts_bus_ctrl, | ||||||
|  | 	.release		= as102_fe_release, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct dvb_frontend *as102_attach(const char *name, | ||||||
|  | 				  const struct as102_fe_ops *ops, | ||||||
|  | 				  void *priv, | ||||||
|  | 				  uint8_t elna_cfg) | ||||||
|  | { | ||||||
|  | 	struct as102_state *state; | ||||||
|  | 	struct dvb_frontend *fe; | ||||||
|  | 
 | ||||||
|  | 	state = kzalloc(sizeof(struct as102_state), GFP_KERNEL); | ||||||
|  | 	if (state == NULL) { | ||||||
|  | 		pr_err("%s: unable to allocate memory for state\n", __func__); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	fe = &state->frontend; | ||||||
|  | 	fe->demodulator_priv = state; | ||||||
|  | 	state->ops = ops; | ||||||
|  | 	state->priv = priv; | ||||||
|  | 	state->elna_cfg = elna_cfg; | ||||||
|  | 
 | ||||||
|  | 	/* init frontend callback ops */ | ||||||
|  | 	memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); | ||||||
|  | 	strncpy(fe->ops.info.name, name, sizeof(fe->ops.info.name)); | ||||||
|  | 
 | ||||||
|  | 	return fe; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(as102_attach); | ||||||
|  | 
 | ||||||
|  | MODULE_DESCRIPTION("as102-fe"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
|  | MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>"); | ||||||
							
								
								
									
										29
									
								
								drivers/media/dvb-frontends/as102_fe.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								drivers/media/dvb-frontends/as102_fe.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | /*
 | ||||||
|  |  * Abilis Systems Single DVB-T Receiver | ||||||
|  |  * Copyright (C) 2014 Mauro Carvalho Chehab <m.chehab@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2, or (at your option) | ||||||
|  |  * any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "as102_fe_types.h" | ||||||
|  | 
 | ||||||
|  | struct as102_fe_ops { | ||||||
|  | 	int (*set_tune)(void *priv, struct as10x_tune_args *tune_args); | ||||||
|  | 	int (*get_tps)(void *priv, struct as10x_tps *tps); | ||||||
|  | 	int (*get_status)(void *priv, struct as10x_tune_status *tstate); | ||||||
|  | 	int (*get_stats)(void *priv, struct as10x_demod_stats *demod_stats); | ||||||
|  | 	int (*stream_ctrl)(void *priv, int acquire, uint32_t elna_cfg); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct dvb_frontend *as102_attach(const char *name, | ||||||
|  | 				  const struct as102_fe_ops *ops, | ||||||
|  | 				  void *priv, | ||||||
|  | 				  uint8_t elna_cfg); | ||||||
|  | @ -11,16 +11,10 @@ | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| #ifndef _AS10X_TYPES_H_ | #ifndef _AS10X_TYPES_H_ | ||||||
| #define _AS10X_TYPES_H_ | #define _AS10X_TYPES_H_ | ||||||
| 
 | 
 | ||||||
| #include "as10x_handle.h" |  | ||||||
| 
 |  | ||||||
| /*********************************/ | /*********************************/ | ||||||
| /*       MACRO DEFINITIONS       */ | /*       MACRO DEFINITIONS       */ | ||||||
| /*********************************/ | /*********************************/ | ||||||
|  | @ -639,12 +639,12 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) | ||||||
| 		err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); | 		err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 	deb_info("got firmware: %zd\n",fw->size); | 	deb_info("got firmware: %zu\n", fw->size); | ||||||
| 
 | 
 | ||||||
| 	b = fw->data; | 	b = fw->data; | ||||||
| 	for (i = 0; i < fw->size;) { | 	for (i = 0; i < fw->size;) { | ||||||
| 		addr = le16_to_cpu( *( (u16 *)&b[i] ) ); | 		addr = le16_to_cpu(*((__le16 *)&b[i])); | ||||||
| 		len  = le16_to_cpu( *( (u16 *)&b[i+2] ) ); | 		len  = le16_to_cpu(*((__le16 *)&b[i+2])); | ||||||
| 		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); | 		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); | ||||||
| 		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { | 		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { | ||||||
| 			err("firmware download failed: %d\n",ret); | 			err("firmware download failed: %d\n",ret); | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	priv->delivery_system = SYS_DVBC_ANNEX_A; | 	priv->delivery_system = SYS_DVBC_ANNEX_A; | ||||||
| 	priv->ber_running = 0; /* tune stops BER counter */ | 	priv->ber_running = false; /* tune stops BER counter */ | ||||||
| 
 | 
 | ||||||
| 	/* program IF frequency */ | 	/* program IF frequency */ | ||||||
| 	if (fe->ops.tuner_ops.get_if_frequency) { | 	if (fe->ops.tuner_ops.get_if_frequency) { | ||||||
|  | @ -168,7 +168,7 @@ int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) | ||||||
| 			start_ber = 1; | 			start_ber = 1; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		priv->ber_running = 1; | 		priv->ber_running = true; | ||||||
| 		start_ber = 1; | 		start_ber = 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -564,10 +564,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	/* check if we have a valid signal */ | 	/* check if we have a valid signal */ | ||||||
| 	if (status & FE_HAS_LOCK) { | 	if (status & FE_HAS_LOCK) { | ||||||
| 		priv->last_tune_failed = 0; | 		priv->last_tune_failed = false; | ||||||
| 		return DVBFE_ALGO_SEARCH_SUCCESS; | 		return DVBFE_ALGO_SEARCH_SUCCESS; | ||||||
| 	} else { | 	} else { | ||||||
| 		priv->last_tune_failed = 1; | 		priv->last_tune_failed = true; | ||||||
| 		return DVBFE_ALGO_SEARCH_AGAIN; | 		return DVBFE_ALGO_SEARCH_AGAIN; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	priv->delivery_system = SYS_DVBT; | 	priv->delivery_system = SYS_DVBT; | ||||||
| 	priv->ber_running = 0; /* tune stops BER counter */ | 	priv->ber_running = false; /* tune stops BER counter */ | ||||||
| 
 | 
 | ||||||
| 	/* program IF frequency */ | 	/* program IF frequency */ | ||||||
| 	if (fe->ops.tuner_ops.get_if_frequency) { | 	if (fe->ops.tuner_ops.get_if_frequency) { | ||||||
|  | @ -272,7 +272,7 @@ int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) | ||||||
| 			start_ber = 1; | 			start_ber = 1; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		priv->ber_running = 1; | 		priv->ber_running = true; | ||||||
| 		start_ber = 1; | 		start_ber = 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2559,7 +2559,7 @@ static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode) | ||||||
| 	dib7000p_write_word(state, 1288, reg_1288); | 	dib7000p_write_word(state, 1288, reg_1288); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) | static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) | ||||||
| { | { | ||||||
| 	struct dib7000p_state *state = fe->demodulator_priv; | 	struct dib7000p_state *state = fe->demodulator_priv; | ||||||
| 	u16 reg_1287; | 	u16 reg_1287; | ||||||
|  |  | ||||||
|  | @ -2174,7 +2174,7 @@ int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr, | ||||||
| 				     u32 addr, | 				     u32 addr, | ||||||
| 				     u32 *data, u32 flags) | 				     u32 *data, u32 flags) | ||||||
| { | { | ||||||
| 	u8 buf[sizeof(*data)]; | 	u8 buf[sizeof(*data)] = { 0 }; | ||||||
| 	int rc = -EIO; | 	int rc = -EIO; | ||||||
| 	u32 word = 0; | 	u32 word = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -4193,7 +4193,7 @@ int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, | ||||||
| 					 u32 addr, | 					 u32 addr, | ||||||
| 					 u16 *data, u32 flags) | 					 u16 *data, u32 flags) | ||||||
| { | { | ||||||
| 	u8 buf[2]; | 	u8 buf[2] = { 0 }; | ||||||
| 	int rc = -EIO; | 	int rc = -EIO; | ||||||
| 	u16 word = 0; | 	u16 word = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -10667,7 +10667,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod, | ||||||
| 	enum drx_standard standard = ext_attr->standard; | 	enum drx_standard standard = ext_attr->standard; | ||||||
| 	int rc; | 	int rc; | ||||||
| 	u32 ber, cnt, err, pkt; | 	u32 ber, cnt, err, pkt; | ||||||
| 	u16 mer, strength; | 	u16 mer, strength = 0; | ||||||
| 
 | 
 | ||||||
| 	rc = get_sig_strength(demod, &strength); | 	rc = get_sig_strength(demod, &strength); | ||||||
| 	if (rc < 0) { | 	if (rc < 0) { | ||||||
|  | @ -11602,7 +11602,7 @@ static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words) | ||||||
| 	u32 carry = 0; | 	u32 carry = 0; | ||||||
| 
 | 
 | ||||||
| 	while (i < nr_words) { | 	while (i < nr_words) { | ||||||
| 		crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data)); | 		crc_word |= (u32)be16_to_cpu(*(__be16 *)(block_data)); | ||||||
| 		for (j = 0; j < 16; j++) { | 		for (j = 0; j < 16; j++) { | ||||||
| 			crc_word <<= 1; | 			crc_word <<= 1; | ||||||
| 			if (carry != 0) | 			if (carry != 0) | ||||||
|  | @ -11629,7 +11629,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, | ||||||
| 	int i; | 	int i; | ||||||
| 	unsigned count = 2 * sizeof(u16); | 	unsigned count = 2 * sizeof(u16); | ||||||
| 	u32 mc_dev_type, mc_version, mc_base_version; | 	u32 mc_dev_type, mc_version, mc_base_version; | ||||||
| 	u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16))); | 	u16 mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data + sizeof(u16))); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Scan microcode blocks first for version info | 	 * Scan microcode blocks first for version info | ||||||
|  | @ -11647,13 +11647,13 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, | ||||||
| 			goto eof; | 			goto eof; | ||||||
| 
 | 
 | ||||||
| 		/* Process block header */ | 		/* Process block header */ | ||||||
| 		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count)); | 		block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data + count)); | ||||||
| 		count += sizeof(u32); | 		count += sizeof(u32); | ||||||
| 		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count)); | 		block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data + count)); | ||||||
| 		count += sizeof(u16); | 		count += sizeof(u16); | ||||||
| 		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count)); | 		block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data + count)); | ||||||
| 		count += sizeof(u16); | 		count += sizeof(u16); | ||||||
| 		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count)); | 		block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data + count)); | ||||||
| 		count += sizeof(u16); | 		count += sizeof(u16); | ||||||
| 
 | 
 | ||||||
| 		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", | 		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", | ||||||
|  | @ -11667,7 +11667,7 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, | ||||||
| 			if (block_hdr.addr + sizeof(u16) > size) | 			if (block_hdr.addr + sizeof(u16) > size) | ||||||
| 				goto eof; | 				goto eof; | ||||||
| 
 | 
 | ||||||
| 			auxtype = be16_to_cpu(*(u32 *)(auxblk)); | 			auxtype = be16_to_cpu(*(__be16 *)(auxblk)); | ||||||
| 
 | 
 | ||||||
| 			/* Aux block. Check type */ | 			/* Aux block. Check type */ | ||||||
| 			if (DRX_ISMCVERTYPE(auxtype)) { | 			if (DRX_ISMCVERTYPE(auxtype)) { | ||||||
|  | @ -11675,11 +11675,11 @@ static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, | ||||||
| 					goto eof; | 					goto eof; | ||||||
| 
 | 
 | ||||||
| 				auxblk += sizeof(u16); | 				auxblk += sizeof(u16); | ||||||
| 				mc_dev_type = be32_to_cpu(*(u32 *)(auxblk)); | 				mc_dev_type = be32_to_cpu(*(__be32 *)(auxblk)); | ||||||
| 				auxblk += sizeof(u32); | 				auxblk += sizeof(u32); | ||||||
| 				mc_version = be32_to_cpu(*(u32 *)(auxblk)); | 				mc_version = be32_to_cpu(*(__be32 *)(auxblk)); | ||||||
| 				auxblk += sizeof(u32); | 				auxblk += sizeof(u32); | ||||||
| 				mc_base_version = be32_to_cpu(*(u32 *)(auxblk)); | 				mc_base_version = be32_to_cpu(*(__be32 *)(auxblk)); | ||||||
| 
 | 
 | ||||||
| 				DRX_ATTR_MCRECORD(demod).aux_type = auxtype; | 				DRX_ATTR_MCRECORD(demod).aux_type = auxtype; | ||||||
| 				DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type; | 				DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type; | ||||||
|  | @ -11765,9 +11765,9 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod, | ||||||
| 
 | 
 | ||||||
| 	mc_data = (void *)mc_data_init; | 	mc_data = (void *)mc_data_init; | ||||||
| 	/* Check data */ | 	/* Check data */ | ||||||
| 	mc_magic_word = be16_to_cpu(*(u32 *)(mc_data)); | 	mc_magic_word = be16_to_cpu(*(__be16 *)(mc_data)); | ||||||
| 	mc_data += sizeof(u16); | 	mc_data += sizeof(u16); | ||||||
| 	mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data)); | 	mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data)); | ||||||
| 	mc_data += sizeof(u16); | 	mc_data += sizeof(u16); | ||||||
| 
 | 
 | ||||||
| 	if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) { | 	if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) { | ||||||
|  | @ -11791,13 +11791,13 @@ static int drx_ctrl_u_code(struct drx_demod_instance *demod, | ||||||
| 		u16 mc_block_nr_bytes = 0; | 		u16 mc_block_nr_bytes = 0; | ||||||
| 
 | 
 | ||||||
| 		/* Process block header */ | 		/* Process block header */ | ||||||
| 		block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data)); | 		block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data)); | ||||||
| 		mc_data += sizeof(u32); | 		mc_data += sizeof(u32); | ||||||
| 		block_hdr.size = be16_to_cpu(*(u32 *)(mc_data)); | 		block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data)); | ||||||
| 		mc_data += sizeof(u16); | 		mc_data += sizeof(u16); | ||||||
| 		block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data)); | 		block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data)); | ||||||
| 		mc_data += sizeof(u16); | 		mc_data += sizeof(u16); | ||||||
| 		block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data)); | 		block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data)); | ||||||
| 		mc_data += sizeof(u16); | 		mc_data += sizeof(u16); | ||||||
| 
 | 
 | ||||||
| 		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", | 		pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", | ||||||
|  |  | ||||||
|  | @ -2628,10 +2628,11 @@ static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size) | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		/* Apply I2c address patch to B1 */ | 		/* Apply I2c address patch to B1 */ | ||||||
| 		if (!state->type_A && state->m_HiI2cPatch != NULL) | 		if (!state->type_A && state->m_HiI2cPatch != NULL) { | ||||||
| 			status = WriteTable(state, state->m_HiI2cPatch); | 			status = WriteTable(state, state->m_HiI2cPatch); | ||||||
| 			if (status < 0) | 			if (status < 0) | ||||||
| 				break; | 				break; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if (state->type_A) { | 		if (state->type_A) { | ||||||
| 			/* HI firmware patch for UIO readout,
 | 			/* HI firmware patch for UIO readout,
 | ||||||
|  | @ -2830,14 +2831,8 @@ static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status) | ||||||
| static int drxd_init(struct dvb_frontend *fe) | static int drxd_init(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	struct drxd_state *state = fe->demodulator_priv; | 	struct drxd_state *state = fe->demodulator_priv; | ||||||
| 	int err = 0; |  | ||||||
| 
 | 
 | ||||||
| /*	if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */ |  | ||||||
| 	return DRXD_init(state, NULL, 0); | 	return DRXD_init(state, NULL, 0); | ||||||
| 
 |  | ||||||
| 	err = DRXD_init(state, state->fw->data, state->fw->size); |  | ||||||
| 	release_firmware(state->fw); |  | ||||||
| 	return err; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int drxd_config_i2c(struct dvb_frontend *fe, int onoff) | static int drxd_config_i2c(struct dvb_frontend *fe, int onoff) | ||||||
|  |  | ||||||
|  | @ -1028,7 +1028,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) | ||||||
| 		    ((state->m_hi_cfg_ctrl) & | 		    ((state->m_hi_cfg_ctrl) & | ||||||
| 		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == | 		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == | ||||||
| 		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); | 		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); | ||||||
| 	if (powerdown_cmd == false) { | 	if (!powerdown_cmd) { | ||||||
| 		/* Wait until command rdy */ | 		/* Wait until command rdy */ | ||||||
| 		u32 retry_count = 0; | 		u32 retry_count = 0; | ||||||
| 		u16 wait_cmd; | 		u16 wait_cmd; | ||||||
|  | @ -1129,7 +1129,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) | ||||||
| 	if (status < 0) | 	if (status < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	if (mpeg_enable == false) { | 	if (!mpeg_enable) { | ||||||
| 		/*  Set MPEG TS pads to inputmode */ | 		/*  Set MPEG TS pads to inputmode */ | ||||||
| 		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); | 		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); | ||||||
| 		if (status < 0) | 		if (status < 0) | ||||||
|  | @ -1190,7 +1190,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) | ||||||
| 		if (status < 0) | 		if (status < 0) | ||||||
| 			goto error; | 			goto error; | ||||||
| 
 | 
 | ||||||
| 		if (state->m_enable_parallel == true) { | 		if (state->m_enable_parallel) { | ||||||
| 			/* parallel -> enable MD1 to MD7 */ | 			/* parallel -> enable MD1 to MD7 */ | ||||||
| 			status = write16(state, SIO_PDR_MD1_CFG__A, | 			status = write16(state, SIO_PDR_MD1_CFG__A, | ||||||
| 					 sio_pdr_mdx_cfg); | 					 sio_pdr_mdx_cfg); | ||||||
|  | @ -1392,7 +1392,7 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) | ||||||
| 
 | 
 | ||||||
| 	dprintk(1, "\n"); | 	dprintk(1, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (enable == false) { | 	if (!enable) { | ||||||
| 		desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; | 		desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; | ||||||
| 		desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; | 		desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; | ||||||
| 	} | 	} | ||||||
|  | @ -2012,7 +2012,7 @@ static int mpegts_dto_setup(struct drxk_state *state, | ||||||
| 		goto error; | 		goto error; | ||||||
| 	fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); | 	fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); | ||||||
| 	fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); | 	fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); | ||||||
| 	if (state->m_insert_rs_byte == true) { | 	if (state->m_insert_rs_byte) { | ||||||
| 		/* enable parity symbol forward */ | 		/* enable parity symbol forward */ | ||||||
| 		fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; | 		fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; | ||||||
| 		/* MVAL disable during parity bytes */ | 		/* MVAL disable during parity bytes */ | ||||||
|  | @ -2023,7 +2023,7 @@ static int mpegts_dto_setup(struct drxk_state *state, | ||||||
| 
 | 
 | ||||||
| 	/* Check serial or parallel output */ | 	/* Check serial or parallel output */ | ||||||
| 	fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); | 	fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); | ||||||
| 	if (state->m_enable_parallel == false) { | 	if (!state->m_enable_parallel) { | ||||||
| 		/* MPEG data output is serial -> set ipr_mode[0] */ | 		/* MPEG data output is serial -> set ipr_mode[0] */ | ||||||
| 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; | 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; | ||||||
| 	} | 	} | ||||||
|  | @ -2136,19 +2136,19 @@ static int mpegts_configure_polarity(struct drxk_state *state) | ||||||
| 
 | 
 | ||||||
| 	/* Control selective inversion of output bits */ | 	/* Control selective inversion of output bits */ | ||||||
| 	fec_oc_reg_ipr_invert &= (~(invert_data_mask)); | 	fec_oc_reg_ipr_invert &= (~(invert_data_mask)); | ||||||
| 	if (state->m_invert_data == true) | 	if (state->m_invert_data) | ||||||
| 		fec_oc_reg_ipr_invert |= invert_data_mask; | 		fec_oc_reg_ipr_invert |= invert_data_mask; | ||||||
| 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); | 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); | ||||||
| 	if (state->m_invert_err == true) | 	if (state->m_invert_err) | ||||||
| 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; | 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; | ||||||
| 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); | 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); | ||||||
| 	if (state->m_invert_str == true) | 	if (state->m_invert_str) | ||||||
| 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; | 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; | ||||||
| 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); | 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); | ||||||
| 	if (state->m_invert_val == true) | 	if (state->m_invert_val) | ||||||
| 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; | 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; | ||||||
| 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); | 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); | ||||||
| 	if (state->m_invert_clk == true) | 	if (state->m_invert_clk) | ||||||
| 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; | 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; | ||||||
| 
 | 
 | ||||||
| 	return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); | 	return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); | ||||||
|  | @ -2220,12 +2220,13 @@ static int set_agc_rf(struct drxk_state *state, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Set TOP, only if IF-AGC is in AUTO mode */ | 		/* Set TOP, only if IF-AGC is in AUTO mode */ | ||||||
| 		if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) | 		if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) { | ||||||
| 			status = write16(state, | 			status = write16(state, | ||||||
| 					 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, | 					 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, | ||||||
| 					 p_agc_cfg->top); | 					 p_agc_cfg->top); | ||||||
| 			if (status < 0) | 			if (status < 0) | ||||||
| 				goto error; | 				goto error; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Cut-Off current */ | 		/* Cut-Off current */ | ||||||
| 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, | 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, | ||||||
|  | @ -3352,7 +3353,7 @@ static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) | ||||||
| 	int status; | 	int status; | ||||||
| 
 | 
 | ||||||
| 	dprintk(1, "\n"); | 	dprintk(1, "\n"); | ||||||
| 	if (*enabled == true) | 	if (*enabled) | ||||||
| 		status = write16(state, IQM_CF_BYPASSDET__A, 0); | 		status = write16(state, IQM_CF_BYPASSDET__A, 0); | ||||||
| 	else | 	else | ||||||
| 		status = write16(state, IQM_CF_BYPASSDET__A, 1); | 		status = write16(state, IQM_CF_BYPASSDET__A, 1); | ||||||
|  | @ -3368,7 +3369,7 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) | ||||||
| 	int status; | 	int status; | ||||||
| 
 | 
 | ||||||
| 	dprintk(1, "\n"); | 	dprintk(1, "\n"); | ||||||
| 	if (*enabled == true) { | 	if (*enabled) { | ||||||
| 		/* write mask to 1 */ | 		/* write mask to 1 */ | ||||||
| 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, | 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, | ||||||
| 				   DEFAULT_FR_THRES_8K); | 				   DEFAULT_FR_THRES_8K); | ||||||
|  | @ -6794,11 +6795,11 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, | ||||||
| 	state->enable_merr_cfg = config->enable_merr_cfg; | 	state->enable_merr_cfg = config->enable_merr_cfg; | ||||||
| 
 | 
 | ||||||
| 	if (config->dynamic_clk) { | 	if (config->dynamic_clk) { | ||||||
| 		state->m_dvbt_static_clk = 0; | 		state->m_dvbt_static_clk = false; | ||||||
| 		state->m_dvbc_static_clk = 0; | 		state->m_dvbc_static_clk = false; | ||||||
| 	} else { | 	} else { | ||||||
| 		state->m_dvbt_static_clk = 1; | 		state->m_dvbt_static_clk = true; | ||||||
| 		state->m_dvbc_static_clk = 1; | 		state->m_dvbc_static_clk = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -159,6 +159,7 @@ static int m88ds3103_wr_reg_val_tab(struct m88ds3103_priv *priv, | ||||||
| { | { | ||||||
| 	int ret, i, j; | 	int ret, i, j; | ||||||
| 	u8 buf[83]; | 	u8 buf[83]; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); | 	dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len); | ||||||
| 
 | 
 | ||||||
| 	if (tab_len > 83) { | 	if (tab_len > 83) { | ||||||
|  | @ -247,8 +248,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 	u8 u8tmp, u8tmp1, u8tmp2; | 	u8 u8tmp, u8tmp1, u8tmp2; | ||||||
| 	u8 buf[2]; | 	u8 buf[2]; | ||||||
| 	u16 u16tmp, divide_ratio; | 	u16 u16tmp, divide_ratio; | ||||||
| 	u32 tuner_frequency, target_mclk, ts_clk; | 	u32 tuner_frequency, target_mclk; | ||||||
| 	s32 s32tmp; | 	s32 s32tmp; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, | 	dev_dbg(&priv->i2c->dev, | ||||||
| 			"%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", | 			"%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", | ||||||
| 			__func__, c->delivery_system, | 			__func__, c->delivery_system, | ||||||
|  | @ -316,9 +318,6 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 				target_mclk = 144000; | 				target_mclk = 144000; | ||||||
| 			break; | 			break; | ||||||
| 		case M88DS3103_TS_PARALLEL: | 		case M88DS3103_TS_PARALLEL: | ||||||
| 		case M88DS3103_TS_PARALLEL_12: |  | ||||||
| 		case M88DS3103_TS_PARALLEL_16: |  | ||||||
| 		case M88DS3103_TS_PARALLEL_19_2: |  | ||||||
| 		case M88DS3103_TS_CI: | 		case M88DS3103_TS_CI: | ||||||
| 			if (c->symbol_rate < 18000000) | 			if (c->symbol_rate < 18000000) | ||||||
| 				target_mclk = 96000; | 				target_mclk = 96000; | ||||||
|  | @ -352,33 +351,17 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 	switch (priv->cfg->ts_mode) { | 	switch (priv->cfg->ts_mode) { | ||||||
| 	case M88DS3103_TS_SERIAL: | 	case M88DS3103_TS_SERIAL: | ||||||
| 		u8tmp1 = 0x00; | 		u8tmp1 = 0x00; | ||||||
| 		ts_clk = 0; | 		u8tmp = 0x06; | ||||||
| 		u8tmp = 0x46; |  | ||||||
| 		break; | 		break; | ||||||
| 	case M88DS3103_TS_SERIAL_D7: | 	case M88DS3103_TS_SERIAL_D7: | ||||||
| 		u8tmp1 = 0x20; | 		u8tmp1 = 0x20; | ||||||
| 		ts_clk = 0; | 		u8tmp = 0x06; | ||||||
| 		u8tmp = 0x46; |  | ||||||
| 		break; | 		break; | ||||||
| 	case M88DS3103_TS_PARALLEL: | 	case M88DS3103_TS_PARALLEL: | ||||||
| 		ts_clk = 24000; | 		u8tmp = 0x02; | ||||||
| 		u8tmp = 0x42; |  | ||||||
| 		break; |  | ||||||
| 	case M88DS3103_TS_PARALLEL_12: |  | ||||||
| 		ts_clk = 12000; |  | ||||||
| 		u8tmp = 0x42; |  | ||||||
| 		break; |  | ||||||
| 	case M88DS3103_TS_PARALLEL_16: |  | ||||||
| 		ts_clk = 16000; |  | ||||||
| 		u8tmp = 0x42; |  | ||||||
| 		break; |  | ||||||
| 	case M88DS3103_TS_PARALLEL_19_2: |  | ||||||
| 		ts_clk = 19200; |  | ||||||
| 		u8tmp = 0x42; |  | ||||||
| 		break; | 		break; | ||||||
| 	case M88DS3103_TS_CI: | 	case M88DS3103_TS_CI: | ||||||
| 		ts_clk = 6000; | 		u8tmp = 0x03; | ||||||
| 		u8tmp = 0x43; |  | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__); | 		dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__); | ||||||
|  | @ -386,6 +369,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (priv->cfg->ts_clk_pol) | ||||||
|  | 		u8tmp |= 0x40; | ||||||
|  | 
 | ||||||
| 	/* TS mode */ | 	/* TS mode */ | ||||||
| 	ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp); | 	ret = m88ds3103_wr_reg(priv, 0xfd, u8tmp); | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  | @ -399,8 +385,8 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 			goto err; | 			goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (ts_clk) { | 	if (priv->cfg->ts_clk) { | ||||||
| 		divide_ratio = DIV_ROUND_UP(target_mclk, ts_clk); | 		divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk); | ||||||
| 		u8tmp1 = divide_ratio / 2; | 		u8tmp1 = divide_ratio / 2; | ||||||
| 		u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); | 		u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -411,7 +397,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, | 	dev_dbg(&priv->i2c->dev, | ||||||
| 			"%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n", | 			"%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n", | ||||||
| 			__func__, target_mclk, ts_clk, divide_ratio); | 			__func__, target_mclk, priv->cfg->ts_clk, divide_ratio); | ||||||
| 
 | 
 | ||||||
| 	u8tmp1--; | 	u8tmp1--; | ||||||
| 	u8tmp2--; | 	u8tmp2--; | ||||||
|  | @ -536,6 +522,7 @@ static int m88ds3103_init(struct dvb_frontend *fe) | ||||||
| 	const struct firmware *fw = NULL; | 	const struct firmware *fw = NULL; | ||||||
| 	u8 *fw_file = M88DS3103_FIRMWARE; | 	u8 *fw_file = M88DS3103_FIRMWARE; | ||||||
| 	u8 u8tmp; | 	u8 u8tmp; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	/* set cold state by default */ | 	/* set cold state by default */ | ||||||
|  | @ -648,6 +635,7 @@ static int m88ds3103_sleep(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	struct m88ds3103_priv *priv = fe->demodulator_priv; | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	priv->delivery_system = SYS_UNDEFINED; | 	priv->delivery_system = SYS_UNDEFINED; | ||||||
|  | @ -682,6 +670,7 @@ static int m88ds3103_get_frontend(struct dvb_frontend *fe) | ||||||
| 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	u8 buf[3]; | 	u8 buf[3]; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { | 	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { | ||||||
|  | @ -857,6 +846,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr) | ||||||
| 	u8 buf[3]; | 	u8 buf[3]; | ||||||
| 	u16 noise, signal; | 	u16 noise, signal; | ||||||
| 	u32 noise_tot, signal_tot; | 	u32 noise_tot, signal_tot; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||||||
| 	/* reports SNR in resolution of 0.1 dB */ | 	/* reports SNR in resolution of 0.1 dB */ | ||||||
| 
 | 
 | ||||||
|  | @ -933,6 +923,7 @@ static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber) | ||||||
| 	int ret; | 	int ret; | ||||||
| 	unsigned int utmp; | 	unsigned int utmp; | ||||||
| 	u8 buf[3], u8tmp; | 	u8 buf[3], u8tmp; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	switch (c->delivery_system) { | 	switch (c->delivery_system) { | ||||||
|  | @ -1013,6 +1004,7 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe, | ||||||
| 	struct m88ds3103_priv *priv = fe->demodulator_priv; | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	u8 u8tmp, tone, reg_a1_mask; | 	u8 u8tmp, tone, reg_a1_mask; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__, | 	dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__, | ||||||
| 			fe_sec_tone_mode); | 			fe_sec_tone_mode); | ||||||
| 
 | 
 | ||||||
|  | @ -1053,12 +1045,64 @@ err: | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int m88ds3103_set_voltage(struct dvb_frontend *fe, | ||||||
|  | 	fe_sec_voltage_t fe_sec_voltage) | ||||||
|  | { | ||||||
|  | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
|  | 	int ret; | ||||||
|  | 	u8 u8tmp; | ||||||
|  | 	bool voltage_sel, voltage_dis; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__, | ||||||
|  | 			fe_sec_voltage); | ||||||
|  | 
 | ||||||
|  | 	if (!priv->warm) { | ||||||
|  | 		ret = -EAGAIN; | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (fe_sec_voltage) { | ||||||
|  | 	case SEC_VOLTAGE_18: | ||||||
|  | 		voltage_sel = true; | ||||||
|  | 		voltage_dis = false; | ||||||
|  | 		break; | ||||||
|  | 	case SEC_VOLTAGE_13: | ||||||
|  | 		voltage_sel = false; | ||||||
|  | 		voltage_dis = false; | ||||||
|  | 		break; | ||||||
|  | 	case SEC_VOLTAGE_OFF: | ||||||
|  | 		voltage_sel = false; | ||||||
|  | 		voltage_dis = true; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n", | ||||||
|  | 				__func__); | ||||||
|  | 		ret = -EINVAL; | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* output pin polarity */ | ||||||
|  | 	voltage_sel ^= priv->cfg->lnb_hv_pol; | ||||||
|  | 	voltage_dis ^= priv->cfg->lnb_en_pol; | ||||||
|  | 
 | ||||||
|  | 	u8tmp = voltage_dis << 1 | voltage_sel << 0; | ||||||
|  | 	ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0x03); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | err: | ||||||
|  | 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, | static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||||||
| 		struct dvb_diseqc_master_cmd *diseqc_cmd) | 		struct dvb_diseqc_master_cmd *diseqc_cmd) | ||||||
| { | { | ||||||
| 	struct m88ds3103_priv *priv = fe->demodulator_priv; | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 	u8 u8tmp; | 	u8 u8tmp; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__, | 	dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__, | ||||||
| 			diseqc_cmd->msg_len, diseqc_cmd->msg); | 			diseqc_cmd->msg_len, diseqc_cmd->msg); | ||||||
| 
 | 
 | ||||||
|  | @ -1130,6 +1174,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, | ||||||
| 	struct m88ds3103_priv *priv = fe->demodulator_priv; | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 	u8 u8tmp, burst; | 	u8 u8tmp, burst; | ||||||
|  | 
 | ||||||
| 	dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, | 	dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, | ||||||
| 			fe_sec_mini_cmd); | 			fe_sec_mini_cmd); | ||||||
| 
 | 
 | ||||||
|  | @ -1202,6 +1247,7 @@ static int m88ds3103_get_tune_settings(struct dvb_frontend *fe, | ||||||
| static void m88ds3103_release(struct dvb_frontend *fe) | static void m88ds3103_release(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	struct m88ds3103_priv *priv = fe->demodulator_priv; | 	struct m88ds3103_priv *priv = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
| 	i2c_del_mux_adapter(priv->i2c_adapter); | 	i2c_del_mux_adapter(priv->i2c_adapter); | ||||||
| 	kfree(priv); | 	kfree(priv); | ||||||
| } | } | ||||||
|  | @ -1370,6 +1416,7 @@ static struct dvb_frontend_ops m88ds3103_ops = { | ||||||
| 	.diseqc_send_burst = m88ds3103_diseqc_send_burst, | 	.diseqc_send_burst = m88ds3103_diseqc_send_burst, | ||||||
| 
 | 
 | ||||||
| 	.set_tone = m88ds3103_set_tone, | 	.set_tone = m88ds3103_set_tone, | ||||||
|  | 	.set_voltage = m88ds3103_set_voltage, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||||||
|  |  | ||||||
|  | @ -47,13 +47,22 @@ struct m88ds3103_config { | ||||||
| 	 */ | 	 */ | ||||||
| #define M88DS3103_TS_SERIAL             0 /* TS output pin D0, normal */ | #define M88DS3103_TS_SERIAL             0 /* TS output pin D0, normal */ | ||||||
| #define M88DS3103_TS_SERIAL_D7          1 /* TS output pin D7 */ | #define M88DS3103_TS_SERIAL_D7          1 /* TS output pin D7 */ | ||||||
| #define M88DS3103_TS_PARALLEL           2 /* 24 MHz, normal */ | #define M88DS3103_TS_PARALLEL           2 /* TS Parallel mode */ | ||||||
| #define M88DS3103_TS_PARALLEL_12        3 /* 12 MHz */ | #define M88DS3103_TS_CI                 3 /* TS CI Mode */ | ||||||
| #define M88DS3103_TS_PARALLEL_16        4 /* 16 MHz */ |  | ||||||
| #define M88DS3103_TS_PARALLEL_19_2      5 /* 19.2 MHz */ |  | ||||||
| #define M88DS3103_TS_CI                 6 /* 6 MHz */ |  | ||||||
| 	u8 ts_mode; | 	u8 ts_mode; | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * TS clk in KHz | ||||||
|  | 	 * Default: 0. | ||||||
|  | 	 */ | ||||||
|  | 	u32 ts_clk; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * TS clk polarity. | ||||||
|  | 	 * Default: 0. 1-active at falling edge; 0-active at rising edge. | ||||||
|  | 	 */ | ||||||
|  | 	u8 ts_clk_pol:1; | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * spectrum inversion | 	 * spectrum inversion | ||||||
| 	 * Default: 0 | 	 * Default: 0 | ||||||
|  | @ -86,6 +95,22 @@ struct m88ds3103_config { | ||||||
| 	 * Default: none, must set | 	 * Default: none, must set | ||||||
| 	 */ | 	 */ | ||||||
| 	u8 agc; | 	u8 agc; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * LNB H/V pin polarity | ||||||
|  | 	 * Default: 0. | ||||||
|  | 	 * 1: pin high set to VOLTAGE_13, pin low to set VOLTAGE_18. | ||||||
|  | 	 * 0: pin high set to VOLTAGE_18, pin low to set VOLTAGE_13. | ||||||
|  | 	 */ | ||||||
|  | 	u8 lnb_hv_pol:1; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * LNB enable pin polarity | ||||||
|  | 	 * Default: 0. | ||||||
|  | 	 * 1: pin high to enable, pin low to disable. | ||||||
|  | 	 * 0: pin high to disable, pin low to enable. | ||||||
|  | 	 */ | ||||||
|  | 	u8 lnb_en_pol:1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
| #include "mb86a16.h" | #include "mb86a16.h" | ||||||
| #include "mb86a16_priv.h" | #include "mb86a16_priv.h" | ||||||
| 
 | 
 | ||||||
| unsigned int verbose = 5; | static unsigned int verbose = 5; | ||||||
| module_param(verbose, int, 0644); | module_param(verbose, int, 0644); | ||||||
| 
 | 
 | ||||||
| #define ABS(x)		((x) < 0 ? (-x) : (x)) | #define ABS(x)		((x) < 0 ? (-x) : (x)) | ||||||
|  | @ -115,9 +115,11 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) | ||||||
| 	}; | 	}; | ||||||
| 	ret = i2c_transfer(state->i2c_adap, msg, 2); | 	ret = i2c_transfer(state->i2c_adap, msg, 2); | ||||||
| 	if (ret != 2) { | 	if (ret != 2) { | ||||||
| 		dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", | 		dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=%i)", | ||||||
| 			reg, ret); | 			reg, ret); | ||||||
| 
 | 
 | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			return ret; | ||||||
| 		return -EREMOTEIO; | 		return -EREMOTEIO; | ||||||
| 	} | 	} | ||||||
| 	*val = b1[0]; | 	*val = b1[0]; | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ enum mb86a20s_bandwidth { | ||||||
| 	MB86A20S_3SEG = 3, | 	MB86A20S_3SEG = 3, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| u8 mb86a20s_subchannel[] = { | static u8 mb86a20s_subchannel[] = { | ||||||
| 	0xb0, 0xc0, 0xd0, 0xe0, | 	0xb0, 0xc0, 0xd0, 0xe0, | ||||||
| 	0xf0, 0x00, 0x10, 0x20, | 	0xf0, 0x00, 0x10, 0x20, | ||||||
| }; | }; | ||||||
|  | @ -1228,7 +1228,7 @@ struct linear_segments { | ||||||
|  * All tables below return a dB/1000 measurement |  * All tables below return a dB/1000 measurement | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static struct linear_segments cnr_to_db_table[] = { | static const struct linear_segments cnr_to_db_table[] = { | ||||||
| 	{ 19648,     0}, | 	{ 19648,     0}, | ||||||
| 	{ 18187,  1000}, | 	{ 18187,  1000}, | ||||||
| 	{ 16534,  2000}, | 	{ 16534,  2000}, | ||||||
|  | @ -1262,7 +1262,7 @@ static struct linear_segments cnr_to_db_table[] = { | ||||||
| 	{   788, 30000}, | 	{   788, 30000}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static struct linear_segments cnr_64qam_table[] = { | static const struct linear_segments cnr_64qam_table[] = { | ||||||
| 	{ 3922688,     0}, | 	{ 3922688,     0}, | ||||||
| 	{ 3920384,  1000}, | 	{ 3920384,  1000}, | ||||||
| 	{ 3902720,  2000}, | 	{ 3902720,  2000}, | ||||||
|  | @ -1296,7 +1296,7 @@ static struct linear_segments cnr_64qam_table[] = { | ||||||
| 	{  388864, 30000}, | 	{  388864, 30000}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static struct linear_segments cnr_16qam_table[] = { | static const struct linear_segments cnr_16qam_table[] = { | ||||||
| 	{ 5314816,     0}, | 	{ 5314816,     0}, | ||||||
| 	{ 5219072,  1000}, | 	{ 5219072,  1000}, | ||||||
| 	{ 5118720,  2000}, | 	{ 5118720,  2000}, | ||||||
|  | @ -1330,7 +1330,7 @@ static struct linear_segments cnr_16qam_table[] = { | ||||||
| 	{   95744, 30000}, | 	{   95744, 30000}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct linear_segments cnr_qpsk_table[] = { | static const struct linear_segments cnr_qpsk_table[] = { | ||||||
| 	{ 2834176,     0}, | 	{ 2834176,     0}, | ||||||
| 	{ 2683648,  1000}, | 	{ 2683648,  1000}, | ||||||
| 	{ 2536960,  2000}, | 	{ 2536960,  2000}, | ||||||
|  | @ -1364,7 +1364,7 @@ struct linear_segments cnr_qpsk_table[] = { | ||||||
| 	{   11520, 30000}, | 	{   11520, 30000}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static u32 interpolate_value(u32 value, struct linear_segments *segments, | static u32 interpolate_value(u32 value, const struct linear_segments *segments, | ||||||
| 			     unsigned len) | 			     unsigned len) | ||||||
| { | { | ||||||
| 	u64 tmp64; | 	u64 tmp64; | ||||||
|  | @ -1448,7 +1448,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) | ||||||
| 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||||
| 	u32 mer, cnr; | 	u32 mer, cnr; | ||||||
| 	int rc, val, layer; | 	int rc, val, layer; | ||||||
| 	struct linear_segments *segs; | 	const struct linear_segments *segs; | ||||||
| 	unsigned segs_len; | 	unsigned segs_len; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 	dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | ||||||
|  |  | ||||||
|  | @ -103,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, | ||||||
| 
 | 
 | ||||||
| 	if (1 + count > sizeof(buf)) { | 	if (1 + count > sizeof(buf)) { | ||||||
| 		printk(KERN_WARNING | 		printk(KERN_WARNING | ||||||
| 		       "mt312: write: len=%zd is too big!\n", count); | 		       "mt312: write: len=%zu is too big!\n", count); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe, | ||||||
| 	u8 tudata[585]; | 	u8 tudata[585]; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	dprintk("Firmware is %zd bytes\n",fw->size); | 	dprintk("Firmware is %zu bytes\n", fw->size); | ||||||
| 
 | 
 | ||||||
| 	/* Get eprom data */ | 	/* Get eprom data */ | ||||||
| 	tudata[0] = 17; | 	tudata[0] = 17; | ||||||
|  |  | ||||||
|  | @ -936,7 +936,7 @@ static void rtl2832_i2c_gate_work(struct work_struct *work) | ||||||
| 	if (ret != 1) | 	if (ret != 1) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	priv->i2c_gate_state = 0; | 	priv->i2c_gate_state = false; | ||||||
| 
 | 
 | ||||||
| 	return; | 	return; | ||||||
| err: | err: | ||||||
|  |  | ||||||
|  | @ -329,7 +329,7 @@ static int rtl2832_sdr_rd_reg_mask(struct rtl2832_sdr_state *s, u16 reg, | ||||||
| static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( | static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf( | ||||||
| 		struct rtl2832_sdr_state *s) | 		struct rtl2832_sdr_state *s) | ||||||
| { | { | ||||||
| 	unsigned long flags = 0; | 	unsigned long flags; | ||||||
| 	struct rtl2832_sdr_frame_buf *buf = NULL; | 	struct rtl2832_sdr_frame_buf *buf = NULL; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&s->queued_bufs_lock, flags); | 	spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||||||
|  | @ -365,17 +365,19 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s, | ||||||
| 		dst_len = 0; | 		dst_len = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* calculate samping rate and output it in 10 seconds intervals */ | 	/* calculate sample rate and output it in 10 seconds intervals */ | ||||||
| 	if (unlikely(time_is_before_jiffies(s->jiffies_next))) { | 	if (unlikely(time_is_before_jiffies(s->jiffies_next))) { | ||||||
| #define MSECS 10000UL | 		#define MSECS 10000UL | ||||||
|  | 		unsigned int msecs = jiffies_to_msecs(jiffies - | ||||||
|  | 				s->jiffies_next + msecs_to_jiffies(MSECS)); | ||||||
| 		unsigned int samples = s->sample - s->sample_measured; | 		unsigned int samples = s->sample - s->sample_measured; | ||||||
| 
 | 
 | ||||||
| 		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); | 		s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); | ||||||
| 		s->sample_measured = s->sample; | 		s->sample_measured = s->sample; | ||||||
| 		dev_dbg(&s->udev->dev, | 		dev_dbg(&s->udev->dev, | ||||||
| 				"slen=%d samples=%u msecs=%lu sampling rate=%lu\n", | 				"slen=%u samples=%u msecs=%u sample rate=%lu\n", | ||||||
| 				src_len, samples, MSECS, | 				src_len, samples, msecs, | ||||||
| 				samples * 1000UL / MSECS); | 				samples * 1000UL / msecs); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* total number of I+Q pairs */ | 	/* total number of I+Q pairs */ | ||||||
|  | @ -394,8 +396,8 @@ static void rtl2832_sdr_urb_complete(struct urb *urb) | ||||||
| 	struct rtl2832_sdr_frame_buf *fbuf; | 	struct rtl2832_sdr_frame_buf *fbuf; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg_ratelimited(&s->udev->dev, | 	dev_dbg_ratelimited(&s->udev->dev, | ||||||
| 			"%s: status=%d length=%d/%d errors=%d\n", | 			"status=%d length=%d/%d errors=%d\n", | ||||||
| 			__func__, urb->status, urb->actual_length, | 			urb->status, urb->actual_length, | ||||||
| 			urb->transfer_buffer_length, urb->error_count); | 			urb->transfer_buffer_length, urb->error_count); | ||||||
| 
 | 
 | ||||||
| 	switch (urb->status) { | 	switch (urb->status) { | ||||||
|  | @ -443,7 +445,7 @@ static int rtl2832_sdr_kill_urbs(struct rtl2832_sdr_state *s) | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = s->urbs_submitted - 1; i >= 0; i--) { | 	for (i = s->urbs_submitted - 1; i >= 0; i--) { | ||||||
| 		dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i); | 		dev_dbg(&s->udev->dev, "kill urb=%d\n", i); | ||||||
| 		/* stop the URB */ | 		/* stop the URB */ | ||||||
| 		usb_kill_urb(s->urb_list[i]); | 		usb_kill_urb(s->urb_list[i]); | ||||||
| 	} | 	} | ||||||
|  | @ -457,7 +459,7 @@ static int rtl2832_sdr_submit_urbs(struct rtl2832_sdr_state *s) | ||||||
| 	int i, ret; | 	int i, ret; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < s->urbs_initialized; i++) { | 	for (i = 0; i < s->urbs_initialized; i++) { | ||||||
| 		dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i); | 		dev_dbg(&s->udev->dev, "submit urb=%d\n", i); | ||||||
| 		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); | 		ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			dev_err(&s->udev->dev, | 			dev_err(&s->udev->dev, | ||||||
|  | @ -477,8 +479,7 @@ static int rtl2832_sdr_free_stream_bufs(struct rtl2832_sdr_state *s) | ||||||
| 	if (s->flags & USB_STATE_URB_BUF) { | 	if (s->flags & USB_STATE_URB_BUF) { | ||||||
| 		while (s->buf_num) { | 		while (s->buf_num) { | ||||||
| 			s->buf_num--; | 			s->buf_num--; | ||||||
| 			dev_dbg(&s->udev->dev, "%s: free buf=%d\n", | 			dev_dbg(&s->udev->dev, "free buf=%d\n", s->buf_num); | ||||||
| 					__func__, s->buf_num); |  | ||||||
| 			usb_free_coherent(s->udev, s->buf_size, | 			usb_free_coherent(s->udev, s->buf_size, | ||||||
| 					  s->buf_list[s->buf_num], | 					  s->buf_list[s->buf_num], | ||||||
| 					  s->dma_addr[s->buf_num]); | 					  s->dma_addr[s->buf_num]); | ||||||
|  | @ -494,24 +495,22 @@ static int rtl2832_sdr_alloc_stream_bufs(struct rtl2832_sdr_state *s) | ||||||
| 	s->buf_num = 0; | 	s->buf_num = 0; | ||||||
| 	s->buf_size = BULK_BUFFER_SIZE; | 	s->buf_size = BULK_BUFFER_SIZE; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, | 	dev_dbg(&s->udev->dev, "all in all I will use %u bytes for streaming\n", | ||||||
| 			"%s: all in all I will use %u bytes for streaming\n", | 			MAX_BULK_BUFS * BULK_BUFFER_SIZE); | ||||||
| 			__func__,  MAX_BULK_BUFS * BULK_BUFFER_SIZE); |  | ||||||
| 
 | 
 | ||||||
| 	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { | 	for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { | ||||||
| 		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, | 		s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, | ||||||
| 				BULK_BUFFER_SIZE, GFP_ATOMIC, | 				BULK_BUFFER_SIZE, GFP_ATOMIC, | ||||||
| 				&s->dma_addr[s->buf_num]); | 				&s->dma_addr[s->buf_num]); | ||||||
| 		if (!s->buf_list[s->buf_num]) { | 		if (!s->buf_list[s->buf_num]) { | ||||||
| 			dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n", | 			dev_dbg(&s->udev->dev, "alloc buf=%d failed\n", | ||||||
| 					__func__, s->buf_num); | 					s->buf_num); | ||||||
| 			rtl2832_sdr_free_stream_bufs(s); | 			rtl2832_sdr_free_stream_bufs(s); | ||||||
| 			return -ENOMEM; | 			return -ENOMEM; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", | 		dev_dbg(&s->udev->dev, "alloc buf=%d %p (dma %llu)\n", | ||||||
| 				__func__, s->buf_num, | 				s->buf_num, s->buf_list[s->buf_num], | ||||||
| 				s->buf_list[s->buf_num], |  | ||||||
| 				(long long)s->dma_addr[s->buf_num]); | 				(long long)s->dma_addr[s->buf_num]); | ||||||
| 		s->flags |= USB_STATE_URB_BUF; | 		s->flags |= USB_STATE_URB_BUF; | ||||||
| 	} | 	} | ||||||
|  | @ -527,8 +526,7 @@ static int rtl2832_sdr_free_urbs(struct rtl2832_sdr_state *s) | ||||||
| 
 | 
 | ||||||
| 	for (i = s->urbs_initialized - 1; i >= 0; i--) { | 	for (i = s->urbs_initialized - 1; i >= 0; i--) { | ||||||
| 		if (s->urb_list[i]) { | 		if (s->urb_list[i]) { | ||||||
| 			dev_dbg(&s->udev->dev, "%s: free urb=%d\n", | 			dev_dbg(&s->udev->dev, "free urb=%d\n", i); | ||||||
| 					__func__, i); |  | ||||||
| 			/* free the URBs */ | 			/* free the URBs */ | ||||||
| 			usb_free_urb(s->urb_list[i]); | 			usb_free_urb(s->urb_list[i]); | ||||||
| 		} | 		} | ||||||
|  | @ -544,10 +542,10 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) | ||||||
| 
 | 
 | ||||||
| 	/* allocate the URBs */ | 	/* allocate the URBs */ | ||||||
| 	for (i = 0; i < MAX_BULK_BUFS; i++) { | 	for (i = 0; i < MAX_BULK_BUFS; i++) { | ||||||
| 		dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i); | 		dev_dbg(&s->udev->dev, "alloc urb=%d\n", i); | ||||||
| 		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); | 		s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); | ||||||
| 		if (!s->urb_list[i]) { | 		if (!s->urb_list[i]) { | ||||||
| 			dev_dbg(&s->udev->dev, "%s: failed\n", __func__); | 			dev_dbg(&s->udev->dev, "failed\n"); | ||||||
| 			for (j = 0; j < i; j++) | 			for (j = 0; j < i; j++) | ||||||
| 				usb_free_urb(s->urb_list[j]); | 				usb_free_urb(s->urb_list[j]); | ||||||
| 			return -ENOMEM; | 			return -ENOMEM; | ||||||
|  | @ -570,9 +568,9 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s) | ||||||
| /* Must be called with vb_queue_lock hold */ | /* Must be called with vb_queue_lock hold */ | ||||||
| static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) | static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s) | ||||||
| { | { | ||||||
| 	unsigned long flags = 0; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&s->queued_bufs_lock, flags); | 	spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||||||
| 	while (!list_empty(&s->queued_bufs)) { | 	while (!list_empty(&s->queued_bufs)) { | ||||||
|  | @ -591,7 +589,7 @@ static void rtl2832_sdr_release_sec(struct dvb_frontend *fe) | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = fe->sec_priv; | 	struct rtl2832_sdr_state *s = fe->sec_priv; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&s->vb_queue_lock); | 	mutex_lock(&s->vb_queue_lock); | ||||||
| 	mutex_lock(&s->v4l2_lock); | 	mutex_lock(&s->v4l2_lock); | ||||||
|  | @ -613,7 +611,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | 	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | ||||||
| 	strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); | 	strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); | ||||||
|  | @ -631,15 +629,15 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); | 	dev_dbg(&s->udev->dev, "nbuffers=%d\n", *nbuffers); | ||||||
| 
 | 
 | ||||||
| 	/* Need at least 8 buffers */ | 	/* Need at least 8 buffers */ | ||||||
| 	if (vq->num_buffers + *nbuffers < 8) | 	if (vq->num_buffers + *nbuffers < 8) | ||||||
| 		*nbuffers = 8 - vq->num_buffers; | 		*nbuffers = 8 - vq->num_buffers; | ||||||
| 	*nplanes = 1; | 	*nplanes = 1; | ||||||
| 	sizes[0] = PAGE_ALIGN(s->buffersize); | 	sizes[0] = PAGE_ALIGN(s->buffersize); | ||||||
| 	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", | 	dev_dbg(&s->udev->dev, "nbuffers=%d sizes[0]=%d\n", | ||||||
| 			__func__, *nbuffers, sizes[0]); | 			*nbuffers, sizes[0]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -659,7 +657,7 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb) | ||||||
| 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); | 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue); | ||||||
| 	struct rtl2832_sdr_frame_buf *buf = | 	struct rtl2832_sdr_frame_buf *buf = | ||||||
| 			container_of(vb, struct rtl2832_sdr_frame_buf, vb); | 			container_of(vb, struct rtl2832_sdr_frame_buf, vb); | ||||||
| 	unsigned long flags = 0; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	/* Check the device has not disconnected between prep and queuing */ | 	/* Check the device has not disconnected between prep and queuing */ | ||||||
| 	if (!s->udev) { | 	if (!s->udev) { | ||||||
|  | @ -681,7 +679,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) | ||||||
| 	u64 u64tmp; | 	u64 u64tmp; | ||||||
| 	u32 u32tmp; | 	u32 u32tmp; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc); | 	dev_dbg(&s->udev->dev, "f_adc=%u\n", s->f_adc); | ||||||
| 
 | 
 | ||||||
| 	if (!test_bit(POWER_ON, &s->flags)) | 	if (!test_bit(POWER_ON, &s->flags)) | ||||||
| 		return 0; | 		return 0; | ||||||
|  | @ -715,8 +713,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s) | ||||||
| 	u64tmp = -u64tmp; | 	u64tmp = -u64tmp; | ||||||
| 	u32tmp = u64tmp & 0x3fffff; | 	u32tmp = u64tmp & 0x3fffff; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: f_if=%u if_ctl=%08x\n", | 	dev_dbg(&s->udev->dev, "f_if=%u if_ctl=%08x\n", f_if, u32tmp); | ||||||
| 			__func__, f_if, u32tmp); |  | ||||||
| 
 | 
 | ||||||
| 	buf[0] = (u32tmp >> 16) & 0xff; | 	buf[0] = (u32tmp >> 16) & 0xff; | ||||||
| 	buf[1] = (u32tmp >>  8) & 0xff; | 	buf[1] = (u32tmp >>  8) & 0xff; | ||||||
|  | @ -903,7 +900,7 @@ static void rtl2832_sdr_unset_adc(struct rtl2832_sdr_state *s) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	/* PID filter */ | 	/* PID filter */ | ||||||
| 	ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1); | 	ret = rtl2832_sdr_wr_regs(s, 0x061, "\xe0", 1); | ||||||
|  | @ -964,8 +961,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s) | ||||||
| 	c->frequency = s->f_tuner; | 	c->frequency = s->f_tuner; | ||||||
| 	c->delivery_system = SYS_DVBT; | 	c->delivery_system = SYS_DVBT; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: frequency=%u bandwidth=%d\n", | 	dev_dbg(&s->udev->dev, "frequency=%u bandwidth=%d\n", | ||||||
| 			__func__, c->frequency, c->bandwidth_hz); | 			c->frequency, c->bandwidth_hz); | ||||||
| 
 | 
 | ||||||
| 	if (!test_bit(POWER_ON, &s->flags)) | 	if (!test_bit(POWER_ON, &s->flags)) | ||||||
| 		return 0; | 		return 0; | ||||||
|  | @ -980,7 +977,7 @@ static int rtl2832_sdr_set_tuner(struct rtl2832_sdr_state *s) | ||||||
| { | { | ||||||
| 	struct dvb_frontend *fe = s->fe; | 	struct dvb_frontend *fe = s->fe; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (fe->ops.tuner_ops.init) | 	if (fe->ops.tuner_ops.init) | ||||||
| 		fe->ops.tuner_ops.init(fe); | 		fe->ops.tuner_ops.init(fe); | ||||||
|  | @ -992,7 +989,7 @@ static void rtl2832_sdr_unset_tuner(struct rtl2832_sdr_state *s) | ||||||
| { | { | ||||||
| 	struct dvb_frontend *fe = s->fe; | 	struct dvb_frontend *fe = s->fe; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (fe->ops.tuner_ops.sleep) | 	if (fe->ops.tuner_ops.sleep) | ||||||
| 		fe->ops.tuner_ops.sleep(fe); | 		fe->ops.tuner_ops.sleep(fe); | ||||||
|  | @ -1005,7 +1002,7 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) | ||||||
| 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (!s->udev) | 	if (!s->udev) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
|  | @ -1054,7 +1051,7 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq) | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&s->v4l2_lock); | 	mutex_lock(&s->v4l2_lock); | ||||||
| 
 | 
 | ||||||
|  | @ -1088,8 +1085,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n", | 	dev_dbg(&s->udev->dev, "index=%d type=%d\n", v->index, v->type); | ||||||
| 			__func__, v->index, v->type); |  | ||||||
| 
 | 
 | ||||||
| 	if (v->index == 0) { | 	if (v->index == 0) { | ||||||
| 		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); | 		strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); | ||||||
|  | @ -1115,7 +1111,7 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (v->index > 1) | 	if (v->index > 1) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -1127,8 +1123,8 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", | 	dev_dbg(&s->udev->dev, "tuner=%d type=%d index=%d\n", | ||||||
| 			__func__, band->tuner, band->type, band->index); | 			band->tuner, band->type, band->index); | ||||||
| 
 | 
 | ||||||
| 	if (band->tuner == 0) { | 	if (band->tuner == 0) { | ||||||
| 		if (band->index >= ARRAY_SIZE(bands_adc)) | 		if (band->index >= ARRAY_SIZE(bands_adc)) | ||||||
|  | @ -1153,8 +1149,8 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv, | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 	int ret  = 0; | 	int ret  = 0; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", | 	dev_dbg(&s->udev->dev, "tuner=%d type=%d\n", | ||||||
| 			__func__, f->tuner, f->type); | 			f->tuner, f->type); | ||||||
| 
 | 
 | ||||||
| 	if (f->tuner == 0) { | 	if (f->tuner == 0) { | ||||||
| 		f->frequency = s->f_adc; | 		f->frequency = s->f_adc; | ||||||
|  | @ -1175,8 +1171,8 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 	int ret, band; | 	int ret, band; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", | 	dev_dbg(&s->udev->dev, "tuner=%d type=%d frequency=%u\n", | ||||||
| 			__func__, f->tuner, f->type, f->frequency); | 			f->tuner, f->type, f->frequency); | ||||||
| 
 | 
 | ||||||
| 	/* ADC band midpoints */ | 	/* ADC band midpoints */ | ||||||
| 	#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2) | 	#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2) | ||||||
|  | @ -1194,15 +1190,13 @@ static int rtl2832_sdr_s_frequency(struct file *file, void *priv, | ||||||
| 				bands_adc[band].rangelow, | 				bands_adc[band].rangelow, | ||||||
| 				bands_adc[band].rangehigh); | 				bands_adc[band].rangehigh); | ||||||
| 
 | 
 | ||||||
| 		dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", | 		dev_dbg(&s->udev->dev, "ADC frequency=%u Hz\n", s->f_adc); | ||||||
| 				__func__, s->f_adc); |  | ||||||
| 		ret = rtl2832_sdr_set_adc(s); | 		ret = rtl2832_sdr_set_adc(s); | ||||||
| 	} else if (f->tuner == 1) { | 	} else if (f->tuner == 1) { | ||||||
| 		s->f_tuner = clamp_t(unsigned int, f->frequency, | 		s->f_tuner = clamp_t(unsigned int, f->frequency, | ||||||
| 				bands_fm[0].rangelow, | 				bands_fm[0].rangelow, | ||||||
| 				bands_fm[0].rangehigh); | 				bands_fm[0].rangehigh); | ||||||
| 		dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n", | 		dev_dbg(&s->udev->dev, "RF frequency=%u Hz\n", f->frequency); | ||||||
| 				__func__, f->frequency); |  | ||||||
| 
 | 
 | ||||||
| 		ret = rtl2832_sdr_set_tuner_freq(s); | 		ret = rtl2832_sdr_set_tuner_freq(s); | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -1217,7 +1211,7 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (f->index >= s->num_formats) | 	if (f->index >= s->num_formats) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -1233,7 +1227,7 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv, | ||||||
| { | { | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s:\n", __func__); | 	dev_dbg(&s->udev->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	f->fmt.sdr.pixelformat = s->pixelformat; | 	f->fmt.sdr.pixelformat = s->pixelformat; | ||||||
| 	f->fmt.sdr.buffersize = s->buffersize; | 	f->fmt.sdr.buffersize = s->buffersize; | ||||||
|  | @ -1250,7 +1244,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv, | ||||||
| 	struct vb2_queue *q = &s->vb_queue; | 	struct vb2_queue *q = &s->vb_queue; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | 	dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", | ||||||
| 			(char *)&f->fmt.sdr.pixelformat); | 			(char *)&f->fmt.sdr.pixelformat); | ||||||
| 
 | 
 | ||||||
| 	if (vb2_is_busy(q)) | 	if (vb2_is_busy(q)) | ||||||
|  | @ -1280,7 +1274,7 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv, | ||||||
| 	struct rtl2832_sdr_state *s = video_drvdata(file); | 	struct rtl2832_sdr_state *s = video_drvdata(file); | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | 	dev_dbg(&s->udev->dev, "pixelformat fourcc %4.4s\n", | ||||||
| 			(char *)&f->fmt.sdr.pixelformat); | 			(char *)&f->fmt.sdr.pixelformat); | ||||||
| 
 | 
 | ||||||
| 	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | 	memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||||||
|  | @ -1354,8 +1348,8 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->udev->dev, | 	dev_dbg(&s->udev->dev, | ||||||
| 			"%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", | 			"id=%d name=%s val=%d min=%lld max=%lld step=%lld\n", | ||||||
| 			__func__, ctrl->id, ctrl->name, ctrl->val, | 			ctrl->id, ctrl->name, ctrl->val, | ||||||
| 			ctrl->minimum, ctrl->maximum, ctrl->step); | 			ctrl->minimum, ctrl->maximum, ctrl->step); | ||||||
| 
 | 
 | ||||||
| 	switch (ctrl->id) { | 	switch (ctrl->id) { | ||||||
|  | @ -1432,7 +1426,7 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe, | ||||||
| 	s->pixelformat = formats[0].pixelformat; | 	s->pixelformat = formats[0].pixelformat; | ||||||
| 	s->buffersize = formats[0].buffersize; | 	s->buffersize = formats[0].buffersize; | ||||||
| 	s->num_formats = NUM_FORMATS; | 	s->num_formats = NUM_FORMATS; | ||||||
| 	if (rtl2832_sdr_emulated_fmt == false) | 	if (!rtl2832_sdr_emulated_fmt) | ||||||
| 		s->num_formats -= 1; | 		s->num_formats -= 1; | ||||||
| 
 | 
 | ||||||
| 	mutex_init(&s->v4l2_lock); | 	mutex_init(&s->v4l2_lock); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| /*
 | /*
 | ||||||
|     Driver for Silicon Labs SI2165 DVB-C/-T Demodulator |     Driver for Silicon Labs Si2161 DVB-T and Si2165 DVB-C/-T Demodulator | ||||||
| 
 | 
 | ||||||
|     Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org> |     Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org> | ||||||
| 
 | 
 | ||||||
|  | @ -44,9 +44,7 @@ struct si2165_state { | ||||||
| 
 | 
 | ||||||
| 	struct si2165_config config; | 	struct si2165_config config; | ||||||
| 
 | 
 | ||||||
| 	/* chip revision */ | 	u8 chip_revcode; | ||||||
| 	u8 revcode; |  | ||||||
| 	/* chip type */ |  | ||||||
| 	u8 chip_type; | 	u8 chip_type; | ||||||
| 
 | 
 | ||||||
| 	/* calculated by xtal and div settings */ | 	/* calculated by xtal and div settings */ | ||||||
|  | @ -312,7 +310,7 @@ static u32 si2165_get_fe_clk(struct si2165_state *state) | ||||||
| 	return state->adc_clk; | 	return state->adc_clk; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool si2165_wait_init_done(struct si2165_state *state) | static int si2165_wait_init_done(struct si2165_state *state) | ||||||
| { | { | ||||||
| 	int ret = -EINVAL; | 	int ret = -EINVAL; | ||||||
| 	u8 val = 0; | 	u8 val = 0; | ||||||
|  | @ -407,7 +405,7 @@ static int si2165_upload_firmware(struct si2165_state *state) | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	const struct firmware *fw = NULL; | 	const struct firmware *fw = NULL; | ||||||
| 	u8 *fw_file = SI2165_FIRMWARE; | 	u8 *fw_file; | ||||||
| 	const u8 *data; | 	const u8 *data; | ||||||
| 	u32 len; | 	u32 len; | ||||||
| 	u32 offset; | 	u32 offset; | ||||||
|  | @ -415,10 +413,20 @@ static int si2165_upload_firmware(struct si2165_state *state) | ||||||
| 	u8 block_count; | 	u8 block_count; | ||||||
| 	u16 crc_expected; | 	u16 crc_expected; | ||||||
| 
 | 
 | ||||||
|  | 	switch (state->chip_revcode) { | ||||||
|  | 	case 0x03: /* revision D */ | ||||||
|  | 		fw_file = SI2165_FIRMWARE_REV_D; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		dev_info(&state->i2c->dev, "%s: no firmware file for revision=%d\n", | ||||||
|  | 			KBUILD_MODNAME, state->chip_revcode); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* request the firmware, this will block and timeout */ | 	/* request the firmware, this will block and timeout */ | ||||||
| 	ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); | 	ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		dev_warn(&state->i2c->dev, "%s: firmare file '%s' not found\n", | 		dev_warn(&state->i2c->dev, "%s: firmware file '%s' not found\n", | ||||||
| 				KBUILD_MODNAME, fw_file); | 				KBUILD_MODNAME, fw_file); | ||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
|  | @ -908,7 +916,7 @@ static void si2165_release(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| static struct dvb_frontend_ops si2165_ops = { | static struct dvb_frontend_ops si2165_ops = { | ||||||
| 	.info = { | 	.info = { | ||||||
| 		.name = "Silicon Labs Si2165", | 		.name = "Silicon Labs ", | ||||||
| 		.caps =	FE_CAN_FEC_1_2 | | 		.caps =	FE_CAN_FEC_1_2 | | ||||||
| 			FE_CAN_FEC_2_3 | | 			FE_CAN_FEC_2_3 | | ||||||
| 			FE_CAN_FEC_3_4 | | 			FE_CAN_FEC_3_4 | | ||||||
|  | @ -948,6 +956,8 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, | ||||||
| 	int n; | 	int n; | ||||||
| 	int io_ret; | 	int io_ret; | ||||||
| 	u8 val; | 	u8 val; | ||||||
|  | 	char rev_char; | ||||||
|  | 	const char *chip_name; | ||||||
| 
 | 
 | ||||||
| 	if (config == NULL || i2c == NULL) | 	if (config == NULL || i2c == NULL) | ||||||
| 		goto error; | 		goto error; | ||||||
|  | @ -984,7 +994,7 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, | ||||||
| 	if (val != state->config.chip_mode) | 	if (val != state->config.chip_mode) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	io_ret = si2165_readreg8(state, 0x0023 , &state->revcode); | 	io_ret = si2165_readreg8(state, 0x0023, &state->chip_revcode); | ||||||
| 	if (io_ret < 0) | 	if (io_ret < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
|  | @ -997,22 +1007,35 @@ struct dvb_frontend *si2165_attach(const struct si2165_config *config, | ||||||
| 	if (io_ret < 0) | 	if (io_ret < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	dev_info(&state->i2c->dev, "%s: hardware revision 0x%02x, chip type 0x%02x\n", | 	if (state->chip_revcode < 26) | ||||||
| 		 KBUILD_MODNAME, state->revcode, state->chip_type); | 		rev_char = 'A' + state->chip_revcode; | ||||||
|  | 	else | ||||||
|  | 		rev_char = '?'; | ||||||
| 
 | 
 | ||||||
| 	/* It is a guess that register 0x0118 (chip type?) can be used to
 | 	switch (state->chip_type) { | ||||||
| 	 * differ between si2161, si2163 and si2165 | 	case 0x06: | ||||||
| 	 * Only si2165 has been tested. | 		chip_name = "Si2161"; | ||||||
| 	 */ | 		state->has_dvbt = true; | ||||||
| 	if (state->revcode == 0x03 && state->chip_type == 0x07) { | 		break; | ||||||
|  | 	case 0x07: | ||||||
|  | 		chip_name = "Si2165"; | ||||||
| 		state->has_dvbt = true; | 		state->has_dvbt = true; | ||||||
| 		state->has_dvbc = true; | 		state->has_dvbc = true; | ||||||
| 	} else { | 		break; | ||||||
| 		dev_err(&state->i2c->dev, "%s: Unsupported chip.\n", | 	default: | ||||||
| 			KBUILD_MODNAME); | 		dev_err(&state->i2c->dev, "%s: Unsupported Silicon Labs chip (type %d, rev %d)\n", | ||||||
|  | 			KBUILD_MODNAME, state->chip_type, state->chip_revcode); | ||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	dev_info(&state->i2c->dev, | ||||||
|  | 		"%s: Detected Silicon Labs %s-%c (type %d, rev %d)\n", | ||||||
|  | 		KBUILD_MODNAME, chip_name, rev_char, state->chip_type, | ||||||
|  | 		state->chip_revcode); | ||||||
|  | 
 | ||||||
|  | 	strlcat(state->frontend.ops.info.name, chip_name, | ||||||
|  | 			sizeof(state->frontend.ops.info.name)); | ||||||
|  | 
 | ||||||
| 	n = 0; | 	n = 0; | ||||||
| 	if (state->has_dvbt) { | 	if (state->has_dvbt) { | ||||||
| 		state->frontend.ops.delsys[n++] = SYS_DVBT; | 		state->frontend.ops.delsys[n++] = SYS_DVBT; | ||||||
|  | @ -1037,4 +1060,4 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||||||
| MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver"); | MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver"); | ||||||
| MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>"); | MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>"); | ||||||
| MODULE_LICENSE("GPL"); | MODULE_LICENSE("GPL"); | ||||||
| MODULE_FIRMWARE(SI2165_FIRMWARE); | MODULE_FIRMWARE(SI2165_FIRMWARE_REV_D); | ||||||
|  |  | ||||||
|  | @ -18,6 +18,6 @@ | ||||||
| #ifndef _DVB_SI2165_PRIV | #ifndef _DVB_SI2165_PRIV | ||||||
| #define _DVB_SI2165_PRIV | #define _DVB_SI2165_PRIV | ||||||
| 
 | 
 | ||||||
| #define SI2165_FIRMWARE "dvb-demod-si2165.fw" | #define SI2165_FIRMWARE_REV_D "dvb-demod-si2165.fw" | ||||||
| 
 | 
 | ||||||
| #endif /* _DVB_SI2165_PRIV */ | #endif /* _DVB_SI2165_PRIV */ | ||||||
|  |  | ||||||
|  | @ -55,8 +55,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) | ||||||
| 				break; | 				break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", | 		dev_dbg(&s->client->dev, "cmd execution took %d ms\n", | ||||||
| 				__func__, |  | ||||||
| 				jiffies_to_msecs(jiffies) - | 				jiffies_to_msecs(jiffies) - | ||||||
| 				(jiffies_to_msecs(timeout) - TIMEOUT)); | 				(jiffies_to_msecs(timeout) - TIMEOUT)); | ||||||
| 
 | 
 | ||||||
|  | @ -75,7 +74,7 @@ err_mutex_unlock: | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| err: | err: | ||||||
| 	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&s->client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -150,12 +149,12 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||||||
| 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n", | 	dev_dbg(&s->client->dev, "status=%02x args=%*ph\n", | ||||||
| 			__func__, *status, cmd.rlen, cmd.args); | 			*status, cmd.rlen, cmd.args); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| err: | err: | ||||||
| 	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&s->client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -168,10 +167,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) | ||||||
| 	u8 bandwidth, delivery_system; | 	u8 bandwidth, delivery_system; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->client->dev, | 	dev_dbg(&s->client->dev, | ||||||
| 			"%s: delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u\n", | 			"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n", | ||||||
| 			__func__, c->delivery_system, c->modulation, | 			c->delivery_system, c->modulation, | ||||||
| 			c->frequency, c->bandwidth_hz, c->symbol_rate, | 			c->frequency, c->bandwidth_hz, c->symbol_rate, | ||||||
| 			c->inversion); | 			c->inversion, c->stream_id); | ||||||
| 
 | 
 | ||||||
| 	if (!s->active) { | 	if (!s->active) { | ||||||
| 		ret = -EAGAIN; | 		ret = -EAGAIN; | ||||||
|  | @ -235,6 +234,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
|  | 	if (c->delivery_system == SYS_DVBT2) { | ||||||
|  | 		/* select PLP */ | ||||||
|  | 		cmd.args[0] = 0x52; | ||||||
|  | 		cmd.args[1] = c->stream_id & 0xff; | ||||||
|  | 		cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1; | ||||||
|  | 		cmd.wlen = 3; | ||||||
|  | 		cmd.rlen = 1; | ||||||
|  | 		ret = si2168_cmd_execute(s, &cmd); | ||||||
|  | 		if (ret) | ||||||
|  | 			goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	memcpy(cmd.args, "\x51\x03", 2); | 	memcpy(cmd.args, "\x51\x03", 2); | ||||||
| 	cmd.wlen = 2; | 	cmd.wlen = 2; | ||||||
| 	cmd.rlen = 12; | 	cmd.rlen = 12; | ||||||
|  | @ -297,13 +308,6 @@ static int si2168_set_frontend(struct dvb_frontend *fe) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6); |  | ||||||
| 	cmd.wlen = 6; |  | ||||||
| 	cmd.rlen = 4; |  | ||||||
| 	ret = si2168_cmd_execute(s, &cmd); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto err; |  | ||||||
| 
 |  | ||||||
| 	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6); | 	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6); | ||||||
| 	cmd.wlen = 6; | 	cmd.wlen = 6; | ||||||
| 	cmd.rlen = 4; | 	cmd.rlen = 4; | ||||||
|  | @ -343,7 +347,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| err: | err: | ||||||
| 	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&s->client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -357,8 +361,9 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 	struct si2168_cmd cmd; | 	struct si2168_cmd cmd; | ||||||
| 	unsigned int chip_id; | 	unsigned int chip_id; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->client->dev, "%s:\n", __func__); | 	dev_dbg(&s->client->dev, "\n"); | ||||||
| 
 | 
 | ||||||
|  | 	/* initialize */ | ||||||
| 	memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); | 	memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13); | ||||||
| 	cmd.wlen = 13; | 	cmd.wlen = 13; | ||||||
| 	cmd.rlen = 0; | 	cmd.rlen = 0; | ||||||
|  | @ -366,6 +371,26 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
|  | 	if (s->fw_loaded) { | ||||||
|  | 		/* resume */ | ||||||
|  | 		memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8); | ||||||
|  | 		cmd.wlen = 8; | ||||||
|  | 		cmd.rlen = 1; | ||||||
|  | 		ret = si2168_cmd_execute(s, &cmd); | ||||||
|  | 		if (ret) | ||||||
|  | 			goto err; | ||||||
|  | 
 | ||||||
|  | 		memcpy(cmd.args, "\x85", 1); | ||||||
|  | 		cmd.wlen = 1; | ||||||
|  | 		cmd.rlen = 1; | ||||||
|  | 		ret = si2168_cmd_execute(s, &cmd); | ||||||
|  | 		if (ret) | ||||||
|  | 			goto err; | ||||||
|  | 
 | ||||||
|  | 		goto warm; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* power up */ | ||||||
| 	memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); | 	memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8); | ||||||
| 	cmd.wlen = 8; | 	cmd.wlen = 8; | ||||||
| 	cmd.rlen = 1; | 	cmd.rlen = 1; | ||||||
|  | @ -400,16 +425,16 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		dev_err(&s->client->dev, | 		dev_err(&s->client->dev, | ||||||
| 				"%s: unkown chip version Si21%d-%c%c%c\n", | 				"unknown chip version Si21%d-%c%c%c\n", | ||||||
| 				KBUILD_MODNAME, cmd.args[2], cmd.args[1], | 				cmd.args[2], cmd.args[1], | ||||||
| 				cmd.args[3], cmd.args[4]); | 				cmd.args[3], cmd.args[4]); | ||||||
| 		ret = -EINVAL; | 		ret = -EINVAL; | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* cold state - try to download firmware */ | 	/* cold state - try to download firmware */ | ||||||
| 	dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", | 	dev_info(&s->client->dev, "found a '%s' in cold state\n", | ||||||
| 			KBUILD_MODNAME, si2168_ops.info.name); | 			si2168_ops.info.name); | ||||||
| 
 | 
 | ||||||
| 	/* request the firmware, this will block and timeout */ | 	/* request the firmware, this will block and timeout */ | ||||||
| 	ret = request_firmware(&fw, fw_file, &s->client->dev); | 	ret = request_firmware(&fw, fw_file, &s->client->dev); | ||||||
|  | @ -422,18 +447,18 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 		if (ret == 0) { | 		if (ret == 0) { | ||||||
| 			dev_notice(&s->client->dev, | 			dev_notice(&s->client->dev, | ||||||
| 					"%s: please install firmware file '%s'\n", | 					"please install firmware file '%s'\n", | ||||||
| 					KBUILD_MODNAME, SI2168_B40_FIRMWARE); | 					SI2168_B40_FIRMWARE); | ||||||
| 		} else { | 		} else { | ||||||
| 			dev_err(&s->client->dev, | 			dev_err(&s->client->dev, | ||||||
| 					"%s: firmware file '%s' not found\n", | 					"firmware file '%s' not found\n", | ||||||
| 					KBUILD_MODNAME, fw_file); | 					fw_file); | ||||||
| 			goto err; | 			goto err; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", | 	dev_info(&s->client->dev, "downloading firmware from file '%s'\n", | ||||||
| 			KBUILD_MODNAME, fw_file); | 			fw_file); | ||||||
| 
 | 
 | ||||||
| 	for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { | 	for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { | ||||||
| 		len = remaining; | 		len = remaining; | ||||||
|  | @ -446,8 +471,8 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 		ret = si2168_cmd_execute(s, &cmd); | 		ret = si2168_cmd_execute(s, &cmd); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			dev_err(&s->client->dev, | 			dev_err(&s->client->dev, | ||||||
| 					"%s: firmware download failed=%d\n", | 					"firmware download failed=%d\n", | ||||||
| 					KBUILD_MODNAME, ret); | 					ret); | ||||||
| 			goto err; | 			goto err; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -462,8 +487,20 @@ static int si2168_init(struct dvb_frontend *fe) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	dev_info(&s->client->dev, "%s: found a '%s' in warm state\n", | 	/* set ts mode */ | ||||||
| 			KBUILD_MODNAME, si2168_ops.info.name); | 	memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6); | ||||||
|  | 	cmd.args[4] |= s->ts_mode; | ||||||
|  | 	cmd.wlen = 6; | ||||||
|  | 	cmd.rlen = 4; | ||||||
|  | 	ret = si2168_cmd_execute(s, &cmd); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	s->fw_loaded = true; | ||||||
|  | 
 | ||||||
|  | warm: | ||||||
|  | 	dev_info(&s->client->dev, "found a '%s' in warm state\n", | ||||||
|  | 			si2168_ops.info.name); | ||||||
| 
 | 
 | ||||||
| 	s->active = true; | 	s->active = true; | ||||||
| 
 | 
 | ||||||
|  | @ -472,7 +509,7 @@ err: | ||||||
| 	if (fw) | 	if (fw) | ||||||
| 		release_firmware(fw); | 		release_firmware(fw); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&s->client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -482,7 +519,7 @@ static int si2168_sleep(struct dvb_frontend *fe) | ||||||
| 	int ret; | 	int ret; | ||||||
| 	struct si2168_cmd cmd; | 	struct si2168_cmd cmd; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&s->client->dev, "%s:\n", __func__); | 	dev_dbg(&s->client->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	s->active = false; | 	s->active = false; | ||||||
| 
 | 
 | ||||||
|  | @ -495,7 +532,7 @@ static int si2168_sleep(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| err: | err: | ||||||
| 	dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&s->client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -528,8 +565,7 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) | ||||||
| 	/* open tuner I2C gate */ | 	/* open tuner I2C gate */ | ||||||
| 	ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); | 	ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); | ||||||
| 	if (ret != 1) { | 	if (ret != 1) { | ||||||
| 		dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", | 		dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); | ||||||
| 				KBUILD_MODNAME, ret); |  | ||||||
| 		if (ret >= 0) | 		if (ret >= 0) | ||||||
| 			ret = -EREMOTEIO; | 			ret = -EREMOTEIO; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -553,8 +589,7 @@ static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) | ||||||
| 	/* close tuner I2C gate */ | 	/* close tuner I2C gate */ | ||||||
| 	ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); | 	ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); | ||||||
| 	if (ret != 1) { | 	if (ret != 1) { | ||||||
| 		dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", | 		dev_warn(&s->client->dev, "i2c write failed=%d\n", ret); | ||||||
| 				KBUILD_MODNAME, ret); |  | ||||||
| 		if (ret >= 0) | 		if (ret >= 0) | ||||||
| 			ret = -EREMOTEIO; | 			ret = -EREMOTEIO; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -587,7 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = { | ||||||
| 			FE_CAN_GUARD_INTERVAL_AUTO | | 			FE_CAN_GUARD_INTERVAL_AUTO | | ||||||
| 			FE_CAN_HIERARCHY_AUTO | | 			FE_CAN_HIERARCHY_AUTO | | ||||||
| 			FE_CAN_MUTE_TS | | 			FE_CAN_MUTE_TS | | ||||||
| 			FE_CAN_2G_MODULATION | 			FE_CAN_2G_MODULATION | | ||||||
|  | 			FE_CAN_MULTISTREAM | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	.get_tune_settings = si2168_get_tune_settings, | 	.get_tune_settings = si2168_get_tune_settings, | ||||||
|  | @ -607,12 +643,12 @@ static int si2168_probe(struct i2c_client *client, | ||||||
| 	struct si2168 *s; | 	struct si2168 *s; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&client->dev, "%s:\n", __func__); | 	dev_dbg(&client->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	s = kzalloc(sizeof(struct si2168), GFP_KERNEL); | 	s = kzalloc(sizeof(struct si2168), GFP_KERNEL); | ||||||
| 	if (!s) { | 	if (!s) { | ||||||
| 		ret = -ENOMEM; | 		ret = -ENOMEM; | ||||||
| 		dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | 		dev_err(&client->dev, "kzalloc() failed\n"); | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -633,16 +669,17 @@ static int si2168_probe(struct i2c_client *client, | ||||||
| 
 | 
 | ||||||
| 	*config->i2c_adapter = s->adapter; | 	*config->i2c_adapter = s->adapter; | ||||||
| 	*config->fe = &s->fe; | 	*config->fe = &s->fe; | ||||||
|  | 	s->ts_mode = config->ts_mode; | ||||||
|  | 	s->fw_loaded = false; | ||||||
| 
 | 
 | ||||||
| 	i2c_set_clientdata(client, s); | 	i2c_set_clientdata(client, s); | ||||||
| 
 | 
 | ||||||
| 	dev_info(&s->client->dev, | 	dev_info(&s->client->dev, | ||||||
| 			"%s: Silicon Labs Si2168 successfully attached\n", | 			"Silicon Labs Si2168 successfully attached\n"); | ||||||
| 			KBUILD_MODNAME); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| err: | err: | ||||||
| 	kfree(s); | 	kfree(s); | ||||||
| 	dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); | 	dev_dbg(&client->dev, "failed=%d\n", ret); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -650,7 +687,7 @@ static int si2168_remove(struct i2c_client *client) | ||||||
| { | { | ||||||
| 	struct si2168 *s = i2c_get_clientdata(client); | 	struct si2168 *s = i2c_get_clientdata(client); | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&client->dev, "%s:\n", __func__); | 	dev_dbg(&client->dev, "\n"); | ||||||
| 
 | 
 | ||||||
| 	i2c_del_mux_adapter(s->adapter); | 	i2c_del_mux_adapter(s->adapter); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,6 +34,12 @@ struct si2168_config { | ||||||
| 	 * returned by driver | 	 * returned by driver | ||||||
| 	 */ | 	 */ | ||||||
| 	struct i2c_adapter **i2c_adapter; | 	struct i2c_adapter **i2c_adapter; | ||||||
|  | 
 | ||||||
|  | 	/* TS mode */ | ||||||
|  | 	u8 ts_mode; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | #define SI2168_TS_PARALLEL	0x06 | ||||||
|  | #define SI2168_TS_SERIAL	0x03 | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ struct si2168 { | ||||||
| 	fe_delivery_system_t delivery_system; | 	fe_delivery_system_t delivery_system; | ||||||
| 	fe_status_t fe_status; | 	fe_status_t fe_status; | ||||||
| 	bool active; | 	bool active; | ||||||
|  | 	bool fw_loaded; | ||||||
|  | 	u8 ts_mode; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* firmare command struct */ | /* firmare command struct */ | ||||||
|  |  | ||||||
|  | @ -236,6 +236,9 @@ static int si21_writeregs(struct si21xx_state *state, u8 reg1, | ||||||
| 				.len = len + 1 | 				.len = len + 1 | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	if (len > sizeof(buf) - 1) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
| 	msg.buf[0] =  reg1; | 	msg.buf[0] =  reg1; | ||||||
| 	memcpy(msg.buf + 1, data, len); | 	memcpy(msg.buf + 1, data, len); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										441
									
								
								drivers/media/dvb-frontends/sp2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								drivers/media/dvb-frontends/sp2.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,441 @@ | ||||||
|  | /*
 | ||||||
|  |  * CIMaX SP2/SP2HF (Atmel T90FJR) CI driver | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> | ||||||
|  |  * | ||||||
|  |  * Heavily based on CIMax2(R) SP2 driver in conjunction with NetUp Dual | ||||||
|  |  * DVB-S2 CI card (cimax2) with following copyrights: | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2009 NetUP Inc. | ||||||
|  |  *  Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> | ||||||
|  |  *  Copyright (C) 2009 Abylay Ospan <aospan@netup.ru> | ||||||
|  |  * | ||||||
|  |  *    This program is free software; you can redistribute it and/or modify | ||||||
|  |  *    it under the terms of the GNU General Public License as published by | ||||||
|  |  *    the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  *    (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *    This program is distributed in the hope that it will be useful, | ||||||
|  |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *    GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "sp2_priv.h" | ||||||
|  | 
 | ||||||
|  | static int sp2_read_i2c(struct sp2 *s, u8 reg, u8 *buf, int len) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	struct i2c_client *client = s->client; | ||||||
|  | 	struct i2c_adapter *adap = client->adapter; | ||||||
|  | 	struct i2c_msg msg[] = { | ||||||
|  | 		{ | ||||||
|  | 			.addr = client->addr, | ||||||
|  | 			.flags = 0, | ||||||
|  | 			.buf = ®, | ||||||
|  | 			.len = 1 | ||||||
|  | 		}, { | ||||||
|  | 			.addr = client->addr, | ||||||
|  | 			.flags	= I2C_M_RD, | ||||||
|  | 			.buf = buf, | ||||||
|  | 			.len = len | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	ret = i2c_transfer(adap, msg, 2); | ||||||
|  | 
 | ||||||
|  | 	if (ret != 2) { | ||||||
|  | 		dev_err(&client->dev, "i2c read error, reg = 0x%02x, status = %d\n", | ||||||
|  | 				reg, ret); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			return ret; | ||||||
|  | 		else | ||||||
|  | 			return -EIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %02x\n", | ||||||
|  | 				client->addr, reg, buf[0]); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sp2_write_i2c(struct sp2 *s, u8 reg, u8 *buf, int len) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	u8 buffer[35]; | ||||||
|  | 	struct i2c_client *client = s->client; | ||||||
|  | 	struct i2c_adapter *adap = client->adapter; | ||||||
|  | 	struct i2c_msg msg = { | ||||||
|  | 		.addr = client->addr, | ||||||
|  | 		.flags = 0, | ||||||
|  | 		.buf = &buffer[0], | ||||||
|  | 		.len = len + 1 | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	if ((len + 1) > sizeof(buffer)) { | ||||||
|  | 		dev_err(&client->dev, "i2c wr reg=%02x: len=%d is too big!\n", | ||||||
|  | 				reg, len); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	buffer[0] = reg; | ||||||
|  | 	memcpy(&buffer[1], buf, len); | ||||||
|  | 
 | ||||||
|  | 	ret = i2c_transfer(adap, &msg, 1); | ||||||
|  | 
 | ||||||
|  | 	if (ret != 1) { | ||||||
|  | 		dev_err(&client->dev, "i2c write error, reg = 0x%02x, status = %d\n", | ||||||
|  | 				reg, ret); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			return ret; | ||||||
|  | 		else | ||||||
|  | 			return -EIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs, | ||||||
|  | 			u8 read, int addr, u8 data) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s = en50221->data; | ||||||
|  | 	u8 store; | ||||||
|  | 	int mem, ret; | ||||||
|  | 	int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x", | ||||||
|  | 			slot, acs, addr, data); | ||||||
|  | 
 | ||||||
|  | 	if (slot != 0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * change module access type between IO space and attribute memory | ||||||
|  | 	 * when needed | ||||||
|  | 	 */ | ||||||
|  | 	if (s->module_access_type != acs) { | ||||||
|  | 		ret = sp2_read_i2c(s, 0x00, &store, 1); | ||||||
|  | 
 | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  | 
 | ||||||
|  | 		store &= ~(SP2_MOD_CTL_ACS1 | SP2_MOD_CTL_ACS0); | ||||||
|  | 		store |= acs; | ||||||
|  | 
 | ||||||
|  | 		ret = sp2_write_i2c(s, 0x00, &store, 1); | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	s->module_access_type = acs; | ||||||
|  | 
 | ||||||
|  | 	/* implementation of ci_op_cam is device specific */ | ||||||
|  | 	if (ci_op_cam) { | ||||||
|  | 		ret = ci_op_cam(s->priv, read, addr, data, &mem); | ||||||
|  | 	} else { | ||||||
|  | 		dev_err(&s->client->dev, "callback not defined"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	if (read) { | ||||||
|  | 		dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x", | ||||||
|  | 				addr, mem); | ||||||
|  | 		return mem; | ||||||
|  | 	} else { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, | ||||||
|  | 				int slot, int addr) | ||||||
|  | { | ||||||
|  | 	return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS, | ||||||
|  | 			SP2_CI_RD, addr, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, | ||||||
|  | 				int slot, int addr, u8 data) | ||||||
|  | { | ||||||
|  | 	return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS, | ||||||
|  | 			SP2_CI_WR, addr, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221, | ||||||
|  | 				int slot, u8 addr) | ||||||
|  | { | ||||||
|  | 	return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS, | ||||||
|  | 			SP2_CI_RD, addr, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221, | ||||||
|  | 				int slot, u8 addr, u8 data) | ||||||
|  | { | ||||||
|  | 	return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS, | ||||||
|  | 			SP2_CI_WR, addr, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s = en50221->data; | ||||||
|  | 	u8 buf; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "slot: %d\n", slot); | ||||||
|  | 
 | ||||||
|  | 	if (slot != 0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	/* RST on */ | ||||||
|  | 	buf = SP2_MOD_CTL_RST; | ||||||
|  | 	ret = sp2_write_i2c(s, 0x00, &buf, 1); | ||||||
|  | 
 | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	usleep_range(500, 600); | ||||||
|  | 
 | ||||||
|  | 	/* RST off */ | ||||||
|  | 	buf = 0x00; | ||||||
|  | 	ret = sp2_write_i2c(s, 0x00, &buf, 1); | ||||||
|  | 
 | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	msleep(1000); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s = en50221->data; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "slot:%d\n", slot); | ||||||
|  | 
 | ||||||
|  | 	/* not implemented */ | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s = en50221->data; | ||||||
|  | 	u8 buf; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "slot:%d\n", slot); | ||||||
|  | 
 | ||||||
|  | 	if (slot != 0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	sp2_read_i2c(s, 0x00, &buf, 1); | ||||||
|  | 
 | ||||||
|  | 	/* disable bypass and enable TS */ | ||||||
|  | 	buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN); | ||||||
|  | 	return sp2_write_i2c(s, 0, &buf, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221, | ||||||
|  | 				int slot, int open) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s = en50221->data; | ||||||
|  | 	u8 buf[2]; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * CAM module INSERT/REMOVE processing. Slow operation because of i2c | ||||||
|  | 	 * transfers. Throttle read to one per sec. | ||||||
|  | 	 */ | ||||||
|  | 	if (time_after(jiffies, s->next_status_checked_time)) { | ||||||
|  | 		ret = sp2_read_i2c(s, 0x00, buf, 1); | ||||||
|  | 		s->next_status_checked_time = jiffies +	msecs_to_jiffies(1000); | ||||||
|  | 
 | ||||||
|  | 		if (ret) | ||||||
|  | 			return 0; | ||||||
|  | 
 | ||||||
|  | 		if (buf[0] & SP2_MOD_CTL_DET) | ||||||
|  | 			s->status = DVB_CA_EN50221_POLL_CAM_PRESENT | | ||||||
|  | 					DVB_CA_EN50221_POLL_CAM_READY; | ||||||
|  | 		else | ||||||
|  | 			s->status = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return s->status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_init(struct sp2 *s) | ||||||
|  | { | ||||||
|  | 	int ret = 0; | ||||||
|  | 	u8 buf; | ||||||
|  | 	u8 cimax_init[34] = { | ||||||
|  | 		0x00, /* module A control*/ | ||||||
|  | 		0x00, /* auto select mask high A */ | ||||||
|  | 		0x00, /* auto select mask low A */ | ||||||
|  | 		0x00, /* auto select pattern high A */ | ||||||
|  | 		0x00, /* auto select pattern low A */ | ||||||
|  | 		0x44, /* memory access time A, 600 ns */ | ||||||
|  | 		0x00, /* invert input A */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x00, /* module B control*/ | ||||||
|  | 		0x00, /* auto select mask high B */ | ||||||
|  | 		0x00, /* auto select mask low B */ | ||||||
|  | 		0x00, /* auto select pattern high B */ | ||||||
|  | 		0x00, /* auto select pattern low B */ | ||||||
|  | 		0x44, /* memory access time B, 600 ns */ | ||||||
|  | 		0x00, /* invert input B */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x00, /* auto select mask high Ext */ | ||||||
|  | 		0x00, /* auto select mask low Ext */ | ||||||
|  | 		0x00, /* auto select pattern high Ext */ | ||||||
|  | 		0x00, /* auto select pattern low Ext */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x02, /* destination - module A */ | ||||||
|  | 		0x01, /* power control reg, VCC power on */ | ||||||
|  | 		0x00, /* RFU */ | ||||||
|  | 		0x00, /* int status read only */ | ||||||
|  | 		0x00, /* Interrupt Mask Register */ | ||||||
|  | 		0x05, /* EXTINT=active-high, INT=push-pull */ | ||||||
|  | 		0x00, /* USCG1 */ | ||||||
|  | 		0x04, /* ack active low */ | ||||||
|  | 		0x00, /* LOCK = 0 */ | ||||||
|  | 		0x22, /* unknown */ | ||||||
|  | 		0x00, /* synchronization? */ | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&s->client->dev, "\n"); | ||||||
|  | 
 | ||||||
|  | 	s->ca.owner = THIS_MODULE; | ||||||
|  | 	s->ca.read_attribute_mem = sp2_ci_read_attribute_mem; | ||||||
|  | 	s->ca.write_attribute_mem = sp2_ci_write_attribute_mem; | ||||||
|  | 	s->ca.read_cam_control = sp2_ci_read_cam_control; | ||||||
|  | 	s->ca.write_cam_control = sp2_ci_write_cam_control; | ||||||
|  | 	s->ca.slot_reset = sp2_ci_slot_reset; | ||||||
|  | 	s->ca.slot_shutdown = sp2_ci_slot_shutdown; | ||||||
|  | 	s->ca.slot_ts_enable = sp2_ci_slot_ts_enable; | ||||||
|  | 	s->ca.poll_slot_status = sp2_ci_poll_slot_status; | ||||||
|  | 	s->ca.data = s; | ||||||
|  | 	s->module_access_type = 0; | ||||||
|  | 
 | ||||||
|  | 	/* initialize all regs */ | ||||||
|  | 	ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	/* lock registers */ | ||||||
|  | 	buf = 1; | ||||||
|  | 	ret = sp2_write_i2c(s, 0x1f, &buf, 1); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	/* power on slots */ | ||||||
|  | 	ret = sp2_write_i2c(s, 0x18, &buf, 1); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | err: | ||||||
|  | 	dev_dbg(&s->client->dev, "init failed=%d\n", ret); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sp2_exit(struct i2c_client *client) | ||||||
|  | { | ||||||
|  | 	struct sp2 *s; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&client->dev, "\n"); | ||||||
|  | 
 | ||||||
|  | 	if (client == NULL) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	s = i2c_get_clientdata(client); | ||||||
|  | 	if (s == NULL) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	if (s->ca.data == NULL) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	dvb_ca_en50221_release(&s->ca); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sp2_probe(struct i2c_client *client, | ||||||
|  | 		const struct i2c_device_id *id) | ||||||
|  | { | ||||||
|  | 	struct sp2_config *cfg = client->dev.platform_data; | ||||||
|  | 	struct sp2 *s; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&client->dev, "\n"); | ||||||
|  | 
 | ||||||
|  | 	s = kzalloc(sizeof(struct sp2), GFP_KERNEL); | ||||||
|  | 	if (!s) { | ||||||
|  | 		ret = -ENOMEM; | ||||||
|  | 		dev_err(&client->dev, "kzalloc() failed\n"); | ||||||
|  | 		goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	s->client = client; | ||||||
|  | 	s->dvb_adap = cfg->dvb_adap; | ||||||
|  | 	s->priv = cfg->priv; | ||||||
|  | 	s->ci_control = cfg->ci_control; | ||||||
|  | 
 | ||||||
|  | 	i2c_set_clientdata(client, s); | ||||||
|  | 
 | ||||||
|  | 	ret = sp2_init(s); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto err; | ||||||
|  | 
 | ||||||
|  | 	dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n"); | ||||||
|  | 	return 0; | ||||||
|  | err: | ||||||
|  | 	dev_dbg(&client->dev, "init failed=%d\n", ret); | ||||||
|  | 	kfree(s); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sp2_remove(struct i2c_client *client) | ||||||
|  | { | ||||||
|  | 	struct si2157 *s = i2c_get_clientdata(client); | ||||||
|  | 
 | ||||||
|  | 	dev_dbg(&client->dev, "\n"); | ||||||
|  | 
 | ||||||
|  | 	sp2_exit(client); | ||||||
|  | 	if (s != NULL) | ||||||
|  | 		kfree(s); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct i2c_device_id sp2_id[] = { | ||||||
|  | 	{"sp2", 0}, | ||||||
|  | 	{} | ||||||
|  | }; | ||||||
|  | MODULE_DEVICE_TABLE(i2c, sp2_id); | ||||||
|  | 
 | ||||||
|  | static struct i2c_driver sp2_driver = { | ||||||
|  | 	.driver = { | ||||||
|  | 		.owner	= THIS_MODULE, | ||||||
|  | 		.name	= "sp2", | ||||||
|  | 	}, | ||||||
|  | 	.probe		= sp2_probe, | ||||||
|  | 	.remove		= sp2_remove, | ||||||
|  | 	.id_table	= sp2_id, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module_i2c_driver(sp2_driver); | ||||||
|  | 
 | ||||||
|  | MODULE_DESCRIPTION("CIMaX SP2/HF CI driver"); | ||||||
|  | MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
							
								
								
									
										53
									
								
								drivers/media/dvb-frontends/sp2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								drivers/media/dvb-frontends/sp2.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | /*
 | ||||||
|  |  * CIMaX SP2/HF CI driver | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> | ||||||
|  |  * | ||||||
|  |  *    This program is free software; you can redistribute it and/or modify | ||||||
|  |  *    it under the terms of the GNU General Public License as published by | ||||||
|  |  *    the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  *    (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *    This program is distributed in the hope that it will be useful, | ||||||
|  |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *    GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef SP2_H | ||||||
|  | #define SP2_H | ||||||
|  | 
 | ||||||
|  | #include <linux/kconfig.h> | ||||||
|  | #include "dvb_ca_en50221.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * I2C address | ||||||
|  |  * 0x40 (port 0) | ||||||
|  |  * 0x41 (port 1) | ||||||
|  |  */ | ||||||
|  | struct sp2_config { | ||||||
|  | 	/* dvb_adapter to attach the ci to */ | ||||||
|  | 	struct dvb_adapter *dvb_adap; | ||||||
|  | 
 | ||||||
|  | 	/* function ci_control handles the device specific ci ops */ | ||||||
|  | 	void *ci_control; | ||||||
|  | 
 | ||||||
|  | 	/* priv is passed back to function ci_control */ | ||||||
|  | 	void *priv; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, | ||||||
|  | 					int slot, int addr); | ||||||
|  | extern int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, | ||||||
|  | 					int slot, int addr, u8 data); | ||||||
|  | extern int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221, | ||||||
|  | 					int slot, u8 addr); | ||||||
|  | extern int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221, | ||||||
|  | 					int slot, u8 addr, u8 data); | ||||||
|  | extern int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot); | ||||||
|  | extern int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot); | ||||||
|  | extern int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot); | ||||||
|  | extern int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221, | ||||||
|  | 					int slot, int open); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										50
									
								
								drivers/media/dvb-frontends/sp2_priv.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								drivers/media/dvb-frontends/sp2_priv.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | /*
 | ||||||
|  |  * CIMaX SP2/HF CI driver | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi> | ||||||
|  |  * | ||||||
|  |  *    This program is free software; you can redistribute it and/or modify | ||||||
|  |  *    it under the terms of the GNU General Public License as published by | ||||||
|  |  *    the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  *    (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  *    This program is distributed in the hope that it will be useful, | ||||||
|  |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  *    GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef SP2_PRIV_H | ||||||
|  | #define SP2_PRIV_H | ||||||
|  | 
 | ||||||
|  | #include "sp2.h" | ||||||
|  | #include "dvb_frontend.h" | ||||||
|  | 
 | ||||||
|  | /* state struct */ | ||||||
|  | struct sp2 { | ||||||
|  | 	int status; | ||||||
|  | 	struct i2c_client *client; | ||||||
|  | 	struct dvb_adapter *dvb_adap; | ||||||
|  | 	struct dvb_ca_en50221 ca; | ||||||
|  | 	int module_access_type; | ||||||
|  | 	unsigned long next_status_checked_time; | ||||||
|  | 	void *priv; | ||||||
|  | 	void *ci_control; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define SP2_CI_ATTR_ACS		0x00 | ||||||
|  | #define SP2_CI_IO_ACS		0x04 | ||||||
|  | #define SP2_CI_WR		0 | ||||||
|  | #define SP2_CI_RD		1 | ||||||
|  | 
 | ||||||
|  | /* Module control register (0x00 module A, 0x09 module B) bits */ | ||||||
|  | #define SP2_MOD_CTL_DET		0x01 | ||||||
|  | #define SP2_MOD_CTL_AUTO	0x02 | ||||||
|  | #define SP2_MOD_CTL_ACS0	0x04 | ||||||
|  | #define SP2_MOD_CTL_ACS1	0x08 | ||||||
|  | #define SP2_MOD_CTL_HAD		0x10 | ||||||
|  | #define SP2_MOD_CTL_TSIEN	0x20 | ||||||
|  | #define SP2_MOD_CTL_TSOEN	0x40 | ||||||
|  | #define SP2_MOD_CTL_RST		0x80 | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -394,8 +394,7 @@ static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber) | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		return -EIO; | 		return -EIO; | ||||||
| 
 | 
 | ||||||
| 	 tmp = ret << 6; | 	tmp = ret << 6; | ||||||
| 
 |  | ||||||
| 	if (tmp >= 0x3FFF0) | 	if (tmp >= 0x3FFF0) | ||||||
| 		tmp = ~0; | 		tmp = ~0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,7 +59,6 @@ struct stv0367cab_state { | ||||||
| 	int locked;			/* channel found		*/ | 	int locked;			/* channel found		*/ | ||||||
| 	u32 freq_khz;			/* found frequency (in kHz)	*/ | 	u32 freq_khz;			/* found frequency (in kHz)	*/ | ||||||
| 	u32 symbol_rate;		/* found symbol rate (in Bds)	*/ | 	u32 symbol_rate;		/* found symbol rate (in Bds)	*/ | ||||||
| 	enum stv0367cab_mod modulation;	/* modulation			*/ |  | ||||||
| 	fe_spectral_inversion_t	spect_inv; /* Spectrum Inversion	*/ | 	fe_spectral_inversion_t	spect_inv; /* Spectrum Inversion	*/ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -554,7 +553,7 @@ static struct st_register def0367ter[STV0367TER_NBREGS] = { | ||||||
| #define RF_LOOKUP_TABLE_SIZE  31 | #define RF_LOOKUP_TABLE_SIZE  31 | ||||||
| #define RF_LOOKUP_TABLE2_SIZE 16 | #define RF_LOOKUP_TABLE2_SIZE 16 | ||||||
| /* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/ | /* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/ | ||||||
| s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { | static const s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { | ||||||
| 	{/*AGC1*/ | 	{/*AGC1*/ | ||||||
| 		48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63, | 		48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63, | ||||||
| 		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, | 		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, | ||||||
|  | @ -566,7 +565,7 @@ s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| /* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/ | /* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/ | ||||||
| s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = { | static const s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = { | ||||||
| 	{/*AGC2*/ | 	{/*AGC2*/ | ||||||
| 		28, 29, 31, 32, 34, 35, 36, 37, | 		28, 29, 31, 32, 34, 35, 36, 37, | ||||||
| 		38, 39, 40, 41, 42, 43, 44, 45, | 		38, 39, 40, 41, 42, 43, 44, 45, | ||||||
|  | @ -1935,8 +1934,6 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe) | ||||||
| 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | 	struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||||||
| 	struct stv0367_state *state = fe->demodulator_priv; | 	struct stv0367_state *state = fe->demodulator_priv; | ||||||
| 	struct stv0367ter_state *ter_state = state->ter_state; | 	struct stv0367ter_state *ter_state = state->ter_state; | ||||||
| 
 |  | ||||||
| 	int error = 0; |  | ||||||
| 	enum stv0367_ter_mode mode; | 	enum stv0367_ter_mode mode; | ||||||
| 	int constell = 0,/* snr = 0,*/ Data = 0; | 	int constell = 0,/* snr = 0,*/ Data = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -2020,7 +2017,7 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe) | ||||||
| 
 | 
 | ||||||
| 	p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD); | 	p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD); | ||||||
| 
 | 
 | ||||||
| 	return error; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) | static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) | ||||||
|  | @ -2999,7 +2996,6 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state, | ||||||
| 
 | 
 | ||||||
| 	if (QAMFEC_Lock) { | 	if (QAMFEC_Lock) { | ||||||
| 		signalType = FE_CAB_DATAOK; | 		signalType = FE_CAB_DATAOK; | ||||||
| 		cab_state->modulation = p->modulation; |  | ||||||
| 		cab_state->spect_inv = stv0367_readbits(state, | 		cab_state->spect_inv = stv0367_readbits(state, | ||||||
| 							F367CAB_QUAD_INV); | 							F367CAB_QUAD_INV); | ||||||
| #if 0 | #if 0 | ||||||
|  | @ -3165,7 +3161,7 @@ static int stv0367cab_get_frontend(struct dvb_frontend *fe) | ||||||
| 	case FE_CAB_MOD_QAM128: | 	case FE_CAB_MOD_QAM128: | ||||||
| 		p->modulation = QAM_128; | 		p->modulation = QAM_128; | ||||||
| 		break; | 		break; | ||||||
| 	case QAM_256: | 	case FE_CAB_MOD_QAM256: | ||||||
| 		p->modulation = QAM_256; | 		p->modulation = QAM_256; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
|  |  | ||||||
|  | @ -1270,7 +1270,6 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, | ||||||
| 					enum fe_stv0900_demod_mode LDPC_Mode, | 					enum fe_stv0900_demod_mode LDPC_Mode, | ||||||
| 					enum fe_stv0900_demod_num demod) | 					enum fe_stv0900_demod_num demod) | ||||||
| { | { | ||||||
| 	enum fe_stv0900_error error = STV0900_NO_ERROR; |  | ||||||
| 	s32 reg_ind; | 	s32 reg_ind; | ||||||
| 
 | 
 | ||||||
| 	dprintk("%s\n", __func__); | 	dprintk("%s\n", __func__); | ||||||
|  | @ -1337,7 +1336,7 @@ enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp, | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return error; | 	return STV0900_NO_ERROR; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | ||||||
|  | @ -1555,8 +1554,6 @@ static int stv0900_status(struct stv0900_internal *intp, | ||||||
| static int stv0900_set_mis(struct stv0900_internal *intp, | static int stv0900_set_mis(struct stv0900_internal *intp, | ||||||
| 				enum fe_stv0900_demod_num demod, int mis) | 				enum fe_stv0900_demod_num demod, int mis) | ||||||
| { | { | ||||||
| 	enum fe_stv0900_error error = STV0900_NO_ERROR; |  | ||||||
| 
 |  | ||||||
| 	dprintk("%s\n", __func__); | 	dprintk("%s\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	if (mis < 0 || mis > 255) { | 	if (mis < 0 || mis > 255) { | ||||||
|  | @ -1569,7 +1566,7 @@ static int stv0900_set_mis(struct stv0900_internal *intp, | ||||||
| 		stv0900_write_reg(intp, ISIBITENA, 0xff); | 		stv0900_write_reg(intp, ISIBITENA, 0xff); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return error; | 	return STV0900_NO_ERROR; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1733,9 +1733,10 @@ static void stv0900_set_search_standard(struct stv0900_internal *intp, | ||||||
| 		break; | 		break; | ||||||
| 	case STV0900_SEARCH_DSS: | 	case STV0900_SEARCH_DSS: | ||||||
| 		dprintk("Search Standard = DSS\n"); | 		dprintk("Search Standard = DSS\n"); | ||||||
| 	case STV0900_SEARCH_DVBS2: |  | ||||||
| 		break; | 		break; | ||||||
|  | 	case STV0900_SEARCH_DVBS2: | ||||||
| 		dprintk("Search Standard = DVBS2\n"); | 		dprintk("Search Standard = DVBS2\n"); | ||||||
|  | 		break; | ||||||
| 	case STV0900_AUTO_SEARCH: | 	case STV0900_AUTO_SEARCH: | ||||||
| 	default: | 	default: | ||||||
| 		dprintk("Search Standard = AUTO\n"); | 		dprintk("Search Standard = AUTO\n"); | ||||||
|  |  | ||||||
							
								
								
									
										840
									
								
								drivers/media/dvb-frontends/tc90522.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										840
									
								
								drivers/media/dvb-frontends/tc90522.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,840 @@ | ||||||
|  | /*
 | ||||||
|  |  * Toshiba TC90522 Demodulator | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU General Public License as | ||||||
|  |  * published by the Free Software Foundation version 2. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * NOTICE: | ||||||
|  |  * This driver is incomplete and lacks init/config of the chips, | ||||||
|  |  * as the necessary info is not disclosed. | ||||||
|  |  * It assumes that users of this driver (such as a PCI bridge of | ||||||
|  |  * DTV receiver cards) properly init and configure the chip | ||||||
|  |  * via I2C *before* calling this driver's init() function. | ||||||
|  |  * | ||||||
|  |  * Currently, PT3 driver is the only one that uses this driver, | ||||||
|  |  * and contains init/config code in its firmware. | ||||||
|  |  * Thus some part of the code might be dependent on PT3 specific config. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/math64.h> | ||||||
|  | #include <linux/dvb/frontend.h> | ||||||
|  | #include "dvb_math.h" | ||||||
|  | #include "tc90522.h" | ||||||
|  | 
 | ||||||
|  | #define TC90522_I2C_THRU_REG 0xfe | ||||||
|  | 
 | ||||||
|  | #define TC90522_MODULE_IDX(addr) (((u8)(addr) & 0x02U) >> 1) | ||||||
|  | 
 | ||||||
|  | struct tc90522_state { | ||||||
|  | 	struct tc90522_config cfg; | ||||||
|  | 	struct dvb_frontend fe; | ||||||
|  | 	struct i2c_client *i2c_client; | ||||||
|  | 	struct i2c_adapter tuner_i2c; | ||||||
|  | 
 | ||||||
|  | 	bool lna; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct reg_val { | ||||||
|  | 	u8 reg; | ||||||
|  | 	u8 val; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | reg_write(struct tc90522_state *state, const struct reg_val *regs, int num) | ||||||
|  | { | ||||||
|  | 	int i, ret; | ||||||
|  | 	struct i2c_msg msg; | ||||||
|  | 
 | ||||||
|  | 	ret = 0; | ||||||
|  | 	msg.addr = state->i2c_client->addr; | ||||||
|  | 	msg.flags = 0; | ||||||
|  | 	msg.len = 2; | ||||||
|  | 	for (i = 0; i < num; i++) { | ||||||
|  | 		msg.buf = (u8 *)®s[i]; | ||||||
|  | 		ret = i2c_transfer(state->i2c_client->adapter, &msg, 1); | ||||||
|  | 		if (ret == 0) | ||||||
|  | 			ret = -EIO; | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			return ret; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int reg_read(struct tc90522_state *state, u8 reg, u8 *val, u8 len) | ||||||
|  | { | ||||||
|  | 	struct i2c_msg msgs[2] = { | ||||||
|  | 		{ | ||||||
|  | 			.addr = state->i2c_client->addr, | ||||||
|  | 			.flags = 0, | ||||||
|  | 			.buf = ®, | ||||||
|  | 			.len = 1, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			.addr = state->i2c_client->addr, | ||||||
|  | 			.flags = I2C_M_RD, | ||||||
|  | 			.buf = val, | ||||||
|  | 			.len = len, | ||||||
|  | 		}, | ||||||
|  | 	}; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = i2c_transfer(state->i2c_client->adapter, msgs, ARRAY_SIZE(msgs)); | ||||||
|  | 	if (ret == ARRAY_SIZE(msgs)) | ||||||
|  | 		ret = 0; | ||||||
|  | 	else if (ret >= 0) | ||||||
|  | 		ret = -EIO; | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct tc90522_state *cfg_to_state(struct tc90522_config *c) | ||||||
|  | { | ||||||
|  | 	return container_of(c, struct tc90522_state, cfg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int tc90522s_set_tsid(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct reg_val set_tsid[] = { | ||||||
|  | 		{ 0x8f, 00 }, | ||||||
|  | 		{ 0x90, 00 } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	set_tsid[0].val = (fe->dtv_property_cache.stream_id & 0xff00) >> 8; | ||||||
|  | 	set_tsid[1].val = fe->dtv_property_cache.stream_id & 0xff; | ||||||
|  | 	return reg_write(fe->demodulator_priv, set_tsid, ARRAY_SIZE(set_tsid)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tc90522t_set_layers(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct reg_val rv; | ||||||
|  | 	u8 laysel; | ||||||
|  | 
 | ||||||
|  | 	laysel = ~fe->dtv_property_cache.isdbt_layer_enabled & 0x07; | ||||||
|  | 	laysel = (laysel & 0x01) << 2 | (laysel & 0x02) | (laysel & 0x04) >> 2; | ||||||
|  | 	rv.reg = 0x71; | ||||||
|  | 	rv.val = laysel; | ||||||
|  | 	return reg_write(fe->demodulator_priv, &rv, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* frontend ops */ | ||||||
|  | 
 | ||||||
|  | static int tc90522s_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	int ret; | ||||||
|  | 	u8 reg; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	ret = reg_read(state, 0xc3, ®, 1); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	*status = 0; | ||||||
|  | 	if (reg & 0x80) /* input level under min ? */ | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_SIGNAL; | ||||||
|  | 
 | ||||||
|  | 	if (reg & 0x60) /* carrier? */ | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; | ||||||
|  | 
 | ||||||
|  | 	if (reg & 0x10) | ||||||
|  | 		return 0; | ||||||
|  | 	if (reg_read(state, 0xc5, ®, 1) < 0 || !(reg & 0x03)) | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_LOCK; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tc90522t_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	int ret; | ||||||
|  | 	u8 reg; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	ret = reg_read(state, 0x96, ®, 1); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	*status = 0; | ||||||
|  | 	if (reg & 0xe0) { | ||||||
|  | 		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | ||||||
|  | 				| FE_HAS_SYNC | FE_HAS_LOCK; | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = reg_read(state, 0x80, ®, 1); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	if (reg & 0xf0) | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||||||
|  | 
 | ||||||
|  | 	if (reg & 0x0c) | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_SYNC | FE_HAS_VITERBI; | ||||||
|  | 
 | ||||||
|  | 	if (reg & 0x02) | ||||||
|  | 		return 0; | ||||||
|  | 	*status |= FE_HAS_LOCK; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const fe_code_rate_t fec_conv_sat[] = { | ||||||
|  | 	FEC_NONE, /* unused */ | ||||||
|  | 	FEC_1_2, /* for BPSK */ | ||||||
|  | 	FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, /* for QPSK */ | ||||||
|  | 	FEC_2_3, /* for 8PSK. (trellis code) */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int tc90522s_get_frontend(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	struct dtv_frontend_properties *c; | ||||||
|  | 	struct dtv_fe_stats *stats; | ||||||
|  | 	int ret, i; | ||||||
|  | 	int layers; | ||||||
|  | 	u8 val[10]; | ||||||
|  | 	u32 cndat; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	c = &fe->dtv_property_cache; | ||||||
|  | 	c->delivery_system = SYS_ISDBS; | ||||||
|  | 
 | ||||||
|  | 	layers = 0; | ||||||
|  | 	ret = reg_read(state, 0xe8, val, 3); | ||||||
|  | 	if (ret == 0) { | ||||||
|  | 		int slots; | ||||||
|  | 		u8 v; | ||||||
|  | 
 | ||||||
|  | 		/* high/single layer */ | ||||||
|  | 		v = (val[0] & 0x70) >> 4; | ||||||
|  | 		c->modulation = (v == 7) ? PSK_8 : QPSK; | ||||||
|  | 		c->fec_inner = fec_conv_sat[v]; | ||||||
|  | 		c->layer[0].fec = c->fec_inner; | ||||||
|  | 		c->layer[0].modulation = c->modulation; | ||||||
|  | 		c->layer[0].segment_count = val[1] & 0x3f; /* slots */ | ||||||
|  | 
 | ||||||
|  | 		/* low layer */ | ||||||
|  | 		v = (val[0] & 0x07); | ||||||
|  | 		c->layer[1].fec = fec_conv_sat[v]; | ||||||
|  | 		if (v == 0)  /* no low layer */ | ||||||
|  | 			c->layer[1].segment_count = 0; | ||||||
|  | 		else | ||||||
|  | 			c->layer[1].segment_count = val[2] & 0x3f; /* slots */ | ||||||
|  | 		/* actually, BPSK if v==1, but not defined in fe_modulation_t */ | ||||||
|  | 		c->layer[1].modulation = QPSK; | ||||||
|  | 		layers = (v > 0) ? 2 : 1; | ||||||
|  | 
 | ||||||
|  | 		slots =  c->layer[0].segment_count +  c->layer[1].segment_count; | ||||||
|  | 		c->symbol_rate = 28860000 * slots / 48; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* statistics */ | ||||||
|  | 
 | ||||||
|  | 	stats = &c->strength; | ||||||
|  | 	stats->len = 0; | ||||||
|  | 	/* let the connected tuner set RSSI property cache */ | ||||||
|  | 	if (fe->ops.tuner_ops.get_rf_strength) { | ||||||
|  | 		u16 dummy; | ||||||
|  | 
 | ||||||
|  | 		fe->ops.tuner_ops.get_rf_strength(fe, &dummy); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	stats = &c->cnr; | ||||||
|  | 	stats->len = 1; | ||||||
|  | 	stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	cndat = 0; | ||||||
|  | 	ret = reg_read(state, 0xbc, val, 2); | ||||||
|  | 	if (ret == 0) | ||||||
|  | 		cndat = val[0] << 8 | val[1]; | ||||||
|  | 	if (cndat >= 3000) { | ||||||
|  | 		u32 p, p4; | ||||||
|  | 		s64 cn; | ||||||
|  | 
 | ||||||
|  | 		cndat -= 3000;  /* cndat: 4.12 fixed point float */ | ||||||
|  | 		/*
 | ||||||
|  | 		 * cnr[mdB] = -1634.6 * P^5 + 14341 * P^4 - 50259 * P^3 | ||||||
|  | 		 *                 + 88977 * P^2 - 89565 * P + 58857 | ||||||
|  | 		 *  (P = sqrt(cndat) / 64) | ||||||
|  | 		 */ | ||||||
|  | 		/* p := sqrt(cndat) << 8 = P << 14, 2.14 fixed  point float */ | ||||||
|  | 		/* cn = cnr << 3 */ | ||||||
|  | 		p = int_sqrt(cndat << 16); | ||||||
|  | 		p4 = cndat * cndat; | ||||||
|  | 		cn = div64_s64(-16346LL * p4 * p, 10) >> 35; | ||||||
|  | 		cn += (14341LL * p4) >> 21; | ||||||
|  | 		cn -= (50259LL * cndat * p) >> 23; | ||||||
|  | 		cn += (88977LL * cndat) >> 9; | ||||||
|  | 		cn -= (89565LL * p) >> 11; | ||||||
|  | 		cn += 58857  << 3; | ||||||
|  | 		stats->stat[0].svalue = cn >> 3; | ||||||
|  | 		stats->stat[0].scale = FE_SCALE_DECIBEL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* per-layer post viterbi BER (or PER? config dependent?) */ | ||||||
|  | 	stats = &c->post_bit_error; | ||||||
|  | 	memset(stats, 0, sizeof(*stats)); | ||||||
|  | 	stats->len = layers; | ||||||
|  | 	ret = reg_read(state, 0xeb, val, 10); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		for (i = 0; i < layers; i++) | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	else { | ||||||
|  | 		for (i = 0; i < layers; i++) { | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_COUNTER; | ||||||
|  | 			stats->stat[i].uvalue = val[i * 5] << 16 | ||||||
|  | 				| val[i * 5 + 1] << 8 | val[i * 5 + 2]; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	stats = &c->post_bit_count; | ||||||
|  | 	memset(stats, 0, sizeof(*stats)); | ||||||
|  | 	stats->len = layers; | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		for (i = 0; i < layers; i++) | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	else { | ||||||
|  | 		for (i = 0; i < layers; i++) { | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_COUNTER; | ||||||
|  | 			stats->stat[i].uvalue = | ||||||
|  | 				val[i * 5 + 3] << 8 | val[i * 5 + 4]; | ||||||
|  | 			stats->stat[i].uvalue *= 204 * 8; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static const fe_transmit_mode_t tm_conv[] = { | ||||||
|  | 	TRANSMISSION_MODE_2K, | ||||||
|  | 	TRANSMISSION_MODE_4K, | ||||||
|  | 	TRANSMISSION_MODE_8K, | ||||||
|  | 	0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const fe_code_rate_t fec_conv_ter[] = { | ||||||
|  | 	FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, 0, 0, 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const fe_modulation_t mod_conv[] = { | ||||||
|  | 	DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int tc90522t_get_frontend(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	struct dtv_frontend_properties *c; | ||||||
|  | 	struct dtv_fe_stats *stats; | ||||||
|  | 	int ret, i; | ||||||
|  | 	int layers; | ||||||
|  | 	u8 val[15], mode; | ||||||
|  | 	u32 cndat; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	c = &fe->dtv_property_cache; | ||||||
|  | 	c->delivery_system = SYS_ISDBT; | ||||||
|  | 	c->bandwidth_hz = 6000000; | ||||||
|  | 	mode = 1; | ||||||
|  | 	ret = reg_read(state, 0xb0, val, 1); | ||||||
|  | 	if (ret == 0) { | ||||||
|  | 		mode = (val[0] & 0xc0) >> 2; | ||||||
|  | 		c->transmission_mode = tm_conv[mode]; | ||||||
|  | 		c->guard_interval = (val[0] & 0x30) >> 4; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = reg_read(state, 0xb2, val, 6); | ||||||
|  | 	layers = 0; | ||||||
|  | 	if (ret == 0) { | ||||||
|  | 		u8 v; | ||||||
|  | 
 | ||||||
|  | 		c->isdbt_partial_reception = val[0] & 0x01; | ||||||
|  | 		c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01; | ||||||
|  | 
 | ||||||
|  | 		/* layer A */ | ||||||
|  | 		v = (val[2] & 0x78) >> 3; | ||||||
|  | 		if (v == 0x0f) | ||||||
|  | 			c->layer[0].segment_count = 0; | ||||||
|  | 		else { | ||||||
|  | 			layers++; | ||||||
|  | 			c->layer[0].segment_count = v; | ||||||
|  | 			c->layer[0].fec = fec_conv_ter[(val[1] & 0x1c) >> 2]; | ||||||
|  | 			c->layer[0].modulation = mod_conv[(val[1] & 0xe0) >> 5]; | ||||||
|  | 			v = (val[1] & 0x03) << 1 | (val[2] & 0x80) >> 7; | ||||||
|  | 			c->layer[0].interleaving = v; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* layer B */ | ||||||
|  | 		v = (val[3] & 0x03) << 1 | (val[4] & 0xc0) >> 6; | ||||||
|  | 		if (v == 0x0f) | ||||||
|  | 			c->layer[1].segment_count = 0; | ||||||
|  | 		else { | ||||||
|  | 			layers++; | ||||||
|  | 			c->layer[1].segment_count = v; | ||||||
|  | 			c->layer[1].fec = fec_conv_ter[(val[3] & 0xe0) >> 5]; | ||||||
|  | 			c->layer[1].modulation = mod_conv[(val[2] & 0x07)]; | ||||||
|  | 			c->layer[1].interleaving = (val[3] & 0x1c) >> 2; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* layer C */ | ||||||
|  | 		v = (val[5] & 0x1e) >> 1; | ||||||
|  | 		if (v == 0x0f) | ||||||
|  | 			c->layer[2].segment_count = 0; | ||||||
|  | 		else { | ||||||
|  | 			layers++; | ||||||
|  | 			c->layer[2].segment_count = v; | ||||||
|  | 			c->layer[2].fec = fec_conv_ter[(val[4] & 0x07)]; | ||||||
|  | 			c->layer[2].modulation = mod_conv[(val[4] & 0x38) >> 3]; | ||||||
|  | 			c->layer[2].interleaving = (val[5] & 0xe0) >> 5; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* statistics */ | ||||||
|  | 
 | ||||||
|  | 	stats = &c->strength; | ||||||
|  | 	stats->len = 0; | ||||||
|  | 	/* let the connected tuner set RSSI property cache */ | ||||||
|  | 	if (fe->ops.tuner_ops.get_rf_strength) { | ||||||
|  | 		u16 dummy; | ||||||
|  | 
 | ||||||
|  | 		fe->ops.tuner_ops.get_rf_strength(fe, &dummy); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	stats = &c->cnr; | ||||||
|  | 	stats->len = 1; | ||||||
|  | 	stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	cndat = 0; | ||||||
|  | 	ret = reg_read(state, 0x8b, val, 3); | ||||||
|  | 	if (ret == 0) | ||||||
|  | 		cndat = val[0] << 16 | val[1] << 8 | val[2]; | ||||||
|  | 	if (cndat != 0) { | ||||||
|  | 		u32 p, tmp; | ||||||
|  | 		s64 cn; | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * cnr[mdB] = 0.024 P^4 - 1.6 P^3 + 39.8 P^2 + 549.1 P + 3096.5 | ||||||
|  | 		 * (P = 10log10(5505024/cndat)) | ||||||
|  | 		 */ | ||||||
|  | 		/* cn = cnr << 3 (61.3 fixed point float */ | ||||||
|  | 		/* p = 10log10(5505024/cndat) << 24  (8.24 fixed point float)*/ | ||||||
|  | 		p = intlog10(5505024) - intlog10(cndat); | ||||||
|  | 		p *= 10; | ||||||
|  | 
 | ||||||
|  | 		cn = 24772; | ||||||
|  | 		cn += div64_s64(43827LL * p, 10) >> 24; | ||||||
|  | 		tmp = p >> 8; | ||||||
|  | 		cn += div64_s64(3184LL * tmp * tmp, 10) >> 32; | ||||||
|  | 		tmp = p >> 13; | ||||||
|  | 		cn -= div64_s64(128LL * tmp * tmp * tmp, 10) >> 33; | ||||||
|  | 		tmp = p >> 18; | ||||||
|  | 		cn += div64_s64(192LL * tmp * tmp * tmp * tmp, 1000) >> 24; | ||||||
|  | 
 | ||||||
|  | 		stats->stat[0].svalue = cn >> 3; | ||||||
|  | 		stats->stat[0].scale = FE_SCALE_DECIBEL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* per-layer post viterbi BER (or PER? config dependent?) */ | ||||||
|  | 	stats = &c->post_bit_error; | ||||||
|  | 	memset(stats, 0, sizeof(*stats)); | ||||||
|  | 	stats->len = layers; | ||||||
|  | 	ret = reg_read(state, 0x9d, val, 15); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		for (i = 0; i < layers; i++) | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	else { | ||||||
|  | 		for (i = 0; i < layers; i++) { | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_COUNTER; | ||||||
|  | 			stats->stat[i].uvalue = val[i * 3] << 16 | ||||||
|  | 				| val[i * 3 + 1] << 8 | val[i * 3 + 2]; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	stats = &c->post_bit_count; | ||||||
|  | 	memset(stats, 0, sizeof(*stats)); | ||||||
|  | 	stats->len = layers; | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		for (i = 0; i < layers; i++) | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; | ||||||
|  | 	else { | ||||||
|  | 		for (i = 0; i < layers; i++) { | ||||||
|  | 			stats->stat[i].scale = FE_SCALE_COUNTER; | ||||||
|  | 			stats->stat[i].uvalue = | ||||||
|  | 				val[9 + i * 2] << 8 | val[9 + i * 2 + 1]; | ||||||
|  | 			stats->stat[i].uvalue *= 204 * 8; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct reg_val reset_sat = { 0x03, 0x01 }; | ||||||
|  | static const struct reg_val reset_ter = { 0x01, 0x40 }; | ||||||
|  | 
 | ||||||
|  | static int tc90522_set_frontend(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 
 | ||||||
|  | 	if (fe->ops.tuner_ops.set_params) | ||||||
|  | 		ret = fe->ops.tuner_ops.set_params(fe); | ||||||
|  | 	else | ||||||
|  | 		ret = -ENODEV; | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		goto failed; | ||||||
|  | 
 | ||||||
|  | 	if (fe->ops.delsys[0] == SYS_ISDBS) { | ||||||
|  | 		ret = tc90522s_set_tsid(fe); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			goto failed; | ||||||
|  | 		ret = reg_write(state, &reset_sat, 1); | ||||||
|  | 	} else { | ||||||
|  | 		ret = tc90522t_set_layers(fe); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			goto failed; | ||||||
|  | 		ret = reg_write(state, &reset_ter, 1); | ||||||
|  | 	} | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		goto failed; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | failed: | ||||||
|  | 	dev_warn(&state->tuner_i2c.dev, "(%s) failed. [adap%d-fe%d]\n", | ||||||
|  | 			__func__, fe->dvb->num, fe->id); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tc90522_get_tune_settings(struct dvb_frontend *fe, | ||||||
|  | 	struct dvb_frontend_tune_settings *settings) | ||||||
|  | { | ||||||
|  | 	if (fe->ops.delsys[0] == SYS_ISDBS) { | ||||||
|  | 		settings->min_delay_ms = 250; | ||||||
|  | 		settings->step_size = 1000; | ||||||
|  | 		settings->max_drift = settings->step_size * 2; | ||||||
|  | 	} else { | ||||||
|  | 		settings->min_delay_ms = 400; | ||||||
|  | 		settings->step_size = 142857; | ||||||
|  | 		settings->max_drift = settings->step_size; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tc90522_set_if_agc(struct dvb_frontend *fe, bool on) | ||||||
|  | { | ||||||
|  | 	struct reg_val agc_sat[] = { | ||||||
|  | 		{ 0x0a, 0x00 }, | ||||||
|  | 		{ 0x10, 0x30 }, | ||||||
|  | 		{ 0x11, 0x00 }, | ||||||
|  | 		{ 0x03, 0x01 }, | ||||||
|  | 	}; | ||||||
|  | 	struct reg_val agc_ter[] = { | ||||||
|  | 		{ 0x25, 0x00 }, | ||||||
|  | 		{ 0x23, 0x4c }, | ||||||
|  | 		{ 0x01, 0x40 }, | ||||||
|  | 	}; | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	struct reg_val *rv; | ||||||
|  | 	int num; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	if (fe->ops.delsys[0] == SYS_ISDBS) { | ||||||
|  | 		agc_sat[0].val = on ? 0xff : 0x00; | ||||||
|  | 		agc_sat[1].val |= 0x80; | ||||||
|  | 		agc_sat[1].val |= on ? 0x01 : 0x00; | ||||||
|  | 		agc_sat[2].val |= on ? 0x40 : 0x00; | ||||||
|  | 		rv = agc_sat; | ||||||
|  | 		num = ARRAY_SIZE(agc_sat); | ||||||
|  | 	} else { | ||||||
|  | 		agc_ter[0].val = on ? 0x40 : 0x00; | ||||||
|  | 		agc_ter[1].val |= on ? 0x00 : 0x01; | ||||||
|  | 		rv = agc_ter; | ||||||
|  | 		num = ARRAY_SIZE(agc_ter); | ||||||
|  | 	} | ||||||
|  | 	return reg_write(state, rv, num); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct reg_val sleep_sat = { 0x17, 0x01 }; | ||||||
|  | static const struct reg_val sleep_ter = { 0x03, 0x90 }; | ||||||
|  | 
 | ||||||
|  | static int tc90522_sleep(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	if (fe->ops.delsys[0] == SYS_ISDBS) | ||||||
|  | 		ret = reg_write(state, &sleep_sat, 1); | ||||||
|  | 	else { | ||||||
|  | 		ret = reg_write(state, &sleep_ter, 1); | ||||||
|  | 		if (ret == 0 && fe->ops.set_lna && | ||||||
|  | 		    fe->dtv_property_cache.lna == LNA_AUTO) { | ||||||
|  | 			fe->dtv_property_cache.lna = 0; | ||||||
|  | 			ret = fe->ops.set_lna(fe); | ||||||
|  | 			fe->dtv_property_cache.lna = LNA_AUTO; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		dev_warn(&state->tuner_i2c.dev, | ||||||
|  | 			"(%s) failed. [adap%d-fe%d]\n", | ||||||
|  | 			__func__, fe->dvb->num, fe->id); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct reg_val wakeup_sat = { 0x17, 0x00 }; | ||||||
|  | static const struct reg_val wakeup_ter = { 0x03, 0x80 }; | ||||||
|  | 
 | ||||||
|  | static int tc90522_init(struct dvb_frontend *fe) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Because the init sequence is not public, | ||||||
|  | 	 * the parent device/driver should have init'ed the device before. | ||||||
|  | 	 * just wake up the device here. | ||||||
|  | 	 */ | ||||||
|  | 
 | ||||||
|  | 	state = fe->demodulator_priv; | ||||||
|  | 	if (fe->ops.delsys[0] == SYS_ISDBS) | ||||||
|  | 		ret = reg_write(state, &wakeup_sat, 1); | ||||||
|  | 	else { | ||||||
|  | 		ret = reg_write(state, &wakeup_ter, 1); | ||||||
|  | 		if (ret == 0 && fe->ops.set_lna && | ||||||
|  | 		    fe->dtv_property_cache.lna == LNA_AUTO) { | ||||||
|  | 			fe->dtv_property_cache.lna = 1; | ||||||
|  | 			ret = fe->ops.set_lna(fe); | ||||||
|  | 			fe->dtv_property_cache.lna = LNA_AUTO; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		dev_warn(&state->tuner_i2c.dev, | ||||||
|  | 			"(%s) failed. [adap%d-fe%d]\n", | ||||||
|  | 			__func__, fe->dvb->num, fe->id); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* prefer 'all-layers' to 'none' as a default */ | ||||||
|  | 	if (fe->dtv_property_cache.isdbt_layer_enabled == 0) | ||||||
|  | 		fe->dtv_property_cache.isdbt_layer_enabled = 7; | ||||||
|  | 	return tc90522_set_if_agc(fe, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * tuner I2C adapter functions | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | tc90522_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	struct i2c_msg *new_msgs; | ||||||
|  | 	int i, j; | ||||||
|  | 	int ret, rd_num; | ||||||
|  | 	u8 wbuf[256]; | ||||||
|  | 	u8 *p, *bufend; | ||||||
|  | 
 | ||||||
|  | 	if (num <= 0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	rd_num = 0; | ||||||
|  | 	for (i = 0; i < num; i++) | ||||||
|  | 		if (msgs[i].flags & I2C_M_RD) | ||||||
|  | 			rd_num++; | ||||||
|  | 	new_msgs = kmalloc(sizeof(*new_msgs) * (num + rd_num), GFP_KERNEL); | ||||||
|  | 	if (!new_msgs) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	state = i2c_get_adapdata(adap); | ||||||
|  | 	p = wbuf; | ||||||
|  | 	bufend = wbuf + sizeof(wbuf); | ||||||
|  | 	for (i = 0, j = 0; i < num; i++, j++) { | ||||||
|  | 		new_msgs[j].addr = state->i2c_client->addr; | ||||||
|  | 		new_msgs[j].flags = msgs[i].flags; | ||||||
|  | 
 | ||||||
|  | 		if (msgs[i].flags & I2C_M_RD) { | ||||||
|  | 			new_msgs[j].flags &= ~I2C_M_RD; | ||||||
|  | 			if (p + 2 > bufend) | ||||||
|  | 				break; | ||||||
|  | 			p[0] = TC90522_I2C_THRU_REG; | ||||||
|  | 			p[1] = msgs[i].addr << 1 | 0x01; | ||||||
|  | 			new_msgs[j].buf = p; | ||||||
|  | 			new_msgs[j].len = 2; | ||||||
|  | 			p += 2; | ||||||
|  | 			j++; | ||||||
|  | 			new_msgs[j].addr = state->i2c_client->addr; | ||||||
|  | 			new_msgs[j].flags = msgs[i].flags; | ||||||
|  | 			new_msgs[j].buf = msgs[i].buf; | ||||||
|  | 			new_msgs[j].len = msgs[i].len; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (p + msgs[i].len + 2 > bufend) | ||||||
|  | 			break; | ||||||
|  | 		p[0] = TC90522_I2C_THRU_REG; | ||||||
|  | 		p[1] = msgs[i].addr << 1; | ||||||
|  | 		memcpy(p + 2, msgs[i].buf, msgs[i].len); | ||||||
|  | 		new_msgs[j].buf = p; | ||||||
|  | 		new_msgs[j].len = msgs[i].len + 2; | ||||||
|  | 		p += new_msgs[j].len; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (i < num) | ||||||
|  | 		ret = -ENOMEM; | ||||||
|  | 	else | ||||||
|  | 		ret = i2c_transfer(state->i2c_client->adapter, new_msgs, j); | ||||||
|  | 	if (ret >= 0 && ret < j) | ||||||
|  | 		ret = -EIO; | ||||||
|  | 	kfree(new_msgs); | ||||||
|  | 	return (ret == j) ? num : ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static u32 tc90522_functionality(struct i2c_adapter *adap) | ||||||
|  | { | ||||||
|  | 	return I2C_FUNC_I2C; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct i2c_algorithm tc90522_tuner_i2c_algo = { | ||||||
|  | 	.master_xfer   = &tc90522_master_xfer, | ||||||
|  | 	.functionality = &tc90522_functionality, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * I2C driver functions | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static const struct dvb_frontend_ops tc90522_ops_sat = { | ||||||
|  | 	.delsys = { SYS_ISDBS }, | ||||||
|  | 	.info = { | ||||||
|  | 		.name = "Toshiba TC90522 ISDB-S module", | ||||||
|  | 		.frequency_min =  950000, | ||||||
|  | 		.frequency_max = 2150000, | ||||||
|  | 		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | | ||||||
|  | 			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||||||
|  | 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	.init = tc90522_init, | ||||||
|  | 	.sleep = tc90522_sleep, | ||||||
|  | 	.set_frontend = tc90522_set_frontend, | ||||||
|  | 	.get_tune_settings = tc90522_get_tune_settings, | ||||||
|  | 
 | ||||||
|  | 	.get_frontend = tc90522s_get_frontend, | ||||||
|  | 	.read_status = tc90522s_read_status, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct dvb_frontend_ops tc90522_ops_ter = { | ||||||
|  | 	.delsys = { SYS_ISDBT }, | ||||||
|  | 	.info = { | ||||||
|  | 		.name = "Toshiba TC90522 ISDB-T module", | ||||||
|  | 		.frequency_min = 470000000, | ||||||
|  | 		.frequency_max = 770000000, | ||||||
|  | 		.frequency_stepsize = 142857, | ||||||
|  | 		.caps = FE_CAN_INVERSION_AUTO | | ||||||
|  | 			FE_CAN_FEC_1_2  | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||||
|  | 			FE_CAN_FEC_5_6  | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||||||
|  | 			FE_CAN_QPSK     | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||||||
|  | 			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||||||
|  | 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | | ||||||
|  | 			FE_CAN_HIERARCHY_AUTO, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	.init = tc90522_init, | ||||||
|  | 	.sleep = tc90522_sleep, | ||||||
|  | 	.set_frontend = tc90522_set_frontend, | ||||||
|  | 	.get_tune_settings = tc90522_get_tune_settings, | ||||||
|  | 
 | ||||||
|  | 	.get_frontend = tc90522t_get_frontend, | ||||||
|  | 	.read_status = tc90522t_read_status, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int tc90522_probe(struct i2c_client *client, | ||||||
|  | 			 const struct i2c_device_id *id) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 	struct tc90522_config *cfg; | ||||||
|  | 	const struct dvb_frontend_ops *ops; | ||||||
|  | 	struct i2c_adapter *adap; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	state = kzalloc(sizeof(*state), GFP_KERNEL); | ||||||
|  | 	if (!state) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	state->i2c_client = client; | ||||||
|  | 
 | ||||||
|  | 	cfg = client->dev.platform_data; | ||||||
|  | 	memcpy(&state->cfg, cfg, sizeof(state->cfg)); | ||||||
|  | 	cfg->fe = state->cfg.fe = &state->fe; | ||||||
|  | 	ops =  id->driver_data == 0 ? &tc90522_ops_sat : &tc90522_ops_ter; | ||||||
|  | 	memcpy(&state->fe.ops, ops, sizeof(*ops)); | ||||||
|  | 	state->fe.demodulator_priv = state; | ||||||
|  | 
 | ||||||
|  | 	adap = &state->tuner_i2c; | ||||||
|  | 	adap->owner = THIS_MODULE; | ||||||
|  | 	adap->algo = &tc90522_tuner_i2c_algo; | ||||||
|  | 	adap->dev.parent = &client->dev; | ||||||
|  | 	strlcpy(adap->name, "tc90522_sub", sizeof(adap->name)); | ||||||
|  | 	i2c_set_adapdata(adap, state); | ||||||
|  | 	ret = i2c_add_adapter(adap); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		goto err; | ||||||
|  | 	cfg->tuner_i2c = state->cfg.tuner_i2c = adap; | ||||||
|  | 
 | ||||||
|  | 	i2c_set_clientdata(client, &state->cfg); | ||||||
|  | 	dev_info(&client->dev, "Toshiba TC90522 attached.\n"); | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | err: | ||||||
|  | 	kfree(state); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tc90522_remove(struct i2c_client *client) | ||||||
|  | { | ||||||
|  | 	struct tc90522_state *state; | ||||||
|  | 
 | ||||||
|  | 	state = cfg_to_state(i2c_get_clientdata(client)); | ||||||
|  | 	i2c_del_adapter(&state->tuner_i2c); | ||||||
|  | 	kfree(state); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static const struct i2c_device_id tc90522_id[] = { | ||||||
|  | 	{ TC90522_I2C_DEV_SAT, 0 }, | ||||||
|  | 	{ TC90522_I2C_DEV_TER, 1 }, | ||||||
|  | 	{} | ||||||
|  | }; | ||||||
|  | MODULE_DEVICE_TABLE(i2c, tc90522_id); | ||||||
|  | 
 | ||||||
|  | static struct i2c_driver tc90522_driver = { | ||||||
|  | 	.driver = { | ||||||
|  | 		.name	= "tc90522", | ||||||
|  | 	}, | ||||||
|  | 	.probe		= tc90522_probe, | ||||||
|  | 	.remove		= tc90522_remove, | ||||||
|  | 	.id_table	= tc90522_id, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module_i2c_driver(tc90522_driver); | ||||||
|  | 
 | ||||||
|  | MODULE_DESCRIPTION("Toshiba TC90522 frontend"); | ||||||
|  | MODULE_AUTHOR("Akihiro TSUKADA"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
							
								
								
									
										42
									
								
								drivers/media/dvb-frontends/tc90522.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								drivers/media/dvb-frontends/tc90522.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | /*
 | ||||||
|  |  * Toshiba TC90522 Demodulator | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU General Public License as | ||||||
|  |  * published by the Free Software Foundation version 2. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * The demod has 4 input (2xISDB-T and 2xISDB-S), | ||||||
|  |  * and provides independent sub modules for each input. | ||||||
|  |  * As the sub modules work in parallel and have the separate i2c addr's, | ||||||
|  |  * this driver treats each sub module as one demod device. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef TC90522_H | ||||||
|  | #define TC90522_H | ||||||
|  | 
 | ||||||
|  | #include <linux/i2c.h> | ||||||
|  | #include "dvb_frontend.h" | ||||||
|  | 
 | ||||||
|  | /* I2C device types */ | ||||||
|  | #define TC90522_I2C_DEV_SAT "tc90522sat" | ||||||
|  | #define TC90522_I2C_DEV_TER "tc90522ter" | ||||||
|  | 
 | ||||||
|  | struct tc90522_config { | ||||||
|  | 	/* [OUT] frontend returned by driver */ | ||||||
|  | 	struct dvb_frontend *fe; | ||||||
|  | 
 | ||||||
|  | 	/* [OUT] tuner I2C adapter returned by driver */ | ||||||
|  | 	struct i2c_adapter *tuner_i2c; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* TC90522_H */ | ||||||
|  | @ -1037,7 +1037,7 @@ static int tda10071_init(struct dvb_frontend *fe) | ||||||
| 			ret = -EFAULT; | 			ret = -EFAULT; | ||||||
| 			goto error; | 			goto error; | ||||||
| 		} else { | 		} else { | ||||||
| 			priv->warm = 1; | 			priv->warm = true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		cmd.args[0] = CMD_GET_FW_VERSION; | 		cmd.args[0] = CMD_GET_FW_VERSION; | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ static int zl10039_write(struct zl10039_state *state, | ||||||
| 
 | 
 | ||||||
| 	if (1 + count > sizeof(buf)) { | 	if (1 + count > sizeof(buf)) { | ||||||
| 		printk(KERN_WARNING | 		printk(KERN_WARNING | ||||||
| 		       "%s: i2c wr reg=%04x: len=%zd is too big!\n", | 		       "%s: i2c wr reg=%04x: len=%zu is too big!\n", | ||||||
| 		       KBUILD_MODNAME, reg, count); | 		       KBUILD_MODNAME, reg, count); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1157,6 +1157,10 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | ||||||
| 		if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | 		if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||||||
| 			dev_err(fdtv->device, | 			dev_err(fdtv->device, | ||||||
| 				"invalid pmt_cmd_id %d\n", pmt_cmd_id); | 				"invalid pmt_cmd_id %d\n", pmt_cmd_id); | ||||||
|  | 		if (program_info_length > sizeof(c->operand) - 4 - write_pos) { | ||||||
|  | 			ret = -EINVAL; | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		memcpy(&c->operand[write_pos], &msg[read_pos], | 		memcpy(&c->operand[write_pos], &msg[read_pos], | ||||||
| 		       program_info_length); | 		       program_info_length); | ||||||
|  | @ -1180,6 +1184,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | ||||||
| 				dev_err(fdtv->device, "invalid pmt_cmd_id %d " | 				dev_err(fdtv->device, "invalid pmt_cmd_id %d " | ||||||
| 					"at stream level\n", pmt_cmd_id); | 					"at stream level\n", pmt_cmd_id); | ||||||
| 
 | 
 | ||||||
|  | 			if (es_info_length > sizeof(c->operand) - 4 - | ||||||
|  | 					     write_pos) { | ||||||
|  | 				ret = -EINVAL; | ||||||
|  | 				goto out; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			memcpy(&c->operand[write_pos], &msg[read_pos], | 			memcpy(&c->operand[write_pos], &msg[read_pos], | ||||||
| 			       es_info_length); | 			       es_info_length); | ||||||
| 			read_pos += es_info_length; | 			read_pos += es_info_length; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef ADV7343_REG_H | #ifndef ADV7343_REGS_H | ||||||
| #define ADV7343_REGS_H | #define ADV7343_REGS_H | ||||||
| 
 | 
 | ||||||
| struct adv7343_std_info { | struct adv7343_std_info { | ||||||
|  |  | ||||||
|  | @ -1593,7 +1593,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | ||||||
| 			bt->height += hdmi_read16(sd, 0x0b, 0xfff); | 			bt->height += hdmi_read16(sd, 0x0b, 0xfff); | ||||||
| 			bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2; | 			bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2; | ||||||
| 			bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2; | 			bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2; | ||||||
| 			bt->vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2; | 			bt->il_vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2; | ||||||
| 		} | 		} | ||||||
| 		adv7604_fill_optional_dv_timings_fields(sd, timings); | 		adv7604_fill_optional_dv_timings_fields(sd, timings); | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
|  | @ -1435,6 +1435,8 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, | ||||||
| 
 | 
 | ||||||
| 	v4l2_dbg(1, debug, sd, "%s:\n", __func__); | 	v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||||||
| 
 | 
 | ||||||
|  | 	memset(timings, 0, sizeof(struct v4l2_dv_timings)); | ||||||
|  | 
 | ||||||
| 	/* SDP block */ | 	/* SDP block */ | ||||||
| 	if (state->mode == ADV7842_MODE_SDP) | 	if (state->mode == ADV7842_MODE_SDP) | ||||||
| 		return -ENODATA; | 		return -ENODATA; | ||||||
|  | @ -1483,7 +1485,7 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, | ||||||
| 					hdmi_read(sd, 0x2d)) / 2; | 					hdmi_read(sd, 0x2d)) / 2; | ||||||
| 			bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 + | 			bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 + | ||||||
| 					hdmi_read(sd, 0x31)) / 2; | 					hdmi_read(sd, 0x31)) / 2; | ||||||
| 			bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 + | 			bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 + | ||||||
| 					hdmi_read(sd, 0x35)) / 2; | 					hdmi_read(sd, 0x35)) / 2; | ||||||
| 		} | 		} | ||||||
| 		adv7842_fill_optional_dv_timings_fields(sd, timings); | 		adv7842_fill_optional_dv_timings_fields(sd, timings); | ||||||
|  |  | ||||||
|  | @ -100,14 +100,14 @@ static int lm3560_enable_ctrl(struct lm3560_flash *flash, | ||||||
| 	int rval; | 	int rval; | ||||||
| 
 | 
 | ||||||
| 	if (led_no == LM3560_LED0) { | 	if (led_no == LM3560_LED0) { | ||||||
| 		if (on == true) | 		if (on) | ||||||
| 			rval = regmap_update_bits(flash->regmap, | 			rval = regmap_update_bits(flash->regmap, | ||||||
| 						  REG_ENABLE, 0x08, 0x08); | 						  REG_ENABLE, 0x08, 0x08); | ||||||
| 		else | 		else | ||||||
| 			rval = regmap_update_bits(flash->regmap, | 			rval = regmap_update_bits(flash->regmap, | ||||||
| 						  REG_ENABLE, 0x08, 0x00); | 						  REG_ENABLE, 0x08, 0x00); | ||||||
| 	} else { | 	} else { | ||||||
| 		if (on == true) | 		if (on) | ||||||
| 			rval = regmap_update_bits(flash->regmap, | 			rval = regmap_update_bits(flash->regmap, | ||||||
| 						  REG_ENABLE, 0x10, 0x10); | 						  REG_ENABLE, 0x10, 0x10); | ||||||
| 		else | 		else | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ | ||||||
| #include <media/v4l2-device.h> | #include <media/v4l2-device.h> | ||||||
| #include <media/v4l2-ctrls.h> | #include <media/v4l2-ctrls.h> | ||||||
| #include <media/v4l2-mediabus.h> | #include <media/v4l2-mediabus.h> | ||||||
|  | #include <media/v4l2-image-sizes.h> | ||||||
| #include <media/ov7670.h> | #include <media/ov7670.h> | ||||||
| 
 | 
 | ||||||
| MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); | ||||||
|  | @ -29,19 +30,6 @@ static bool debug; | ||||||
| module_param(debug, bool, 0644); | module_param(debug, bool, 0644); | ||||||
| MODULE_PARM_DESC(debug, "Debug level (0-1)"); | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Basic window sizes.  These probably belong somewhere more globally |  | ||||||
|  * useful. |  | ||||||
|  */ |  | ||||||
| #define VGA_WIDTH	640 |  | ||||||
| #define VGA_HEIGHT	480 |  | ||||||
| #define QVGA_WIDTH	320 |  | ||||||
| #define QVGA_HEIGHT	240 |  | ||||||
| #define CIF_WIDTH	352 |  | ||||||
| #define CIF_HEIGHT	288 |  | ||||||
| #define QCIF_WIDTH	176 |  | ||||||
| #define	QCIF_HEIGHT	144 |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * The 7670 sits on i2c with ID 0x42 |  * The 7670 sits on i2c with ID 0x42 | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -816,7 +816,7 @@ static void s5k5baf_hw_find_min_fiv(struct s5k5baf *state) | ||||||
| 				 "error setting frame interval: %d\n", err); | 				 "error setting frame interval: %d\n", err); | ||||||
| 			state->error = -EINVAL; | 			state->error = -EINVAL; | ||||||
| 		} | 		} | ||||||
| 	}; | 	} | ||||||
| 	v4l2_err(&state->sd, "cannot find correct frame interval\n"); | 	v4l2_err(&state->sd, "cannot find correct frame interval\n"); | ||||||
| 	state->error = -ERANGE; | 	state->error = -ERANGE; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -660,7 +660,7 @@ static const struct v4l2_subdev_ops saa6752hs_ops = { | ||||||
| static int saa6752hs_probe(struct i2c_client *client, | static int saa6752hs_probe(struct i2c_client *client, | ||||||
| 		const struct i2c_device_id *id) | 		const struct i2c_device_id *id) | ||||||
| { | { | ||||||
| 	struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | 	struct saa6752hs_state *h; | ||||||
| 	struct v4l2_subdev *sd; | 	struct v4l2_subdev *sd; | ||||||
| 	struct v4l2_ctrl_handler *hdl; | 	struct v4l2_ctrl_handler *hdl; | ||||||
| 	u8 addr = 0x13; | 	u8 addr = 0x13; | ||||||
|  | @ -668,6 +668,8 @@ static int saa6752hs_probe(struct i2c_client *client, | ||||||
| 
 | 
 | ||||||
| 	v4l_info(client, "chip found @ 0x%x (%s)\n", | 	v4l_info(client, "chip found @ 0x%x (%s)\n", | ||||||
| 			client->addr << 1, client->adapter->name); | 			client->addr << 1, client->adapter->name); | ||||||
|  | 
 | ||||||
|  | 	h = devm_kzalloc(&client->dev, sizeof(*h), GFP_KERNEL); | ||||||
| 	if (h == NULL) | 	if (h == NULL) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	sd = &h->sd; | 	sd = &h->sd; | ||||||
|  | @ -752,7 +754,6 @@ static int saa6752hs_probe(struct i2c_client *client, | ||||||
| 		int err = hdl->error; | 		int err = hdl->error; | ||||||
| 
 | 
 | ||||||
| 		v4l2_ctrl_handler_free(hdl); | 		v4l2_ctrl_handler_free(hdl); | ||||||
| 		kfree(h); |  | ||||||
| 		return err; | 		return err; | ||||||
| 	} | 	} | ||||||
| 	v4l2_ctrl_cluster(3, &h->video_bitrate_mode); | 	v4l2_ctrl_cluster(3, &h->video_bitrate_mode); | ||||||
|  | @ -767,7 +768,6 @@ static int saa6752hs_remove(struct i2c_client *client) | ||||||
| 
 | 
 | ||||||
| 	v4l2_device_unregister_subdev(sd); | 	v4l2_device_unregister_subdev(sd); | ||||||
| 	v4l2_ctrl_handler_free(&to_state(sd)->hdl); | 	v4l2_ctrl_handler_free(&to_state(sd)->hdl); | ||||||
| 	kfree(to_state(sd)); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -31,8 +31,9 @@ | ||||||
| #include <linux/device.h> | #include <linux/device.h> | ||||||
| #include <linux/gpio.h> | #include <linux/gpio.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/slab.h> |  | ||||||
| #include <linux/regulator/consumer.h> | #include <linux/regulator/consumer.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/smiapp.h> | ||||||
| #include <linux/v4l2-mediabus.h> | #include <linux/v4l2-mediabus.h> | ||||||
| #include <media/v4l2-device.h> | #include <media/v4l2-device.h> | ||||||
| 
 | 
 | ||||||
|  | @ -297,8 +298,9 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor) | ||||||
| 	if (rval < 0) | 	if (rval < 0) | ||||||
| 		return rval; | 		return rval; | ||||||
| 
 | 
 | ||||||
| 	*sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz; | 	__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray, | ||||||
| 	*sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi; | 				 pll->vt_pix_clk_freq_hz); | ||||||
|  | 	__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -319,13 +321,7 @@ static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor) | ||||||
| 		+ sensor->vblank->val | 		+ sensor->vblank->val | ||||||
| 		- sensor->limits[SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN]; | 		- sensor->limits[SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN]; | ||||||
| 
 | 
 | ||||||
| 	ctrl->maximum = max; | 	__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max); | ||||||
| 	if (ctrl->default_value > max) |  | ||||||
| 		ctrl->default_value = max; |  | ||||||
| 	if (ctrl->val > max) |  | ||||||
| 		ctrl->val = max; |  | ||||||
| 	if (ctrl->cur.val > max) |  | ||||||
| 		ctrl->cur.val = max; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -404,6 +400,14 @@ static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor) | ||||||
| 		pixel_order_str[pixel_order]); | 		pixel_order_str[pixel_order]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const char * const smiapp_test_patterns[] = { | ||||||
|  | 	"Disabled", | ||||||
|  | 	"Solid Colour", | ||||||
|  | 	"Eight Vertical Colour Bars", | ||||||
|  | 	"Colour Bars With Fade to Grey", | ||||||
|  | 	"Pseudorandom Sequence (PN9)", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) | static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) | ||||||
| { | { | ||||||
| 	struct smiapp_sensor *sensor = | 	struct smiapp_sensor *sensor = | ||||||
|  | @ -477,6 +481,39 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) | ||||||
| 
 | 
 | ||||||
| 		return smiapp_pll_update(sensor); | 		return smiapp_pll_update(sensor); | ||||||
| 
 | 
 | ||||||
|  | 	case V4L2_CID_TEST_PATTERN: { | ||||||
|  | 		unsigned int i; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) | ||||||
|  | 			v4l2_ctrl_activate( | ||||||
|  | 				sensor->test_data[i], | ||||||
|  | 				ctrl->val == | ||||||
|  | 				V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR); | ||||||
|  | 
 | ||||||
|  | 		return smiapp_write( | ||||||
|  | 			sensor, SMIAPP_REG_U16_TEST_PATTERN_MODE, ctrl->val); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	case V4L2_CID_TEST_PATTERN_RED: | ||||||
|  | 		return smiapp_write( | ||||||
|  | 			sensor, SMIAPP_REG_U16_TEST_DATA_RED, ctrl->val); | ||||||
|  | 
 | ||||||
|  | 	case V4L2_CID_TEST_PATTERN_GREENR: | ||||||
|  | 		return smiapp_write( | ||||||
|  | 			sensor, SMIAPP_REG_U16_TEST_DATA_GREENR, ctrl->val); | ||||||
|  | 
 | ||||||
|  | 	case V4L2_CID_TEST_PATTERN_BLUE: | ||||||
|  | 		return smiapp_write( | ||||||
|  | 			sensor, SMIAPP_REG_U16_TEST_DATA_BLUE, ctrl->val); | ||||||
|  | 
 | ||||||
|  | 	case V4L2_CID_TEST_PATTERN_GREENB: | ||||||
|  | 		return smiapp_write( | ||||||
|  | 			sensor, SMIAPP_REG_U16_TEST_DATA_GREENB, ctrl->val); | ||||||
|  | 
 | ||||||
|  | 	case V4L2_CID_PIXEL_RATE: | ||||||
|  | 		/* For v4l2_ctrl_s_ctrl_int64() used internally. */ | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
| 	default: | 	default: | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
|  | @ -489,10 +526,10 @@ static const struct v4l2_ctrl_ops smiapp_ctrl_ops = { | ||||||
| static int smiapp_init_controls(struct smiapp_sensor *sensor) | static int smiapp_init_controls(struct smiapp_sensor *sensor) | ||||||
| { | { | ||||||
| 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | ||||||
| 	unsigned int max; | 	unsigned int max, i; | ||||||
| 	int rval; | 	int rval; | ||||||
| 
 | 
 | ||||||
| 	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 7); | 	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12); | ||||||
| 	if (rval) | 	if (rval) | ||||||
| 		return rval; | 		return rval; | ||||||
| 	sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; | 	sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; | ||||||
|  | @ -535,6 +572,20 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor) | ||||||
| 		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops, | 		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops, | ||||||
| 		V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); | 		V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); | ||||||
| 
 | 
 | ||||||
|  | 	v4l2_ctrl_new_std_menu_items(&sensor->pixel_array->ctrl_handler, | ||||||
|  | 				     &smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN, | ||||||
|  | 				     ARRAY_SIZE(smiapp_test_patterns) - 1, | ||||||
|  | 				     0, 0, smiapp_test_patterns); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { | ||||||
|  | 		int max_value = (1 << sensor->csi_format->width) - 1; | ||||||
|  | 		sensor->test_data[i] = | ||||||
|  | 			v4l2_ctrl_new_std( | ||||||
|  | 				&sensor->pixel_array->ctrl_handler, | ||||||
|  | 				&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i, | ||||||
|  | 				0, max_value, 1, max_value); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (sensor->pixel_array->ctrl_handler.error) { | 	if (sensor->pixel_array->ctrl_handler.error) { | ||||||
| 		dev_err(&client->dev, | 		dev_err(&client->dev, | ||||||
| 			"pixel array controls initialization failed (%d)\n", | 			"pixel array controls initialization failed (%d)\n", | ||||||
|  | @ -782,36 +833,25 @@ static void smiapp_update_blanking(struct smiapp_sensor *sensor) | ||||||
| { | { | ||||||
| 	struct v4l2_ctrl *vblank = sensor->vblank; | 	struct v4l2_ctrl *vblank = sensor->vblank; | ||||||
| 	struct v4l2_ctrl *hblank = sensor->hblank; | 	struct v4l2_ctrl *hblank = sensor->hblank; | ||||||
|  | 	int min, max; | ||||||
| 
 | 
 | ||||||
| 	vblank->minimum = | 	min = max_t(int, | ||||||
| 		max_t(int, | 		    sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES], | ||||||
| 		      sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES], | 		    sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] - | ||||||
| 		      sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] - | 		    sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height); | ||||||
| 		      sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height); | 	max = sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] - | ||||||
| 	vblank->maximum = |  | ||||||
| 		sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] - |  | ||||||
| 		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height; | 		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height; | ||||||
| 
 | 
 | ||||||
| 	vblank->val = clamp_t(int, vblank->val, | 	__v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); | ||||||
| 			      vblank->minimum, vblank->maximum); |  | ||||||
| 	vblank->default_value = vblank->minimum; |  | ||||||
| 	vblank->val = vblank->val; |  | ||||||
| 	vblank->cur.val = vblank->val; |  | ||||||
| 
 | 
 | ||||||
| 	hblank->minimum = | 	min = max_t(int, | ||||||
| 		max_t(int, | 		    sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] - | ||||||
| 		      sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] - | 		    sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width, | ||||||
| 		      sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width, | 		    sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]); | ||||||
| 		      sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]); | 	max = sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] - | ||||||
| 	hblank->maximum = |  | ||||||
| 		sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] - |  | ||||||
| 		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width; | 		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width; | ||||||
| 
 | 
 | ||||||
| 	hblank->val = clamp_t(int, hblank->val, | 	__v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min); | ||||||
| 			      hblank->minimum, hblank->maximum); |  | ||||||
| 	hblank->default_value = hblank->minimum; |  | ||||||
| 	hblank->val = hblank->val; |  | ||||||
| 	hblank->cur.val = hblank->val; |  | ||||||
| 
 | 
 | ||||||
| 	__smiapp_update_exposure_limits(sensor); | 	__smiapp_update_exposure_limits(sensor); | ||||||
| } | } | ||||||
|  | @ -1272,7 +1312,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor) | ||||||
| 		clk_disable_unprepare(sensor->ext_clk); | 		clk_disable_unprepare(sensor->ext_clk); | ||||||
| 	usleep_range(5000, 5000); | 	usleep_range(5000, 5000); | ||||||
| 	regulator_disable(sensor->vana); | 	regulator_disable(sensor->vana); | ||||||
| 	sensor->streaming = 0; | 	sensor->streaming = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int smiapp_set_power(struct v4l2_subdev *subdev, int on) | static int smiapp_set_power(struct v4l2_subdev *subdev, int on) | ||||||
|  | @ -1462,13 +1502,13 @@ static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	if (enable) { | 	if (enable) { | ||||||
| 		sensor->streaming = 1; | 		sensor->streaming = true; | ||||||
| 		rval = smiapp_start_streaming(sensor); | 		rval = smiapp_start_streaming(sensor); | ||||||
| 		if (rval < 0) | 		if (rval < 0) | ||||||
| 			sensor->streaming = 0; | 			sensor->streaming = false; | ||||||
| 	} else { | 	} else { | ||||||
| 		rval = smiapp_stop_streaming(sensor); | 		rval = smiapp_stop_streaming(sensor); | ||||||
| 		sensor->streaming = 0; | 		sensor->streaming = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return rval; | 	return rval; | ||||||
|  | @ -1664,17 +1704,34 @@ static int smiapp_set_format(struct v4l2_subdev *subdev, | ||||||
| 	if (fmt->pad == ssd->source_pad) { | 	if (fmt->pad == ssd->source_pad) { | ||||||
| 		u32 code = fmt->format.code; | 		u32 code = fmt->format.code; | ||||||
| 		int rval = __smiapp_get_format(subdev, fh, fmt); | 		int rval = __smiapp_get_format(subdev, fh, fmt); | ||||||
|  | 		bool range_changed = false; | ||||||
|  | 		unsigned int i; | ||||||
| 
 | 
 | ||||||
| 		if (!rval && subdev == &sensor->src->sd) { | 		if (!rval && subdev == &sensor->src->sd) { | ||||||
| 			const struct smiapp_csi_data_format *csi_format = | 			const struct smiapp_csi_data_format *csi_format = | ||||||
| 				smiapp_validate_csi_data_format(sensor, code); | 				smiapp_validate_csi_data_format(sensor, code); | ||||||
| 			if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) | 
 | ||||||
|  | 			if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||||||
|  | 				if (csi_format->width != | ||||||
|  | 				    sensor->csi_format->width) | ||||||
|  | 					range_changed = true; | ||||||
|  | 
 | ||||||
| 				sensor->csi_format = csi_format; | 				sensor->csi_format = csi_format; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			fmt->format.code = csi_format->code; | 			fmt->format.code = csi_format->code; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		mutex_unlock(&sensor->mutex); | 		mutex_unlock(&sensor->mutex); | ||||||
| 		return rval; | 		if (rval || !range_changed) | ||||||
|  | 			return rval; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) | ||||||
|  | 			v4l2_ctrl_modify_range( | ||||||
|  | 				sensor->test_data[i], | ||||||
|  | 				0, (1 << sensor->csi_format->width) - 1, 1, 0); | ||||||
|  | 
 | ||||||
|  | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Sink pad. Width and height are changeable here. */ | 	/* Sink pad. Width and height are changeable here. */ | ||||||
|  |  | ||||||
|  | @ -54,6 +54,8 @@ | ||||||
| 	(1000 +	(SMIAPP_RESET_DELAY_CLOCKS * 1000	\ | 	(1000 +	(SMIAPP_RESET_DELAY_CLOCKS * 1000	\ | ||||||
| 		 + (clk) / 1000 - 1) / ((clk) / 1000)) | 		 + (clk) / 1000 - 1) / ((clk) / 1000)) | ||||||
| 
 | 
 | ||||||
|  | #define SMIAPP_COLOUR_COMPONENTS	4 | ||||||
|  | 
 | ||||||
| #include "smiapp-limits.h" | #include "smiapp-limits.h" | ||||||
| 
 | 
 | ||||||
| struct smiapp_quirk; | struct smiapp_quirk; | ||||||
|  | @ -241,6 +243,8 @@ struct smiapp_sensor { | ||||||
| 	/* src controls */ | 	/* src controls */ | ||||||
| 	struct v4l2_ctrl *link_freq; | 	struct v4l2_ctrl *link_freq; | ||||||
| 	struct v4l2_ctrl *pixel_rate_csi; | 	struct v4l2_ctrl *pixel_rate_csi; | ||||||
|  | 	/* test pattern colour components */ | ||||||
|  | 	struct v4l2_ctrl *test_data[SMIAPP_COLOUR_COMPONENTS]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define to_smiapp_subdev(_sd)				\ | #define to_smiapp_subdev(_sd)				\ | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
| #include <media/soc_camera.h> | #include <media/soc_camera.h> | ||||||
| #include <media/v4l2-clk.h> | #include <media/v4l2-clk.h> | ||||||
| #include <media/v4l2-common.h> | #include <media/v4l2-common.h> | ||||||
|  | #include <media/v4l2-image-sizes.h> | ||||||
| 
 | 
 | ||||||
| /* you can check PLL/clock info */ | /* you can check PLL/clock info */ | ||||||
| /* #define EXT_CLOCK 24000000 */ | /* #define EXT_CLOCK 24000000 */ | ||||||
|  | @ -42,9 +43,6 @@ | ||||||
| #define MAX_WIDTH   2048 | #define MAX_WIDTH   2048 | ||||||
| #define MAX_HEIGHT  1536 | #define MAX_HEIGHT  1536 | ||||||
| 
 | 
 | ||||||
| #define VGA_WIDTH   640 |  | ||||||
| #define VGA_HEIGHT  480 |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * macro of read/write |  * macro of read/write | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
| #include <media/v4l2-clk.h> | #include <media/v4l2-clk.h> | ||||||
| #include <media/v4l2-ctrls.h> | #include <media/v4l2-ctrls.h> | ||||||
| #include <media/v4l2-subdev.h> | #include <media/v4l2-subdev.h> | ||||||
|  | #include <media/v4l2-image-sizes.h> | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * register offset |  * register offset | ||||||
|  | @ -360,10 +361,6 @@ | ||||||
| #define SCAL0_ACTRL     0x08 /* Auto scaling factor control */ | #define SCAL0_ACTRL     0x08 /* Auto scaling factor control */ | ||||||
| #define SCAL1_2_ACTRL   0x04 /* Auto scaling factor control */ | #define SCAL1_2_ACTRL   0x04 /* Auto scaling factor control */ | ||||||
| 
 | 
 | ||||||
| #define VGA_WIDTH		640 |  | ||||||
| #define VGA_HEIGHT		480 |  | ||||||
| #define QVGA_WIDTH		320 |  | ||||||
| #define QVGA_HEIGHT		240 |  | ||||||
| #define OV772X_MAX_WIDTH	VGA_WIDTH | #define OV772X_MAX_WIDTH	VGA_WIDTH | ||||||
| #define OV772X_MAX_HEIGHT	VGA_HEIGHT | #define OV772X_MAX_HEIGHT	VGA_HEIGHT | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -564,13 +564,13 @@ static int ov9740_set_res(struct i2c_client *client, u32 width, u32 height) | ||||||
| 	u32 y_start; | 	u32 y_start; | ||||||
| 	u32 x_end; | 	u32 x_end; | ||||||
| 	u32 y_end; | 	u32 y_end; | ||||||
| 	bool scaling = 0; | 	bool scaling = false; | ||||||
| 	u32 scale_input_x; | 	u32 scale_input_x; | ||||||
| 	u32 scale_input_y; | 	u32 scale_input_y; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if ((width != OV9740_MAX_WIDTH) || (height != OV9740_MAX_HEIGHT)) | 	if ((width != OV9740_MAX_WIDTH) || (height != OV9740_MAX_HEIGHT)) | ||||||
| 		scaling = 1; | 		scaling = true; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Try to use as much of the sensor area as possible when supporting | 	 * Try to use as much of the sensor area as possible when supporting | ||||||
|  |  | ||||||
|  | @ -293,7 +293,7 @@ static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl) | ||||||
| 		if (t->mute->val) { | 		if (t->mute->val) { | ||||||
| 			lf |= TDA7432_MUTE; | 			lf |= TDA7432_MUTE; | ||||||
| 			lr |= TDA7432_MUTE; | 			lr |= TDA7432_MUTE; | ||||||
| 			lf |= TDA7432_MUTE; | 			rf |= TDA7432_MUTE; | ||||||
| 			rr |= TDA7432_MUTE; | 			rr |= TDA7432_MUTE; | ||||||
| 		} | 		} | ||||||
| 		/* Mute & update balance*/ | 		/* Mute & update balance*/ | ||||||
|  |  | ||||||
|  | @ -775,25 +775,20 @@ static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | ||||||
| static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable) | static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable) | ||||||
| { | { | ||||||
| 	struct tvp7002 *device = to_tvp7002(sd); | 	struct tvp7002 *device = to_tvp7002(sd); | ||||||
| 	int error = 0; | 	int error; | ||||||
| 
 | 
 | ||||||
| 	if (device->streaming == enable) | 	if (device->streaming == enable) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	if (enable) { | 	/* low impedance: on, high impedance: off */ | ||||||
| 		/* Set output state on (low impedance means stream on) */ | 	error = tvp7002_write(sd, TVP7002_MISC_CTL_2, enable ? 0x00 : 0x03); | ||||||
| 		error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00); | 	if (error) { | ||||||
| 		device->streaming = enable; | 		v4l2_dbg(1, debug, sd, "Fail to set streaming\n"); | ||||||
| 	} else { | 		return error; | ||||||
| 		/* Set output state off (high impedance means stream off) */ |  | ||||||
| 		error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x03); |  | ||||||
| 		if (error) |  | ||||||
| 			v4l2_dbg(1, debug, sd, "Unable to stop streaming\n"); |  | ||||||
| 
 |  | ||||||
| 		device->streaming = enable; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return error; | 	device->streaming = enable; | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -30,22 +30,10 @@ | ||||||
| #include <media/v4l2-ctrls.h> | #include <media/v4l2-ctrls.h> | ||||||
| #include <media/v4l2-device.h> | #include <media/v4l2-device.h> | ||||||
| #include <media/v4l2-mediabus.h> | #include <media/v4l2-mediabus.h> | ||||||
|  | #include <media/v4l2-image-sizes.h> | ||||||
| 
 | 
 | ||||||
| #include "vs6624_regs.h" | #include "vs6624_regs.h" | ||||||
| 
 | 
 | ||||||
| #define VGA_WIDTH       640 |  | ||||||
| #define VGA_HEIGHT      480 |  | ||||||
| #define QVGA_WIDTH      320 |  | ||||||
| #define QVGA_HEIGHT     240 |  | ||||||
| #define QQVGA_WIDTH     160 |  | ||||||
| #define QQVGA_HEIGHT    120 |  | ||||||
| #define CIF_WIDTH       352 |  | ||||||
| #define CIF_HEIGHT      288 |  | ||||||
| #define QCIF_WIDTH      176 |  | ||||||
| #define QCIF_HEIGHT     144 |  | ||||||
| #define QQCIF_WIDTH     88 |  | ||||||
| #define QQCIF_HEIGHT    72 |  | ||||||
| 
 |  | ||||||
| #define MAX_FRAME_RATE  30 | #define MAX_FRAME_RATE  30 | ||||||
| 
 | 
 | ||||||
| struct vs6624 { | struct vs6624 { | ||||||
|  |  | ||||||
|  | @ -103,10 +103,8 @@ static long media_device_enum_entities(struct media_device *mdev, | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	u_ent.id = ent->id; | 	u_ent.id = ent->id; | ||||||
| 	if (ent->name) { | 	if (ent->name) | ||||||
| 		strncpy(u_ent.name, ent->name, sizeof(u_ent.name)); | 		strlcpy(u_ent.name, ent->name, sizeof(u_ent.name)); | ||||||
| 		u_ent.name[sizeof(u_ent.name) - 1] = '\0'; |  | ||||||
| 	} |  | ||||||
| 	u_ent.type = ent->type; | 	u_ent.type = ent->type; | ||||||
| 	u_ent.revision = ent->revision; | 	u_ent.revision = ent->revision; | ||||||
| 	u_ent.flags = ent->flags; | 	u_ent.flags = ent->flags; | ||||||
|  |  | ||||||
|  | @ -192,7 +192,6 @@ static int media_open(struct inode *inode, struct file *filp) | ||||||
| static int media_release(struct inode *inode, struct file *filp) | static int media_release(struct inode *inode, struct file *filp) | ||||||
| { | { | ||||||
| 	struct media_devnode *mdev = media_devnode_data(filp); | 	struct media_devnode *mdev = media_devnode_data(filp); | ||||||
| 	int ret = 0; |  | ||||||
| 
 | 
 | ||||||
| 	if (mdev->fops->release) | 	if (mdev->fops->release) | ||||||
| 		mdev->fops->release(filp); | 		mdev->fops->release(filp); | ||||||
|  | @ -201,7 +200,7 @@ static int media_release(struct inode *inode, struct file *filp) | ||||||
| 	   return value is ignored. */ | 	   return value is ignored. */ | ||||||
| 	put_device(&mdev->dev); | 	put_device(&mdev->dev); | ||||||
| 	filp->private_data = NULL; | 	filp->private_data = NULL; | ||||||
| 	return ret; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct file_operations media_devnode_fops = { | static const struct file_operations media_devnode_fops = { | ||||||
|  |  | ||||||
|  | @ -629,11 +629,15 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) | ||||||
| { | { | ||||||
| 	int y; | 	int y; | ||||||
| 	int dw = 2 * dev->width; | 	int dw = 2 * dev->width; | ||||||
| 	char tmp[dw + 32]; /* using a temp buffer is faster than direct  */ | 	char *tmp; /* using a temp buffer is faster than direct  */ | ||||||
| 	int cnt = 0; | 	int cnt = 0; | ||||||
| 	int len = 0; | 	int len = 0; | ||||||
| 	unsigned char r8 = 0x5;  /* value for reg8  */ | 	unsigned char r8 = 0x5;  /* value for reg8  */ | ||||||
| 
 | 
 | ||||||
|  | 	tmp = kmalloc(dw + 32, GFP_KERNEL); | ||||||
|  | 	if (!tmp) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
| 	if (rgb555) | 	if (rgb555) | ||||||
| 		r8 |= 0x20; /* else use untranslated rgb = 565 */ | 		r8 |= 0x20; /* else use untranslated rgb = 565 */ | ||||||
| 	mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */ | 	mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */ | ||||||
|  | @ -664,6 +668,7 @@ static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) | ||||||
| 			len += dt; | 			len += dt; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	kfree(tmp); | ||||||
| 	return len; | 	return len; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ source "drivers/media/pci/ivtv/Kconfig" | ||||||
| source "drivers/media/pci/zoran/Kconfig" | source "drivers/media/pci/zoran/Kconfig" | ||||||
| source "drivers/media/pci/saa7146/Kconfig" | source "drivers/media/pci/saa7146/Kconfig" | ||||||
| source "drivers/media/pci/solo6x10/Kconfig" | source "drivers/media/pci/solo6x10/Kconfig" | ||||||
|  | source "drivers/media/pci/tw68/Kconfig" | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT | if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT | ||||||
|  | @ -41,6 +42,7 @@ source "drivers/media/pci/b2c2/Kconfig" | ||||||
| source "drivers/media/pci/pluto2/Kconfig" | source "drivers/media/pci/pluto2/Kconfig" | ||||||
| source "drivers/media/pci/dm1105/Kconfig" | source "drivers/media/pci/dm1105/Kconfig" | ||||||
| source "drivers/media/pci/pt1/Kconfig" | source "drivers/media/pci/pt1/Kconfig" | ||||||
|  | source "drivers/media/pci/pt3/Kconfig" | ||||||
| source "drivers/media/pci/mantis/Kconfig" | source "drivers/media/pci/mantis/Kconfig" | ||||||
| source "drivers/media/pci/ngene/Kconfig" | source "drivers/media/pci/ngene/Kconfig" | ||||||
| source "drivers/media/pci/ddbridge/Kconfig" | source "drivers/media/pci/ddbridge/Kconfig" | ||||||
|  |  | ||||||
|  | @ -7,10 +7,10 @@ obj-y        +=	ttpci/		\ | ||||||
| 		pluto2/		\
 | 		pluto2/		\
 | ||||||
| 		dm1105/		\
 | 		dm1105/		\
 | ||||||
| 		pt1/		\
 | 		pt1/		\
 | ||||||
|  | 		pt3/		\
 | ||||||
| 		mantis/		\
 | 		mantis/		\
 | ||||||
| 		ngene/		\
 | 		ngene/		\
 | ||||||
| 		ddbridge/	\
 | 		ddbridge/	\
 | ||||||
| 		b2c2/		\
 |  | ||||||
| 		saa7146/ | 		saa7146/ | ||||||
| 
 | 
 | ||||||
| obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | ||||||
|  | @ -22,6 +22,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ | ||||||
| obj-$(CONFIG_VIDEO_BT848) += bt8xx/ | obj-$(CONFIG_VIDEO_BT848) += bt8xx/ | ||||||
| obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | ||||||
| obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ | obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ | ||||||
|  | obj-$(CONFIG_VIDEO_TW68) += tw68/ | ||||||
| obj-$(CONFIG_VIDEO_MEYE) += meye/ | obj-$(CONFIG_VIDEO_MEYE) += meye/ | ||||||
| obj-$(CONFIG_STA2X11_VIP) += sta2x11/ | obj-$(CONFIG_STA2X11_VIP) += sta2x11/ | ||||||
| obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ | obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/ | ||||||
|  |  | ||||||
|  | @ -1531,7 +1531,6 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, | ||||||
| { | { | ||||||
| 	struct bttv_buffer *old; | 	struct bttv_buffer *old; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 	int retval = 0; |  | ||||||
| 
 | 
 | ||||||
| 	dprintk("switch_overlay: enter [new=%p]\n", new); | 	dprintk("switch_overlay: enter [new=%p]\n", new); | ||||||
| 	if (new) | 	if (new) | ||||||
|  | @ -1551,7 +1550,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, | ||||||
| 	if (NULL == new) | 	if (NULL == new) | ||||||
| 		free_btres_lock(btv,fh,RESOURCE_OVERLAY); | 		free_btres_lock(btv,fh,RESOURCE_OVERLAY); | ||||||
| 	dprintk("switch_overlay: done\n"); | 	dprintk("switch_overlay: done\n"); | ||||||
| 	return retval; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ----------------------------------------------------------------------- */ | /* ----------------------------------------------------------------------- */ | ||||||
|  | @ -3856,7 +3855,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) | ||||||
| 
 | 
 | ||||||
| 				btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT), | 				btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT), | ||||||
| 						BT848_INT_MASK); | 						BT848_INT_MASK); | ||||||
| 			}; | 			} | ||||||
| 
 | 
 | ||||||
| 			bttv_print_irqbits(stat,astat); | 			bttv_print_irqbits(stat,astat); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -674,11 +674,9 @@ static int dst_ca_release(struct inode *inode, struct file *file) | ||||||
| 
 | 
 | ||||||
| static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) | static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) | ||||||
| { | { | ||||||
| 	ssize_t bytes_read = 0; |  | ||||||
| 
 |  | ||||||
| 	dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); | 	dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); | ||||||
| 
 | 
 | ||||||
| 	return bytes_read; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset) | static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset) | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data, | ||||||
| 	int period_elapsed = 0; | 	int period_elapsed = 0; | ||||||
| 	int length; | 	int length; | ||||||
| 
 | 
 | ||||||
| 	dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc, | 	dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zu\n", cxsc, | ||||||
| 		pcm_data, num_bytes); | 		pcm_data, num_bytes); | ||||||
| 
 | 
 | ||||||
| 	substream = cxsc->capture_pcm_substream; | 	substream = cxsc->capture_pcm_substream; | ||||||
|  |  | ||||||
|  | @ -130,7 +130,7 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) | 	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) | ||||||
| 		CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size); | 		CX18_INFO("loaded %s firmware (%zu bytes)\n", fn, fw->size); | ||||||
| 	size = fw->size; | 	size = fw->size; | ||||||
| 	release_firmware(fw); | 	release_firmware(fw); | ||||||
| 	cx18_setup_page(cx, SCB_OFFSET); | 	cx18_setup_page(cx, SCB_OFFSET); | ||||||
|  | @ -164,7 +164,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, | ||||||
| 
 | 
 | ||||||
| 	apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32]; | 	apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32]; | ||||||
| 	while (offset + sizeof(seghdr) < fw->size) { | 	while (offset + sizeof(seghdr) < fw->size) { | ||||||
| 		const u32 *shptr = src + offset / 4; | 		const __le32 *shptr = (__force __le32 *)src + offset / 4; | ||||||
| 
 | 
 | ||||||
| 		seghdr.sync1 = le32_to_cpu(shptr[0]); | 		seghdr.sync1 = le32_to_cpu(shptr[0]); | ||||||
| 		seghdr.sync2 = le32_to_cpu(shptr[1]); | 		seghdr.sync2 = le32_to_cpu(shptr[1]); | ||||||
|  | @ -202,7 +202,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, | ||||||
| 		offset += seghdr.size; | 		offset += seghdr.size; | ||||||
| 	} | 	} | ||||||
| 	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) | 	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags)) | ||||||
| 		CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n", | 		CX18_INFO("loaded %s firmware V%08x (%zu bytes)\n", | ||||||
| 				fn, apu_version, fw->size); | 				fn, apu_version, fw->size); | ||||||
| 	size = fw->size; | 	size = fw->size; | ||||||
| 	release_firmware(fw); | 	release_firmware(fw); | ||||||
|  |  | ||||||
|  | @ -364,7 +364,7 @@ int cx18_stream_alloc(struct cx18_stream *s) | ||||||
| 					((char __iomem *)cx->scb->cpu_mdl)); | 					((char __iomem *)cx->scb->cpu_mdl)); | ||||||
| 
 | 
 | ||||||
| 		CX18_ERR("Too many buffers, cannot fit in SCB area\n"); | 		CX18_ERR("Too many buffers, cannot fit in SCB area\n"); | ||||||
| 		CX18_ERR("Max buffers = %zd\n", | 		CX18_ERR("Max buffers = %zu\n", | ||||||
| 			bufsz / sizeof(struct cx18_mdl_ent)); | 			bufsz / sizeof(struct cx18_mdl_ent)); | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -3,12 +3,11 @@ config VIDEO_CX23885 | ||||||
| 	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND | 	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND | ||||||
| 	select SND_PCM | 	select SND_PCM | ||||||
| 	select I2C_ALGOBIT | 	select I2C_ALGOBIT | ||||||
| 	select VIDEO_BTCX |  | ||||||
| 	select VIDEO_TUNER | 	select VIDEO_TUNER | ||||||
| 	select VIDEO_TVEEPROM | 	select VIDEO_TVEEPROM | ||||||
| 	depends on RC_CORE | 	depends on RC_CORE | ||||||
| 	select VIDEOBUF_DVB | 	select VIDEOBUF2_DVB | ||||||
| 	select VIDEOBUF_DMA_SG | 	select VIDEOBUF2_DMA_SG | ||||||
| 	select VIDEO_CX25840 | 	select VIDEO_CX25840 | ||||||
| 	select VIDEO_CX2341X | 	select VIDEO_CX2341X | ||||||
| 	select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT | 	select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | @ -32,12 +31,16 @@ config VIDEO_CX23885 | ||||||
| 	select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT | 	select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT | 	select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT | 	select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT | 	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT | ||||||
|  | 	select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT | 	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT | ||||||
| 	---help--- | 	---help--- | ||||||
| 	  This is a video4linux driver for Conexant 23885 based | 	  This is a video4linux driver for Conexant 23885 based | ||||||
|  |  | ||||||
|  | @ -8,7 +8,6 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o | ||||||
| obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o | obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o | ||||||
| 
 | 
 | ||||||
| ccflags-y += -Idrivers/media/i2c | ccflags-y += -Idrivers/media/i2c | ||||||
| ccflags-y += -Idrivers/media/common |  | ||||||
| ccflags-y += -Idrivers/media/tuners | ccflags-y += -Idrivers/media/tuners | ||||||
| ccflags-y += -Idrivers/media/dvb-core | ccflags-y += -Idrivers/media/dvb-core | ||||||
| ccflags-y += -Idrivers/media/dvb-frontends | ccflags-y += -Idrivers/media/dvb-frontends | ||||||
|  |  | ||||||
|  | @ -16,10 +16,6 @@ | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * |  * | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -52,8 +48,8 @@ | ||||||
|  * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0| |  * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0| | ||||||
|  * +-------+-------+-------+-------+-------+-------+-------+-------+ |  * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||||||
|  */ |  */ | ||||||
| #include <media/videobuf-dma-sg.h> | #include <dvb_demux.h> | ||||||
| #include <media/videobuf-dvb.h> | #include <dvb_frontend.h> | ||||||
| #include "altera-ci.h" | #include "altera-ci.h" | ||||||
| #include "dvb_ca_en50221.h" | #include "dvb_ca_en50221.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,10 +16,6 @@ | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * |  * | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| #ifndef __ALTERA_CI_H | #ifndef __ALTERA_CI_H | ||||||
| #define __ALTERA_CI_H | #define __ALTERA_CI_H | ||||||
|  |  | ||||||
|  | @ -17,10 +17,6 @@ | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * |  * | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "cx23885.h" | #include "cx23885.h" | ||||||
|  |  | ||||||
|  | @ -17,10 +17,6 @@ | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * |  * | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program; if not, write to the Free Software |  | ||||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef CIMAX2_H | #ifndef CIMAX2_H | ||||||
|  |  | ||||||
|  | @ -18,10 +18,6 @@ | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  *  GNU General Public License for more details. |  *  GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
|  | @ -865,6 +861,11 @@ static int cx23885_api_cmd(struct cx23885_dev *dev, | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int cx23885_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) | ||||||
|  | { | ||||||
|  | 	return cx23885_mbox_func(priv, cmd, in, out, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int cx23885_find_mailbox(struct cx23885_dev *dev) | static int cx23885_find_mailbox(struct cx23885_dev *dev) | ||||||
| { | { | ||||||
| 	u32 signature[4] = { | 	u32 signature[4] = { | ||||||
|  | @ -941,7 +942,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | ||||||
| 
 | 
 | ||||||
| 	if (firmware->size != CX23885_FIRM_IMAGE_SIZE) { | 	if (firmware->size != CX23885_FIRM_IMAGE_SIZE) { | ||||||
| 		printk(KERN_ERR "ERROR: Firmware size mismatch " | 		printk(KERN_ERR "ERROR: Firmware size mismatch " | ||||||
| 			"(have %zd, expected %d)\n", | 			"(have %zu, expected %d)\n", | ||||||
| 			firmware->size, CX23885_FIRM_IMAGE_SIZE); | 			firmware->size, CX23885_FIRM_IMAGE_SIZE); | ||||||
| 		release_firmware(firmware); | 		release_firmware(firmware); | ||||||
| 		return -1; | 		return -1; | ||||||
|  | @ -1033,12 +1034,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev) | ||||||
| 	cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 	cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | ||||||
| 				dev->ts1.height, dev->ts1.width); | 				dev->ts1.height, dev->ts1.width); | ||||||
| 
 | 
 | ||||||
| 	dev->mpeg_params.width = dev->ts1.width; | 	dev->cxhdl.width = dev->ts1.width; | ||||||
| 	dev->mpeg_params.height = dev->ts1.height; | 	dev->cxhdl.height = dev->ts1.height; | ||||||
| 	dev->mpeg_params.is_50hz = | 	dev->cxhdl.is_50hz = | ||||||
| 		(dev->encodernorm.id & V4L2_STD_625_50) != 0; | 		(dev->encodernorm.id & V4L2_STD_625_50) != 0; | ||||||
| 
 | 
 | ||||||
| 	cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params); | 	cx2341x_handler_setup(&dev->cxhdl); | ||||||
| 
 | 
 | ||||||
| 	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); | 	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); | ||||||
| 	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); | 	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); | ||||||
|  | @ -1137,85 +1138,107 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder) | ||||||
| 
 | 
 | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
| 
 | 
 | ||||||
| static int bb_buf_setup(struct videobuf_queue *q, | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, | ||||||
| 	unsigned int *count, unsigned int *size) | 			   unsigned int *num_buffers, unsigned int *num_planes, | ||||||
|  | 			   unsigned int sizes[], void *alloc_ctxs[]) | ||||||
| { | { | ||||||
| 	struct cx23885_fh *fh = q->priv_data; | 	struct cx23885_dev *dev = q->drv_priv; | ||||||
| 
 |  | ||||||
| 	fh->dev->ts1.ts_packet_size  = mpeglinesize; |  | ||||||
| 	fh->dev->ts1.ts_packet_count = mpeglines; |  | ||||||
| 
 |  | ||||||
| 	*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; |  | ||||||
| 	*count = mpegbufs; |  | ||||||
| 
 | 
 | ||||||
|  | 	dev->ts1.ts_packet_size  = mpeglinesize; | ||||||
|  | 	dev->ts1.ts_packet_count = mpeglines; | ||||||
|  | 	*num_planes = 1; | ||||||
|  | 	sizes[0] = mpeglinesize * mpeglines; | ||||||
|  | 	*num_buffers = mpegbufs; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int bb_buf_prepare(struct videobuf_queue *q, | static int buffer_prepare(struct vb2_buffer *vb) | ||||||
| 	struct videobuf_buffer *vb, enum v4l2_field field) |  | ||||||
| { | { | ||||||
| 	struct cx23885_fh *fh = q->priv_data; | 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv; | ||||||
| 	return cx23885_buf_prepare(q, &fh->dev->ts1, | 	struct cx23885_buffer *buf = | ||||||
| 		(struct cx23885_buffer *)vb, | 		container_of(vb, struct cx23885_buffer, vb); | ||||||
| 		field); | 
 | ||||||
|  | 	return cx23885_buf_prepare(buf, &dev->ts1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bb_buf_queue(struct videobuf_queue *q, | static void buffer_finish(struct vb2_buffer *vb) | ||||||
| 	struct videobuf_buffer *vb) |  | ||||||
| { | { | ||||||
| 	struct cx23885_fh *fh = q->priv_data; | 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv; | ||||||
| 	cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb); | 	struct cx23885_buffer *buf = container_of(vb, | ||||||
|  | 		struct cx23885_buffer, vb); | ||||||
|  | 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||||||
|  | 
 | ||||||
|  | 	cx23885_free_buffer(dev, buf); | ||||||
|  | 
 | ||||||
|  | 	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bb_buf_release(struct videobuf_queue *q, | static void buffer_queue(struct vb2_buffer *vb) | ||||||
| 	struct videobuf_buffer *vb) |  | ||||||
| { | { | ||||||
| 	cx23885_free_buffer(q, (struct cx23885_buffer *)vb); | 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv; | ||||||
|  | 	struct cx23885_buffer   *buf = container_of(vb, | ||||||
|  | 		struct cx23885_buffer, vb); | ||||||
|  | 
 | ||||||
|  | 	cx23885_buf_queue(&dev->ts1, buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct videobuf_queue_ops cx23885_qops = { | static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count) | ||||||
| 	.buf_setup    = bb_buf_setup, | { | ||||||
| 	.buf_prepare  = bb_buf_prepare, | 	struct cx23885_dev *dev = q->drv_priv; | ||||||
| 	.buf_queue    = bb_buf_queue, | 	struct cx23885_dmaqueue *dmaq = &dev->ts1.mpegq; | ||||||
| 	.buf_release  = bb_buf_release, | 	unsigned long flags; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = cx23885_initialize_codec(dev, 1); | ||||||
|  | 	if (ret == 0) { | ||||||
|  | 		struct cx23885_buffer *buf = list_entry(dmaq->active.next, | ||||||
|  | 			struct cx23885_buffer, queue); | ||||||
|  | 
 | ||||||
|  | 		cx23885_start_dma(&dev->ts1, dmaq, buf); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	spin_lock_irqsave(&dev->slock, flags); | ||||||
|  | 	while (!list_empty(&dmaq->active)) { | ||||||
|  | 		struct cx23885_buffer *buf = list_entry(dmaq->active.next, | ||||||
|  | 			struct cx23885_buffer, queue); | ||||||
|  | 
 | ||||||
|  | 		list_del(&buf->queue); | ||||||
|  | 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | ||||||
|  | 	} | ||||||
|  | 	spin_unlock_irqrestore(&dev->slock, flags); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void cx23885_stop_streaming(struct vb2_queue *q) | ||||||
|  | { | ||||||
|  | 	struct cx23885_dev *dev = q->drv_priv; | ||||||
|  | 
 | ||||||
|  | 	/* stop mpeg capture */ | ||||||
|  | 	cx23885_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||||||
|  | 			CX23885_END_NOW, CX23885_MPEG_CAPTURE, | ||||||
|  | 			CX23885_RAW_BITS_NONE); | ||||||
|  | 
 | ||||||
|  | 	msleep(500); | ||||||
|  | 	cx23885_417_check_encoder(dev); | ||||||
|  | 	cx23885_cancel_buffers(&dev->ts1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct vb2_ops cx23885_qops = { | ||||||
|  | 	.queue_setup    = queue_setup, | ||||||
|  | 	.buf_prepare  = buffer_prepare, | ||||||
|  | 	.buf_finish = buffer_finish, | ||||||
|  | 	.buf_queue    = buffer_queue, | ||||||
|  | 	.wait_prepare = vb2_ops_wait_prepare, | ||||||
|  | 	.wait_finish = vb2_ops_wait_finish, | ||||||
|  | 	.start_streaming = cx23885_start_streaming, | ||||||
|  | 	.stop_streaming = cx23885_stop_streaming, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
| 
 | 
 | ||||||
| static const u32 *ctrl_classes[] = { |  | ||||||
| 	cx2341x_mpeg_ctrls, |  | ||||||
| 	NULL |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static int cx23885_queryctrl(struct cx23885_dev *dev, |  | ||||||
| 	struct v4l2_queryctrl *qctrl) |  | ||||||
| { |  | ||||||
| 	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); |  | ||||||
| 	if (qctrl->id == 0) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	/* MPEG V4L2 controls */ |  | ||||||
| 	if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) |  | ||||||
| 		qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int cx23885_querymenu(struct cx23885_dev *dev, |  | ||||||
| 	struct v4l2_querymenu *qmenu) |  | ||||||
| { |  | ||||||
| 	struct v4l2_queryctrl qctrl; |  | ||||||
| 
 |  | ||||||
| 	qctrl.id = qmenu->id; |  | ||||||
| 	cx23885_queryctrl(dev, &qctrl); |  | ||||||
| 	return v4l2_ctrl_query_menu(qmenu, &qctrl, |  | ||||||
| 		cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	*id = dev->tvnorm; | 	*id = dev->tvnorm; | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -1223,29 +1246,26 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||||||
| 
 | 
 | ||||||
| static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 	unsigned int i; | 	unsigned int i; | ||||||
|  | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++) | 	for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++) | ||||||
| 		if (id & cx23885_tvnorms[i].id) | 		if (id & cx23885_tvnorms[i].id) | ||||||
| 			break; | 			break; | ||||||
| 	if (i == ARRAY_SIZE(cx23885_tvnorms)) | 	if (i == ARRAY_SIZE(cx23885_tvnorms)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	dev->encodernorm = cx23885_tvnorms[i]; |  | ||||||
| 
 | 
 | ||||||
| 	/* Have the drier core notify the subdevices */ | 	ret = cx23885_set_tvnorm(dev, id); | ||||||
| 	mutex_lock(&dev->lock); | 	if (!ret) | ||||||
| 	cx23885_set_tvnorm(dev, id); | 		dev->encodernorm = cx23885_tvnorms[i]; | ||||||
| 	mutex_unlock(&dev->lock); | 	return ret; | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_enum_input(struct file *file, void *priv, | static int vidioc_enum_input(struct file *file, void *priv, | ||||||
| 	struct v4l2_input *i) | 	struct v4l2_input *i) | ||||||
| { | { | ||||||
| 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	dprintk(1, "%s()\n", __func__); | 	dprintk(1, "%s()\n", __func__); | ||||||
| 	return cx23885_enum_input(dev, i); | 	return cx23885_enum_input(dev, i); | ||||||
| } | } | ||||||
|  | @ -1263,8 +1283,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||||||
| static int vidioc_g_tuner(struct file *file, void *priv, | static int vidioc_g_tuner(struct file *file, void *priv, | ||||||
| 				struct v4l2_tuner *t) | 				struct v4l2_tuner *t) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	if (dev->tuner_type == TUNER_ABSENT) | 	if (dev->tuner_type == TUNER_ABSENT) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -1281,8 +1300,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | ||||||
| static int vidioc_s_tuner(struct file *file, void *priv, | static int vidioc_s_tuner(struct file *file, void *priv, | ||||||
| 				const struct v4l2_tuner *t) | 				const struct v4l2_tuner *t) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	if (dev->tuner_type == TUNER_ABSENT) | 	if (dev->tuner_type == TUNER_ABSENT) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -1296,8 +1314,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | ||||||
| static int vidioc_g_frequency(struct file *file, void *priv, | static int vidioc_g_frequency(struct file *file, void *priv, | ||||||
| 				struct v4l2_frequency *f) | 				struct v4l2_frequency *f) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	if (dev->tuner_type == TUNER_ABSENT) | 	if (dev->tuner_type == TUNER_ABSENT) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | @ -1315,27 +1332,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, | ||||||
| 	return cx23885_set_frequency(file, priv, f); | 	return cx23885_set_frequency(file, priv, f); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_g_ctrl(struct file *file, void *priv, |  | ||||||
| 	struct v4l2_control *ctl) |  | ||||||
| { |  | ||||||
| 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |  | ||||||
| 
 |  | ||||||
| 	return cx23885_get_control(dev, ctl); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_s_ctrl(struct file *file, void *priv, |  | ||||||
| 	struct v4l2_control *ctl) |  | ||||||
| { |  | ||||||
| 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |  | ||||||
| 
 |  | ||||||
| 	return cx23885_set_control(dev, ctl); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_querycap(struct file *file, void  *priv, | static int vidioc_querycap(struct file *file, void  *priv, | ||||||
| 				struct v4l2_capability *cap) | 				struct v4l2_capability *cap) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 	struct cx23885_tsport  *tsport = &dev->ts1; | 	struct cx23885_tsport  *tsport = &dev->ts1; | ||||||
| 
 | 
 | ||||||
| 	strlcpy(cap->driver, dev->name, sizeof(cap->driver)); | 	strlcpy(cap->driver, dev->name, sizeof(cap->driver)); | ||||||
|  | @ -1368,8 +1368,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv, | ||||||
| static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||||||
| 				struct v4l2_format *f) | 				struct v4l2_format *f) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | ||||||
| 	f->fmt.pix.bytesperline = 0; | 	f->fmt.pix.bytesperline = 0; | ||||||
|  | @ -1378,285 +1377,63 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||||||
| 	f->fmt.pix.colorspace   = 0; | 	f->fmt.pix.colorspace   = 0; | ||||||
| 	f->fmt.pix.width        = dev->ts1.width; | 	f->fmt.pix.width        = dev->ts1.width; | ||||||
| 	f->fmt.pix.height       = dev->ts1.height; | 	f->fmt.pix.height       = dev->ts1.height; | ||||||
| 	f->fmt.pix.field        = fh->mpegq.field; | 	f->fmt.pix.field        = V4L2_FIELD_INTERLACED; | ||||||
| 	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", | 	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n", | ||||||
| 		dev->ts1.width, dev->ts1.height, fh->mpegq.field); | 		dev->ts1.width, dev->ts1.height); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||||||
| 				struct v4l2_format *f) | 				struct v4l2_format *f) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | ||||||
| 	f->fmt.pix.bytesperline = 0; | 	f->fmt.pix.bytesperline = 0; | ||||||
| 	f->fmt.pix.sizeimage    = | 	f->fmt.pix.sizeimage    = | ||||||
| 		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; | 		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; | ||||||
| 	f->fmt.pix.colorspace   = 0; | 	f->fmt.pix.colorspace   = 0; | ||||||
| 	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | 	f->fmt.pix.field        = V4L2_FIELD_INTERLACED; | ||||||
| 		dev->ts1.width, dev->ts1.height, fh->mpegq.field); | 	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n", | ||||||
|  | 		dev->ts1.width, dev->ts1.height); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||||||
| 				struct v4l2_format *f) | 				struct v4l2_format *f) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 | 
 | ||||||
| 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG; | ||||||
| 	f->fmt.pix.bytesperline = 0; | 	f->fmt.pix.bytesperline = 0; | ||||||
| 	f->fmt.pix.sizeimage    = | 	f->fmt.pix.sizeimage    = | ||||||
| 		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; | 		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; | ||||||
| 	f->fmt.pix.colorspace   = 0; | 	f->fmt.pix.colorspace   = 0; | ||||||
|  | 	f->fmt.pix.field        = V4L2_FIELD_INTERLACED; | ||||||
| 	dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", | 	dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", | ||||||
| 		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); | 		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_reqbufs(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_requestbuffers *p) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_reqbufs(&fh->mpegq, p); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_querybuf(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_buffer *p) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_querybuf(&fh->mpegq, p); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_qbuf(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_buffer *p) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_qbuf(&fh->mpegq, p); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static int vidioc_streamon(struct file *file, void *priv, |  | ||||||
| 				enum v4l2_buf_type i) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_streamon(&fh->mpegq); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 
 |  | ||||||
| 	return videobuf_streamoff(&fh->mpegq); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_g_ext_ctrls(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_ext_controls *f) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_s_ext_ctrls(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_ext_controls *f) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 	struct cx2341x_mpeg_params p; |  | ||||||
| 	int err; |  | ||||||
| 
 |  | ||||||
| 	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	p = dev->mpeg_params; |  | ||||||
| 	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); |  | ||||||
| 
 |  | ||||||
| 	if (err == 0) { |  | ||||||
| 		err = cx2341x_update(dev, cx23885_mbox_func, |  | ||||||
| 			&dev->mpeg_params, &p); |  | ||||||
| 		dev->mpeg_params = p; |  | ||||||
| 	} |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_try_ext_ctrls(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_ext_controls *f) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 	struct cx2341x_mpeg_params p; |  | ||||||
| 	int err; |  | ||||||
| 
 |  | ||||||
| 	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) |  | ||||||
| 		return -EINVAL; |  | ||||||
| 
 |  | ||||||
| 	p = dev->mpeg_params; |  | ||||||
| 	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_log_status(struct file *file, void *priv) | static int vidioc_log_status(struct file *file, void *priv) | ||||||
| { | { | ||||||
| 	struct cx23885_fh  *fh  = priv; | 	struct cx23885_dev *dev = video_drvdata(file); | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 	char name[32 + 2]; | 	char name[32 + 2]; | ||||||
| 
 | 
 | ||||||
| 	snprintf(name, sizeof(name), "%s/2", dev->name); | 	snprintf(name, sizeof(name), "%s/2", dev->name); | ||||||
| 	printk(KERN_INFO |  | ||||||
| 		"%s/2: ============  START LOG STATUS  ============\n", |  | ||||||
| 	       dev->name); |  | ||||||
| 	call_all(dev, core, log_status); | 	call_all(dev, core, log_status); | ||||||
| 	cx2341x_log_status(&dev->mpeg_params, name); | 	v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name); | ||||||
| 	printk(KERN_INFO |  | ||||||
| 		"%s/2: =============  END LOG STATUS  =============\n", |  | ||||||
| 	       dev->name); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int vidioc_querymenu(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_querymenu *a) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	return cx23885_querymenu(dev, a); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int vidioc_queryctrl(struct file *file, void *priv, |  | ||||||
| 				struct v4l2_queryctrl *c) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = priv; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	return cx23885_queryctrl(dev, c); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int mpeg_open(struct file *file) |  | ||||||
| { |  | ||||||
| 	struct cx23885_dev *dev = video_drvdata(file); |  | ||||||
| 	struct cx23885_fh *fh; |  | ||||||
| 
 |  | ||||||
| 	dprintk(2, "%s()\n", __func__); |  | ||||||
| 
 |  | ||||||
| 	/* allocate + initialize per filehandle data */ |  | ||||||
| 	fh = kzalloc(sizeof(*fh), GFP_KERNEL); |  | ||||||
| 	if (!fh) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	file->private_data = fh; |  | ||||||
| 	fh->dev      = dev; |  | ||||||
| 
 |  | ||||||
| 	videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops, |  | ||||||
| 			    &dev->pci->dev, &dev->ts1.slock, |  | ||||||
| 			    V4L2_BUF_TYPE_VIDEO_CAPTURE, |  | ||||||
| 			    V4L2_FIELD_INTERLACED, |  | ||||||
| 			    sizeof(struct cx23885_buffer), |  | ||||||
| 			    fh, NULL); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int mpeg_release(struct file *file) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh  *fh  = file->private_data; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	dprintk(2, "%s()\n", __func__); |  | ||||||
| 
 |  | ||||||
| 	/* FIXME: Review this crap */ |  | ||||||
| 	/* Shut device down on last close */ |  | ||||||
| 	if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { |  | ||||||
| 		if (atomic_dec_return(&dev->v4l_reader_count) == 0) { |  | ||||||
| 			/* stop mpeg capture */ |  | ||||||
| 			cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, |  | ||||||
| 				CX23885_END_NOW, CX23885_MPEG_CAPTURE, |  | ||||||
| 				CX23885_RAW_BITS_NONE); |  | ||||||
| 
 |  | ||||||
| 			msleep(500); |  | ||||||
| 			cx23885_417_check_encoder(dev); |  | ||||||
| 
 |  | ||||||
| 			cx23885_cancel_buffers(&fh->dev->ts1); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (fh->mpegq.streaming) |  | ||||||
| 		videobuf_streamoff(&fh->mpegq); |  | ||||||
| 	if (fh->mpegq.reading) |  | ||||||
| 		videobuf_read_stop(&fh->mpegq); |  | ||||||
| 
 |  | ||||||
| 	videobuf_mmap_free(&fh->mpegq); |  | ||||||
| 	file->private_data = NULL; |  | ||||||
| 	kfree(fh); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static ssize_t mpeg_read(struct file *file, char __user *data, |  | ||||||
| 	size_t count, loff_t *ppos) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh *fh = file->private_data; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	dprintk(2, "%s()\n", __func__); |  | ||||||
| 
 |  | ||||||
| 	/* Deal w/ A/V decoder * and mpeg encoder sync issues. */ |  | ||||||
| 	/* Start mpeg encoder on first read. */ |  | ||||||
| 	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { |  | ||||||
| 		if (atomic_inc_return(&dev->v4l_reader_count) == 1) { |  | ||||||
| 			if (cx23885_initialize_codec(dev, 1) < 0) |  | ||||||
| 				return -EINVAL; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, |  | ||||||
| 				    file->f_flags & O_NONBLOCK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned int mpeg_poll(struct file *file, |  | ||||||
| 	struct poll_table_struct *wait) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh *fh = file->private_data; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	dprintk(2, "%s\n", __func__); |  | ||||||
| 
 |  | ||||||
| 	return videobuf_poll_stream(file, &fh->mpegq, wait); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) |  | ||||||
| { |  | ||||||
| 	struct cx23885_fh *fh = file->private_data; |  | ||||||
| 	struct cx23885_dev *dev = fh->dev; |  | ||||||
| 
 |  | ||||||
| 	dprintk(2, "%s()\n", __func__); |  | ||||||
| 
 |  | ||||||
| 	return videobuf_mmap_mapper(&fh->mpegq, vma); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct v4l2_file_operations mpeg_fops = { | static struct v4l2_file_operations mpeg_fops = { | ||||||
| 	.owner	       = THIS_MODULE, | 	.owner	       = THIS_MODULE, | ||||||
| 	.open	       = mpeg_open, | 	.open           = v4l2_fh_open, | ||||||
| 	.release       = mpeg_release, | 	.release        = vb2_fop_release, | ||||||
| 	.read	       = mpeg_read, | 	.read           = vb2_fop_read, | ||||||
| 	.poll          = mpeg_poll, | 	.poll		= vb2_fop_poll, | ||||||
| 	.mmap	       = mpeg_mmap, | 	.unlocked_ioctl = video_ioctl2, | ||||||
| 	.ioctl	       = video_ioctl2, | 	.mmap           = vb2_fop_mmap, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | ||||||
|  | @ -1669,25 +1446,19 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | ||||||
| 	.vidioc_s_tuner		 = vidioc_s_tuner, | 	.vidioc_s_tuner		 = vidioc_s_tuner, | ||||||
| 	.vidioc_g_frequency	 = vidioc_g_frequency, | 	.vidioc_g_frequency	 = vidioc_g_frequency, | ||||||
| 	.vidioc_s_frequency	 = vidioc_s_frequency, | 	.vidioc_s_frequency	 = vidioc_s_frequency, | ||||||
| 	.vidioc_s_ctrl		 = vidioc_s_ctrl, |  | ||||||
| 	.vidioc_g_ctrl		 = vidioc_g_ctrl, |  | ||||||
| 	.vidioc_querycap	 = vidioc_querycap, | 	.vidioc_querycap	 = vidioc_querycap, | ||||||
| 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||||||
| 	.vidioc_g_fmt_vid_cap	 = vidioc_g_fmt_vid_cap, | 	.vidioc_g_fmt_vid_cap	 = vidioc_g_fmt_vid_cap, | ||||||
| 	.vidioc_try_fmt_vid_cap	 = vidioc_try_fmt_vid_cap, | 	.vidioc_try_fmt_vid_cap	 = vidioc_try_fmt_vid_cap, | ||||||
| 	.vidioc_s_fmt_vid_cap	 = vidioc_s_fmt_vid_cap, | 	.vidioc_s_fmt_vid_cap	 = vidioc_s_fmt_vid_cap, | ||||||
| 	.vidioc_reqbufs		 = vidioc_reqbufs, | 	.vidioc_reqbufs       = vb2_ioctl_reqbufs, | ||||||
| 	.vidioc_querybuf	 = vidioc_querybuf, | 	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf, | ||||||
| 	.vidioc_qbuf		 = vidioc_qbuf, | 	.vidioc_querybuf      = vb2_ioctl_querybuf, | ||||||
| 	.vidioc_dqbuf		 = vidioc_dqbuf, | 	.vidioc_qbuf          = vb2_ioctl_qbuf, | ||||||
| 	.vidioc_streamon	 = vidioc_streamon, | 	.vidioc_dqbuf         = vb2_ioctl_dqbuf, | ||||||
| 	.vidioc_streamoff	 = vidioc_streamoff, | 	.vidioc_streamon      = vb2_ioctl_streamon, | ||||||
| 	.vidioc_g_ext_ctrls	 = vidioc_g_ext_ctrls, | 	.vidioc_streamoff     = vb2_ioctl_streamoff, | ||||||
| 	.vidioc_s_ext_ctrls	 = vidioc_s_ext_ctrls, |  | ||||||
| 	.vidioc_try_ext_ctrls	 = vidioc_try_ext_ctrls, |  | ||||||
| 	.vidioc_log_status	 = vidioc_log_status, | 	.vidioc_log_status	 = vidioc_log_status, | ||||||
| 	.vidioc_querymenu	 = vidioc_querymenu, |  | ||||||
| 	.vidioc_queryctrl	 = vidioc_queryctrl, |  | ||||||
| #ifdef CONFIG_VIDEO_ADV_DEBUG | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||||||
| 	.vidioc_g_chip_info	 = cx23885_g_chip_info, | 	.vidioc_g_chip_info	 = cx23885_g_chip_info, | ||||||
| 	.vidioc_g_register	 = cx23885_g_register, | 	.vidioc_g_register	 = cx23885_g_register, | ||||||
|  | @ -1711,6 +1482,7 @@ void cx23885_417_unregister(struct cx23885_dev *dev) | ||||||
| 			video_unregister_device(dev->v4l_device); | 			video_unregister_device(dev->v4l_device); | ||||||
| 		else | 		else | ||||||
| 			video_device_release(dev->v4l_device); | 			video_device_release(dev->v4l_device); | ||||||
|  | 		v4l2_ctrl_handler_free(&dev->cxhdl.hdl); | ||||||
| 		dev->v4l_device = NULL; | 		dev->v4l_device = NULL; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -1742,6 +1514,7 @@ int cx23885_417_register(struct cx23885_dev *dev) | ||||||
| 	/* FIXME: Port1 hardcoded here */ | 	/* FIXME: Port1 hardcoded here */ | ||||||
| 	int err = -ENODEV; | 	int err = -ENODEV; | ||||||
| 	struct cx23885_tsport *tsport = &dev->ts1; | 	struct cx23885_tsport *tsport = &dev->ts1; | ||||||
|  | 	struct vb2_queue *q; | ||||||
| 
 | 
 | ||||||
| 	dprintk(1, "%s()\n", __func__); | 	dprintk(1, "%s()\n", __func__); | ||||||
| 
 | 
 | ||||||
|  | @ -1757,14 +1530,36 @@ int cx23885_417_register(struct cx23885_dev *dev) | ||||||
| 		tsport->height = 576; | 		tsport->height = 576; | ||||||
| 
 | 
 | ||||||
| 	tsport->width = 720; | 	tsport->width = 720; | ||||||
| 	cx2341x_fill_defaults(&dev->mpeg_params); | 	dev->cxhdl.port = CX2341X_PORT_SERIAL; | ||||||
| 
 | 	err = cx2341x_handler_init(&dev->cxhdl, 50); | ||||||
| 	dev->mpeg_params.port = CX2341X_PORT_SERIAL; | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 	dev->cxhdl.priv = dev; | ||||||
|  | 	dev->cxhdl.func = cx23885_api_func; | ||||||
|  | 	cx2341x_handler_set_50hz(&dev->cxhdl, tsport->height == 576); | ||||||
|  | 	v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL); | ||||||
| 
 | 
 | ||||||
| 	/* Allocate and initialize V4L video device */ | 	/* Allocate and initialize V4L video device */ | ||||||
| 	dev->v4l_device = cx23885_video_dev_alloc(tsport, | 	dev->v4l_device = cx23885_video_dev_alloc(tsport, | ||||||
| 		dev->pci, &cx23885_mpeg_template, "mpeg"); | 		dev->pci, &cx23885_mpeg_template, "mpeg"); | ||||||
|  | 	q = &dev->vb2_mpegq; | ||||||
|  | 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||||
|  | 	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||||||
|  | 	q->gfp_flags = GFP_DMA32; | ||||||
|  | 	q->min_buffers_needed = 2; | ||||||
|  | 	q->drv_priv = dev; | ||||||
|  | 	q->buf_struct_size = sizeof(struct cx23885_buffer); | ||||||
|  | 	q->ops = &cx23885_qops; | ||||||
|  | 	q->mem_ops = &vb2_dma_sg_memops; | ||||||
|  | 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||||||
|  | 	q->lock = &dev->lock; | ||||||
|  | 
 | ||||||
|  | 	err = vb2_queue_init(q); | ||||||
|  | 	if (err < 0) | ||||||
|  | 		return err; | ||||||
| 	video_set_drvdata(dev->v4l_device, dev); | 	video_set_drvdata(dev->v4l_device, dev); | ||||||
|  | 	dev->v4l_device->lock = &dev->lock; | ||||||
|  | 	dev->v4l_device->queue = q; | ||||||
| 	err = video_register_device(dev->v4l_device, | 	err = video_register_device(dev->v4l_device, | ||||||
| 		VFL_TYPE_GRABBER, -1); | 		VFL_TYPE_GRABBER, -1); | ||||||
| 	if (err < 0) { | 	if (err < 0) { | ||||||
|  |  | ||||||
|  | @ -15,10 +15,6 @@ | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  *  GNU General Public License for more details. |  *  GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
|  | @ -84,6 +80,82 @@ MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]"); | ||||||
| #define AUD_INT_MCHG_IRQ        (1 << 21) | #define AUD_INT_MCHG_IRQ        (1 << 21) | ||||||
| #define GP_COUNT_CONTROL_RESET	0x3 | #define GP_COUNT_CONTROL_RESET	0x3 | ||||||
| 
 | 
 | ||||||
|  | static int cx23885_alsa_dma_init(struct cx23885_audio_dev *chip, int nr_pages) | ||||||
|  | { | ||||||
|  | 	struct cx23885_audio_buffer *buf = chip->buf; | ||||||
|  | 	struct page *pg; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); | ||||||
|  | 	if (NULL == buf->vaddr) { | ||||||
|  | 		dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", | ||||||
|  | 				(unsigned long)buf->vaddr, | ||||||
|  | 				nr_pages << PAGE_SHIFT); | ||||||
|  | 
 | ||||||
|  | 	memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); | ||||||
|  | 	buf->nr_pages = nr_pages; | ||||||
|  | 
 | ||||||
|  | 	buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); | ||||||
|  | 	if (NULL == buf->sglist) | ||||||
|  | 		goto vzalloc_err; | ||||||
|  | 
 | ||||||
|  | 	sg_init_table(buf->sglist, buf->nr_pages); | ||||||
|  | 	for (i = 0; i < buf->nr_pages; i++) { | ||||||
|  | 		pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); | ||||||
|  | 		if (NULL == pg) | ||||||
|  | 			goto vmalloc_to_page_err; | ||||||
|  | 		sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | vmalloc_to_page_err: | ||||||
|  | 	vfree(buf->sglist); | ||||||
|  | 	buf->sglist = NULL; | ||||||
|  | vzalloc_err: | ||||||
|  | 	vfree(buf->vaddr); | ||||||
|  | 	buf->vaddr = NULL; | ||||||
|  | 	return -ENOMEM; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int cx23885_alsa_dma_map(struct cx23885_audio_dev *dev) | ||||||
|  | { | ||||||
|  | 	struct cx23885_audio_buffer *buf = dev->buf; | ||||||
|  | 
 | ||||||
|  | 	buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist, | ||||||
|  | 			buf->nr_pages, PCI_DMA_FROMDEVICE); | ||||||
|  | 
 | ||||||
|  | 	if (0 == buf->sglen) { | ||||||
|  | 		pr_warn("%s: cx23885_alsa_map_sg failed\n", __func__); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int cx23885_alsa_dma_unmap(struct cx23885_audio_dev *dev) | ||||||
|  | { | ||||||
|  | 	struct cx23885_audio_buffer *buf = dev->buf; | ||||||
|  | 
 | ||||||
|  | 	if (!buf->sglen) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE); | ||||||
|  | 	buf->sglen = 0; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int cx23885_alsa_dma_free(struct cx23885_audio_buffer *buf) | ||||||
|  | { | ||||||
|  | 	vfree(buf->sglist); | ||||||
|  | 	buf->sglist = NULL; | ||||||
|  | 	vfree(buf->vaddr); | ||||||
|  | 	buf->vaddr = NULL; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * BOARD Specific: Sets audio DMA |  * BOARD Specific: Sets audio DMA | ||||||
|  */ |  */ | ||||||
|  | @ -198,15 +270,18 @@ int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask) | ||||||
| 
 | 
 | ||||||
| static int dsp_buffer_free(struct cx23885_audio_dev *chip) | static int dsp_buffer_free(struct cx23885_audio_dev *chip) | ||||||
| { | { | ||||||
|  | 	struct cx23885_riscmem *risc; | ||||||
|  | 
 | ||||||
| 	BUG_ON(!chip->dma_size); | 	BUG_ON(!chip->dma_size); | ||||||
| 
 | 
 | ||||||
| 	dprintk(2, "Freeing buffer\n"); | 	dprintk(2, "Freeing buffer\n"); | ||||||
| 	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); | 	cx23885_alsa_dma_unmap(chip); | ||||||
| 	videobuf_dma_free(chip->dma_risc); | 	cx23885_alsa_dma_free(chip->buf); | ||||||
| 	btcx_riscmem_free(chip->pci, &chip->buf->risc); | 	risc = &chip->buf->risc; | ||||||
|  | 	pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma); | ||||||
| 	kfree(chip->buf); | 	kfree(chip->buf); | ||||||
| 
 | 
 | ||||||
| 	chip->dma_risc = NULL; | 	chip->buf = NULL; | ||||||
| 	chip->dma_size = 0; | 	chip->dma_size = 0; | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -289,6 +364,7 @@ static int snd_cx23885_close(struct snd_pcm_substream *substream) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * hw_params callback |  * hw_params callback | ||||||
|  */ |  */ | ||||||
|  | @ -296,8 +372,6 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, | ||||||
| 			      struct snd_pcm_hw_params *hw_params) | 			      struct snd_pcm_hw_params *hw_params) | ||||||
| { | { | ||||||
| 	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); | 	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); | ||||||
| 	struct videobuf_dmabuf *dma; |  | ||||||
| 
 |  | ||||||
| 	struct cx23885_audio_buffer *buf; | 	struct cx23885_audio_buffer *buf; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -318,19 +392,18 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	buf->bpl = chip->period_size; | 	buf->bpl = chip->period_size; | ||||||
|  | 	chip->buf = buf; | ||||||
| 
 | 
 | ||||||
| 	dma = &buf->dma; | 	ret = cx23885_alsa_dma_init(chip, | ||||||
| 	videobuf_dma_init(dma); |  | ||||||
| 	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, |  | ||||||
| 			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); | 			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	ret = videobuf_dma_map(&chip->pci->dev, dma); | 	ret = cx23885_alsa_dma_map(chip); | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist, | 	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, buf->sglist, | ||||||
| 				   chip->period_size, chip->num_periods, 1); | 				   chip->period_size, chip->num_periods, 1); | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		goto error; | 		goto error; | ||||||
|  | @ -340,10 +413,7 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, | ||||||
| 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||||||
| 	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | 	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | ||||||
| 
 | 
 | ||||||
| 	chip->buf = buf; | 	substream->runtime->dma_area = chip->buf->vaddr; | ||||||
| 	chip->dma_risc = dma; |  | ||||||
| 
 |  | ||||||
| 	substream->runtime->dma_area = chip->dma_risc->vaddr; |  | ||||||
| 	substream->runtime->dma_bytes = chip->dma_size; | 	substream->runtime->dma_bytes = chip->dma_size; | ||||||
| 	substream->runtime->dma_addr = 0; | 	substream->runtime->dma_addr = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -351,6 +421,7 @@ static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, | ||||||
| 
 | 
 | ||||||
| error: | error: | ||||||
| 	kfree(buf); | 	kfree(buf); | ||||||
|  | 	chip->buf = NULL; | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,11 +14,6 @@ | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  *  GNU General Public License for more details. |  *  GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |  | ||||||
|  *  02110-1301, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "cx23885.h" | #include "cx23885.h" | ||||||
|  |  | ||||||
|  | @ -14,11 +14,6 @@ | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  *  GNU General Public License for more details. |  *  GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |  | ||||||
|  *  02110-1301, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef _CX23885_AV_H_ | #ifndef _CX23885_AV_H_ | ||||||
|  |  | ||||||
|  | @ -13,10 +13,6 @@ | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  * |  * | ||||||
|  *  GNU General Public License for more details. |  *  GNU General Public License for more details. | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
|  | @ -679,6 +675,11 @@ struct cx23885_board cx23885_boards[] = { | ||||||
| 			.amux   = CX25840_AUDIO7, | 			.amux   = CX25840_AUDIO7, | ||||||
| 		} }, | 		} }, | ||||||
| 	}, | 	}, | ||||||
|  | 	[CX23885_BOARD_DVBSKY_T9580] = { | ||||||
|  | 		.name		= "DVBSky T9580", | ||||||
|  | 		.portb		= CX23885_MPEG_DVB, | ||||||
|  | 		.portc		= CX23885_MPEG_DVB, | ||||||
|  | 	}, | ||||||
| }; | }; | ||||||
| const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | ||||||
| 
 | 
 | ||||||
|  | @ -934,6 +935,10 @@ struct cx23885_subid cx23885_subids[] = { | ||||||
| 		.subvendor = 0x18ac, | 		.subvendor = 0x18ac, | ||||||
| 		.subdevice = 0xdb98, | 		.subdevice = 0xdb98, | ||||||
| 		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2, | 		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2, | ||||||
|  | 	}, { | ||||||
|  | 		.subvendor = 0x4254, | ||||||
|  | 		.subdevice = 0x9580, | ||||||
|  | 		.card      = CX23885_BOARD_DVBSKY_T9580, | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
| const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | ||||||
|  | @ -1528,6 +1533,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | ||||||
| 		cx_set(GP0_IO, 0x00040004); | 		cx_set(GP0_IO, 0x00040004); | ||||||
| 		mdelay(60); | 		mdelay(60); | ||||||
| 		break; | 		break; | ||||||
|  | 	case CX23885_BOARD_DVBSKY_T9580: | ||||||
|  | 		/* enable GPIO3-18 pins */ | ||||||
|  | 		cx_write(MC417_CTL, 0x00000037); | ||||||
|  | 		cx23885_gpio_enable(dev, GPIO_2 | GPIO_11, 1); | ||||||
|  | 		cx23885_gpio_clear(dev, GPIO_2 | GPIO_11); | ||||||
|  | 		mdelay(100); | ||||||
|  | 		cx23885_gpio_set(dev, GPIO_2 | GPIO_11); | ||||||
|  | 		break; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1851,6 +1864,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) | ||||||
| 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||||||
| 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||||||
| 		break; | 		break; | ||||||
|  | 	case CX23885_BOARD_DVBSKY_T9580: | ||||||
|  | 		ts1->gen_ctrl_val  = 0x5; /* Parallel */ | ||||||
|  | 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||||||
|  | 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||||||
|  | 		ts2->gen_ctrl_val  = 0x8; /* Serial bus */ | ||||||
|  | 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||||||
|  | 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||||||
|  | 		break; | ||||||
| 	case CX23885_BOARD_HAUPPAUGE_HVR1250: | 	case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||||||
| 	case CX23885_BOARD_HAUPPAUGE_HVR1500: | 	case CX23885_BOARD_HAUPPAUGE_HVR1500: | ||||||
| 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | ||||||
|  | @ -1913,6 +1934,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | ||||||
| 	case CX23885_BOARD_AVERMEDIA_HC81R: | 	case CX23885_BOARD_AVERMEDIA_HC81R: | ||||||
| 	case CX23885_BOARD_TBS_6980: | 	case CX23885_BOARD_TBS_6980: | ||||||
| 	case CX23885_BOARD_TBS_6981: | 	case CX23885_BOARD_TBS_6981: | ||||||
|  | 	case CX23885_BOARD_DVBSKY_T9580: | ||||||
| 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | ||||||
| 				&dev->i2c_bus[2].i2c_adap, | 				&dev->i2c_bus[2].i2c_adap, | ||||||
| 				"cx25840", 0x88 >> 1, NULL); | 				"cx25840", 0x88 >> 1, NULL); | ||||||
|  | @ -1970,5 +1992,3 @@ void cx23885_card_setup(struct cx23885_dev *dev) | ||||||
| 	} | 	} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /* ------------------------------------------------------------------ */ |  | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Torvalds
				Linus Torvalds