Pull media updates from Mauro Carvalho Chehab: "This contains: - a new frontend/tuner driver set for si2168 and sa2157 - Videobuf 2 core now supports DVB too - A new gspca sub-driver (dtcs033) - saa7134 is now converted to use videobuf2 - add support for 4K timings - several other driver fixes and improvements PS. This pull request is shorter than usual, partly because I have some other patches on topic branches that I'll be sending you later this week" * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (286 commits) [media] au0828-dvb: restore its permission to 644 [media] xc5000: delay tuner sleep to 5 seconds [media] xc5000: Don't use whitespace before tabs [media] xc5000: fix CamelCase [media] xc5000: Don't wrap msleep() [media] xc5000: get rid of positive error codes [media] au0828: reset streaming when a new frequency is set [media] au0828: Improve debug messages for urb_completion [media] au0828: Cancel stream-restart operation if frontend is disconnected [media] dib0700: fix RC support on Hauppauge Nova-TD [media] USB: as102_usb_drv.c: Remove useless return variables [media] v4l: Fix documentation of V4L2_PIX_FMT_H264_MVC and VP8 pixel formats [media] m5mols: Replace missing header [media] staging: lirc: Fix sparse warnings [media] fix mceusb endpoint type identification/handling [media] az6027: Added the PID for a new revision of the Elgato EyeTV Sat DVB-S Tuner [media] DocBook media: fix typo [media] adv7604: Add missing include to linux/types.h [media] v4l: Validate fields in the core code for subdev EDID ioctls [media] v4l: Add support for DV timings ioctls on subdev nodes ...
Unified · Split
| @@ -125,7 +125,7 @@ location of the buffers in device memory can be determined with the · 124 unmodified lines | ||
| 125 | 125 | <structfield>m.offset</structfield> and <structfield>length</structfield> |
| 126 | 126 | returned in a &v4l2-buffer; are passed as sixth and second parameter to the |
| 127 | 127 | <function>mmap()</function> function. When using the multi-planar API, |
| 128 | −struct &v4l2-buffer; contains an array of &v4l2-plane; structures, each | |
| 128 | +&v4l2-buffer; contains an array of &v4l2-plane; structures, each | |
| 129 | 129 | containing its own <structfield>m.offset</structfield> and |
| 130 | 130 | <structfield>length</structfield>. When using the multi-planar API, every |
| 131 | 131 | plane of every buffer has to be mapped separately, so the number of |
| @@ -699,7 +699,12 @@ linkend="v4l2-buf-type" /></entry> · 567 unmodified lines | ||
| 699 | 699 | buffer. It depends on the negotiated data format and may change with |
| 700 | 700 | each buffer for compressed variable size data like JPEG images. |
| 701 | 701 | Drivers must set this field when <structfield>type</structfield> |
| 702 | −refers to an input stream, applications when it refers to an output stream.</entry> | |
| 702 | +refers to an input stream, applications when it refers to an output stream. | |
| 703 | +If the application sets this to 0 for an output stream, then | |
| 704 | +<structfield>bytesused</structfield> will be set to the size of the | |
| 705 | +buffer (see the <structfield>length</structfield> field of this struct) by | |
| 706 | +the driver. For multiplanar formats this field is ignored and the | |
| 707 | +<structfield>planes</structfield> pointer is used instead.</entry> | |
| 703 | 708 | </row> |
| 704 | 709 | <row> |
| 705 | 710 | <entry>__u32</entry> |
| @@ -861,7 +866,11 @@ should set this to 0.</entry> · 155 unmodified lines | ||
| 861 | 866 | <entry></entry> |
| 862 | 867 | <entry>The number of bytes occupied by data in the plane |
| 863 | 868 | (its payload). Drivers must set this field when <structfield>type</structfield> |
| 864 | − refers to an input stream, applications when it refers to an output stream.</entry> | |
| 869 | + refers to an input stream, applications when it refers to an output stream. | |
| 870 | + If the application sets this to 0 for an output stream, then | |
| 871 | + <structfield>bytesused</structfield> will be set to the size of the | |
| 872 | + plane (see the <structfield>length</structfield> field of this struct) | |
| 873 | + by the driver.</entry> | |
| 865 | 874 | </row> |
| 866 | 875 | <row> |
| 867 | 876 | <entry>__u32</entry> |
| @@ -79,13 +79,13 @@ · 78 unmodified lines | ||
| 79 | 79 | <entry>Entity id, set by the application.</entry> |
| 80 | 80 | </row> |
| 81 | 81 | <row> |
| 82 | − <entry>struct &media-pad-desc;</entry> | |
| 82 | + <entry>&media-pad-desc;</entry> | |
| 83 | 83 | <entry>*<structfield>pads</structfield></entry> |
| 84 | 84 | <entry>Pointer to a pads array allocated by the application. Ignored |
| 85 | 85 | if NULL.</entry> |
| 86 | 86 | </row> |
| 87 | 87 | <row> |
| 88 | − <entry>struct &media-link-desc;</entry> | |
| 88 | + <entry>&media-link-desc;</entry> | |
| 89 | 89 | <entry>*<structfield>links</structfield></entry> |
| 90 | 90 | <entry>Pointer to a links array allocated by the application. Ignored |
| 91 | 91 | if NULL.</entry> |
| @@ -153,12 +153,12 @@ · 61 unmodified lines | ||
| 153 | 153 | &cs-str; |
| 154 | 154 | <tbody valign="top"> |
| 155 | 155 | <row> |
| 156 | − <entry>struct &media-pad-desc;</entry> | |
| 156 | + <entry>&media-pad-desc;</entry> | |
| 157 | 157 | <entry><structfield>source</structfield></entry> |
| 158 | 158 | <entry>Pad at the origin of this link.</entry> |
| 159 | 159 | </row> |
| 160 | 160 | <row> |
| 161 | − <entry>struct &media-pad-desc;</entry> | |
| 161 | + <entry>&media-pad-desc;</entry> | |
| 162 | 162 | <entry><structfield>sink</structfield></entry> |
| 163 | 163 | <entry>Pad at the target of this link.</entry> |
| 164 | 164 | </row> |
| @@ -772,7 +772,7 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see · 771 unmodified lines | ||
| 772 | 772 | </row> |
| 773 | 773 | <row id="V4L2-PIX-FMT-H264-MVC"> |
| 774 | 774 | <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry> |
| 775 | − <entry>'MVC'</entry> | |
| 775 | + <entry>'M264'</entry> | |
| 776 | 776 | <entry>H264 MVC video elementary stream.</entry> |
| 777 | 777 | </row> |
| 778 | 778 | <row id="V4L2-PIX-FMT-H263"> |
| @@ -812,7 +812,7 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see · 33 unmodified lines | ||
| 812 | 812 | </row> |
| 813 | 813 | <row id="V4L2-PIX-FMT-VP8"> |
| 814 | 814 | <entry><constant>V4L2_PIX_FMT_VP8</constant></entry> |
| 815 | − <entry>'VP8'</entry> | |
| 815 | + <entry>'VP80'</entry> | |
| 816 | 816 | <entry>VP8 video elementary stream.</entry> |
| 817 | 817 | </row> |
| 818 | 818 | </tbody> |
| @@ -1898,6 +1898,134 @@ · 1897 unmodified lines | ||
| 1898 | 1898 | <entry>y<subscript>1</subscript></entry> |
| 1899 | 1899 | <entry>y<subscript>0</subscript></entry> |
| 1900 | 1900 | </row> |
| 1901 | + <row id="V4L2-MBUS-FMT-UYVY10-2X10"> | |
| 1902 | + <entry>V4L2_MBUS_FMT_UYVY10_2X10</entry> | |
| 1903 | + <entry>0x2018</entry> | |
| 1904 | + <entry></entry> | |
| 1905 | + &dash-ent-22; | |
| 1906 | + <entry>u<subscript>9</subscript></entry> | |
| 1907 | + <entry>u<subscript>8</subscript></entry> | |
| 1908 | + <entry>u<subscript>7</subscript></entry> | |
| 1909 | + <entry>u<subscript>6</subscript></entry> | |
| 1910 | + <entry>u<subscript>5</subscript></entry> | |
| 1911 | + <entry>u<subscript>4</subscript></entry> | |
| 1912 | + <entry>u<subscript>3</subscript></entry> | |
| 1913 | + <entry>u<subscript>2</subscript></entry> | |
| 1914 | + <entry>u<subscript>1</subscript></entry> | |
| 1915 | + <entry>u<subscript>0</subscript></entry> | |
| 1916 | + </row> | |
| 1917 | + <row> | |
| 1918 | + <entry></entry> | |
| 1919 | + <entry></entry> | |
| 1920 | + <entry></entry> | |
| 1921 | + &dash-ent-22; | |
| 1922 | + <entry>y<subscript>9</subscript></entry> | |
| 1923 | + <entry>y<subscript>8</subscript></entry> | |
| 1924 | + <entry>y<subscript>7</subscript></entry> | |
| 1925 | + <entry>y<subscript>6</subscript></entry> | |
| 1926 | + <entry>y<subscript>5</subscript></entry> | |
| 1927 | + <entry>y<subscript>4</subscript></entry> | |
| 1928 | + <entry>y<subscript>3</subscript></entry> | |
| 1929 | + <entry>y<subscript>2</subscript></entry> | |
| 1930 | + <entry>y<subscript>1</subscript></entry> | |
| 1931 | + <entry>y<subscript>0</subscript></entry> | |
| 1932 | + </row> | |
| 1933 | + <row> | |
| 1934 | + <entry></entry> | |
| 1935 | + <entry></entry> | |
| 1936 | + <entry></entry> | |
| 1937 | + &dash-ent-22; | |
| 1938 | + <entry>v<subscript>9</subscript></entry> | |
| 1939 | + <entry>v<subscript>8</subscript></entry> | |
| 1940 | + <entry>v<subscript>7</subscript></entry> | |
| 1941 | + <entry>v<subscript>6</subscript></entry> | |
| 1942 | + <entry>v<subscript>5</subscript></entry> | |
| 1943 | + <entry>v<subscript>4</subscript></entry> | |
| 1944 | + <entry>v<subscript>3</subscript></entry> | |
| 1945 | + <entry>v<subscript>2</subscript></entry> | |
| 1946 | + <entry>v<subscript>1</subscript></entry> | |
| 1947 | + <entry>v<subscript>0</subscript></entry> | |
| 1948 | + </row> | |
| 1949 | + <row> | |
| 1950 | + <entry></entry> | |
| 1951 | + <entry></entry> | |
| 1952 | + <entry></entry> | |
| 1953 | + &dash-ent-22; | |
| 1954 | + <entry>y<subscript>9</subscript></entry> | |
| 1955 | + <entry>y<subscript>8</subscript></entry> | |
| 1956 | + <entry>y<subscript>7</subscript></entry> | |
| 1957 | + <entry>y<subscript>6</subscript></entry> | |
| 1958 | + <entry>y<subscript>5</subscript></entry> | |
| 1959 | + <entry>y<subscript>4</subscript></entry> | |
| 1960 | + <entry>y<subscript>3</subscript></entry> | |
| 1961 | + <entry>y<subscript>2</subscript></entry> | |
| 1962 | + <entry>y<subscript>1</subscript></entry> | |
| 1963 | + <entry>y<subscript>0</subscript></entry> | |
| 1964 | + </row> | |
| 1965 | + <row id="V4L2-MBUS-FMT-VYUY10-2X10"> | |
| 1966 | + <entry>V4L2_MBUS_FMT_VYUY10_2X10</entry> | |
| 1967 | + <entry>0x2019</entry> | |
| 1968 | + <entry></entry> | |
| 1969 | + &dash-ent-22; | |
| 1970 | + <entry>v<subscript>9</subscript></entry> | |
| 1971 | + <entry>v<subscript>8</subscript></entry> | |
| 1972 | + <entry>v<subscript>7</subscript></entry> | |
| 1973 | + <entry>v<subscript>6</subscript></entry> | |
| 1974 | + <entry>v<subscript>5</subscript></entry> | |
| 1975 | + <entry>v<subscript>4</subscript></entry> | |
| 1976 | + <entry>v<subscript>3</subscript></entry> | |
| 1977 | + <entry>v<subscript>2</subscript></entry> | |
| 1978 | + <entry>v<subscript>1</subscript></entry> | |
| 1979 | + <entry>v<subscript>0</subscript></entry> | |
| 1980 | + </row> | |
| 1981 | + <row> | |
| 1982 | + <entry></entry> | |
| 1983 | + <entry></entry> | |
| 1984 | + <entry></entry> | |
| 1985 | + &dash-ent-22; | |
| 1986 | + <entry>y<subscript>9</subscript></entry> | |
| 1987 | + <entry>y<subscript>8</subscript></entry> | |
| 1988 | + <entry>y<subscript>7</subscript></entry> | |
| 1989 | + <entry>y<subscript>6</subscript></entry> | |
| 1990 | + <entry>y<subscript>5</subscript></entry> | |
| 1991 | + <entry>y<subscript>4</subscript></entry> | |
| 1992 | + <entry>y<subscript>3</subscript></entry> | |
| 1993 | + <entry>y<subscript>2</subscript></entry> | |
| 1994 | + <entry>y<subscript>1</subscript></entry> | |
| 1995 | + <entry>y<subscript>0</subscript></entry> | |
| 1996 | + </row> | |
| 1997 | + <row> | |
| 1998 | + <entry></entry> | |
| 1999 | + <entry></entry> | |
| 2000 | + <entry></entry> | |
| 2001 | + &dash-ent-22; | |
| 2002 | + <entry>u<subscript>9</subscript></entry> | |
| 2003 | + <entry>u<subscript>8</subscript></entry> | |
| 2004 | + <entry>u<subscript>7</subscript></entry> | |
| 2005 | + <entry>u<subscript>6</subscript></entry> | |
| 2006 | + <entry>u<subscript>5</subscript></entry> | |
| 2007 | + <entry>u<subscript>4</subscript></entry> | |
| 2008 | + <entry>u<subscript>3</subscript></entry> | |
| 2009 | + <entry>u<subscript>2</subscript></entry> | |
| 2010 | + <entry>u<subscript>1</subscript></entry> | |
| 2011 | + <entry>u<subscript>0</subscript></entry> | |
| 2012 | + </row> | |
| 2013 | + <row> | |
| 2014 | + <entry></entry> | |
| 2015 | + <entry></entry> | |
| 2016 | + <entry></entry> | |
| 2017 | + &dash-ent-22; | |
| 2018 | + <entry>y<subscript>9</subscript></entry> | |
| 2019 | + <entry>y<subscript>8</subscript></entry> | |
| 2020 | + <entry>y<subscript>7</subscript></entry> | |
| 2021 | + <entry>y<subscript>6</subscript></entry> | |
| 2022 | + <entry>y<subscript>5</subscript></entry> | |
| 2023 | + <entry>y<subscript>4</subscript></entry> | |
| 2024 | + <entry>y<subscript>3</subscript></entry> | |
| 2025 | + <entry>y<subscript>2</subscript></entry> | |
| 2026 | + <entry>y<subscript>1</subscript></entry> | |
| 2027 | + <entry>y<subscript>0</subscript></entry> | |
| 2028 | + </row> | |
| 1901 | 2029 | <row id="V4L2-MBUS-FMT-YUYV10-2X10"> |
| 1902 | 2030 | <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry> |
| 1903 | 2031 | <entry>0x200b</entry> |
| @@ -2308,6 +2436,110 @@ · 404 unmodified lines | ||
| 2308 | 2436 | <entry>v<subscript>1</subscript></entry> |
| 2309 | 2437 | <entry>v<subscript>0</subscript></entry> |
| 2310 | 2438 | </row> |
| 2439 | + <row id="V4L2-MBUS-FMT-UYVY10-1X20"> | |
| 2440 | + <entry>V4L2_MBUS_FMT_UYVY10_1X20</entry> | |
| 2441 | + <entry>0x201a</entry> | |
| 2442 | + <entry></entry> | |
| 2443 | + &dash-ent-12; | |
| 2444 | + <entry>u<subscript>9</subscript></entry> | |
| 2445 | + <entry>u<subscript>8</subscript></entry> | |
| 2446 | + <entry>u<subscript>7</subscript></entry> | |
| 2447 | + <entry>u<subscript>6</subscript></entry> | |
| 2448 | + <entry>u<subscript>5</subscript></entry> | |
| 2449 | + <entry>u<subscript>4</subscript></entry> | |
| 2450 | + <entry>u<subscript>3</subscript></entry> | |
| 2451 | + <entry>u<subscript>2</subscript></entry> | |
| 2452 | + <entry>u<subscript>1</subscript></entry> | |
| 2453 | + <entry>u<subscript>0</subscript></entry> | |
| 2454 | + <entry>y<subscript>9</subscript></entry> | |
| 2455 | + <entry>y<subscript>8</subscript></entry> | |
| 2456 | + <entry>y<subscript>7</subscript></entry> | |
| 2457 | + <entry>y<subscript>6</subscript></entry> | |
| 2458 | + <entry>y<subscript>5</subscript></entry> | |
| 2459 | + <entry>y<subscript>4</subscript></entry> | |
| 2460 | + <entry>y<subscript>3</subscript></entry> | |
| 2461 | + <entry>y<subscript>2</subscript></entry> | |
| 2462 | + <entry>y<subscript>1</subscript></entry> | |
| 2463 | + <entry>y<subscript>0</subscript></entry> | |
| 2464 | + </row> | |
| 2465 | + <row> | |
| 2466 | + <entry></entry> | |
| 2467 | + <entry></entry> | |
| 2468 | + <entry></entry> | |
| 2469 | + &dash-ent-12; | |
| 2470 | + <entry>v<subscript>9</subscript></entry> | |
| 2471 | + <entry>v<subscript>8</subscript></entry> | |
| 2472 | + <entry>v<subscript>7</subscript></entry> | |
| 2473 | + <entry>v<subscript>6</subscript></entry> | |
| 2474 | + <entry>v<subscript>5</subscript></entry> | |
| 2475 | + <entry>v<subscript>4</subscript></entry> | |
| 2476 | + <entry>v<subscript>3</subscript></entry> | |
| 2477 | + <entry>v<subscript>2</subscript></entry> | |
| 2478 | + <entry>v<subscript>1</subscript></entry> | |
| 2479 | + <entry>v<subscript>0</subscript></entry> | |
| 2480 | + <entry>y<subscript>9</subscript></entry> | |
| 2481 | + <entry>y<subscript>8</subscript></entry> | |
| 2482 | + <entry>y<subscript>7</subscript></entry> | |
| 2483 | + <entry>y<subscript>6</subscript></entry> | |
| 2484 | + <entry>y<subscript>5</subscript></entry> | |
| 2485 | + <entry>y<subscript>4</subscript></entry> | |
| 2486 | + <entry>y<subscript>3</subscript></entry> | |
| 2487 | + <entry>y<subscript>2</subscript></entry> | |
| 2488 | + <entry>y<subscript>1</subscript></entry> | |
| 2489 | + <entry>y<subscript>0</subscript></entry> | |
| 2490 | + </row> | |
| 2491 | + <row id="V4L2-MBUS-FMT-VYUY10-1X20"> | |
| 2492 | + <entry>V4L2_MBUS_FMT_VYUY10_1X20</entry> | |
| 2493 | + <entry>0x201b</entry> | |
| 2494 | + <entry></entry> | |
| 2495 | + &dash-ent-12; | |
| 2496 | + <entry>v<subscript>9</subscript></entry> | |
| 2497 | + <entry>v<subscript>8</subscript></entry> | |
| 2498 | + <entry>v<subscript>7</subscript></entry> | |
| 2499 | + <entry>v<subscript>6</subscript></entry> | |
| 2500 | + <entry>v<subscript>5</subscript></entry> | |
| 2501 | + <entry>v<subscript>4</subscript></entry> | |
| 2502 | + <entry>v<subscript>3</subscript></entry> | |
| 2503 | + <entry>v<subscript>2</subscript></entry> | |
| 2504 | + <entry>v<subscript>1</subscript></entry> | |
| 2505 | + <entry>v<subscript>0</subscript></entry> | |
| 2506 | + <entry>y<subscript>9</subscript></entry> | |
| 2507 | + <entry>y<subscript>8</subscript></entry> | |
| 2508 | + <entry>y<subscript>7</subscript></entry> | |
| 2509 | + <entry>y<subscript>6</subscript></entry> | |
| 2510 | + <entry>y<subscript>5</subscript></entry> | |
| 2511 | + <entry>y<subscript>4</subscript></entry> | |
| 2512 | + <entry>y<subscript>3</subscript></entry> | |
| 2513 | + <entry>y<subscript>2</subscript></entry> | |
| 2514 | + <entry>y<subscript>1</subscript></entry> | |
| 2515 | + <entry>y<subscript>0</subscript></entry> | |
| 2516 | + </row> | |
| 2517 | + <row> | |
| 2518 | + <entry></entry> | |
| 2519 | + <entry></entry> | |
| 2520 | + <entry></entry> | |
| 2521 | + &dash-ent-12; | |
| 2522 | + <entry>u<subscript>9</subscript></entry> | |
| 2523 | + <entry>u<subscript>8</subscript></entry> | |
| 2524 | + <entry>u<subscript>7</subscript></entry> | |
| 2525 | + <entry>u<subscript>6</subscript></entry> | |
| 2526 | + <entry>u<subscript>5</subscript></entry> | |
| 2527 | + <entry>u<subscript>4</subscript></entry> | |
| 2528 | + <entry>u<subscript>3</subscript></entry> | |
| 2529 | + <entry>u<subscript>2</subscript></entry> | |
| 2530 | + <entry>u<subscript>1</subscript></entry> | |
| 2531 | + <entry>u<subscript>0</subscript></entry> | |
| 2532 | + <entry>y<subscript>9</subscript></entry> | |
| 2533 | + <entry>y<subscript>8</subscript></entry> | |
| 2534 | + <entry>y<subscript>7</subscript></entry> | |
| 2535 | + <entry>y<subscript>6</subscript></entry> | |
| 2536 | + <entry>y<subscript>5</subscript></entry> | |
| 2537 | + <entry>y<subscript>4</subscript></entry> | |
| 2538 | + <entry>y<subscript>3</subscript></entry> | |
| 2539 | + <entry>y<subscript>2</subscript></entry> | |
| 2540 | + <entry>y<subscript>1</subscript></entry> | |
| 2541 | + <entry>y<subscript>0</subscript></entry> | |
| 2542 | + </row> | |
| 2311 | 2543 | <row id="V4L2-MBUS-FMT-YUYV10-1X20"> |
| 2312 | 2544 | <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry> |
| 2313 | 2545 | <entry>0x200d</entry> |
| @@ -2486,6 +2718,534 @@ · 172 unmodified lines | ||
| 2486 | 2718 | <entry>v<subscript>1</subscript></entry> |
| 2487 | 2719 | <entry>v<subscript>0</subscript></entry> |
| 2488 | 2720 | </row> |
| 2721 | + <row id="V4L2-MBUS-FMT-UYVY12-2X12"> | |
| 2722 | + <entry>V4L2_MBUS_FMT_UYVY12_2X12</entry> | |
| 2723 | + <entry>0x201c</entry> | |
| 2724 | + <entry></entry> | |
| 2725 | + &dash-ent-20; | |
| 2726 | + <entry>u<subscript>11</subscript></entry> | |
| 2727 | + <entry>u<subscript>10</subscript></entry> | |
| 2728 | + <entry>u<subscript>9</subscript></entry> | |
| 2729 | + <entry>u<subscript>8</subscript></entry> | |
| 2730 | + <entry>u<subscript>7</subscript></entry> | |
| 2731 | + <entry>u<subscript>6</subscript></entry> | |
| 2732 | + <entry>u<subscript>5</subscript></entry> | |
| 2733 | + <entry>u<subscript>4</subscript></entry> | |
| 2734 | + <entry>u<subscript>3</subscript></entry> | |
| 2735 | + <entry>u<subscript>2</subscript></entry> | |
| 2736 | + <entry>u<subscript>1</subscript></entry> | |
| 2737 | + <entry>u<subscript>0</subscript></entry> | |
| 2738 | + </row> | |
| 2739 | + <row> | |
| 2740 | + <entry></entry> | |
| 2741 | + <entry></entry> | |
| 2742 | + <entry></entry> | |
| 2743 | + &dash-ent-20; | |
| 2744 | + <entry>y<subscript>11</subscript></entry> | |
| 2745 | + <entry>y<subscript>10</subscript></entry> | |
| 2746 | + <entry>y<subscript>9</subscript></entry> | |
| 2747 | + <entry>y<subscript>8</subscript></entry> | |
| 2748 | + <entry>y<subscript>7</subscript></entry> | |
| 2749 | + <entry>y<subscript>6</subscript></entry> | |
| 2750 | + <entry>y<subscript>5</subscript></entry> | |
| 2751 | + <entry>y<subscript>4</subscript></entry> | |
| 2752 | + <entry>y<subscript>3</subscript></entry> | |
| 2753 | + <entry>y<subscript>2</subscript></entry> | |
| 2754 | + <entry>y<subscript>1</subscript></entry> | |
| 2755 | + <entry>y<subscript>0</subscript></entry> | |
| 2756 | + </row> | |
| 2757 | + <row> | |
| 2758 | + <entry></entry> | |
| 2759 | + <entry></entry> | |
| 2760 | + <entry></entry> | |
| 2761 | + &dash-ent-20; | |
| 2762 | + <entry>v<subscript>11</subscript></entry> | |
| 2763 | + <entry>v<subscript>10</subscript></entry> | |
| 2764 | + <entry>v<subscript>9</subscript></entry> | |
| 2765 | + <entry>v<subscript>8</subscript></entry> | |
| 2766 | + <entry>v<subscript>7</subscript></entry> | |
| 2767 | + <entry>v<subscript>6</subscript></entry> | |
| 2768 | + <entry>v<subscript>5</subscript></entry> | |
| 2769 | + <entry>v<subscript>4</subscript></entry> | |
| 2770 | + <entry>v<subscript>3</subscript></entry> | |
| 2771 | + <entry>v<subscript>2</subscript></entry> | |
| 2772 | + <entry>v<subscript>1</subscript></entry> | |
| 2773 | + <entry>v<subscript>0</subscript></entry> | |
| 2774 | + </row> | |
| 2775 | + <row> | |
| 2776 | + <entry></entry> | |
| 2777 | + <entry></entry> | |
| 2778 | + <entry></entry> | |
| 2779 | + &dash-ent-20; | |
| 2780 | + <entry>y<subscript>11</subscript></entry> | |
| 2781 | + <entry>y<subscript>10</subscript></entry> | |
| 2782 | + <entry>y<subscript>9</subscript></entry> | |
| 2783 | + <entry>y<subscript>8</subscript></entry> | |
| 2784 | + <entry>y<subscript>7</subscript></entry> | |
| 2785 | + <entry>y<subscript>6</subscript></entry> | |
| 2786 | + <entry>y<subscript>5</subscript></entry> | |
| 2787 | + <entry>y<subscript>4</subscript></entry> | |
| 2788 | + <entry>y<subscript>3</subscript></entry> | |
| 2789 | + <entry>y<subscript>2</subscript></entry> | |
| 2790 | + <entry>y<subscript>1</subscript></entry> | |
| 2791 | + <entry>y<subscript>0</subscript></entry> | |
| 2792 | + </row> | |
| 2793 | + <row id="V4L2-MBUS-FMT-VYUY12-2X12"> | |
| 2794 | + <entry>V4L2_MBUS_FMT_VYUY12_2X12</entry> | |
| 2795 | + <entry>0x201d</entry> | |
| 2796 | + <entry></entry> | |
| 2797 | + &dash-ent-20; | |
| 2798 | + <entry>v<subscript>11</subscript></entry> | |
| 2799 | + <entry>v<subscript>10</subscript></entry> | |
| 2800 | + <entry>v<subscript>9</subscript></entry> | |
| 2801 | + <entry>v<subscript>8</subscript></entry> | |
| 2802 | + <entry>v<subscript>7</subscript></entry> | |
| 2803 | + <entry>v<subscript>6</subscript></entry> | |
| 2804 | + <entry>v<subscript>5</subscript></entry> | |
| 2805 | + <entry>v<subscript>4</subscript></entry> | |
| 2806 | + <entry>v<subscript>3</subscript></entry> | |
| 2807 | + <entry>v<subscript>2</subscript></entry> | |
| 2808 | + <entry>v<subscript>1</subscript></entry> | |
| 2809 | + <entry>v<subscript>0</subscript></entry> | |
| 2810 | + </row> | |
| 2811 | + <row> | |
| 2812 | + <entry></entry> | |
| 2813 | + <entry></entry> | |
| 2814 | + <entry></entry> | |
| 2815 | + &dash-ent-20; | |
| 2816 | + <entry>y<subscript>11</subscript></entry> | |
| 2817 | + <entry>y<subscript>10</subscript></entry> | |
| 2818 | + <entry>y<subscript>9</subscript></entry> | |
| 2819 | + <entry>y<subscript>8</subscript></entry> | |
| 2820 | + <entry>y<subscript>7</subscript></entry> | |
| 2821 | + <entry>y<subscript>6</subscript></entry> | |
| 2822 | + <entry>y<subscript>5</subscript></entry> | |
| 2823 | + <entry>y<subscript>4</subscript></entry> | |
| 2824 | + <entry>y<subscript>3</subscript></entry> | |
| 2825 | + <entry>y<subscript>2</subscript></entry> | |
| 2826 | + <entry>y<subscript>1</subscript></entry> | |
| 2827 | + <entry>y<subscript>0</subscript></entry> | |
| 2828 | + </row> | |
| 2829 | + <row> | |
| 2830 | + <entry></entry> | |
| 2831 | + <entry></entry> | |
| 2832 | + <entry></entry> | |
| 2833 | + &dash-ent-20; | |
| 2834 | + <entry>u<subscript>11</subscript></entry> | |
| 2835 | + <entry>u<subscript>10</subscript></entry> | |
| 2836 | + <entry>u<subscript>9</subscript></entry> | |
| 2837 | + <entry>u<subscript>8</subscript></entry> | |
| 2838 | + <entry>u<subscript>7</subscript></entry> | |
| 2839 | + <entry>u<subscript>6</subscript></entry> | |
| 2840 | + <entry>u<subscript>5</subscript></entry> | |
| 2841 | + <entry>u<subscript>4</subscript></entry> | |
| 2842 | + <entry>u<subscript>3</subscript></entry> | |
| 2843 | + <entry>u<subscript>2</subscript></entry> | |
| 2844 | + <entry>u<subscript>1</subscript></entry> | |
| 2845 | + <entry>u<subscript>0</subscript></entry> | |
| 2846 | + </row> | |
| 2847 | + <row> | |
| 2848 | + <entry></entry> | |
| 2849 | + <entry></entry> | |
| 2850 | + <entry></entry> | |
| 2851 | + &dash-ent-20; | |
| 2852 | + <entry>y<subscript>11</subscript></entry> | |
| 2853 | + <entry>y<subscript>10</subscript></entry> | |
| 2854 | + <entry>y<subscript>9</subscript></entry> | |
| 2855 | + <entry>y<subscript>8</subscript></entry> | |
| 2856 | + <entry>y<subscript>7</subscript></entry> | |
| 2857 | + <entry>y<subscript>6</subscript></entry> | |
| 2858 | + <entry>y<subscript>5</subscript></entry> | |
| 2859 | + <entry>y<subscript>4</subscript></entry> | |
| 2860 | + <entry>y<subscript>3</subscript></entry> | |
| 2861 | + <entry>y<subscript>2</subscript></entry> | |
| 2862 | + <entry>y<subscript>1</subscript></entry> | |
| 2863 | + <entry>y<subscript>0</subscript></entry> | |
| 2864 | + </row> | |
| 2865 | + <row id="V4L2-MBUS-FMT-YUYV12-2X12"> | |
| 2866 | + <entry>V4L2_MBUS_FMT_YUYV12_2X12</entry> | |
| 2867 | + <entry>0x201e</entry> | |
| 2868 | + <entry></entry> | |
| 2869 | + &dash-ent-20; | |
| 2870 | + <entry>y<subscript>11</subscript></entry> | |
| 2871 | + <entry>y<subscript>10</subscript></entry> | |
| 2872 | + <entry>y<subscript>9</subscript></entry> | |
| 2873 | + <entry>y<subscript>8</subscript></entry> | |
| 2874 | + <entry>y<subscript>7</subscript></entry> | |
| 2875 | + <entry>y<subscript>6</subscript></entry> | |
| 2876 | + <entry>y<subscript>5</subscript></entry> | |
| 2877 | + <entry>y<subscript>4</subscript></entry> | |
| 2878 | + <entry>y<subscript>3</subscript></entry> | |
| 2879 | + <entry>y<subscript>2</subscript></entry> | |
| 2880 | + <entry>y<subscript>1</subscript></entry> | |
| 2881 | + <entry>y<subscript>0</subscript></entry> | |
| 2882 | + </row> | |
| 2883 | + <row> | |
| 2884 | + <entry></entry> | |
| 2885 | + <entry></entry> | |
| 2886 | + <entry></entry> | |
| 2887 | + &dash-ent-20; | |
| 2888 | + <entry>u<subscript>11</subscript></entry> | |
| 2889 | + <entry>u<subscript>10</subscript></entry> | |
| 2890 | + <entry>u<subscript>9</subscript></entry> | |
| 2891 | + <entry>u<subscript>8</subscript></entry> | |
| 2892 | + <entry>u<subscript>7</subscript></entry> | |
| 2893 | + <entry>u<subscript>6</subscript></entry> | |
| 2894 | + <entry>u<subscript>5</subscript></entry> | |
| 2895 | + <entry>u<subscript>4</subscript></entry> | |
| 2896 | + <entry>u<subscript>3</subscript></entry> | |
| 2897 | + <entry>u<subscript>2</subscript></entry> | |
| 2898 | + <entry>u<subscript>1</subscript></entry> | |
| 2899 | + <entry>u<subscript>0</subscript></entry> | |
| 2900 | + </row> | |
| 2901 | + <row> | |
| 2902 | + <entry></entry> | |
| 2903 | + <entry></entry> | |
| 2904 | + <entry></entry> | |
| 2905 | + &dash-ent-20; | |
| 2906 | + <entry>y<subscript>11</subscript></entry> | |
| 2907 | + <entry>y<subscript>10</subscript></entry> | |
| 2908 | + <entry>y<subscript>9</subscript></entry> | |
| 2909 | + <entry>y<subscript>8</subscript></entry> | |
| 2910 | + <entry>y<subscript>7</subscript></entry> | |
| 2911 | + <entry>y<subscript>6</subscript></entry> | |
| 2912 | + <entry>y<subscript>5</subscript></entry> | |
| 2913 | + <entry>y<subscript>4</subscript></entry> | |
| 2914 | + <entry>y<subscript>3</subscript></entry> | |
| 2915 | + <entry>y<subscript>2</subscript></entry> | |
| 2916 | + <entry>y<subscript>1</subscript></entry> | |
| 2917 | + <entry>y<subscript>0</subscript></entry> | |
| 2918 | + </row> | |
| 2919 | + <row> | |
| 2920 | + <entry></entry> | |
| 2921 | + <entry></entry> | |
| 2922 | + <entry></entry> | |
| 2923 | + &dash-ent-20; | |
| 2924 | + <entry>v<subscript>11</subscript></entry> | |
| 2925 | + <entry>v<subscript>10</subscript></entry> | |
| 2926 | + <entry>v<subscript>9</subscript></entry> | |
| 2927 | + <entry>v<subscript>8</subscript></entry> | |
| 2928 | + <entry>v<subscript>7</subscript></entry> | |
| 2929 | + <entry>v<subscript>6</subscript></entry> | |
| 2930 | + <entry>v<subscript>5</subscript></entry> | |
| 2931 | + <entry>v<subscript>4</subscript></entry> | |
| 2932 | + <entry>v<subscript>3</subscript></entry> | |
| 2933 | + <entry>v<subscript>2</subscript></entry> | |
| 2934 | + <entry>v<subscript>1</subscript></entry> | |
| 2935 | + <entry>v<subscript>0</subscript></entry> | |
| 2936 | + </row> | |
| 2937 | + <row id="V4L2-MBUS-FMT-YVYU12-2X12"> | |
| 2938 | + <entry>V4L2_MBUS_FMT_YVYU12_2X12</entry> | |
| 2939 | + <entry>0x201f</entry> | |
| 2940 | + <entry></entry> | |
| 2941 | + &dash-ent-20; | |
| 2942 | + <entry>y<subscript>11</subscript></entry> | |
| 2943 | + <entry>y<subscript>10</subscript></entry> | |
| 2944 | + <entry>y<subscript>9</subscript></entry> | |
| 2945 | + <entry>y<subscript>8</subscript></entry> | |
| 2946 | + <entry>y<subscript>7</subscript></entry> | |
| 2947 | + <entry>y<subscript>6</subscript></entry> | |
| 2948 | + <entry>y<subscript>5</subscript></entry> | |
| 2949 | + <entry>y<subscript>4</subscript></entry> | |
| 2950 | + <entry>y<subscript>3</subscript></entry> | |
| 2951 | + <entry>y<subscript>2</subscript></entry> | |
| 2952 | + <entry>y<subscript>1</subscript></entry> | |
| 2953 | + <entry>y<subscript>0</subscript></entry> | |
| 2954 | + </row> | |
| 2955 | + <row> | |
| 2956 | + <entry></entry> | |
| 2957 | + <entry></entry> | |
| 2958 | + <entry></entry> | |
| 2959 | + &dash-ent-20; | |
| 2960 | + <entry>v<subscript>11</subscript></entry> | |
| 2961 | + <entry>v<subscript>10</subscript></entry> | |
| 2962 | + <entry>v<subscript>9</subscript></entry> | |
| 2963 | + <entry>v<subscript>8</subscript></entry> | |
| 2964 | + <entry>v<subscript>7</subscript></entry> | |
| 2965 | + <entry>v<subscript>6</subscript></entry> | |
| 2966 | + <entry>v<subscript>5</subscript></entry> | |
| 2967 | + <entry>v<subscript>4</subscript></entry> | |
| 2968 | + <entry>v<subscript>3</subscript></entry> | |
| 2969 | + <entry>v<subscript>2</subscript></entry> | |
| 2970 | + <entry>v<subscript>1</subscript></entry> | |
| 2971 | + <entry>v<subscript>0</subscript></entry> | |
| 2972 | + </row> | |
| 2973 | + <row> | |
| 2974 | + <entry></entry> | |
| 2975 | + <entry></entry> | |
| 2976 | + <entry></entry> | |
| 2977 | + &dash-ent-20; | |
| 2978 | + <entry>y<subscript>11</subscript></entry> | |
| 2979 | + <entry>y<subscript>10</subscript></entry> | |
| 2980 | + <entry>y<subscript>9</subscript></entry> | |
| 2981 | + <entry>y<subscript>8</subscript></entry> | |
| 2982 | + <entry>y<subscript>7</subscript></entry> | |
| 2983 | + <entry>y<subscript>6</subscript></entry> | |
| 2984 | + <entry>y<subscript>5</subscript></entry> | |
| 2985 | + <entry>y<subscript>4</subscript></entry> | |
| 2986 | + <entry>y<subscript>3</subscript></entry> | |
| 2987 | + <entry>y<subscript>2</subscript></entry> | |
| 2988 | + <entry>y<subscript>1</subscript></entry> | |
| 2989 | + <entry>y<subscript>0</subscript></entry> | |
| 2990 | + </row> | |
| 2991 | + <row> | |
| 2992 | + <entry></entry> | |
| 2993 | + <entry></entry> | |
| 2994 | + <entry></entry> | |
| 2995 | + &dash-ent-20; | |
| 2996 | + <entry>u<subscript>11</subscript></entry> | |
| 2997 | + <entry>u<subscript>10</subscript></entry> | |
| 2998 | + <entry>u<subscript>9</subscript></entry> | |
| 2999 | + <entry>u<subscript>8</subscript></entry> | |
| 3000 | + <entry>u<subscript>7</subscript></entry> | |
| 3001 | + <entry>u<subscript>6</subscript></entry> | |
| 3002 | + <entry>u<subscript>5</subscript></entry> | |
| 3003 | + <entry>u<subscript>4</subscript></entry> | |
| 3004 | + <entry>u<subscript>3</subscript></entry> | |
| 3005 | + <entry>u<subscript>2</subscript></entry> | |
| 3006 | + <entry>u<subscript>1</subscript></entry> | |
| 3007 | + <entry>u<subscript>0</subscript></entry> | |
| 3008 | + </row> | |
| 3009 | + <row id="V4L2-MBUS-FMT-UYVY12-1X24"> | |
| 3010 | + <entry>V4L2_MBUS_FMT_UYVY12_1X24</entry> | |
| 3011 | + <entry>0x2020</entry> | |
| 3012 | + <entry></entry> | |
| 3013 | + &dash-ent-8; | |
| 3014 | + <entry>u<subscript>11</subscript></entry> | |
| 3015 | + <entry>u<subscript>10</subscript></entry> | |
| 3016 | + <entry>u<subscript>9</subscript></entry> | |
| 3017 | + <entry>u<subscript>8</subscript></entry> | |
| 3018 | + <entry>u<subscript>7</subscript></entry> | |
| 3019 | + <entry>u<subscript>6</subscript></entry> | |
| 3020 | + <entry>u<subscript>5</subscript></entry> | |
| 3021 | + <entry>u<subscript>4</subscript></entry> | |
| 3022 | + <entry>u<subscript>3</subscript></entry> | |
| 3023 | + <entry>u<subscript>2</subscript></entry> | |
| 3024 | + <entry>u<subscript>1</subscript></entry> | |
| 3025 | + <entry>u<subscript>0</subscript></entry> | |
| 3026 | + <entry>y<subscript>11</subscript></entry> | |
| 3027 | + <entry>y<subscript>10</subscript></entry> | |
| 3028 | + <entry>y<subscript>9</subscript></entry> | |
| 3029 | + <entry>y<subscript>8</subscript></entry> | |
| 3030 | + <entry>y<subscript>7</subscript></entry> | |
| 3031 | + <entry>y<subscript>6</subscript></entry> | |
| 3032 | + <entry>y<subscript>5</subscript></entry> | |
| 3033 | + <entry>y<subscript>4</subscript></entry> | |
| 3034 | + <entry>y<subscript>3</subscript></entry> | |
| 3035 | + <entry>y<subscript>2</subscript></entry> | |
| 3036 | + <entry>y<subscript>1</subscript></entry> | |
| 3037 | + <entry>y<subscript>0</subscript></entry> | |
| 3038 | + </row> | |
| 3039 | + <row> | |
| 3040 | + <entry></entry> | |
| 3041 | + <entry></entry> | |
| 3042 | + <entry></entry> | |
| 3043 | + &dash-ent-8; | |
| 3044 | + <entry>v<subscript>11</subscript></entry> | |
| 3045 | + <entry>v<subscript>10</subscript></entry> | |
| 3046 | + <entry>v<subscript>9</subscript></entry> | |
| 3047 | + <entry>v<subscript>8</subscript></entry> | |
| 3048 | + <entry>v<subscript>7</subscript></entry> | |
| 3049 | + <entry>v<subscript>6</subscript></entry> | |
| 3050 | + <entry>v<subscript>5</subscript></entry> | |
| 3051 | + <entry>v<subscript>4</subscript></entry> | |
| 3052 | + <entry>v<subscript>3</subscript></entry> | |
| 3053 | + <entry>v<subscript>2</subscript></entry> | |
| 3054 | + <entry>v<subscript>1</subscript></entry> | |
| 3055 | + <entry>v<subscript>0</subscript></entry> | |
| 3056 | + <entry>y<subscript>11</subscript></entry> | |
| 3057 | + <entry>y<subscript>10</subscript></entry> | |
| 3058 | + <entry>y<subscript>9</subscript></entry> | |
| 3059 | + <entry>y<subscript>8</subscript></entry> | |
| 3060 | + <entry>y<subscript>7</subscript></entry> | |
| 3061 | + <entry>y<subscript>6</subscript></entry> | |
| 3062 | + <entry>y<subscript>5</subscript></entry> | |
| 3063 | + <entry>y<subscript>4</subscript></entry> | |
| 3064 | + <entry>y<subscript>3</subscript></entry> | |
| 3065 | + <entry>y<subscript>2</subscript></entry> | |
| 3066 | + <entry>y<subscript>1</subscript></entry> | |
| 3067 | + <entry>y<subscript>0</subscript></entry> | |
| 3068 | + </row> | |
| 3069 | + <row id="V4L2-MBUS-FMT-VYUY12-1X24"> | |
| 3070 | + <entry>V4L2_MBUS_FMT_VYUY12_1X24</entry> | |
| 3071 | + <entry>0x2021</entry> | |
| 3072 | + <entry></entry> | |
| 3073 | + &dash-ent-8; | |
| 3074 | + <entry>v<subscript>11</subscript></entry> | |
| 3075 | + <entry>v<subscript>10</subscript></entry> | |
| 3076 | + <entry>v<subscript>9</subscript></entry> | |
| 3077 | + <entry>v<subscript>8</subscript></entry> | |
| 3078 | + <entry>v<subscript>7</subscript></entry> | |
| 3079 | + <entry>v<subscript>6</subscript></entry> | |
| 3080 | + <entry>v<subscript>5</subscript></entry> | |
| 3081 | + <entry>v<subscript>4</subscript></entry> | |
| 3082 | + <entry>v<subscript>3</subscript></entry> | |
| 3083 | + <entry>v<subscript>2</subscript></entry> | |
| 3084 | + <entry>v<subscript>1</subscript></entry> | |
| 3085 | + <entry>v<subscript>0</subscript></entry> | |
| 3086 | + <entry>y<subscript>11</subscript></entry> | |
| 3087 | + <entry>y<subscript>10</subscript></entry> | |
| 3088 | + <entry>y<subscript>9</subscript></entry> | |
| 3089 | + <entry>y<subscript>8</subscript></entry> | |
| 3090 | + <entry>y<subscript>7</subscript></entry> | |
| 3091 | + <entry>y<subscript>6</subscript></entry> | |
| 3092 | + <entry>y<subscript>5</subscript></entry> | |
| 3093 | + <entry>y<subscript>4</subscript></entry> | |
| 3094 | + <entry>y<subscript>3</subscript></entry> | |
| 3095 | + <entry>y<subscript>2</subscript></entry> | |
| 3096 | + <entry>y<subscript>1</subscript></entry> | |
| 3097 | + <entry>y<subscript>0</subscript></entry> | |
| 3098 | + </row> | |
| 3099 | + <row> | |
| 3100 | + <entry></entry> | |
| 3101 | + <entry></entry> | |
| 3102 | + <entry></entry> | |
| 3103 | + &dash-ent-8; | |
| 3104 | + <entry>u<subscript>11</subscript></entry> | |
| 3105 | + <entry>u<subscript>10</subscript></entry> | |
| 3106 | + <entry>u<subscript>9</subscript></entry> | |
| 3107 | + <entry>u<subscript>8</subscript></entry> | |
| 3108 | + <entry>u<subscript>7</subscript></entry> | |
| 3109 | + <entry>u<subscript>6</subscript></entry> | |
| 3110 | + <entry>u<subscript>5</subscript></entry> | |
| 3111 | + <entry>u<subscript>4</subscript></entry> | |
| 3112 | + <entry>u<subscript>3</subscript></entry> | |
| 3113 | + <entry>u<subscript>2</subscript></entry> | |
| 3114 | + <entry>u<subscript>1</subscript></entry> | |
| 3115 | + <entry>u<subscript>0</subscript></entry> | |
| 3116 | + <entry>y<subscript>11</subscript></entry> | |
| 3117 | + <entry>y<subscript>10</subscript></entry> | |
| 3118 | + <entry>y<subscript>9</subscript></entry> | |
| 3119 | + <entry>y<subscript>8</subscript></entry> | |
| 3120 | + <entry>y<subscript>7</subscript></entry> | |
| 3121 | + <entry>y<subscript>6</subscript></entry> | |
| 3122 | + <entry>y<subscript>5</subscript></entry> | |
| 3123 | + <entry>y<subscript>4</subscript></entry> | |
| 3124 | + <entry>y<subscript>3</subscript></entry> | |
| 3125 | + <entry>y<subscript>2</subscript></entry> | |
| 3126 | + <entry>y<subscript>1</subscript></entry> | |
| 3127 | + <entry>y<subscript>0</subscript></entry> | |
| 3128 | + </row> | |
| 3129 | + <row id="V4L2-MBUS-FMT-YUYV12-1X24"> | |
| 3130 | + <entry>V4L2_MBUS_FMT_YUYV12_1X24</entry> | |
| 3131 | + <entry>0x2022</entry> | |
| 3132 | + <entry></entry> | |
| 3133 | + &dash-ent-8; | |
| 3134 | + <entry>y<subscript>11</subscript></entry> | |
| 3135 | + <entry>y<subscript>10</subscript></entry> | |
| 3136 | + <entry>y<subscript>9</subscript></entry> | |
| 3137 | + <entry>y<subscript>8</subscript></entry> | |
| 3138 | + <entry>y<subscript>7</subscript></entry> | |
| 3139 | + <entry>y<subscript>6</subscript></entry> | |
| 3140 | + <entry>y<subscript>5</subscript></entry> | |
| 3141 | + <entry>y<subscript>4</subscript></entry> | |
| 3142 | + <entry>y<subscript>3</subscript></entry> | |
| 3143 | + <entry>y<subscript>2</subscript></entry> | |
| 3144 | + <entry>y<subscript>1</subscript></entry> | |
| 3145 | + <entry>y<subscript>0</subscript></entry> | |
| 3146 | + <entry>u<subscript>11</subscript></entry> | |
| 3147 | + <entry>u<subscript>10</subscript></entry> | |
| 3148 | + <entry>u<subscript>9</subscript></entry> | |
| 3149 | + <entry>u<subscript>8</subscript></entry> | |
| 3150 | + <entry>u<subscript>7</subscript></entry> | |
| 3151 | + <entry>u<subscript>6</subscript></entry> | |
| 3152 | + <entry>u<subscript>5</subscript></entry> | |
| 3153 | + <entry>u<subscript>4</subscript></entry> | |
| 3154 | + <entry>u<subscript>3</subscript></entry> | |
| 3155 | + <entry>u<subscript>2</subscript></entry> | |
| 3156 | + <entry>u<subscript>1</subscript></entry> | |
| 3157 | + <entry>u<subscript>0</subscript></entry> | |
| 3158 | + </row> | |
| 3159 | + <row> | |
| 3160 | + <entry></entry> | |
| 3161 | + <entry></entry> | |
| 3162 | + <entry></entry> | |
| 3163 | + &dash-ent-8; | |
| 3164 | + <entry>y<subscript>11</subscript></entry> | |
| 3165 | + <entry>y<subscript>10</subscript></entry> | |
| 3166 | + <entry>y<subscript>9</subscript></entry> | |
| 3167 | + <entry>y<subscript>8</subscript></entry> | |
| 3168 | + <entry>y<subscript>7</subscript></entry> | |
| 3169 | + <entry>y<subscript>6</subscript></entry> | |
| 3170 | + <entry>y<subscript>5</subscript></entry> | |
| 3171 | + <entry>y<subscript>4</subscript></entry> | |
| 3172 | + <entry>y<subscript>3</subscript></entry> | |
| 3173 | + <entry>y<subscript>2</subscript></entry> | |
| 3174 | + <entry>y<subscript>1</subscript></entry> | |
| 3175 | + <entry>y<subscript>0</subscript></entry> | |
| 3176 | + <entry>v<subscript>11</subscript></entry> | |
| 3177 | + <entry>v<subscript>10</subscript></entry> | |
| 3178 | + <entry>v<subscript>9</subscript></entry> | |
| 3179 | + <entry>v<subscript>8</subscript></entry> | |
| 3180 | + <entry>v<subscript>7</subscript></entry> | |
| 3181 | + <entry>v<subscript>6</subscript></entry> | |
| 3182 | + <entry>v<subscript>5</subscript></entry> | |
| 3183 | + <entry>v<subscript>4</subscript></entry> | |
| 3184 | + <entry>v<subscript>3</subscript></entry> | |
| 3185 | + <entry>v<subscript>2</subscript></entry> | |
| 3186 | + <entry>v<subscript>1</subscript></entry> | |
| 3187 | + <entry>v<subscript>0</subscript></entry> | |
| 3188 | + </row> | |
| 3189 | + <row id="V4L2-MBUS-FMT-YVYU12-1X24"> | |
| 3190 | + <entry>V4L2_MBUS_FMT_YVYU12_1X24</entry> | |
| 3191 | + <entry>0x2023</entry> | |
| 3192 | + <entry></entry> | |
| 3193 | + &dash-ent-8; | |
| 3194 | + <entry>y<subscript>11</subscript></entry> | |
| 3195 | + <entry>y<subscript>10</subscript></entry> | |
| 3196 | + <entry>y<subscript>9</subscript></entry> | |
| 3197 | + <entry>y<subscript>8</subscript></entry> | |
| 3198 | + <entry>y<subscript>7</subscript></entry> | |
| 3199 | + <entry>y<subscript>6</subscript></entry> | |
| 3200 | + <entry>y<subscript>5</subscript></entry> | |
| 3201 | + <entry>y<subscript>4</subscript></entry> | |
| 3202 | + <entry>y<subscript>3</subscript></entry> | |
| 3203 | + <entry>y<subscript>2</subscript></entry> | |
| 3204 | + <entry>y<subscript>1</subscript></entry> | |
| 3205 | + <entry>y<subscript>0</subscript></entry> | |
| 3206 | + <entry>v<subscript>11</subscript></entry> | |
| 3207 | + <entry>v<subscript>10</subscript></entry> | |
| 3208 | + <entry>v<subscript>9</subscript></entry> | |
| 3209 | + <entry>v<subscript>8</subscript></entry> | |
| 3210 | + <entry>v<subscript>7</subscript></entry> | |
| 3211 | + <entry>v<subscript>6</subscript></entry> | |
| 3212 | + <entry>v<subscript>5</subscript></entry> | |
| 3213 | + <entry>v<subscript>4</subscript></entry> | |
| 3214 | + <entry>v<subscript>3</subscript></entry> | |
| 3215 | + <entry>v<subscript>2</subscript></entry> | |
| 3216 | + <entry>v<subscript>1</subscript></entry> | |
| 3217 | + <entry>v<subscript>0</subscript></entry> | |
| 3218 | + </row> | |
| 3219 | + <row> | |
| 3220 | + <entry></entry> | |
| 3221 | + <entry></entry> | |
| 3222 | + <entry></entry> | |
| 3223 | + &dash-ent-8; | |
| 3224 | + <entry>y<subscript>11</subscript></entry> | |
| 3225 | + <entry>y<subscript>10</subscript></entry> | |
| 3226 | + <entry>y<subscript>9</subscript></entry> | |
| 3227 | + <entry>y<subscript>8</subscript></entry> | |
| 3228 | + <entry>y<subscript>7</subscript></entry> | |
| 3229 | + <entry>y<subscript>6</subscript></entry> | |
| 3230 | + <entry>y<subscript>5</subscript></entry> | |
| 3231 | + <entry>y<subscript>4</subscript></entry> | |
| 3232 | + <entry>y<subscript>3</subscript></entry> | |
| 3233 | + <entry>y<subscript>2</subscript></entry> | |
| 3234 | + <entry>y<subscript>1</subscript></entry> | |
| 3235 | + <entry>y<subscript>0</subscript></entry> | |
| 3236 | + <entry>u<subscript>11</subscript></entry> | |
| 3237 | + <entry>u<subscript>10</subscript></entry> | |
| 3238 | + <entry>u<subscript>9</subscript></entry> | |
| 3239 | + <entry>u<subscript>8</subscript></entry> | |
| 3240 | + <entry>u<subscript>7</subscript></entry> | |
| 3241 | + <entry>u<subscript>6</subscript></entry> | |
| 3242 | + <entry>u<subscript>5</subscript></entry> | |
| 3243 | + <entry>u<subscript>4</subscript></entry> | |
| 3244 | + <entry>u<subscript>3</subscript></entry> | |
| 3245 | + <entry>u<subscript>2</subscript></entry> | |
| 3246 | + <entry>u<subscript>1</subscript></entry> | |
| 3247 | + <entry>u<subscript>0</subscript></entry> | |
| 3248 | + </row> | |
| 2489 | 3249 | </tbody> |
| 2490 | 3250 | </tgroup> |
| 2491 | 3251 | </table> |
| @@ -242,6 +242,22 @@ · 241 unmodified lines | ||
| 242 | 242 | </tgroup> |
| 243 | 243 | </table> |
| 244 | 244 | |
| 245 | + <table frame="none" pgwide="1" id="v4l2-event-src-change"> | |
| 246 | + <title>struct <structname>v4l2_event_src_change</structname></title> | |
| 247 | + <tgroup cols="3"> | |
| 248 | + &cs-str; | |
| 249 | + <tbody valign="top"> | |
| 250 | + <row> | |
| 251 | + <entry>__u32</entry> | |
| 252 | + <entry><structfield>changes</structfield></entry> | |
| 253 | + <entry> | |
| 254 | + A bitmask that tells what has changed. See <xref linkend="src-changes-flags" />. | |
| 255 | + </entry> | |
| 256 | + </row> | |
| 257 | + </tbody> | |
| 258 | + </tgroup> | |
| 259 | + </table> | |
| 260 | + | |
| 245 | 261 | <table pgwide="1" frame="none" id="changes-flags"> |
| 246 | 262 | <title>Changes</title> |
| 247 | 263 | <tgroup cols="3"> |
| @@ -270,6 +286,23 @@ · 22 unmodified lines | ||
| 270 | 286 | </tbody> |
| 271 | 287 | </tgroup> |
| 272 | 288 | </table> |
| 289 | + | |
| 290 | + <table pgwide="1" frame="none" id="src-changes-flags"> | |
| 291 | + <title>Source Changes</title> | |
| 292 | + <tgroup cols="3"> | |
| 293 | + &cs-def; | |
| 294 | + <tbody valign="top"> | |
| 295 | + <row> | |
| 296 | + <entry><constant>V4L2_EVENT_SRC_CH_RESOLUTION</constant></entry> | |
| 297 | + <entry>0x0001</entry> | |
| 298 | + <entry>This event gets triggered when a resolution change is | |
| 299 | + detected at an input. This can come from an input connector or | |
| 300 | + from a video decoder. | |
| 301 | + </entry> | |
| 302 | + </row> | |
| 303 | + </tbody> | |
| 304 | + </tgroup> | |
| 305 | + </table> | |
| 273 | 306 | </refsect1> |
| 274 | 307 | <refsect1> |
| 275 | 308 | &return-value; |
| @@ -1,11 +1,12 @@ | ||
| 1 | 1 | <refentry id="vidioc-dv-timings-cap"> |
| 2 | 2 | <refmeta> |
| 3 | − <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP</refentrytitle> | |
| 3 | + <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle> | |
| 4 | 4 | &manvol; |
| 5 | 5 | </refmeta> |
| 6 | 6 | |
| 7 | 7 | <refnamediv> |
| 8 | 8 | <refname>VIDIOC_DV_TIMINGS_CAP</refname> |
| 9 | + <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname> | |
| 9 | 10 | <refpurpose>The capabilities of the Digital Video receiver/transmitter</refpurpose> |
| 10 | 11 | </refnamediv> |
| 11 | 12 | |
| @@ -33,7 +34,7 @@ · 21 unmodified lines | ||
| 33 | 34 | <varlistentry> |
| 34 | 35 | <term><parameter>request</parameter></term> |
| 35 | 36 | <listitem> |
| 36 | − <para>VIDIOC_DV_TIMINGS_CAP</para> | |
| 37 | + <para>VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para> | |
| 37 | 38 | </listitem> |
| 38 | 39 | </varlistentry> |
| 39 | 40 | <varlistentry> |
| @@ -54,10 +55,19 @@ · 14 unmodified lines | ||
| 54 | 55 | interface and may change in the future.</para> |
| 55 | 56 | </note> |
| 56 | 57 | |
| 57 | − <para>To query the capabilities of the DV receiver/transmitter applications can call | |
| 58 | −this ioctl and the driver will fill in the structure. Note that drivers may return | |
| 58 | + <para>To query the capabilities of the DV receiver/transmitter applications | |
| 59 | +can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node | |
| 60 | +and the driver will fill in the structure. Note that drivers may return | |
| 59 | 61 | different values after switching the video input or output.</para> |
| 60 | 62 | |
| 63 | + <para>When implemented by the driver DV capabilities of subdevices can be | |
| 64 | +queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl | |
| 65 | +directly on a subdevice node. The capabilities are specific to inputs (for DV | |
| 66 | +receivers) or outputs (for DV transmitters), applications must specify the | |
| 67 | +desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield> | |
| 68 | +field. Attempts to query capabilities on a pad that doesn't support them will | |
| 69 | +return an &EINVAL;.</para> | |
| 70 | + | |
| 61 | 71 | <table pgwide="1" frame="none" id="v4l2-bt-timings-cap"> |
| 62 | 72 | <title>struct <structname>v4l2_bt_timings_cap</structname></title> |
| 63 | 73 | <tgroup cols="3"> |
| @@ -127,7 +137,14 @@ different values after switching the video input or output.</para> · 63 unmodified lines | ||
| 127 | 137 | </row> |
| 128 | 138 | <row> |
| 129 | 139 | <entry>__u32</entry> |
| 130 | − <entry><structfield>reserved</structfield>[3]</entry> | |
| 140 | + <entry><structfield>pad</structfield></entry> | |
| 141 | + <entry>Pad number as reported by the media controller API. This field | |
| 142 | + is only used when operating on a subdevice node. When operating on a | |
| 143 | + video node applications must set this field to zero.</entry> | |
| 144 | + </row> | |
| 145 | + <row> | |
| 146 | + <entry>__u32</entry> | |
| 147 | + <entry><structfield>reserved</structfield>[2]</entry> | |
| 131 | 148 | <entry>Reserved for future extensions. Drivers must set the array to zero.</entry> |
| 132 | 149 | </row> |
| 133 | 150 | <row> |
| @@ -1,11 +1,12 @@ | ||
| 1 | 1 | <refentry id="vidioc-enum-dv-timings"> |
| 2 | 2 | <refmeta> |
| 3 | − <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS</refentrytitle> | |
| 3 | + <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle> | |
| 4 | 4 | &manvol; |
| 5 | 5 | </refmeta> |
| 6 | 6 | |
| 7 | 7 | <refnamediv> |
| 8 | 8 | <refname>VIDIOC_ENUM_DV_TIMINGS</refname> |
| 9 | + <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname> | |
| 9 | 10 | <refpurpose>Enumerate supported Digital Video timings</refpurpose> |
| 10 | 11 | </refnamediv> |
| 11 | 12 | |
| @@ -33,7 +34,7 @@ · 21 unmodified lines | ||
| 33 | 34 | <varlistentry> |
| 34 | 35 | <term><parameter>request</parameter></term> |
| 35 | 36 | <listitem> |
| 36 | − <para>VIDIOC_ENUM_DV_TIMINGS</para> | |
| 37 | + <para>VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para> | |
| 37 | 38 | </listitem> |
| 38 | 39 | </varlistentry> |
| 39 | 40 | <varlistentry> |
| @@ -61,14 +62,21 @@ standards or even custom timings that are not in this list.</para> · 21 unmodified lines | ||
| 61 | 62 | |
| 62 | 63 | <para>To query the available timings, applications initialize the |
| 63 | 64 | <structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings; |
| 64 | −and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl with a pointer to this | |
| 65 | −structure. Drivers fill the rest of the structure or return an | |
| 65 | +and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a | |
| 66 | +pointer to this structure. Drivers fill the rest of the structure or return an | |
| 66 | 67 | &EINVAL; when the index is out of bounds. To enumerate all supported DV timings, |
| 67 | 68 | applications shall begin at index zero, incrementing by one until the |
| 68 | 69 | driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a |
| 69 | 70 | different set of DV timings after switching the video input or |
| 70 | 71 | output.</para> |
| 71 | 72 | |
| 73 | + <para>When implemented by the driver DV timings of subdevices can be queried | |
| 74 | +by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly | |
| 75 | +on a subdevice node. The DV timings are specific to inputs (for DV receivers) or | |
| 76 | +outputs (for DV transmitters), applications must specify the desired pad number | |
| 77 | +in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to | |
| 78 | +enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para> | |
| 79 | + | |
| 72 | 80 | <table pgwide="1" frame="none" id="v4l2-enum-dv-timings"> |
| 73 | 81 | <title>struct <structname>v4l2_enum_dv_timings</structname></title> |
| 74 | 82 | <tgroup cols="3"> |
| @@ -82,8 +90,16 @@ application.</entry> · 7 unmodified lines | ||
| 82 | 90 | </row> |
| 83 | 91 | <row> |
| 84 | 92 | <entry>__u32</entry> |
| 85 | − <entry><structfield>reserved</structfield>[3]</entry> | |
| 86 | − <entry>Reserved for future extensions. Drivers must set the array to zero.</entry> | |
| 93 | + <entry><structfield>pad</structfield></entry> | |
| 94 | + <entry>Pad number as reported by the media controller API. This field | |
| 95 | + is only used when operating on a subdevice node. When operating on a | |
| 96 | + video node applications must set this field to zero.</entry> | |
| 97 | + </row> | |
| 98 | + <row> | |
| 99 | + <entry>__u32</entry> | |
| 100 | + <entry><structfield>reserved</structfield>[2]</entry> | |
| 101 | + <entry>Reserved for future extensions. Drivers and applications must | |
| 102 | + set the array to zero.</entry> | |
| 87 | 103 | </row> |
| 88 | 104 | <row> |
| 89 | 105 | <entry>&v4l2-dv-timings;</entry> |
| @@ -103,7 +119,7 @@ application.</entry> · 13 unmodified lines | ||
| 103 | 119 | <term><errorcode>EINVAL</errorcode></term> |
| 104 | 120 | <listitem> |
| 105 | 121 | <para>The &v4l2-enum-dv-timings; <structfield>index</structfield> |
| 106 | −is out of bounds.</para> | |
| 122 | +is out of bounds or the <structfield>pad</structfield> number is invalid.</para> | |
| 107 | 123 | </listitem> |
| 108 | 124 | </varlistentry> |
| 109 | 125 | <varlistentry> |
| @@ -154,6 +154,26 @@ · 153 unmodified lines | ||
| 154 | 154 | frame interval in between them.</para> |
| 155 | 155 | </entry> |
| 156 | 156 | </row> |
| 157 | + <row> | |
| 158 | + <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry> | |
| 159 | + <entry>5</entry> | |
| 160 | + <entry> | |
| 161 | + <para>This event is triggered when a source parameter change is | |
| 162 | + detected during runtime by the video device. It can be a | |
| 163 | + runtime resolution change triggered by a video decoder or the | |
| 164 | + format change happening on an input connector. | |
| 165 | + This event requires that the <structfield>id</structfield> | |
| 166 | + matches the input index (when used with a video device node) | |
| 167 | + or the pad index (when used with a subdevice node) from which | |
| 168 | + you want to receive events.</para> | |
| 169 | + | |
| 170 | + <para>This event has a &v4l2-event-src-change; associated | |
| 171 | + with it. The <structfield>changes</structfield> bitfield denotes | |
| 172 | + what has changed for the subscribed pad. If multiple events | |
| 173 | + occurred before application could dequeue them, then the changes | |
| 174 | + will have the ORed value of all the events generated.</para> | |
| 175 | + </entry> | |
| 176 | + </row> | |
| 157 | 177 | <row> |
| 158 | 178 | <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry> |
| 159 | 179 | <entry>0x08000000</entry> |
| @@ -10,7 +10,8 @@ Required properties: · 9 unmodified lines | ||
| 10 | 10 | - compatible : value should be either one among the following |
| 11 | 11 | (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs |
| 12 | 12 | (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs |
| 13 | − (b) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC | |
| 13 | + (c) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC | |
| 14 | + (d) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC | |
| 14 | 15 | |
| 15 | 16 | - reg : Physical base address of the IP registers and length of memory |
| 16 | 17 | mapped region. |
| @@ -164,3 +164,4 @@ · 163 unmodified lines | ||
| 164 | 164 | 163 -> Bt848 Capture 14MHz |
| 165 | 165 | 164 -> CyberVision CV06 (SV) |
| 166 | 166 | 165 -> Kworld V-Stream Xpert TV PVR878 |
| 167 | +166 -> PCI-8604PW | |
| @@ -92,3 +92,4 @@ · 91 unmodified lines | ||
| 92 | 92 | 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765) [1ae7:9003,1ae7:9004] |
| 93 | 93 | 92 -> PCTV DVB-S2 Stick (461e) (em28178) |
| 94 | 94 | 93 -> KWorld USB ATSC TV Stick UB435-Q V3 (em2874) [1b80:e34c] |
| 95 | + 94 -> PCTV tripleStick (292e) (em28178) | |
| @@ -140,39 +140,9 @@ You can either grep through the kernel log to find relevant information, i.e. · 139 unmodified lines | ||
| 140 | 140 | or retrieve the information from /dev/media? with help of the media-ctl tool: |
| 141 | 141 | # media-ctl -p |
| 142 | 142 | |
| 143 | −6. Platform support | |
| 144 | −=================== | |
| 145 | − | |
| 146 | −The machine code (arch/arm/plat-samsung and arch/arm/mach-*) must select | |
| 147 | −following options: | |
| 148 | − | |
| 149 | −CONFIG_S5P_DEV_FIMC0 mandatory | |
| 150 | −CONFIG_S5P_DEV_FIMC1 \ | |
| 151 | −CONFIG_S5P_DEV_FIMC2 | optional | |
| 152 | −CONFIG_S5P_DEV_FIMC3 | | |
| 153 | −CONFIG_S5P_SETUP_FIMC / | |
| 154 | −CONFIG_S5P_DEV_CSIS0 \ optional for MIPI-CSI interface | |
| 155 | −CONFIG_S5P_DEV_CSIS1 / | |
| 156 | − | |
| 157 | −Except that, relevant s5p_device_fimc? should be registered in the machine code | |
| 158 | −in addition to a "s5p-fimc-md" platform device to which the media device driver | |
| 159 | −is bound. The "s5p-fimc-md" device instance is required even if only mem-to-mem | |
| 160 | −operation is used. | |
| 161 | − | |
| 162 | −The description of sensor(s) attached to FIMC/MIPI-CSIS camera inputs should be | |
| 163 | −passed as the "s5p-fimc-md" device platform_data. The platform data structure | |
| 164 | −is defined in file include/media/s5p_fimc.h. | |
| 165 | − | |
| 166 | 143 | 7. Build |
| 167 | 144 | ======== |
| 168 | 145 | |
| 169 | −This driver depends on following config options: | |
| 170 | −PLAT_S5P, | |
| 171 | −PM_RUNTIME, | |
| 172 | −I2C, | |
| 173 | −REGULATOR, | |
| 174 | −VIDEO_V4L2_SUBDEV_API, | |
| 175 | − | |
| 176 | 146 | If the driver is built as a loadable kernel module (CONFIG_VIDEO_SAMSUNG_S5P_FIMC=m) |
| 177 | 147 | two modules are created (in addition to the core v4l2 modules): s5p-fimc.ko and |
| 178 | 148 | optional s5p-csis.ko (MIPI-CSI receiver subdev). |
| @@ -77,7 +77,8 @@ struct skeleton { · 76 unmodified lines | ||
| 77 | 77 | |
| 78 | 78 | spinlock_t qlock; |
| 79 | 79 | struct list_head buf_list; |
| 80 | − unsigned int sequence; | |
| 80 | + unsigned field; | |
| 81 | + unsigned sequence; | |
| 81 | 82 | }; |
| 82 | 83 | |
| 83 | 84 | struct skel_buffer { |
| @@ -124,7 +125,7 @@ static const struct v4l2_dv_timings_cap skel_timings_cap = { · 40 unmodified lines | ||
| 124 | 125 | * Interrupt handler: typically interrupts happen after a new frame has been |
| 125 | 126 | * captured. It is the job of the handler to remove the new frame from the |
| 126 | 127 | * internal list and give it back to the vb2 framework, updating the sequence |
| 127 | − * counter and timestamp at the same time. | |
| 128 | + * counter, field and timestamp at the same time. | |
| 128 | 129 | */ |
| 129 | 130 | static irqreturn_t skeleton_irq(int irq, void *dev_id) |
| 130 | 131 | { |
| @@ -139,8 +140,15 @@ static irqreturn_t skeleton_irq(int irq, void *dev_id) · 8 unmodified lines | ||
| 139 | 140 | spin_lock(&skel->qlock); |
| 140 | 141 | list_del(&new_buf->list); |
| 141 | 142 | spin_unlock(&skel->qlock); |
| 142 | − new_buf->vb.v4l2_buf.sequence = skel->sequence++; | |
| 143 | 143 | v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp); |
| 144 | + new_buf->vb.v4l2_buf.sequence = skel->sequence++; | |
| 145 | + new_buf->vb.v4l2_buf.field = skel->field; | |
| 146 | + if (skel->format.field == V4L2_FIELD_ALTERNATE) { | |
| 147 | + if (skel->field == V4L2_FIELD_BOTTOM) | |
| 148 | + skel->field = V4L2_FIELD_TOP; | |
| 149 | + else if (skel->field == V4L2_FIELD_TOP) | |
| 150 | + skel->field = V4L2_FIELD_BOTTOM; | |
| 151 | + } | |
| 144 | 152 | vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE); |
| 145 | 153 | } |
| 146 | 154 | #endif |
| @@ -160,6 +168,17 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 13 unmodified lines | ||
| 160 | 168 | { |
| 161 | 169 | struct skeleton *skel = vb2_get_drv_priv(vq); |
| 162 | 170 | |
| 171 | + skel->field = skel->format.field; | |
| 172 | + if (skel->field == V4L2_FIELD_ALTERNATE) { | |
| 173 | + /* | |
| 174 | + * You cannot use read() with FIELD_ALTERNATE since the field | |
| 175 | + * information (TOP/BOTTOM) cannot be passed back to the user. | |
| 176 | + */ | |
| 177 | + if (vb2_fileio_is_active(vq)) | |
| 178 | + return -EINVAL; | |
| 179 | + skel->field = V4L2_FIELD_TOP; | |
| 180 | + } | |
| 181 | + | |
| 163 | 182 | if (vq->num_buffers + *nbuffers < 3) |
| 164 | 183 | *nbuffers = 3 - vq->num_buffers; |
| 165 | 184 | |
| @@ -173,10 +192,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 7 unmodified lines | ||
| 173 | 192 | |
| 174 | 193 | /* |
| 175 | 194 | * Prepare the buffer for queueing to the DMA engine: check and set the |
| 176 | − * payload size and fill in the field. Note: if the format's field is | |
| 177 | − * V4L2_FIELD_ALTERNATE, then vb->v4l2_buf.field should be set in the | |
| 178 | − * interrupt handler since that's usually where you know if the TOP or | |
| 179 | − * BOTTOM field has been captured. | |
| 195 | + * payload size. | |
| 180 | 196 | */ |
| 181 | 197 | static int buffer_prepare(struct vb2_buffer *vb) |
| 182 | 198 | { |
| @@ -190,7 +206,6 @@ static int buffer_prepare(struct vb2_buffer *vb) · 7 unmodified lines | ||
| 190 | 206 | } |
| 191 | 207 | |
| 192 | 208 | vb2_set_plane_payload(vb, 0, size); |
| 193 | − vb->v4l2_buf.field = skel->format.field; | |
| 194 | 209 | return 0; |
| 195 | 210 | } |
| 196 | 211 | |
| @@ -254,7 +269,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 57 unmodified lines | ||
| 254 | 269 | * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued |
| 255 | 270 | * and passed on to the vb2 framework marked as STATE_ERROR. |
| 256 | 271 | */ |
| 257 | −static int stop_streaming(struct vb2_queue *vq) | |
| 272 | +static void stop_streaming(struct vb2_queue *vq) | |
| 258 | 273 | { |
| 259 | 274 | struct skeleton *skel = vb2_get_drv_priv(vq); |
| 260 | 275 | |
| @@ -262,7 +277,6 @@ static int stop_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 262 | 277 | |
| 263 | 278 | /* Release all active buffers */ |
| 264 | 279 | return_all_buffers(skel, VB2_BUF_STATE_ERROR); |
| 265 | − return 0; | |
| 266 | 280 | } |
| 267 | 281 | |
| 268 | 282 | /* |
| @@ -319,10 +333,12 @@ static void skeleton_fill_pix_format(struct skeleton *skel, · 50 unmodified lines | ||
| 319 | 333 | /* HDMI input */ |
| 320 | 334 | pix->width = skel->timings.bt.width; |
| 321 | 335 | pix->height = skel->timings.bt.height; |
| 322 | − if (skel->timings.bt.interlaced) | |
| 323 | − pix->field = V4L2_FIELD_INTERLACED; | |
| 324 | − else | |
| 336 | + if (skel->timings.bt.interlaced) { | |
| 337 | + pix->field = V4L2_FIELD_ALTERNATE; | |
| 338 | + pix->height /= 2; | |
| 339 | + } else { | |
| 325 | 340 | pix->field = V4L2_FIELD_NONE; |
| 341 | + } | |
| 326 | 342 | pix->colorspace = V4L2_COLORSPACE_REC709; |
| 327 | 343 | } |
| 328 | 344 | |
| @@ -7668,7 +7668,6 @@ L: linux-media@vger.kernel.org · 7667 unmodified lines | ||
| 7668 | 7668 | Q: https://patchwork.linuxtv.org/project/linux-media/list/ |
| 7669 | 7669 | S: Supported |
| 7670 | 7670 | F: drivers/media/platform/exynos4-is/ |
| 7671 | −F: include/media/s5p_fimc.h | |
| 7672 | 7671 | |
| 7673 | 7672 | SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER |
| 7674 | 7673 | M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com> |
| @@ -7971,6 +7970,26 @@ M: Robin Holt <robinmholt@gmail.com> · 296 unmodified lines | ||
| 7971 | 7970 | S: Maintained |
| 7972 | 7971 | F: drivers/misc/sgi-xp/ |
| 7973 | 7972 | |
| 7973 | +SI2157 MEDIA DRIVER | |
| 7974 | +M: Antti Palosaari <crope@iki.fi> | |
| 7975 | +L: linux-media@vger.kernel.org | |
| 7976 | +W: http://linuxtv.org/ | |
| 7977 | +W: http://palosaari.fi/linux/ | |
| 7978 | +Q: http://patchwork.linuxtv.org/project/linux-media/list/ | |
| 7979 | +T: git git://linuxtv.org/anttip/media_tree.git | |
| 7980 | +S: Maintained | |
| 7981 | +F: drivers/media/tuners/si2157* | |
| 7982 | + | |
| 7983 | +SI2168 MEDIA DRIVER | |
| 7984 | +M: Antti Palosaari <crope@iki.fi> | |
| 7985 | +L: linux-media@vger.kernel.org | |
| 7986 | +W: http://linuxtv.org/ | |
| 7987 | +W: http://palosaari.fi/linux/ | |
| 7988 | +Q: http://patchwork.linuxtv.org/project/linux-media/list/ | |
| 7989 | +T: git git://linuxtv.org/anttip/media_tree.git | |
| 7990 | +S: Maintained | |
| 7991 | +F: drivers/media/dvb-frontends/si2168* | |
| 7992 | + | |
| 7974 | 7993 | SI470X FM RADIO RECEIVER I2C DRIVER |
| 7975 | 7994 | M: Hans Verkuil <hverkuil@xs4all.nl> |
| 7976 | 7995 | L: linux-media@vger.kernel.org |
| @@ -49,11 +49,6 @@ · 48 unmodified lines | ||
| 49 | 49 | #include <plat/clock.h> |
| 50 | 50 | #include <plat/samsung-time.h> |
| 51 | 51 | #include <plat/mfc.h> |
| 52 | −#include <plat/camport.h> | |
| 53 | − | |
| 54 | −#include <media/v4l2-mediabus.h> | |
| 55 | −#include <media/s5p_fimc.h> | |
| 56 | −#include <media/noon010pc30.h> | |
| 57 | 52 | |
| 58 | 53 | #include "common.h" |
| 59 | 54 | |
| @@ -285,14 +280,6 @@ static void __init goni_tsp_init(void) · 225 unmodified lines | ||
| 285 | 280 | /* USB OTG */ |
| 286 | 281 | static struct s3c_hsotg_plat goni_hsotg_pdata; |
| 287 | 282 | |
| 288 | −static void goni_camera_init(void) | |
| 289 | −{ | |
| 290 | − s5pv210_fimc_setup_gpio(S5P_CAMPORT_A); | |
| 291 | − | |
| 292 | − /* Set max driver strength on CAM_A_CLKOUT pin. */ | |
| 293 | − s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4); | |
| 294 | −} | |
| 295 | − | |
| 296 | 283 | /* MAX8998 regulators */ |
| 297 | 284 | #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) |
| 298 | 285 | |
| @@ -825,34 +812,6 @@ static void goni_setup_sdhci(void) · 526 unmodified lines | ||
| 825 | 812 | s3c_sdhci2_set_platdata(&goni_hsmmc2_data); |
| 826 | 813 | }; |
| 827 | 814 | |
| 828 | −static struct noon010pc30_platform_data noon010pc30_pldata = { | |
| 829 | − .clk_rate = 16000000UL, | |
| 830 | − .gpio_nreset = S5PV210_GPB(2), /* CAM_CIF_NRST */ | |
| 831 | − .gpio_nstby = S5PV210_GPB(0), /* CAM_CIF_NSTBY */ | |
| 832 | −}; | |
| 833 | − | |
| 834 | −static struct i2c_board_info noon010pc30_board_info = { | |
| 835 | − I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1), | |
| 836 | − .platform_data = &noon010pc30_pldata, | |
| 837 | −}; | |
| 838 | − | |
| 839 | −static struct fimc_source_info goni_camera_sensors[] = { | |
| 840 | − { | |
| 841 | − .mux_id = 0, | |
| 842 | − .flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | | |
| 843 | − V4L2_MBUS_VSYNC_ACTIVE_LOW, | |
| 844 | − .fimc_bus_type = FIMC_BUS_TYPE_ITU_601, | |
| 845 | − .board_info = &noon010pc30_board_info, | |
| 846 | − .i2c_bus_num = 0, | |
| 847 | − .clk_frequency = 16000000UL, | |
| 848 | − }, | |
| 849 | −}; | |
| 850 | − | |
| 851 | −static struct s5p_platform_fimc goni_fimc_md_platdata __initdata = { | |
| 852 | − .source_info = goni_camera_sensors, | |
| 853 | − .num_clients = ARRAY_SIZE(goni_camera_sensors), | |
| 854 | −}; | |
| 855 | − | |
| 856 | 815 | /* Audio device */ |
| 857 | 816 | static struct platform_device goni_device_audio = { |
| 858 | 817 | .name = "smdk-audio", |
| @@ -874,10 +833,6 @@ static struct platform_device *goni_devices[] __initdata = { · 15 unmodified lines | ||
| 874 | 833 | &s5p_device_mixer, |
| 875 | 834 | &s5p_device_sdo, |
| 876 | 835 | &s3c_device_i2c0, |
| 877 | − &s5p_device_fimc0, | |
| 878 | − &s5p_device_fimc1, | |
| 879 | − &s5p_device_fimc2, | |
| 880 | − &s5p_device_fimc_md, | |
| 881 | 836 | &s3c_device_hsmmc0, |
| 882 | 837 | &s3c_device_hsmmc1, |
| 883 | 838 | &s3c_device_hsmmc2, |
| @@ -946,14 +901,8 @@ static void __init goni_machine_init(void) · 62 unmodified lines | ||
| 946 | 901 | /* FB */ |
| 947 | 902 | s3c_fb_set_platdata(&goni_lcd_pdata); |
| 948 | 903 | |
| 949 | − /* FIMC */ | |
| 950 | − s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata), | |
| 951 | − &s5p_device_fimc_md); | |
| 952 | − | |
| 953 | 904 | s3c_hsotg_set_platdata(&goni_hsotg_pdata); |
| 954 | 905 | |
| 955 | − goni_camera_init(); | |
| 956 | − | |
| 957 | 906 | /* SPI */ |
| 958 | 907 | spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); |
| 959 | 908 | |
| @@ -356,11 +356,13 @@ · 355 unmodified lines | ||
| 356 | 356 | #define USB_PID_ELGATO_EYETV_DTT_2 0x003f |
| 357 | 357 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 |
| 358 | 358 | #define USB_PID_ELGATO_EYETV_SAT 0x002a |
| 359 | +#define USB_PID_ELGATO_EYETV_SAT_V2 0x0025 | |
| 359 | 360 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 |
| 360 | 361 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 |
| 361 | 362 | #define USB_PID_FRIIO_WHITE 0x0001 |
| 362 | 363 | #define USB_PID_TVWAY_PLUS 0x0002 |
| 363 | 364 | #define USB_PID_SVEON_STV20 0xe39d |
| 365 | +#define USB_PID_SVEON_STV20_RTL2832U 0xd39d | |
| 364 | 366 | #define USB_PID_SVEON_STV22 0xe401 |
| 365 | 367 | #define USB_PID_SVEON_STV22_IT9137 0xe411 |
| 366 | 368 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 |
| @@ -375,4 +377,5 @@ · 8 unmodified lines | ||
| 375 | 377 | #define USB_PID_CTVDIGDUAL_V2 0xe410 |
| 376 | 378 | #define USB_PID_PCTV_2002E 0x025c |
| 377 | 379 | #define USB_PID_PCTV_2002E_SE 0x025d |
| 380 | +#define USB_PID_SVEON_STV27 0xd3af | |
| 378 | 381 | #endif |
| @@ -446,6 +446,13 @@ config DVB_RTL2832 · 445 unmodified lines | ||
| 446 | 446 | help |
| 447 | 447 | Say Y when you want to support this frontend. |
| 448 | 448 | |
| 449 | +config DVB_SI2168 | |
| 450 | + tristate "Silicon Labs Si2168" | |
| 451 | + depends on DVB_CORE && I2C && I2C_MUX | |
| 452 | + default m if !MEDIA_SUBDRV_AUTOSELECT | |
| 453 | + help | |
| 454 | + Say Y when you want to support this frontend. | |
| 455 | + | |
| 449 | 456 | comment "DVB-C (cable) frontends" |
| 450 | 457 | depends on DVB_CORE |
| 451 | 458 | |
| @@ -78,6 +78,7 @@ obj-$(CONFIG_DVB_AF9013) += af9013.o · 77 unmodified lines | ||
| 78 | 78 | obj-$(CONFIG_DVB_CX24116) += cx24116.o |
| 79 | 79 | obj-$(CONFIG_DVB_CX24117) += cx24117.o |
| 80 | 80 | obj-$(CONFIG_DVB_SI21XX) += si21xx.o |
| 81 | +obj-$(CONFIG_DVB_SI2168) += si2168.o | |
| 81 | 82 | obj-$(CONFIG_DVB_STV0288) += stv0288.o |
| 82 | 83 | obj-$(CONFIG_DVB_STB6000) += stb6000.o |
| 83 | 84 | obj-$(CONFIG_DVB_S921) += s921.o |
| @@ -0,0 +1,760 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2168 DVB-T/T2/C demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#include "si2168_priv.h" | |
| 18 | + | |
| 19 | +static const struct dvb_frontend_ops si2168_ops; | |
| 20 | + | |
| 21 | +/* execute firmware command */ | |
| 22 | +static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd) | |
| 23 | +{ | |
| 24 | + int ret; | |
| 25 | + unsigned long timeout; | |
| 26 | + | |
| 27 | + mutex_lock(&s->i2c_mutex); | |
| 28 | + | |
| 29 | + if (cmd->wlen) { | |
| 30 | + /* write cmd and args for firmware */ | |
| 31 | + ret = i2c_master_send(s->client, cmd->args, cmd->wlen); | |
| 32 | + if (ret < 0) { | |
| 33 | + goto err_mutex_unlock; | |
| 34 | + } else if (ret != cmd->wlen) { | |
| 35 | + ret = -EREMOTEIO; | |
| 36 | + goto err_mutex_unlock; | |
| 37 | + } | |
| 38 | + } | |
| 39 | + | |
| 40 | + if (cmd->rlen) { | |
| 41 | + /* wait cmd execution terminate */ | |
| 42 | + #define TIMEOUT 50 | |
| 43 | + timeout = jiffies + msecs_to_jiffies(TIMEOUT); | |
| 44 | + while (!time_after(jiffies, timeout)) { | |
| 45 | + ret = i2c_master_recv(s->client, cmd->args, cmd->rlen); | |
| 46 | + if (ret < 0) { | |
| 47 | + goto err_mutex_unlock; | |
| 48 | + } else if (ret != cmd->rlen) { | |
| 49 | + ret = -EREMOTEIO; | |
| 50 | + goto err_mutex_unlock; | |
| 51 | + } | |
| 52 | + | |
| 53 | + /* firmware ready? */ | |
| 54 | + if ((cmd->args[0] >> 7) & 0x01) | |
| 55 | + break; | |
| 56 | + } | |
| 57 | + | |
| 58 | + dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", | |
| 59 | + __func__, | |
| 60 | + jiffies_to_msecs(jiffies) - | |
| 61 | + (jiffies_to_msecs(timeout) - TIMEOUT)); | |
| 62 | + | |
| 63 | + if (!(cmd->args[0] >> 7) & 0x01) { | |
| 64 | + ret = -ETIMEDOUT; | |
| 65 | + goto err_mutex_unlock; | |
| 66 | + } | |
| 67 | + } | |
| 68 | + | |
| 69 | + ret = 0; | |
| 70 | + | |
| 71 | +err_mutex_unlock: | |
| 72 | + mutex_unlock(&s->i2c_mutex); | |
| 73 | + if (ret) | |
| 74 | + goto err; | |
| 75 | + | |
| 76 | + return 0; | |
| 77 | +err: | |
| 78 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 79 | + return ret; | |
| 80 | +} | |
| 81 | + | |
| 82 | +static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status) | |
| 83 | +{ | |
| 84 | + struct si2168 *s = fe->demodulator_priv; | |
| 85 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 86 | + int ret; | |
| 87 | + struct si2168_cmd cmd; | |
| 88 | + | |
| 89 | + *status = 0; | |
| 90 | + | |
| 91 | + if (!s->active) { | |
| 92 | + ret = -EAGAIN; | |
| 93 | + goto err; | |
| 94 | + } | |
| 95 | + | |
| 96 | + switch (c->delivery_system) { | |
| 97 | + case SYS_DVBT: | |
| 98 | + cmd.args[0] = 0xa0; | |
| 99 | + cmd.args[1] = 0x01; | |
| 100 | + cmd.wlen = 2; | |
| 101 | + cmd.rlen = 13; | |
| 102 | + break; | |
| 103 | + case SYS_DVBC_ANNEX_A: | |
| 104 | + cmd.args[0] = 0x90; | |
| 105 | + cmd.args[1] = 0x01; | |
| 106 | + cmd.wlen = 2; | |
| 107 | + cmd.rlen = 9; | |
| 108 | + break; | |
| 109 | + case SYS_DVBT2: | |
| 110 | + cmd.args[0] = 0x50; | |
| 111 | + cmd.args[1] = 0x01; | |
| 112 | + cmd.wlen = 2; | |
| 113 | + cmd.rlen = 14; | |
| 114 | + break; | |
| 115 | + default: | |
| 116 | + ret = -EINVAL; | |
| 117 | + goto err; | |
| 118 | + } | |
| 119 | + | |
| 120 | + ret = si2168_cmd_execute(s, &cmd); | |
| 121 | + if (ret) | |
| 122 | + goto err; | |
| 123 | + | |
| 124 | + /* | |
| 125 | + * Possible values seen, in order from strong signal to weak: | |
| 126 | + * 16 0001 0110 full lock | |
| 127 | + * 1e 0001 1110 partial lock | |
| 128 | + * 1a 0001 1010 partial lock | |
| 129 | + * 18 0001 1000 no lock | |
| 130 | + * | |
| 131 | + * [b3:b1] lock bits | |
| 132 | + * [b4] statistics ready? Set in a few secs after lock is gained. | |
| 133 | + */ | |
| 134 | + | |
| 135 | + switch ((cmd.args[2] >> 1) & 0x03) { | |
| 136 | + case 0x01: | |
| 137 | + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | |
| 138 | + break; | |
| 139 | + case 0x03: | |
| 140 | + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | | |
| 141 | + FE_HAS_SYNC | FE_HAS_LOCK; | |
| 142 | + break; | |
| 143 | + } | |
| 144 | + | |
| 145 | + s->fe_status = *status; | |
| 146 | + | |
| 147 | + dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n", | |
| 148 | + __func__, *status, cmd.rlen, cmd.args); | |
| 149 | + | |
| 150 | + return 0; | |
| 151 | +err: | |
| 152 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 153 | + return ret; | |
| 154 | +} | |
| 155 | + | |
| 156 | +static int si2168_set_frontend(struct dvb_frontend *fe) | |
| 157 | +{ | |
| 158 | + struct si2168 *s = fe->demodulator_priv; | |
| 159 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 160 | + int ret; | |
| 161 | + struct si2168_cmd cmd; | |
| 162 | + u8 bandwidth, delivery_system; | |
| 163 | + | |
| 164 | + dev_dbg(&s->client->dev, | |
| 165 | + "%s: delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u\n", | |
| 166 | + __func__, c->delivery_system, c->modulation, | |
| 167 | + c->frequency, c->bandwidth_hz, c->symbol_rate, | |
| 168 | + c->inversion); | |
| 169 | + | |
| 170 | + if (!s->active) { | |
| 171 | + ret = -EAGAIN; | |
| 172 | + goto err; | |
| 173 | + } | |
| 174 | + | |
| 175 | + switch (c->delivery_system) { | |
| 176 | + case SYS_DVBT: | |
| 177 | + delivery_system = 0x20; | |
| 178 | + break; | |
| 179 | + case SYS_DVBC_ANNEX_A: | |
| 180 | + delivery_system = 0x30; | |
| 181 | + break; | |
| 182 | + case SYS_DVBT2: | |
| 183 | + delivery_system = 0x70; | |
| 184 | + break; | |
| 185 | + default: | |
| 186 | + ret = -EINVAL; | |
| 187 | + goto err; | |
| 188 | + } | |
| 189 | + | |
| 190 | + if (c->bandwidth_hz <= 5000000) | |
| 191 | + bandwidth = 0x05; | |
| 192 | + else if (c->bandwidth_hz <= 6000000) | |
| 193 | + bandwidth = 0x06; | |
| 194 | + else if (c->bandwidth_hz <= 7000000) | |
| 195 | + bandwidth = 0x07; | |
| 196 | + else if (c->bandwidth_hz <= 8000000) | |
| 197 | + bandwidth = 0x08; | |
| 198 | + else if (c->bandwidth_hz <= 9000000) | |
| 199 | + bandwidth = 0x09; | |
| 200 | + else if (c->bandwidth_hz <= 10000000) | |
| 201 | + bandwidth = 0x0a; | |
| 202 | + else | |
| 203 | + bandwidth = 0x0f; | |
| 204 | + | |
| 205 | + /* program tuner */ | |
| 206 | + if (fe->ops.tuner_ops.set_params) { | |
| 207 | + ret = fe->ops.tuner_ops.set_params(fe); | |
| 208 | + if (ret) | |
| 209 | + goto err; | |
| 210 | + } | |
| 211 | + | |
| 212 | + memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5); | |
| 213 | + cmd.wlen = 5; | |
| 214 | + cmd.rlen = 5; | |
| 215 | + ret = si2168_cmd_execute(s, &cmd); | |
| 216 | + if (ret) | |
| 217 | + goto err; | |
| 218 | + | |
| 219 | + /* that has no big effect */ | |
| 220 | + if (c->delivery_system == SYS_DVBT) | |
| 221 | + memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6); | |
| 222 | + else if (c->delivery_system == SYS_DVBC_ANNEX_A) | |
| 223 | + memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6); | |
| 224 | + else if (c->delivery_system == SYS_DVBT2) | |
| 225 | + memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6); | |
| 226 | + cmd.wlen = 6; | |
| 227 | + cmd.rlen = 3; | |
| 228 | + ret = si2168_cmd_execute(s, &cmd); | |
| 229 | + if (ret) | |
| 230 | + goto err; | |
| 231 | + | |
| 232 | + memcpy(cmd.args, "\x51\x03", 2); | |
| 233 | + cmd.wlen = 2; | |
| 234 | + cmd.rlen = 12; | |
| 235 | + ret = si2168_cmd_execute(s, &cmd); | |
| 236 | + if (ret) | |
| 237 | + goto err; | |
| 238 | + | |
| 239 | + memcpy(cmd.args, "\x12\x08\x04", 3); | |
| 240 | + cmd.wlen = 3; | |
| 241 | + cmd.rlen = 3; | |
| 242 | + ret = si2168_cmd_execute(s, &cmd); | |
| 243 | + if (ret) | |
| 244 | + goto err; | |
| 245 | + | |
| 246 | + memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6); | |
| 247 | + cmd.wlen = 6; | |
| 248 | + cmd.rlen = 1; | |
| 249 | + ret = si2168_cmd_execute(s, &cmd); | |
| 250 | + if (ret) | |
| 251 | + goto err; | |
| 252 | + | |
| 253 | + memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6); | |
| 254 | + cmd.wlen = 6; | |
| 255 | + cmd.rlen = 1; | |
| 256 | + ret = si2168_cmd_execute(s, &cmd); | |
| 257 | + if (ret) | |
| 258 | + goto err; | |
| 259 | + | |
| 260 | + memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6); | |
| 261 | + cmd.wlen = 6; | |
| 262 | + cmd.rlen = 1; | |
| 263 | + ret = si2168_cmd_execute(s, &cmd); | |
| 264 | + if (ret) | |
| 265 | + goto err; | |
| 266 | + | |
| 267 | + memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6); | |
| 268 | + cmd.wlen = 6; | |
| 269 | + cmd.rlen = 1; | |
| 270 | + ret = si2168_cmd_execute(s, &cmd); | |
| 271 | + if (ret) | |
| 272 | + goto err; | |
| 273 | + | |
| 274 | + memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6); | |
| 275 | + cmd.wlen = 6; | |
| 276 | + cmd.rlen = 1; | |
| 277 | + ret = si2168_cmd_execute(s, &cmd); | |
| 278 | + if (ret) | |
| 279 | + goto err; | |
| 280 | + | |
| 281 | + memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6); | |
| 282 | + cmd.wlen = 6; | |
| 283 | + cmd.rlen = 1; | |
| 284 | + ret = si2168_cmd_execute(s, &cmd); | |
| 285 | + if (ret) | |
| 286 | + goto err; | |
| 287 | + | |
| 288 | + memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6); | |
| 289 | + cmd.wlen = 6; | |
| 290 | + cmd.rlen = 1; | |
| 291 | + ret = si2168_cmd_execute(s, &cmd); | |
| 292 | + if (ret) | |
| 293 | + goto err; | |
| 294 | + | |
| 295 | + memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6); | |
| 296 | + cmd.args[4] = delivery_system | bandwidth; | |
| 297 | + cmd.wlen = 6; | |
| 298 | + cmd.rlen = 1; | |
| 299 | + ret = si2168_cmd_execute(s, &cmd); | |
| 300 | + if (ret) | |
| 301 | + goto err; | |
| 302 | + | |
| 303 | + memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6); | |
| 304 | + cmd.wlen = 6; | |
| 305 | + cmd.rlen = 1; | |
| 306 | + ret = si2168_cmd_execute(s, &cmd); | |
| 307 | + if (ret) | |
| 308 | + goto err; | |
| 309 | + | |
| 310 | + memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6); | |
| 311 | + cmd.wlen = 6; | |
| 312 | + cmd.rlen = 1; | |
| 313 | + ret = si2168_cmd_execute(s, &cmd); | |
| 314 | + if (ret) | |
| 315 | + goto err; | |
| 316 | + | |
| 317 | + memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); | |
| 318 | + cmd.wlen = 6; | |
| 319 | + cmd.rlen = 1; | |
| 320 | + ret = si2168_cmd_execute(s, &cmd); | |
| 321 | + if (ret) | |
| 322 | + goto err; | |
| 323 | + | |
| 324 | + memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6); | |
| 325 | + cmd.wlen = 6; | |
| 326 | + cmd.rlen = 1; | |
| 327 | + ret = si2168_cmd_execute(s, &cmd); | |
| 328 | + if (ret) | |
| 329 | + goto err; | |
| 330 | + | |
| 331 | + memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6); | |
| 332 | + cmd.wlen = 6; | |
| 333 | + cmd.rlen = 1; | |
| 334 | + ret = si2168_cmd_execute(s, &cmd); | |
| 335 | + if (ret) | |
| 336 | + goto err; | |
| 337 | + | |
| 338 | + memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6); | |
| 339 | + cmd.wlen = 6; | |
| 340 | + cmd.rlen = 1; | |
| 341 | + ret = si2168_cmd_execute(s, &cmd); | |
| 342 | + if (ret) | |
| 343 | + goto err; | |
| 344 | + | |
| 345 | + memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6); | |
| 346 | + cmd.wlen = 6; | |
| 347 | + cmd.rlen = 1; | |
| 348 | + ret = si2168_cmd_execute(s, &cmd); | |
| 349 | + if (ret) | |
| 350 | + goto err; | |
| 351 | + | |
| 352 | + memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6); | |
| 353 | + cmd.wlen = 6; | |
| 354 | + cmd.rlen = 1; | |
| 355 | + ret = si2168_cmd_execute(s, &cmd); | |
| 356 | + if (ret) | |
| 357 | + goto err; | |
| 358 | + | |
| 359 | + memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6); | |
| 360 | + cmd.wlen = 6; | |
| 361 | + cmd.rlen = 1; | |
| 362 | + ret = si2168_cmd_execute(s, &cmd); | |
| 363 | + if (ret) | |
| 364 | + goto err; | |
| 365 | + | |
| 366 | + memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6); | |
| 367 | + cmd.wlen = 6; | |
| 368 | + cmd.rlen = 1; | |
| 369 | + ret = si2168_cmd_execute(s, &cmd); | |
| 370 | + if (ret) | |
| 371 | + goto err; | |
| 372 | + | |
| 373 | + memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6); | |
| 374 | + cmd.wlen = 6; | |
| 375 | + cmd.rlen = 1; | |
| 376 | + ret = si2168_cmd_execute(s, &cmd); | |
| 377 | + if (ret) | |
| 378 | + goto err; | |
| 379 | + | |
| 380 | + memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6); | |
| 381 | + cmd.wlen = 6; | |
| 382 | + cmd.rlen = 1; | |
| 383 | + ret = si2168_cmd_execute(s, &cmd); | |
| 384 | + if (ret) | |
| 385 | + goto err; | |
| 386 | + | |
| 387 | + memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6); | |
| 388 | + cmd.wlen = 6; | |
| 389 | + cmd.rlen = 1; | |
| 390 | + ret = si2168_cmd_execute(s, &cmd); | |
| 391 | + if (ret) | |
| 392 | + goto err; | |
| 393 | + | |
| 394 | + memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6); | |
| 395 | + cmd.wlen = 6; | |
| 396 | + cmd.rlen = 1; | |
| 397 | + ret = si2168_cmd_execute(s, &cmd); | |
| 398 | + if (ret) | |
| 399 | + goto err; | |
| 400 | + | |
| 401 | + memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6); | |
| 402 | + cmd.wlen = 6; | |
| 403 | + cmd.rlen = 1; | |
| 404 | + ret = si2168_cmd_execute(s, &cmd); | |
| 405 | + if (ret) | |
| 406 | + goto err; | |
| 407 | + | |
| 408 | + memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6); | |
| 409 | + cmd.wlen = 6; | |
| 410 | + cmd.rlen = 1; | |
| 411 | + ret = si2168_cmd_execute(s, &cmd); | |
| 412 | + if (ret) | |
| 413 | + goto err; | |
| 414 | + | |
| 415 | + cmd.args[0] = 0x85; | |
| 416 | + cmd.wlen = 1; | |
| 417 | + cmd.rlen = 1; | |
| 418 | + ret = si2168_cmd_execute(s, &cmd); | |
| 419 | + if (ret) | |
| 420 | + goto err; | |
| 421 | + | |
| 422 | + s->delivery_system = c->delivery_system; | |
| 423 | + | |
| 424 | + return 0; | |
| 425 | +err: | |
| 426 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 427 | + return ret; | |
| 428 | +} | |
| 429 | + | |
| 430 | +static int si2168_init(struct dvb_frontend *fe) | |
| 431 | +{ | |
| 432 | + struct si2168 *s = fe->demodulator_priv; | |
| 433 | + int ret, len, remaining; | |
| 434 | + const struct firmware *fw = NULL; | |
| 435 | + u8 *fw_file = SI2168_FIRMWARE; | |
| 436 | + const unsigned int i2c_wr_max = 8; | |
| 437 | + struct si2168_cmd cmd; | |
| 438 | + | |
| 439 | + dev_dbg(&s->client->dev, "%s:\n", __func__); | |
| 440 | + | |
| 441 | + cmd.args[0] = 0x13; | |
| 442 | + cmd.wlen = 1; | |
| 443 | + cmd.rlen = 0; | |
| 444 | + ret = si2168_cmd_execute(s, &cmd); | |
| 445 | + if (ret) | |
| 446 | + goto err; | |
| 447 | + | |
| 448 | + cmd.args[0] = 0xc0; | |
| 449 | + cmd.args[1] = 0x12; | |
| 450 | + cmd.args[2] = 0x00; | |
| 451 | + cmd.args[3] = 0x0c; | |
| 452 | + cmd.args[4] = 0x00; | |
| 453 | + cmd.args[5] = 0x0d; | |
| 454 | + cmd.args[6] = 0x16; | |
| 455 | + cmd.args[7] = 0x00; | |
| 456 | + cmd.args[8] = 0x00; | |
| 457 | + cmd.args[9] = 0x00; | |
| 458 | + cmd.args[10] = 0x00; | |
| 459 | + cmd.args[11] = 0x00; | |
| 460 | + cmd.args[12] = 0x00; | |
| 461 | + cmd.wlen = 13; | |
| 462 | + cmd.rlen = 0; | |
| 463 | + ret = si2168_cmd_execute(s, &cmd); | |
| 464 | + if (ret) | |
| 465 | + goto err; | |
| 466 | + | |
| 467 | + cmd.args[0] = 0xc0; | |
| 468 | + cmd.args[1] = 0x06; | |
| 469 | + cmd.args[2] = 0x01; | |
| 470 | + cmd.args[3] = 0x0f; | |
| 471 | + cmd.args[4] = 0x00; | |
| 472 | + cmd.args[5] = 0x20; | |
| 473 | + cmd.args[6] = 0x20; | |
| 474 | + cmd.args[7] = 0x01; | |
| 475 | + cmd.wlen = 8; | |
| 476 | + cmd.rlen = 1; | |
| 477 | + ret = si2168_cmd_execute(s, &cmd); | |
| 478 | + if (ret) | |
| 479 | + goto err; | |
| 480 | + | |
| 481 | + cmd.args[0] = 0x02; | |
| 482 | + cmd.wlen = 1; | |
| 483 | + cmd.rlen = 13; | |
| 484 | + ret = si2168_cmd_execute(s, &cmd); | |
| 485 | + if (ret) | |
| 486 | + goto err; | |
| 487 | + | |
| 488 | + cmd.args[0] = 0x05; | |
| 489 | + cmd.args[1] = 0x00; | |
| 490 | + cmd.args[2] = 0xaa; | |
| 491 | + cmd.args[3] = 0x4d; | |
| 492 | + cmd.args[4] = 0x56; | |
| 493 | + cmd.args[5] = 0x40; | |
| 494 | + cmd.args[6] = 0x00; | |
| 495 | + cmd.args[7] = 0x00; | |
| 496 | + cmd.wlen = 8; | |
| 497 | + cmd.rlen = 1; | |
| 498 | + ret = si2168_cmd_execute(s, &cmd); | |
| 499 | + if (ret) | |
| 500 | + goto err; | |
| 501 | + | |
| 502 | + /* cold state - try to download firmware */ | |
| 503 | + dev_info(&s->client->dev, "%s: found a '%s' in cold state\n", | |
| 504 | + KBUILD_MODNAME, si2168_ops.info.name); | |
| 505 | + | |
| 506 | + /* request the firmware, this will block and timeout */ | |
| 507 | + ret = request_firmware(&fw, fw_file, &s->client->dev); | |
| 508 | + if (ret) { | |
| 509 | + dev_err(&s->client->dev, "%s: firmare file '%s' not found\n", | |
| 510 | + KBUILD_MODNAME, fw_file); | |
| 511 | + goto err; | |
| 512 | + } | |
| 513 | + | |
| 514 | + dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n", | |
| 515 | + KBUILD_MODNAME, fw_file); | |
| 516 | + | |
| 517 | + for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) { | |
| 518 | + len = remaining; | |
| 519 | + if (len > i2c_wr_max) | |
| 520 | + len = i2c_wr_max; | |
| 521 | + | |
| 522 | + memcpy(cmd.args, &fw->data[fw->size - remaining], len); | |
| 523 | + cmd.wlen = len; | |
| 524 | + cmd.rlen = 1; | |
| 525 | + ret = si2168_cmd_execute(s, &cmd); | |
| 526 | + if (ret) { | |
| 527 | + dev_err(&s->client->dev, | |
| 528 | + "%s: firmware download failed=%d\n", | |
| 529 | + KBUILD_MODNAME, ret); | |
| 530 | + goto err; | |
| 531 | + } | |
| 532 | + } | |
| 533 | + | |
| 534 | + release_firmware(fw); | |
| 535 | + fw = NULL; | |
| 536 | + | |
| 537 | + cmd.args[0] = 0x01; | |
| 538 | + cmd.args[1] = 0x01; | |
| 539 | + cmd.wlen = 2; | |
| 540 | + cmd.rlen = 1; | |
| 541 | + ret = si2168_cmd_execute(s, &cmd); | |
| 542 | + if (ret) | |
| 543 | + goto err; | |
| 544 | + | |
| 545 | + dev_info(&s->client->dev, "%s: found a '%s' in warm state\n", | |
| 546 | + KBUILD_MODNAME, si2168_ops.info.name); | |
| 547 | + | |
| 548 | + s->active = true; | |
| 549 | + | |
| 550 | + return 0; | |
| 551 | +err: | |
| 552 | + if (fw) | |
| 553 | + release_firmware(fw); | |
| 554 | + | |
| 555 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 556 | + return ret; | |
| 557 | +} | |
| 558 | + | |
| 559 | +static int si2168_sleep(struct dvb_frontend *fe) | |
| 560 | +{ | |
| 561 | + struct si2168 *s = fe->demodulator_priv; | |
| 562 | + | |
| 563 | + dev_dbg(&s->client->dev, "%s:\n", __func__); | |
| 564 | + | |
| 565 | + s->active = false; | |
| 566 | + | |
| 567 | + return 0; | |
| 568 | +} | |
| 569 | + | |
| 570 | +static int si2168_get_tune_settings(struct dvb_frontend *fe, | |
| 571 | + struct dvb_frontend_tune_settings *s) | |
| 572 | +{ | |
| 573 | + s->min_delay_ms = 900; | |
| 574 | + | |
| 575 | + return 0; | |
| 576 | +} | |
| 577 | + | |
| 578 | +/* | |
| 579 | + * I2C gate logic | |
| 580 | + * We must use unlocked i2c_transfer() here because I2C lock is already taken | |
| 581 | + * by tuner driver. | |
| 582 | + */ | |
| 583 | +static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) | |
| 584 | +{ | |
| 585 | + struct si2168 *s = mux_priv; | |
| 586 | + int ret; | |
| 587 | + struct i2c_msg gate_open_msg = { | |
| 588 | + .addr = s->client->addr, | |
| 589 | + .flags = 0, | |
| 590 | + .len = 3, | |
| 591 | + .buf = "\xc0\x0d\x01", | |
| 592 | + }; | |
| 593 | + | |
| 594 | + mutex_lock(&s->i2c_mutex); | |
| 595 | + | |
| 596 | + /* open tuner I2C gate */ | |
| 597 | + ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1); | |
| 598 | + if (ret != 1) { | |
| 599 | + dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", | |
| 600 | + KBUILD_MODNAME, ret); | |
| 601 | + if (ret >= 0) | |
| 602 | + ret = -EREMOTEIO; | |
| 603 | + } else { | |
| 604 | + ret = 0; | |
| 605 | + } | |
| 606 | + | |
| 607 | + return ret; | |
| 608 | +} | |
| 609 | + | |
| 610 | +static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) | |
| 611 | +{ | |
| 612 | + struct si2168 *s = mux_priv; | |
| 613 | + int ret; | |
| 614 | + struct i2c_msg gate_close_msg = { | |
| 615 | + .addr = s->client->addr, | |
| 616 | + .flags = 0, | |
| 617 | + .len = 3, | |
| 618 | + .buf = "\xc0\x0d\x00", | |
| 619 | + }; | |
| 620 | + | |
| 621 | + /* close tuner I2C gate */ | |
| 622 | + ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1); | |
| 623 | + if (ret != 1) { | |
| 624 | + dev_warn(&s->client->dev, "%s: i2c write failed=%d\n", | |
| 625 | + KBUILD_MODNAME, ret); | |
| 626 | + if (ret >= 0) | |
| 627 | + ret = -EREMOTEIO; | |
| 628 | + } else { | |
| 629 | + ret = 0; | |
| 630 | + } | |
| 631 | + | |
| 632 | + mutex_unlock(&s->i2c_mutex); | |
| 633 | + | |
| 634 | + return ret; | |
| 635 | +} | |
| 636 | + | |
| 637 | +static const struct dvb_frontend_ops si2168_ops = { | |
| 638 | + .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A}, | |
| 639 | + .info = { | |
| 640 | + .name = "Silicon Labs Si2168", | |
| 641 | + .caps = FE_CAN_FEC_1_2 | | |
| 642 | + FE_CAN_FEC_2_3 | | |
| 643 | + FE_CAN_FEC_3_4 | | |
| 644 | + FE_CAN_FEC_5_6 | | |
| 645 | + FE_CAN_FEC_7_8 | | |
| 646 | + FE_CAN_FEC_AUTO | | |
| 647 | + FE_CAN_QPSK | | |
| 648 | + FE_CAN_QAM_16 | | |
| 649 | + FE_CAN_QAM_32 | | |
| 650 | + FE_CAN_QAM_64 | | |
| 651 | + FE_CAN_QAM_128 | | |
| 652 | + FE_CAN_QAM_256 | | |
| 653 | + FE_CAN_QAM_AUTO | | |
| 654 | + FE_CAN_TRANSMISSION_MODE_AUTO | | |
| 655 | + FE_CAN_GUARD_INTERVAL_AUTO | | |
| 656 | + FE_CAN_HIERARCHY_AUTO | | |
| 657 | + FE_CAN_MUTE_TS | | |
| 658 | + FE_CAN_2G_MODULATION | |
| 659 | + }, | |
| 660 | + | |
| 661 | + .get_tune_settings = si2168_get_tune_settings, | |
| 662 | + | |
| 663 | + .init = si2168_init, | |
| 664 | + .sleep = si2168_sleep, | |
| 665 | + | |
| 666 | + .set_frontend = si2168_set_frontend, | |
| 667 | + | |
| 668 | + .read_status = si2168_read_status, | |
| 669 | +}; | |
| 670 | + | |
| 671 | +static int si2168_probe(struct i2c_client *client, | |
| 672 | + const struct i2c_device_id *id) | |
| 673 | +{ | |
| 674 | + struct si2168_config *config = client->dev.platform_data; | |
| 675 | + struct si2168 *s; | |
| 676 | + int ret; | |
| 677 | + struct si2168_cmd cmd; | |
| 678 | + | |
| 679 | + dev_dbg(&client->dev, "%s:\n", __func__); | |
| 680 | + | |
| 681 | + s = kzalloc(sizeof(struct si2168), GFP_KERNEL); | |
| 682 | + if (!s) { | |
| 683 | + ret = -ENOMEM; | |
| 684 | + dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | |
| 685 | + goto err; | |
| 686 | + } | |
| 687 | + | |
| 688 | + s->client = client; | |
| 689 | + mutex_init(&s->i2c_mutex); | |
| 690 | + | |
| 691 | + /* check if the demod is there */ | |
| 692 | + cmd.wlen = 0; | |
| 693 | + cmd.rlen = 1; | |
| 694 | + ret = si2168_cmd_execute(s, &cmd); | |
| 695 | + if (ret) | |
| 696 | + goto err; | |
| 697 | + | |
| 698 | + /* create mux i2c adapter for tuner */ | |
| 699 | + s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s, | |
| 700 | + 0, 0, 0, si2168_select, si2168_deselect); | |
| 701 | + if (s->adapter == NULL) | |
| 702 | + goto err; | |
| 703 | + | |
| 704 | + /* create dvb_frontend */ | |
| 705 | + memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops)); | |
| 706 | + s->fe.demodulator_priv = s; | |
| 707 | + | |
| 708 | + *config->i2c_adapter = s->adapter; | |
| 709 | + *config->fe = &s->fe; | |
| 710 | + | |
| 711 | + i2c_set_clientdata(client, s); | |
| 712 | + | |
| 713 | + dev_info(&s->client->dev, | |
| 714 | + "%s: Silicon Labs Si2168 successfully attached\n", | |
| 715 | + KBUILD_MODNAME); | |
| 716 | + return 0; | |
| 717 | +err: | |
| 718 | + kfree(s); | |
| 719 | + dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); | |
| 720 | + return ret; | |
| 721 | +} | |
| 722 | + | |
| 723 | +static int si2168_remove(struct i2c_client *client) | |
| 724 | +{ | |
| 725 | + struct si2168 *s = i2c_get_clientdata(client); | |
| 726 | + | |
| 727 | + dev_dbg(&client->dev, "%s:\n", __func__); | |
| 728 | + | |
| 729 | + i2c_del_mux_adapter(s->adapter); | |
| 730 | + | |
| 731 | + s->fe.ops.release = NULL; | |
| 732 | + s->fe.demodulator_priv = NULL; | |
| 733 | + | |
| 734 | + kfree(s); | |
| 735 | + | |
| 736 | + return 0; | |
| 737 | +} | |
| 738 | + | |
| 739 | +static const struct i2c_device_id si2168_id[] = { | |
| 740 | + {"si2168", 0}, | |
| 741 | + {} | |
| 742 | +}; | |
| 743 | +MODULE_DEVICE_TABLE(i2c, si2168_id); | |
| 744 | + | |
| 745 | +static struct i2c_driver si2168_driver = { | |
| 746 | + .driver = { | |
| 747 | + .owner = THIS_MODULE, | |
| 748 | + .name = "si2168", | |
| 749 | + }, | |
| 750 | + .probe = si2168_probe, | |
| 751 | + .remove = si2168_remove, | |
| 752 | + .id_table = si2168_id, | |
| 753 | +}; | |
| 754 | + | |
| 755 | +module_i2c_driver(si2168_driver); | |
| 756 | + | |
| 757 | +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
| 758 | +MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver"); | |
| 759 | +MODULE_LICENSE("GPL"); | |
| 760 | +MODULE_FIRMWARE(SI2168_FIRMWARE); | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2168 DVB-T/T2/C demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef SI2168_H | |
| 18 | +#define SI2168_H | |
| 19 | + | |
| 20 | +#include <linux/dvb/frontend.h> | |
| 21 | +/* | |
| 22 | + * I2C address | |
| 23 | + * 0x64 | |
| 24 | + */ | |
| 25 | +struct si2168_config { | |
| 26 | + /* | |
| 27 | + * frontend | |
| 28 | + * returned by driver | |
| 29 | + */ | |
| 30 | + struct dvb_frontend **fe; | |
| 31 | + | |
| 32 | + /* | |
| 33 | + * tuner I2C adapter | |
| 34 | + * returned by driver | |
| 35 | + */ | |
| 36 | + struct i2c_adapter **i2c_adapter; | |
| 37 | +}; | |
| 38 | + | |
| 39 | +#endif | |
| @@ -0,0 +1,46 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2168 DVB-T/T2/C demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef SI2168_PRIV_H | |
| 18 | +#define SI2168_PRIV_H | |
| 19 | + | |
| 20 | +#include "si2168.h" | |
| 21 | +#include "dvb_frontend.h" | |
| 22 | +#include <linux/firmware.h> | |
| 23 | +#include <linux/i2c-mux.h> | |
| 24 | + | |
| 25 | +#define SI2168_FIRMWARE "dvb-demod-si2168-01.fw" | |
| 26 | + | |
| 27 | +/* state struct */ | |
| 28 | +struct si2168 { | |
| 29 | + struct i2c_client *client; | |
| 30 | + struct i2c_adapter *adapter; | |
| 31 | + struct mutex i2c_mutex; | |
| 32 | + struct dvb_frontend fe; | |
| 33 | + fe_delivery_system_t delivery_system; | |
| 34 | + fe_status_t fe_status; | |
| 35 | + bool active; | |
| 36 | +}; | |
| 37 | + | |
| 38 | +/* firmare command struct */ | |
| 39 | +#define SI2157_ARGLEN 30 | |
| 40 | +struct si2168_cmd { | |
| 41 | + u8 args[SI2157_ARGLEN]; | |
| 42 | + unsigned wlen; | |
| 43 | + unsigned rlen; | |
| 44 | +}; | |
| 45 | + | |
| 46 | +#endif | |
| @@ -571,35 +571,6 @@ static const struct v4l2_subdev_core_ops ad9389b_core_ops = { · 570 unmodified lines | ||
| 571 | 571 | .interrupt_service_routine = ad9389b_isr, |
| 572 | 572 | }; |
| 573 | 573 | |
| 574 | −/* ------------------------------ PAD OPS ------------------------------ */ | |
| 575 | − | |
| 576 | −static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |
| 577 | −{ | |
| 578 | − struct ad9389b_state *state = get_ad9389b_state(sd); | |
| 579 | − | |
| 580 | − if (edid->pad != 0) | |
| 581 | − return -EINVAL; | |
| 582 | − if (edid->blocks == 0 || edid->blocks > 256) | |
| 583 | − return -EINVAL; | |
| 584 | − if (!edid->edid) | |
| 585 | − return -EINVAL; | |
| 586 | − if (!state->edid.segments) { | |
| 587 | − v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | |
| 588 | − return -ENODATA; | |
| 589 | − } | |
| 590 | − if (edid->start_block >= state->edid.segments * 2) | |
| 591 | − return -E2BIG; | |
| 592 | − if (edid->blocks + edid->start_block >= state->edid.segments * 2) | |
| 593 | − edid->blocks = state->edid.segments * 2 - edid->start_block; | |
| 594 | − memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | |
| 595 | − 128 * edid->blocks); | |
| 596 | − return 0; | |
| 597 | −} | |
| 598 | − | |
| 599 | −static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = { | |
| 600 | − .get_edid = ad9389b_get_edid, | |
| 601 | −}; | |
| 602 | − | |
| 603 | 574 | /* ------------------------------ VIDEO OPS ------------------------------ */ |
| 604 | 575 | |
| 605 | 576 | /* Enable/disable ad9389b output */ |
| @@ -678,6 +649,9 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd, · 72 unmodified lines | ||
| 678 | 649 | static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, |
| 679 | 650 | struct v4l2_enum_dv_timings *timings) |
| 680 | 651 | { |
| 652 | + if (timings->pad != 0) | |
| 653 | + return -EINVAL; | |
| 654 | + | |
| 681 | 655 | return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap, |
| 682 | 656 | NULL, NULL); |
| 683 | 657 | } |
| @@ -685,6 +659,9 @@ static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, · 1 unmodified line | ||
| 685 | 659 | static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, |
| 686 | 660 | struct v4l2_dv_timings_cap *cap) |
| 687 | 661 | { |
| 662 | + if (cap->pad != 0) | |
| 663 | + return -EINVAL; | |
| 664 | + | |
| 688 | 665 | *cap = ad9389b_timings_cap; |
| 689 | 666 | return 0; |
| 690 | 667 | } |
| @@ -693,10 +670,39 @@ static const struct v4l2_subdev_video_ops ad9389b_video_ops = { · 2 unmodified lines | ||
| 693 | 670 | .s_stream = ad9389b_s_stream, |
| 694 | 671 | .s_dv_timings = ad9389b_s_dv_timings, |
| 695 | 672 | .g_dv_timings = ad9389b_g_dv_timings, |
| 673 | +}; | |
| 674 | + | |
| 675 | +/* ------------------------------ PAD OPS ------------------------------ */ | |
| 676 | + | |
| 677 | +static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |
| 678 | +{ | |
| 679 | + struct ad9389b_state *state = get_ad9389b_state(sd); | |
| 680 | + | |
| 681 | + if (edid->pad != 0) | |
| 682 | + return -EINVAL; | |
| 683 | + if (edid->blocks == 0 || edid->blocks > 256) | |
| 684 | + return -EINVAL; | |
| 685 | + if (!state->edid.segments) { | |
| 686 | + v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | |
| 687 | + return -ENODATA; | |
| 688 | + } | |
| 689 | + if (edid->start_block >= state->edid.segments * 2) | |
| 690 | + return -E2BIG; | |
| 691 | + if (edid->blocks + edid->start_block >= state->edid.segments * 2) | |
| 692 | + edid->blocks = state->edid.segments * 2 - edid->start_block; | |
| 693 | + memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | |
| 694 | + 128 * edid->blocks); | |
| 695 | + return 0; | |
| 696 | +} | |
| 697 | + | |
| 698 | +static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = { | |
| 699 | + .get_edid = ad9389b_get_edid, | |
| 696 | 700 | .enum_dv_timings = ad9389b_enum_dv_timings, |
| 697 | 701 | .dv_timings_cap = ad9389b_dv_timings_cap, |
| 698 | 702 | }; |
| 699 | 703 | |
| 704 | +/* ------------------------------ AUDIO OPS ------------------------------ */ | |
| 705 | + | |
| 700 | 706 | static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable) |
| 701 | 707 | { |
| 702 | 708 | v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); |
| @@ -461,6 +461,7 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd, · 460 unmodified lines | ||
| 461 | 461 | } |
| 462 | 462 | |
| 463 | 463 | static const struct v4l2_subdev_video_ops adv7180_video_ops = { |
| 464 | + .s_std = adv7180_s_std, | |
| 464 | 465 | .querystd = adv7180_querystd, |
| 465 | 466 | .g_input_status = adv7180_g_input_status, |
| 466 | 467 | .s_routing = adv7180_s_routing, |
| @@ -472,7 +473,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { · 5 unmodified lines | ||
| 472 | 473 | }; |
| 473 | 474 | |
| 474 | 475 | static const struct v4l2_subdev_core_ops adv7180_core_ops = { |
| 475 | − .s_std = adv7180_s_std, | |
| 476 | 476 | .s_power = adv7180_s_power, |
| 477 | 477 | }; |
| 478 | 478 | |
| @@ -501,8 +501,6 @@ static const struct v4l2_ctrl_ops adv7183_ctrl_ops = { · 500 unmodified lines | ||
| 501 | 501 | |
| 502 | 502 | static const struct v4l2_subdev_core_ops adv7183_core_ops = { |
| 503 | 503 | .log_status = adv7183_log_status, |
| 504 | − .g_std = adv7183_g_std, | |
| 505 | − .s_std = adv7183_s_std, | |
| 506 | 504 | .reset = adv7183_reset, |
| 507 | 505 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 508 | 506 | .g_register = adv7183_g_register, |
| @@ -511,6 +509,8 @@ static const struct v4l2_subdev_core_ops adv7183_core_ops = { · 2 unmodified lines | ||
| 511 | 509 | }; |
| 512 | 510 | |
| 513 | 511 | static const struct v4l2_subdev_video_ops adv7183_video_ops = { |
| 512 | + .g_std = adv7183_g_std, | |
| 513 | + .s_std = adv7183_s_std, | |
| 514 | 514 | .s_routing = adv7183_s_routing, |
| 515 | 515 | .querystd = adv7183_querystd, |
| 516 | 516 | .g_input_status = adv7183_g_input_status, |
| @@ -597,34 +597,6 @@ static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled) · 596 unmodified lines | ||
| 597 | 597 | return 0; |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | −static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |
| 601 | −{ | |
| 602 | − struct adv7511_state *state = get_adv7511_state(sd); | |
| 603 | − | |
| 604 | − if (edid->pad != 0) | |
| 605 | − return -EINVAL; | |
| 606 | − if ((edid->blocks == 0) || (edid->blocks > 256)) | |
| 607 | − return -EINVAL; | |
| 608 | − if (!edid->edid) | |
| 609 | − return -EINVAL; | |
| 610 | − if (!state->edid.segments) { | |
| 611 | − v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | |
| 612 | − return -ENODATA; | |
| 613 | − } | |
| 614 | − if (edid->start_block >= state->edid.segments * 2) | |
| 615 | − return -E2BIG; | |
| 616 | − if ((edid->blocks + edid->start_block) >= state->edid.segments * 2) | |
| 617 | − edid->blocks = state->edid.segments * 2 - edid->start_block; | |
| 618 | − | |
| 619 | − memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | |
| 620 | − 128 * edid->blocks); | |
| 621 | − return 0; | |
| 622 | −} | |
| 623 | − | |
| 624 | −static const struct v4l2_subdev_pad_ops adv7511_pad_ops = { | |
| 625 | − .get_edid = adv7511_get_edid, | |
| 626 | −}; | |
| 627 | − | |
| 628 | 600 | static const struct v4l2_subdev_core_ops adv7511_core_ops = { |
| 629 | 601 | .log_status = adv7511_log_status, |
| 630 | 602 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| @@ -700,12 +672,18 @@ static int adv7511_g_dv_timings(struct v4l2_subdev *sd, · 69 unmodified lines | ||
| 700 | 672 | static int adv7511_enum_dv_timings(struct v4l2_subdev *sd, |
| 701 | 673 | struct v4l2_enum_dv_timings *timings) |
| 702 | 674 | { |
| 675 | + if (timings->pad != 0) | |
| 676 | + return -EINVAL; | |
| 677 | + | |
| 703 | 678 | return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL); |
| 704 | 679 | } |
| 705 | 680 | |
| 706 | 681 | static int adv7511_dv_timings_cap(struct v4l2_subdev *sd, |
| 707 | 682 | struct v4l2_dv_timings_cap *cap) |
| 708 | 683 | { |
| 684 | + if (cap->pad != 0) | |
| 685 | + return -EINVAL; | |
| 686 | + | |
| 709 | 687 | *cap = adv7511_timings_cap; |
| 710 | 688 | return 0; |
| 711 | 689 | } |
| @@ -714,8 +692,6 @@ static const struct v4l2_subdev_video_ops adv7511_video_ops = { · 2 unmodified lines | ||
| 714 | 692 | .s_stream = adv7511_s_stream, |
| 715 | 693 | .s_dv_timings = adv7511_s_dv_timings, |
| 716 | 694 | .g_dv_timings = adv7511_g_dv_timings, |
| 717 | − .enum_dv_timings = adv7511_enum_dv_timings, | |
| 718 | − .dv_timings_cap = adv7511_dv_timings_cap, | |
| 719 | 695 | }; |
| 720 | 696 | |
| 721 | 697 | /* ------------------------------ AUDIO OPS ------------------------------ */ |
| @@ -797,6 +773,36 @@ static const struct v4l2_subdev_audio_ops adv7511_audio_ops = { · 75 unmodified lines | ||
| 797 | 773 | .s_routing = adv7511_s_routing, |
| 798 | 774 | }; |
| 799 | 775 | |
| 776 | +/* ---------------------------- PAD OPS ------------------------------------- */ | |
| 777 | + | |
| 778 | +static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |
| 779 | +{ | |
| 780 | + struct adv7511_state *state = get_adv7511_state(sd); | |
| 781 | + | |
| 782 | + if (edid->pad != 0) | |
| 783 | + return -EINVAL; | |
| 784 | + if ((edid->blocks == 0) || (edid->blocks > 256)) | |
| 785 | + return -EINVAL; | |
| 786 | + if (!state->edid.segments) { | |
| 787 | + v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); | |
| 788 | + return -ENODATA; | |
| 789 | + } | |
| 790 | + if (edid->start_block >= state->edid.segments * 2) | |
| 791 | + return -E2BIG; | |
| 792 | + if ((edid->blocks + edid->start_block) >= state->edid.segments * 2) | |
| 793 | + edid->blocks = state->edid.segments * 2 - edid->start_block; | |
| 794 | + | |
| 795 | + memcpy(edid->edid, &state->edid.data[edid->start_block * 128], | |
| 796 | + 128 * edid->blocks); | |
| 797 | + return 0; | |
| 798 | +} | |
| 799 | + | |
| 800 | +static const struct v4l2_subdev_pad_ops adv7511_pad_ops = { | |
| 801 | + .get_edid = adv7511_get_edid, | |
| 802 | + .enum_dv_timings = adv7511_enum_dv_timings, | |
| 803 | + .dv_timings_cap = adv7511_dv_timings_cap, | |
| 804 | +}; | |
| 805 | + | |
| 800 | 806 | /* --------------------- SUBDEV OPS --------------------------------------- */ |
| 801 | 807 | |
| 802 | 808 | static const struct v4l2_subdev_ops adv7511_ops = { |
| @@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 1672 unmodified lines | ||
| 1673 | 1673 | return -EINVAL; |
| 1674 | 1674 | if (edid->start_block == 1) |
| 1675 | 1675 | edid->blocks = 1; |
| 1676 | − if (!edid->edid) | |
| 1677 | − return -EINVAL; | |
| 1678 | 1676 | |
| 1679 | 1677 | if (edid->blocks > state->edid.blocks) |
| 1680 | 1678 | edid->blocks = state->edid.blocks; |
| @@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 80 unmodified lines | ||
| 1761 | 1759 | edid->blocks = 2; |
| 1762 | 1760 | return -E2BIG; |
| 1763 | 1761 | } |
| 1764 | − if (!edid->edid) | |
| 1765 | − return -EINVAL; | |
| 1766 | 1762 | |
| 1767 | 1763 | v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n", |
| 1768 | 1764 | __func__, edid->pad, state->edid.present); |
| @@ -1399,6 +1399,9 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) · 1398 unmodified lines | ||
| 1399 | 1399 | static int adv7842_enum_dv_timings(struct v4l2_subdev *sd, |
| 1400 | 1400 | struct v4l2_enum_dv_timings *timings) |
| 1401 | 1401 | { |
| 1402 | + if (timings->pad != 0) | |
| 1403 | + return -EINVAL; | |
| 1404 | + | |
| 1402 | 1405 | return v4l2_enum_dv_timings_cap(timings, |
| 1403 | 1406 | adv7842_get_dv_timings_cap(sd), adv7842_check_dv_timings, NULL); |
| 1404 | 1407 | } |
| @@ -1406,6 +1409,9 @@ static int adv7842_enum_dv_timings(struct v4l2_subdev *sd, · 1 unmodified line | ||
| 1406 | 1409 | static int adv7842_dv_timings_cap(struct v4l2_subdev *sd, |
| 1407 | 1410 | struct v4l2_dv_timings_cap *cap) |
| 1408 | 1411 | { |
| 1412 | + if (cap->pad != 0) | |
| 1413 | + return -EINVAL; | |
| 1414 | + | |
| 1409 | 1415 | *cap = *adv7842_get_dv_timings_cap(sd); |
| 1410 | 1416 | return 0; |
| 1411 | 1417 | } |
| @@ -2000,6 +2006,7 @@ static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled) · 588 unmodified lines | ||
| 2000 | 2006 | if (irq_status[5] & 0x08) { |
| 2001 | 2007 | v4l2_dbg(1, debug, sd, "%s: irq %s mode\n", __func__, |
| 2002 | 2008 | (io_read(sd, 0x65) & 0x08) ? "HDMI" : "DVI"); |
| 2009 | + set_rgb_quantization_range(sd); | |
| 2003 | 2010 | if (handled) |
| 2004 | 2011 | *handled = true; |
| 2005 | 2012 | } |
| @@ -2029,8 +2036,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 23 unmodified lines | ||
| 2029 | 2036 | return -EINVAL; |
| 2030 | 2037 | if (edid->start_block == 1) |
| 2031 | 2038 | edid->blocks = 1; |
| 2032 | − if (!edid->edid) | |
| 2033 | − return -EINVAL; | |
| 2034 | 2039 | |
| 2035 | 2040 | switch (edid->pad) { |
| 2036 | 2041 | case ADV7842_EDID_PORT_A: |
| @@ -2065,8 +2070,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e) · 28 unmodified lines | ||
| 2065 | 2070 | return -EINVAL; |
| 2066 | 2071 | if (e->blocks > 2) |
| 2067 | 2072 | return -E2BIG; |
| 2068 | − if (!e->edid) | |
| 2069 | − return -EINVAL; | |
| 2070 | 2073 | |
| 2071 | 2074 | /* todo, per edid */ |
| 2072 | 2075 | state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15], |
| @@ -2610,6 +2613,12 @@ static int adv7842_core_init(struct v4l2_subdev *sd) · 537 unmodified lines | ||
| 2610 | 2613 | |
| 2611 | 2614 | disable_input(sd); |
| 2612 | 2615 | |
| 2616 | + /* | |
| 2617 | + * Disable I2C access to internal EDID ram from HDMI DDC ports | |
| 2618 | + * Disable auto edid enable when leaving powerdown mode | |
| 2619 | + */ | |
| 2620 | + rep_write_and_or(sd, 0x77, 0xd3, 0x20); | |
| 2621 | + | |
| 2613 | 2622 | /* power */ |
| 2614 | 2623 | io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */ |
| 2615 | 2624 | io_write(sd, 0x15, 0x80); /* Power up pads */ |
| @@ -2690,9 +2699,6 @@ static int adv7842_core_init(struct v4l2_subdev *sd) · 74 unmodified lines | ||
| 2690 | 2699 | |
| 2691 | 2700 | enable_input(sd); |
| 2692 | 2701 | |
| 2693 | − /* disable I2C access to internal EDID ram from HDMI DDC ports */ | |
| 2694 | − rep_write_and_or(sd, 0x77, 0xf3, 0x00); | |
| 2695 | − | |
| 2696 | 2702 | if (pdata->hpa_auto) { |
| 2697 | 2703 | /* HPA auto, HPA 0.5s after Edid set and Cable detect */ |
| 2698 | 2704 | hdmi_write(sd, 0x69, 0x5c); |
| @@ -2869,8 +2875,6 @@ static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { · 170 unmodified lines | ||
| 2869 | 2875 | |
| 2870 | 2876 | static const struct v4l2_subdev_core_ops adv7842_core_ops = { |
| 2871 | 2877 | .log_status = adv7842_log_status, |
| 2872 | − .g_std = adv7842_g_std, | |
| 2873 | − .s_std = adv7842_s_std, | |
| 2874 | 2878 | .ioctl = adv7842_ioctl, |
| 2875 | 2879 | .interrupt_service_routine = adv7842_isr, |
| 2876 | 2880 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| @@ -2880,14 +2884,14 @@ static const struct v4l2_subdev_core_ops adv7842_core_ops = { · 3 unmodified lines | ||
| 2880 | 2884 | }; |
| 2881 | 2885 | |
| 2882 | 2886 | static const struct v4l2_subdev_video_ops adv7842_video_ops = { |
| 2887 | + .g_std = adv7842_g_std, | |
| 2888 | + .s_std = adv7842_s_std, | |
| 2883 | 2889 | .s_routing = adv7842_s_routing, |
| 2884 | 2890 | .querystd = adv7842_querystd, |
| 2885 | 2891 | .g_input_status = adv7842_g_input_status, |
| 2886 | 2892 | .s_dv_timings = adv7842_s_dv_timings, |
| 2887 | 2893 | .g_dv_timings = adv7842_g_dv_timings, |
| 2888 | 2894 | .query_dv_timings = adv7842_query_dv_timings, |
| 2889 | − .enum_dv_timings = adv7842_enum_dv_timings, | |
| 2890 | − .dv_timings_cap = adv7842_dv_timings_cap, | |
| 2891 | 2895 | .enum_mbus_fmt = adv7842_enum_mbus_fmt, |
| 2892 | 2896 | .g_mbus_fmt = adv7842_g_mbus_fmt, |
| 2893 | 2897 | .try_mbus_fmt = adv7842_g_mbus_fmt, |
| @@ -2897,6 +2901,8 @@ static const struct v4l2_subdev_video_ops adv7842_video_ops = { · 3 unmodified lines | ||
| 2897 | 2901 | static const struct v4l2_subdev_pad_ops adv7842_pad_ops = { |
| 2898 | 2902 | .get_edid = adv7842_get_edid, |
| 2899 | 2903 | .set_edid = adv7842_set_edid, |
| 2904 | + .enum_dv_timings = adv7842_enum_dv_timings, | |
| 2905 | + .dv_timings_cap = adv7842_dv_timings_cap, | |
| 2900 | 2906 | }; |
| 2901 | 2907 | |
| 2902 | 2908 | static const struct v4l2_subdev_ops adv7842_ops = { |
| @@ -387,10 +387,10 @@ static const struct v4l2_subdev_core_ops bt819_core_ops = { · 386 unmodified lines | ||
| 387 | 387 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 388 | 388 | .queryctrl = v4l2_subdev_queryctrl, |
| 389 | 389 | .querymenu = v4l2_subdev_querymenu, |
| 390 | − .s_std = bt819_s_std, | |
| 391 | 390 | }; |
| 392 | 391 | |
| 393 | 392 | static const struct v4l2_subdev_video_ops bt819_video_ops = { |
| 393 | + .s_std = bt819_s_std, | |
| 394 | 394 | .s_routing = bt819_s_routing, |
| 395 | 395 | .s_stream = bt819_s_stream, |
| 396 | 396 | .querystd = bt819_querystd, |
| @@ -5041,8 +5041,6 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = { · 5040 unmodified lines | ||
| 5041 | 5041 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
| 5042 | 5042 | .queryctrl = v4l2_subdev_queryctrl, |
| 5043 | 5043 | .querymenu = v4l2_subdev_querymenu, |
| 5044 | − .s_std = cx25840_s_std, | |
| 5045 | − .g_std = cx25840_g_std, | |
| 5046 | 5044 | .reset = cx25840_reset, |
| 5047 | 5045 | .load_fw = cx25840_load_fw, |
| 5048 | 5046 | .s_io_pin_config = common_s_io_pin_config, |
| @@ -5067,6 +5065,8 @@ static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { · 18 unmodified lines | ||
| 5067 | 5065 | }; |
| 5068 | 5066 | |
| 5069 | 5067 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { |
| 5068 | + .s_std = cx25840_s_std, | |
| 5069 | + .g_std = cx25840_g_std, | |
| 5070 | 5070 | .s_routing = cx25840_s_video_routing, |
| 5071 | 5071 | .s_mbus_fmt = cx25840_s_mbus_fmt, |
| 5072 | 5072 | .s_stream = cx25840_s_stream, |
| @@ -648,11 +648,8 @@ static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) · 647 unmodified lines | ||
| 648 | 648 | |
| 649 | 649 | /* ----------------------------------------------------------------------- */ |
| 650 | 650 | |
| 651 | −static const struct v4l2_subdev_core_ops ks0127_core_ops = { | |
| 652 | − .s_std = ks0127_s_std, | |
| 653 | −}; | |
| 654 | − | |
| 655 | 651 | static const struct v4l2_subdev_video_ops ks0127_video_ops = { |
| 652 | + .s_std = ks0127_s_std, | |
| 656 | 653 | .s_routing = ks0127_s_routing, |
| 657 | 654 | .s_stream = ks0127_s_stream, |
| 658 | 655 | .querystd = ks0127_querystd, |
| @@ -660,7 +657,6 @@ static const struct v4l2_subdev_video_ops ks0127_video_ops = { · 1 unmodified line | ||
| 660 | 657 | }; |
| 661 | 658 | |
| 662 | 659 | static const struct v4l2_subdev_ops ks0127_ops = { |
| 663 | − .core = &ks0127_core_ops, | |
| 664 | 660 | .video = &ks0127_video_ops, |
| 665 | 661 | }; |
| 666 | 662 | |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <media/v4l2-device.h> |
| 27 | 27 | #include <media/v4l2-subdev.h> |
| 28 | 28 | #include <media/m5mols.h> |
| 29 | −#include <media/s5p_fimc.h> | |
| 29 | +#include <media/exynos-fimc.h> | |
| 30 | 30 | |
| 31 | 31 | #include "m5mols.h" |
| 32 | 32 | #include "m5mols_reg.h" |
| @@ -276,6 +276,7 @@ static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = { · 275 unmodified lines | ||
| 276 | 276 | }; |
| 277 | 277 | |
| 278 | 278 | static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { |
| 279 | + .s_std = ml86v7667_s_std, | |
| 279 | 280 | .querystd = ml86v7667_querystd, |
| 280 | 281 | .g_input_status = ml86v7667_g_input_status, |
| 281 | 282 | .enum_mbus_fmt = ml86v7667_enum_mbus_fmt, |
| @@ -286,7 +287,6 @@ static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { · 4 unmodified lines | ||
| 286 | 287 | }; |
| 287 | 288 | |
| 288 | 289 | static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = { |
| 289 | − .s_std = ml86v7667_s_std, | |
| 290 | 290 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 291 | 291 | .g_register = ml86v7667_g_register, |
| 292 | 292 | .s_register = ml86v7667_s_register, |
| @@ -649,10 +649,10 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { · 648 unmodified lines | ||
| 649 | 649 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 650 | 650 | .queryctrl = v4l2_subdev_queryctrl, |
| 651 | 651 | .querymenu = v4l2_subdev_querymenu, |
| 652 | − .s_std = msp_s_std, | |
| 653 | 652 | }; |
| 654 | 653 | |
| 655 | 654 | static const struct v4l2_subdev_video_ops msp_video_ops = { |
| 655 | + .s_std = msp_s_std, | |
| 656 | 656 | .querystd = msp_querystd, |
| 657 | 657 | }; |
| 658 | 658 | |
| @@ -647,6 +647,28 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev, · 646 unmodified lines | ||
| 647 | 647 | #define V4L2_CID_BLC_ANALOG_OFFSET (V4L2_CID_USER_BASE | 0x1004) |
| 648 | 648 | #define V4L2_CID_BLC_DIGITAL_OFFSET (V4L2_CID_USER_BASE | 0x1005) |
| 649 | 649 | |
| 650 | +static int mt9p031_restore_blc(struct mt9p031 *mt9p031) | |
| 651 | +{ | |
| 652 | + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | |
| 653 | + int ret; | |
| 654 | + | |
| 655 | + if (mt9p031->blc_auto->cur.val != 0) { | |
| 656 | + ret = mt9p031_set_mode2(mt9p031, 0, | |
| 657 | + MT9P031_READ_MODE_2_ROW_BLC); | |
| 658 | + if (ret < 0) | |
| 659 | + return ret; | |
| 660 | + } | |
| 661 | + | |
| 662 | + if (mt9p031->blc_offset->cur.val != 0) { | |
| 663 | + ret = mt9p031_write(client, MT9P031_ROW_BLACK_TARGET, | |
| 664 | + mt9p031->blc_offset->cur.val); | |
| 665 | + if (ret < 0) | |
| 666 | + return ret; | |
| 667 | + } | |
| 668 | + | |
| 669 | + return 0; | |
| 670 | +} | |
| 671 | + | |
| 650 | 672 | static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl) |
| 651 | 673 | { |
| 652 | 674 | struct mt9p031 *mt9p031 = |
| @@ -655,6 +677,9 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl) · 2 unmodified lines | ||
| 655 | 677 | u16 data; |
| 656 | 678 | int ret; |
| 657 | 679 | |
| 680 | + if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) | |
| 681 | + return 0; | |
| 682 | + | |
| 658 | 683 | switch (ctrl->id) { |
| 659 | 684 | case V4L2_CID_EXPOSURE: |
| 660 | 685 | ret = mt9p031_write(client, MT9P031_SHUTTER_WIDTH_UPPER, |
| @@ -709,18 +734,20 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl) · 48 unmodified lines | ||
| 709 | 734 | MT9P031_READ_MODE_2_ROW_MIR, 0); |
| 710 | 735 | |
| 711 | 736 | case V4L2_CID_TEST_PATTERN: |
| 737 | + /* The digital side of the Black Level Calibration function must | |
| 738 | + * be disabled when generating a test pattern to avoid artifacts | |
| 739 | + * in the image. Activate (deactivate) the BLC-related controls | |
| 740 | + * when the test pattern is enabled (disabled). | |
| 741 | + */ | |
| 742 | + v4l2_ctrl_activate(mt9p031->blc_auto, ctrl->val == 0); | |
| 743 | + v4l2_ctrl_activate(mt9p031->blc_offset, ctrl->val == 0); | |
| 744 | + | |
| 712 | 745 | if (!ctrl->val) { |
| 713 | − /* Restore the black level compensation settings. */ | |
| 714 | − if (mt9p031->blc_auto->cur.val != 0) { | |
| 715 | − ret = mt9p031_s_ctrl(mt9p031->blc_auto); | |
| 716 | − if (ret < 0) | |
| 717 | − return ret; | |
| 718 | − } | |
| 719 | − if (mt9p031->blc_offset->cur.val != 0) { | |
| 720 | − ret = mt9p031_s_ctrl(mt9p031->blc_offset); | |
| 721 | − if (ret < 0) | |
| 722 | − return ret; | |
| 723 | − } | |
| 746 | + /* Restore the BLC settings. */ | |
| 747 | + ret = mt9p031_restore_blc(mt9p031); | |
| 748 | + if (ret < 0) | |
| 749 | + return ret; | |
| 750 | + | |
| 724 | 751 | return mt9p031_write(client, MT9P031_TEST_PATTERN, |
| 725 | 752 | MT9P031_TEST_PATTERN_DISABLE); |
| 726 | 753 | } |
| @@ -735,9 +762,7 @@ static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl) · 8 unmodified lines | ||
| 735 | 762 | if (ret < 0) |
| 736 | 763 | return ret; |
| 737 | 764 | |
| 738 | − /* Disable digital black level compensation when using a test | |
| 739 | − * pattern. | |
| 740 | − */ | |
| 765 | + /* Disable digital BLC when generating a test pattern. */ | |
| 741 | 766 | ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC, |
| 742 | 767 | 0); |
| 743 | 768 | if (ret < 0) |
| @@ -643,10 +643,10 @@ static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = { · 642 unmodified lines | ||
| 643 | 643 | |
| 644 | 644 | static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { |
| 645 | 645 | .init = saa6752hs_init, |
| 646 | − .s_std = saa6752hs_s_std, | |
| 647 | 646 | }; |
| 648 | 647 | |
| 649 | 648 | static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { |
| 649 | + .s_std = saa6752hs_s_std, | |
| 650 | 650 | .s_mbus_fmt = saa6752hs_s_mbus_fmt, |
| 651 | 651 | .try_mbus_fmt = saa6752hs_try_mbus_fmt, |
| 652 | 652 | .g_mbus_fmt = saa6752hs_g_mbus_fmt, |
| @@ -365,10 +365,10 @@ static const struct v4l2_subdev_core_ops saa7110_core_ops = { · 364 unmodified lines | ||
| 365 | 365 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 366 | 366 | .queryctrl = v4l2_subdev_queryctrl, |
| 367 | 367 | .querymenu = v4l2_subdev_querymenu, |
| 368 | − .s_std = saa7110_s_std, | |
| 369 | 368 | }; |
| 370 | 369 | |
| 371 | 370 | static const struct v4l2_subdev_video_ops saa7110_video_ops = { |
| 371 | + .s_std = saa7110_s_std, | |
| 372 | 372 | .s_routing = saa7110_s_routing, |
| 373 | 373 | .s_stream = saa7110_s_stream, |
| 374 | 374 | .querystd = saa7110_querystd, |
| @@ -1582,7 +1582,6 @@ static const struct v4l2_subdev_core_ops saa711x_core_ops = { · 1581 unmodified lines | ||
| 1582 | 1582 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 1583 | 1583 | .queryctrl = v4l2_subdev_queryctrl, |
| 1584 | 1584 | .querymenu = v4l2_subdev_querymenu, |
| 1585 | − .s_std = saa711x_s_std, | |
| 1586 | 1585 | .reset = saa711x_reset, |
| 1587 | 1586 | .s_gpio = saa711x_s_gpio, |
| 1588 | 1587 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| @@ -1601,6 +1600,7 @@ static const struct v4l2_subdev_audio_ops saa711x_audio_ops = { · 12 unmodified lines | ||
| 1601 | 1600 | }; |
| 1602 | 1601 | |
| 1603 | 1602 | static const struct v4l2_subdev_video_ops saa711x_video_ops = { |
| 1603 | + .s_std = saa711x_s_std, | |
| 1604 | 1604 | .s_routing = saa711x_s_routing, |
| 1605 | 1605 | .s_crystal_freq = saa711x_s_crystal_freq, |
| 1606 | 1606 | .s_mbus_fmt = saa711x_s_mbus_fmt, |
| @@ -1198,7 +1198,6 @@ static const struct v4l2_subdev_core_ops saa717x_core_ops = { · 1197 unmodified lines | ||
| 1198 | 1198 | .g_register = saa717x_g_register, |
| 1199 | 1199 | .s_register = saa717x_s_register, |
| 1200 | 1200 | #endif |
| 1201 | − .s_std = saa717x_s_std, | |
| 1202 | 1201 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
| 1203 | 1202 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
| 1204 | 1203 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, |
| @@ -1216,6 +1215,7 @@ static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { · 11 unmodified lines | ||
| 1216 | 1215 | }; |
| 1217 | 1216 | |
| 1218 | 1217 | static const struct v4l2_subdev_video_ops saa717x_video_ops = { |
| 1218 | + .s_std = saa717x_s_std, | |
| 1219 | 1219 | .s_routing = saa717x_s_video_routing, |
| 1220 | 1220 | .s_mbus_fmt = saa717x_s_mbus_fmt, |
| 1221 | 1221 | .s_stream = saa717x_s_stream, |
| @@ -573,10 +573,10 @@ static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) · 572 unmodified lines | ||
| 573 | 573 | static const struct v4l2_subdev_core_ops saa7191_core_ops = { |
| 574 | 574 | .g_ctrl = saa7191_g_ctrl, |
| 575 | 575 | .s_ctrl = saa7191_s_ctrl, |
| 576 | − .s_std = saa7191_s_std, | |
| 577 | 576 | }; |
| 578 | 577 | |
| 579 | 578 | static const struct v4l2_subdev_video_ops saa7191_video_ops = { |
| 579 | + .s_std = saa7191_s_std, | |
| 580 | 580 | .s_routing = saa7191_s_routing, |
| 581 | 581 | .querystd = saa7191_querystd, |
| 582 | 582 | .g_input_status = saa7191_g_input_status, |
| @@ -46,7 +46,7 @@ struct smiapp_pll { · 45 unmodified lines | ||
| 46 | 46 | uint8_t bus_width; |
| 47 | 47 | } parallel; |
| 48 | 48 | }; |
| 49 | − uint8_t flags; | |
| 49 | + unsigned long flags; | |
| 50 | 50 | uint8_t binning_horizontal; |
| 51 | 51 | uint8_t binning_vertical; |
| 52 | 52 | uint8_t scale_m; |
| @@ -606,7 +606,7 @@ static int smiapp_get_limits(struct smiapp_sensor *sensor, int const *limit, · 605 unmodified lines | ||
| 606 | 606 | if (rval) |
| 607 | 607 | return rval; |
| 608 | 608 | sensor->limits[limit[i]] = val; |
| 609 | − dev_dbg(&client->dev, "0x%8.8x \"%s\" = %d, 0x%x\n", | |
| 609 | + dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n", | |
| 610 | 610 | smiapp_reg_limits[limit[i]].addr, |
| 611 | 611 | smiapp_reg_limits[limit[i]].what, val, val); |
| 612 | 612 | } |
| @@ -741,8 +741,8 @@ static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor) · 128 unmodified lines | ||
| 741 | 741 | if (rval) |
| 742 | 742 | return rval; |
| 743 | 743 | |
| 744 | − dev_dbg(&client->dev, "bpp %d, compressed %d\n", | |
| 745 | − fmt >> 8, (u8)fmt); | |
| 744 | + dev_dbg(&client->dev, "%u: bpp %u, compressed %u\n", | |
| 745 | + i, fmt >> 8, (u8)fmt); | |
| 746 | 746 | |
| 747 | 747 | for (j = 0; j < ARRAY_SIZE(smiapp_csi_data_formats); j++) { |
| 748 | 748 | const struct smiapp_csi_data_format *f = |
| @@ -1128,7 +1128,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor) · 379 unmodified lines | ||
| 1128 | 1128 | } |
| 1129 | 1129 | usleep_range(1000, 1000); |
| 1130 | 1130 | |
| 1131 | − if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) | |
| 1131 | + if (gpio_is_valid(sensor->platform_data->xshutdown)) | |
| 1132 | 1132 | gpio_set_value(sensor->platform_data->xshutdown, 1); |
| 1133 | 1133 | |
| 1134 | 1134 | sleep = SMIAPP_RESET_DELAY(sensor->platform_data->ext_clk); |
| @@ -1238,7 +1238,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor) · 103 unmodified lines | ||
| 1238 | 1238 | return 0; |
| 1239 | 1239 | |
| 1240 | 1240 | out_cci_addr_fail: |
| 1241 | − if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) | |
| 1241 | + if (gpio_is_valid(sensor->platform_data->xshutdown)) | |
| 1242 | 1242 | gpio_set_value(sensor->platform_data->xshutdown, 0); |
| 1243 | 1243 | if (sensor->platform_data->set_xclk) |
| 1244 | 1244 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| @@ -1264,7 +1264,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor) · 19 unmodified lines | ||
| 1264 | 1264 | SMIAPP_REG_U8_SOFTWARE_RESET, |
| 1265 | 1265 | SMIAPP_SOFTWARE_RESET); |
| 1266 | 1266 | |
| 1267 | − if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) | |
| 1267 | + if (gpio_is_valid(sensor->platform_data->xshutdown)) | |
| 1268 | 1268 | gpio_set_value(sensor->platform_data->xshutdown, 0); |
| 1269 | 1269 | if (sensor->platform_data->set_xclk) |
| 1270 | 1270 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| @@ -1766,7 +1766,7 @@ static void smiapp_set_compose_binner(struct v4l2_subdev *subdev, · 495 unmodified lines | ||
| 1766 | 1766 | struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); |
| 1767 | 1767 | unsigned int i; |
| 1768 | 1768 | unsigned int binh = 1, binv = 1; |
| 1769 | − unsigned int best = scaling_goodness( | |
| 1769 | + int best = scaling_goodness( | |
| 1770 | 1770 | subdev, |
| 1771 | 1771 | crops[SMIAPP_PAD_SINK]->width, sel->r.width, |
| 1772 | 1772 | crops[SMIAPP_PAD_SINK]->height, sel->r.height, sel->flags); |
| @@ -2355,17 +2355,17 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 582 unmodified lines | ||
| 2355 | 2355 | unsigned int i; |
| 2356 | 2356 | int rval; |
| 2357 | 2357 | |
| 2358 | − sensor->vana = devm_regulator_get(&client->dev, "VANA"); | |
| 2358 | + sensor->vana = devm_regulator_get(&client->dev, "vana"); | |
| 2359 | 2359 | if (IS_ERR(sensor->vana)) { |
| 2360 | 2360 | dev_err(&client->dev, "could not get regulator for vana\n"); |
| 2361 | − return -ENODEV; | |
| 2361 | + return PTR_ERR(sensor->vana); | |
| 2362 | 2362 | } |
| 2363 | 2363 | |
| 2364 | 2364 | if (!sensor->platform_data->set_xclk) { |
| 2365 | 2365 | sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk"); |
| 2366 | 2366 | if (IS_ERR(sensor->ext_clk)) { |
| 2367 | 2367 | dev_err(&client->dev, "could not get clock\n"); |
| 2368 | − return -ENODEV; | |
| 2368 | + return PTR_ERR(sensor->ext_clk); | |
| 2369 | 2369 | } |
| 2370 | 2370 | |
| 2371 | 2371 | rval = clk_set_rate(sensor->ext_clk, |
| @@ -2374,18 +2374,19 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 2 unmodified lines | ||
| 2374 | 2374 | dev_err(&client->dev, |
| 2375 | 2375 | "unable to set clock freq to %u\n", |
| 2376 | 2376 | sensor->platform_data->ext_clk); |
| 2377 | − return -ENODEV; | |
| 2377 | + return rval; | |
| 2378 | 2378 | } |
| 2379 | 2379 | } |
| 2380 | 2380 | |
| 2381 | − if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) { | |
| 2382 | − if (devm_gpio_request_one(&client->dev, | |
| 2383 | − sensor->platform_data->xshutdown, 0, | |
| 2384 | − "SMIA++ xshutdown") != 0) { | |
| 2381 | + if (gpio_is_valid(sensor->platform_data->xshutdown)) { | |
| 2382 | + rval = devm_gpio_request_one( | |
| 2383 | + &client->dev, sensor->platform_data->xshutdown, 0, | |
| 2384 | + "SMIA++ xshutdown"); | |
| 2385 | + if (rval < 0) { | |
| 2385 | 2386 | dev_err(&client->dev, |
| 2386 | 2387 | "unable to acquire reset gpio %d\n", |
| 2387 | 2388 | sensor->platform_data->xshutdown); |
| 2388 | − return -ENODEV; | |
| 2389 | + return rval; | |
| 2389 | 2390 | } |
| 2390 | 2391 | } |
| 2391 | 2392 | |
| @@ -2423,6 +2424,12 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 31 unmodified lines | ||
| 2423 | 2424 | sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP | |
| 2424 | 2425 | SMIAPP_IMAGE_ORIENTATION_VFLIP; |
| 2425 | 2426 | |
| 2427 | + rval = smiapp_call_quirk(sensor, limits); | |
| 2428 | + if (rval) { | |
| 2429 | + dev_err(&client->dev, "limits quirks failed\n"); | |
| 2430 | + goto out_power_off; | |
| 2431 | + } | |
| 2432 | + | |
| 2426 | 2433 | rval = smiapp_get_mbus_formats(sensor); |
| 2427 | 2434 | if (rval) { |
| 2428 | 2435 | rval = -ENODEV; |
| @@ -2483,12 +2490,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 54 unmodified lines | ||
| 2483 | 2490 | } |
| 2484 | 2491 | } |
| 2485 | 2492 | |
| 2486 | − rval = smiapp_call_quirk(sensor, limits); | |
| 2487 | − if (rval) { | |
| 2488 | − dev_err(&client->dev, "limits quirks failed\n"); | |
| 2489 | − goto out_nvm_release; | |
| 2490 | − } | |
| 2491 | − | |
| 2492 | 2493 | /* We consider this as profile 0 sensor if any of these are zero. */ |
| 2493 | 2494 | if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] || |
| 2494 | 2495 | !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] || |
| @@ -2543,8 +2544,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 48 unmodified lines | ||
| 2543 | 2544 | } |
| 2544 | 2545 | |
| 2545 | 2546 | snprintf(this->sd.name, |
| 2546 | − sizeof(this->sd.name), "%s %s", | |
| 2547 | − sensor->minfo.name, _this->name); | |
| 2547 | + sizeof(this->sd.name), "%s %d-%4.4x %s", | |
| 2548 | + sensor->minfo.name, i2c_adapter_id(client->adapter), | |
| 2549 | + client->addr, _this->name); | |
| 2548 | 2550 | |
| 2549 | 2551 | this->sink_fmt.width = |
| 2550 | 2552 | sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1; |
| @@ -2616,12 +2618,11 @@ static int smiapp_registered(struct v4l2_subdev *subdev) · 65 unmodified lines | ||
| 2616 | 2618 | pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; |
| 2617 | 2619 | pll->csi2.lanes = sensor->platform_data->lanes; |
| 2618 | 2620 | pll->ext_clk_freq_hz = sensor->platform_data->ext_clk; |
| 2621 | + pll->flags = smiapp_call_quirk(sensor, pll_flags); | |
| 2622 | + | |
| 2619 | 2623 | /* Profile 0 sensors have no separate OP clock branch. */ |
| 2620 | 2624 | if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) |
| 2621 | 2625 | pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; |
| 2622 | − if (smiapp_needs_quirk(sensor, | |
| 2623 | − SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE)) | |
| 2624 | − pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; | |
| 2625 | 2626 | pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]; |
| 2626 | 2627 | |
| 2627 | 2628 | rval = smiapp_update_mode(sensor); |
| @@ -2830,7 +2831,7 @@ static int smiapp_remove(struct i2c_client *client) · 202 unmodified lines | ||
| 2830 | 2831 | unsigned int i; |
| 2831 | 2832 | |
| 2832 | 2833 | if (sensor->power_count) { |
| 2833 | − if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) | |
| 2834 | + if (gpio_is_valid(sensor->platform_data->xshutdown)) | |
| 2834 | 2835 | gpio_set_value(sensor->platform_data->xshutdown, 0); |
| 2835 | 2836 | if (sensor->platform_data->set_xclk) |
| 2836 | 2837 | sensor->platform_data->set_xclk(&sensor->src->sd, 0); |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val) |
| 30 | 30 | { |
| 31 | − return smiapp_write(sensor, (SMIA_REG_8BIT << 16) | reg, val); | |
| 31 | + return smiapp_write(sensor, SMIAPP_REG_MK_U8(reg), val); | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | static int smiapp_write_8s(struct smiapp_sensor *sensor, |
| @@ -61,52 +61,6 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor, · 26 unmodified lines | ||
| 61 | 61 | sensor->limits[limit] = val; |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | −bool smiapp_quirk_reg(struct smiapp_sensor *sensor, | |
| 65 | − u32 reg, u32 *val) | |
| 66 | −{ | |
| 67 | − struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); | |
| 68 | − const struct smia_reg *sreg; | |
| 69 | − | |
| 70 | − if (!sensor->minfo.quirk) | |
| 71 | − return false; | |
| 72 | − | |
| 73 | − sreg = sensor->minfo.quirk->regs; | |
| 74 | − | |
| 75 | − if (!sreg) | |
| 76 | − return false; | |
| 77 | − | |
| 78 | − while (sreg->type) { | |
| 79 | − u16 type = reg >> 16; | |
| 80 | − u16 reg16 = reg; | |
| 81 | − | |
| 82 | − if (sreg->type != type || sreg->reg != reg16) { | |
| 83 | − sreg++; | |
| 84 | − continue; | |
| 85 | − } | |
| 86 | − | |
| 87 | − switch ((u8)type) { | |
| 88 | − case SMIA_REG_8BIT: | |
| 89 | − dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%2.2x\n", | |
| 90 | − reg, sreg->val); | |
| 91 | − break; | |
| 92 | − case SMIA_REG_16BIT: | |
| 93 | − dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%4.4x\n", | |
| 94 | − reg, sreg->val); | |
| 95 | − break; | |
| 96 | − case SMIA_REG_32BIT: | |
| 97 | − dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%8.8x\n", | |
| 98 | − reg, sreg->val); | |
| 99 | − break; | |
| 100 | − } | |
| 101 | − | |
| 102 | − *val = sreg->val; | |
| 103 | − | |
| 104 | − return true; | |
| 105 | − } | |
| 106 | − | |
| 107 | − return false; | |
| 108 | −} | |
| 109 | − | |
| 110 | 64 | static int jt8ew9_limits(struct smiapp_sensor *sensor) |
| 111 | 65 | { |
| 112 | 66 | if (sensor->minfo.revision_number_major < 0x03) |
| @@ -266,12 +220,17 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor) · 153 unmodified lines | ||
| 266 | 220 | return smiapp_write_8(sensor, 0x3328, 0x80); |
| 267 | 221 | } |
| 268 | 222 | |
| 223 | +static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor) | |
| 224 | +{ | |
| 225 | + return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; | |
| 226 | +} | |
| 227 | + | |
| 269 | 228 | const struct smiapp_quirk smiapp_jt8ev1_quirk = { |
| 270 | 229 | .limits = jt8ev1_limits, |
| 271 | 230 | .post_poweron = jt8ev1_post_poweron, |
| 272 | 231 | .pre_streamon = jt8ev1_pre_streamon, |
| 273 | 232 | .post_streamoff = jt8ev1_post_streamoff, |
| 274 | − .flags = SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE, | |
| 233 | + .pll_flags = jt8ev1_pll_flags, | |
| 275 | 234 | }; |
| 276 | 235 | |
| 277 | 236 | static int tcm8500md_limits(struct smiapp_sensor *sensor) |
| @@ -35,19 +35,30 @@ struct smiapp_sensor; · 34 unmodified lines | ||
| 35 | 35 | * @post_poweron: Called always after the sensor has been fully powered on. |
| 36 | 36 | * @pre_streamon: Called just before streaming is enabled. |
| 37 | 37 | * @post_streamon: Called right after stopping streaming. |
| 38 | + * @reg_access: Register access quirk. The quirk may divert the access | |
| 39 | + * to another register, or no register at all. | |
| 40 | + * | |
| 41 | + * @write: Is this read (false) or write (true) access? | |
| 42 | + * @reg: Pointer to the register to access | |
| 43 | + * @value: Register value, set by the caller on write, or | |
| 44 | + * by the quirk on read | |
| 45 | + * | |
| 46 | + * @return: 0 on success, -ENOIOCTLCMD if no register | |
| 47 | + * access may be done by the caller (default read | |
| 48 | + * value is zero), else negative error code on error | |
| 38 | 49 | */ |
| 39 | 50 | struct smiapp_quirk { |
| 40 | 51 | int (*limits)(struct smiapp_sensor *sensor); |
| 41 | 52 | int (*post_poweron)(struct smiapp_sensor *sensor); |
| 42 | 53 | int (*pre_streamon)(struct smiapp_sensor *sensor); |
| 43 | 54 | int (*post_streamoff)(struct smiapp_sensor *sensor); |
| 44 | − const struct smia_reg *regs; | |
| 55 | + unsigned long (*pll_flags)(struct smiapp_sensor *sensor); | |
| 56 | + int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg, | |
| 57 | + u32 *val); | |
| 45 | 58 | unsigned long flags; |
| 46 | 59 | }; |
| 47 | 60 | |
| 48 | −/* op pix clock is for all lanes in total normally */ | |
| 49 | −#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) | |
| 50 | −#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY (1 << 1) | |
| 61 | +#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY (1 << 0) | |
| 51 | 62 | |
| 52 | 63 | struct smiapp_reg_8 { |
| 53 | 64 | u16 reg; |
| @@ -56,12 +67,9 @@ struct smiapp_reg_8 { · 2 unmodified lines | ||
| 56 | 67 | |
| 57 | 68 | void smiapp_replace_limit(struct smiapp_sensor *sensor, |
| 58 | 69 | u32 limit, u32 val); |
| 59 | −bool smiapp_quirk_reg(struct smiapp_sensor *sensor, | |
| 60 | − u32 reg, u32 *val); | |
| 61 | 70 | |
| 62 | −#define SMIAPP_MK_QUIRK_REG(_reg, _val) \ | |
| 71 | +#define SMIAPP_MK_QUIRK_REG_8(_reg, _val) \ | |
| 63 | 72 | { \ |
| 64 | − .type = (_reg >> 16), \ | |
| 65 | 73 | .reg = (u16)_reg, \ |
| 66 | 74 | .val = _val, \ |
| 67 | 75 | } |
| @@ -21,11 +21,11 @@ · 20 unmodified lines | ||
| 21 | 21 | * 02110-1301 USA |
| 22 | 22 | * |
| 23 | 23 | */ |
| 24 | −#define SMIAPP_REG_MK_U8(r) ((SMIA_REG_8BIT << 16) | (r)) | |
| 25 | −#define SMIAPP_REG_MK_U16(r) ((SMIA_REG_16BIT << 16) | (r)) | |
| 26 | −#define SMIAPP_REG_MK_U32(r) ((SMIA_REG_32BIT << 16) | (r)) | |
| 24 | +#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r)) | |
| 25 | +#define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r)) | |
| 26 | +#define SMIAPP_REG_MK_U32(r) ((SMIAPP_REG_32BIT << 16) | (r)) | |
| 27 | 27 | |
| 28 | −#define SMIAPP_REG_MK_F32(r) (SMIA_REG_FLAG_FLOAT | (SMIA_REG_32BIT << 16) | (r)) | |
| 28 | +#define SMIAPP_REG_MK_F32(r) (SMIAPP_REG_FLAG_FLOAT | (SMIAPP_REG_32BIT << 16) | (r)) | |
| 29 | 29 | |
| 30 | 30 | #define SMIAPP_REG_U16_MODEL_ID SMIAPP_REG_MK_U16(0x0000) |
| 31 | 31 | #define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR SMIAPP_REG_MK_U8(0x0002) |
| @@ -114,14 +114,14 @@ static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg, · 113 unmodified lines | ||
| 114 | 114 | *val = 0; |
| 115 | 115 | /* high byte comes first */ |
| 116 | 116 | switch (len) { |
| 117 | − case SMIA_REG_32BIT: | |
| 117 | + case SMIAPP_REG_32BIT: | |
| 118 | 118 | *val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + |
| 119 | 119 | data[3]; |
| 120 | 120 | break; |
| 121 | − case SMIA_REG_16BIT: | |
| 121 | + case SMIAPP_REG_16BIT: | |
| 122 | 122 | *val = (data[0] << 8) + data[1]; |
| 123 | 123 | break; |
| 124 | − case SMIA_REG_8BIT: | |
| 124 | + case SMIAPP_REG_8BIT: | |
| 125 | 125 | *val = data[0]; |
| 126 | 126 | break; |
| 127 | 127 | default: |
| @@ -165,31 +165,28 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val, · 37 unmodified lines | ||
| 165 | 165 | bool only8) |
| 166 | 166 | { |
| 167 | 167 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 168 | − unsigned int len = (u8)(reg >> 16); | |
| 168 | + u8 len = SMIAPP_REG_WIDTH(reg); | |
| 169 | 169 | int rval; |
| 170 | 170 | |
| 171 | − if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT | |
| 172 | − && len != SMIA_REG_32BIT) | |
| 171 | + if (len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT | |
| 172 | + && len != SMIAPP_REG_32BIT) | |
| 173 | 173 | return -EINVAL; |
| 174 | 174 | |
| 175 | − if (smiapp_quirk_reg(sensor, reg, val)) | |
| 176 | − goto found_quirk; | |
| 177 | − | |
| 178 | − if (len == SMIA_REG_8BIT && !only8) | |
| 179 | − rval = ____smiapp_read(sensor, (u16)reg, len, val); | |
| 175 | + if (len == SMIAPP_REG_8BIT || !only8) | |
| 176 | + rval = ____smiapp_read(sensor, SMIAPP_REG_ADDR(reg), len, val); | |
| 180 | 177 | else |
| 181 | − rval = ____smiapp_read_8only(sensor, (u16)reg, len, val); | |
| 178 | + rval = ____smiapp_read_8only(sensor, SMIAPP_REG_ADDR(reg), len, | |
| 179 | + val); | |
| 182 | 180 | if (rval < 0) |
| 183 | 181 | return rval; |
| 184 | 182 | |
| 185 | −found_quirk: | |
| 186 | − if (reg & SMIA_REG_FLAG_FLOAT) | |
| 183 | + if (reg & SMIAPP_REG_FLAG_FLOAT) | |
| 187 | 184 | *val = float_to_u32_mul_1000000(client, *val); |
| 188 | 185 | |
| 189 | 186 | return 0; |
| 190 | 187 | } |
| 191 | 188 | |
| 192 | −int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) | |
| 189 | +int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val) | |
| 193 | 190 | { |
| 194 | 191 | return __smiapp_read( |
| 195 | 192 | sensor, reg, val, |
| @@ -197,28 +194,47 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) · 1 unmodified line | ||
| 197 | 194 | SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY)); |
| 198 | 195 | } |
| 199 | 196 | |
| 197 | +int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) | |
| 198 | +{ | |
| 199 | + int rval; | |
| 200 | + | |
| 201 | + *val = 0; | |
| 202 | + rval = smiapp_call_quirk(sensor, reg_access, false, ®, val); | |
| 203 | + if (rval == -ENOIOCTLCMD) | |
| 204 | + return 0; | |
| 205 | + if (rval < 0) | |
| 206 | + return rval; | |
| 207 | + | |
| 208 | + return smiapp_read_no_quirk(sensor, reg, val); | |
| 209 | +} | |
| 210 | + | |
| 200 | 211 | int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val) |
| 201 | 212 | { |
| 213 | + int rval; | |
| 214 | + | |
| 215 | + *val = 0; | |
| 216 | + rval = smiapp_call_quirk(sensor, reg_access, false, ®, val); | |
| 217 | + if (rval == -ENOIOCTLCMD) | |
| 218 | + return 0; | |
| 219 | + if (rval < 0) | |
| 220 | + return rval; | |
| 221 | + | |
| 202 | 222 | return __smiapp_read(sensor, reg, val, true); |
| 203 | 223 | } |
| 204 | 224 | |
| 205 | −/* | |
| 206 | − * Write to a 8/16-bit register. | |
| 207 | − * Returns zero if successful, or non-zero otherwise. | |
| 208 | − */ | |
| 209 | −int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val) | |
| 225 | +int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val) | |
| 210 | 226 | { |
| 211 | 227 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); |
| 212 | 228 | struct i2c_msg msg; |
| 213 | 229 | unsigned char data[6]; |
| 214 | 230 | unsigned int retries; |
| 215 | − unsigned int flags = reg >> 24; | |
| 216 | − unsigned int len = (u8)(reg >> 16); | |
| 217 | − u16 offset = reg; | |
| 231 | + u8 flags = SMIAPP_REG_FLAGS(reg); | |
| 232 | + u8 len = SMIAPP_REG_WIDTH(reg); | |
| 233 | + u16 offset = SMIAPP_REG_ADDR(reg); | |
| 218 | 234 | int r; |
| 219 | 235 | |
| 220 | − if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT && | |
| 221 | − len != SMIA_REG_32BIT) || flags) | |
| 236 | + if ((len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT && | |
| 237 | + len != SMIAPP_REG_32BIT) || flags) | |
| 222 | 238 | return -EINVAL; |
| 223 | 239 | |
| 224 | 240 | msg.addr = client->addr; |
| @@ -231,14 +247,14 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val) · 6 unmodified lines | ||
| 231 | 247 | data[1] = (u8) (reg & 0xff); |
| 232 | 248 | |
| 233 | 249 | switch (len) { |
| 234 | − case SMIA_REG_8BIT: | |
| 250 | + case SMIAPP_REG_8BIT: | |
| 235 | 251 | data[2] = val; |
| 236 | 252 | break; |
| 237 | − case SMIA_REG_16BIT: | |
| 253 | + case SMIAPP_REG_16BIT: | |
| 238 | 254 | data[2] = val >> 8; |
| 239 | 255 | data[3] = val; |
| 240 | 256 | break; |
| 241 | − case SMIA_REG_32BIT: | |
| 257 | + case SMIAPP_REG_32BIT: | |
| 242 | 258 | data[2] = val >> 24; |
| 243 | 259 | data[3] = val >> 16; |
| 244 | 260 | data[4] = val >> 8; |
| @@ -271,3 +287,20 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val) · 26 unmodified lines | ||
| 271 | 287 | |
| 272 | 288 | return r; |
| 273 | 289 | } |
| 290 | + | |
| 291 | +/* | |
| 292 | + * Write to a 8/16-bit register. | |
| 293 | + * Returns zero if successful, or non-zero otherwise. | |
| 294 | + */ | |
| 295 | +int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val) | |
| 296 | +{ | |
| 297 | + int rval; | |
| 298 | + | |
| 299 | + rval = smiapp_call_quirk(sensor, reg_access, true, ®, &val); | |
| 300 | + if (rval == -ENOIOCTLCMD) | |
| 301 | + return 0; | |
| 302 | + if (rval < 0) | |
| 303 | + return rval; | |
| 304 | + | |
| 305 | + return smiapp_write_no_quirk(sensor, reg, val); | |
| 306 | +} | |
| @@ -28,22 +28,23 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/i2c.h> |
| 29 | 29 | #include <linux/types.h> |
| 30 | 30 | |
| 31 | +#define SMIAPP_REG_ADDR(reg) ((u16)reg) | |
| 32 | +#define SMIAPP_REG_WIDTH(reg) ((u8)(reg >> 16)) | |
| 33 | +#define SMIAPP_REG_FLAGS(reg) ((u8)(reg >> 24)) | |
| 34 | + | |
| 31 | 35 | /* Use upper 8 bits of the type field for flags */ |
| 32 | −#define SMIA_REG_FLAG_FLOAT (1 << 24) | |
| 36 | +#define SMIAPP_REG_FLAG_FLOAT (1 << 24) | |
| 33 | 37 | |
| 34 | −#define SMIA_REG_8BIT 1 | |
| 35 | −#define SMIA_REG_16BIT 2 | |
| 36 | −#define SMIA_REG_32BIT 4 | |
| 37 | −struct smia_reg { | |
| 38 | − u16 type; | |
| 39 | − u16 reg; /* 16-bit offset */ | |
| 40 | − u32 val; /* 8/16/32-bit value */ | |
| 41 | −}; | |
| 38 | +#define SMIAPP_REG_8BIT 1 | |
| 39 | +#define SMIAPP_REG_16BIT 2 | |
| 40 | +#define SMIAPP_REG_32BIT 4 | |
| 42 | 41 | |
| 43 | 42 | struct smiapp_sensor; |
| 44 | 43 | |
| 44 | +int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val); | |
| 45 | 45 | int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val); |
| 46 | 46 | int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val); |
| 47 | +int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val); | |
| 47 | 48 | int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val); |
| 48 | 49 | |
| 49 | 50 | #endif |
| @@ -814,8 +814,6 @@ done: · 813 unmodified lines | ||
| 814 | 814 | } |
| 815 | 815 | |
| 816 | 816 | static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { |
| 817 | − .s_std = tw9910_s_std, | |
| 818 | − .g_std = tw9910_g_std, | |
| 819 | 817 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 820 | 818 | .g_register = tw9910_g_register, |
| 821 | 819 | .s_register = tw9910_s_register, |
| @@ -872,7 +870,15 @@ static int tw9910_s_mbus_config(struct v4l2_subdev *sd, · 50 unmodified lines | ||
| 872 | 870 | return i2c_smbus_write_byte_data(client, OUTCTR1, val); |
| 873 | 871 | } |
| 874 | 872 | |
| 873 | +static int tw9910_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm) | |
| 874 | +{ | |
| 875 | + *norm = V4L2_STD_NTSC | V4L2_STD_PAL; | |
| 876 | + return 0; | |
| 877 | +} | |
| 878 | + | |
| 875 | 879 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { |
| 880 | + .s_std = tw9910_s_std, | |
| 881 | + .g_std = tw9910_g_std, | |
| 876 | 882 | .s_stream = tw9910_s_stream, |
| 877 | 883 | .g_mbus_fmt = tw9910_g_fmt, |
| 878 | 884 | .s_mbus_fmt = tw9910_s_fmt, |
| @@ -882,6 +888,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { · 3 unmodified lines | ||
| 882 | 888 | .enum_mbus_fmt = tw9910_enum_fmt, |
| 883 | 889 | .g_mbus_config = tw9910_g_mbus_config, |
| 884 | 890 | .s_mbus_config = tw9910_s_mbus_config, |
| 891 | + .g_tvnorms = tw9910_g_tvnorms, | |
| 885 | 892 | }; |
| 886 | 893 | |
| 887 | 894 | static struct v4l2_subdev_ops tw9910_subdev_ops = { |
| @@ -327,18 +327,18 @@ static int sony_btf_mpx_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner · 326 unmodified lines | ||
| 327 | 327 | |
| 328 | 328 | /* --------------------------------------------------------------------------*/ |
| 329 | 329 | |
| 330 | −static const struct v4l2_subdev_core_ops sony_btf_mpx_core_ops = { | |
| 331 | − .s_std = sony_btf_mpx_s_std, | |
| 332 | −}; | |
| 333 | − | |
| 334 | 330 | static const struct v4l2_subdev_tuner_ops sony_btf_mpx_tuner_ops = { |
| 335 | 331 | .s_tuner = sony_btf_mpx_s_tuner, |
| 336 | 332 | .g_tuner = sony_btf_mpx_g_tuner, |
| 337 | 333 | }; |
| 338 | 334 | |
| 335 | +static const struct v4l2_subdev_video_ops sony_btf_mpx_video_ops = { | |
| 336 | + .s_std = sony_btf_mpx_s_std, | |
| 337 | +}; | |
| 338 | + | |
| 339 | 339 | static const struct v4l2_subdev_ops sony_btf_mpx_ops = { |
| 340 | − .core = &sony_btf_mpx_core_ops, | |
| 341 | 340 | .tuner = &sony_btf_mpx_tuner_ops, |
| 341 | + .video = &sony_btf_mpx_video_ops, | |
| 342 | 342 | }; |
| 343 | 343 | |
| 344 | 344 | /* --------------------------------------------------------------------------*/ |
| @@ -410,6 +410,9 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd, · 409 unmodified lines | ||
| 410 | 410 | static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, |
| 411 | 411 | struct v4l2_enum_dv_timings *timings) |
| 412 | 412 | { |
| 413 | + if (timings->pad != 0) | |
| 414 | + return -EINVAL; | |
| 415 | + | |
| 413 | 416 | return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap, |
| 414 | 417 | NULL, NULL); |
| 415 | 418 | } |
| @@ -417,6 +420,9 @@ static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, · 1 unmodified line | ||
| 417 | 420 | static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, |
| 418 | 421 | struct v4l2_dv_timings_cap *cap) |
| 419 | 422 | { |
| 423 | + if (cap->pad != 0) | |
| 424 | + return -EINVAL; | |
| 425 | + | |
| 420 | 426 | *cap = ths8200_timings_cap; |
| 421 | 427 | return 0; |
| 422 | 428 | } |
| @@ -426,6 +432,9 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = { · 3 unmodified lines | ||
| 426 | 432 | .s_stream = ths8200_s_stream, |
| 427 | 433 | .s_dv_timings = ths8200_s_dv_timings, |
| 428 | 434 | .g_dv_timings = ths8200_g_dv_timings, |
| 435 | +}; | |
| 436 | + | |
| 437 | +static const struct v4l2_subdev_pad_ops ths8200_pad_ops = { | |
| 429 | 438 | .enum_dv_timings = ths8200_enum_dv_timings, |
| 430 | 439 | .dv_timings_cap = ths8200_dv_timings_cap, |
| 431 | 440 | }; |
| @@ -434,6 +443,7 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = { · 2 unmodified lines | ||
| 434 | 443 | static const struct v4l2_subdev_ops ths8200_ops = { |
| 435 | 444 | .core = &ths8200_core_ops, |
| 436 | 445 | .video = &ths8200_video_ops, |
| 446 | + .pad = &ths8200_pad_ops, | |
| 437 | 447 | }; |
| 438 | 448 | |
| 439 | 449 | static int ths8200_probe(struct i2c_client *client, |
| @@ -1862,7 +1862,6 @@ static const struct v4l2_subdev_core_ops tvaudio_core_ops = { · 1861 unmodified lines | ||
| 1862 | 1862 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 1863 | 1863 | .queryctrl = v4l2_subdev_queryctrl, |
| 1864 | 1864 | .querymenu = v4l2_subdev_querymenu, |
| 1865 | − .s_std = tvaudio_s_std, | |
| 1866 | 1865 | }; |
| 1867 | 1866 | |
| 1868 | 1867 | static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { |
| @@ -1876,10 +1875,15 @@ static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = { · 7 unmodified lines | ||
| 1876 | 1875 | .s_routing = tvaudio_s_routing, |
| 1877 | 1876 | }; |
| 1878 | 1877 | |
| 1878 | +static const struct v4l2_subdev_video_ops tvaudio_video_ops = { | |
| 1879 | + .s_std = tvaudio_s_std, | |
| 1880 | +}; | |
| 1881 | + | |
| 1879 | 1882 | static const struct v4l2_subdev_ops tvaudio_ops = { |
| 1880 | 1883 | .core = &tvaudio_core_ops, |
| 1881 | 1884 | .tuner = &tvaudio_tuner_ops, |
| 1882 | 1885 | .audio = &tvaudio_audio_ops, |
| 1886 | + .video = &tvaudio_video_ops, | |
| 1883 | 1887 | }; |
| 1884 | 1888 | |
| 1885 | 1889 | /* ----------------------------------------------------------------------- */ |
| @@ -1010,10 +1010,10 @@ static const struct v4l2_subdev_core_ops tvp514x_core_ops = { · 1009 unmodified lines | ||
| 1010 | 1010 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 1011 | 1011 | .queryctrl = v4l2_subdev_queryctrl, |
| 1012 | 1012 | .querymenu = v4l2_subdev_querymenu, |
| 1013 | − .s_std = tvp514x_s_std, | |
| 1014 | 1013 | }; |
| 1015 | 1014 | |
| 1016 | 1015 | static const struct v4l2_subdev_video_ops tvp514x_video_ops = { |
| 1016 | + .s_std = tvp514x_s_std, | |
| 1017 | 1017 | .s_routing = tvp514x_s_routing, |
| 1018 | 1018 | .querystd = tvp514x_querystd, |
| 1019 | 1019 | .enum_mbus_fmt = tvp514x_enum_mbus_fmt, |
| @@ -913,7 +913,7 @@ static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) · 912 unmodified lines | ||
| 913 | 913 | |
| 914 | 914 | static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
| 915 | 915 | { |
| 916 | − struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | |
| 916 | + struct tvp5150 *decoder = to_tvp5150(sd); | |
| 917 | 917 | |
| 918 | 918 | a->c = decoder->rect; |
| 919 | 919 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| @@ -923,7 +923,7 @@ static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) · 3 unmodified lines | ||
| 923 | 923 | |
| 924 | 924 | static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) |
| 925 | 925 | { |
| 926 | − struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | |
| 926 | + struct tvp5150 *decoder = to_tvp5150(sd); | |
| 927 | 927 | v4l2_std_id std; |
| 928 | 928 | |
| 929 | 929 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| @@ -1063,7 +1063,6 @@ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { · 133 unmodified lines | ||
| 1063 | 1063 | |
| 1064 | 1064 | static const struct v4l2_subdev_core_ops tvp5150_core_ops = { |
| 1065 | 1065 | .log_status = tvp5150_log_status, |
| 1066 | − .s_std = tvp5150_s_std, | |
| 1067 | 1066 | .reset = tvp5150_reset, |
| 1068 | 1067 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 1069 | 1068 | .g_register = tvp5150_g_register, |
| @@ -1076,6 +1075,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { · 6 unmodified lines | ||
| 1076 | 1075 | }; |
| 1077 | 1076 | |
| 1078 | 1077 | static const struct v4l2_subdev_video_ops tvp5150_video_ops = { |
| 1078 | + .s_std = tvp5150_s_std, | |
| 1079 | 1079 | .s_routing = tvp5150_s_routing, |
| 1080 | 1080 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, |
| 1081 | 1081 | .s_mbus_fmt = tvp5150_mbus_fmt, |
| @@ -833,6 +833,9 @@ static int tvp7002_log_status(struct v4l2_subdev *sd) · 832 unmodified lines | ||
| 833 | 833 | static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd, |
| 834 | 834 | struct v4l2_enum_dv_timings *timings) |
| 835 | 835 | { |
| 836 | + if (timings->pad != 0) | |
| 837 | + return -EINVAL; | |
| 838 | + | |
| 836 | 839 | /* Check requested format index is within range */ |
| 837 | 840 | if (timings->index >= NUM_TIMINGS) |
| 838 | 841 | return -EINVAL; |
| @@ -924,7 +927,6 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { · 85 unmodified lines | ||
| 924 | 927 | static const struct v4l2_subdev_video_ops tvp7002_video_ops = { |
| 925 | 928 | .g_dv_timings = tvp7002_g_dv_timings, |
| 926 | 929 | .s_dv_timings = tvp7002_s_dv_timings, |
| 927 | − .enum_dv_timings = tvp7002_enum_dv_timings, | |
| 928 | 930 | .query_dv_timings = tvp7002_query_dv_timings, |
| 929 | 931 | .s_stream = tvp7002_s_stream, |
| 930 | 932 | .g_mbus_fmt = tvp7002_mbus_fmt, |
| @@ -938,6 +940,7 @@ static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = { · 7 unmodified lines | ||
| 938 | 940 | .enum_mbus_code = tvp7002_enum_mbus_code, |
| 939 | 941 | .get_fmt = tvp7002_get_pad_format, |
| 940 | 942 | .set_fmt = tvp7002_set_pad_format, |
| 943 | + .enum_dv_timings = tvp7002_enum_dv_timings, | |
| 941 | 944 | }; |
| 942 | 945 | |
| 943 | 946 | /* V4L2 top level operation handlers */ |
| @@ -342,12 +342,12 @@ static const struct v4l2_ctrl_ops tw2804_ctrl_ops = { · 341 unmodified lines | ||
| 342 | 342 | }; |
| 343 | 343 | |
| 344 | 344 | static const struct v4l2_subdev_video_ops tw2804_video_ops = { |
| 345 | + .s_std = tw2804_s_std, | |
| 345 | 346 | .s_routing = tw2804_s_video_routing, |
| 346 | 347 | }; |
| 347 | 348 | |
| 348 | 349 | static const struct v4l2_subdev_core_ops tw2804_core_ops = { |
| 349 | 350 | .log_status = tw2804_log_status, |
| 350 | − .s_std = tw2804_s_std, | |
| 351 | 351 | }; |
| 352 | 352 | |
| 353 | 353 | static const struct v4l2_subdev_ops tw2804_ops = { |
| @@ -187,10 +187,10 @@ static const struct v4l2_ctrl_ops tw9903_ctrl_ops = { · 186 unmodified lines | ||
| 187 | 187 | |
| 188 | 188 | static const struct v4l2_subdev_core_ops tw9903_core_ops = { |
| 189 | 189 | .log_status = tw9903_log_status, |
| 190 | − .s_std = tw9903_s_std, | |
| 191 | 190 | }; |
| 192 | 191 | |
| 193 | 192 | static const struct v4l2_subdev_video_ops tw9903_video_ops = { |
| 193 | + .s_std = tw9903_s_std, | |
| 194 | 194 | .s_routing = tw9903_s_video_routing, |
| 195 | 195 | }; |
| 196 | 196 | |
| @@ -157,10 +157,10 @@ static const struct v4l2_ctrl_ops tw9906_ctrl_ops = { · 156 unmodified lines | ||
| 157 | 157 | |
| 158 | 158 | static const struct v4l2_subdev_core_ops tw9906_core_ops = { |
| 159 | 159 | .log_status = tw9906_log_status, |
| 160 | − .s_std = tw9906_s_std, | |
| 161 | 160 | }; |
| 162 | 161 | |
| 163 | 162 | static const struct v4l2_subdev_video_ops tw9906_video_ops = { |
| 163 | + .s_std = tw9906_s_std, | |
| 164 | 164 | .s_routing = tw9906_s_video_routing, |
| 165 | 165 | }; |
| 166 | 166 | |
| @@ -124,7 +124,6 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) · 123 unmodified lines | ||
| 124 | 124 | |
| 125 | 125 | static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { |
| 126 | 126 | .log_status = vp27smpx_log_status, |
| 127 | − .s_std = vp27smpx_s_std, | |
| 128 | 127 | }; |
| 129 | 128 | |
| 130 | 129 | static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = { |
| @@ -133,9 +132,14 @@ static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = { · 2 unmodified lines | ||
| 133 | 132 | .g_tuner = vp27smpx_g_tuner, |
| 134 | 133 | }; |
| 135 | 134 | |
| 135 | +static const struct v4l2_subdev_video_ops vp27smpx_video_ops = { | |
| 136 | + .s_std = vp27smpx_s_std, | |
| 137 | +}; | |
| 138 | + | |
| 136 | 139 | static const struct v4l2_subdev_ops vp27smpx_ops = { |
| 137 | 140 | .core = &vp27smpx_core_ops, |
| 138 | 141 | .tuner = &vp27smpx_tuner_ops, |
| 142 | + .video = &vp27smpx_video_ops, | |
| 139 | 143 | }; |
| 140 | 144 | |
| 141 | 145 | /* ----------------------------------------------------------------------- */ |
| @@ -457,10 +457,10 @@ static const struct v4l2_subdev_core_ops vpx3220_core_ops = { · 456 unmodified lines | ||
| 457 | 457 | .s_ctrl = v4l2_subdev_s_ctrl, |
| 458 | 458 | .queryctrl = v4l2_subdev_queryctrl, |
| 459 | 459 | .querymenu = v4l2_subdev_querymenu, |
| 460 | − .s_std = vpx3220_s_std, | |
| 461 | 460 | }; |
| 462 | 461 | |
| 463 | 462 | static const struct v4l2_subdev_video_ops vpx3220_video_ops = { |
| 463 | + .s_std = vpx3220_s_std, | |
| 464 | 464 | .s_routing = vpx3220_s_routing, |
| 465 | 465 | .s_stream = vpx3220_s_stream, |
| 466 | 466 | .querystd = vpx3220_querystd, |
| @@ -373,7 +373,8 @@ static void media_device_release(struct media_devnode *mdev) · 372 unmodified lines | ||
| 373 | 373 | * - dev must point to the parent device |
| 374 | 374 | * - model must be filled with the device model name |
| 375 | 375 | */ |
| 376 | −int __must_check media_device_register(struct media_device *mdev) | |
| 376 | +int __must_check __media_device_register(struct media_device *mdev, | |
| 377 | + struct module *owner) | |
| 377 | 378 | { |
| 378 | 379 | int ret; |
| 379 | 380 | |
| @@ -389,7 +390,7 @@ int __must_check media_device_register(struct media_device *mdev) · 9 unmodified lines | ||
| 389 | 390 | mdev->devnode.fops = &media_device_fops; |
| 390 | 391 | mdev->devnode.parent = mdev->dev; |
| 391 | 392 | mdev->devnode.release = media_device_release; |
| 392 | − ret = media_devnode_register(&mdev->devnode); | |
| 393 | + ret = media_devnode_register(&mdev->devnode, owner); | |
| 393 | 394 | if (ret < 0) |
| 394 | 395 | return ret; |
| 395 | 396 | |
| @@ -401,7 +402,7 @@ int __must_check media_device_register(struct media_device *mdev) · 5 unmodified lines | ||
| 401 | 402 | |
| 402 | 403 | return 0; |
| 403 | 404 | } |
| 404 | −EXPORT_SYMBOL_GPL(media_device_register); | |
| 405 | +EXPORT_SYMBOL_GPL(__media_device_register); | |
| 405 | 406 | |
| 406 | 407 | /** |
| 407 | 408 | * media_device_unregister - unregister a media device |
| @@ -232,7 +232,8 @@ static const struct file_operations media_devnode_fops = { · 231 unmodified lines | ||
| 232 | 232 | * the media_devnode structure is *not* called, so the caller is responsible for |
| 233 | 233 | * freeing any data. |
| 234 | 234 | */ |
| 235 | −int __must_check media_devnode_register(struct media_devnode *mdev) | |
| 235 | +int __must_check media_devnode_register(struct media_devnode *mdev, | |
| 236 | + struct module *owner) | |
| 236 | 237 | { |
| 237 | 238 | int minor; |
| 238 | 239 | int ret; |
| @@ -253,7 +254,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev) · 14 unmodified lines | ||
| 253 | 254 | |
| 254 | 255 | /* Part 2: Initialize and register the character device */ |
| 255 | 256 | cdev_init(&mdev->cdev, &media_devnode_fops); |
| 256 | − mdev->cdev.owner = mdev->fops->owner; | |
| 257 | + mdev->cdev.owner = owner; | |
| 257 | 258 | |
| 258 | 259 | ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1); |
| 259 | 260 | if (ret < 0) { |
| @@ -937,7 +937,7 @@ static struct qcam *qcam_init(struct parport *port) · 936 unmodified lines | ||
| 937 | 937 | return NULL; |
| 938 | 938 | |
| 939 | 939 | v4l2_dev = &qcam->v4l2_dev; |
| 940 | − snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%d", num_cams); | |
| 940 | + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%u", num_cams); | |
| 941 | 941 | |
| 942 | 942 | if (v4l2_device_register(port->dev, v4l2_dev) < 0) { |
| 943 | 943 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); |
| @@ -52,6 +52,7 @@ static void osprey_eeprom(struct bttv *btv, const u8 ee[256]); · 51 unmodified lines | ||
| 52 | 52 | static void modtec_eeprom(struct bttv *btv); |
| 53 | 53 | static void init_PXC200(struct bttv *btv); |
| 54 | 54 | static void init_RTV24(struct bttv *btv); |
| 55 | +static void init_PCI8604PW(struct bttv *btv); | |
| 55 | 56 | |
| 56 | 57 | static void rv605_muxsel(struct bttv *btv, unsigned int input); |
| 57 | 58 | static void eagle_muxsel(struct bttv *btv, unsigned int input); |
| @@ -2871,6 +2872,22 @@ struct tvcard bttv_tvcards[] = { · 2813 unmodified lines | ||
| 2871 | 2872 | .has_remote = 1, |
| 2872 | 2873 | .has_radio = 1, |
| 2873 | 2874 | }, |
| 2875 | + /* ---- card 0xa6---------------------------------- */ | |
| 2876 | + [BTTV_BOARD_PCI_8604PW] = { | |
| 2877 | + /* PCI-8604PW with special unlock sequence */ | |
| 2878 | + .name = "PCI-8604PW", | |
| 2879 | + .video_inputs = 2, | |
| 2880 | + /* .audio_inputs= 0, */ | |
| 2881 | + .svhs = NO_SVHS, | |
| 2882 | + /* The second input is available on CN4, if populated. | |
| 2883 | + * The other 5x2 header (CN2?) connects to the same inputs | |
| 2884 | + * as the on-board BNCs */ | |
| 2885 | + .muxsel = MUXSEL(2, 3), | |
| 2886 | + .tuner_type = TUNER_ABSENT, | |
| 2887 | + .no_msp34xx = 1, | |
| 2888 | + .no_tda7432 = 1, | |
| 2889 | + .pll = PLL_35, | |
| 2890 | + }, | |
| 2874 | 2891 | }; |
| 2875 | 2892 | |
| 2876 | 2893 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
| @@ -3305,6 +3322,9 @@ void bttv_init_card1(struct bttv *btv) · 428 unmodified lines | ||
| 3305 | 3322 | case BTTV_BOARD_ADLINK_RTV24: |
| 3306 | 3323 | init_RTV24( btv ); |
| 3307 | 3324 | break; |
| 3325 | + case BTTV_BOARD_PCI_8604PW: | |
| 3326 | + init_PCI8604PW(btv); | |
| 3327 | + break; | |
| 3308 | 3328 | |
| 3309 | 3329 | } |
| 3310 | 3330 | if (!bttv_tvcards[btv->c.type].has_dvb) |
| @@ -4184,6 +4204,96 @@ init_RTV24 (struct bttv *btv) · 873 unmodified lines | ||
| 4184 | 4204 | |
| 4185 | 4205 | |
| 4186 | 4206 | |
| 4207 | +/* ----------------------------------------------------------------------- */ | |
| 4208 | +/* | |
| 4209 | + * The PCI-8604PW contains a CPLD, probably an ispMACH 4A, that filters | |
| 4210 | + * the PCI REQ signals comming from the four BT878 chips. After power | |
| 4211 | + * up, the CPLD does not forward requests to the bus, which prevents | |
| 4212 | + * the BT878 from fetching RISC instructions from memory. While the | |
| 4213 | + * CPLD is connected to most of the GPIOs of PCI device 0xD, only | |
| 4214 | + * five appear to play a role in unlocking the REQ signal. The following | |
| 4215 | + * sequence has been determined by trial and error without access to the | |
| 4216 | + * original driver. | |
| 4217 | + * | |
| 4218 | + * Eight GPIOs of device 0xC are provided on connector CN4 (4 in, 4 out). | |
| 4219 | + * Devices 0xE and 0xF do not appear to have anything connected to their | |
| 4220 | + * GPIOs. | |
| 4221 | + * | |
| 4222 | + * The correct GPIO_OUT_EN value might have some more bits set. It should | |
| 4223 | + * be possible to derive it from a boundary scan of the CPLD. Its JTAG | |
| 4224 | + * pins are routed to test points. | |
| 4225 | + * | |
| 4226 | + */ | |
| 4227 | +/* ----------------------------------------------------------------------- */ | |
| 4228 | +static void | |
| 4229 | +init_PCI8604PW(struct bttv *btv) | |
| 4230 | +{ | |
| 4231 | + int state; | |
| 4232 | + | |
| 4233 | + if ((PCI_SLOT(btv->c.pci->devfn) & ~3) != 0xC) { | |
| 4234 | + pr_warn("This is not a PCI-8604PW\n"); | |
| 4235 | + return; | |
| 4236 | + } | |
| 4237 | + | |
| 4238 | + if (PCI_SLOT(btv->c.pci->devfn) != 0xD) | |
| 4239 | + return; | |
| 4240 | + | |
| 4241 | + btwrite(0x080002, BT848_GPIO_OUT_EN); | |
| 4242 | + | |
| 4243 | + state = (btread(BT848_GPIO_DATA) >> 21) & 7; | |
| 4244 | + | |
| 4245 | + for (;;) { | |
| 4246 | + switch (state) { | |
| 4247 | + case 1: | |
| 4248 | + case 5: | |
| 4249 | + case 6: | |
| 4250 | + case 4: | |
| 4251 | + pr_debug("PCI-8604PW in state %i, toggling pin\n", | |
| 4252 | + state); | |
| 4253 | + btwrite(0x080000, BT848_GPIO_DATA); | |
| 4254 | + msleep(1); | |
| 4255 | + btwrite(0x000000, BT848_GPIO_DATA); | |
| 4256 | + msleep(1); | |
| 4257 | + break; | |
| 4258 | + case 7: | |
| 4259 | + pr_info("PCI-8604PW unlocked\n"); | |
| 4260 | + return; | |
| 4261 | + case 0: | |
| 4262 | + /* FIXME: If we are in state 7 and toggle GPIO[19] one | |
| 4263 | + more time, the CPLD goes into state 0, where PCI bus | |
| 4264 | + mastering is inhibited again. We have not managed to | |
| 4265 | + get out of that state. */ | |
| 4266 | + | |
| 4267 | + pr_err("PCI-8604PW locked until reset\n"); | |
| 4268 | + return; | |
| 4269 | + default: | |
| 4270 | + pr_err("PCI-8604PW in unknown state %i\n", state); | |
| 4271 | + return; | |
| 4272 | + } | |
| 4273 | + | |
| 4274 | + state = (state << 4) | ((btread(BT848_GPIO_DATA) >> 21) & 7); | |
| 4275 | + | |
| 4276 | + switch (state) { | |
| 4277 | + case 0x15: | |
| 4278 | + case 0x56: | |
| 4279 | + case 0x64: | |
| 4280 | + case 0x47: | |
| 4281 | + /* The transition from state 7 to state 0 is, as explained | |
| 4282 | + above, valid but undesired and with this code impossible | |
| 4283 | + as we exit as soon as we are in state 7. | |
| 4284 | + case 0x70: */ | |
| 4285 | + break; | |
| 4286 | + default: | |
| 4287 | + pr_err("PCI-8604PW invalid transition %i -> %i\n", | |
| 4288 | + state >> 4, state & 7); | |
| 4289 | + return; | |
| 4290 | + } | |
| 4291 | + state &= 7; | |
| 4292 | + } | |
| 4293 | +} | |
| 4294 | + | |
| 4295 | + | |
| 4296 | + | |
| 4187 | 4297 | /* ----------------------------------------------------------------------- */ |
| 4188 | 4298 | /* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ |
| 4189 | 4299 | /* |
| @@ -1182,7 +1182,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) · 1181 unmodified lines | ||
| 1182 | 1182 | break; |
| 1183 | 1183 | } |
| 1184 | 1184 | id = tvnorm->v4l2_id; |
| 1185 | − bttv_call_all(btv, core, s_std, id); | |
| 1185 | + bttv_call_all(btv, video, s_std, id); | |
| 1186 | 1186 | |
| 1187 | 1187 | return 0; |
| 1188 | 1188 | } |
| @@ -189,6 +189,7 @@ · 188 unmodified lines | ||
| 189 | 189 | #define BTTV_BOARD_BT848_CAP_14 0xa3 |
| 190 | 190 | #define BTTV_BOARD_CYBERVISION_CV06 0xa4 |
| 191 | 191 | #define BTTV_BOARD_KWORLD_VSTREAM_XPERT 0xa5 |
| 192 | +#define BTTV_BOARD_PCI_8604PW 0xa6 | |
| 192 | 193 | |
| 193 | 194 | /* more card-specific defines */ |
| 194 | 195 | #define PT2254_L_CHANNEL 0x10 |
| @@ -1544,7 +1544,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) · 1543 unmodified lines | ||
| 1544 | 1544 | } |
| 1545 | 1545 | |
| 1546 | 1546 | |
| 1547 | −static int dst_init(struct dvb_frontend *fe) | |
| 1547 | +static int bt8xx_dst_init(struct dvb_frontend *fe) | |
| 1548 | 1548 | { |
| 1549 | 1549 | struct dst_state *state = fe->demodulator_priv; |
| 1550 | 1550 | |
| @@ -1707,7 +1707,7 @@ static int dst_get_frontend(struct dvb_frontend *fe) · 156 unmodified lines | ||
| 1707 | 1707 | return 0; |
| 1708 | 1708 | } |
| 1709 | 1709 | |
| 1710 | −static void dst_release(struct dvb_frontend *fe) | |
| 1710 | +static void bt8xx_dst_release(struct dvb_frontend *fe) | |
| 1711 | 1711 | { |
| 1712 | 1712 | struct dst_state *state = fe->demodulator_priv; |
| 1713 | 1713 | if (state->dst_ca) { |
| @@ -1776,8 +1776,8 @@ static struct dvb_frontend_ops dst_dvbt_ops = { · 62 unmodified lines | ||
| 1776 | 1776 | FE_CAN_GUARD_INTERVAL_AUTO |
| 1777 | 1777 | }, |
| 1778 | 1778 | |
| 1779 | − .release = dst_release, | |
| 1780 | − .init = dst_init, | |
| 1779 | + .release = bt8xx_dst_release, | |
| 1780 | + .init = bt8xx_dst_init, | |
| 1781 | 1781 | .tune = dst_tune_frontend, |
| 1782 | 1782 | .set_frontend = dst_set_frontend, |
| 1783 | 1783 | .get_frontend = dst_get_frontend, |
| @@ -1801,8 +1801,8 @@ static struct dvb_frontend_ops dst_dvbs_ops = { · 17 unmodified lines | ||
| 1801 | 1801 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK |
| 1802 | 1802 | }, |
| 1803 | 1803 | |
| 1804 | − .release = dst_release, | |
| 1805 | − .init = dst_init, | |
| 1804 | + .release = bt8xx_dst_release, | |
| 1805 | + .init = bt8xx_dst_init, | |
| 1806 | 1806 | .tune = dst_tune_frontend, |
| 1807 | 1807 | .set_frontend = dst_set_frontend, |
| 1808 | 1808 | .get_frontend = dst_get_frontend, |
| @@ -1834,8 +1834,8 @@ static struct dvb_frontend_ops dst_dvbc_ops = { · 25 unmodified lines | ||
| 1834 | 1834 | FE_CAN_QAM_256 |
| 1835 | 1835 | }, |
| 1836 | 1836 | |
| 1837 | − .release = dst_release, | |
| 1838 | − .init = dst_init, | |
| 1837 | + .release = bt8xx_dst_release, | |
| 1838 | + .init = bt8xx_dst_init, | |
| 1839 | 1839 | .tune = dst_tune_frontend, |
| 1840 | 1840 | .set_frontend = dst_set_frontend, |
| 1841 | 1841 | .get_frontend = dst_get_frontend, |
| @@ -1857,8 +1857,8 @@ static struct dvb_frontend_ops dst_atsc_ops = { · 15 unmodified lines | ||
| 1857 | 1857 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB |
| 1858 | 1858 | }, |
| 1859 | 1859 | |
| 1860 | − .release = dst_release, | |
| 1861 | − .init = dst_init, | |
| 1860 | + .release = bt8xx_dst_release, | |
| 1861 | + .init = bt8xx_dst_init, | |
| 1862 | 1862 | .tune = dst_tune_frontend, |
| 1863 | 1863 | .set_frontend = dst_set_frontend, |
| 1864 | 1864 | .get_frontend = dst_get_frontend, |
| @@ -1263,7 +1263,6 @@ static const struct v4l2_subdev_core_ops cx18_av_general_ops = { · 1262 unmodified lines | ||
| 1263 | 1263 | .log_status = cx18_av_log_status, |
| 1264 | 1264 | .load_fw = cx18_av_load_fw, |
| 1265 | 1265 | .reset = cx18_av_reset, |
| 1266 | − .s_std = cx18_av_s_std, | |
| 1267 | 1266 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 1268 | 1267 | .g_register = cx18_av_g_register, |
| 1269 | 1268 | .s_register = cx18_av_s_register, |
| @@ -1283,6 +1282,7 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { · 13 unmodified lines | ||
| 1283 | 1282 | }; |
| 1284 | 1283 | |
| 1285 | 1284 | static const struct v4l2_subdev_video_ops cx18_av_video_ops = { |
| 1285 | + .s_std = cx18_av_s_std, | |
| 1286 | 1286 | .s_routing = cx18_av_s_video_routing, |
| 1287 | 1287 | .s_stream = cx18_av_s_stream, |
| 1288 | 1288 | .s_mbus_fmt = cx18_av_s_mbus_fmt, |
| @@ -760,7 +760,7 @@ int cx18_v4l2_close(struct file *filp) · 759 unmodified lines | ||
| 760 | 760 | /* Mark that the radio is no longer in use */ |
| 761 | 761 | clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags); |
| 762 | 762 | /* Switch tuner to TV */ |
| 763 | − cx18_call_all(cx, core, s_std, cx->std); | |
| 763 | + cx18_call_all(cx, video, s_std, cx->std); | |
| 764 | 764 | /* Select correct audio input (i.e. TV tuner or Line in) */ |
| 765 | 765 | cx18_audio_set_io(cx); |
| 766 | 766 | if (atomic_read(&cx->ana_capturing) > 0) { |
| @@ -180,7 +180,6 @@ static int gpiomux_s_audio_routing(struct v4l2_subdev *sd, · 179 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | static const struct v4l2_subdev_core_ops gpiomux_core_ops = { |
| 182 | 182 | .log_status = gpiomux_log_status, |
| 183 | − .s_std = gpiomux_s_std, | |
| 184 | 183 | }; |
| 185 | 184 | |
| 186 | 185 | static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = { |
| @@ -191,10 +190,15 @@ static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = { · 4 unmodified lines | ||
| 191 | 190 | .s_routing = gpiomux_s_audio_routing, |
| 192 | 191 | }; |
| 193 | 192 | |
| 193 | +static const struct v4l2_subdev_video_ops gpiomux_video_ops = { | |
| 194 | + .s_std = gpiomux_s_std, | |
| 195 | +}; | |
| 196 | + | |
| 194 | 197 | static const struct v4l2_subdev_ops gpiomux_ops = { |
| 195 | 198 | .core = &gpiomux_core_ops, |
| 196 | 199 | .tuner = &gpiomux_tuner_ops, |
| 197 | 200 | .audio = &gpiomux_audio_ops, |
| 201 | + .video = &gpiomux_video_ops, | |
| 198 | 202 | }; |
| 199 | 203 | |
| 200 | 204 | /* |
| @@ -602,7 +602,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id std) · 601 unmodified lines | ||
| 602 | 602 | (unsigned long long) cx->std); |
| 603 | 603 | |
| 604 | 604 | /* Tuner */ |
| 605 | − cx18_call_all(cx, core, s_std, cx->std); | |
| 605 | + cx18_call_all(cx, video, s_std, cx->std); | |
| 606 | 606 | return 0; |
| 607 | 607 | } |
| 608 | 608 | |
| @@ -326,7 +326,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) · 325 unmodified lines | ||
| 326 | 326 | |
| 327 | 327 | dev->tvnorm = norm; |
| 328 | 328 | |
| 329 | − call_all(dev, core, s_std, norm); | |
| 329 | + call_all(dev, video, s_std, norm); | |
| 330 | 330 | |
| 331 | 331 | return 0; |
| 332 | 332 | } |
| @@ -1589,7 +1589,7 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, · 1256 unmodified lines | ||
| 1589 | 1589 | fe = &dev->ts1.analog_fe; |
| 1590 | 1590 | |
| 1591 | 1591 | if (fe && fe->ops.tuner_ops.set_analog_params) { |
| 1592 | − call_all(dev, core, s_std, dev->tvnorm); | |
| 1592 | + call_all(dev, video, s_std, dev->tvnorm); | |
| 1593 | 1593 | fe->ops.tuner_ops.set_analog_params(fe, ¶ms); |
| 1594 | 1594 | } |
| 1595 | 1595 | else |
| @@ -1012,7 +1012,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) · 1011 unmodified lines | ||
| 1012 | 1012 | set_tvaudio(core); |
| 1013 | 1013 | |
| 1014 | 1014 | // tell i2c chips |
| 1015 | − call_all(core, core, s_std, norm); | |
| 1015 | + call_all(core, video, s_std, norm); | |
| 1016 | 1016 | |
| 1017 | 1017 | /* The chroma_agc control should be inaccessible if the video format is SECAM */ |
| 1018 | 1018 | v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM); |
| @@ -159,6 +159,12 @@ static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream) · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | /* Instruct the CX2341[56] to start sending packets */ |
| 161 | 161 | snd_ivtv_lock(itvsc); |
| 162 | + | |
| 163 | + if (ivtv_init_on_first_open(itv)) { | |
| 164 | + snd_ivtv_unlock(itvsc); | |
| 165 | + return -ENXIO; | |
| 166 | + } | |
| 167 | + | |
| 162 | 168 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; |
| 163 | 169 | |
| 164 | 170 | v4l2_fh_init(&item.fh, s->vdev); |
| @@ -894,7 +894,7 @@ int ivtv_v4l2_close(struct file *filp) · 893 unmodified lines | ||
| 894 | 894 | /* Mark that the radio is no longer in use */ |
| 895 | 895 | clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); |
| 896 | 896 | /* Switch tuner to TV */ |
| 897 | − ivtv_call_all(itv, core, s_std, itv->std); | |
| 897 | + ivtv_call_all(itv, video, s_std, itv->std); | |
| 898 | 898 | /* Select correct audio input (i.e. TV tuner or Line in) */ |
| 899 | 899 | ivtv_audio_set_io(itv); |
| 900 | 900 | if (itv->hw_flags & IVTV_HW_SAA711X) { |
| @@ -1090,7 +1090,7 @@ void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id std) · 1089 unmodified lines | ||
| 1090 | 1090 | itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; |
| 1091 | 1091 | |
| 1092 | 1092 | /* Tuner */ |
| 1093 | − ivtv_call_all(itv, core, s_std, itv->std); | |
| 1093 | + ivtv_call_all(itv, video, s_std, itv->std); | |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| 1096 | 1096 | void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std) |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | config VIDEO_SAA7134 |
| 2 | 2 | tristate "Philips SAA7134 support" |
| 3 | 3 | depends on VIDEO_DEV && PCI && I2C |
| 4 | − select VIDEOBUF_DMA_SG | |
| 4 | + select VIDEOBUF2_DMA_SG | |
| 5 | 5 | select VIDEO_TUNER |
| 6 | 6 | select VIDEO_TVEEPROM |
| 7 | 7 | select CRC32 |
| @@ -37,7 +37,7 @@ config VIDEO_SAA7134_RC · 29 unmodified lines | ||
| 37 | 37 | config VIDEO_SAA7134_DVB |
| 38 | 38 | tristate "DVB/ATSC Support for saa7134 based TV cards" |
| 39 | 39 | depends on VIDEO_SAA7134 && DVB_CORE |
| 40 | − select VIDEOBUF_DVB | |
| 40 | + select VIDEOBUF2_DVB | |
| 41 | 41 | select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT |
| 42 | 42 | select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT |
| 43 | 43 | select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <sound/pcm_params.h> |
| 28 | 28 | #include <sound/initval.h> |
| 29 | 29 | #include <linux/interrupt.h> |
| 30 | +#include <linux/vmalloc.h> | |
| 30 | 31 | |
| 31 | 32 | #include "saa7134.h" |
| 32 | 33 | #include "saa7134-reg.h" |
| @@ -274,6 +275,82 @@ static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream · 241 unmodified lines | ||
| 274 | 275 | return err; |
| 275 | 276 | } |
| 276 | 277 | |
| 278 | +static int saa7134_alsa_dma_init(struct saa7134_dev *dev, int nr_pages) | |
| 279 | +{ | |
| 280 | + struct saa7134_dmasound *dma = &dev->dmasound; | |
| 281 | + struct page *pg; | |
| 282 | + int i; | |
| 283 | + | |
| 284 | + dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); | |
| 285 | + if (NULL == dma->vaddr) { | |
| 286 | + dprintk("vmalloc_32(%d pages) failed\n", nr_pages); | |
| 287 | + return -ENOMEM; | |
| 288 | + } | |
| 289 | + | |
| 290 | + dprintk("vmalloc is at addr 0x%08lx, size=%d\n", | |
| 291 | + (unsigned long)dma->vaddr, | |
| 292 | + nr_pages << PAGE_SHIFT); | |
| 293 | + | |
| 294 | + memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT); | |
| 295 | + dma->nr_pages = nr_pages; | |
| 296 | + | |
| 297 | + dma->sglist = vzalloc(dma->nr_pages * sizeof(*dma->sglist)); | |
| 298 | + if (NULL == dma->sglist) | |
| 299 | + goto vzalloc_err; | |
| 300 | + | |
| 301 | + sg_init_table(dma->sglist, dma->nr_pages); | |
| 302 | + for (i = 0; i < dma->nr_pages; i++) { | |
| 303 | + pg = vmalloc_to_page(dma->vaddr + i * PAGE_SIZE); | |
| 304 | + if (NULL == pg) | |
| 305 | + goto vmalloc_to_page_err; | |
| 306 | + sg_set_page(&dma->sglist[i], pg, PAGE_SIZE, 0); | |
| 307 | + } | |
| 308 | + return 0; | |
| 309 | + | |
| 310 | +vmalloc_to_page_err: | |
| 311 | + vfree(dma->sglist); | |
| 312 | + dma->sglist = NULL; | |
| 313 | +vzalloc_err: | |
| 314 | + vfree(dma->vaddr); | |
| 315 | + dma->vaddr = NULL; | |
| 316 | + return -ENOMEM; | |
| 317 | +} | |
| 318 | + | |
| 319 | +static int saa7134_alsa_dma_map(struct saa7134_dev *dev) | |
| 320 | +{ | |
| 321 | + struct saa7134_dmasound *dma = &dev->dmasound; | |
| 322 | + | |
| 323 | + dma->sglen = dma_map_sg(&dev->pci->dev, dma->sglist, | |
| 324 | + dma->nr_pages, PCI_DMA_FROMDEVICE); | |
| 325 | + | |
| 326 | + if (0 == dma->sglen) { | |
| 327 | + pr_warn("%s: saa7134_alsa_map_sg failed\n", __func__); | |
| 328 | + return -ENOMEM; | |
| 329 | + } | |
| 330 | + return 0; | |
| 331 | +} | |
| 332 | + | |
| 333 | +static int saa7134_alsa_dma_unmap(struct saa7134_dev *dev) | |
| 334 | +{ | |
| 335 | + struct saa7134_dmasound *dma = &dev->dmasound; | |
| 336 | + | |
| 337 | + if (!dma->sglen) | |
| 338 | + return 0; | |
| 339 | + | |
| 340 | + dma_unmap_sg(&dev->pci->dev, dma->sglist, dma->sglen, PCI_DMA_FROMDEVICE); | |
| 341 | + dma->sglen = 0; | |
| 342 | + return 0; | |
| 343 | +} | |
| 344 | + | |
| 345 | +static int saa7134_alsa_dma_free(struct saa7134_dmasound *dma) | |
| 346 | +{ | |
| 347 | + vfree(dma->sglist); | |
| 348 | + dma->sglist = NULL; | |
| 349 | + vfree(dma->vaddr); | |
| 350 | + dma->vaddr = NULL; | |
| 351 | + return 0; | |
| 352 | +} | |
| 353 | + | |
| 277 | 354 | /* |
| 278 | 355 | * DMA buffer initialization |
| 279 | 356 | * |
| @@ -291,9 +368,8 @@ static int dsp_buffer_init(struct saa7134_dev *dev) · 11 unmodified lines | ||
| 291 | 368 | |
| 292 | 369 | BUG_ON(!dev->dmasound.bufsize); |
| 293 | 370 | |
| 294 | − videobuf_dma_init(&dev->dmasound.dma); | |
| 295 | − err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, | |
| 296 | − (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); | |
| 371 | + err = saa7134_alsa_dma_init(dev, | |
| 372 | + (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); | |
| 297 | 373 | if (0 != err) |
| 298 | 374 | return err; |
| 299 | 375 | return 0; |
| @@ -310,7 +386,7 @@ static int dsp_buffer_free(struct saa7134_dev *dev) · 10 unmodified lines | ||
| 310 | 386 | { |
| 311 | 387 | BUG_ON(!dev->dmasound.blksize); |
| 312 | 388 | |
| 313 | − videobuf_dma_free(&dev->dmasound.dma); | |
| 389 | + saa7134_alsa_dma_free(&dev->dmasound); | |
| 314 | 390 | |
| 315 | 391 | dev->dmasound.blocks = 0; |
| 316 | 392 | dev->dmasound.blksize = 0; |
| @@ -632,7 +708,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, · 315 unmodified lines | ||
| 632 | 708 | /* release the old buffer */ |
| 633 | 709 | if (substream->runtime->dma_area) { |
| 634 | 710 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
| 635 | − videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | |
| 711 | + saa7134_alsa_dma_unmap(dev); | |
| 636 | 712 | dsp_buffer_free(dev); |
| 637 | 713 | substream->runtime->dma_area = NULL; |
| 638 | 714 | } |
| @@ -648,21 +724,22 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, · 9 unmodified lines | ||
| 648 | 724 | return err; |
| 649 | 725 | } |
| 650 | 726 | |
| 651 | − if (0 != (err = videobuf_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { | |
| 727 | + err = saa7134_alsa_dma_map(dev); | |
| 728 | + if (err) { | |
| 652 | 729 | dsp_buffer_free(dev); |
| 653 | 730 | return err; |
| 654 | 731 | } |
| 655 | − if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { | |
| 656 | − videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | |
| 732 | + err = saa7134_pgtable_alloc(dev->pci, &dev->dmasound.pt); | |
| 733 | + if (err) { | |
| 734 | + saa7134_alsa_dma_unmap(dev); | |
| 657 | 735 | dsp_buffer_free(dev); |
| 658 | 736 | return err; |
| 659 | 737 | } |
| 660 | − if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | |
| 661 | − dev->dmasound.dma.sglist, | |
| 662 | − dev->dmasound.dma.sglen, | |
| 663 | − 0))) { | |
| 738 | + err = saa7134_pgtable_build(dev->pci, &dev->dmasound.pt, | |
| 739 | + dev->dmasound.sglist, dev->dmasound.sglen, 0); | |
| 740 | + if (err) { | |
| 664 | 741 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
| 665 | − videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | |
| 742 | + saa7134_alsa_dma_unmap(dev); | |
| 666 | 743 | dsp_buffer_free(dev); |
| 667 | 744 | return err; |
| 668 | 745 | } |
| @@ -671,7 +748,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, · 2 unmodified lines | ||
| 671 | 748 | byte, but it doesn't work. So I allocate the DMA using the |
| 672 | 749 | V4L functions, and force ALSA to use that as the DMA area */ |
| 673 | 750 | |
| 674 | − substream->runtime->dma_area = dev->dmasound.dma.vaddr; | |
| 751 | + substream->runtime->dma_area = dev->dmasound.vaddr; | |
| 675 | 752 | substream->runtime->dma_bytes = dev->dmasound.bufsize; |
| 676 | 753 | substream->runtime->dma_addr = 0; |
| 677 | 754 | |
| @@ -698,7 +775,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) · 20 unmodified lines | ||
| 698 | 775 | |
| 699 | 776 | if (substream->runtime->dma_area) { |
| 700 | 777 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
| 701 | − videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | |
| 778 | + saa7134_alsa_dma_unmap(dev); | |
| 702 | 779 | dsp_buffer_free(dev); |
| 703 | 780 | substream->runtime->dma_area = NULL; |
| 704 | 781 | } |
| @@ -69,6 +69,10 @@ module_param_named(no_overlay, saa7134_no_overlay, int, 0444); · 68 unmodified lines | ||
| 69 | 69 | MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" |
| 70 | 70 | " [some VIA/SIS chipsets are known to have problem with overlay]"); |
| 71 | 71 | |
| 72 | +bool saa7134_userptr; | |
| 73 | +module_param(saa7134_userptr, bool, 0644); | |
| 74 | +MODULE_PARM_DESC(saa7134_userptr, "enable page-aligned userptr support"); | |
| 75 | + | |
| 72 | 76 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
| 73 | 77 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
| 74 | 78 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
| @@ -203,16 +207,16 @@ int saa7134_buffer_count(unsigned int size, unsigned int count) · 128 unmodified lines | ||
| 203 | 207 | |
| 204 | 208 | int saa7134_buffer_startpage(struct saa7134_buf *buf) |
| 205 | 209 | { |
| 206 | − return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i; | |
| 210 | + return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index; | |
| 207 | 211 | } |
| 208 | 212 | |
| 209 | 213 | unsigned long saa7134_buffer_base(struct saa7134_buf *buf) |
| 210 | 214 | { |
| 211 | 215 | unsigned long base; |
| 212 | − struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | |
| 216 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 213 | 217 | |
| 214 | 218 | base = saa7134_buffer_startpage(buf) * 4096; |
| 215 | − base += dma->sglist[0].offset; | |
| 219 | + base += dma->sgl[0].offset; | |
| 216 | 220 | return base; |
| 217 | 221 | } |
| 218 | 222 | |
| @@ -237,14 +241,16 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt, · 18 unmodified lines | ||
| 237 | 241 | unsigned int startpage) |
| 238 | 242 | { |
| 239 | 243 | __le32 *ptr; |
| 240 | − unsigned int i,p; | |
| 244 | + unsigned int i, p; | |
| 241 | 245 | |
| 242 | 246 | BUG_ON(NULL == pt || NULL == pt->cpu); |
| 243 | 247 | |
| 244 | 248 | ptr = pt->cpu + startpage; |
| 245 | − for (i = 0; i < length; i++, list++) | |
| 249 | + for (i = 0; i < length; i++, list = sg_next(list)) { | |
| 246 | 250 | for (p = 0; p * 4096 < list->length; p++, ptr++) |
| 247 | − *ptr = cpu_to_le32(sg_dma_address(list) - list->offset); | |
| 251 | + *ptr = cpu_to_le32(sg_dma_address(list) + | |
| 252 | + list->offset + p * 4096); | |
| 253 | + } | |
| 248 | 254 | return 0; |
| 249 | 255 | } |
| 250 | 256 | |
| @@ -258,44 +264,31 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt) · 7 unmodified lines | ||
| 258 | 264 | |
| 259 | 265 | /* ------------------------------------------------------------------ */ |
| 260 | 266 | |
| 261 | −void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) | |
| 262 | −{ | |
| 263 | − struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | |
| 264 | − BUG_ON(in_interrupt()); | |
| 265 | − | |
| 266 | − videobuf_waiton(q, &buf->vb, 0, 0); | |
| 267 | − videobuf_dma_unmap(q->dev, dma); | |
| 268 | − videobuf_dma_free(dma); | |
| 269 | − buf->vb.state = VIDEOBUF_NEEDS_INIT; | |
| 270 | −} | |
| 271 | − | |
| 272 | −/* ------------------------------------------------------------------ */ | |
| 273 | − | |
| 274 | 267 | int saa7134_buffer_queue(struct saa7134_dev *dev, |
| 275 | 268 | struct saa7134_dmaqueue *q, |
| 276 | 269 | struct saa7134_buf *buf) |
| 277 | 270 | { |
| 278 | 271 | struct saa7134_buf *next = NULL; |
| 272 | + unsigned long flags; | |
| 279 | 273 | |
| 280 | − assert_spin_locked(&dev->slock); | |
| 281 | − dprintk("buffer_queue %p\n",buf); | |
| 274 | + spin_lock_irqsave(&dev->slock, flags); | |
| 275 | + dprintk("buffer_queue %p\n", buf); | |
| 282 | 276 | if (NULL == q->curr) { |
| 283 | 277 | if (!q->need_two) { |
| 284 | 278 | q->curr = buf; |
| 285 | − buf->activate(dev,buf,NULL); | |
| 279 | + buf->activate(dev, buf, NULL); | |
| 286 | 280 | } else if (list_empty(&q->queue)) { |
| 287 | − list_add_tail(&buf->vb.queue,&q->queue); | |
| 288 | − buf->vb.state = VIDEOBUF_QUEUED; | |
| 281 | + list_add_tail(&buf->entry, &q->queue); | |
| 289 | 282 | } else { |
| 290 | − next = list_entry(q->queue.next,struct saa7134_buf, | |
| 291 | − vb.queue); | |
| 283 | + next = list_entry(q->queue.next, struct saa7134_buf, | |
| 284 | + entry); | |
| 292 | 285 | q->curr = buf; |
| 293 | − buf->activate(dev,buf,next); | |
| 286 | + buf->activate(dev, buf, next); | |
| 294 | 287 | } |
| 295 | 288 | } else { |
| 296 | − list_add_tail(&buf->vb.queue,&q->queue); | |
| 297 | − buf->vb.state = VIDEOBUF_QUEUED; | |
| 289 | + list_add_tail(&buf->entry, &q->queue); | |
| 298 | 290 | } |
| 291 | + spin_unlock_irqrestore(&dev->slock, flags); | |
| 299 | 292 | return 0; |
| 300 | 293 | } |
| 301 | 294 | |
| @@ -303,13 +296,12 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, · 1 unmodified line | ||
| 303 | 296 | struct saa7134_dmaqueue *q, |
| 304 | 297 | unsigned int state) |
| 305 | 298 | { |
| 306 | − assert_spin_locked(&dev->slock); | |
| 307 | − dprintk("buffer_finish %p\n",q->curr); | |
| 299 | + dprintk("buffer_finish %p\n", q->curr); | |
| 308 | 300 | |
| 309 | 301 | /* finish current buffer */ |
| 310 | − q->curr->vb.state = state; | |
| 311 | − v4l2_get_timestamp(&q->curr->vb.ts); | |
| 312 | − wake_up(&q->curr->vb.done); | |
| 302 | + v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp); | |
| 303 | + q->curr->vb2.v4l2_buf.sequence = q->seq_nr++; | |
| 304 | + vb2_buffer_done(&q->curr->vb2, state); | |
| 313 | 305 | q->curr = NULL; |
| 314 | 306 | } |
| 315 | 307 | |
| @@ -323,36 +315,31 @@ void saa7134_buffer_next(struct saa7134_dev *dev, · 7 unmodified lines | ||
| 323 | 315 | |
| 324 | 316 | if (!list_empty(&q->queue)) { |
| 325 | 317 | /* activate next one from queue */ |
| 326 | − buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue); | |
| 318 | + buf = list_entry(q->queue.next, struct saa7134_buf, entry); | |
| 327 | 319 | dprintk("buffer_next %p [prev=%p/next=%p]\n", |
| 328 | − buf,q->queue.prev,q->queue.next); | |
| 329 | − list_del(&buf->vb.queue); | |
| 320 | + buf, q->queue.prev, q->queue.next); | |
| 321 | + list_del(&buf->entry); | |
| 330 | 322 | if (!list_empty(&q->queue)) |
| 331 | − next = list_entry(q->queue.next,struct saa7134_buf, | |
| 332 | − vb.queue); | |
| 323 | + next = list_entry(q->queue.next, struct saa7134_buf, entry); | |
| 333 | 324 | q->curr = buf; |
| 334 | − buf->activate(dev,buf,next); | |
| 325 | + buf->activate(dev, buf, next); | |
| 335 | 326 | dprintk("buffer_next #2 prev=%p/next=%p\n", |
| 336 | − q->queue.prev,q->queue.next); | |
| 327 | + q->queue.prev, q->queue.next); | |
| 337 | 328 | } else { |
| 338 | 329 | /* nothing to do -- just stop DMA */ |
| 339 | − dprintk("buffer_next %p\n",NULL); | |
| 330 | + dprintk("buffer_next %p\n", NULL); | |
| 340 | 331 | saa7134_set_dmabits(dev); |
| 341 | 332 | del_timer(&q->timeout); |
| 342 | − | |
| 343 | − if (card_has_mpeg(dev)) | |
| 344 | − if (dev->ts_started) | |
| 345 | − saa7134_ts_stop(dev); | |
| 346 | 333 | } |
| 347 | 334 | } |
| 348 | 335 | |
| 349 | 336 | void saa7134_buffer_timeout(unsigned long data) |
| 350 | 337 | { |
| 351 | − struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data; | |
| 338 | + struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue *)data; | |
| 352 | 339 | struct saa7134_dev *dev = q->dev; |
| 353 | 340 | unsigned long flags; |
| 354 | 341 | |
| 355 | − spin_lock_irqsave(&dev->slock,flags); | |
| 342 | + spin_lock_irqsave(&dev->slock, flags); | |
| 356 | 343 | |
| 357 | 344 | /* try to reset the hardware (SWRST) */ |
| 358 | 345 | saa_writeb(SAA7134_REGION_ENABLE, 0x00); |
| @@ -362,13 +349,33 @@ void saa7134_buffer_timeout(unsigned long data) · 3 unmodified lines | ||
| 362 | 349 | /* flag current buffer as failed, |
| 363 | 350 | try to start over with the next one. */ |
| 364 | 351 | if (q->curr) { |
| 365 | − dprintk("timeout on %p\n",q->curr); | |
| 366 | − saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR); | |
| 352 | + dprintk("timeout on %p\n", q->curr); | |
| 353 | + saa7134_buffer_finish(dev, q, VB2_BUF_STATE_ERROR); | |
| 367 | 354 | } |
| 368 | − saa7134_buffer_next(dev,q); | |
| 369 | − spin_unlock_irqrestore(&dev->slock,flags); | |
| 355 | + saa7134_buffer_next(dev, q); | |
| 356 | + spin_unlock_irqrestore(&dev->slock, flags); | |
| 370 | 357 | } |
| 371 | 358 | |
| 359 | +void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q) | |
| 360 | +{ | |
| 361 | + unsigned long flags; | |
| 362 | + struct list_head *pos, *n; | |
| 363 | + struct saa7134_buf *tmp; | |
| 364 | + | |
| 365 | + spin_lock_irqsave(&dev->slock, flags); | |
| 366 | + if (!list_empty(&q->queue)) { | |
| 367 | + list_for_each_safe(pos, n, &q->queue) { | |
| 368 | + tmp = list_entry(pos, struct saa7134_buf, entry); | |
| 369 | + vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR); | |
| 370 | + list_del(pos); | |
| 371 | + tmp = NULL; | |
| 372 | + } | |
| 373 | + } | |
| 374 | + spin_unlock_irqrestore(&dev->slock, flags); | |
| 375 | + saa7134_buffer_timeout((unsigned long)q); /* also calls del_timer(&q->timeout) */ | |
| 376 | +} | |
| 377 | +EXPORT_SYMBOL_GPL(saa7134_stop_streaming); | |
| 378 | + | |
| 372 | 379 | /* ------------------------------------------------------------------ */ |
| 373 | 380 | |
| 374 | 381 | int saa7134_set_dmabits(struct saa7134_dev *dev) |
| @@ -388,12 +395,11 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) · 13 unmodified lines | ||
| 388 | 395 | ctrl |= SAA7134_MAIN_CTRL_TE0; |
| 389 | 396 | irq |= SAA7134_IRQ1_INTE_RA0_1 | |
| 390 | 397 | SAA7134_IRQ1_INTE_RA0_0; |
| 391 | − cap = dev->video_q.curr->vb.field; | |
| 398 | + cap = dev->field; | |
| 392 | 399 | } |
| 393 | 400 | |
| 394 | 401 | /* video capture -- dma 1+2 (planar modes) */ |
| 395 | − if (dev->video_q.curr && | |
| 396 | − dev->video_q.curr->fmt->planar) { | |
| 402 | + if (dev->video_q.curr && dev->fmt->planar) { | |
| 397 | 403 | ctrl |= SAA7134_MAIN_CTRL_TE4 | |
| 398 | 404 | SAA7134_MAIN_CTRL_TE5; |
| 399 | 405 | } |
| @@ -1047,6 +1053,8 @@ static int saa7134_initdev(struct pci_dev *pci_dev, · 647 unmodified lines | ||
| 1047 | 1053 | |
| 1048 | 1054 | dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); |
| 1049 | 1055 | dev->video_dev->ctrl_handler = &dev->ctrl_handler; |
| 1056 | + dev->video_dev->lock = &dev->lock; | |
| 1057 | + dev->video_dev->queue = &dev->video_vbq; | |
| 1050 | 1058 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, |
| 1051 | 1059 | video_nr[dev->nr]); |
| 1052 | 1060 | if (err < 0) { |
| @@ -1059,6 +1067,8 @@ static int saa7134_initdev(struct pci_dev *pci_dev, · 6 unmodified lines | ||
| 1059 | 1067 | |
| 1060 | 1068 | dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi"); |
| 1061 | 1069 | dev->vbi_dev->ctrl_handler = &dev->ctrl_handler; |
| 1070 | + dev->vbi_dev->lock = &dev->lock; | |
| 1071 | + dev->vbi_dev->queue = &dev->vbi_vbq; | |
| 1062 | 1072 | |
| 1063 | 1073 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, |
| 1064 | 1074 | vbi_nr[dev->nr]); |
| @@ -1070,6 +1080,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev, · 5 unmodified lines | ||
| 1070 | 1080 | if (card_has_radio(dev)) { |
| 1071 | 1081 | dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); |
| 1072 | 1082 | dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler; |
| 1083 | + dev->radio_dev->lock = &dev->lock; | |
| 1073 | 1084 | err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, |
| 1074 | 1085 | radio_nr[dev->nr]); |
| 1075 | 1086 | if (err < 0) |
| @@ -1189,7 +1200,7 @@ static int saa7134_buffer_requeue(struct saa7134_dev *dev, · 113 unmodified lines | ||
| 1189 | 1200 | |
| 1190 | 1201 | if (!list_empty(&q->queue)) |
| 1191 | 1202 | next = list_entry(q->queue.next, struct saa7134_buf, |
| 1192 | − vb.queue); | |
| 1203 | + entry); | |
| 1193 | 1204 | buf->activate(dev, buf, next); |
| 1194 | 1205 | |
| 1195 | 1206 | return 0; |
| @@ -1360,10 +1371,3 @@ EXPORT_SYMBOL(saa7134_pgtable_free); · 164 unmodified lines | ||
| 1360 | 1371 | EXPORT_SYMBOL(saa7134_pgtable_build); |
| 1361 | 1372 | EXPORT_SYMBOL(saa7134_pgtable_alloc); |
| 1362 | 1373 | EXPORT_SYMBOL(saa7134_set_dmabits); |
| 1363 | − | |
| 1364 | −/* ----------------------------------------------------------- */ | |
| 1365 | −/* | |
| 1366 | − * Local variables: | |
| 1367 | − * c-basic-offset: 8 | |
| 1368 | − * End: | |
| 1369 | − */ | |
| @@ -602,10 +602,10 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, · 601 unmodified lines | ||
| 602 | 602 | struct tda1004x_config *cdec_conf, |
| 603 | 603 | struct tda827x_config *tuner_conf) |
| 604 | 604 | { |
| 605 | − struct videobuf_dvb_frontend *fe0; | |
| 605 | + struct vb2_dvb_frontend *fe0; | |
| 606 | 606 | |
| 607 | 607 | /* Get the first frontend */ |
| 608 | − fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | |
| 608 | + fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); | |
| 609 | 609 | |
| 610 | 610 | if (!fe0) |
| 611 | 611 | return -EINVAL; |
| @@ -1215,29 +1215,38 @@ static int dvb_init(struct saa7134_dev *dev) · 603 unmodified lines | ||
| 1215 | 1215 | { |
| 1216 | 1216 | int ret; |
| 1217 | 1217 | int attach_xc3028 = 0; |
| 1218 | − struct videobuf_dvb_frontend *fe0; | |
| 1218 | + struct vb2_dvb_frontend *fe0; | |
| 1219 | + struct vb2_queue *q; | |
| 1219 | 1220 | |
| 1220 | 1221 | /* FIXME: add support for multi-frontend */ |
| 1221 | 1222 | mutex_init(&dev->frontends.lock); |
| 1222 | 1223 | INIT_LIST_HEAD(&dev->frontends.felist); |
| 1223 | 1224 | |
| 1224 | 1225 | printk(KERN_INFO "%s() allocating 1 frontend\n", __func__); |
| 1225 | − fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1); | |
| 1226 | + fe0 = vb2_dvb_alloc_frontend(&dev->frontends, 1); | |
| 1226 | 1227 | if (!fe0) { |
| 1227 | 1228 | printk(KERN_ERR "%s() failed to alloc\n", __func__); |
| 1228 | 1229 | return -ENOMEM; |
| 1229 | 1230 | } |
| 1230 | 1231 | |
| 1231 | − /* init struct videobuf_dvb */ | |
| 1232 | + /* init struct vb2_dvb */ | |
| 1232 | 1233 | dev->ts.nr_bufs = 32; |
| 1233 | 1234 | dev->ts.nr_packets = 32*4; |
| 1234 | 1235 | fe0->dvb.name = dev->name; |
| 1235 | − videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops, | |
| 1236 | − &dev->pci->dev, &dev->slock, | |
| 1237 | − V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
| 1238 | − V4L2_FIELD_ALTERNATE, | |
| 1239 | − sizeof(struct saa7134_buf), | |
| 1240 | − dev, NULL); | |
| 1236 | + q = &fe0->dvb.dvbq; | |
| 1237 | + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 1238 | + q->io_modes = VB2_MMAP | VB2_READ; | |
| 1239 | + q->drv_priv = &dev->ts_q; | |
| 1240 | + q->ops = &saa7134_ts_qops; | |
| 1241 | + q->mem_ops = &vb2_dma_sg_memops; | |
| 1242 | + q->buf_struct_size = sizeof(struct saa7134_buf); | |
| 1243 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 1244 | + q->lock = &dev->lock; | |
| 1245 | + ret = vb2_queue_init(q); | |
| 1246 | + if (ret) { | |
| 1247 | + vb2_dvb_dealloc_frontends(&dev->frontends); | |
| 1248 | + return ret; | |
| 1249 | + } | |
| 1241 | 1250 | |
| 1242 | 1251 | switch (dev->board) { |
| 1243 | 1252 | case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: |
| @@ -1876,7 +1885,7 @@ static int dvb_init(struct saa7134_dev *dev) · 632 unmodified lines | ||
| 1876 | 1885 | fe0->dvb.frontend->callback = saa7134_tuner_callback; |
| 1877 | 1886 | |
| 1878 | 1887 | /* register everything else */ |
| 1879 | − ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | |
| 1888 | + ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | |
| 1880 | 1889 | &dev->pci->dev, adapter_nr, 0); |
| 1881 | 1890 | |
| 1882 | 1891 | /* this sequence is necessary to make the tda1004x load its firmware |
| @@ -1893,16 +1902,17 @@ static int dvb_init(struct saa7134_dev *dev) · 10 unmodified lines | ||
| 1893 | 1902 | return ret; |
| 1894 | 1903 | |
| 1895 | 1904 | detach_frontend: |
| 1896 | − videobuf_dvb_dealloc_frontends(&dev->frontends); | |
| 1905 | + vb2_dvb_dealloc_frontends(&dev->frontends); | |
| 1906 | + vb2_queue_release(&fe0->dvb.dvbq); | |
| 1897 | 1907 | return -EINVAL; |
| 1898 | 1908 | } |
| 1899 | 1909 | |
| 1900 | 1910 | static int dvb_fini(struct saa7134_dev *dev) |
| 1901 | 1911 | { |
| 1902 | − struct videobuf_dvb_frontend *fe0; | |
| 1912 | + struct vb2_dvb_frontend *fe0; | |
| 1903 | 1913 | |
| 1904 | 1914 | /* Get the first frontend */ |
| 1905 | − fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | |
| 1915 | + fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); | |
| 1906 | 1916 | if (!fe0) |
| 1907 | 1917 | return -EINVAL; |
| 1908 | 1918 | |
| @@ -1933,7 +1943,8 @@ static int dvb_fini(struct saa7134_dev *dev) · 24 unmodified lines | ||
| 1933 | 1943 | } |
| 1934 | 1944 | } |
| 1935 | 1945 | } |
| 1936 | − videobuf_dvb_unregister_bus(&dev->frontends); | |
| 1946 | + vb2_dvb_unregister_bus(&dev->frontends); | |
| 1947 | + vb2_queue_release(&fe0->dvb.dvbq); | |
| 1937 | 1948 | return 0; |
| 1938 | 1949 | } |
| 1939 | 1950 | |
| @@ -1955,10 +1966,3 @@ static void __exit dvb_unregister(void) · 15 unmodified lines | ||
| 1955 | 1966 | |
| 1956 | 1967 | module_init(dvb_register); |
| 1957 | 1968 | module_exit(dvb_unregister); |
| 1958 | − | |
| 1959 | −/* ------------------------------------------------------------------ */ | |
| 1960 | −/* | |
| 1961 | − * Local variables: | |
| 1962 | − * c-basic-offset: 8 | |
| 1963 | − * End: | |
| 1964 | − */ | |
| @@ -48,21 +48,16 @@ MODULE_PARM_DESC(debug,"enable debug messages"); · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | /* ------------------------------------------------------------------ */ |
| 50 | 50 | |
| 51 | −static void ts_reset_encoder(struct saa7134_dev* dev) | |
| 52 | −{ | |
| 53 | − if (!dev->empress_started) | |
| 54 | − return; | |
| 55 | − | |
| 56 | − saa_writeb(SAA7134_SPECIAL_MODE, 0x00); | |
| 57 | − msleep(10); | |
| 58 | − saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | |
| 59 | − msleep(100); | |
| 60 | − dev->empress_started = 0; | |
| 61 | −} | |
| 62 | − | |
| 63 | −static int ts_init_encoder(struct saa7134_dev* dev) | |
| 51 | +static int start_streaming(struct vb2_queue *vq, unsigned int count) | |
| 64 | 52 | { |
| 53 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 54 | + struct saa7134_dev *dev = dmaq->dev; | |
| 65 | 55 | u32 leading_null_bytes = 0; |
| 56 | + int err; | |
| 57 | + | |
| 58 | + err = saa7134_ts_start_streaming(vq, count); | |
| 59 | + if (err) | |
| 60 | + return err; | |
| 66 | 61 | |
| 67 | 62 | /* If more cards start to need this, then this |
| 68 | 63 | should probably be added to the card definitions. */ |
| @@ -73,97 +68,43 @@ static int ts_init_encoder(struct saa7134_dev* dev) · 4 unmodified lines | ||
| 73 | 68 | leading_null_bytes = 1; |
| 74 | 69 | break; |
| 75 | 70 | } |
| 76 | − ts_reset_encoder(dev); | |
| 77 | 71 | saa_call_all(dev, core, init, leading_null_bytes); |
| 78 | − dev->empress_started = 1; | |
| 79 | − return 0; | |
| 80 | −} | |
| 81 | − | |
| 82 | −/* ------------------------------------------------------------------ */ | |
| 83 | − | |
| 84 | −static int ts_open(struct file *file) | |
| 85 | −{ | |
| 86 | − struct video_device *vdev = video_devdata(file); | |
| 87 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 88 | − struct saa7134_fh *fh; | |
| 89 | − | |
| 90 | − /* allocate + initialize per filehandle data */ | |
| 91 | − fh = kzalloc(sizeof(*fh), GFP_KERNEL); | |
| 92 | − if (NULL == fh) | |
| 93 | − return -ENOMEM; | |
| 94 | − | |
| 95 | − v4l2_fh_init(&fh->fh, vdev); | |
| 96 | − file->private_data = fh; | |
| 97 | − fh->is_empress = true; | |
| 98 | − v4l2_fh_add(&fh->fh); | |
| 99 | − | |
| 100 | 72 | /* Unmute audio */ |
| 101 | 73 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, |
| 102 | − saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6)); | |
| 103 | − | |
| 104 | − return 0; | |
| 105 | −} | |
| 106 | − | |
| 107 | −static int ts_release(struct file *file) | |
| 108 | −{ | |
| 109 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 110 | − struct saa7134_fh *fh = file->private_data; | |
| 111 | − | |
| 112 | − if (res_check(fh, RESOURCE_EMPRESS)) { | |
| 113 | − videobuf_stop(&dev->empress_tsq); | |
| 114 | − videobuf_mmap_free(&dev->empress_tsq); | |
| 115 | − | |
| 116 | − /* stop the encoder */ | |
| 117 | − ts_reset_encoder(dev); | |
| 118 | − | |
| 119 | − /* Mute audio */ | |
| 120 | − saa_writeb(SAA7134_AUDIO_MUTE_CTRL, | |
| 121 | − saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); | |
| 122 | − } | |
| 123 | − | |
| 124 | − v4l2_fh_del(&fh->fh); | |
| 125 | − v4l2_fh_exit(&fh->fh); | |
| 74 | + saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6)); | |
| 75 | + dev->empress_started = 1; | |
| 126 | 76 | return 0; |
| 127 | 77 | } |
| 128 | 78 | |
| 129 | −static ssize_t | |
| 130 | −ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |
| 79 | +static void stop_streaming(struct vb2_queue *vq) | |
| 131 | 80 | { |
| 132 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 81 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 82 | + struct saa7134_dev *dev = dmaq->dev; | |
| 133 | 83 | |
| 134 | − if (res_locked(dev, RESOURCE_EMPRESS)) | |
| 135 | − return -EBUSY; | |
| 136 | − if (!dev->empress_started) | |
| 137 | − ts_init_encoder(dev); | |
| 138 | − | |
| 139 | − return videobuf_read_stream(&dev->empress_tsq, | |
| 140 | − data, count, ppos, 0, | |
| 141 | − file->f_flags & O_NONBLOCK); | |
| 142 | −} | |
| 143 | − | |
| 144 | −static unsigned int | |
| 145 | −ts_poll(struct file *file, struct poll_table_struct *wait) | |
| 146 | −{ | |
| 147 | − unsigned long req_events = poll_requested_events(wait); | |
| 148 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 149 | − struct saa7134_fh *fh = file->private_data; | |
| 150 | − unsigned int rc = 0; | |
| 151 | − | |
| 152 | − if (v4l2_event_pending(&fh->fh)) | |
| 153 | − rc = POLLPRI; | |
| 154 | − else if (req_events & POLLPRI) | |
| 155 | − poll_wait(file, &fh->fh.wait, wait); | |
| 156 | − return rc | videobuf_poll_stream(file, &dev->empress_tsq, wait); | |
| 84 | + saa7134_ts_stop_streaming(vq); | |
| 85 | + saa_writeb(SAA7134_SPECIAL_MODE, 0x00); | |
| 86 | + msleep(20); | |
| 87 | + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | |
| 88 | + msleep(100); | |
| 89 | + /* Mute audio */ | |
| 90 | + saa_writeb(SAA7134_AUDIO_MUTE_CTRL, | |
| 91 | + saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); | |
| 92 | + dev->empress_started = 0; | |
| 157 | 93 | } |
| 158 | 94 | |
| 95 | +static struct vb2_ops saa7134_empress_qops = { | |
| 96 | + .queue_setup = saa7134_ts_queue_setup, | |
| 97 | + .buf_init = saa7134_ts_buffer_init, | |
| 98 | + .buf_prepare = saa7134_ts_buffer_prepare, | |
| 99 | + .buf_finish = saa7134_ts_buffer_finish, | |
| 100 | + .buf_queue = saa7134_vb2_buffer_queue, | |
| 101 | + .wait_prepare = vb2_ops_wait_prepare, | |
| 102 | + .wait_finish = vb2_ops_wait_finish, | |
| 103 | + .start_streaming = start_streaming, | |
| 104 | + .stop_streaming = stop_streaming, | |
| 105 | +}; | |
| 159 | 106 | |
| 160 | −static int | |
| 161 | −ts_mmap(struct file *file, struct vm_area_struct * vma) | |
| 162 | −{ | |
| 163 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 164 | − | |
| 165 | − return videobuf_mmap_mapper(&dev->empress_tsq, vma); | |
| 166 | −} | |
| 107 | +/* ------------------------------------------------------------------ */ | |
| 167 | 108 | |
| 168 | 109 | static int empress_enum_fmt_vid_cap(struct file *file, void *priv, |
| 169 | 110 | struct v4l2_fmtdesc *f) |
| @@ -233,11 +174,11 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv, · 63 unmodified lines | ||
| 233 | 174 | static const struct v4l2_file_operations ts_fops = |
| 234 | 175 | { |
| 235 | 176 | .owner = THIS_MODULE, |
| 236 | − .open = ts_open, | |
| 237 | − .release = ts_release, | |
| 238 | − .read = ts_read, | |
| 239 | − .poll = ts_poll, | |
| 240 | − .mmap = ts_mmap, | |
| 177 | + .open = v4l2_fh_open, | |
| 178 | + .release = vb2_fop_release, | |
| 179 | + .read = vb2_fop_read, | |
| 180 | + .poll = vb2_fop_poll, | |
| 181 | + .mmap = vb2_fop_mmap, | |
| 241 | 182 | .ioctl = video_ioctl2, |
| 242 | 183 | }; |
| 243 | 184 | |
| @@ -247,12 +188,12 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { · 3 unmodified lines | ||
| 247 | 188 | .vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap, |
| 248 | 189 | .vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap, |
| 249 | 190 | .vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap, |
| 250 | − .vidioc_reqbufs = saa7134_reqbufs, | |
| 251 | − .vidioc_querybuf = saa7134_querybuf, | |
| 252 | − .vidioc_qbuf = saa7134_qbuf, | |
| 253 | − .vidioc_dqbuf = saa7134_dqbuf, | |
| 254 | − .vidioc_streamon = saa7134_streamon, | |
| 255 | − .vidioc_streamoff = saa7134_streamoff, | |
| 191 | + .vidioc_reqbufs = vb2_ioctl_reqbufs, | |
| 192 | + .vidioc_querybuf = vb2_ioctl_querybuf, | |
| 193 | + .vidioc_qbuf = vb2_ioctl_qbuf, | |
| 194 | + .vidioc_dqbuf = vb2_ioctl_dqbuf, | |
| 195 | + .vidioc_streamon = vb2_ioctl_streamon, | |
| 196 | + .vidioc_streamoff = vb2_ioctl_streamoff, | |
| 256 | 197 | .vidioc_g_frequency = saa7134_g_frequency, |
| 257 | 198 | .vidioc_s_frequency = saa7134_s_frequency, |
| 258 | 199 | .vidioc_g_tuner = saa7134_g_tuner, |
| @@ -262,6 +203,7 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { · 3 unmodified lines | ||
| 262 | 203 | .vidioc_s_input = saa7134_s_input, |
| 263 | 204 | .vidioc_s_std = saa7134_s_std, |
| 264 | 205 | .vidioc_g_std = saa7134_g_std, |
| 206 | + .vidioc_querystd = saa7134_querystd, | |
| 265 | 207 | .vidioc_log_status = v4l2_ctrl_log_status, |
| 266 | 208 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, |
| 267 | 209 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
| @@ -314,6 +256,7 @@ static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl) · 46 unmodified lines | ||
| 314 | 256 | static int empress_init(struct saa7134_dev *dev) |
| 315 | 257 | { |
| 316 | 258 | struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler; |
| 259 | + struct vb2_queue *q; | |
| 317 | 260 | int err; |
| 318 | 261 | |
| 319 | 262 | dprintk("%s: %s\n",dev->name,__func__); |
| @@ -323,6 +266,7 @@ static int empress_init(struct saa7134_dev *dev) · 3 unmodified lines | ||
| 323 | 266 | *(dev->empress_dev) = saa7134_empress_template; |
| 324 | 267 | dev->empress_dev->v4l2_dev = &dev->v4l2_dev; |
| 325 | 268 | dev->empress_dev->release = video_device_release; |
| 269 | + dev->empress_dev->lock = &dev->lock; | |
| 326 | 270 | snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name), |
| 327 | 271 | "%s empress (%s)", dev->name, |
| 328 | 272 | saa7134_boards[dev->board].name); |
| @@ -339,6 +283,26 @@ static int empress_init(struct saa7134_dev *dev) · 10 unmodified lines | ||
| 339 | 283 | |
| 340 | 284 | INIT_WORK(&dev->empress_workqueue, empress_signal_update); |
| 341 | 285 | |
| 286 | + q = &dev->empress_vbq; | |
| 287 | + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 288 | + /* | |
| 289 | + * Do not add VB2_USERPTR: the saa7134 DMA engine cannot handle | |
| 290 | + * transfers that do not start at the beginning of a page. A USERPTR | |
| 291 | + * can start anywhere in a page, so USERPTR support is a no-go. | |
| 292 | + */ | |
| 293 | + q->io_modes = VB2_MMAP | VB2_READ; | |
| 294 | + q->drv_priv = &dev->ts_q; | |
| 295 | + q->ops = &saa7134_empress_qops; | |
| 296 | + q->gfp_flags = GFP_DMA32; | |
| 297 | + q->mem_ops = &vb2_dma_sg_memops; | |
| 298 | + q->buf_struct_size = sizeof(struct saa7134_buf); | |
| 299 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 300 | + q->lock = &dev->lock; | |
| 301 | + err = vb2_queue_init(q); | |
| 302 | + if (err) | |
| 303 | + return err; | |
| 304 | + dev->empress_dev->queue = q; | |
| 305 | + | |
| 342 | 306 | video_set_drvdata(dev->empress_dev, dev); |
| 343 | 307 | err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, |
| 344 | 308 | empress_nr[dev->nr]); |
| @@ -352,13 +316,6 @@ static int empress_init(struct saa7134_dev *dev) · 7 unmodified lines | ||
| 352 | 316 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", |
| 353 | 317 | dev->name, video_device_node_name(dev->empress_dev)); |
| 354 | 318 | |
| 355 | − videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, | |
| 356 | − &dev->pci->dev, &dev->slock, | |
| 357 | − V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
| 358 | − V4L2_FIELD_ALTERNATE, | |
| 359 | − sizeof(struct saa7134_buf), | |
| 360 | − dev, NULL); | |
| 361 | − | |
| 362 | 319 | empress_signal_update(&dev->empress_workqueue); |
| 363 | 320 | return 0; |
| 364 | 321 | } |
| @@ -371,6 +328,7 @@ static int empress_fini(struct saa7134_dev *dev) · 6 unmodified lines | ||
| 371 | 328 | return 0; |
| 372 | 329 | flush_work(&dev->empress_workqueue); |
| 373 | 330 | video_unregister_device(dev->empress_dev); |
| 331 | + vb2_queue_release(&dev->empress_vbq); | |
| 374 | 332 | v4l2_ctrl_handler_free(&dev->empress_ctrl_handler); |
| 375 | 333 | dev->empress_dev = NULL; |
| 376 | 334 | return 0; |
| @@ -395,10 +353,3 @@ static void __exit empress_unregister(void) · 18 unmodified lines | ||
| 395 | 353 | |
| 396 | 354 | module_init(empress_register); |
| 397 | 355 | module_exit(empress_unregister); |
| 398 | − | |
| 399 | −/* ----------------------------------------------------------- */ | |
| 400 | −/* | |
| 401 | − * Local variables: | |
| 402 | − * c-basic-offset: 8 | |
| 403 | − * End: | |
| 404 | − */ | |
| @@ -427,10 +427,3 @@ int saa7134_i2c_unregister(struct saa7134_dev *dev) · 426 unmodified lines | ||
| 427 | 427 | i2c_del_adapter(&dev->i2c_adap); |
| 428 | 428 | return 0; |
| 429 | 429 | } |
| 430 | − | |
| 431 | −/* ----------------------------------------------------------- */ | |
| 432 | −/* | |
| 433 | − * Local variables: | |
| 434 | − * c-basic-offset: 8 | |
| 435 | − * End: | |
| 436 | − */ | |
| @@ -167,17 +167,22 @@ · 166 unmodified lines | ||
| 167 | 167 | #define SAA7134_HSYNC_START 0x106 |
| 168 | 168 | #define SAA7134_HSYNC_STOP 0x107 |
| 169 | 169 | #define SAA7134_SYNC_CTRL 0x108 |
| 170 | +#define SAA7134_SYNC_CTRL_AUFD (1 << 7) | |
| 170 | 171 | #define SAA7134_LUMA_CTRL 0x109 |
| 172 | +#define SAA7134_LUMA_CTRL_LDEL (1 << 5) | |
| 171 | 173 | #define SAA7134_DEC_LUMA_BRIGHT 0x10a |
| 172 | 174 | #define SAA7134_DEC_LUMA_CONTRAST 0x10b |
| 173 | 175 | #define SAA7134_DEC_CHROMA_SATURATION 0x10c |
| 174 | 176 | #define SAA7134_DEC_CHROMA_HUE 0x10d |
| 175 | 177 | #define SAA7134_CHROMA_CTRL1 0x10e |
| 178 | +#define SAA7134_CHROMA_CTRL1_AUTO0 (1 << 1) | |
| 179 | +#define SAA7134_CHROMA_CTRL1_FCTC (1 << 2) | |
| 176 | 180 | #define SAA7134_CHROMA_GAIN 0x10f |
| 177 | 181 | #define SAA7134_CHROMA_CTRL2 0x110 |
| 178 | 182 | #define SAA7134_MODE_DELAY_CTRL 0x111 |
| 179 | 183 | |
| 180 | 184 | #define SAA7134_ANALOG_ADC 0x114 |
| 185 | +#define SAA7134_ANALOG_ADC_AUTO1 (1 << 2) | |
| 181 | 186 | #define SAA7134_VGATE_START 0x115 |
| 182 | 187 | #define SAA7134_VGATE_STOP 0x116 |
| 183 | 188 | #define SAA7134_MISC_VGATE_MSB 0x117 |
| @@ -369,10 +374,3 @@ · 185 unmodified lines | ||
| 369 | 374 | #define SAA7135_DSP_RWCLEAR_RERR 1 |
| 370 | 375 | |
| 371 | 376 | #define SAA7133_I2S_AUDIO_CONTROL 0x591 |
| 372 | −/* ------------------------------------------------------------------ */ | |
| 373 | −/* | |
| 374 | − * Local variables: | |
| 375 | − * c-basic-offset: 8 | |
| 376 | − * End: | |
| 377 | − */ | |
| 378 | − | |
| @@ -39,26 +39,29 @@ MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); · 38 unmodified lines | ||
| 39 | 39 | printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg) |
| 40 | 40 | |
| 41 | 41 | /* ------------------------------------------------------------------ */ |
| 42 | − | |
| 43 | 42 | static int buffer_activate(struct saa7134_dev *dev, |
| 44 | 43 | struct saa7134_buf *buf, |
| 45 | 44 | struct saa7134_buf *next) |
| 46 | 45 | { |
| 47 | 46 | |
| 48 | 47 | dprintk("buffer_activate [%p]",buf); |
| 49 | − buf->vb.state = VIDEOBUF_ACTIVE; | |
| 50 | 48 | buf->top_seen = 0; |
| 51 | 49 | |
| 50 | + if (!dev->ts_started) | |
| 51 | + dev->ts_field = V4L2_FIELD_TOP; | |
| 52 | + | |
| 52 | 53 | if (NULL == next) |
| 53 | 54 | next = buf; |
| 54 | − if (V4L2_FIELD_TOP == buf->vb.field) { | |
| 55 | + if (V4L2_FIELD_TOP == dev->ts_field) { | |
| 55 | 56 | dprintk("- [top] buf=%p next=%p\n",buf,next); |
| 56 | 57 | saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf)); |
| 57 | 58 | saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next)); |
| 59 | + dev->ts_field = V4L2_FIELD_BOTTOM; | |
| 58 | 60 | } else { |
| 59 | 61 | dprintk("- [bottom] buf=%p next=%p\n",buf,next); |
| 60 | 62 | saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next)); |
| 61 | 63 | saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf)); |
| 64 | + dev->ts_field = V4L2_FIELD_TOP; | |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | 67 | /* start DMA */ |
| @@ -72,96 +75,123 @@ static int buffer_activate(struct saa7134_dev *dev, · 7 unmodified lines | ||
| 72 | 75 | return 0; |
| 73 | 76 | } |
| 74 | 77 | |
| 75 | −static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |
| 76 | − enum v4l2_field field) | |
| 78 | +int saa7134_ts_buffer_init(struct vb2_buffer *vb2) | |
| 77 | 79 | { |
| 78 | − struct saa7134_dev *dev = q->priv_data; | |
| 79 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 80 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 81 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 82 | + | |
| 83 | + dmaq->curr = NULL; | |
| 84 | + buf->activate = buffer_activate; | |
| 85 | + | |
| 86 | + return 0; | |
| 87 | +} | |
| 88 | +EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init); | |
| 89 | + | |
| 90 | +int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2) | |
| 91 | +{ | |
| 92 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 93 | + struct saa7134_dev *dev = dmaq->dev; | |
| 94 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 95 | + struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0); | |
| 80 | 96 | unsigned int lines, llength, size; |
| 81 | − int err; | |
| 97 | + int ret; | |
| 82 | 98 | |
| 83 | − dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); | |
| 99 | + dprintk("buffer_prepare [%p]\n", buf); | |
| 84 | 100 | |
| 85 | 101 | llength = TS_PACKET_SIZE; |
| 86 | 102 | lines = dev->ts.nr_packets; |
| 87 | 103 | |
| 88 | 104 | size = lines * llength; |
| 89 | − if (0 != buf->vb.baddr && buf->vb.bsize < size) | |
| 105 | + if (vb2_plane_size(vb2, 0) < size) | |
| 90 | 106 | return -EINVAL; |
| 91 | 107 | |
| 92 | − if (buf->vb.size != size) { | |
| 93 | − saa7134_dma_free(q,buf); | |
| 94 | − } | |
| 95 | − | |
| 96 | − if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | |
| 97 | − | |
| 98 | − struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | |
| 99 | − | |
| 100 | − dprintk("buffer_prepare: needs_init\n"); | |
| 101 | − | |
| 102 | − buf->vb.width = llength; | |
| 103 | − buf->vb.height = lines; | |
| 104 | − buf->vb.size = size; | |
| 105 | − buf->pt = &dev->ts.pt_ts; | |
| 106 | − | |
| 107 | − err = videobuf_iolock(q,&buf->vb,NULL); | |
| 108 | − if (err) | |
| 109 | − goto oops; | |
| 110 | − err = saa7134_pgtable_build(dev->pci,buf->pt, | |
| 111 | − dma->sglist, | |
| 112 | − dma->sglen, | |
| 113 | − saa7134_buffer_startpage(buf)); | |
| 114 | − if (err) | |
| 115 | − goto oops; | |
| 116 | − } | |
| 117 | − | |
| 118 | − buf->vb.state = VIDEOBUF_PREPARED; | |
| 119 | − buf->activate = buffer_activate; | |
| 120 | − buf->vb.field = field; | |
| 121 | − return 0; | |
| 108 | + vb2_set_plane_payload(vb2, 0, size); | |
| 109 | + vb2->v4l2_buf.field = dev->field; | |
| 122 | 110 | |
| 123 | − oops: | |
| 124 | − saa7134_dma_free(q,buf); | |
| 125 | − return err; | |
| 111 | + ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 112 | + if (!ret) | |
| 113 | + return -EIO; | |
| 114 | + return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, | |
| 115 | + saa7134_buffer_startpage(buf)); | |
| 126 | 116 | } |
| 117 | +EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare); | |
| 127 | 118 | |
| 128 | −static int | |
| 129 | −buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |
| 119 | +void saa7134_ts_buffer_finish(struct vb2_buffer *vb2) | |
| 130 | 120 | { |
| 131 | − struct saa7134_dev *dev = q->priv_data; | |
| 121 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 122 | + struct saa7134_dev *dev = dmaq->dev; | |
| 123 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 124 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 132 | 125 | |
| 133 | − *size = TS_PACKET_SIZE * dev->ts.nr_packets; | |
| 134 | − if (0 == *count) | |
| 135 | − *count = dev->ts.nr_bufs; | |
| 136 | − *count = saa7134_buffer_count(*size,*count); | |
| 126 | + dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 127 | +} | |
| 128 | +EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish); | |
| 137 | 129 | |
| 130 | +int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, | |
| 131 | + unsigned int *nbuffers, unsigned int *nplanes, | |
| 132 | + unsigned int sizes[], void *alloc_ctxs[]) | |
| 133 | +{ | |
| 134 | + struct saa7134_dmaqueue *dmaq = q->drv_priv; | |
| 135 | + struct saa7134_dev *dev = dmaq->dev; | |
| 136 | + int size = TS_PACKET_SIZE * dev->ts.nr_packets; | |
| 137 | + | |
| 138 | + if (0 == *nbuffers) | |
| 139 | + *nbuffers = dev->ts.nr_bufs; | |
| 140 | + *nbuffers = saa7134_buffer_count(size, *nbuffers); | |
| 141 | + if (*nbuffers < 3) | |
| 142 | + *nbuffers = 3; | |
| 143 | + *nplanes = 1; | |
| 144 | + sizes[0] = size; | |
| 138 | 145 | return 0; |
| 139 | 146 | } |
| 147 | +EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup); | |
| 140 | 148 | |
| 141 | −static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 149 | +int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count) | |
| 142 | 150 | { |
| 143 | − struct saa7134_dev *dev = q->priv_data; | |
| 144 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 145 | − | |
| 146 | − saa7134_buffer_queue(dev,&dev->ts_q,buf); | |
| 151 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 152 | + struct saa7134_dev *dev = dmaq->dev; | |
| 153 | + | |
| 154 | + /* | |
| 155 | + * Planar video capture and TS share the same DMA channel, | |
| 156 | + * so only one can be active at a time. | |
| 157 | + */ | |
| 158 | + if (vb2_is_busy(&dev->video_vbq) && dev->fmt->planar) { | |
| 159 | + struct saa7134_buf *buf, *tmp; | |
| 160 | + | |
| 161 | + list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) { | |
| 162 | + list_del(&buf->entry); | |
| 163 | + vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED); | |
| 164 | + } | |
| 165 | + if (dmaq->curr) { | |
| 166 | + vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED); | |
| 167 | + dmaq->curr = NULL; | |
| 168 | + } | |
| 169 | + return -EBUSY; | |
| 170 | + } | |
| 171 | + dmaq->seq_nr = 0; | |
| 172 | + return 0; | |
| 147 | 173 | } |
| 174 | +EXPORT_SYMBOL_GPL(saa7134_ts_start_streaming); | |
| 148 | 175 | |
| 149 | −static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 176 | +void saa7134_ts_stop_streaming(struct vb2_queue *vq) | |
| 150 | 177 | { |
| 151 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 152 | − struct saa7134_dev *dev = q->priv_data; | |
| 153 | − | |
| 154 | − if (dev->ts_started) | |
| 155 | − saa7134_ts_stop(dev); | |
| 178 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 179 | + struct saa7134_dev *dev = dmaq->dev; | |
| 156 | 180 | |
| 157 | − saa7134_dma_free(q,buf); | |
| 181 | + saa7134_ts_stop(dev); | |
| 182 | + saa7134_stop_streaming(dev, dmaq); | |
| 158 | 183 | } |
| 159 | − | |
| 160 | −struct videobuf_queue_ops saa7134_ts_qops = { | |
| 161 | − .buf_setup = buffer_setup, | |
| 162 | − .buf_prepare = buffer_prepare, | |
| 163 | − .buf_queue = buffer_queue, | |
| 164 | − .buf_release = buffer_release, | |
| 184 | +EXPORT_SYMBOL_GPL(saa7134_ts_stop_streaming); | |
| 185 | + | |
| 186 | +struct vb2_ops saa7134_ts_qops = { | |
| 187 | + .queue_setup = saa7134_ts_queue_setup, | |
| 188 | + .buf_init = saa7134_ts_buffer_init, | |
| 189 | + .buf_prepare = saa7134_ts_buffer_prepare, | |
| 190 | + .buf_finish = saa7134_ts_buffer_finish, | |
| 191 | + .buf_queue = saa7134_vb2_buffer_queue, | |
| 192 | + .wait_prepare = vb2_ops_wait_prepare, | |
| 193 | + .wait_finish = vb2_ops_wait_finish, | |
| 194 | + .stop_streaming = saa7134_ts_stop_streaming, | |
| 165 | 195 | }; |
| 166 | 196 | EXPORT_SYMBOL_GPL(saa7134_ts_qops); |
| 167 | 197 | |
| @@ -213,7 +243,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev) · 45 unmodified lines | ||
| 213 | 243 | dev->ts_q.dev = dev; |
| 214 | 244 | dev->ts_q.need_two = 1; |
| 215 | 245 | dev->ts_started = 0; |
| 216 | − saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); | |
| 246 | + saa7134_pgtable_alloc(dev->pci, &dev->ts_q.pt); | |
| 217 | 247 | |
| 218 | 248 | /* init TS hw */ |
| 219 | 249 | saa7134_ts_init_hw(dev); |
| @@ -226,7 +256,8 @@ int saa7134_ts_stop(struct saa7134_dev *dev) · 6 unmodified lines | ||
| 226 | 256 | { |
| 227 | 257 | dprintk("TS stop\n"); |
| 228 | 258 | |
| 229 | − BUG_ON(!dev->ts_started); | |
| 259 | + if (!dev->ts_started) | |
| 260 | + return 0; | |
| 230 | 261 | |
| 231 | 262 | /* Stop TS stream */ |
| 232 | 263 | switch (saa7134_boards[dev->board].ts_type) { |
| @@ -247,7 +278,8 @@ int saa7134_ts_start(struct saa7134_dev *dev) · 14 unmodified lines | ||
| 247 | 278 | { |
| 248 | 279 | dprintk("TS start\n"); |
| 249 | 280 | |
| 250 | − BUG_ON(dev->ts_started); | |
| 281 | + if (WARN_ON(dev->ts_started)) | |
| 282 | + return 0; | |
| 251 | 283 | |
| 252 | 284 | /* dma: setup channel 5 (= TS) */ |
| 253 | 285 | saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); |
| @@ -259,7 +291,7 @@ int saa7134_ts_start(struct saa7134_dev *dev) · 5 unmodified lines | ||
| 259 | 291 | saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); |
| 260 | 292 | saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | |
| 261 | 293 | SAA7134_RS_CONTROL_ME | |
| 262 | − (dev->ts.pt_ts.dma >> 12)); | |
| 294 | + (dev->ts_q.pt.dma >> 12)); | |
| 263 | 295 | |
| 264 | 296 | /* reset hardware TS buffers */ |
| 265 | 297 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); |
| @@ -293,7 +325,7 @@ int saa7134_ts_start(struct saa7134_dev *dev) · 27 unmodified lines | ||
| 293 | 325 | |
| 294 | 326 | int saa7134_ts_fini(struct saa7134_dev *dev) |
| 295 | 327 | { |
| 296 | − saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts); | |
| 328 | + saa7134_pgtable_free(dev->pci, &dev->ts_q.pt); | |
| 297 | 329 | return 0; |
| 298 | 330 | } |
| 299 | 331 | |
| @@ -303,25 +335,18 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) · 3 unmodified lines | ||
| 303 | 335 | |
| 304 | 336 | spin_lock(&dev->slock); |
| 305 | 337 | if (dev->ts_q.curr) { |
| 306 | − field = dev->ts_q.curr->vb.field; | |
| 307 | − if (field == V4L2_FIELD_TOP) { | |
| 338 | + field = dev->ts_field; | |
| 339 | + if (field != V4L2_FIELD_TOP) { | |
| 308 | 340 | if ((status & 0x100000) != 0x000000) |
| 309 | 341 | goto done; |
| 310 | 342 | } else { |
| 311 | 343 | if ((status & 0x100000) != 0x100000) |
| 312 | 344 | goto done; |
| 313 | 345 | } |
| 314 | − saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE); | |
| 346 | + saa7134_buffer_finish(dev, &dev->ts_q, VB2_BUF_STATE_DONE); | |
| 315 | 347 | } |
| 316 | 348 | saa7134_buffer_next(dev,&dev->ts_q); |
| 317 | 349 | |
| 318 | 350 | done: |
| 319 | 351 | spin_unlock(&dev->slock); |
| 320 | 352 | } |
| 321 | − | |
| 322 | −/* ----------------------------------------------------------- */ | |
| 323 | −/* | |
| 324 | − * Local variables: | |
| 325 | − * c-basic-offset: 8 | |
| 326 | − * End: | |
| 327 | − */ | |
| @@ -1079,10 +1079,3 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) · 1078 unmodified lines | ||
| 1079 | 1079 | |
| 1080 | 1080 | EXPORT_SYMBOL(saa_dsp_writel); |
| 1081 | 1081 | EXPORT_SYMBOL(saa7134_tvaudio_setmute); |
| 1082 | − | |
| 1083 | −/* ----------------------------------------------------------- */ | |
| 1084 | −/* | |
| 1085 | − * Local variables: | |
| 1086 | − * c-basic-offset: 8 | |
| 1087 | − * End: | |
| 1088 | − */ | |
| @@ -67,10 +67,10 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf, · 66 unmodified lines | ||
| 67 | 67 | saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task), 0x00); |
| 68 | 68 | saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00); |
| 69 | 69 | |
| 70 | − saa_writeb(SAA7134_VBI_H_LEN1(task), buf->vb.width & 0xff); | |
| 71 | − saa_writeb(SAA7134_VBI_H_LEN2(task), buf->vb.width >> 8); | |
| 72 | − saa_writeb(SAA7134_VBI_V_LEN1(task), buf->vb.height & 0xff); | |
| 73 | − saa_writeb(SAA7134_VBI_V_LEN2(task), buf->vb.height >> 8); | |
| 70 | + saa_writeb(SAA7134_VBI_H_LEN1(task), dev->vbi_hlen & 0xff); | |
| 71 | + saa_writeb(SAA7134_VBI_H_LEN2(task), dev->vbi_hlen >> 8); | |
| 72 | + saa_writeb(SAA7134_VBI_V_LEN1(task), dev->vbi_vlen & 0xff); | |
| 73 | + saa_writeb(SAA7134_VBI_V_LEN2(task), dev->vbi_vlen >> 8); | |
| 74 | 74 | |
| 75 | 75 | saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00); |
| 76 | 76 | } |
| @@ -81,14 +81,14 @@ static int buffer_activate(struct saa7134_dev *dev, · 4 unmodified lines | ||
| 81 | 81 | struct saa7134_buf *buf, |
| 82 | 82 | struct saa7134_buf *next) |
| 83 | 83 | { |
| 84 | − unsigned long control,base; | |
| 84 | + struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv; | |
| 85 | + unsigned long control, base; | |
| 85 | 86 | |
| 86 | − dprintk("buffer_activate [%p]\n",buf); | |
| 87 | − buf->vb.state = VIDEOBUF_ACTIVE; | |
| 87 | + dprintk("buffer_activate [%p]\n", buf); | |
| 88 | 88 | buf->top_seen = 0; |
| 89 | 89 | |
| 90 | − task_init(dev,buf,TASK_A); | |
| 91 | − task_init(dev,buf,TASK_B); | |
| 90 | + task_init(dev, buf, TASK_A); | |
| 91 | + task_init(dev, buf, TASK_B); | |
| 92 | 92 | saa_writeb(SAA7134_OFMT_DATA_A, 0x06); |
| 93 | 93 | saa_writeb(SAA7134_OFMT_DATA_B, 0x06); |
| 94 | 94 | |
| @@ -96,107 +96,99 @@ static int buffer_activate(struct saa7134_dev *dev, · 1 unmodified line | ||
| 96 | 96 | base = saa7134_buffer_base(buf); |
| 97 | 97 | control = SAA7134_RS_CONTROL_BURST_16 | |
| 98 | 98 | SAA7134_RS_CONTROL_ME | |
| 99 | − (buf->pt->dma >> 12); | |
| 100 | − saa_writel(SAA7134_RS_BA1(2),base); | |
| 101 | − saa_writel(SAA7134_RS_BA2(2),base + buf->vb.size/2); | |
| 102 | − saa_writel(SAA7134_RS_PITCH(2),buf->vb.width); | |
| 103 | − saa_writel(SAA7134_RS_CONTROL(2),control); | |
| 104 | − saa_writel(SAA7134_RS_BA1(3),base); | |
| 105 | − saa_writel(SAA7134_RS_BA2(3),base + buf->vb.size/2); | |
| 106 | − saa_writel(SAA7134_RS_PITCH(3),buf->vb.width); | |
| 107 | − saa_writel(SAA7134_RS_CONTROL(3),control); | |
| 99 | + (dmaq->pt.dma >> 12); | |
| 100 | + saa_writel(SAA7134_RS_BA1(2), base); | |
| 101 | + saa_writel(SAA7134_RS_BA2(2), base + dev->vbi_hlen * dev->vbi_vlen); | |
| 102 | + saa_writel(SAA7134_RS_PITCH(2), dev->vbi_hlen); | |
| 103 | + saa_writel(SAA7134_RS_CONTROL(2), control); | |
| 104 | + saa_writel(SAA7134_RS_BA1(3), base); | |
| 105 | + saa_writel(SAA7134_RS_BA2(3), base + dev->vbi_hlen * dev->vbi_vlen); | |
| 106 | + saa_writel(SAA7134_RS_PITCH(3), dev->vbi_hlen); | |
| 107 | + saa_writel(SAA7134_RS_CONTROL(3), control); | |
| 108 | 108 | |
| 109 | 109 | /* start DMA */ |
| 110 | 110 | saa7134_set_dmabits(dev); |
| 111 | − mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT); | |
| 111 | + mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT); | |
| 112 | 112 | |
| 113 | 113 | return 0; |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | −static int buffer_prepare(struct videobuf_queue *q, | |
| 117 | − struct videobuf_buffer *vb, | |
| 118 | − enum v4l2_field field) | |
| 116 | +static int buffer_prepare(struct vb2_buffer *vb2) | |
| 119 | 117 | { |
| 120 | − struct saa7134_dev *dev = q->priv_data; | |
| 121 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 122 | − struct saa7134_tvnorm *norm = dev->tvnorm; | |
| 123 | − unsigned int lines, llength, size; | |
| 124 | − int err; | |
| 125 | − | |
| 126 | − lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1; | |
| 127 | − if (lines > VBI_LINE_COUNT) | |
| 128 | − lines = VBI_LINE_COUNT; | |
| 129 | − llength = VBI_LINE_LENGTH; | |
| 130 | − size = lines * llength * 2; | |
| 131 | − if (0 != buf->vb.baddr && buf->vb.bsize < size) | |
| 118 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 119 | + struct saa7134_dev *dev = dmaq->dev; | |
| 120 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 121 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 122 | + unsigned int size; | |
| 123 | + int ret; | |
| 124 | + | |
| 125 | + if (dma->sgl->offset) { | |
| 126 | + pr_err("The buffer is not page-aligned\n"); | |
| 132 | 127 | return -EINVAL; |
| 133 | − | |
| 134 | − if (buf->vb.size != size) | |
| 135 | − saa7134_dma_free(q,buf); | |
| 136 | − | |
| 137 | − if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | |
| 138 | − struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | |
| 139 | − | |
| 140 | − buf->vb.width = llength; | |
| 141 | − buf->vb.height = lines; | |
| 142 | − buf->vb.size = size; | |
| 143 | − buf->pt = &dev->pt_vbi; | |
| 144 | − | |
| 145 | − err = videobuf_iolock(q,&buf->vb,NULL); | |
| 146 | − if (err) | |
| 147 | − goto oops; | |
| 148 | − err = saa7134_pgtable_build(dev->pci,buf->pt, | |
| 149 | − dma->sglist, | |
| 150 | − dma->sglen, | |
| 151 | − saa7134_buffer_startpage(buf)); | |
| 152 | − if (err) | |
| 153 | − goto oops; | |
| 154 | 128 | } |
| 155 | − buf->vb.state = VIDEOBUF_PREPARED; | |
| 156 | − buf->activate = buffer_activate; | |
| 157 | − buf->vb.field = field; | |
| 158 | − return 0; | |
| 129 | + size = dev->vbi_hlen * dev->vbi_vlen * 2; | |
| 130 | + if (vb2_plane_size(vb2, 0) < size) | |
| 131 | + return -EINVAL; | |
| 132 | + | |
| 133 | + vb2_set_plane_payload(vb2, 0, size); | |
| 159 | 134 | |
| 160 | − oops: | |
| 161 | − saa7134_dma_free(q,buf); | |
| 162 | − return err; | |
| 135 | + ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 136 | + if (!ret) | |
| 137 | + return -EIO; | |
| 138 | + return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, | |
| 139 | + saa7134_buffer_startpage(buf)); | |
| 163 | 140 | } |
| 164 | 141 | |
| 165 | −static int | |
| 166 | −buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |
| 142 | +static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, | |
| 143 | + unsigned int *nbuffers, unsigned int *nplanes, | |
| 144 | + unsigned int sizes[], void *alloc_ctxs[]) | |
| 167 | 145 | { |
| 168 | − struct saa7134_dev *dev = q->priv_data; | |
| 169 | − int llength,lines; | |
| 170 | − | |
| 171 | − lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1; | |
| 172 | − llength = VBI_LINE_LENGTH; | |
| 173 | − *size = lines * llength * 2; | |
| 174 | − if (0 == *count) | |
| 175 | − *count = vbibufs; | |
| 176 | − *count = saa7134_buffer_count(*size,*count); | |
| 146 | + struct saa7134_dmaqueue *dmaq = q->drv_priv; | |
| 147 | + struct saa7134_dev *dev = dmaq->dev; | |
| 148 | + unsigned int size; | |
| 149 | + | |
| 150 | + dev->vbi_vlen = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 + 1; | |
| 151 | + if (dev->vbi_vlen > VBI_LINE_COUNT) | |
| 152 | + dev->vbi_vlen = VBI_LINE_COUNT; | |
| 153 | + dev->vbi_hlen = VBI_LINE_LENGTH; | |
| 154 | + size = dev->vbi_hlen * dev->vbi_vlen * 2; | |
| 155 | + | |
| 156 | + *nbuffers = saa7134_buffer_count(size, *nbuffers); | |
| 157 | + *nplanes = 1; | |
| 158 | + sizes[0] = size; | |
| 177 | 159 | return 0; |
| 178 | 160 | } |
| 179 | 161 | |
| 180 | −static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 162 | +static int buffer_init(struct vb2_buffer *vb2) | |
| 181 | 163 | { |
| 182 | − struct saa7134_dev *dev = q->priv_data; | |
| 183 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 164 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 165 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 184 | 166 | |
| 185 | − saa7134_buffer_queue(dev,&dev->vbi_q,buf); | |
| 167 | + dmaq->curr = NULL; | |
| 168 | + buf->activate = buffer_activate; | |
| 169 | + return 0; | |
| 186 | 170 | } |
| 187 | 171 | |
| 188 | −static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 172 | +static void buffer_finish(struct vb2_buffer *vb2) | |
| 189 | 173 | { |
| 190 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 174 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 175 | + struct saa7134_dev *dev = dmaq->dev; | |
| 176 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 177 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 191 | 178 | |
| 192 | − saa7134_dma_free(q,buf); | |
| 179 | + dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 193 | 180 | } |
| 194 | 181 | |
| 195 | −struct videobuf_queue_ops saa7134_vbi_qops = { | |
| 196 | − .buf_setup = buffer_setup, | |
| 197 | − .buf_prepare = buffer_prepare, | |
| 198 | − .buf_queue = buffer_queue, | |
| 199 | − .buf_release = buffer_release, | |
| 182 | +struct vb2_ops saa7134_vbi_qops = { | |
| 183 | + .queue_setup = queue_setup, | |
| 184 | + .buf_init = buffer_init, | |
| 185 | + .buf_prepare = buffer_prepare, | |
| 186 | + .buf_finish = buffer_finish, | |
| 187 | + .buf_queue = saa7134_vb2_buffer_queue, | |
| 188 | + .wait_prepare = vb2_ops_wait_prepare, | |
| 189 | + .wait_finish = vb2_ops_wait_finish, | |
| 190 | + .start_streaming = saa7134_vb2_start_streaming, | |
| 191 | + .stop_streaming = saa7134_vb2_stop_streaming, | |
| 200 | 192 | }; |
| 201 | 193 | |
| 202 | 194 | /* ------------------------------------------------------------------ */ |
| @@ -226,7 +218,6 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status) · 23 unmodified lines | ||
| 226 | 218 | { |
| 227 | 219 | spin_lock(&dev->slock); |
| 228 | 220 | if (dev->vbi_q.curr) { |
| 229 | − dev->vbi_fieldcount++; | |
| 230 | 221 | /* make sure we have seen both fields */ |
| 231 | 222 | if ((status & 0x10) == 0x00) { |
| 232 | 223 | dev->vbi_q.curr->top_seen = 1; |
| @@ -235,18 +226,10 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status) · 2 unmodified lines | ||
| 235 | 226 | if (!dev->vbi_q.curr->top_seen) |
| 236 | 227 | goto done; |
| 237 | 228 | |
| 238 | − dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount; | |
| 239 | − saa7134_buffer_finish(dev,&dev->vbi_q,VIDEOBUF_DONE); | |
| 229 | + saa7134_buffer_finish(dev, &dev->vbi_q, VB2_BUF_STATE_DONE); | |
| 240 | 230 | } |
| 241 | − saa7134_buffer_next(dev,&dev->vbi_q); | |
| 231 | + saa7134_buffer_next(dev, &dev->vbi_q); | |
| 242 | 232 | |
| 243 | 233 | done: |
| 244 | 234 | spin_unlock(&dev->slock); |
| 245 | 235 | } |
| 246 | − | |
| 247 | −/* ----------------------------------------------------------- */ | |
| 248 | −/* | |
| 249 | − * Local variables: | |
| 250 | − * c-basic-offset: 8 | |
| 251 | − * End: | |
| 252 | − */ | |
| @@ -381,42 +381,6 @@ static struct saa7134_format* format_by_fourcc(unsigned int fourcc) · 380 unmodified lines | ||
| 381 | 381 | return NULL; |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | −/* ----------------------------------------------------------------------- */ | |
| 385 | −/* resource management */ | |
| 386 | − | |
| 387 | −static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit) | |
| 388 | −{ | |
| 389 | − if (fh->resources & bit) | |
| 390 | − /* have it already allocated */ | |
| 391 | − return 1; | |
| 392 | − | |
| 393 | − /* is it free? */ | |
| 394 | − mutex_lock(&dev->lock); | |
| 395 | − if (dev->resources & bit) { | |
| 396 | − /* no, someone else uses it */ | |
| 397 | − mutex_unlock(&dev->lock); | |
| 398 | − return 0; | |
| 399 | − } | |
| 400 | − /* it's free, grab it */ | |
| 401 | − fh->resources |= bit; | |
| 402 | − dev->resources |= bit; | |
| 403 | − dprintk("res: get %d\n",bit); | |
| 404 | − mutex_unlock(&dev->lock); | |
| 405 | − return 1; | |
| 406 | −} | |
| 407 | − | |
| 408 | −static | |
| 409 | −void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) | |
| 410 | −{ | |
| 411 | − BUG_ON((fh->resources & bits) != bits); | |
| 412 | − | |
| 413 | − mutex_lock(&dev->lock); | |
| 414 | − fh->resources &= ~bits; | |
| 415 | − dev->resources &= ~bits; | |
| 416 | − dprintk("res: put %d\n",bits); | |
| 417 | − mutex_unlock(&dev->lock); | |
| 418 | −} | |
| 419 | − | |
| 420 | 384 | /* ------------------------------------------------------------------ */ |
| 421 | 385 | |
| 422 | 386 | static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) |
| @@ -452,19 +416,26 @@ static void video_mux(struct saa7134_dev *dev, int input) · 29 unmodified lines | ||
| 452 | 416 | |
| 453 | 417 | static void saa7134_set_decoder(struct saa7134_dev *dev) |
| 454 | 418 | { |
| 455 | − int luma_control, sync_control, mux; | |
| 419 | + int luma_control, sync_control, chroma_ctrl1, mux; | |
| 456 | 420 | |
| 457 | 421 | struct saa7134_tvnorm *norm = dev->tvnorm; |
| 458 | 422 | mux = card_in(dev, dev->ctl_input).vmux; |
| 459 | 423 | |
| 460 | 424 | luma_control = norm->luma_control; |
| 461 | 425 | sync_control = norm->sync_control; |
| 426 | + chroma_ctrl1 = norm->chroma_ctrl1; | |
| 462 | 427 | |
| 463 | 428 | if (mux > 5) |
| 464 | 429 | luma_control |= 0x80; /* svideo */ |
| 465 | 430 | if (noninterlaced || dev->nosignal) |
| 466 | 431 | sync_control |= 0x20; |
| 467 | 432 | |
| 433 | + /* switch on auto standard detection */ | |
| 434 | + sync_control |= SAA7134_SYNC_CTRL_AUFD; | |
| 435 | + chroma_ctrl1 |= SAA7134_CHROMA_CTRL1_AUTO0; | |
| 436 | + chroma_ctrl1 &= ~SAA7134_CHROMA_CTRL1_FCTC; | |
| 437 | + luma_control &= ~SAA7134_LUMA_CTRL_LDEL; | |
| 438 | + | |
| 468 | 439 | /* setup video decoder */ |
| 469 | 440 | saa_writeb(SAA7134_INCR_DELAY, 0x08); |
| 470 | 441 | saa_writeb(SAA7134_ANALOG_IN_CTRL1, 0xc0 | mux); |
| @@ -487,7 +458,7 @@ static void saa7134_set_decoder(struct saa7134_dev *dev) · 16 unmodified lines | ||
| 487 | 458 | dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation); |
| 488 | 459 | |
| 489 | 460 | saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue); |
| 490 | − saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1); | |
| 461 | + saa_writeb(SAA7134_CHROMA_CTRL1, chroma_ctrl1); | |
| 491 | 462 | saa_writeb(SAA7134_CHROMA_GAIN, norm->chroma_gain); |
| 492 | 463 | |
| 493 | 464 | saa_writeb(SAA7134_CHROMA_CTRL2, norm->chroma_ctrl2); |
| @@ -506,10 +477,10 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) · 12 unmodified lines | ||
| 506 | 477 | saa7134_set_decoder(dev); |
| 507 | 478 | |
| 508 | 479 | if (card_in(dev, dev->ctl_input).tv) |
| 509 | − saa_call_all(dev, core, s_std, dev->tvnorm->id); | |
| 480 | + saa_call_all(dev, video, s_std, dev->tvnorm->id); | |
| 510 | 481 | /* Set the correct norm for the saa6752hs. This function |
| 511 | 482 | does nothing if there is no saa6752hs. */ |
| 512 | − saa_call_empress(dev, core, s_std, dev->tvnorm->id); | |
| 483 | + saa_call_empress(dev, video, s_std, dev->tvnorm->id); | |
| 513 | 484 | } |
| 514 | 485 | |
| 515 | 486 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) |
| @@ -817,35 +788,35 @@ static int buffer_activate(struct saa7134_dev *dev, · 301 unmodified lines | ||
| 817 | 788 | struct saa7134_buf *buf, |
| 818 | 789 | struct saa7134_buf *next) |
| 819 | 790 | { |
| 791 | + struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv; | |
| 820 | 792 | unsigned long base,control,bpl; |
| 821 | 793 | unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */ |
| 822 | 794 | |
| 823 | 795 | dprintk("buffer_activate buf=%p\n",buf); |
| 824 | − buf->vb.state = VIDEOBUF_ACTIVE; | |
| 825 | 796 | buf->top_seen = 0; |
| 826 | 797 | |
| 827 | − set_size(dev,TASK_A,buf->vb.width,buf->vb.height, | |
| 828 | − V4L2_FIELD_HAS_BOTH(buf->vb.field)); | |
| 829 | − if (buf->fmt->yuv) | |
| 798 | + set_size(dev, TASK_A, dev->width, dev->height, | |
| 799 | + V4L2_FIELD_HAS_BOTH(dev->field)); | |
| 800 | + if (dev->fmt->yuv) | |
| 830 | 801 | saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03); |
| 831 | 802 | else |
| 832 | 803 | saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01); |
| 833 | − saa_writeb(SAA7134_OFMT_VIDEO_A, buf->fmt->pm); | |
| 804 | + saa_writeb(SAA7134_OFMT_VIDEO_A, dev->fmt->pm); | |
| 834 | 805 | |
| 835 | 806 | /* DMA: setup channel 0 (= Video Task A0) */ |
| 836 | 807 | base = saa7134_buffer_base(buf); |
| 837 | − if (buf->fmt->planar) | |
| 838 | − bpl = buf->vb.width; | |
| 808 | + if (dev->fmt->planar) | |
| 809 | + bpl = dev->width; | |
| 839 | 810 | else |
| 840 | − bpl = (buf->vb.width * buf->fmt->depth) / 8; | |
| 811 | + bpl = (dev->width * dev->fmt->depth) / 8; | |
| 841 | 812 | control = SAA7134_RS_CONTROL_BURST_16 | |
| 842 | 813 | SAA7134_RS_CONTROL_ME | |
| 843 | − (buf->pt->dma >> 12); | |
| 844 | − if (buf->fmt->bswap) | |
| 814 | + (dmaq->pt.dma >> 12); | |
| 815 | + if (dev->fmt->bswap) | |
| 845 | 816 | control |= SAA7134_RS_CONTROL_BSWAP; |
| 846 | − if (buf->fmt->wswap) | |
| 817 | + if (dev->fmt->wswap) | |
| 847 | 818 | control |= SAA7134_RS_CONTROL_WSWAP; |
| 848 | − if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) { | |
| 819 | + if (V4L2_FIELD_HAS_BOTH(dev->field)) { | |
| 849 | 820 | /* interlaced */ |
| 850 | 821 | saa_writel(SAA7134_RS_BA1(0),base); |
| 851 | 822 | saa_writel(SAA7134_RS_BA2(0),base+bpl); |
| @@ -858,17 +829,17 @@ static int buffer_activate(struct saa7134_dev *dev, · 6 unmodified lines | ||
| 858 | 829 | } |
| 859 | 830 | saa_writel(SAA7134_RS_CONTROL(0),control); |
| 860 | 831 | |
| 861 | − if (buf->fmt->planar) { | |
| 832 | + if (dev->fmt->planar) { | |
| 862 | 833 | /* DMA: setup channel 4+5 (= planar task A) */ |
| 863 | − bpl_uv = bpl >> buf->fmt->hshift; | |
| 864 | − lines_uv = buf->vb.height >> buf->fmt->vshift; | |
| 865 | − base2 = base + bpl * buf->vb.height; | |
| 834 | + bpl_uv = bpl >> dev->fmt->hshift; | |
| 835 | + lines_uv = dev->height >> dev->fmt->vshift; | |
| 836 | + base2 = base + bpl * dev->height; | |
| 866 | 837 | base3 = base2 + bpl_uv * lines_uv; |
| 867 | − if (buf->fmt->uvswap) | |
| 838 | + if (dev->fmt->uvswap) | |
| 868 | 839 | tmp = base2, base2 = base3, base3 = tmp; |
| 869 | 840 | dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n", |
| 870 | 841 | bpl_uv,lines_uv,base2,base3); |
| 871 | − if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) { | |
| 842 | + if (V4L2_FIELD_HAS_BOTH(dev->field)) { | |
| 872 | 843 | /* interlaced */ |
| 873 | 844 | saa_writel(SAA7134_RS_BA1(4),base2); |
| 874 | 845 | saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv); |
| @@ -891,22 +862,65 @@ static int buffer_activate(struct saa7134_dev *dev, · 16 unmodified lines | ||
| 891 | 862 | |
| 892 | 863 | /* start DMA */ |
| 893 | 864 | saa7134_set_dmabits(dev); |
| 894 | − mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT); | |
| 865 | + mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT); | |
| 866 | + return 0; | |
| 867 | +} | |
| 868 | + | |
| 869 | +static int buffer_init(struct vb2_buffer *vb2) | |
| 870 | +{ | |
| 871 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 872 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 873 | + | |
| 874 | + dmaq->curr = NULL; | |
| 875 | + buf->activate = buffer_activate; | |
| 895 | 876 | return 0; |
| 896 | 877 | } |
| 897 | 878 | |
| 898 | −static int buffer_prepare(struct videobuf_queue *q, | |
| 899 | − struct videobuf_buffer *vb, | |
| 900 | − enum v4l2_field field) | |
| 879 | +static int buffer_prepare(struct vb2_buffer *vb2) | |
| 901 | 880 | { |
| 902 | − struct saa7134_dev *dev = q->priv_data; | |
| 903 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 881 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 882 | + struct saa7134_dev *dev = dmaq->dev; | |
| 883 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 884 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 904 | 885 | unsigned int size; |
| 905 | − int err; | |
| 886 | + int ret; | |
| 906 | 887 | |
| 907 | − /* sanity checks */ | |
| 908 | − if (NULL == dev->fmt) | |
| 888 | + if (dma->sgl->offset) { | |
| 889 | + pr_err("The buffer is not page-aligned\n"); | |
| 909 | 890 | return -EINVAL; |
| 891 | + } | |
| 892 | + size = (dev->width * dev->height * dev->fmt->depth) >> 3; | |
| 893 | + if (vb2_plane_size(vb2, 0) < size) | |
| 894 | + return -EINVAL; | |
| 895 | + | |
| 896 | + vb2_set_plane_payload(vb2, 0, size); | |
| 897 | + vb2->v4l2_buf.field = dev->field; | |
| 898 | + | |
| 899 | + ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 900 | + if (!ret) | |
| 901 | + return -EIO; | |
| 902 | + return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents, | |
| 903 | + saa7134_buffer_startpage(buf)); | |
| 904 | +} | |
| 905 | + | |
| 906 | +static void buffer_finish(struct vb2_buffer *vb2) | |
| 907 | +{ | |
| 908 | + struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv; | |
| 909 | + struct saa7134_dev *dev = dmaq->dev; | |
| 910 | + struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2); | |
| 911 | + struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0); | |
| 912 | + | |
| 913 | + dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE); | |
| 914 | +} | |
| 915 | + | |
| 916 | +static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, | |
| 917 | + unsigned int *nbuffers, unsigned int *nplanes, | |
| 918 | + unsigned int sizes[], void *alloc_ctxs[]) | |
| 919 | +{ | |
| 920 | + struct saa7134_dmaqueue *dmaq = q->drv_priv; | |
| 921 | + struct saa7134_dev *dev = dmaq->dev; | |
| 922 | + int size = dev->fmt->depth * dev->width * dev->height >> 3; | |
| 923 | + | |
| 910 | 924 | if (dev->width < 48 || |
| 911 | 925 | dev->height < 32 || |
| 912 | 926 | dev->width/4 > dev->crop_current.width || |
| @@ -914,83 +928,88 @@ static int buffer_prepare(struct videobuf_queue *q, · 1 unmodified line | ||
| 914 | 928 | dev->width > dev->crop_bounds.width || |
| 915 | 929 | dev->height > dev->crop_bounds.height) |
| 916 | 930 | return -EINVAL; |
| 917 | − size = (dev->width * dev->height * dev->fmt->depth) >> 3; | |
| 918 | − if (0 != buf->vb.baddr && buf->vb.bsize < size) | |
| 919 | − return -EINVAL; | |
| 920 | − | |
| 921 | − dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n", | |
| 922 | − vb->i, dev->width, dev->height, size, v4l2_field_names[field], | |
| 923 | − dev->fmt->name); | |
| 924 | − if (buf->vb.width != dev->width || | |
| 925 | − buf->vb.height != dev->height || | |
| 926 | − buf->vb.size != size || | |
| 927 | − buf->vb.field != field || | |
| 928 | − buf->fmt != dev->fmt) { | |
| 929 | − saa7134_dma_free(q,buf); | |
| 930 | − } | |
| 931 | 931 | |
| 932 | − if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | |
| 933 | − struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | |
| 934 | − | |
| 935 | − buf->vb.width = dev->width; | |
| 936 | − buf->vb.height = dev->height; | |
| 937 | − buf->vb.size = size; | |
| 938 | − buf->vb.field = field; | |
| 939 | − buf->fmt = dev->fmt; | |
| 940 | − buf->pt = &dev->pt_cap; | |
| 941 | − dev->video_q.curr = NULL; | |
| 942 | − | |
| 943 | − err = videobuf_iolock(q,&buf->vb,&dev->ovbuf); | |
| 944 | − if (err) | |
| 945 | − goto oops; | |
| 946 | − err = saa7134_pgtable_build(dev->pci,buf->pt, | |
| 947 | − dma->sglist, | |
| 948 | − dma->sglen, | |
| 949 | − saa7134_buffer_startpage(buf)); | |
| 950 | − if (err) | |
| 951 | − goto oops; | |
| 952 | − } | |
| 953 | − buf->vb.state = VIDEOBUF_PREPARED; | |
| 954 | − buf->activate = buffer_activate; | |
| 932 | + *nbuffers = saa7134_buffer_count(size, *nbuffers); | |
| 933 | + *nplanes = 1; | |
| 934 | + sizes[0] = size; | |
| 955 | 935 | return 0; |
| 956 | − | |
| 957 | − oops: | |
| 958 | − saa7134_dma_free(q,buf); | |
| 959 | − return err; | |
| 960 | 936 | } |
| 961 | 937 | |
| 962 | −static int | |
| 963 | −buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |
| 938 | +/* | |
| 939 | + * move buffer to hardware queue | |
| 940 | + */ | |
| 941 | +void saa7134_vb2_buffer_queue(struct vb2_buffer *vb) | |
| 964 | 942 | { |
| 965 | − struct saa7134_dev *dev = q->priv_data; | |
| 943 | + struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv; | |
| 944 | + struct saa7134_dev *dev = dmaq->dev; | |
| 945 | + struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2); | |
| 966 | 946 | |
| 967 | − *size = dev->fmt->depth * dev->width * dev->height >> 3; | |
| 968 | − if (0 == *count) | |
| 969 | − *count = gbuffers; | |
| 970 | − *count = saa7134_buffer_count(*size,*count); | |
| 971 | − return 0; | |
| 947 | + saa7134_buffer_queue(dev, dmaq, buf); | |
| 972 | 948 | } |
| 949 | +EXPORT_SYMBOL_GPL(saa7134_vb2_buffer_queue); | |
| 973 | 950 | |
| 974 | −static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 951 | +int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) | |
| 975 | 952 | { |
| 976 | − struct saa7134_dev *dev = q->priv_data; | |
| 977 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 953 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 954 | + struct saa7134_dev *dev = dmaq->dev; | |
| 955 | + | |
| 956 | + /* | |
| 957 | + * Planar video capture and TS share the same DMA channel, | |
| 958 | + * so only one can be active at a time. | |
| 959 | + */ | |
| 960 | + if (card_is_empress(dev) && vb2_is_busy(&dev->empress_vbq) && | |
| 961 | + dmaq == &dev->video_q && dev->fmt->planar) { | |
| 962 | + struct saa7134_buf *buf, *tmp; | |
| 978 | 963 | |
| 979 | − saa7134_buffer_queue(dev, &dev->video_q, buf); | |
| 964 | + list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) { | |
| 965 | + list_del(&buf->entry); | |
| 966 | + vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED); | |
| 967 | + } | |
| 968 | + if (dmaq->curr) { | |
| 969 | + vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED); | |
| 970 | + dmaq->curr = NULL; | |
| 971 | + } | |
| 972 | + return -EBUSY; | |
| 973 | + } | |
| 974 | + | |
| 975 | + /* The SAA7134 has a 1K FIFO; the datasheet suggests that when | |
| 976 | + * configured conservatively, there's 22 usec of buffering for video. | |
| 977 | + * We therefore request a DMA latency of 20 usec, giving us 2 usec of | |
| 978 | + * margin in case the FIFO is configured differently to the datasheet. | |
| 979 | + * Unfortunately, I lack register-level documentation to check the | |
| 980 | + * Linux FIFO setup and confirm the perfect value. | |
| 981 | + */ | |
| 982 | + if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) || | |
| 983 | + (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq))) | |
| 984 | + pm_qos_add_request(&dev->qos_request, | |
| 985 | + PM_QOS_CPU_DMA_LATENCY, 20); | |
| 986 | + dmaq->seq_nr = 0; | |
| 987 | + | |
| 988 | + return 0; | |
| 980 | 989 | } |
| 981 | 990 | |
| 982 | −static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | |
| 991 | +void saa7134_vb2_stop_streaming(struct vb2_queue *vq) | |
| 983 | 992 | { |
| 984 | − struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | |
| 993 | + struct saa7134_dmaqueue *dmaq = vq->drv_priv; | |
| 994 | + struct saa7134_dev *dev = dmaq->dev; | |
| 995 | + | |
| 996 | + saa7134_stop_streaming(dev, dmaq); | |
| 985 | 997 | |
| 986 | − saa7134_dma_free(q,buf); | |
| 998 | + if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) || | |
| 999 | + (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq))) | |
| 1000 | + pm_qos_remove_request(&dev->qos_request); | |
| 987 | 1001 | } |
| 988 | 1002 | |
| 989 | −static struct videobuf_queue_ops video_qops = { | |
| 990 | − .buf_setup = buffer_setup, | |
| 991 | − .buf_prepare = buffer_prepare, | |
| 992 | − .buf_queue = buffer_queue, | |
| 993 | − .buf_release = buffer_release, | |
| 1003 | +static struct vb2_ops vb2_qops = { | |
| 1004 | + .queue_setup = queue_setup, | |
| 1005 | + .buf_init = buffer_init, | |
| 1006 | + .buf_prepare = buffer_prepare, | |
| 1007 | + .buf_finish = buffer_finish, | |
| 1008 | + .buf_queue = saa7134_vb2_buffer_queue, | |
| 1009 | + .wait_prepare = vb2_ops_wait_prepare, | |
| 1010 | + .wait_finish = vb2_ops_wait_finish, | |
| 1011 | + .start_streaming = saa7134_vb2_start_streaming, | |
| 1012 | + .stop_streaming = saa7134_vb2_stop_streaming, | |
| 994 | 1013 | }; |
| 995 | 1014 | |
| 996 | 1015 | /* ------------------------------------------------------------------ */ |
| @@ -1068,7 +1087,7 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl) · 71 unmodified lines | ||
| 1068 | 1087 | default: |
| 1069 | 1088 | return -EINVAL; |
| 1070 | 1089 | } |
| 1071 | − if (restart_overlay && res_locked(dev, RESOURCE_OVERLAY)) { | |
| 1090 | + if (restart_overlay && dev->overlay_owner) { | |
| 1072 | 1091 | spin_lock_irqsave(&dev->slock, flags); |
| 1073 | 1092 | stop_preview(dev); |
| 1074 | 1093 | start_preview(dev); |
| @@ -1079,182 +1098,57 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl) · 4 unmodified lines | ||
| 1079 | 1098 | |
| 1080 | 1099 | /* ------------------------------------------------------------------ */ |
| 1081 | 1100 | |
| 1082 | −static struct videobuf_queue *saa7134_queue(struct file *file) | |
| 1101 | +static inline struct vb2_queue *saa7134_queue(struct file *file) | |
| 1083 | 1102 | { |
| 1084 | − struct video_device *vdev = video_devdata(file); | |
| 1085 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 1086 | − struct saa7134_fh *fh = file->private_data; | |
| 1087 | − struct videobuf_queue *q = NULL; | |
| 1088 | − | |
| 1089 | − switch (vdev->vfl_type) { | |
| 1090 | − case VFL_TYPE_GRABBER: | |
| 1091 | − q = fh->is_empress ? &dev->empress_tsq : &dev->cap; | |
| 1092 | − break; | |
| 1093 | − case VFL_TYPE_VBI: | |
| 1094 | − q = &dev->vbi; | |
| 1095 | − break; | |
| 1096 | − default: | |
| 1097 | − BUG(); | |
| 1098 | − } | |
| 1099 | − return q; | |
| 1100 | −} | |
| 1101 | − | |
| 1102 | −static int saa7134_resource(struct file *file) | |
| 1103 | −{ | |
| 1104 | − struct video_device *vdev = video_devdata(file); | |
| 1105 | − struct saa7134_fh *fh = file->private_data; | |
| 1106 | − | |
| 1107 | − if (vdev->vfl_type == VFL_TYPE_GRABBER) | |
| 1108 | − return fh->is_empress ? RESOURCE_EMPRESS : RESOURCE_VIDEO; | |
| 1109 | − | |
| 1110 | − if (vdev->vfl_type == VFL_TYPE_VBI) | |
| 1111 | − return RESOURCE_VBI; | |
| 1112 | − | |
| 1113 | − BUG(); | |
| 1114 | − return 0; | |
| 1103 | + return video_devdata(file)->queue; | |
| 1115 | 1104 | } |
| 1116 | 1105 | |
| 1117 | 1106 | static int video_open(struct file *file) |
| 1118 | 1107 | { |
| 1119 | 1108 | struct video_device *vdev = video_devdata(file); |
| 1120 | 1109 | struct saa7134_dev *dev = video_drvdata(file); |
| 1121 | − struct saa7134_fh *fh; | |
| 1122 | − | |
| 1123 | − /* allocate + initialize per filehandle data */ | |
| 1124 | − fh = kzalloc(sizeof(*fh),GFP_KERNEL); | |
| 1125 | − if (NULL == fh) | |
| 1126 | − return -ENOMEM; | |
| 1110 | + int ret = v4l2_fh_open(file); | |
| 1127 | 1111 | |
| 1128 | − v4l2_fh_init(&fh->fh, vdev); | |
| 1129 | − file->private_data = fh; | |
| 1112 | + if (ret < 0) | |
| 1113 | + return ret; | |
| 1130 | 1114 | |
| 1115 | + mutex_lock(&dev->lock); | |
| 1131 | 1116 | if (vdev->vfl_type == VFL_TYPE_RADIO) { |
| 1132 | 1117 | /* switch to radio mode */ |
| 1133 | − saa7134_tvaudio_setinput(dev,&card(dev).radio); | |
| 1118 | + saa7134_tvaudio_setinput(dev, &card(dev).radio); | |
| 1134 | 1119 | saa_call_all(dev, tuner, s_radio); |
| 1135 | 1120 | } else { |
| 1136 | 1121 | /* switch to video/vbi mode */ |
| 1137 | − video_mux(dev,dev->ctl_input); | |
| 1122 | + video_mux(dev, dev->ctl_input); | |
| 1138 | 1123 | } |
| 1139 | − v4l2_fh_add(&fh->fh); | |
| 1124 | + mutex_unlock(&dev->lock); | |
| 1140 | 1125 | |
| 1141 | 1126 | return 0; |
| 1142 | 1127 | } |
| 1143 | 1128 | |
| 1144 | −static ssize_t | |
| 1145 | −video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |
| 1146 | −{ | |
| 1147 | − struct video_device *vdev = video_devdata(file); | |
| 1148 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 1149 | − struct saa7134_fh *fh = file->private_data; | |
| 1150 | − | |
| 1151 | − switch (vdev->vfl_type) { | |
| 1152 | − case VFL_TYPE_GRABBER: | |
| 1153 | − if (res_locked(dev, RESOURCE_VIDEO)) | |
| 1154 | − return -EBUSY; | |
| 1155 | − return videobuf_read_one(saa7134_queue(file), | |
| 1156 | − data, count, ppos, | |
| 1157 | − file->f_flags & O_NONBLOCK); | |
| 1158 | − case VFL_TYPE_VBI: | |
| 1159 | − if (!res_get(dev, fh, RESOURCE_VBI)) | |
| 1160 | − return -EBUSY; | |
| 1161 | − return videobuf_read_stream(saa7134_queue(file), | |
| 1162 | − data, count, ppos, 1, | |
| 1163 | − file->f_flags & O_NONBLOCK); | |
| 1164 | − break; | |
| 1165 | − default: | |
| 1166 | − BUG(); | |
| 1167 | − return 0; | |
| 1168 | − } | |
| 1169 | −} | |
| 1170 | − | |
| 1171 | −static unsigned int | |
| 1172 | −video_poll(struct file *file, struct poll_table_struct *wait) | |
| 1173 | −{ | |
| 1174 | − unsigned long req_events = poll_requested_events(wait); | |
| 1175 | − struct video_device *vdev = video_devdata(file); | |
| 1176 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 1177 | − struct saa7134_fh *fh = file->private_data; | |
| 1178 | − struct videobuf_buffer *buf = NULL; | |
| 1179 | − unsigned int rc = 0; | |
| 1180 | − | |
| 1181 | − if (v4l2_event_pending(&fh->fh)) | |
| 1182 | − rc = POLLPRI; | |
| 1183 | − else if (req_events & POLLPRI) | |
| 1184 | − poll_wait(file, &fh->fh.wait, wait); | |
| 1185 | − | |
| 1186 | − if (vdev->vfl_type == VFL_TYPE_VBI) | |
| 1187 | − return rc | videobuf_poll_stream(file, &dev->vbi, wait); | |
| 1188 | − | |
| 1189 | − if (res_check(fh, RESOURCE_VIDEO)) { | |
| 1190 | − mutex_lock(&dev->cap.vb_lock); | |
| 1191 | − if (!list_empty(&dev->cap.stream)) | |
| 1192 | − buf = list_entry(dev->cap.stream.next, struct videobuf_buffer, stream); | |
| 1193 | − } else { | |
| 1194 | − mutex_lock(&dev->cap.vb_lock); | |
| 1195 | − if (UNSET == dev->cap.read_off) { | |
| 1196 | − /* need to capture a new frame */ | |
| 1197 | − if (res_locked(dev, RESOURCE_VIDEO)) | |
| 1198 | − goto err; | |
| 1199 | − if (0 != dev->cap.ops->buf_prepare(&dev->cap, | |
| 1200 | − dev->cap.read_buf, dev->cap.field)) | |
| 1201 | − goto err; | |
| 1202 | − dev->cap.ops->buf_queue(&dev->cap, dev->cap.read_buf); | |
| 1203 | − dev->cap.read_off = 0; | |
| 1204 | − } | |
| 1205 | − buf = dev->cap.read_buf; | |
| 1206 | − } | |
| 1207 | − | |
| 1208 | − if (!buf) | |
| 1209 | − goto err; | |
| 1210 | − | |
| 1211 | − poll_wait(file, &buf->done, wait); | |
| 1212 | − if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) | |
| 1213 | − rc |= POLLIN | POLLRDNORM; | |
| 1214 | − mutex_unlock(&dev->cap.vb_lock); | |
| 1215 | − return rc; | |
| 1216 | − | |
| 1217 | −err: | |
| 1218 | − mutex_unlock(&dev->cap.vb_lock); | |
| 1219 | − return rc | POLLERR; | |
| 1220 | −} | |
| 1221 | − | |
| 1222 | 1129 | static int video_release(struct file *file) |
| 1223 | 1130 | { |
| 1224 | 1131 | struct video_device *vdev = video_devdata(file); |
| 1225 | 1132 | struct saa7134_dev *dev = video_drvdata(file); |
| 1226 | − struct saa7134_fh *fh = file->private_data; | |
| 1133 | + struct v4l2_fh *fh = file->private_data; | |
| 1227 | 1134 | struct saa6588_command cmd; |
| 1228 | 1135 | unsigned long flags; |
| 1229 | 1136 | |
| 1137 | + mutex_lock(&dev->lock); | |
| 1230 | 1138 | saa7134_tvaudio_close(dev); |
| 1231 | 1139 | |
| 1232 | 1140 | /* turn off overlay */ |
| 1233 | − if (res_check(fh, RESOURCE_OVERLAY)) { | |
| 1141 | + if (fh == dev->overlay_owner) { | |
| 1234 | 1142 | spin_lock_irqsave(&dev->slock,flags); |
| 1235 | 1143 | stop_preview(dev); |
| 1236 | 1144 | spin_unlock_irqrestore(&dev->slock,flags); |
| 1237 | − res_free(dev, fh, RESOURCE_OVERLAY); | |
| 1238 | − } | |
| 1239 | − | |
| 1240 | − /* stop video capture */ | |
| 1241 | − if (res_check(fh, RESOURCE_VIDEO)) { | |
| 1242 | − pm_qos_remove_request(&dev->qos_request); | |
| 1243 | − videobuf_streamoff(&dev->cap); | |
| 1244 | − res_free(dev, fh, RESOURCE_VIDEO); | |
| 1245 | − videobuf_mmap_free(&dev->cap); | |
| 1246 | − } | |
| 1247 | − if (dev->cap.read_buf) { | |
| 1248 | − buffer_release(&dev->cap, dev->cap.read_buf); | |
| 1249 | − kfree(dev->cap.read_buf); | |
| 1145 | + dev->overlay_owner = NULL; | |
| 1250 | 1146 | } |
| 1251 | 1147 | |
| 1252 | − /* stop vbi capture */ | |
| 1253 | − if (res_check(fh, RESOURCE_VBI)) { | |
| 1254 | − videobuf_stop(&dev->vbi); | |
| 1255 | − res_free(dev, fh, RESOURCE_VBI); | |
| 1256 | − videobuf_mmap_free(&dev->vbi); | |
| 1257 | − } | |
| 1148 | + if (vdev->vfl_type == VFL_TYPE_RADIO) | |
| 1149 | + v4l2_fh_release(file); | |
| 1150 | + else | |
| 1151 | + _vb2_fop_release(file, NULL); | |
| 1258 | 1152 | |
| 1259 | 1153 | /* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/ |
| 1260 | 1154 | saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0); |
| @@ -1265,19 +1159,11 @@ static int video_release(struct file *file) · 4 unmodified lines | ||
| 1265 | 1159 | saa_call_all(dev, core, s_power, 0); |
| 1266 | 1160 | if (vdev->vfl_type == VFL_TYPE_RADIO) |
| 1267 | 1161 | saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); |
| 1162 | + mutex_unlock(&dev->lock); | |
| 1268 | 1163 | |
| 1269 | − v4l2_fh_del(&fh->fh); | |
| 1270 | − v4l2_fh_exit(&fh->fh); | |
| 1271 | − file->private_data = NULL; | |
| 1272 | − kfree(fh); | |
| 1273 | 1164 | return 0; |
| 1274 | 1165 | } |
| 1275 | 1166 | |
| 1276 | −static int video_mmap(struct file *file, struct vm_area_struct * vma) | |
| 1277 | −{ | |
| 1278 | − return videobuf_mmap_mapper(saa7134_queue(file), vma); | |
| 1279 | −} | |
| 1280 | − | |
| 1281 | 1167 | static ssize_t radio_read(struct file *file, char __user *data, |
| 1282 | 1168 | size_t count, loff_t *ppos) |
| 1283 | 1169 | { |
| @@ -1290,7 +1176,9 @@ static ssize_t radio_read(struct file *file, char __user *data, · 6 unmodified lines | ||
| 1290 | 1176 | cmd.instance = file; |
| 1291 | 1177 | cmd.result = -ENODEV; |
| 1292 | 1178 | |
| 1179 | + mutex_lock(&dev->lock); | |
| 1293 | 1180 | saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd); |
| 1181 | + mutex_unlock(&dev->lock); | |
| 1294 | 1182 | |
| 1295 | 1183 | return cmd.result; |
| 1296 | 1184 | } |
| @@ -1304,7 +1192,9 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) · 7 unmodified lines | ||
| 1304 | 1192 | cmd.instance = file; |
| 1305 | 1193 | cmd.event_list = wait; |
| 1306 | 1194 | cmd.result = 0; |
| 1195 | + mutex_lock(&dev->lock); | |
| 1307 | 1196 | saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd); |
| 1197 | + mutex_unlock(&dev->lock); | |
| 1308 | 1198 | |
| 1309 | 1199 | return rc | cmd.result; |
| 1310 | 1200 | } |
| @@ -1338,7 +1228,7 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, · 27 unmodified lines | ||
| 1338 | 1228 | |
| 1339 | 1229 | f->fmt.pix.width = dev->width; |
| 1340 | 1230 | f->fmt.pix.height = dev->height; |
| 1341 | − f->fmt.pix.field = dev->cap.field; | |
| 1231 | + f->fmt.pix.field = dev->field; | |
| 1342 | 1232 | f->fmt.pix.pixelformat = dev->fmt->fourcc; |
| 1343 | 1233 | f->fmt.pix.bytesperline = |
| 1344 | 1234 | (f->fmt.pix.width * dev->fmt->depth) >> 3; |
| @@ -1362,7 +1252,6 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, · 17 unmodified lines | ||
| 1362 | 1252 | printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); |
| 1363 | 1253 | return -EINVAL; |
| 1364 | 1254 | } |
| 1365 | − mutex_lock(&dev->lock); | |
| 1366 | 1255 | f->fmt.win = dev->win; |
| 1367 | 1256 | f->fmt.win.clips = clips; |
| 1368 | 1257 | if (clips == NULL) |
| @@ -1376,7 +1265,6 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, · 7 unmodified lines | ||
| 1376 | 1265 | sizeof(struct v4l2_rect))) |
| 1377 | 1266 | err = -EFAULT; |
| 1378 | 1267 | } |
| 1379 | − mutex_unlock(&dev->lock); | |
| 1380 | 1268 | |
| 1381 | 1269 | return err; |
| 1382 | 1270 | } |
| @@ -1457,10 +1345,10 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv, · 74 unmodified lines | ||
| 1457 | 1345 | if (0 != err) |
| 1458 | 1346 | return err; |
| 1459 | 1347 | |
| 1460 | − dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | |
| 1461 | − dev->width = f->fmt.pix.width; | |
| 1462 | − dev->height = f->fmt.pix.height; | |
| 1463 | − dev->cap.field = f->fmt.pix.field; | |
| 1348 | + dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | |
| 1349 | + dev->width = f->fmt.pix.width; | |
| 1350 | + dev->height = f->fmt.pix.height; | |
| 1351 | + dev->field = f->fmt.pix.field; | |
| 1464 | 1352 | return 0; |
| 1465 | 1353 | } |
| 1466 | 1354 | |
| @@ -1481,25 +1369,20 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, · 14 unmodified lines | ||
| 1481 | 1369 | if (0 != err) |
| 1482 | 1370 | return err; |
| 1483 | 1371 | |
| 1484 | − mutex_lock(&dev->lock); | |
| 1485 | − | |
| 1486 | 1372 | dev->win = f->fmt.win; |
| 1487 | 1373 | dev->nclips = f->fmt.win.clipcount; |
| 1488 | 1374 | |
| 1489 | 1375 | if (copy_from_user(dev->clips, f->fmt.win.clips, |
| 1490 | − sizeof(struct v4l2_clip) * dev->nclips)) { | |
| 1491 | − mutex_unlock(&dev->lock); | |
| 1376 | + sizeof(struct v4l2_clip) * dev->nclips)) | |
| 1492 | 1377 | return -EFAULT; |
| 1493 | − } | |
| 1494 | 1378 | |
| 1495 | − if (res_check(priv, RESOURCE_OVERLAY)) { | |
| 1379 | + if (priv == dev->overlay_owner) { | |
| 1496 | 1380 | spin_lock_irqsave(&dev->slock, flags); |
| 1497 | 1381 | stop_preview(dev); |
| 1498 | 1382 | start_preview(dev); |
| 1499 | 1383 | spin_unlock_irqrestore(&dev->slock, flags); |
| 1500 | 1384 | } |
| 1501 | 1385 | |
| 1502 | − mutex_unlock(&dev->lock); | |
| 1503 | 1386 | return 0; |
| 1504 | 1387 | } |
| 1505 | 1388 | |
| @@ -1551,9 +1434,7 @@ int saa7134_s_input(struct file *file, void *priv, unsigned int i) · 45 unmodified lines | ||
| 1551 | 1434 | return -EINVAL; |
| 1552 | 1435 | if (NULL == card_in(dev, i).name) |
| 1553 | 1436 | return -EINVAL; |
| 1554 | − mutex_lock(&dev->lock); | |
| 1555 | 1437 | video_mux(dev, i); |
| 1556 | − mutex_unlock(&dev->lock); | |
| 1557 | 1438 | return 0; |
| 1558 | 1439 | } |
| 1559 | 1440 | EXPORT_SYMBOL_GPL(saa7134_s_input); |
| @@ -1563,7 +1444,6 @@ int saa7134_querycap(struct file *file, void *priv, · 3 unmodified lines | ||
| 1563 | 1444 | { |
| 1564 | 1445 | struct saa7134_dev *dev = video_drvdata(file); |
| 1565 | 1446 | struct video_device *vdev = video_devdata(file); |
| 1566 | − struct saa7134_fh *fh = priv; | |
| 1567 | 1447 | u32 radio_caps, video_caps, vbi_caps; |
| 1568 | 1448 | |
| 1569 | 1449 | unsigned int tuner_type = dev->tuner_type; |
| @@ -1582,7 +1462,7 @@ int saa7134_querycap(struct file *file, void *priv, · 12 unmodified lines | ||
| 1582 | 1462 | radio_caps |= V4L2_CAP_RDS_CAPTURE; |
| 1583 | 1463 | |
| 1584 | 1464 | video_caps = V4L2_CAP_VIDEO_CAPTURE; |
| 1585 | − if (saa7134_no_overlay <= 0 && !fh->is_empress) | |
| 1465 | + if (saa7134_no_overlay <= 0 && !is_empress(file)) | |
| 1586 | 1466 | video_caps |= V4L2_CAP_VIDEO_OVERLAY; |
| 1587 | 1467 | |
| 1588 | 1468 | vbi_caps = V4L2_CAP_VBI_CAPTURE; |
| @@ -1613,12 +1493,12 @@ EXPORT_SYMBOL_GPL(saa7134_querycap); · 24 unmodified lines | ||
| 1613 | 1493 | int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id) |
| 1614 | 1494 | { |
| 1615 | 1495 | struct saa7134_dev *dev = video_drvdata(file); |
| 1616 | − struct saa7134_fh *fh = priv; | |
| 1496 | + struct v4l2_fh *fh = priv; | |
| 1617 | 1497 | unsigned long flags; |
| 1618 | 1498 | unsigned int i; |
| 1619 | 1499 | v4l2_std_id fixup; |
| 1620 | 1500 | |
| 1621 | − if (fh->is_empress && res_locked(dev, RESOURCE_OVERLAY)) { | |
| 1501 | + if (is_empress(file) && dev->overlay_owner) { | |
| 1622 | 1502 | /* Don't change the std from the mpeg device |
| 1623 | 1503 | if overlay is active. */ |
| 1624 | 1504 | return -EBUSY; |
| @@ -1657,8 +1537,7 @@ int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id) · 32 unmodified lines | ||
| 1657 | 1537 | |
| 1658 | 1538 | id = tvnorms[i].id; |
| 1659 | 1539 | |
| 1660 | − mutex_lock(&dev->lock); | |
| 1661 | − if (!fh->is_empress && res_check(fh, RESOURCE_OVERLAY)) { | |
| 1540 | + if (!is_empress(file) && fh == dev->overlay_owner) { | |
| 1662 | 1541 | spin_lock_irqsave(&dev->slock, flags); |
| 1663 | 1542 | stop_preview(dev); |
| 1664 | 1543 | spin_unlock_irqrestore(&dev->slock, flags); |
| @@ -1672,7 +1551,6 @@ int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id) · 7 unmodified lines | ||
| 1672 | 1551 | set_tvnorm(dev, &tvnorms[i]); |
| 1673 | 1552 | |
| 1674 | 1553 | saa7134_tvaudio_do_scan(dev); |
| 1675 | − mutex_unlock(&dev->lock); | |
| 1676 | 1554 | return 0; |
| 1677 | 1555 | } |
| 1678 | 1556 | EXPORT_SYMBOL_GPL(saa7134_s_std); |
| @@ -1686,6 +1564,35 @@ int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id) · 7 unmodified lines | ||
| 1686 | 1564 | } |
| 1687 | 1565 | EXPORT_SYMBOL_GPL(saa7134_g_std); |
| 1688 | 1566 | |
| 1567 | +static v4l2_std_id saa7134_read_std(struct saa7134_dev *dev) | |
| 1568 | +{ | |
| 1569 | + static v4l2_std_id stds[] = { | |
| 1570 | + V4L2_STD_UNKNOWN, | |
| 1571 | + V4L2_STD_NTSC, | |
| 1572 | + V4L2_STD_PAL, | |
| 1573 | + V4L2_STD_SECAM }; | |
| 1574 | + | |
| 1575 | + v4l2_std_id result = 0; | |
| 1576 | + | |
| 1577 | + u8 st1 = saa_readb(SAA7134_STATUS_VIDEO1); | |
| 1578 | + u8 st2 = saa_readb(SAA7134_STATUS_VIDEO2); | |
| 1579 | + | |
| 1580 | + if (!(st2 & 0x1)) /* RDCAP == 0 */ | |
| 1581 | + result = V4L2_STD_UNKNOWN; | |
| 1582 | + else | |
| 1583 | + result = stds[st1 & 0x03]; | |
| 1584 | + | |
| 1585 | + return result; | |
| 1586 | +} | |
| 1587 | + | |
| 1588 | +int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std) | |
| 1589 | +{ | |
| 1590 | + struct saa7134_dev *dev = video_drvdata(file); | |
| 1591 | + *std &= saa7134_read_std(dev); | |
| 1592 | + return 0; | |
| 1593 | +} | |
| 1594 | +EXPORT_SYMBOL_GPL(saa7134_querystd); | |
| 1595 | + | |
| 1689 | 1596 | static int saa7134_cropcap(struct file *file, void *priv, |
| 1690 | 1597 | struct v4l2_cropcap *cap) |
| 1691 | 1598 | { |
| @@ -1730,9 +1637,9 @@ static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *cr · 38 unmodified lines | ||
| 1730 | 1637 | crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) |
| 1731 | 1638 | return -EINVAL; |
| 1732 | 1639 | |
| 1733 | − if (res_locked(dev, RESOURCE_OVERLAY)) | |
| 1640 | + if (dev->overlay_owner) | |
| 1734 | 1641 | return -EBUSY; |
| 1735 | − if (res_locked(dev, RESOURCE_VIDEO)) | |
| 1642 | + if (vb2_is_streaming(&dev->video_vbq)) | |
| 1736 | 1643 | return -EBUSY; |
| 1737 | 1644 | |
| 1738 | 1645 | *c = crop->c; |
| @@ -1826,12 +1733,10 @@ int saa7134_s_frequency(struct file *file, void *priv, · 87 unmodified lines | ||
| 1826 | 1733 | |
| 1827 | 1734 | if (0 != f->tuner) |
| 1828 | 1735 | return -EINVAL; |
| 1829 | − mutex_lock(&dev->lock); | |
| 1830 | 1736 | |
| 1831 | 1737 | saa_call_all(dev, tuner, s_frequency, f); |
| 1832 | 1738 | |
| 1833 | 1739 | saa7134_tvaudio_do_scan(dev); |
| 1834 | − mutex_unlock(&dev->lock); | |
| 1835 | 1740 | return 0; |
| 1836 | 1741 | } |
| 1837 | 1742 | EXPORT_SYMBOL_GPL(saa7134_s_frequency); |
| @@ -1915,92 +1820,24 @@ static int saa7134_overlay(struct file *file, void *priv, unsigned int on) · 77 unmodified lines | ||
| 1915 | 1820 | return -EINVAL; |
| 1916 | 1821 | } |
| 1917 | 1822 | |
| 1918 | − if (!res_get(dev, priv, RESOURCE_OVERLAY)) | |
| 1823 | + if (dev->overlay_owner && priv != dev->overlay_owner) | |
| 1919 | 1824 | return -EBUSY; |
| 1825 | + dev->overlay_owner = priv; | |
| 1920 | 1826 | spin_lock_irqsave(&dev->slock, flags); |
| 1921 | 1827 | start_preview(dev); |
| 1922 | 1828 | spin_unlock_irqrestore(&dev->slock, flags); |
| 1923 | 1829 | } |
| 1924 | 1830 | if (!on) { |
| 1925 | − if (!res_check(priv, RESOURCE_OVERLAY)) | |
| 1831 | + if (priv != dev->overlay_owner) | |
| 1926 | 1832 | return -EINVAL; |
| 1927 | 1833 | spin_lock_irqsave(&dev->slock, flags); |
| 1928 | 1834 | stop_preview(dev); |
| 1929 | 1835 | spin_unlock_irqrestore(&dev->slock, flags); |
| 1930 | − res_free(dev, priv, RESOURCE_OVERLAY); | |
| 1836 | + dev->overlay_owner = NULL; | |
| 1931 | 1837 | } |
| 1932 | 1838 | return 0; |
| 1933 | 1839 | } |
| 1934 | 1840 | |
| 1935 | −int saa7134_reqbufs(struct file *file, void *priv, | |
| 1936 | − struct v4l2_requestbuffers *p) | |
| 1937 | −{ | |
| 1938 | − return videobuf_reqbufs(saa7134_queue(file), p); | |
| 1939 | −} | |
| 1940 | −EXPORT_SYMBOL_GPL(saa7134_reqbufs); | |
| 1941 | − | |
| 1942 | −int saa7134_querybuf(struct file *file, void *priv, | |
| 1943 | − struct v4l2_buffer *b) | |
| 1944 | −{ | |
| 1945 | − return videobuf_querybuf(saa7134_queue(file), b); | |
| 1946 | −} | |
| 1947 | −EXPORT_SYMBOL_GPL(saa7134_querybuf); | |
| 1948 | − | |
| 1949 | −int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | |
| 1950 | −{ | |
| 1951 | − return videobuf_qbuf(saa7134_queue(file), b); | |
| 1952 | −} | |
| 1953 | −EXPORT_SYMBOL_GPL(saa7134_qbuf); | |
| 1954 | − | |
| 1955 | −int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | |
| 1956 | −{ | |
| 1957 | − return videobuf_dqbuf(saa7134_queue(file), b, | |
| 1958 | − file->f_flags & O_NONBLOCK); | |
| 1959 | −} | |
| 1960 | −EXPORT_SYMBOL_GPL(saa7134_dqbuf); | |
| 1961 | − | |
| 1962 | −int saa7134_streamon(struct file *file, void *priv, | |
| 1963 | − enum v4l2_buf_type type) | |
| 1964 | −{ | |
| 1965 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 1966 | − int res = saa7134_resource(file); | |
| 1967 | − | |
| 1968 | − if (!res_get(dev, priv, res)) | |
| 1969 | − return -EBUSY; | |
| 1970 | − | |
| 1971 | − /* The SAA7134 has a 1K FIFO; the datasheet suggests that when | |
| 1972 | − * configured conservatively, there's 22 usec of buffering for video. | |
| 1973 | − * We therefore request a DMA latency of 20 usec, giving us 2 usec of | |
| 1974 | − * margin in case the FIFO is configured differently to the datasheet. | |
| 1975 | − * Unfortunately, I lack register-level documentation to check the | |
| 1976 | − * Linux FIFO setup and confirm the perfect value. | |
| 1977 | − */ | |
| 1978 | − if (res != RESOURCE_EMPRESS) | |
| 1979 | − pm_qos_add_request(&dev->qos_request, | |
| 1980 | − PM_QOS_CPU_DMA_LATENCY, 20); | |
| 1981 | − | |
| 1982 | − return videobuf_streamon(saa7134_queue(file)); | |
| 1983 | −} | |
| 1984 | −EXPORT_SYMBOL_GPL(saa7134_streamon); | |
| 1985 | − | |
| 1986 | −int saa7134_streamoff(struct file *file, void *priv, | |
| 1987 | − enum v4l2_buf_type type) | |
| 1988 | −{ | |
| 1989 | − struct saa7134_dev *dev = video_drvdata(file); | |
| 1990 | − int err; | |
| 1991 | − int res = saa7134_resource(file); | |
| 1992 | − | |
| 1993 | − if (res != RESOURCE_EMPRESS) | |
| 1994 | − pm_qos_remove_request(&dev->qos_request); | |
| 1995 | − | |
| 1996 | − err = videobuf_streamoff(saa7134_queue(file)); | |
| 1997 | − if (err < 0) | |
| 1998 | − return err; | |
| 1999 | − res_free(dev, priv, res); | |
| 2000 | − return 0; | |
| 2001 | −} | |
| 2002 | −EXPORT_SYMBOL_GPL(saa7134_streamoff); | |
| 2003 | − | |
| 2004 | 1841 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 2005 | 1842 | static int vidioc_g_register (struct file *file, void *priv, |
| 2006 | 1843 | struct v4l2_dbg_register *reg) |
| @@ -2058,10 +1895,10 @@ static const struct v4l2_file_operations video_fops = · 51 unmodified lines | ||
| 2058 | 1895 | .owner = THIS_MODULE, |
| 2059 | 1896 | .open = video_open, |
| 2060 | 1897 | .release = video_release, |
| 2061 | − .read = video_read, | |
| 2062 | − .poll = video_poll, | |
| 2063 | − .mmap = video_mmap, | |
| 2064 | − .ioctl = video_ioctl2, | |
| 1898 | + .read = vb2_fop_read, | |
| 1899 | + .poll = vb2_fop_poll, | |
| 1900 | + .mmap = vb2_fop_mmap, | |
| 1901 | + .unlocked_ioctl = video_ioctl2, | |
| 2065 | 1902 | }; |
| 2066 | 1903 | |
| 2067 | 1904 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
| @@ -2078,17 +1915,18 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { · 10 unmodified lines | ||
| 2078 | 1915 | .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
| 2079 | 1916 | .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
| 2080 | 1917 | .vidioc_cropcap = saa7134_cropcap, |
| 2081 | − .vidioc_reqbufs = saa7134_reqbufs, | |
| 2082 | − .vidioc_querybuf = saa7134_querybuf, | |
| 2083 | − .vidioc_qbuf = saa7134_qbuf, | |
| 2084 | − .vidioc_dqbuf = saa7134_dqbuf, | |
| 1918 | + .vidioc_reqbufs = vb2_ioctl_reqbufs, | |
| 1919 | + .vidioc_querybuf = vb2_ioctl_querybuf, | |
| 1920 | + .vidioc_qbuf = vb2_ioctl_qbuf, | |
| 1921 | + .vidioc_dqbuf = vb2_ioctl_dqbuf, | |
| 2085 | 1922 | .vidioc_s_std = saa7134_s_std, |
| 2086 | 1923 | .vidioc_g_std = saa7134_g_std, |
| 1924 | + .vidioc_querystd = saa7134_querystd, | |
| 2087 | 1925 | .vidioc_enum_input = saa7134_enum_input, |
| 2088 | 1926 | .vidioc_g_input = saa7134_g_input, |
| 2089 | 1927 | .vidioc_s_input = saa7134_s_input, |
| 2090 | − .vidioc_streamon = saa7134_streamon, | |
| 2091 | − .vidioc_streamoff = saa7134_streamoff, | |
| 1928 | + .vidioc_streamon = vb2_ioctl_streamon, | |
| 1929 | + .vidioc_streamoff = vb2_ioctl_streamoff, | |
| 2092 | 1930 | .vidioc_g_tuner = saa7134_g_tuner, |
| 2093 | 1931 | .vidioc_s_tuner = saa7134_s_tuner, |
| 2094 | 1932 | .vidioc_g_crop = saa7134_g_crop, |
| @@ -2112,7 +1950,7 @@ static const struct v4l2_file_operations radio_fops = { · 17 unmodified lines | ||
| 2112 | 1950 | .open = video_open, |
| 2113 | 1951 | .read = radio_read, |
| 2114 | 1952 | .release = video_release, |
| 2115 | − .ioctl = video_ioctl2, | |
| 1953 | + .unlocked_ioctl = video_ioctl2, | |
| 2116 | 1954 | .poll = radio_poll, |
| 2117 | 1955 | }; |
| 2118 | 1956 | |
| @@ -2190,6 +2028,8 @@ static const struct v4l2_ctrl_config saa7134_ctrl_automute = { · 71 unmodified lines | ||
| 2190 | 2028 | int saa7134_video_init1(struct saa7134_dev *dev) |
| 2191 | 2029 | { |
| 2192 | 2030 | struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; |
| 2031 | + struct vb2_queue *q; | |
| 2032 | + int ret; | |
| 2193 | 2033 | |
| 2194 | 2034 | /* sanitycheck insmod options */ |
| 2195 | 2035 | if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) |
| @@ -2241,6 +2081,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) · 45 unmodified lines | ||
| 2241 | 2081 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); |
| 2242 | 2082 | dev->width = 720; |
| 2243 | 2083 | dev->height = 576; |
| 2084 | + dev->field = V4L2_FIELD_INTERLACED; | |
| 2244 | 2085 | dev->win.w.width = dev->width; |
| 2245 | 2086 | dev->win.w.height = dev->height; |
| 2246 | 2087 | dev->win.field = V4L2_FIELD_INTERLACED; |
| @@ -2252,20 +2093,47 @@ int saa7134_video_init1(struct saa7134_dev *dev) · 5 unmodified lines | ||
| 2252 | 2093 | if (saa7134_boards[dev->board].video_out) |
| 2253 | 2094 | saa7134_videoport_init(dev); |
| 2254 | 2095 | |
| 2255 | − videobuf_queue_sg_init(&dev->cap, &video_qops, | |
| 2256 | − &dev->pci->dev, &dev->slock, | |
| 2257 | − V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
| 2258 | − V4L2_FIELD_INTERLACED, | |
| 2259 | − sizeof(struct saa7134_buf), | |
| 2260 | − dev, NULL); | |
| 2261 | − videobuf_queue_sg_init(&dev->vbi, &saa7134_vbi_qops, | |
| 2262 | − &dev->pci->dev, &dev->slock, | |
| 2263 | − V4L2_BUF_TYPE_VBI_CAPTURE, | |
| 2264 | − V4L2_FIELD_SEQ_TB, | |
| 2265 | − sizeof(struct saa7134_buf), | |
| 2266 | − dev, NULL); | |
| 2267 | − saa7134_pgtable_alloc(dev->pci, &dev->pt_cap); | |
| 2268 | − saa7134_pgtable_alloc(dev->pci, &dev->pt_vbi); | |
| 2096 | + q = &dev->video_vbq; | |
| 2097 | + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 2098 | + /* | |
| 2099 | + * Do not add VB2_USERPTR unless explicitly requested: the saa7134 DMA | |
| 2100 | + * engine cannot handle transfers that do not start at the beginning | |
| 2101 | + * of a page. A user-provided pointer can start anywhere in a page, so | |
| 2102 | + * USERPTR support is a no-go unless the application knows about these | |
| 2103 | + * limitations and has special support for this. | |
| 2104 | + */ | |
| 2105 | + q->io_modes = VB2_MMAP | VB2_READ; | |
| 2106 | + if (saa7134_userptr) | |
| 2107 | + q->io_modes |= VB2_USERPTR; | |
| 2108 | + q->drv_priv = &dev->video_q; | |
| 2109 | + q->ops = &vb2_qops; | |
| 2110 | + q->gfp_flags = GFP_DMA32; | |
| 2111 | + q->mem_ops = &vb2_dma_sg_memops; | |
| 2112 | + q->buf_struct_size = sizeof(struct saa7134_buf); | |
| 2113 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 2114 | + q->lock = &dev->lock; | |
| 2115 | + ret = vb2_queue_init(q); | |
| 2116 | + if (ret) | |
| 2117 | + return ret; | |
| 2118 | + saa7134_pgtable_alloc(dev->pci, &dev->video_q.pt); | |
| 2119 | + | |
| 2120 | + q = &dev->vbi_vbq; | |
| 2121 | + q->type = V4L2_BUF_TYPE_VBI_CAPTURE; | |
| 2122 | + /* Don't add VB2_USERPTR, see comment above */ | |
| 2123 | + q->io_modes = VB2_MMAP | VB2_READ; | |
| 2124 | + if (saa7134_userptr) | |
| 2125 | + q->io_modes |= VB2_USERPTR; | |
| 2126 | + q->drv_priv = &dev->vbi_q; | |
| 2127 | + q->ops = &saa7134_vbi_qops; | |
| 2128 | + q->gfp_flags = GFP_DMA32; | |
| 2129 | + q->mem_ops = &vb2_dma_sg_memops; | |
| 2130 | + q->buf_struct_size = sizeof(struct saa7134_buf); | |
| 2131 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 2132 | + q->lock = &dev->lock; | |
| 2133 | + ret = vb2_queue_init(q); | |
| 2134 | + if (ret) | |
| 2135 | + return ret; | |
| 2136 | + saa7134_pgtable_alloc(dev->pci, &dev->vbi_q.pt); | |
| 2269 | 2137 | |
| 2270 | 2138 | return 0; |
| 2271 | 2139 | } |
| @@ -2273,8 +2141,10 @@ int saa7134_video_init1(struct saa7134_dev *dev) · 1 unmodified line | ||
| 2273 | 2141 | void saa7134_video_fini(struct saa7134_dev *dev) |
| 2274 | 2142 | { |
| 2275 | 2143 | /* free stuff */ |
| 2276 | − saa7134_pgtable_free(dev->pci, &dev->pt_cap); | |
| 2277 | − saa7134_pgtable_free(dev->pci, &dev->pt_vbi); | |
| 2144 | + vb2_queue_release(&dev->video_vbq); | |
| 2145 | + saa7134_pgtable_free(dev->pci, &dev->video_q.pt); | |
| 2146 | + vb2_queue_release(&dev->vbi_vbq); | |
| 2147 | + saa7134_pgtable_free(dev->pci, &dev->vbi_q.pt); | |
| 2278 | 2148 | v4l2_ctrl_handler_free(&dev->ctrl_handler); |
| 2279 | 2149 | if (card_has_radio(dev)) |
| 2280 | 2150 | v4l2_ctrl_handler_free(&dev->radio_ctrl_handler); |
| @@ -2367,8 +2237,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) · 86 unmodified lines | ||
| 2367 | 2237 | |
| 2368 | 2238 | spin_lock(&dev->slock); |
| 2369 | 2239 | if (dev->video_q.curr) { |
| 2370 | − dev->video_fieldcount++; | |
| 2371 | − field = dev->video_q.curr->vb.field; | |
| 2240 | + field = dev->field; | |
| 2372 | 2241 | if (V4L2_FIELD_HAS_BOTH(field)) { |
| 2373 | 2242 | /* make sure we have seen both fields */ |
| 2374 | 2243 | if ((status & 0x10) == 0x00) { |
| @@ -2384,18 +2253,10 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) · 9 unmodified lines | ||
| 2384 | 2253 | if ((status & 0x10) != 0x00) |
| 2385 | 2254 | goto done; |
| 2386 | 2255 | } |
| 2387 | − dev->video_q.curr->vb.field_count = dev->video_fieldcount; | |
| 2388 | − saa7134_buffer_finish(dev,&dev->video_q,VIDEOBUF_DONE); | |
| 2256 | + saa7134_buffer_finish(dev, &dev->video_q, VB2_BUF_STATE_DONE); | |
| 2389 | 2257 | } |
| 2390 | − saa7134_buffer_next(dev,&dev->video_q); | |
| 2258 | + saa7134_buffer_next(dev, &dev->video_q); | |
| 2391 | 2259 | |
| 2392 | 2260 | done: |
| 2393 | 2261 | spin_unlock(&dev->slock); |
| 2394 | 2262 | } |
| 2395 | − | |
| 2396 | −/* ----------------------------------------------------------- */ | |
| 2397 | −/* | |
| 2398 | − * Local variables: | |
| 2399 | − * c-basic-offset: 8 | |
| 2400 | − * End: | |
| 2401 | − */ | |
| @@ -41,11 +41,11 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <media/tuner.h> |
| 42 | 42 | #include <media/rc-core.h> |
| 43 | 43 | #include <media/ir-kbd-i2c.h> |
| 44 | −#include <media/videobuf-dma-sg.h> | |
| 44 | +#include <media/videobuf2-dma-sg.h> | |
| 45 | 45 | #include <sound/core.h> |
| 46 | 46 | #include <sound/pcm.h> |
| 47 | 47 | #if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) |
| 48 | −#include <media/videobuf-dvb.h> | |
| 48 | +#include <media/videobuf2-dvb.h> | |
| 49 | 49 | #endif |
| 50 | 50 | #include "tda8290.h" |
| 51 | 51 | |
| @@ -453,17 +453,15 @@ struct saa7134_thread { · 401 unmodified lines | ||
| 453 | 453 | /* buffer for one video/vbi/ts frame */ |
| 454 | 454 | struct saa7134_buf { |
| 455 | 455 | /* common v4l buffer stuff -- must be first */ |
| 456 | − struct videobuf_buffer vb; | |
| 456 | + struct vb2_buffer vb2; | |
| 457 | 457 | |
| 458 | 458 | /* saa7134 specific */ |
| 459 | − struct saa7134_format *fmt; | |
| 460 | 459 | unsigned int top_seen; |
| 461 | 460 | int (*activate)(struct saa7134_dev *dev, |
| 462 | 461 | struct saa7134_buf *buf, |
| 463 | 462 | struct saa7134_buf *next); |
| 464 | 463 | |
| 465 | − /* page tables */ | |
| 466 | − struct saa7134_pgtable *pt; | |
| 464 | + struct list_head entry; | |
| 467 | 465 | }; |
| 468 | 466 | |
| 469 | 467 | struct saa7134_dmaqueue { |
| @@ -472,13 +470,8 @@ struct saa7134_dmaqueue { · 2 unmodified lines | ||
| 472 | 470 | struct list_head queue; |
| 473 | 471 | struct timer_list timeout; |
| 474 | 472 | unsigned int need_two; |
| 475 | −}; | |
| 476 | − | |
| 477 | −/* video filehandle status */ | |
| 478 | −struct saa7134_fh { | |
| 479 | − struct v4l2_fh fh; | |
| 480 | − bool is_empress; | |
| 481 | − unsigned int resources; | |
| 473 | + unsigned int seq_nr; | |
| 474 | + struct saa7134_pgtable pt; | |
| 482 | 475 | }; |
| 483 | 476 | |
| 484 | 477 | /* dmasound dsp status */ |
| @@ -504,7 +497,10 @@ struct saa7134_dmasound { · 19 unmodified lines | ||
| 504 | 497 | unsigned int blksize; |
| 505 | 498 | unsigned int bufsize; |
| 506 | 499 | struct saa7134_pgtable pt; |
| 507 | − struct videobuf_dmabuf dma; | |
| 500 | + void *vaddr; | |
| 501 | + struct scatterlist *sglist; | |
| 502 | + int sglen; | |
| 503 | + int nr_pages; | |
| 508 | 504 | unsigned int dma_blk; |
| 509 | 505 | unsigned int read_offset; |
| 510 | 506 | unsigned int read_count; |
| @@ -515,7 +511,6 @@ struct saa7134_dmasound { · 4 unmodified lines | ||
| 515 | 511 | /* ts/mpeg status */ |
| 516 | 512 | struct saa7134_ts { |
| 517 | 513 | /* TS capture */ |
| 518 | − struct saa7134_pgtable pt_ts; | |
| 519 | 514 | int nr_packets; |
| 520 | 515 | int nr_bufs; |
| 521 | 516 | }; |
| @@ -584,21 +579,35 @@ struct saa7134_dev { · 62 unmodified lines | ||
| 584 | 579 | struct v4l2_window win; |
| 585 | 580 | struct v4l2_clip clips[8]; |
| 586 | 581 | unsigned int nclips; |
| 582 | + struct v4l2_fh *overlay_owner; | |
| 587 | 583 | |
| 588 | 584 | |
| 589 | 585 | /* video+ts+vbi capture */ |
| 590 | 586 | struct saa7134_dmaqueue video_q; |
| 591 | − struct videobuf_queue cap; | |
| 592 | − struct saa7134_pgtable pt_cap; | |
| 587 | + struct vb2_queue video_vbq; | |
| 593 | 588 | struct saa7134_dmaqueue vbi_q; |
| 594 | − struct videobuf_queue vbi; | |
| 595 | − struct saa7134_pgtable pt_vbi; | |
| 596 | − unsigned int video_fieldcount; | |
| 597 | − unsigned int vbi_fieldcount; | |
| 589 | + struct vb2_queue vbi_vbq; | |
| 590 | + enum v4l2_field field; | |
| 598 | 591 | struct saa7134_format *fmt; |
| 599 | 592 | unsigned int width, height; |
| 593 | + unsigned int vbi_hlen, vbi_vlen; | |
| 600 | 594 | struct pm_qos_request qos_request; |
| 601 | 595 | |
| 596 | + /* SAA7134_MPEG_* */ | |
| 597 | + struct saa7134_ts ts; | |
| 598 | + struct saa7134_dmaqueue ts_q; | |
| 599 | + enum v4l2_field ts_field; | |
| 600 | + int ts_started; | |
| 601 | + struct saa7134_mpeg_ops *mops; | |
| 602 | + | |
| 603 | + /* SAA7134_MPEG_EMPRESS only */ | |
| 604 | + struct video_device *empress_dev; | |
| 605 | + struct v4l2_subdev *empress_sd; | |
| 606 | + struct vb2_queue empress_vbq; | |
| 607 | + struct work_struct empress_workqueue; | |
| 608 | + int empress_started; | |
| 609 | + struct v4l2_ctrl_handler empress_ctrl_handler; | |
| 610 | + | |
| 602 | 611 | /* various v4l controls */ |
| 603 | 612 | struct saa7134_tvnorm *tvnorm; /* video */ |
| 604 | 613 | struct saa7134_tvaudio *tvaudio; |
| @@ -635,23 +644,9 @@ struct saa7134_dev { · 30 unmodified lines | ||
| 635 | 644 | /* I2C keyboard data */ |
| 636 | 645 | struct IR_i2c_init_data init_data; |
| 637 | 646 | |
| 638 | − /* SAA7134_MPEG_* */ | |
| 639 | − struct saa7134_ts ts; | |
| 640 | − struct saa7134_dmaqueue ts_q; | |
| 641 | − int ts_started; | |
| 642 | − struct saa7134_mpeg_ops *mops; | |
| 643 | − | |
| 644 | − /* SAA7134_MPEG_EMPRESS only */ | |
| 645 | − struct video_device *empress_dev; | |
| 646 | − struct v4l2_subdev *empress_sd; | |
| 647 | − struct videobuf_queue empress_tsq; | |
| 648 | − struct work_struct empress_workqueue; | |
| 649 | − int empress_started; | |
| 650 | − struct v4l2_ctrl_handler empress_ctrl_handler; | |
| 651 | − | |
| 652 | 647 | #if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB) |
| 653 | 648 | /* SAA7134_MPEG_DVB only */ |
| 654 | − struct videobuf_dvb_frontends frontends; | |
| 649 | + struct vb2_dvb_frontends frontends; | |
| 655 | 650 | int (*original_demod_sleep)(struct dvb_frontend *fe); |
| 656 | 651 | int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); |
| 657 | 652 | int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); |
| @@ -705,14 +700,12 @@ struct saa7134_dev { · 47 unmodified lines | ||
| 705 | 700 | _rc; \ |
| 706 | 701 | }) |
| 707 | 702 | |
| 708 | −static inline int res_check(struct saa7134_fh *fh, unsigned int bit) | |
| 703 | +static inline bool is_empress(struct file *file) | |
| 709 | 704 | { |
| 710 | − return fh->resources & bit; | |
| 711 | −} | |
| 705 | + struct video_device *vdev = video_devdata(file); | |
| 706 | + struct saa7134_dev *dev = video_get_drvdata(vdev); | |
| 712 | 707 | |
| 713 | −static inline int res_locked(struct saa7134_dev *dev, unsigned int bit) | |
| 714 | −{ | |
| 715 | − return dev->resources & bit; | |
| 708 | + return vdev->queue == &dev->empress_vbq; | |
| 716 | 709 | } |
| 717 | 710 | |
| 718 | 711 | /* ----------------------------------------------------------- */ |
| @@ -721,6 +714,7 @@ static inline int res_locked(struct saa7134_dev *dev, unsigned int bit) · 2 unmodified lines | ||
| 721 | 714 | extern struct list_head saa7134_devlist; |
| 722 | 715 | extern struct mutex saa7134_devlist_lock; |
| 723 | 716 | extern int saa7134_no_overlay; |
| 717 | +extern bool saa7134_userptr; | |
| 724 | 718 | |
| 725 | 719 | void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); |
| 726 | 720 | void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); |
| @@ -743,7 +737,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q, · 16 unmodified lines | ||
| 743 | 737 | unsigned int state); |
| 744 | 738 | void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); |
| 745 | 739 | void saa7134_buffer_timeout(unsigned long data); |
| 746 | −void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); | |
| 740 | +void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q); | |
| 747 | 741 | |
| 748 | 742 | int saa7134_set_dmabits(struct saa7134_dev *dev); |
| 749 | 743 | |
| @@ -777,8 +771,13 @@ extern unsigned int video_debug; · 27 unmodified lines | ||
| 777 | 771 | extern struct video_device saa7134_video_template; |
| 778 | 772 | extern struct video_device saa7134_radio_template; |
| 779 | 773 | |
| 774 | +void saa7134_vb2_buffer_queue(struct vb2_buffer *vb); | |
| 775 | +int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count); | |
| 776 | +void saa7134_vb2_stop_streaming(struct vb2_queue *vq); | |
| 777 | + | |
| 780 | 778 | int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id); |
| 781 | 779 | int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id); |
| 780 | +int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std); | |
| 782 | 781 | int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i); |
| 783 | 782 | int saa7134_g_input(struct file *file, void *priv, unsigned int *i); |
| 784 | 783 | int saa7134_s_input(struct file *file, void *priv, unsigned int i); |
| @@ -792,16 +791,6 @@ int saa7134_g_frequency(struct file *file, void *priv, · 7 unmodified lines | ||
| 792 | 791 | struct v4l2_frequency *f); |
| 793 | 792 | int saa7134_s_frequency(struct file *file, void *priv, |
| 794 | 793 | const struct v4l2_frequency *f); |
| 795 | −int saa7134_reqbufs(struct file *file, void *priv, | |
| 796 | − struct v4l2_requestbuffers *p); | |
| 797 | −int saa7134_querybuf(struct file *file, void *priv, | |
| 798 | − struct v4l2_buffer *b); | |
| 799 | −int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b); | |
| 800 | −int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b); | |
| 801 | −int saa7134_streamon(struct file *file, void *priv, | |
| 802 | − enum v4l2_buf_type type); | |
| 803 | −int saa7134_streamoff(struct file *file, void *priv, | |
| 804 | − enum v4l2_buf_type type); | |
| 805 | 794 | |
| 806 | 795 | int saa7134_videoport_init(struct saa7134_dev *dev); |
| 807 | 796 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); |
| @@ -818,7 +807,16 @@ void saa7134_video_fini(struct saa7134_dev *dev); · 10 unmodified lines | ||
| 818 | 807 | |
| 819 | 808 | #define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ |
| 820 | 809 | |
| 821 | −extern struct videobuf_queue_ops saa7134_ts_qops; | |
| 810 | +int saa7134_ts_buffer_init(struct vb2_buffer *vb2); | |
| 811 | +int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2); | |
| 812 | +void saa7134_ts_buffer_finish(struct vb2_buffer *vb2); | |
| 813 | +int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, | |
| 814 | + unsigned int *nbuffers, unsigned int *nplanes, | |
| 815 | + unsigned int sizes[], void *alloc_ctxs[]); | |
| 816 | +int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count); | |
| 817 | +void saa7134_ts_stop_streaming(struct vb2_queue *vq); | |
| 818 | + | |
| 819 | +extern struct vb2_ops saa7134_ts_qops; | |
| 822 | 820 | |
| 823 | 821 | int saa7134_ts_init1(struct saa7134_dev *dev); |
| 824 | 822 | int saa7134_ts_fini(struct saa7134_dev *dev); |
| @@ -835,7 +833,7 @@ int saa7134_ts_stop(struct saa7134_dev *dev); · 10 unmodified lines | ||
| 835 | 833 | /* ----------------------------------------------------------- */ |
| 836 | 834 | /* saa7134-vbi.c */ |
| 837 | 835 | |
| 838 | −extern struct videobuf_queue_ops saa7134_vbi_qops; | |
| 836 | +extern struct vb2_ops saa7134_vbi_qops; | |
| 839 | 837 | extern struct video_device saa7134_vbi_template; |
| 840 | 838 | |
| 841 | 839 | int saa7134_vbi_init1(struct saa7134_dev *dev); |
| @@ -357,7 +357,7 @@ static int mxb_init_done(struct saa7146_dev* dev) · 356 unmodified lines | ||
| 357 | 357 | tea6420_route(mxb, 6); |
| 358 | 358 | |
| 359 | 359 | /* select video mode in saa7111a */ |
| 360 | − saa7111a_call(mxb, core, s_std, std); | |
| 360 | + saa7111a_call(mxb, video, s_std, std); | |
| 361 | 361 | |
| 362 | 362 | /* select tuner-output on saa7111a */ |
| 363 | 363 | i = 0; |
| @@ -379,8 +379,8 @@ static int mxb_init_done(struct saa7146_dev* dev) · 15 unmodified lines | ||
| 379 | 379 | /* These two gpio calls set the GPIO pins that control the tda9820 */ |
| 380 | 380 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
| 381 | 381 | saa7111a_call(mxb, core, s_gpio, 1); |
| 382 | − saa7111a_call(mxb, core, s_std, std); | |
| 383 | − tuner_call(mxb, core, s_std, std); | |
| 382 | + saa7111a_call(mxb, video, s_std, std); | |
| 383 | + tuner_call(mxb, video, s_std, std); | |
| 384 | 384 | |
| 385 | 385 | /* switch to tuner-channel on tea6415c */ |
| 386 | 386 | tea6415c_call(mxb, video, s_routing, 3, 17, 0); |
| @@ -771,9 +771,9 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa · 384 unmodified lines | ||
| 771 | 771 | /* These two gpio calls set the GPIO pins that control the tda9820 */ |
| 772 | 772 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
| 773 | 773 | saa7111a_call(mxb, core, s_gpio, 0); |
| 774 | − saa7111a_call(mxb, core, s_std, std); | |
| 774 | + saa7111a_call(mxb, video, s_std, std); | |
| 775 | 775 | if (mxb->cur_input == 0) |
| 776 | − tuner_call(mxb, core, s_std, std); | |
| 776 | + tuner_call(mxb, video, s_std, std); | |
| 777 | 777 | } else { |
| 778 | 778 | v4l2_std_id std = V4L2_STD_PAL_BG; |
| 779 | 779 | |
| @@ -783,9 +783,9 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa · 3 unmodified lines | ||
| 783 | 783 | /* These two gpio calls set the GPIO pins that control the tda9820 */ |
| 784 | 784 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
| 785 | 785 | saa7111a_call(mxb, core, s_gpio, 1); |
| 786 | − saa7111a_call(mxb, core, s_std, std); | |
| 786 | + saa7111a_call(mxb, video, s_std, std); | |
| 787 | 787 | if (mxb->cur_input == 0) |
| 788 | − tuner_call(mxb, core, s_std, std); | |
| 788 | + tuner_call(mxb, video, s_std, std); | |
| 789 | 789 | } |
| 790 | 790 | return 0; |
| 791 | 791 | } |
| @@ -357,7 +357,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 356 unmodified lines | ||
| 357 | 357 | } |
| 358 | 358 | |
| 359 | 359 | /* abort streaming and wait for last buffer */ |
| 360 | −static int stop_streaming(struct vb2_queue *vq) | |
| 360 | +static void stop_streaming(struct vb2_queue *vq) | |
| 361 | 361 | { |
| 362 | 362 | struct sta2x11_vip *vip = vb2_get_drv_priv(vq); |
| 363 | 363 | struct vip_buffer *vip_buf, *node; |
| @@ -374,7 +374,6 @@ static int stop_streaming(struct vb2_queue *vq) · 10 unmodified lines | ||
| 374 | 374 | list_del(&vip_buf->list); |
| 375 | 375 | } |
| 376 | 376 | spin_unlock(&vip->lock); |
| 377 | − return 0; | |
| 378 | 377 | } |
| 379 | 378 | |
| 380 | 379 | static struct vb2_ops vip_video_qops = { |
| @@ -445,7 +444,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) · 64 unmodified lines | ||
| 445 | 444 | int status; |
| 446 | 445 | |
| 447 | 446 | if (V4L2_STD_ALL == std) { |
| 448 | − v4l2_subdev_call(vip->decoder, core, s_std, std); | |
| 447 | + v4l2_subdev_call(vip->decoder, video, s_std, std); | |
| 449 | 448 | ssleep(2); |
| 450 | 449 | v4l2_subdev_call(vip->decoder, video, querystd, &newstd); |
| 451 | 450 | v4l2_subdev_call(vip->decoder, video, g_input_status, &status); |
| @@ -468,7 +467,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) · 16 unmodified lines | ||
| 468 | 467 | vip->format = formats_50[0]; |
| 469 | 468 | } |
| 470 | 469 | |
| 471 | − return v4l2_subdev_call(vip->decoder, core, s_std, std); | |
| 470 | + return v4l2_subdev_call(vip->decoder, video, s_std, std); | |
| 472 | 471 | } |
| 473 | 472 | |
| 474 | 473 | /** |
| @@ -958,8 +958,10 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait) · 957 unmodified lines | ||
| 958 | 958 | if (av7110->playing) { |
| 959 | 959 | if (FREE_COND) |
| 960 | 960 | mask |= (POLLOUT | POLLWRNORM); |
| 961 | − } else /* if not playing: may play if asked for */ | |
| 962 | − mask |= (POLLOUT | POLLWRNORM); | |
| 961 | + } else { | |
| 962 | + /* if not playing: may play if asked for */ | |
| 963 | + mask |= (POLLOUT | POLLWRNORM); | |
| 964 | + } | |
| 963 | 965 | } |
| 964 | 966 | |
| 965 | 967 | return mask; |
| @@ -1572,7 +1572,7 @@ zoran_init_hardware (struct zoran *zr) · 1571 unmodified lines | ||
| 1572 | 1572 | } |
| 1573 | 1573 | |
| 1574 | 1574 | decoder_call(zr, core, init, 0); |
| 1575 | − decoder_call(zr, core, s_std, zr->norm); | |
| 1575 | + decoder_call(zr, video, s_std, zr->norm); | |
| 1576 | 1576 | decoder_call(zr, video, s_routing, |
| 1577 | 1577 | zr->card.input[zr->input].muxsel, 0, 0); |
| 1578 | 1578 | |
| @@ -1469,7 +1469,7 @@ zoran_set_norm (struct zoran *zr, · 1468 unmodified lines | ||
| 1469 | 1469 | if (on) |
| 1470 | 1470 | zr36057_overlay(zr, 0); |
| 1471 | 1471 | |
| 1472 | − decoder_call(zr, core, s_std, norm); | |
| 1472 | + decoder_call(zr, video, s_std, norm); | |
| 1473 | 1473 | encoder_call(zr, video, s_std_output, norm); |
| 1474 | 1474 | |
| 1475 | 1475 | if (on) |
| @@ -427,15 +427,12 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) · 426 unmodified lines | ||
| 427 | 427 | return 0; |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | −static int bcap_stop_streaming(struct vb2_queue *vq) | |
| 430 | +static void bcap_stop_streaming(struct vb2_queue *vq) | |
| 431 | 431 | { |
| 432 | 432 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); |
| 433 | 433 | struct ppi_if *ppi = bcap_dev->ppi; |
| 434 | 434 | int ret; |
| 435 | 435 | |
| 436 | − if (!vb2_is_streaming(vq)) | |
| 437 | − return 0; | |
| 438 | − | |
| 439 | 436 | bcap_dev->stop = true; |
| 440 | 437 | wait_for_completion(&bcap_dev->comp); |
| 441 | 438 | ppi->ops->stop(ppi); |
| @@ -452,7 +449,6 @@ static int bcap_stop_streaming(struct vb2_queue *vq) · 10 unmodified lines | ||
| 452 | 449 | list_del(&bcap_dev->cur_frm->list); |
| 453 | 450 | vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR); |
| 454 | 451 | } |
| 455 | − return 0; | |
| 456 | 452 | } |
| 457 | 453 | |
| 458 | 454 | static struct vb2_ops bcap_video_qops = { |
| @@ -635,7 +631,7 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std) · 176 unmodified lines | ||
| 635 | 631 | if (vb2_is_busy(&bcap_dev->buffer_queue)) |
| 636 | 632 | return -EBUSY; |
| 637 | 633 | |
| 638 | − ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, std); | |
| 634 | + ret = v4l2_subdev_call(bcap_dev->sd, video, s_std, std); | |
| 639 | 635 | if (ret < 0) |
| 640 | 636 | return ret; |
| 641 | 637 | |
| @@ -648,7 +644,9 @@ static int bcap_enum_dv_timings(struct file *file, void *priv, · 6 unmodified lines | ||
| 648 | 644 | { |
| 649 | 645 | struct bcap_device *bcap_dev = video_drvdata(file); |
| 650 | 646 | |
| 651 | − return v4l2_subdev_call(bcap_dev->sd, video, | |
| 647 | + timings->pad = 0; | |
| 648 | + | |
| 649 | + return v4l2_subdev_call(bcap_dev->sd, pad, | |
| 652 | 650 | enum_dv_timings, timings); |
| 653 | 651 | } |
| 654 | 652 | |
| @@ -1069,7 +1067,7 @@ static int bcap_probe(struct platform_device *pdev) · 414 unmodified lines | ||
| 1069 | 1067 | /* now we can probe the default state */ |
| 1070 | 1068 | if (config->inputs[0].capabilities & V4L2_IN_CAP_STD) { |
| 1071 | 1069 | v4l2_std_id std; |
| 1072 | − ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); | |
| 1070 | + ret = v4l2_subdev_call(bcap_dev->sd, video, g_std, &std); | |
| 1073 | 1071 | if (ret) { |
| 1074 | 1072 | v4l2_err(&bcap_dev->v4l2_dev, |
| 1075 | 1073 | "Unable to get std\n"); |
| @@ -2269,7 +2269,7 @@ out: · 2268 unmodified lines | ||
| 2269 | 2269 | return ret; |
| 2270 | 2270 | } |
| 2271 | 2271 | |
| 2272 | −static int coda_stop_streaming(struct vb2_queue *q) | |
| 2272 | +static void coda_stop_streaming(struct vb2_queue *q) | |
| 2273 | 2273 | { |
| 2274 | 2274 | struct coda_ctx *ctx = vb2_get_drv_priv(q); |
| 2275 | 2275 | struct coda_dev *dev = ctx->dev; |
| @@ -2295,8 +2295,6 @@ static int coda_stop_streaming(struct vb2_queue *q) · 19 unmodified lines | ||
| 2295 | 2295 | ctx->bitstream.vaddr, ctx->bitstream.size); |
| 2296 | 2296 | ctx->runcounter = 0; |
| 2297 | 2297 | } |
| 2298 | − | |
| 2299 | − return 0; | |
| 2300 | 2298 | } |
| 2301 | 2299 | |
| 2302 | 2300 | static struct vb2_ops coda_qops = { |
| @@ -3235,7 +3233,7 @@ static int coda_probe(struct platform_device *pdev) · 932 unmodified lines | ||
| 3235 | 3233 | } |
| 3236 | 3234 | |
| 3237 | 3235 | if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler, |
| 3238 | − IRQF_ONESHOT, CODA_NAME, dev) < 0) { | |
| 3236 | + IRQF_ONESHOT, dev_name(&pdev->dev), dev) < 0) { | |
| 3239 | 3237 | dev_err(&pdev->dev, "failed to request irq\n"); |
| 3240 | 3238 | return -ENOENT; |
| 3241 | 3239 | } |
| @@ -355,8 +355,17 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count) · 354 unmodified lines | ||
| 355 | 355 | |
| 356 | 356 | /* Set parameters in OSD and VENC */ |
| 357 | 357 | ret = vpbe_set_osd_display_params(fh->disp_dev, layer); |
| 358 | − if (ret < 0) | |
| 358 | + if (ret < 0) { | |
| 359 | + struct vpbe_disp_buffer *buf, *tmp; | |
| 360 | + | |
| 361 | + vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_QUEUED); | |
| 362 | + list_for_each_entry_safe(buf, tmp, &layer->dma_queue, list) { | |
| 363 | + list_del(&buf->list); | |
| 364 | + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | |
| 365 | + } | |
| 366 | + | |
| 359 | 367 | return ret; |
| 368 | + } | |
| 360 | 369 | |
| 361 | 370 | /* |
| 362 | 371 | * if request format is yuv420 semiplanar, need to |
| @@ -368,7 +377,7 @@ static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count) · 5 unmodified lines | ||
| 368 | 377 | return ret; |
| 369 | 378 | } |
| 370 | 379 | |
| 371 | −static int vpbe_stop_streaming(struct vb2_queue *vq) | |
| 380 | +static void vpbe_stop_streaming(struct vb2_queue *vq) | |
| 372 | 381 | { |
| 373 | 382 | struct vpbe_fh *fh = vb2_get_drv_priv(vq); |
| 374 | 383 | struct vpbe_layer *layer = fh->layer; |
| @@ -376,7 +385,7 @@ static int vpbe_stop_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 376 | 385 | unsigned long flags; |
| 377 | 386 | |
| 378 | 387 | if (!vb2_is_streaming(vq)) |
| 379 | − return 0; | |
| 388 | + return; | |
| 380 | 389 | |
| 381 | 390 | /* release all active buffers */ |
| 382 | 391 | spin_lock_irqsave(&disp->dma_queue_lock, flags); |
| @@ -398,7 +407,6 @@ static int vpbe_stop_streaming(struct vb2_queue *vq) · 15 unmodified lines | ||
| 398 | 407 | vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR); |
| 399 | 408 | } |
| 400 | 409 | spin_unlock_irqrestore(&disp->dma_queue_lock, flags); |
| 401 | − return 0; | |
| 402 | 410 | } |
| 403 | 411 | |
| 404 | 412 | static struct vb2_ops video_qops = { |
| @@ -680,29 +688,6 @@ static int vpbe_try_format(struct vpbe_display *disp_dev, · 275 unmodified lines | ||
| 680 | 688 | return 0; |
| 681 | 689 | } |
| 682 | 690 | |
| 683 | −static int vpbe_display_g_priority(struct file *file, void *priv, | |
| 684 | − enum v4l2_priority *p) | |
| 685 | −{ | |
| 686 | − struct vpbe_fh *fh = file->private_data; | |
| 687 | − struct vpbe_layer *layer = fh->layer; | |
| 688 | − | |
| 689 | − *p = v4l2_prio_max(&layer->prio); | |
| 690 | − | |
| 691 | − return 0; | |
| 692 | −} | |
| 693 | − | |
| 694 | −static int vpbe_display_s_priority(struct file *file, void *priv, | |
| 695 | − enum v4l2_priority p) | |
| 696 | −{ | |
| 697 | − struct vpbe_fh *fh = file->private_data; | |
| 698 | − struct vpbe_layer *layer = fh->layer; | |
| 699 | − int ret; | |
| 700 | − | |
| 701 | − ret = v4l2_prio_change(&layer->prio, &fh->prio, p); | |
| 702 | − | |
| 703 | − return ret; | |
| 704 | −} | |
| 705 | − | |
| 706 | 691 | static int vpbe_display_querycap(struct file *file, void *priv, |
| 707 | 692 | struct v4l2_capability *cap) |
| 708 | 693 | { |
| @@ -1492,6 +1477,7 @@ static int vpbe_display_open(struct file *file) · 783 unmodified lines | ||
| 1492 | 1477 | { |
| 1493 | 1478 | struct vpbe_fh *fh = NULL; |
| 1494 | 1479 | struct vpbe_layer *layer = video_drvdata(file); |
| 1480 | + struct video_device *vdev = video_devdata(file); | |
| 1495 | 1481 | struct vpbe_display *disp_dev = layer->disp_dev; |
| 1496 | 1482 | struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; |
| 1497 | 1483 | struct osd_state *osd_device = disp_dev->osd_device; |
| @@ -1504,6 +1490,7 @@ static int vpbe_display_open(struct file *file) · 6 unmodified lines | ||
| 1504 | 1490 | "unable to allocate memory for file handle object\n"); |
| 1505 | 1491 | return -ENOMEM; |
| 1506 | 1492 | } |
| 1493 | + v4l2_fh_init(&fh->fh, vdev); | |
| 1507 | 1494 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, |
| 1508 | 1495 | "vpbe display open plane = %d\n", |
| 1509 | 1496 | layer->device_id); |
| @@ -1532,9 +1519,7 @@ static int vpbe_display_open(struct file *file) · 22 unmodified lines | ||
| 1532 | 1519 | layer->usrs++; |
| 1533 | 1520 | /* Set io_allowed member to false */ |
| 1534 | 1521 | fh->io_allowed = 0; |
| 1535 | − /* Initialize priority of this instance to default priority */ | |
| 1536 | − fh->prio = V4L2_PRIORITY_UNSET; | |
| 1537 | − v4l2_prio_open(&layer->prio, &fh->prio); | |
| 1522 | + v4l2_fh_add(&fh->fh); | |
| 1538 | 1523 | v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, |
| 1539 | 1524 | "vpbe display device opened successfully\n"); |
| 1540 | 1525 | return 0; |
| @@ -1589,8 +1574,9 @@ static int vpbe_display_release(struct file *file) · 48 unmodified lines | ||
| 1589 | 1574 | osd_device->ops.release_layer(osd_device, |
| 1590 | 1575 | layer->layer_info.id); |
| 1591 | 1576 | } |
| 1592 | − /* Close the priority */ | |
| 1593 | − v4l2_prio_close(&layer->prio, fh->prio); | |
| 1577 | + | |
| 1578 | + v4l2_fh_del(&fh->fh); | |
| 1579 | + v4l2_fh_exit(&fh->fh); | |
| 1594 | 1580 | file->private_data = NULL; |
| 1595 | 1581 | mutex_unlock(&layer->opslock); |
| 1596 | 1582 | |
| @@ -1618,8 +1604,6 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { · 21 unmodified lines | ||
| 1618 | 1604 | .vidioc_cropcap = vpbe_display_cropcap, |
| 1619 | 1605 | .vidioc_g_crop = vpbe_display_g_crop, |
| 1620 | 1606 | .vidioc_s_crop = vpbe_display_s_crop, |
| 1621 | − .vidioc_g_priority = vpbe_display_g_priority, | |
| 1622 | − .vidioc_s_priority = vpbe_display_s_priority, | |
| 1623 | 1607 | .vidioc_s_std = vpbe_display_s_std, |
| 1624 | 1608 | .vidioc_g_std = vpbe_display_g_std, |
| 1625 | 1609 | .vidioc_enum_output = vpbe_display_enum_output, |
| @@ -1699,8 +1683,6 @@ static int init_vpbe_layer(int i, struct vpbe_display *disp_dev, · 73 unmodified lines | ||
| 1699 | 1683 | vpbe_display_layer->layer_info.id = |
| 1700 | 1684 | ((i == VPBE_DISPLAY_DEVICE_0) ? WIN_VID0 : WIN_VID1); |
| 1701 | 1685 | |
| 1702 | − /* Initialize prio member of layer object */ | |
| 1703 | − v4l2_prio_init(&vpbe_display_layer->prio); | |
| 1704 | 1686 | |
| 1705 | 1687 | return 0; |
| 1706 | 1688 | } |
| @@ -1727,6 +1709,7 @@ static int register_device(struct vpbe_layer *vpbe_display_layer, · 20 unmodified lines | ||
| 1727 | 1709 | vpbe_display_layer->disp_dev = disp_dev; |
| 1728 | 1710 | /* set the driver data in platform device */ |
| 1729 | 1711 | platform_set_drvdata(pdev, disp_dev); |
| 1712 | + set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags); | |
| 1730 | 1713 | video_set_drvdata(&vpbe_display_layer->video_dev, |
| 1731 | 1714 | vpbe_display_layer); |
| 1732 | 1715 | |
| @@ -498,6 +498,7 @@ unlock: · 497 unmodified lines | ||
| 498 | 498 | static int vpfe_open(struct file *file) |
| 499 | 499 | { |
| 500 | 500 | struct vpfe_device *vpfe_dev = video_drvdata(file); |
| 501 | + struct video_device *vdev = video_devdata(file); | |
| 501 | 502 | struct vpfe_fh *fh; |
| 502 | 503 | |
| 503 | 504 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n"); |
| @@ -517,6 +518,7 @@ static int vpfe_open(struct file *file) · 13 unmodified lines | ||
| 517 | 518 | /* store pointer to fh in private_data member of file */ |
| 518 | 519 | file->private_data = fh; |
| 519 | 520 | fh->vpfe_dev = vpfe_dev; |
| 521 | + v4l2_fh_init(&fh->fh, vdev); | |
| 520 | 522 | mutex_lock(&vpfe_dev->lock); |
| 521 | 523 | /* If decoder is not initialized. initialize it */ |
| 522 | 524 | if (!vpfe_dev->initialized) { |
| @@ -529,9 +531,7 @@ static int vpfe_open(struct file *file) · 6 unmodified lines | ||
| 529 | 531 | vpfe_dev->usrs++; |
| 530 | 532 | /* Set io_allowed member to false */ |
| 531 | 533 | fh->io_allowed = 0; |
| 532 | − /* Initialize priority of this instance to default priority */ | |
| 533 | − fh->prio = V4L2_PRIORITY_UNSET; | |
| 534 | − v4l2_prio_open(&vpfe_dev->prio, &fh->prio); | |
| 534 | + v4l2_fh_add(&fh->fh); | |
| 535 | 535 | mutex_unlock(&vpfe_dev->lock); |
| 536 | 536 | return 0; |
| 537 | 537 | } |
| @@ -740,8 +740,8 @@ static int vpfe_release(struct file *file) · 202 unmodified lines | ||
| 740 | 740 | |
| 741 | 741 | /* Decrement device usrs counter */ |
| 742 | 742 | vpfe_dev->usrs--; |
| 743 | − /* Close the priority */ | |
| 744 | − v4l2_prio_close(&vpfe_dev->prio, fh->prio); | |
| 743 | + v4l2_fh_del(&fh->fh); | |
| 744 | + v4l2_fh_exit(&fh->fh); | |
| 745 | 745 | /* If this is the last file handle */ |
| 746 | 746 | if (!vpfe_dev->usrs) { |
| 747 | 747 | vpfe_dev->initialized = 0; |
| @@ -1217,7 +1217,7 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) · 469 unmodified lines | ||
| 1217 | 1217 | } |
| 1218 | 1218 | |
| 1219 | 1219 | ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, |
| 1220 | − core, s_std, std_id); | |
| 1220 | + video, s_std, std_id); | |
| 1221 | 1221 | if (ret < 0) { |
| 1222 | 1222 | v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); |
| 1223 | 1223 | goto unlock_out; |
| @@ -1910,14 +1910,13 @@ static int vpfe_probe(struct platform_device *pdev) · 686 unmodified lines | ||
| 1910 | 1910 | /* Initialize field of the device objects */ |
| 1911 | 1911 | vpfe_dev->numbuffers = config_params.numbuffers; |
| 1912 | 1912 | |
| 1913 | − /* Initialize prio member of device object */ | |
| 1914 | − v4l2_prio_init(&vpfe_dev->prio); | |
| 1915 | 1913 | /* register video device */ |
| 1916 | 1914 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
| 1917 | 1915 | "trying to register vpfe device.\n"); |
| 1918 | 1916 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
| 1919 | 1917 | "video_dev=%x\n", (int)&vpfe_dev->video_dev); |
| 1920 | 1918 | vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 1919 | + set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags); | |
| 1921 | 1920 | ret = video_register_device(vpfe_dev->video_dev, |
| 1922 | 1921 | VFL_TYPE_GRABBER, -1); |
| 1923 | 1922 | |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2009 Texas Instruments Inc |
| 3 | + * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com> | |
| 3 | 4 | * |
| 4 | 5 | * This program is free software; you can redistribute it and/or modify |
| 5 | 6 | * it under the terms of the GNU General Public License as published by |
| @@ -65,14 +66,26 @@ static struct vpif_config_params config_params = { · 59 unmodified lines | ||
| 65 | 66 | .channel_bufsize[1] = 720 * 576 * 2, |
| 66 | 67 | }; |
| 67 | 68 | |
| 69 | +#define VPIF_DRIVER_NAME "vpif_capture" | |
| 70 | + | |
| 68 | 71 | /* global variables */ |
| 69 | 72 | static struct vpif_device vpif_obj = { {NULL} }; |
| 70 | 73 | static struct device *vpif_dev; |
| 71 | 74 | static void vpif_calculate_offsets(struct channel_obj *ch); |
| 72 | 75 | static void vpif_config_addr(struct channel_obj *ch, int muxmode); |
| 73 | 76 | |
| 77 | +static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} }; | |
| 78 | + | |
| 79 | +/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ | |
| 80 | +static int ycmux_mode; | |
| 81 | + | |
| 82 | +static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_buffer *vb) | |
| 83 | +{ | |
| 84 | + return container_of(vb, struct vpif_cap_buffer, vb); | |
| 85 | +} | |
| 86 | + | |
| 74 | 87 | /** |
| 75 | − * buffer_prepare : callback function for buffer prepare | |
| 88 | + * vpif_buffer_prepare : callback function for buffer prepare | |
| 76 | 89 | * @vb: ptr to vb2_buffer |
| 77 | 90 | * |
| 78 | 91 | * This is the callback function for buffer prepare when vb2_qbuf() |
| @@ -81,10 +94,8 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode); · 2 unmodified lines | ||
| 81 | 94 | */ |
| 82 | 95 | static int vpif_buffer_prepare(struct vb2_buffer *vb) |
| 83 | 96 | { |
| 84 | − /* Get the file handle object and channel object */ | |
| 85 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 86 | 97 | struct vb2_queue *q = vb->vb2_queue; |
| 87 | − struct channel_obj *ch = fh->channel; | |
| 98 | + struct channel_obj *ch = vb2_get_drv_priv(q); | |
| 88 | 99 | struct common_obj *common; |
| 89 | 100 | unsigned long addr; |
| 90 | 101 | |
| @@ -92,26 +103,22 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb) · 1 unmodified line | ||
| 92 | 103 | |
| 93 | 104 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 94 | 105 | |
| 95 | − if (vb->state != VB2_BUF_STATE_ACTIVE && | |
| 96 | − vb->state != VB2_BUF_STATE_PREPARED) { | |
| 97 | − vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); | |
| 98 | − if (vb2_plane_vaddr(vb, 0) && | |
| 99 | − vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) | |
| 100 | − goto exit; | |
| 101 | − addr = vb2_dma_contig_plane_dma_addr(vb, 0); | |
| 106 | + vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); | |
| 107 | + if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) | |
| 108 | + return -EINVAL; | |
| 102 | 109 | |
| 103 | − if (q->streaming) { | |
| 104 | − if (!IS_ALIGNED((addr + common->ytop_off), 8) || | |
| 105 | − !IS_ALIGNED((addr + common->ybtm_off), 8) || | |
| 106 | − !IS_ALIGNED((addr + common->ctop_off), 8) || | |
| 107 | − !IS_ALIGNED((addr + common->cbtm_off), 8)) | |
| 108 | − goto exit; | |
| 109 | − } | |
| 110 | + vb->v4l2_buf.field = common->fmt.fmt.pix.field; | |
| 111 | + | |
| 112 | + addr = vb2_dma_contig_plane_dma_addr(vb, 0); | |
| 113 | + if (!IS_ALIGNED((addr + common->ytop_off), 8) || | |
| 114 | + !IS_ALIGNED((addr + common->ybtm_off), 8) || | |
| 115 | + !IS_ALIGNED((addr + common->ctop_off), 8) || | |
| 116 | + !IS_ALIGNED((addr + common->cbtm_off), 8)) { | |
| 117 | + vpif_dbg(1, debug, "offset is not aligned\n"); | |
| 118 | + return -EINVAL; | |
| 110 | 119 | } |
| 120 | + | |
| 111 | 121 | return 0; |
| 112 | −exit: | |
| 113 | − vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n"); | |
| 114 | − return -EINVAL; | |
| 115 | 122 | } |
| 116 | 123 | |
| 117 | 124 | /** |
| @@ -131,49 +138,26 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq, · 13 unmodified lines | ||
| 131 | 138 | unsigned int *nbuffers, unsigned int *nplanes, |
| 132 | 139 | unsigned int sizes[], void *alloc_ctxs[]) |
| 133 | 140 | { |
| 134 | − /* Get the file handle object and channel object */ | |
| 135 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 136 | − struct channel_obj *ch = fh->channel; | |
| 141 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 137 | 142 | struct common_obj *common; |
| 138 | − unsigned long size; | |
| 139 | 143 | |
| 140 | 144 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 141 | 145 | |
| 142 | 146 | vpif_dbg(2, debug, "vpif_buffer_setup\n"); |
| 143 | 147 | |
| 144 | − /* If memory type is not mmap, return */ | |
| 145 | − if (V4L2_MEMORY_MMAP == common->memory) { | |
| 146 | − /* Calculate the size of the buffer */ | |
| 147 | − size = config_params.channel_bufsize[ch->channel_id]; | |
| 148 | − /* | |
| 149 | − * Checking if the buffer size exceeds the available buffer | |
| 150 | − * ycmux_mode = 0 means 1 channel mode HD and | |
| 151 | − * ycmux_mode = 1 means 2 channels mode SD | |
| 152 | − */ | |
| 153 | − if (ch->vpifparams.std_info.ycmux_mode == 0) { | |
| 154 | − if (config_params.video_limit[ch->channel_id]) | |
| 155 | − while (size * *nbuffers > | |
| 156 | − (config_params.video_limit[0] | |
| 157 | − + config_params.video_limit[1])) | |
| 158 | − (*nbuffers)--; | |
| 159 | − } else { | |
| 160 | − if (config_params.video_limit[ch->channel_id]) | |
| 161 | − while (size * *nbuffers > | |
| 162 | − config_params.video_limit[ch->channel_id]) | |
| 163 | − (*nbuffers)--; | |
| 164 | − } | |
| 165 | − | |
| 166 | − } else { | |
| 167 | − size = common->fmt.fmt.pix.sizeimage; | |
| 168 | − } | |
| 148 | + if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) | |
| 149 | + return -EINVAL; | |
| 169 | 150 | |
| 170 | − if (*nbuffers < config_params.min_numbuffers) | |
| 171 | − *nbuffers = config_params.min_numbuffers; | |
| 151 | + if (vq->num_buffers + *nbuffers < 3) | |
| 152 | + *nbuffers = 3 - vq->num_buffers; | |
| 172 | 153 | |
| 173 | 154 | *nplanes = 1; |
| 174 | − sizes[0] = size; | |
| 155 | + sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage; | |
| 175 | 156 | alloc_ctxs[0] = common->alloc_ctx; |
| 176 | 157 | |
| 158 | + /* Calculate the offset for Y and C data in the buffer */ | |
| 159 | + vpif_calculate_offsets(ch); | |
| 160 | + | |
| 177 | 161 | return 0; |
| 178 | 162 | } |
| 179 | 163 | |
| @@ -183,11 +167,8 @@ static int vpif_buffer_queue_setup(struct vb2_queue *vq, · 3 unmodified lines | ||
| 183 | 167 | */ |
| 184 | 168 | static void vpif_buffer_queue(struct vb2_buffer *vb) |
| 185 | 169 | { |
| 186 | − /* Get the file handle object and channel object */ | |
| 187 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 188 | − struct channel_obj *ch = fh->channel; | |
| 189 | − struct vpif_cap_buffer *buf = container_of(vb, | |
| 190 | − struct vpif_cap_buffer, vb); | |
| 170 | + struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); | |
| 171 | + struct vpif_cap_buffer *buf = to_vpif_buffer(vb); | |
| 191 | 172 | struct common_obj *common; |
| 192 | 173 | unsigned long flags; |
| 193 | 174 | |
| @@ -202,102 +183,25 @@ static void vpif_buffer_queue(struct vb2_buffer *vb) · 8 unmodified lines | ||
| 202 | 183 | } |
| 203 | 184 | |
| 204 | 185 | /** |
| 205 | − * vpif_buf_cleanup : Callback function to free buffer | |
| 186 | + * vpif_start_streaming : Starts the DMA engine for streaming | |
| 206 | 187 | * @vb: ptr to vb2_buffer |
| 207 | − * | |
| 208 | − * This function is called from the videobuf2 layer to free memory | |
| 209 | − * allocated to the buffers | |
| 188 | + * @count: number of buffers | |
| 210 | 189 | */ |
| 211 | −static void vpif_buf_cleanup(struct vb2_buffer *vb) | |
| 212 | −{ | |
| 213 | − /* Get the file handle object and channel object */ | |
| 214 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 215 | − struct vpif_cap_buffer *buf = container_of(vb, | |
| 216 | − struct vpif_cap_buffer, vb); | |
| 217 | − struct channel_obj *ch = fh->channel; | |
| 218 | − struct common_obj *common; | |
| 219 | − unsigned long flags; | |
| 220 | − | |
| 221 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 222 | − | |
| 223 | − spin_lock_irqsave(&common->irqlock, flags); | |
| 224 | − if (vb->state == VB2_BUF_STATE_ACTIVE) | |
| 225 | − list_del_init(&buf->list); | |
| 226 | − spin_unlock_irqrestore(&common->irqlock, flags); | |
| 227 | − | |
| 228 | −} | |
| 229 | − | |
| 230 | −static void vpif_wait_prepare(struct vb2_queue *vq) | |
| 231 | −{ | |
| 232 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 233 | − struct channel_obj *ch = fh->channel; | |
| 234 | − struct common_obj *common; | |
| 235 | − | |
| 236 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 237 | − mutex_unlock(&common->lock); | |
| 238 | −} | |
| 239 | − | |
| 240 | −static void vpif_wait_finish(struct vb2_queue *vq) | |
| 241 | −{ | |
| 242 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 243 | − struct channel_obj *ch = fh->channel; | |
| 244 | − struct common_obj *common; | |
| 245 | − | |
| 246 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 247 | − mutex_lock(&common->lock); | |
| 248 | −} | |
| 249 | − | |
| 250 | −static int vpif_buffer_init(struct vb2_buffer *vb) | |
| 251 | −{ | |
| 252 | − struct vpif_cap_buffer *buf = container_of(vb, | |
| 253 | − struct vpif_cap_buffer, vb); | |
| 254 | − | |
| 255 | − INIT_LIST_HEAD(&buf->list); | |
| 256 | − | |
| 257 | − return 0; | |
| 258 | −} | |
| 259 | − | |
| 260 | −static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = | |
| 261 | − { {1, 1} }; | |
| 262 | − | |
| 263 | 190 | static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) |
| 264 | 191 | { |
| 265 | 192 | struct vpif_capture_config *vpif_config_data = |
| 266 | 193 | vpif_dev->platform_data; |
| 267 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 268 | − struct channel_obj *ch = fh->channel; | |
| 194 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 269 | 195 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 270 | 196 | struct vpif_params *vpif = &ch->vpifparams; |
| 271 | − unsigned long addr = 0; | |
| 272 | − unsigned long flags; | |
| 197 | + struct vpif_cap_buffer *buf, *tmp; | |
| 198 | + unsigned long addr, flags; | |
| 273 | 199 | int ret; |
| 274 | 200 | |
| 275 | 201 | spin_lock_irqsave(&common->irqlock, flags); |
| 276 | 202 | |
| 277 | − /* Get the next frame from the buffer queue */ | |
| 278 | − common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, | |
| 279 | − struct vpif_cap_buffer, list); | |
| 280 | − /* Remove buffer from the buffer queue */ | |
| 281 | − list_del(&common->cur_frm->list); | |
| 282 | − spin_unlock_irqrestore(&common->irqlock, flags); | |
| 283 | − /* Mark state of the current frame to active */ | |
| 284 | − common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | |
| 285 | − /* Initialize field_id and started member */ | |
| 203 | + /* Initialize field_id */ | |
| 286 | 204 | ch->field_id = 0; |
| 287 | − common->started = 1; | |
| 288 | − addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | |
| 289 | − | |
| 290 | − /* Calculate the offset for Y and C data in the buffer */ | |
| 291 | − vpif_calculate_offsets(ch); | |
| 292 | − | |
| 293 | − if ((vpif->std_info.frm_fmt && | |
| 294 | − ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && | |
| 295 | − (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || | |
| 296 | − (!vpif->std_info.frm_fmt && | |
| 297 | − (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { | |
| 298 | − vpif_dbg(1, debug, "conflict in field format and std format\n"); | |
| 299 | − return -EINVAL; | |
| 300 | − } | |
| 301 | 205 | |
| 302 | 206 | /* configure 1 or 2 channel mode */ |
| 303 | 207 | if (vpif_config_data->setup_input_channel_mode) { |
| @@ -305,21 +209,37 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) · 1 unmodified line | ||
| 305 | 209 | setup_input_channel_mode(vpif->std_info.ycmux_mode); |
| 306 | 210 | if (ret < 0) { |
| 307 | 211 | vpif_dbg(1, debug, "can't set vpif channel mode\n"); |
| 308 | − return ret; | |
| 212 | + goto err; | |
| 309 | 213 | } |
| 310 | 214 | } |
| 311 | 215 | |
| 216 | + ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); | |
| 217 | + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { | |
| 218 | + vpif_dbg(1, debug, "stream on failed in subdev\n"); | |
| 219 | + goto err; | |
| 220 | + } | |
| 221 | + | |
| 312 | 222 | /* Call vpif_set_params function to set the parameters and addresses */ |
| 313 | 223 | ret = vpif_set_video_params(vpif, ch->channel_id); |
| 314 | − | |
| 315 | 224 | if (ret < 0) { |
| 316 | 225 | vpif_dbg(1, debug, "can't set video params\n"); |
| 317 | − return ret; | |
| 226 | + goto err; | |
| 318 | 227 | } |
| 319 | 228 | |
| 320 | − common->started = ret; | |
| 229 | + ycmux_mode = ret; | |
| 321 | 230 | vpif_config_addr(ch, ret); |
| 322 | 231 | |
| 232 | + /* Get the next frame from the buffer queue */ | |
| 233 | + common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, | |
| 234 | + struct vpif_cap_buffer, list); | |
| 235 | + /* Remove buffer from the buffer queue */ | |
| 236 | + list_del(&common->cur_frm->list); | |
| 237 | + spin_unlock_irqrestore(&common->irqlock, flags); | |
| 238 | + /* Mark state of the current frame to active */ | |
| 239 | + common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | |
| 240 | + | |
| 241 | + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | |
| 242 | + | |
| 323 | 243 | common->set_addr(addr + common->ytop_off, |
| 324 | 244 | addr + common->ybtm_off, |
| 325 | 245 | addr + common->ctop_off, |
| @@ -330,31 +250,42 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) · 4 unmodified lines | ||
| 330 | 250 | * VPIF register |
| 331 | 251 | */ |
| 332 | 252 | channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; |
| 333 | − if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { | |
| 253 | + if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { | |
| 334 | 254 | channel0_intr_assert(); |
| 335 | 255 | channel0_intr_enable(1); |
| 336 | 256 | enable_channel0(1); |
| 337 | 257 | } |
| 338 | − if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || | |
| 339 | − (common->started == 2)) { | |
| 258 | + if (VPIF_CHANNEL1_VIDEO == ch->channel_id || | |
| 259 | + ycmux_mode == 2) { | |
| 340 | 260 | channel1_intr_assert(); |
| 341 | 261 | channel1_intr_enable(1); |
| 342 | 262 | enable_channel1(1); |
| 343 | 263 | } |
| 344 | 264 | |
| 345 | 265 | return 0; |
| 266 | + | |
| 267 | +err: | |
| 268 | + list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { | |
| 269 | + list_del(&buf->list); | |
| 270 | + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | |
| 271 | + } | |
| 272 | + | |
| 273 | + return ret; | |
| 346 | 274 | } |
| 347 | 275 | |
| 348 | −/* abort streaming and wait for last buffer */ | |
| 349 | −static int vpif_stop_streaming(struct vb2_queue *vq) | |
| 276 | +/** | |
| 277 | + * vpif_stop_streaming : Stop the DMA engine | |
| 278 | + * @vq: ptr to vb2_queue | |
| 279 | + * | |
| 280 | + * This callback stops the DMA engine and any remaining buffers | |
| 281 | + * in the DMA queue are released. | |
| 282 | + */ | |
| 283 | +static void vpif_stop_streaming(struct vb2_queue *vq) | |
| 350 | 284 | { |
| 351 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 352 | − struct channel_obj *ch = fh->channel; | |
| 285 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 353 | 286 | struct common_obj *common; |
| 354 | 287 | unsigned long flags; |
| 355 | − | |
| 356 | − if (!vb2_is_streaming(vq)) | |
| 357 | − return 0; | |
| 288 | + int ret; | |
| 358 | 289 | |
| 359 | 290 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 360 | 291 | |
| @@ -363,12 +294,17 @@ static int vpif_stop_streaming(struct vb2_queue *vq) · 2 unmodified lines | ||
| 363 | 294 | enable_channel0(0); |
| 364 | 295 | channel0_intr_enable(0); |
| 365 | 296 | } |
| 366 | − if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || | |
| 367 | − (2 == common->started)) { | |
| 297 | + if (VPIF_CHANNEL1_VIDEO == ch->channel_id || | |
| 298 | + ycmux_mode == 2) { | |
| 368 | 299 | enable_channel1(0); |
| 369 | 300 | channel1_intr_enable(0); |
| 370 | 301 | } |
| 371 | − common->started = 0; | |
| 302 | + | |
| 303 | + ycmux_mode = 0; | |
| 304 | + | |
| 305 | + ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); | |
| 306 | + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) | |
| 307 | + vpif_dbg(1, debug, "stream off failed in subdev\n"); | |
| 372 | 308 | |
| 373 | 309 | /* release all active buffers */ |
| 374 | 310 | spin_lock_irqsave(&common->irqlock, flags); |
| @@ -390,19 +326,13 @@ static int vpif_stop_streaming(struct vb2_queue *vq) · 15 unmodified lines | ||
| 390 | 326 | vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); |
| 391 | 327 | } |
| 392 | 328 | spin_unlock_irqrestore(&common->irqlock, flags); |
| 393 | − | |
| 394 | − return 0; | |
| 395 | 329 | } |
| 396 | 330 | |
| 397 | 331 | static struct vb2_ops video_qops = { |
| 398 | 332 | .queue_setup = vpif_buffer_queue_setup, |
| 399 | − .wait_prepare = vpif_wait_prepare, | |
| 400 | − .wait_finish = vpif_wait_finish, | |
| 401 | − .buf_init = vpif_buffer_init, | |
| 402 | 333 | .buf_prepare = vpif_buffer_prepare, |
| 403 | 334 | .start_streaming = vpif_start_streaming, |
| 404 | 335 | .stop_streaming = vpif_stop_streaming, |
| 405 | − .buf_cleanup = vpif_buf_cleanup, | |
| 406 | 336 | .buf_queue = vpif_buffer_queue, |
| 407 | 337 | }; |
| 408 | 338 | |
| @@ -479,9 +409,6 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) · 70 unmodified lines | ||
| 479 | 409 | for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) { |
| 480 | 410 | common = &ch->common[i]; |
| 481 | 411 | /* skip If streaming is not started in this channel */ |
| 482 | − if (0 == common->started) | |
| 483 | − continue; | |
| 484 | − | |
| 485 | 412 | /* Check the field format */ |
| 486 | 413 | if (1 == ch->vpifparams.std_info.frm_fmt) { |
| 487 | 414 | /* Progressive mode */ |
| @@ -683,11 +610,6 @@ static void vpif_config_format(struct channel_obj *ch) · 195 unmodified lines | ||
| 683 | 610 | vpif_dbg(2, debug, "vpif_config_format\n"); |
| 684 | 611 | |
| 685 | 612 | common->fmt.fmt.pix.field = V4L2_FIELD_ANY; |
| 686 | − if (config_params.numbuffers[ch->channel_id] == 0) | |
| 687 | − common->memory = V4L2_MEMORY_USERPTR; | |
| 688 | − else | |
| 689 | − common->memory = V4L2_MEMORY_MMAP; | |
| 690 | − | |
| 691 | 613 | common->fmt.fmt.pix.sizeimage |
| 692 | 614 | = config_params.channel_bufsize[ch->channel_id]; |
| 693 | 615 | |
| @@ -836,415 +758,6 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode) · 142 unmodified lines | ||
| 836 | 758 | common->set_addr = ch0_set_videobuf_addr; |
| 837 | 759 | } |
| 838 | 760 | |
| 839 | −/** | |
| 840 | − * vpif_mmap : It is used to map kernel space buffers into user spaces | |
| 841 | − * @filep: file pointer | |
| 842 | − * @vma: ptr to vm_area_struct | |
| 843 | − */ | |
| 844 | −static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) | |
| 845 | −{ | |
| 846 | − /* Get the channel object and file handle object */ | |
| 847 | − struct vpif_fh *fh = filep->private_data; | |
| 848 | − struct channel_obj *ch = fh->channel; | |
| 849 | − struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); | |
| 850 | − int ret; | |
| 851 | − | |
| 852 | − vpif_dbg(2, debug, "vpif_mmap\n"); | |
| 853 | − | |
| 854 | − if (mutex_lock_interruptible(&common->lock)) | |
| 855 | − return -ERESTARTSYS; | |
| 856 | − ret = vb2_mmap(&common->buffer_queue, vma); | |
| 857 | − mutex_unlock(&common->lock); | |
| 858 | − return ret; | |
| 859 | −} | |
| 860 | − | |
| 861 | −/** | |
| 862 | − * vpif_poll: It is used for select/poll system call | |
| 863 | − * @filep: file pointer | |
| 864 | − * @wait: poll table to wait | |
| 865 | − */ | |
| 866 | −static unsigned int vpif_poll(struct file *filep, poll_table * wait) | |
| 867 | −{ | |
| 868 | − struct vpif_fh *fh = filep->private_data; | |
| 869 | − struct channel_obj *channel = fh->channel; | |
| 870 | − struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]); | |
| 871 | − unsigned int res = 0; | |
| 872 | − | |
| 873 | − vpif_dbg(2, debug, "vpif_poll\n"); | |
| 874 | − | |
| 875 | − if (common->started) { | |
| 876 | − mutex_lock(&common->lock); | |
| 877 | − res = vb2_poll(&common->buffer_queue, filep, wait); | |
| 878 | − mutex_unlock(&common->lock); | |
| 879 | − } | |
| 880 | − return res; | |
| 881 | −} | |
| 882 | − | |
| 883 | −/** | |
| 884 | − * vpif_open : vpif open handler | |
| 885 | − * @filep: file ptr | |
| 886 | − * | |
| 887 | − * It creates object of file handle structure and stores it in private_data | |
| 888 | − * member of filepointer | |
| 889 | − */ | |
| 890 | −static int vpif_open(struct file *filep) | |
| 891 | −{ | |
| 892 | − struct video_device *vdev = video_devdata(filep); | |
| 893 | − struct common_obj *common; | |
| 894 | − struct video_obj *vid_ch; | |
| 895 | − struct channel_obj *ch; | |
| 896 | − struct vpif_fh *fh; | |
| 897 | − | |
| 898 | − vpif_dbg(2, debug, "vpif_open\n"); | |
| 899 | − | |
| 900 | − ch = video_get_drvdata(vdev); | |
| 901 | − | |
| 902 | − vid_ch = &ch->video; | |
| 903 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 904 | − | |
| 905 | − /* Allocate memory for the file handle object */ | |
| 906 | − fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); | |
| 907 | − if (NULL == fh) { | |
| 908 | − vpif_err("unable to allocate memory for file handle object\n"); | |
| 909 | − return -ENOMEM; | |
| 910 | − } | |
| 911 | − | |
| 912 | − if (mutex_lock_interruptible(&common->lock)) { | |
| 913 | − kfree(fh); | |
| 914 | − return -ERESTARTSYS; | |
| 915 | − } | |
| 916 | − /* store pointer to fh in private_data member of filep */ | |
| 917 | − filep->private_data = fh; | |
| 918 | − fh->channel = ch; | |
| 919 | − fh->initialized = 0; | |
| 920 | − /* If decoder is not initialized. initialize it */ | |
| 921 | − if (!ch->initialized) { | |
| 922 | − fh->initialized = 1; | |
| 923 | − ch->initialized = 1; | |
| 924 | − memset(&(ch->vpifparams), 0, sizeof(struct vpif_params)); | |
| 925 | − } | |
| 926 | − /* Increment channel usrs counter */ | |
| 927 | − ch->usrs++; | |
| 928 | − /* Set io_allowed member to false */ | |
| 929 | − fh->io_allowed[VPIF_VIDEO_INDEX] = 0; | |
| 930 | − /* Initialize priority of this instance to default priority */ | |
| 931 | − fh->prio = V4L2_PRIORITY_UNSET; | |
| 932 | − v4l2_prio_open(&ch->prio, &fh->prio); | |
| 933 | − mutex_unlock(&common->lock); | |
| 934 | − return 0; | |
| 935 | −} | |
| 936 | − | |
| 937 | −/** | |
| 938 | − * vpif_release : function to clean up file close | |
| 939 | − * @filep: file pointer | |
| 940 | − * | |
| 941 | − * This function deletes buffer queue, frees the buffers and the vpif file | |
| 942 | − * handle | |
| 943 | − */ | |
| 944 | −static int vpif_release(struct file *filep) | |
| 945 | −{ | |
| 946 | − struct vpif_fh *fh = filep->private_data; | |
| 947 | − struct channel_obj *ch = fh->channel; | |
| 948 | − struct common_obj *common; | |
| 949 | − | |
| 950 | − vpif_dbg(2, debug, "vpif_release\n"); | |
| 951 | − | |
| 952 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 953 | − | |
| 954 | − mutex_lock(&common->lock); | |
| 955 | − /* if this instance is doing IO */ | |
| 956 | − if (fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 957 | − /* Reset io_usrs member of channel object */ | |
| 958 | − common->io_usrs = 0; | |
| 959 | − /* Free buffers allocated */ | |
| 960 | − vb2_queue_release(&common->buffer_queue); | |
| 961 | − vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 962 | − } | |
| 963 | − | |
| 964 | − /* Decrement channel usrs counter */ | |
| 965 | − ch->usrs--; | |
| 966 | − | |
| 967 | − /* Close the priority */ | |
| 968 | − v4l2_prio_close(&ch->prio, fh->prio); | |
| 969 | − | |
| 970 | − if (fh->initialized) | |
| 971 | − ch->initialized = 0; | |
| 972 | − | |
| 973 | − mutex_unlock(&common->lock); | |
| 974 | − filep->private_data = NULL; | |
| 975 | − kfree(fh); | |
| 976 | − return 0; | |
| 977 | −} | |
| 978 | − | |
| 979 | −/** | |
| 980 | − * vpif_reqbufs() - request buffer handler | |
| 981 | − * @file: file ptr | |
| 982 | − * @priv: file handle | |
| 983 | − * @reqbuf: request buffer structure ptr | |
| 984 | − */ | |
| 985 | −static int vpif_reqbufs(struct file *file, void *priv, | |
| 986 | − struct v4l2_requestbuffers *reqbuf) | |
| 987 | −{ | |
| 988 | − struct vpif_fh *fh = priv; | |
| 989 | − struct channel_obj *ch = fh->channel; | |
| 990 | − struct common_obj *common; | |
| 991 | − u8 index = 0; | |
| 992 | − struct vb2_queue *q; | |
| 993 | − int ret; | |
| 994 | − | |
| 995 | − vpif_dbg(2, debug, "vpif_reqbufs\n"); | |
| 996 | − | |
| 997 | − /** | |
| 998 | − * This file handle has not initialized the channel, | |
| 999 | − * It is not allowed to do settings | |
| 1000 | − */ | |
| 1001 | − if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) | |
| 1002 | − || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { | |
| 1003 | − if (!fh->initialized) { | |
| 1004 | − vpif_dbg(1, debug, "Channel Busy\n"); | |
| 1005 | − return -EBUSY; | |
| 1006 | − } | |
| 1007 | − } | |
| 1008 | − | |
| 1009 | − if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type || !vpif_dev) | |
| 1010 | − return -EINVAL; | |
| 1011 | − | |
| 1012 | − index = VPIF_VIDEO_INDEX; | |
| 1013 | − | |
| 1014 | − common = &ch->common[index]; | |
| 1015 | − | |
| 1016 | − if (0 != common->io_usrs) | |
| 1017 | − return -EBUSY; | |
| 1018 | − | |
| 1019 | − /* Initialize videobuf2 queue as per the buffer type */ | |
| 1020 | − common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); | |
| 1021 | − if (IS_ERR(common->alloc_ctx)) { | |
| 1022 | − vpif_err("Failed to get the context\n"); | |
| 1023 | − return PTR_ERR(common->alloc_ctx); | |
| 1024 | − } | |
| 1025 | − q = &common->buffer_queue; | |
| 1026 | − q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 1027 | − q->io_modes = VB2_MMAP | VB2_USERPTR; | |
| 1028 | − q->drv_priv = fh; | |
| 1029 | − q->ops = &video_qops; | |
| 1030 | − q->mem_ops = &vb2_dma_contig_memops; | |
| 1031 | − q->buf_struct_size = sizeof(struct vpif_cap_buffer); | |
| 1032 | − q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 1033 | − q->min_buffers_needed = 1; | |
| 1034 | − | |
| 1035 | − ret = vb2_queue_init(q); | |
| 1036 | − if (ret) { | |
| 1037 | − vpif_err("vpif_capture: vb2_queue_init() failed\n"); | |
| 1038 | − vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 1039 | − return ret; | |
| 1040 | − } | |
| 1041 | − /* Set io allowed member of file handle to TRUE */ | |
| 1042 | − fh->io_allowed[index] = 1; | |
| 1043 | − /* Increment io usrs member of channel object to 1 */ | |
| 1044 | − common->io_usrs = 1; | |
| 1045 | − /* Store type of memory requested in channel object */ | |
| 1046 | − common->memory = reqbuf->memory; | |
| 1047 | − INIT_LIST_HEAD(&common->dma_queue); | |
| 1048 | − | |
| 1049 | − /* Allocate buffers */ | |
| 1050 | − return vb2_reqbufs(&common->buffer_queue, reqbuf); | |
| 1051 | −} | |
| 1052 | − | |
| 1053 | −/** | |
| 1054 | − * vpif_querybuf() - query buffer handler | |
| 1055 | − * @file: file ptr | |
| 1056 | − * @priv: file handle | |
| 1057 | − * @buf: v4l2 buffer structure ptr | |
| 1058 | − */ | |
| 1059 | −static int vpif_querybuf(struct file *file, void *priv, | |
| 1060 | − struct v4l2_buffer *buf) | |
| 1061 | −{ | |
| 1062 | − struct vpif_fh *fh = priv; | |
| 1063 | − struct channel_obj *ch = fh->channel; | |
| 1064 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1065 | − | |
| 1066 | − vpif_dbg(2, debug, "vpif_querybuf\n"); | |
| 1067 | − | |
| 1068 | − if (common->fmt.type != buf->type) | |
| 1069 | − return -EINVAL; | |
| 1070 | − | |
| 1071 | − if (common->memory != V4L2_MEMORY_MMAP) { | |
| 1072 | − vpif_dbg(1, debug, "Invalid memory\n"); | |
| 1073 | − return -EINVAL; | |
| 1074 | − } | |
| 1075 | − | |
| 1076 | − return vb2_querybuf(&common->buffer_queue, buf); | |
| 1077 | −} | |
| 1078 | − | |
| 1079 | −/** | |
| 1080 | − * vpif_qbuf() - query buffer handler | |
| 1081 | − * @file: file ptr | |
| 1082 | − * @priv: file handle | |
| 1083 | − * @buf: v4l2 buffer structure ptr | |
| 1084 | − */ | |
| 1085 | −static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
| 1086 | −{ | |
| 1087 | − | |
| 1088 | − struct vpif_fh *fh = priv; | |
| 1089 | − struct channel_obj *ch = fh->channel; | |
| 1090 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1091 | − struct v4l2_buffer tbuf = *buf; | |
| 1092 | − | |
| 1093 | − vpif_dbg(2, debug, "vpif_qbuf\n"); | |
| 1094 | − | |
| 1095 | − if (common->fmt.type != tbuf.type) { | |
| 1096 | − vpif_err("invalid buffer type\n"); | |
| 1097 | − return -EINVAL; | |
| 1098 | − } | |
| 1099 | − | |
| 1100 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1101 | − vpif_err("fh io not allowed\n"); | |
| 1102 | − return -EACCES; | |
| 1103 | − } | |
| 1104 | − | |
| 1105 | − return vb2_qbuf(&common->buffer_queue, buf); | |
| 1106 | −} | |
| 1107 | − | |
| 1108 | −/** | |
| 1109 | − * vpif_dqbuf() - query buffer handler | |
| 1110 | − * @file: file ptr | |
| 1111 | − * @priv: file handle | |
| 1112 | − * @buf: v4l2 buffer structure ptr | |
| 1113 | − */ | |
| 1114 | −static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
| 1115 | −{ | |
| 1116 | − struct vpif_fh *fh = priv; | |
| 1117 | − struct channel_obj *ch = fh->channel; | |
| 1118 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1119 | − | |
| 1120 | − vpif_dbg(2, debug, "vpif_dqbuf\n"); | |
| 1121 | − | |
| 1122 | − return vb2_dqbuf(&common->buffer_queue, buf, | |
| 1123 | − (file->f_flags & O_NONBLOCK)); | |
| 1124 | −} | |
| 1125 | − | |
| 1126 | −/** | |
| 1127 | − * vpif_streamon() - streamon handler | |
| 1128 | − * @file: file ptr | |
| 1129 | − * @priv: file handle | |
| 1130 | − * @buftype: v4l2 buffer type | |
| 1131 | − */ | |
| 1132 | −static int vpif_streamon(struct file *file, void *priv, | |
| 1133 | − enum v4l2_buf_type buftype) | |
| 1134 | −{ | |
| 1135 | − | |
| 1136 | − struct vpif_fh *fh = priv; | |
| 1137 | − struct channel_obj *ch = fh->channel; | |
| 1138 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1139 | − struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; | |
| 1140 | − struct vpif_params *vpif; | |
| 1141 | − int ret = 0; | |
| 1142 | − | |
| 1143 | − vpif_dbg(2, debug, "vpif_streamon\n"); | |
| 1144 | − | |
| 1145 | − vpif = &ch->vpifparams; | |
| 1146 | − | |
| 1147 | − if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | |
| 1148 | − vpif_dbg(1, debug, "buffer type not supported\n"); | |
| 1149 | − return -EINVAL; | |
| 1150 | − } | |
| 1151 | − | |
| 1152 | − /* If file handle is not allowed IO, return error */ | |
| 1153 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1154 | − vpif_dbg(1, debug, "io not allowed\n"); | |
| 1155 | − return -EACCES; | |
| 1156 | − } | |
| 1157 | − | |
| 1158 | − /* If Streaming is already started, return error */ | |
| 1159 | − if (common->started) { | |
| 1160 | − vpif_dbg(1, debug, "channel->started\n"); | |
| 1161 | − return -EBUSY; | |
| 1162 | − } | |
| 1163 | − | |
| 1164 | − if ((ch->channel_id == VPIF_CHANNEL0_VIDEO && | |
| 1165 | − oth_ch->common[VPIF_VIDEO_INDEX].started && | |
| 1166 | − vpif->std_info.ycmux_mode == 0) || | |
| 1167 | − ((ch->channel_id == VPIF_CHANNEL1_VIDEO) && | |
| 1168 | − (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) { | |
| 1169 | − vpif_dbg(1, debug, "other channel is being used\n"); | |
| 1170 | − return -EBUSY; | |
| 1171 | − } | |
| 1172 | − | |
| 1173 | − ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0); | |
| 1174 | − if (ret) | |
| 1175 | − return ret; | |
| 1176 | − | |
| 1177 | − /* Enable streamon on the sub device */ | |
| 1178 | − ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); | |
| 1179 | − | |
| 1180 | − if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { | |
| 1181 | − vpif_dbg(1, debug, "stream on failed in subdev\n"); | |
| 1182 | − return ret; | |
| 1183 | − } | |
| 1184 | − | |
| 1185 | − /* Call vb2_streamon to start streaming in videobuf2 */ | |
| 1186 | − ret = vb2_streamon(&common->buffer_queue, buftype); | |
| 1187 | − if (ret) { | |
| 1188 | − vpif_dbg(1, debug, "vb2_streamon\n"); | |
| 1189 | − return ret; | |
| 1190 | − } | |
| 1191 | − | |
| 1192 | − return ret; | |
| 1193 | −} | |
| 1194 | − | |
| 1195 | −/** | |
| 1196 | − * vpif_streamoff() - streamoff handler | |
| 1197 | − * @file: file ptr | |
| 1198 | − * @priv: file handle | |
| 1199 | − * @buftype: v4l2 buffer type | |
| 1200 | − */ | |
| 1201 | −static int vpif_streamoff(struct file *file, void *priv, | |
| 1202 | − enum v4l2_buf_type buftype) | |
| 1203 | −{ | |
| 1204 | − | |
| 1205 | − struct vpif_fh *fh = priv; | |
| 1206 | − struct channel_obj *ch = fh->channel; | |
| 1207 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1208 | − int ret; | |
| 1209 | − | |
| 1210 | − vpif_dbg(2, debug, "vpif_streamoff\n"); | |
| 1211 | − | |
| 1212 | − if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | |
| 1213 | − vpif_dbg(1, debug, "buffer type not supported\n"); | |
| 1214 | − return -EINVAL; | |
| 1215 | − } | |
| 1216 | − | |
| 1217 | − /* If io is allowed for this file handle, return error */ | |
| 1218 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1219 | − vpif_dbg(1, debug, "io not allowed\n"); | |
| 1220 | − return -EACCES; | |
| 1221 | − } | |
| 1222 | − | |
| 1223 | − /* If streaming is not started, return error */ | |
| 1224 | − if (!common->started) { | |
| 1225 | − vpif_dbg(1, debug, "channel->started\n"); | |
| 1226 | − return -EINVAL; | |
| 1227 | − } | |
| 1228 | − | |
| 1229 | − /* disable channel */ | |
| 1230 | − if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { | |
| 1231 | − enable_channel0(0); | |
| 1232 | − channel0_intr_enable(0); | |
| 1233 | − } else { | |
| 1234 | − enable_channel1(0); | |
| 1235 | − channel1_intr_enable(0); | |
| 1236 | − } | |
| 1237 | − | |
| 1238 | − common->started = 0; | |
| 1239 | − | |
| 1240 | − ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); | |
| 1241 | − | |
| 1242 | − if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) | |
| 1243 | − vpif_dbg(1, debug, "stream off failed in subdev\n"); | |
| 1244 | − | |
| 1245 | − return vb2_streamoff(&common->buffer_queue, buftype); | |
| 1246 | −} | |
| 1247 | − | |
| 1248 | 761 | /** |
| 1249 | 762 | * vpif_input_to_subdev() - Maps input to sub device |
| 1250 | 763 | * @vpif_cfg - global config ptr |
| @@ -1348,8 +861,8 @@ static int vpif_set_input( · 97 unmodified lines | ||
| 1348 | 861 | */ |
| 1349 | 862 | static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) |
| 1350 | 863 | { |
| 1351 | − struct vpif_fh *fh = priv; | |
| 1352 | − struct channel_obj *ch = fh->channel; | |
| 864 | + struct video_device *vdev = video_devdata(file); | |
| 865 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1353 | 866 | int ret = 0; |
| 1354 | 867 | |
| 1355 | 868 | vpif_dbg(2, debug, "vpif_querystd\n"); |
| @@ -1375,11 +888,22 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) · 19 unmodified lines | ||
| 1375 | 888 | */ |
| 1376 | 889 | static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) |
| 1377 | 890 | { |
| 1378 | − struct vpif_fh *fh = priv; | |
| 1379 | − struct channel_obj *ch = fh->channel; | |
| 891 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 892 | + struct video_device *vdev = video_devdata(file); | |
| 893 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 894 | + struct vpif_capture_chan_config *chan_cfg; | |
| 895 | + struct v4l2_input input; | |
| 1380 | 896 | |
| 1381 | 897 | vpif_dbg(2, debug, "vpif_g_std\n"); |
| 1382 | 898 | |
| 899 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 900 | + return -ENODATA; | |
| 901 | + | |
| 902 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 903 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 904 | + if (input.capabilities != V4L2_IN_CAP_STD) | |
| 905 | + return -ENODATA; | |
| 906 | + | |
| 1383 | 907 | *std = ch->video.stdid; |
| 1384 | 908 | return 0; |
| 1385 | 909 | } |
| @@ -1392,31 +916,26 @@ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) · 6 unmodified lines | ||
| 1392 | 916 | */ |
| 1393 | 917 | static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) |
| 1394 | 918 | { |
| 1395 | − struct vpif_fh *fh = priv; | |
| 1396 | − struct channel_obj *ch = fh->channel; | |
| 919 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 920 | + struct video_device *vdev = video_devdata(file); | |
| 921 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1397 | 922 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1398 | − int ret = 0; | |
| 923 | + struct vpif_capture_chan_config *chan_cfg; | |
| 924 | + struct v4l2_input input; | |
| 925 | + int ret; | |
| 1399 | 926 | |
| 1400 | 927 | vpif_dbg(2, debug, "vpif_s_std\n"); |
| 1401 | 928 | |
| 1402 | − if (common->started) { | |
| 1403 | − vpif_err("streaming in progress\n"); | |
| 1404 | − return -EBUSY; | |
| 1405 | − } | |
| 1406 | − | |
| 1407 | − if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || | |
| 1408 | − (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { | |
| 1409 | − if (!fh->initialized) { | |
| 1410 | − vpif_dbg(1, debug, "Channel Busy\n"); | |
| 1411 | − return -EBUSY; | |
| 1412 | − } | |
| 1413 | − } | |
| 929 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 930 | + return -ENODATA; | |
| 1414 | 931 | |
| 1415 | − ret = v4l2_prio_check(&ch->prio, fh->prio); | |
| 1416 | − if (0 != ret) | |
| 1417 | − return ret; | |
| 932 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 933 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 934 | + if (input.capabilities != V4L2_IN_CAP_STD) | |
| 935 | + return -ENODATA; | |
| 1418 | 936 | |
| 1419 | − fh->initialized = 1; | |
| 937 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 938 | + return -EBUSY; | |
| 1420 | 939 | |
| 1421 | 940 | /* Call encoder subdevice function to set the standard */ |
| 1422 | 941 | ch->video.stdid = std_id; |
| @@ -1432,7 +951,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) · 9 unmodified lines | ||
| 1432 | 951 | vpif_config_format(ch); |
| 1433 | 952 | |
| 1434 | 953 | /* set standard in the sub device */ |
| 1435 | − ret = v4l2_subdev_call(ch->sd, core, s_std, std_id); | |
| 954 | + ret = v4l2_subdev_call(ch->sd, video, s_std, std_id); | |
| 1436 | 955 | if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { |
| 1437 | 956 | vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); |
| 1438 | 957 | return ret; |
| @@ -1451,9 +970,9 @@ static int vpif_enum_input(struct file *file, void *priv, · 12 unmodified lines | ||
| 1451 | 970 | { |
| 1452 | 971 | |
| 1453 | 972 | struct vpif_capture_config *config = vpif_dev->platform_data; |
| 973 | + struct video_device *vdev = video_devdata(file); | |
| 974 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1454 | 975 | struct vpif_capture_chan_config *chan_cfg; |
| 1455 | − struct vpif_fh *fh = priv; | |
| 1456 | − struct channel_obj *ch = fh->channel; | |
| 1457 | 976 | |
| 1458 | 977 | chan_cfg = &config->chan_config[ch->channel_id]; |
| 1459 | 978 | |
| @@ -1475,8 +994,8 @@ static int vpif_enum_input(struct file *file, void *priv, · 15 unmodified lines | ||
| 1475 | 994 | */ |
| 1476 | 995 | static int vpif_g_input(struct file *file, void *priv, unsigned int *index) |
| 1477 | 996 | { |
| 1478 | − struct vpif_fh *fh = priv; | |
| 1479 | − struct channel_obj *ch = fh->channel; | |
| 997 | + struct video_device *vdev = video_devdata(file); | |
| 998 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1480 | 999 | |
| 1481 | 1000 | *index = ch->input_idx; |
| 1482 | 1001 | return 0; |
| @@ -1491,35 +1010,19 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index) · 8 unmodified lines | ||
| 1491 | 1010 | static int vpif_s_input(struct file *file, void *priv, unsigned int index) |
| 1492 | 1011 | { |
| 1493 | 1012 | struct vpif_capture_config *config = vpif_dev->platform_data; |
| 1494 | − struct vpif_capture_chan_config *chan_cfg; | |
| 1495 | − struct vpif_fh *fh = priv; | |
| 1496 | − struct channel_obj *ch = fh->channel; | |
| 1013 | + struct video_device *vdev = video_devdata(file); | |
| 1014 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1497 | 1015 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1498 | − int ret; | |
| 1016 | + struct vpif_capture_chan_config *chan_cfg; | |
| 1499 | 1017 | |
| 1500 | 1018 | chan_cfg = &config->chan_config[ch->channel_id]; |
| 1501 | 1019 | |
| 1502 | 1020 | if (index >= chan_cfg->input_count) |
| 1503 | 1021 | return -EINVAL; |
| 1504 | 1022 | |
| 1505 | − if (common->started) { | |
| 1506 | − vpif_err("Streaming in progress\n"); | |
| 1023 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 1507 | 1024 | return -EBUSY; |
| 1508 | − } | |
| 1509 | − | |
| 1510 | − if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || | |
| 1511 | − (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { | |
| 1512 | − if (!fh->initialized) { | |
| 1513 | − vpif_dbg(1, debug, "Channel Busy\n"); | |
| 1514 | − return -EBUSY; | |
| 1515 | − } | |
| 1516 | − } | |
| 1517 | − | |
| 1518 | − ret = v4l2_prio_check(&ch->prio, fh->prio); | |
| 1519 | − if (0 != ret) | |
| 1520 | − return ret; | |
| 1521 | 1025 | |
| 1522 | − fh->initialized = 1; | |
| 1523 | 1026 | return vpif_set_input(config, ch, index); |
| 1524 | 1027 | } |
| 1525 | 1028 | |
| @@ -1532,8 +1035,8 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) · 6 unmodified lines | ||
| 1532 | 1035 | static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, |
| 1533 | 1036 | struct v4l2_fmtdesc *fmt) |
| 1534 | 1037 | { |
| 1535 | − struct vpif_fh *fh = priv; | |
| 1536 | − struct channel_obj *ch = fh->channel; | |
| 1038 | + struct video_device *vdev = video_devdata(file); | |
| 1039 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1537 | 1040 | |
| 1538 | 1041 | if (fmt->index != 0) { |
| 1539 | 1042 | vpif_dbg(1, debug, "Invalid format index\n"); |
| @@ -1562,8 +1065,8 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, · 22 unmodified lines | ||
| 1562 | 1065 | static int vpif_try_fmt_vid_cap(struct file *file, void *priv, |
| 1563 | 1066 | struct v4l2_format *fmt) |
| 1564 | 1067 | { |
| 1565 | − struct vpif_fh *fh = priv; | |
| 1566 | − struct channel_obj *ch = fh->channel; | |
| 1068 | + struct video_device *vdev = video_devdata(file); | |
| 1069 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1567 | 1070 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
| 1568 | 1071 | |
| 1569 | 1072 | return vpif_check_format(ch, pixfmt, 1); |
| @@ -1579,8 +1082,8 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv, · 9 unmodified lines | ||
| 1579 | 1082 | static int vpif_g_fmt_vid_cap(struct file *file, void *priv, |
| 1580 | 1083 | struct v4l2_format *fmt) |
| 1581 | 1084 | { |
| 1582 | − struct vpif_fh *fh = priv; | |
| 1583 | − struct channel_obj *ch = fh->channel; | |
| 1085 | + struct video_device *vdev = video_devdata(file); | |
| 1086 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1584 | 1087 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1585 | 1088 | |
| 1586 | 1089 | /* Check the validity of the buffer type */ |
| @@ -1601,33 +1104,16 @@ static int vpif_g_fmt_vid_cap(struct file *file, void *priv, · 14 unmodified lines | ||
| 1601 | 1104 | static int vpif_s_fmt_vid_cap(struct file *file, void *priv, |
| 1602 | 1105 | struct v4l2_format *fmt) |
| 1603 | 1106 | { |
| 1604 | − struct vpif_fh *fh = priv; | |
| 1605 | − struct channel_obj *ch = fh->channel; | |
| 1107 | + struct video_device *vdev = video_devdata(file); | |
| 1108 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1606 | 1109 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1607 | 1110 | struct v4l2_pix_format *pixfmt; |
| 1608 | 1111 | int ret = 0; |
| 1609 | 1112 | |
| 1610 | 1113 | vpif_dbg(2, debug, "%s\n", __func__); |
| 1611 | 1114 | |
| 1612 | − /* If streaming is started, return error */ | |
| 1613 | − if (common->started) { | |
| 1614 | − vpif_dbg(1, debug, "Streaming is started\n"); | |
| 1115 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 1615 | 1116 | return -EBUSY; |
| 1616 | − } | |
| 1617 | − | |
| 1618 | − if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || | |
| 1619 | − (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { | |
| 1620 | − if (!fh->initialized) { | |
| 1621 | − vpif_dbg(1, debug, "Channel Busy\n"); | |
| 1622 | − return -EBUSY; | |
| 1623 | − } | |
| 1624 | − } | |
| 1625 | − | |
| 1626 | − ret = v4l2_prio_check(&ch->prio, fh->prio); | |
| 1627 | − if (0 != ret) | |
| 1628 | − return ret; | |
| 1629 | − | |
| 1630 | − fh->initialized = 1; | |
| 1631 | 1117 | |
| 1632 | 1118 | pixfmt = &fmt->fmt.pix; |
| 1633 | 1119 | /* Check for valid field format */ |
| @@ -1653,7 +1139,7 @@ static int vpif_querycap(struct file *file, void *priv, · 19 unmodified lines | ||
| 1653 | 1139 | |
| 1654 | 1140 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
| 1655 | 1141 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
| 1656 | − snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); | |
| 1142 | + strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); | |
| 1657 | 1143 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
| 1658 | 1144 | dev_name(vpif_dev)); |
| 1659 | 1145 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); |
| @@ -1661,61 +1147,6 @@ static int vpif_querycap(struct file *file, void *priv, · 1 unmodified line | ||
| 1661 | 1147 | return 0; |
| 1662 | 1148 | } |
| 1663 | 1149 | |
| 1664 | −/** | |
| 1665 | − * vpif_g_priority() - get priority handler | |
| 1666 | − * @file: file ptr | |
| 1667 | − * @priv: file handle | |
| 1668 | − * @prio: ptr to v4l2_priority structure | |
| 1669 | − */ | |
| 1670 | −static int vpif_g_priority(struct file *file, void *priv, | |
| 1671 | − enum v4l2_priority *prio) | |
| 1672 | −{ | |
| 1673 | − struct vpif_fh *fh = priv; | |
| 1674 | − struct channel_obj *ch = fh->channel; | |
| 1675 | − | |
| 1676 | − *prio = v4l2_prio_max(&ch->prio); | |
| 1677 | − | |
| 1678 | − return 0; | |
| 1679 | −} | |
| 1680 | − | |
| 1681 | −/** | |
| 1682 | − * vpif_s_priority() - set priority handler | |
| 1683 | − * @file: file ptr | |
| 1684 | − * @priv: file handle | |
| 1685 | − * @prio: ptr to v4l2_priority structure | |
| 1686 | − */ | |
| 1687 | −static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) | |
| 1688 | −{ | |
| 1689 | − struct vpif_fh *fh = priv; | |
| 1690 | − struct channel_obj *ch = fh->channel; | |
| 1691 | − | |
| 1692 | − return v4l2_prio_change(&ch->prio, &fh->prio, p); | |
| 1693 | −} | |
| 1694 | − | |
| 1695 | −/** | |
| 1696 | − * vpif_cropcap() - cropcap handler | |
| 1697 | − * @file: file ptr | |
| 1698 | − * @priv: file handle | |
| 1699 | − * @crop: ptr to v4l2_cropcap structure | |
| 1700 | − */ | |
| 1701 | −static int vpif_cropcap(struct file *file, void *priv, | |
| 1702 | − struct v4l2_cropcap *crop) | |
| 1703 | −{ | |
| 1704 | − struct vpif_fh *fh = priv; | |
| 1705 | − struct channel_obj *ch = fh->channel; | |
| 1706 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1707 | − | |
| 1708 | − if (V4L2_BUF_TYPE_VIDEO_CAPTURE != crop->type) | |
| 1709 | − return -EINVAL; | |
| 1710 | − | |
| 1711 | − crop->bounds.left = 0; | |
| 1712 | − crop->bounds.top = 0; | |
| 1713 | − crop->bounds.height = common->height; | |
| 1714 | − crop->bounds.width = common->width; | |
| 1715 | − crop->defrect = crop->bounds; | |
| 1716 | − return 0; | |
| 1717 | −} | |
| 1718 | − | |
| 1719 | 1150 | /** |
| 1720 | 1151 | * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler |
| 1721 | 1152 | * @file: file ptr |
| @@ -1726,13 +1157,27 @@ static int · 4 unmodified lines | ||
| 1726 | 1157 | vpif_enum_dv_timings(struct file *file, void *priv, |
| 1727 | 1158 | struct v4l2_enum_dv_timings *timings) |
| 1728 | 1159 | { |
| 1729 | − struct vpif_fh *fh = priv; | |
| 1730 | − struct channel_obj *ch = fh->channel; | |
| 1160 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 1161 | + struct video_device *vdev = video_devdata(file); | |
| 1162 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1163 | + struct vpif_capture_chan_config *chan_cfg; | |
| 1164 | + struct v4l2_input input; | |
| 1731 | 1165 | int ret; |
| 1732 | 1166 | |
| 1733 | − ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); | |
| 1167 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 1168 | + return -ENODATA; | |
| 1169 | + | |
| 1170 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 1171 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 1172 | + if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) | |
| 1173 | + return -ENODATA; | |
| 1174 | + | |
| 1175 | + timings->pad = 0; | |
| 1176 | + | |
| 1177 | + ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings); | |
| 1734 | 1178 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
| 1735 | 1179 | return -EINVAL; |
| 1180 | + | |
| 1736 | 1181 | return ret; |
| 1737 | 1182 | } |
| 1738 | 1183 | |
| @@ -1746,13 +1191,25 @@ static int · 7 unmodified lines | ||
| 1746 | 1191 | vpif_query_dv_timings(struct file *file, void *priv, |
| 1747 | 1192 | struct v4l2_dv_timings *timings) |
| 1748 | 1193 | { |
| 1749 | − struct vpif_fh *fh = priv; | |
| 1750 | − struct channel_obj *ch = fh->channel; | |
| 1194 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 1195 | + struct video_device *vdev = video_devdata(file); | |
| 1196 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1197 | + struct vpif_capture_chan_config *chan_cfg; | |
| 1198 | + struct v4l2_input input; | |
| 1751 | 1199 | int ret; |
| 1752 | 1200 | |
| 1201 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 1202 | + return -ENODATA; | |
| 1203 | + | |
| 1204 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 1205 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 1206 | + if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) | |
| 1207 | + return -ENODATA; | |
| 1208 | + | |
| 1753 | 1209 | ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings); |
| 1754 | 1210 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
| 1755 | 1211 | return -ENODATA; |
| 1212 | + | |
| 1756 | 1213 | return ret; |
| 1757 | 1214 | } |
| 1758 | 1215 | |
| @@ -1765,19 +1222,34 @@ vpif_query_dv_timings(struct file *file, void *priv, · 6 unmodified lines | ||
| 1765 | 1222 | static int vpif_s_dv_timings(struct file *file, void *priv, |
| 1766 | 1223 | struct v4l2_dv_timings *timings) |
| 1767 | 1224 | { |
| 1768 | − struct vpif_fh *fh = priv; | |
| 1769 | − struct channel_obj *ch = fh->channel; | |
| 1225 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 1226 | + struct video_device *vdev = video_devdata(file); | |
| 1227 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1770 | 1228 | struct vpif_params *vpifparams = &ch->vpifparams; |
| 1771 | 1229 | struct vpif_channel_config_params *std_info = &vpifparams->std_info; |
| 1230 | + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1772 | 1231 | struct video_obj *vid_ch = &ch->video; |
| 1773 | 1232 | struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; |
| 1233 | + struct vpif_capture_chan_config *chan_cfg; | |
| 1234 | + struct v4l2_input input; | |
| 1774 | 1235 | int ret; |
| 1775 | 1236 | |
| 1237 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 1238 | + return -ENODATA; | |
| 1239 | + | |
| 1240 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 1241 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 1242 | + if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) | |
| 1243 | + return -ENODATA; | |
| 1244 | + | |
| 1776 | 1245 | if (timings->type != V4L2_DV_BT_656_1120) { |
| 1777 | 1246 | vpif_dbg(2, debug, "Timing type not defined\n"); |
| 1778 | 1247 | return -EINVAL; |
| 1779 | 1248 | } |
| 1780 | 1249 | |
| 1250 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 1251 | + return -EBUSY; | |
| 1252 | + | |
| 1781 | 1253 | /* Configure subdevice timings, if any */ |
| 1782 | 1254 | ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); |
| 1783 | 1255 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
| @@ -1853,9 +1325,20 @@ static int vpif_s_dv_timings(struct file *file, void *priv, · 69 unmodified lines | ||
| 1853 | 1325 | static int vpif_g_dv_timings(struct file *file, void *priv, |
| 1854 | 1326 | struct v4l2_dv_timings *timings) |
| 1855 | 1327 | { |
| 1856 | − struct vpif_fh *fh = priv; | |
| 1857 | − struct channel_obj *ch = fh->channel; | |
| 1328 | + struct vpif_capture_config *config = vpif_dev->platform_data; | |
| 1329 | + struct video_device *vdev = video_devdata(file); | |
| 1330 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1858 | 1331 | struct video_obj *vid_ch = &ch->video; |
| 1332 | + struct vpif_capture_chan_config *chan_cfg; | |
| 1333 | + struct v4l2_input input; | |
| 1334 | + | |
| 1335 | + if (config->chan_config[ch->channel_id].inputs == NULL) | |
| 1336 | + return -ENODATA; | |
| 1337 | + | |
| 1338 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 1339 | + input = chan_cfg->inputs[ch->input_idx].input; | |
| 1340 | + if (input.capabilities != V4L2_IN_CAP_DV_TIMINGS) | |
| 1341 | + return -ENODATA; | |
| 1859 | 1342 | |
| 1860 | 1343 | *timings = vid_ch->dv_timings; |
| 1861 | 1344 | |
| @@ -1879,49 +1362,45 @@ static int vpif_log_status(struct file *filep, void *priv) · 17 unmodified lines | ||
| 1879 | 1362 | |
| 1880 | 1363 | /* vpif capture ioctl operations */ |
| 1881 | 1364 | static const struct v4l2_ioctl_ops vpif_ioctl_ops = { |
| 1882 | − .vidioc_querycap = vpif_querycap, | |
| 1883 | − .vidioc_g_priority = vpif_g_priority, | |
| 1884 | − .vidioc_s_priority = vpif_s_priority, | |
| 1365 | + .vidioc_querycap = vpif_querycap, | |
| 1885 | 1366 | .vidioc_enum_fmt_vid_cap = vpif_enum_fmt_vid_cap, |
| 1886 | − .vidioc_g_fmt_vid_cap = vpif_g_fmt_vid_cap, | |
| 1367 | + .vidioc_g_fmt_vid_cap = vpif_g_fmt_vid_cap, | |
| 1887 | 1368 | .vidioc_s_fmt_vid_cap = vpif_s_fmt_vid_cap, |
| 1888 | 1369 | .vidioc_try_fmt_vid_cap = vpif_try_fmt_vid_cap, |
| 1370 | + | |
| 1889 | 1371 | .vidioc_enum_input = vpif_enum_input, |
| 1890 | 1372 | .vidioc_s_input = vpif_s_input, |
| 1891 | 1373 | .vidioc_g_input = vpif_g_input, |
| 1892 | − .vidioc_reqbufs = vpif_reqbufs, | |
| 1893 | − .vidioc_querybuf = vpif_querybuf, | |
| 1374 | + | |
| 1375 | + .vidioc_reqbufs = vb2_ioctl_reqbufs, | |
| 1376 | + .vidioc_create_bufs = vb2_ioctl_create_bufs, | |
| 1377 | + .vidioc_querybuf = vb2_ioctl_querybuf, | |
| 1378 | + .vidioc_qbuf = vb2_ioctl_qbuf, | |
| 1379 | + .vidioc_dqbuf = vb2_ioctl_dqbuf, | |
| 1380 | + .vidioc_expbuf = vb2_ioctl_expbuf, | |
| 1381 | + .vidioc_streamon = vb2_ioctl_streamon, | |
| 1382 | + .vidioc_streamoff = vb2_ioctl_streamoff, | |
| 1383 | + | |
| 1894 | 1384 | .vidioc_querystd = vpif_querystd, |
| 1895 | − .vidioc_s_std = vpif_s_std, | |
| 1385 | + .vidioc_s_std = vpif_s_std, | |
| 1896 | 1386 | .vidioc_g_std = vpif_g_std, |
| 1897 | − .vidioc_qbuf = vpif_qbuf, | |
| 1898 | − .vidioc_dqbuf = vpif_dqbuf, | |
| 1899 | − .vidioc_streamon = vpif_streamon, | |
| 1900 | − .vidioc_streamoff = vpif_streamoff, | |
| 1901 | − .vidioc_cropcap = vpif_cropcap, | |
| 1902 | − .vidioc_enum_dv_timings = vpif_enum_dv_timings, | |
| 1903 | − .vidioc_query_dv_timings = vpif_query_dv_timings, | |
| 1904 | − .vidioc_s_dv_timings = vpif_s_dv_timings, | |
| 1905 | − .vidioc_g_dv_timings = vpif_g_dv_timings, | |
| 1387 | + | |
| 1388 | + .vidioc_enum_dv_timings = vpif_enum_dv_timings, | |
| 1389 | + .vidioc_query_dv_timings = vpif_query_dv_timings, | |
| 1390 | + .vidioc_s_dv_timings = vpif_s_dv_timings, | |
| 1391 | + .vidioc_g_dv_timings = vpif_g_dv_timings, | |
| 1392 | + | |
| 1906 | 1393 | .vidioc_log_status = vpif_log_status, |
| 1907 | 1394 | }; |
| 1908 | 1395 | |
| 1909 | 1396 | /* vpif file operations */ |
| 1910 | 1397 | static struct v4l2_file_operations vpif_fops = { |
| 1911 | 1398 | .owner = THIS_MODULE, |
| 1912 | − .open = vpif_open, | |
| 1913 | − .release = vpif_release, | |
| 1399 | + .open = v4l2_fh_open, | |
| 1400 | + .release = vb2_fop_release, | |
| 1914 | 1401 | .unlocked_ioctl = video_ioctl2, |
| 1915 | − .mmap = vpif_mmap, | |
| 1916 | − .poll = vpif_poll | |
| 1917 | −}; | |
| 1918 | − | |
| 1919 | −/* vpif video template */ | |
| 1920 | −static struct video_device vpif_video_template = { | |
| 1921 | − .name = "vpif", | |
| 1922 | − .fops = &vpif_fops, | |
| 1923 | − .minor = -1, | |
| 1924 | − .ioctl_ops = &vpif_ioctl_ops, | |
| 1402 | + .mmap = vb2_fop_mmap, | |
| 1403 | + .poll = vb2_fop_poll | |
| 1925 | 1404 | }; |
| 1926 | 1405 | |
| 1927 | 1406 | /** |
| @@ -1999,7 +1478,9 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier, · 71 unmodified lines | ||
| 1999 | 1478 | static int vpif_probe_complete(void) |
| 2000 | 1479 | { |
| 2001 | 1480 | struct common_obj *common; |
| 1481 | + struct video_device *vdev; | |
| 2002 | 1482 | struct channel_obj *ch; |
| 1483 | + struct vb2_queue *q; | |
| 2003 | 1484 | int i, j, err, k; |
| 2004 | 1485 | |
| 2005 | 1486 | for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { |
| @@ -2008,17 +1489,52 @@ static int vpif_probe_complete(void) · 2 unmodified lines | ||
| 2008 | 1489 | common = &(ch->common[VPIF_VIDEO_INDEX]); |
| 2009 | 1490 | spin_lock_init(&common->irqlock); |
| 2010 | 1491 | mutex_init(&common->lock); |
| 2011 | − ch->video_dev->lock = &common->lock; | |
| 2012 | − /* Initialize prio member of channel object */ | |
| 2013 | − v4l2_prio_init(&ch->prio); | |
| 2014 | − video_set_drvdata(ch->video_dev, ch); | |
| 2015 | 1492 | |
| 2016 | 1493 | /* select input 0 */ |
| 2017 | 1494 | err = vpif_set_input(vpif_obj.config, ch, 0); |
| 2018 | 1495 | if (err) |
| 2019 | 1496 | goto probe_out; |
| 2020 | 1497 | |
| 2021 | − err = video_register_device(ch->video_dev, | |
| 1498 | + /* Initialize vb2 queue */ | |
| 1499 | + q = &common->buffer_queue; | |
| 1500 | + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 1501 | + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; | |
| 1502 | + q->drv_priv = ch; | |
| 1503 | + q->ops = &video_qops; | |
| 1504 | + q->mem_ops = &vb2_dma_contig_memops; | |
| 1505 | + q->buf_struct_size = sizeof(struct vpif_cap_buffer); | |
| 1506 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 1507 | + q->min_buffers_needed = 1; | |
| 1508 | + q->lock = &common->lock; | |
| 1509 | + | |
| 1510 | + err = vb2_queue_init(q); | |
| 1511 | + if (err) { | |
| 1512 | + vpif_err("vpif_capture: vb2_queue_init() failed\n"); | |
| 1513 | + goto probe_out; | |
| 1514 | + } | |
| 1515 | + | |
| 1516 | + common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); | |
| 1517 | + if (IS_ERR(common->alloc_ctx)) { | |
| 1518 | + vpif_err("Failed to get the context\n"); | |
| 1519 | + err = PTR_ERR(common->alloc_ctx); | |
| 1520 | + goto probe_out; | |
| 1521 | + } | |
| 1522 | + | |
| 1523 | + INIT_LIST_HEAD(&common->dma_queue); | |
| 1524 | + | |
| 1525 | + /* Initialize the video_device structure */ | |
| 1526 | + vdev = ch->video_dev; | |
| 1527 | + strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); | |
| 1528 | + vdev->release = video_device_release; | |
| 1529 | + vdev->fops = &vpif_fops; | |
| 1530 | + vdev->ioctl_ops = &vpif_ioctl_ops; | |
| 1531 | + vdev->v4l2_dev = &vpif_obj.v4l2_dev; | |
| 1532 | + vdev->vfl_dir = VFL_DIR_RX; | |
| 1533 | + vdev->queue = q; | |
| 1534 | + vdev->lock = &common->lock; | |
| 1535 | + set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | |
| 1536 | + video_set_drvdata(ch->video_dev, ch); | |
| 1537 | + err = video_register_device(vdev, | |
| 2022 | 1538 | VFL_TYPE_GRABBER, (j ? 1 : 0)); |
| 2023 | 1539 | if (err) |
| 2024 | 1540 | goto probe_out; |
| @@ -2031,6 +1547,8 @@ probe_out: · 6 unmodified lines | ||
| 2031 | 1547 | for (k = 0; k < j; k++) { |
| 2032 | 1548 | /* Get the pointer to the channel object */ |
| 2033 | 1549 | ch = vpif_obj.dev[k]; |
| 1550 | + common = &ch->common[k]; | |
| 1551 | + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 2034 | 1552 | /* Unregister video device */ |
| 2035 | 1553 | video_unregister_device(ch->video_dev); |
| 2036 | 1554 | } |
| @@ -2067,7 +1585,6 @@ static __init int vpif_probe(struct platform_device *pdev) · 30 unmodified lines | ||
| 2067 | 1585 | struct video_device *vfd; |
| 2068 | 1586 | struct resource *res; |
| 2069 | 1587 | int subdev_count; |
| 2070 | − size_t size; | |
| 2071 | 1588 | |
| 2072 | 1589 | vpif_dev = &pdev->dev; |
| 2073 | 1590 | |
| @@ -2085,7 +1602,7 @@ static __init int vpif_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 2085 | 1602 | |
| 2086 | 1603 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
| 2087 | 1604 | err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, |
| 2088 | − IRQF_SHARED, "VPIF_Capture", | |
| 1605 | + IRQF_SHARED, VPIF_DRIVER_NAME, | |
| 2089 | 1606 | (void *)(&vpif_obj.dev[res_idx]-> |
| 2090 | 1607 | channel_id)); |
| 2091 | 1608 | if (err) { |
| @@ -2109,34 +1626,10 @@ static __init int vpif_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 2109 | 1626 | goto vpif_unregister; |
| 2110 | 1627 | } |
| 2111 | 1628 | |
| 2112 | − /* Initialize field of video device */ | |
| 2113 | − *vfd = vpif_video_template; | |
| 2114 | − vfd->v4l2_dev = &vpif_obj.v4l2_dev; | |
| 2115 | − vfd->release = video_device_release; | |
| 2116 | − snprintf(vfd->name, sizeof(vfd->name), | |
| 2117 | − "VPIF_Capture_DRIVER_V%s", | |
| 2118 | − VPIF_CAPTURE_VERSION); | |
| 2119 | 1629 | /* Set video_dev to the video device */ |
| 2120 | 1630 | ch->video_dev = vfd; |
| 2121 | 1631 | } |
| 2122 | 1632 | |
| 2123 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 2124 | − if (res) { | |
| 2125 | − size = resource_size(res); | |
| 2126 | − /* The resources are divided into two equal memory and when we | |
| 2127 | − * have HD output we can add them together | |
| 2128 | − */ | |
| 2129 | − for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { | |
| 2130 | − ch = vpif_obj.dev[j]; | |
| 2131 | − ch->channel_id = j; | |
| 2132 | − /* only enabled if second resource exists */ | |
| 2133 | − config_params.video_limit[ch->channel_id] = 0; | |
| 2134 | − if (size) | |
| 2135 | − config_params.video_limit[ch->channel_id] = | |
| 2136 | − size/2; | |
| 2137 | − } | |
| 2138 | − } | |
| 2139 | − | |
| 2140 | 1633 | vpif_obj.config = pdev->dev.platform_data; |
| 2141 | 1634 | |
| 2142 | 1635 | subdev_count = vpif_obj.config->subdev_count; |
| @@ -2209,6 +1702,7 @@ vpif_unregister: · 66 unmodified lines | ||
| 2209 | 1702 | */ |
| 2210 | 1703 | static int vpif_remove(struct platform_device *device) |
| 2211 | 1704 | { |
| 1705 | + struct common_obj *common; | |
| 2212 | 1706 | struct channel_obj *ch; |
| 2213 | 1707 | int i; |
| 2214 | 1708 | |
| @@ -2219,6 +1713,8 @@ static int vpif_remove(struct platform_device *device) · 4 unmodified lines | ||
| 2219 | 1713 | for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { |
| 2220 | 1714 | /* Get the pointer to the channel object */ |
| 2221 | 1715 | ch = vpif_obj.dev[i]; |
| 1716 | + common = &ch->common[i]; | |
| 1717 | + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 2222 | 1718 | /* Unregister video device */ |
| 2223 | 1719 | video_unregister_device(ch->video_dev); |
| 2224 | 1720 | kfree(vpif_obj.dev[i]); |
| @@ -2226,7 +1722,7 @@ static int vpif_remove(struct platform_device *device) · 1 unmodified line | ||
| 2226 | 1722 | return 0; |
| 2227 | 1723 | } |
| 2228 | 1724 | |
| 2229 | −#ifdef CONFIG_PM | |
| 1725 | +#ifdef CONFIG_PM_SLEEP | |
| 2230 | 1726 | /** |
| 2231 | 1727 | * vpif_suspend: vpif device suspend |
| 2232 | 1728 | */ |
| @@ -2241,18 +1737,20 @@ static int vpif_suspend(struct device *dev) · 8 unmodified lines | ||
| 2241 | 1737 | /* Get the pointer to the channel object */ |
| 2242 | 1738 | ch = vpif_obj.dev[i]; |
| 2243 | 1739 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1740 | + | |
| 1741 | + if (!vb2_is_streaming(&common->buffer_queue)) | |
| 1742 | + continue; | |
| 1743 | + | |
| 2244 | 1744 | mutex_lock(&common->lock); |
| 2245 | − if (ch->usrs && common->io_usrs) { | |
| 2246 | − /* Disable channel */ | |
| 2247 | − if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { | |
| 2248 | − enable_channel0(0); | |
| 2249 | − channel0_intr_enable(0); | |
| 2250 | − } | |
| 2251 | − if (ch->channel_id == VPIF_CHANNEL1_VIDEO || | |
| 2252 | − common->started == 2) { | |
| 2253 | − enable_channel1(0); | |
| 2254 | − channel1_intr_enable(0); | |
| 2255 | − } | |
| 1745 | + /* Disable channel */ | |
| 1746 | + if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { | |
| 1747 | + enable_channel0(0); | |
| 1748 | + channel0_intr_enable(0); | |
| 1749 | + } | |
| 1750 | + if (ch->channel_id == VPIF_CHANNEL1_VIDEO || | |
| 1751 | + ycmux_mode == 2) { | |
| 1752 | + enable_channel1(0); | |
| 1753 | + channel1_intr_enable(0); | |
| 2256 | 1754 | } |
| 2257 | 1755 | mutex_unlock(&common->lock); |
| 2258 | 1756 | } |
| @@ -2273,40 +1771,35 @@ static int vpif_resume(struct device *dev) · 14 unmodified lines | ||
| 2273 | 1771 | /* Get the pointer to the channel object */ |
| 2274 | 1772 | ch = vpif_obj.dev[i]; |
| 2275 | 1773 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1774 | + | |
| 1775 | + if (!vb2_is_streaming(&common->buffer_queue)) | |
| 1776 | + continue; | |
| 1777 | + | |
| 2276 | 1778 | mutex_lock(&common->lock); |
| 2277 | − if (ch->usrs && common->io_usrs) { | |
| 2278 | − /* Disable channel */ | |
| 2279 | − if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { | |
| 2280 | − enable_channel0(1); | |
| 2281 | − channel0_intr_enable(1); | |
| 2282 | − } | |
| 2283 | − if (ch->channel_id == VPIF_CHANNEL1_VIDEO || | |
| 2284 | − common->started == 2) { | |
| 2285 | − enable_channel1(1); | |
| 2286 | − channel1_intr_enable(1); | |
| 2287 | − } | |
| 1779 | + /* Enable channel */ | |
| 1780 | + if (ch->channel_id == VPIF_CHANNEL0_VIDEO) { | |
| 1781 | + enable_channel0(1); | |
| 1782 | + channel0_intr_enable(1); | |
| 1783 | + } | |
| 1784 | + if (ch->channel_id == VPIF_CHANNEL1_VIDEO || | |
| 1785 | + ycmux_mode == 2) { | |
| 1786 | + enable_channel1(1); | |
| 1787 | + channel1_intr_enable(1); | |
| 2288 | 1788 | } |
| 2289 | 1789 | mutex_unlock(&common->lock); |
| 2290 | 1790 | } |
| 2291 | 1791 | |
| 2292 | 1792 | return 0; |
| 2293 | 1793 | } |
| 2294 | − | |
| 2295 | −static const struct dev_pm_ops vpif_dev_pm_ops = { | |
| 2296 | − .suspend = vpif_suspend, | |
| 2297 | − .resume = vpif_resume, | |
| 2298 | −}; | |
| 2299 | − | |
| 2300 | −#define vpif_pm_ops (&vpif_dev_pm_ops) | |
| 2301 | −#else | |
| 2302 | −#define vpif_pm_ops NULL | |
| 2303 | 1794 | #endif |
| 2304 | 1795 | |
| 1796 | +static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); | |
| 1797 | + | |
| 2305 | 1798 | static __refdata struct platform_driver vpif_driver = { |
| 2306 | 1799 | .driver = { |
| 2307 | − .name = "vpif_capture", | |
| 1800 | + .name = VPIF_DRIVER_NAME, | |
| 2308 | 1801 | .owner = THIS_MODULE, |
| 2309 | − .pm = vpif_pm_ops, | |
| 1802 | + .pm = &vpif_pm_ops, | |
| 2310 | 1803 | }, |
| 2311 | 1804 | .probe = vpif_probe, |
| 2312 | 1805 | .remove = vpif_remove, |
| @@ -19,8 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #ifndef VPIF_CAPTURE_H |
| 20 | 20 | #define VPIF_CAPTURE_H |
| 21 | 21 | |
| 22 | −#ifdef __KERNEL__ | |
| 23 | − | |
| 24 | 22 | /* Header files */ |
| 25 | 23 | #include <media/videobuf2-dma-contig.h> |
| 26 | 24 | #include <media/v4l2-device.h> |
| @@ -63,11 +61,6 @@ struct common_obj { · 36 unmodified lines | ||
| 63 | 61 | struct vpif_cap_buffer *cur_frm; |
| 64 | 62 | /* Pointer pointing to current v4l2_buffer */ |
| 65 | 63 | struct vpif_cap_buffer *next_frm; |
| 66 | − /* | |
| 67 | − * This field keeps track of type of buffer exchange mechanism | |
| 68 | − * user has selected | |
| 69 | − */ | |
| 70 | − enum v4l2_memory memory; | |
| 71 | 64 | /* Used to store pixel format */ |
| 72 | 65 | struct v4l2_format fmt; |
| 73 | 66 | /* Buffer queue used in video-buf */ |
| @@ -80,10 +73,6 @@ struct common_obj { · 6 unmodified lines | ||
| 80 | 73 | spinlock_t irqlock; |
| 81 | 74 | /* lock used to access this structure */ |
| 82 | 75 | struct mutex lock; |
| 83 | − /* number of users performing IO */ | |
| 84 | − u32 io_usrs; | |
| 85 | − /* Indicates whether streaming started */ | |
| 86 | − u8 started; | |
| 87 | 76 | /* Function pointer to set the addresses */ |
| 88 | 77 | void (*set_addr) (unsigned long, unsigned long, unsigned long, |
| 89 | 78 | unsigned long); |
| @@ -104,10 +93,6 @@ struct common_obj { · 14 unmodified lines | ||
| 104 | 93 | struct channel_obj { |
| 105 | 94 | /* Identifies video device for this channel */ |
| 106 | 95 | struct video_device *video_dev; |
| 107 | − /* Used to keep track of state of the priority */ | |
| 108 | − struct v4l2_prio_state prio; | |
| 109 | − /* number of open instances of the channel */ | |
| 110 | − int usrs; | |
| 111 | 96 | /* Indicates id of the field which is being displayed */ |
| 112 | 97 | u32 field_id; |
| 113 | 98 | /* flag to indicate whether decoder is initialized */ |
| @@ -126,18 +111,6 @@ struct channel_obj { · 12 unmodified lines | ||
| 126 | 111 | struct video_obj video; |
| 127 | 112 | }; |
| 128 | 113 | |
| 129 | −/* File handle structure */ | |
| 130 | −struct vpif_fh { | |
| 131 | − /* pointer to channel object for opened device */ | |
| 132 | − struct channel_obj *channel; | |
| 133 | − /* Indicates whether this file handle is doing IO */ | |
| 134 | − u8 io_allowed[VPIF_NUMBER_OF_OBJECTS]; | |
| 135 | − /* Used to keep track priority of this instance */ | |
| 136 | − enum v4l2_priority prio; | |
| 137 | − /* Used to indicate channel is initialize or not */ | |
| 138 | − u8 initialized; | |
| 139 | −}; | |
| 140 | − | |
| 141 | 114 | struct vpif_device { |
| 142 | 115 | struct v4l2_device v4l2_dev; |
| 143 | 116 | struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; |
| @@ -157,5 +130,4 @@ struct vpif_config_params { · 13 unmodified lines | ||
| 157 | 130 | u8 max_device_type; |
| 158 | 131 | }; |
| 159 | 132 | |
| 160 | −#endif /* End of __KERNEL__ */ | |
| 161 | 133 | #endif /* VPIF_CAPTURE_H */ |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * Display driver for TI DaVinci VPIF |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ |
| 6 | + * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com> | |
| 6 | 7 | * |
| 7 | 8 | * This program is free software; you can redistribute it and/or |
| 8 | 9 | * modify it under the terms of the GNU General Public License as |
| @@ -35,129 +36,110 @@ MODULE_VERSION(VPIF_DISPLAY_VERSION); · 26 unmodified lines | ||
| 35 | 36 | v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) |
| 36 | 37 | |
| 37 | 38 | static int debug = 1; |
| 38 | −static u32 ch2_numbuffers = 3; | |
| 39 | −static u32 ch3_numbuffers = 3; | |
| 40 | −static u32 ch2_bufsize = 1920 * 1080 * 2; | |
| 41 | −static u32 ch3_bufsize = 720 * 576 * 2; | |
| 42 | 39 | |
| 43 | 40 | module_param(debug, int, 0644); |
| 44 | −module_param(ch2_numbuffers, uint, S_IRUGO); | |
| 45 | −module_param(ch3_numbuffers, uint, S_IRUGO); | |
| 46 | −module_param(ch2_bufsize, uint, S_IRUGO); | |
| 47 | −module_param(ch3_bufsize, uint, S_IRUGO); | |
| 48 | 41 | |
| 49 | 42 | MODULE_PARM_DESC(debug, "Debug level 0-1"); |
| 50 | −MODULE_PARM_DESC(ch2_numbuffers, "Channel2 buffer count (default:3)"); | |
| 51 | −MODULE_PARM_DESC(ch3_numbuffers, "Channel3 buffer count (default:3)"); | |
| 52 | −MODULE_PARM_DESC(ch2_bufsize, "Channel2 buffer size (default:1920 x 1080 x 2)"); | |
| 53 | −MODULE_PARM_DESC(ch3_bufsize, "Channel3 buffer size (default:720 x 576 x 2)"); | |
| 54 | − | |
| 55 | −static struct vpif_config_params config_params = { | |
| 56 | − .min_numbuffers = 3, | |
| 57 | − .numbuffers[0] = 3, | |
| 58 | − .numbuffers[1] = 3, | |
| 59 | − .min_bufsize[0] = 720 * 480 * 2, | |
| 60 | − .min_bufsize[1] = 720 * 480 * 2, | |
| 61 | − .channel_bufsize[0] = 1920 * 1080 * 2, | |
| 62 | − .channel_bufsize[1] = 720 * 576 * 2, | |
| 63 | −}; | |
| 43 | + | |
| 44 | +#define VPIF_DRIVER_NAME "vpif_display" | |
| 45 | + | |
| 46 | +/* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ | |
| 47 | +static int ycmux_mode; | |
| 48 | + | |
| 49 | +static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; | |
| 64 | 50 | |
| 65 | 51 | static struct vpif_device vpif_obj = { {NULL} }; |
| 66 | 52 | static struct device *vpif_dev; |
| 67 | 53 | static void vpif_calculate_offsets(struct channel_obj *ch); |
| 68 | 54 | static void vpif_config_addr(struct channel_obj *ch, int muxmode); |
| 69 | 55 | |
| 70 | −/* | |
| 71 | − * buffer_prepare: This is the callback function called from vb2_qbuf() | |
| 72 | − * function the buffer is prepared and user space virtual address is converted | |
| 73 | − * into physical address | |
| 56 | +static inline struct vpif_disp_buffer *to_vpif_buffer(struct vb2_buffer *vb) | |
| 57 | +{ | |
| 58 | + return container_of(vb, struct vpif_disp_buffer, vb); | |
| 59 | +} | |
| 60 | + | |
| 61 | +/** | |
| 62 | + * vpif_buffer_prepare : callback function for buffer prepare | |
| 63 | + * @vb: ptr to vb2_buffer | |
| 64 | + * | |
| 65 | + * This is the callback function for buffer prepare when vb2_qbuf() | |
| 66 | + * function is called. The buffer is prepared and user space virtual address | |
| 67 | + * or user address is converted into physical address | |
| 74 | 68 | */ |
| 75 | 69 | static int vpif_buffer_prepare(struct vb2_buffer *vb) |
| 76 | 70 | { |
| 77 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 78 | − struct vb2_queue *q = vb->vb2_queue; | |
| 71 | + struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); | |
| 79 | 72 | struct common_obj *common; |
| 80 | − unsigned long addr; | |
| 81 | − | |
| 82 | − common = &fh->channel->common[VPIF_VIDEO_INDEX]; | |
| 83 | − if (vb->state != VB2_BUF_STATE_ACTIVE && | |
| 84 | − vb->state != VB2_BUF_STATE_PREPARED) { | |
| 85 | − vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); | |
| 86 | − if (vb2_plane_vaddr(vb, 0) && | |
| 87 | − vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) | |
| 88 | − goto buf_align_exit; | |
| 89 | − | |
| 90 | − addr = vb2_dma_contig_plane_dma_addr(vb, 0); | |
| 91 | − if (q->streaming && | |
| 92 | − (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { | |
| 93 | − if (!ISALIGNED(addr + common->ytop_off) || | |
| 73 | + | |
| 74 | + common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 75 | + | |
| 76 | + vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); | |
| 77 | + if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) | |
| 78 | + return -EINVAL; | |
| 79 | + | |
| 80 | + vb->v4l2_buf.field = common->fmt.fmt.pix.field; | |
| 81 | + | |
| 82 | + if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | |
| 83 | + unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0); | |
| 84 | + | |
| 85 | + if (!ISALIGNED(addr + common->ytop_off) || | |
| 94 | 86 | !ISALIGNED(addr + common->ybtm_off) || |
| 95 | 87 | !ISALIGNED(addr + common->ctop_off) || |
| 96 | − !ISALIGNED(addr + common->cbtm_off)) | |
| 97 | − goto buf_align_exit; | |
| 88 | + !ISALIGNED(addr + common->cbtm_off)) { | |
| 89 | + vpif_err("buffer offset not aligned to 8 bytes\n"); | |
| 90 | + return -EINVAL; | |
| 98 | 91 | } |
| 99 | 92 | } |
| 100 | − return 0; | |
| 101 | 93 | |
| 102 | −buf_align_exit: | |
| 103 | − vpif_err("buffer offset not aligned to 8 bytes\n"); | |
| 104 | − return -EINVAL; | |
| 94 | + return 0; | |
| 105 | 95 | } |
| 106 | 96 | |
| 107 | −/* | |
| 108 | − * vpif_buffer_queue_setup: This function allocates memory for the buffers | |
| 97 | +/** | |
| 98 | + * vpif_buffer_queue_setup : Callback function for buffer setup. | |
| 99 | + * @vq: vb2_queue ptr | |
| 100 | + * @fmt: v4l2 format | |
| 101 | + * @nbuffers: ptr to number of buffers requested by application | |
| 102 | + * @nplanes:: contains number of distinct video planes needed to hold a frame | |
| 103 | + * @sizes[]: contains the size (in bytes) of each plane. | |
| 104 | + * @alloc_ctxs: ptr to allocation context | |
| 105 | + * | |
| 106 | + * This callback function is called when reqbuf() is called to adjust | |
| 107 | + * the buffer count and buffer size | |
| 109 | 108 | */ |
| 110 | 109 | static int vpif_buffer_queue_setup(struct vb2_queue *vq, |
| 111 | 110 | const struct v4l2_format *fmt, |
| 112 | 111 | unsigned int *nbuffers, unsigned int *nplanes, |
| 113 | 112 | unsigned int sizes[], void *alloc_ctxs[]) |
| 114 | 113 | { |
| 115 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 116 | − struct channel_obj *ch = fh->channel; | |
| 114 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 117 | 115 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 118 | − unsigned long size; | |
| 119 | − | |
| 120 | − if (V4L2_MEMORY_MMAP == common->memory) { | |
| 121 | − size = config_params.channel_bufsize[ch->channel_id]; | |
| 122 | − /* | |
| 123 | − * Checking if the buffer size exceeds the available buffer | |
| 124 | − * ycmux_mode = 0 means 1 channel mode HD and | |
| 125 | − * ycmux_mode = 1 means 2 channels mode SD | |
| 126 | − */ | |
| 127 | − if (ch->vpifparams.std_info.ycmux_mode == 0) { | |
| 128 | − if (config_params.video_limit[ch->channel_id]) | |
| 129 | − while (size * *nbuffers > | |
| 130 | − (config_params.video_limit[0] | |
| 131 | − + config_params.video_limit[1])) | |
| 132 | − (*nbuffers)--; | |
| 133 | − } else { | |
| 134 | − if (config_params.video_limit[ch->channel_id]) | |
| 135 | − while (size * *nbuffers > | |
| 136 | − config_params.video_limit[ch->channel_id]) | |
| 137 | − (*nbuffers)--; | |
| 138 | − } | |
| 139 | − } else { | |
| 140 | − size = common->fmt.fmt.pix.sizeimage; | |
| 141 | − } | |
| 142 | 116 | |
| 143 | − if (*nbuffers < config_params.min_numbuffers) | |
| 144 | − *nbuffers = config_params.min_numbuffers; | |
| 117 | + if (fmt && fmt->fmt.pix.sizeimage < common->fmt.fmt.pix.sizeimage) | |
| 118 | + return -EINVAL; | |
| 119 | + | |
| 120 | + if (vq->num_buffers + *nbuffers < 3) | |
| 121 | + *nbuffers = 3 - vq->num_buffers; | |
| 145 | 122 | |
| 146 | 123 | *nplanes = 1; |
| 147 | − sizes[0] = size; | |
| 124 | + sizes[0] = fmt ? fmt->fmt.pix.sizeimage : common->fmt.fmt.pix.sizeimage; | |
| 148 | 125 | alloc_ctxs[0] = common->alloc_ctx; |
| 126 | + | |
| 127 | + /* Calculate the offset for Y and C data in the buffer */ | |
| 128 | + vpif_calculate_offsets(ch); | |
| 129 | + | |
| 149 | 130 | return 0; |
| 150 | 131 | } |
| 151 | 132 | |
| 152 | −/* | |
| 153 | − * vpif_buffer_queue: This function adds the buffer to DMA queue | |
| 133 | +/** | |
| 134 | + * vpif_buffer_queue : Callback function to add buffer to DMA queue | |
| 135 | + * @vb: ptr to vb2_buffer | |
| 136 | + * | |
| 137 | + * This callback fucntion queues the buffer to DMA engine | |
| 154 | 138 | */ |
| 155 | 139 | static void vpif_buffer_queue(struct vb2_buffer *vb) |
| 156 | 140 | { |
| 157 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 158 | − struct vpif_disp_buffer *buf = container_of(vb, | |
| 159 | − struct vpif_disp_buffer, vb); | |
| 160 | − struct channel_obj *ch = fh->channel; | |
| 141 | + struct vpif_disp_buffer *buf = to_vpif_buffer(vb); | |
| 142 | + struct channel_obj *ch = vb2_get_drv_priv(vb->vb2_queue); | |
| 161 | 143 | struct common_obj *common; |
| 162 | 144 | unsigned long flags; |
| 163 | 145 | |
| @@ -169,98 +151,26 @@ static void vpif_buffer_queue(struct vb2_buffer *vb) · 5 unmodified lines | ||
| 169 | 151 | spin_unlock_irqrestore(&common->irqlock, flags); |
| 170 | 152 | } |
| 171 | 153 | |
| 172 | −/* | |
| 173 | − * vpif_buf_cleanup: This function is called from the videobuf2 layer to | |
| 174 | − * free memory allocated to the buffers | |
| 154 | +/** | |
| 155 | + * vpif_start_streaming : Starts the DMA engine for streaming | |
| 156 | + * @vb: ptr to vb2_buffer | |
| 157 | + * @count: number of buffers | |
| 175 | 158 | */ |
| 176 | −static void vpif_buf_cleanup(struct vb2_buffer *vb) | |
| 177 | −{ | |
| 178 | − struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); | |
| 179 | − struct vpif_disp_buffer *buf = container_of(vb, | |
| 180 | − struct vpif_disp_buffer, vb); | |
| 181 | − struct channel_obj *ch = fh->channel; | |
| 182 | − struct common_obj *common; | |
| 183 | − unsigned long flags; | |
| 184 | − | |
| 185 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 186 | − | |
| 187 | − spin_lock_irqsave(&common->irqlock, flags); | |
| 188 | − if (vb->state == VB2_BUF_STATE_ACTIVE) | |
| 189 | − list_del_init(&buf->list); | |
| 190 | − spin_unlock_irqrestore(&common->irqlock, flags); | |
| 191 | −} | |
| 192 | − | |
| 193 | −static void vpif_wait_prepare(struct vb2_queue *vq) | |
| 194 | −{ | |
| 195 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 196 | − struct channel_obj *ch = fh->channel; | |
| 197 | − struct common_obj *common; | |
| 198 | − | |
| 199 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 200 | − mutex_unlock(&common->lock); | |
| 201 | −} | |
| 202 | − | |
| 203 | −static void vpif_wait_finish(struct vb2_queue *vq) | |
| 204 | −{ | |
| 205 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 206 | − struct channel_obj *ch = fh->channel; | |
| 207 | − struct common_obj *common; | |
| 208 | − | |
| 209 | − common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 210 | − mutex_lock(&common->lock); | |
| 211 | −} | |
| 212 | − | |
| 213 | −static int vpif_buffer_init(struct vb2_buffer *vb) | |
| 214 | −{ | |
| 215 | − struct vpif_disp_buffer *buf = container_of(vb, | |
| 216 | − struct vpif_disp_buffer, vb); | |
| 217 | − | |
| 218 | − INIT_LIST_HEAD(&buf->list); | |
| 219 | − | |
| 220 | − return 0; | |
| 221 | −} | |
| 222 | − | |
| 223 | −static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; | |
| 224 | − | |
| 225 | 159 | static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) |
| 226 | 160 | { |
| 227 | 161 | struct vpif_display_config *vpif_config_data = |
| 228 | 162 | vpif_dev->platform_data; |
| 229 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 230 | − struct channel_obj *ch = fh->channel; | |
| 163 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 231 | 164 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 232 | 165 | struct vpif_params *vpif = &ch->vpifparams; |
| 233 | − unsigned long addr = 0; | |
| 234 | − unsigned long flags; | |
| 166 | + struct vpif_disp_buffer *buf, *tmp; | |
| 167 | + unsigned long addr, flags; | |
| 235 | 168 | int ret; |
| 236 | 169 | |
| 237 | 170 | spin_lock_irqsave(&common->irqlock, flags); |
| 238 | 171 | |
| 239 | − /* Get the next frame from the buffer queue */ | |
| 240 | − common->next_frm = common->cur_frm = | |
| 241 | − list_entry(common->dma_queue.next, | |
| 242 | − struct vpif_disp_buffer, list); | |
| 243 | − | |
| 244 | − list_del(&common->cur_frm->list); | |
| 245 | − spin_unlock_irqrestore(&common->irqlock, flags); | |
| 246 | − /* Mark state of the current frame to active */ | |
| 247 | − common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | |
| 248 | − | |
| 249 | − /* Initialize field_id and started member */ | |
| 172 | + /* Initialize field_id */ | |
| 250 | 173 | ch->field_id = 0; |
| 251 | − common->started = 1; | |
| 252 | − addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | |
| 253 | − /* Calculate the offset for Y and C data in the buffer */ | |
| 254 | − vpif_calculate_offsets(ch); | |
| 255 | − | |
| 256 | − if ((ch->vpifparams.std_info.frm_fmt && | |
| 257 | − ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) | |
| 258 | − && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) | |
| 259 | − || (!ch->vpifparams.std_info.frm_fmt | |
| 260 | − && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { | |
| 261 | − vpif_err("conflict in field format and std format\n"); | |
| 262 | − return -EINVAL; | |
| 263 | − } | |
| 264 | 174 | |
| 265 | 175 | /* clock settings */ |
| 266 | 176 | if (vpif_config_data->set_clock) { |
| @@ -268,24 +178,37 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) · 1 unmodified line | ||
| 268 | 178 | ycmux_mode, ch->vpifparams.std_info.hd_sd); |
| 269 | 179 | if (ret < 0) { |
| 270 | 180 | vpif_err("can't set clock\n"); |
| 271 | − return ret; | |
| 181 | + goto err; | |
| 272 | 182 | } |
| 273 | 183 | } |
| 274 | 184 | |
| 275 | 185 | /* set the parameters and addresses */ |
| 276 | 186 | ret = vpif_set_video_params(vpif, ch->channel_id + 2); |
| 277 | 187 | if (ret < 0) |
| 278 | − return ret; | |
| 188 | + goto err; | |
| 279 | 189 | |
| 280 | − common->started = ret; | |
| 190 | + ycmux_mode = ret; | |
| 281 | 191 | vpif_config_addr(ch, ret); |
| 192 | + /* Get the next frame from the buffer queue */ | |
| 193 | + common->next_frm = common->cur_frm = | |
| 194 | + list_entry(common->dma_queue.next, | |
| 195 | + struct vpif_disp_buffer, list); | |
| 196 | + | |
| 197 | + list_del(&common->cur_frm->list); | |
| 198 | + spin_unlock_irqrestore(&common->irqlock, flags); | |
| 199 | + /* Mark state of the current frame to active */ | |
| 200 | + common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; | |
| 201 | + | |
| 202 | + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); | |
| 282 | 203 | common->set_addr((addr + common->ytop_off), |
| 283 | 204 | (addr + common->ybtm_off), |
| 284 | 205 | (addr + common->ctop_off), |
| 285 | 206 | (addr + common->cbtm_off)); |
| 286 | 207 | |
| 287 | − /* Set interrupt for both the fields in VPIF | |
| 288 | − Register enable channel in VPIF register */ | |
| 208 | + /* | |
| 209 | + * Set interrupt for both the fields in VPIF | |
| 210 | + * Register enable channel in VPIF register | |
| 211 | + */ | |
| 289 | 212 | channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; |
| 290 | 213 | if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { |
| 291 | 214 | channel2_intr_assert(); |
| @@ -295,8 +218,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) · 3 unmodified lines | ||
| 295 | 218 | channel2_clipping_enable(1); |
| 296 | 219 | } |
| 297 | 220 | |
| 298 | − if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) | |
| 299 | − || (common->started == 2)) { | |
| 221 | + if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) { | |
| 300 | 222 | channel3_intr_assert(); |
| 301 | 223 | channel3_intr_enable(1); |
| 302 | 224 | enable_channel3(1); |
| @@ -305,19 +227,29 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) · 2 unmodified lines | ||
| 305 | 227 | } |
| 306 | 228 | |
| 307 | 229 | return 0; |
| 230 | + | |
| 231 | +err: | |
| 232 | + list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) { | |
| 233 | + list_del(&buf->list); | |
| 234 | + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | |
| 235 | + } | |
| 236 | + | |
| 237 | + return ret; | |
| 308 | 238 | } |
| 309 | 239 | |
| 310 | −/* abort streaming and wait for last buffer */ | |
| 311 | −static int vpif_stop_streaming(struct vb2_queue *vq) | |
| 240 | +/** | |
| 241 | + * vpif_stop_streaming : Stop the DMA engine | |
| 242 | + * @vq: ptr to vb2_queue | |
| 243 | + * | |
| 244 | + * This callback stops the DMA engine and any remaining buffers | |
| 245 | + * in the DMA queue are released. | |
| 246 | + */ | |
| 247 | +static void vpif_stop_streaming(struct vb2_queue *vq) | |
| 312 | 248 | { |
| 313 | − struct vpif_fh *fh = vb2_get_drv_priv(vq); | |
| 314 | − struct channel_obj *ch = fh->channel; | |
| 249 | + struct channel_obj *ch = vb2_get_drv_priv(vq); | |
| 315 | 250 | struct common_obj *common; |
| 316 | 251 | unsigned long flags; |
| 317 | 252 | |
| 318 | − if (!vb2_is_streaming(vq)) | |
| 319 | − return 0; | |
| 320 | − | |
| 321 | 253 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 322 | 254 | |
| 323 | 255 | /* Disable channel */ |
| @@ -325,12 +257,10 @@ static int vpif_stop_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 325 | 257 | enable_channel2(0); |
| 326 | 258 | channel2_intr_enable(0); |
| 327 | 259 | } |
| 328 | − if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || | |
| 329 | − (2 == common->started)) { | |
| 260 | + if (VPIF_CHANNEL3_VIDEO == ch->channel_id || ycmux_mode == 2) { | |
| 330 | 261 | enable_channel3(0); |
| 331 | 262 | channel3_intr_enable(0); |
| 332 | 263 | } |
| 333 | − common->started = 0; | |
| 334 | 264 | |
| 335 | 265 | /* release all active buffers */ |
| 336 | 266 | spin_lock_irqsave(&common->irqlock, flags); |
| @@ -352,19 +282,15 @@ static int vpif_stop_streaming(struct vb2_queue *vq) · 15 unmodified lines | ||
| 352 | 282 | vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); |
| 353 | 283 | } |
| 354 | 284 | spin_unlock_irqrestore(&common->irqlock, flags); |
| 355 | − | |
| 356 | − return 0; | |
| 357 | 285 | } |
| 358 | 286 | |
| 359 | 287 | static struct vb2_ops video_qops = { |
| 360 | 288 | .queue_setup = vpif_buffer_queue_setup, |
| 361 | − .wait_prepare = vpif_wait_prepare, | |
| 362 | − .wait_finish = vpif_wait_finish, | |
| 363 | − .buf_init = vpif_buffer_init, | |
| 289 | + .wait_prepare = vb2_ops_wait_prepare, | |
| 290 | + .wait_finish = vb2_ops_wait_finish, | |
| 364 | 291 | .buf_prepare = vpif_buffer_prepare, |
| 365 | 292 | .start_streaming = vpif_start_streaming, |
| 366 | 293 | .stop_streaming = vpif_stop_streaming, |
| 367 | − .buf_cleanup = vpif_buf_cleanup, | |
| 368 | 294 | .buf_queue = vpif_buffer_queue, |
| 369 | 295 | }; |
| 370 | 296 | |
| @@ -446,8 +372,6 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) · 75 unmodified lines | ||
| 446 | 372 | for (i = 0; i < VPIF_NUMOBJECTS; i++) { |
| 447 | 373 | common = &ch->common[i]; |
| 448 | 374 | /* If streaming is started in this channel */ |
| 449 | − if (0 == common->started) | |
| 450 | − continue; | |
| 451 | 375 | |
| 452 | 376 | if (1 == ch->vpifparams.std_info.frm_fmt) { |
| 453 | 377 | spin_lock(&common->irqlock); |
| @@ -543,6 +467,7 @@ static int vpif_update_resolution(struct channel_obj *ch) · 89 unmodified lines | ||
| 543 | 467 | return -EINVAL; |
| 544 | 468 | } |
| 545 | 469 | |
| 470 | + common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; | |
| 546 | 471 | common->fmt.fmt.pix.width = std_info->width; |
| 547 | 472 | common->fmt.fmt.pix.height = std_info->height; |
| 548 | 473 | vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n", |
| @@ -551,6 +476,17 @@ static int vpif_update_resolution(struct channel_obj *ch) · 2 unmodified lines | ||
| 551 | 476 | /* Set height and width paramateres */ |
| 552 | 477 | common->height = std_info->height; |
| 553 | 478 | common->width = std_info->width; |
| 479 | + common->fmt.fmt.pix.sizeimage = common->height * common->width * 2; | |
| 480 | + | |
| 481 | + if (vid_ch->stdid) | |
| 482 | + common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | |
| 483 | + else | |
| 484 | + common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709; | |
| 485 | + | |
| 486 | + if (ch->vpifparams.std_info.frm_fmt) | |
| 487 | + common->fmt.fmt.pix.field = V4L2_FIELD_NONE; | |
| 488 | + else | |
| 489 | + common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; | |
| 554 | 490 | |
| 555 | 491 | return 0; |
| 556 | 492 | } |
| @@ -621,70 +557,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch) · 64 unmodified lines | ||
| 621 | 557 | ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid; |
| 622 | 558 | } |
| 623 | 559 | |
| 624 | −static void vpif_config_format(struct channel_obj *ch) | |
| 625 | −{ | |
| 626 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 627 | − | |
| 628 | − common->fmt.fmt.pix.field = V4L2_FIELD_ANY; | |
| 629 | − if (config_params.numbuffers[ch->channel_id] == 0) | |
| 630 | − common->memory = V4L2_MEMORY_USERPTR; | |
| 631 | − else | |
| 632 | − common->memory = V4L2_MEMORY_MMAP; | |
| 633 | − | |
| 634 | − common->fmt.fmt.pix.sizeimage = | |
| 635 | − config_params.channel_bufsize[ch->channel_id]; | |
| 636 | − common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; | |
| 637 | − common->fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | |
| 638 | −} | |
| 639 | − | |
| 640 | −static int vpif_check_format(struct channel_obj *ch, | |
| 641 | − struct v4l2_pix_format *pixfmt) | |
| 642 | −{ | |
| 643 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 644 | − enum v4l2_field field = pixfmt->field; | |
| 645 | − u32 sizeimage, hpitch, vpitch; | |
| 646 | − | |
| 647 | − if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) | |
| 648 | − goto invalid_fmt_exit; | |
| 649 | − | |
| 650 | − if (!(VPIF_VALID_FIELD(field))) | |
| 651 | − goto invalid_fmt_exit; | |
| 652 | − | |
| 653 | − if (pixfmt->bytesperline <= 0) | |
| 654 | − goto invalid_pitch_exit; | |
| 655 | − | |
| 656 | − sizeimage = pixfmt->sizeimage; | |
| 657 | − | |
| 658 | − if (vpif_update_resolution(ch)) | |
| 659 | − return -EINVAL; | |
| 660 | − | |
| 661 | − hpitch = pixfmt->bytesperline; | |
| 662 | − vpitch = sizeimage / (hpitch * 2); | |
| 663 | − | |
| 664 | − /* Check for valid value of pitch */ | |
| 665 | − if ((hpitch < ch->vpifparams.std_info.width) || | |
| 666 | − (vpitch < ch->vpifparams.std_info.height)) | |
| 667 | − goto invalid_pitch_exit; | |
| 668 | − | |
| 669 | − /* Check for 8 byte alignment */ | |
| 670 | − if (!ISALIGNED(hpitch)) { | |
| 671 | − vpif_err("invalid pitch alignment\n"); | |
| 672 | − return -EINVAL; | |
| 673 | − } | |
| 674 | − pixfmt->width = common->fmt.fmt.pix.width; | |
| 675 | − pixfmt->height = common->fmt.fmt.pix.height; | |
| 676 | − | |
| 677 | − return 0; | |
| 678 | − | |
| 679 | −invalid_fmt_exit: | |
| 680 | − vpif_err("invalid field format\n"); | |
| 681 | − return -EINVAL; | |
| 682 | − | |
| 683 | −invalid_pitch_exit: | |
| 684 | − vpif_err("invalid pitch\n"); | |
| 685 | − return -EINVAL; | |
| 686 | −} | |
| 687 | − | |
| 688 | 560 | static void vpif_config_addr(struct channel_obj *ch, int muxmode) |
| 689 | 561 | { |
| 690 | 562 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| @@ -699,127 +571,6 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode) · 8 unmodified lines | ||
| 699 | 571 | } |
| 700 | 572 | } |
| 701 | 573 | |
| 702 | −/* | |
| 703 | − * vpif_mmap: It is used to map kernel space buffers into user spaces | |
| 704 | − */ | |
| 705 | −static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) | |
| 706 | −{ | |
| 707 | − struct vpif_fh *fh = filep->private_data; | |
| 708 | − struct channel_obj *ch = fh->channel; | |
| 709 | − struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); | |
| 710 | − int ret; | |
| 711 | − | |
| 712 | − vpif_dbg(2, debug, "vpif_mmap\n"); | |
| 713 | − | |
| 714 | − if (mutex_lock_interruptible(&common->lock)) | |
| 715 | − return -ERESTARTSYS; | |
| 716 | − ret = vb2_mmap(&common->buffer_queue, vma); | |
| 717 | − mutex_unlock(&common->lock); | |
| 718 | − return ret; | |
| 719 | −} | |
| 720 | − | |
| 721 | −/* | |
| 722 | − * vpif_poll: It is used for select/poll system call | |
| 723 | − */ | |
| 724 | −static unsigned int vpif_poll(struct file *filep, poll_table *wait) | |
| 725 | −{ | |
| 726 | − struct vpif_fh *fh = filep->private_data; | |
| 727 | − struct channel_obj *ch = fh->channel; | |
| 728 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 729 | − unsigned int res = 0; | |
| 730 | − | |
| 731 | − if (common->started) { | |
| 732 | − mutex_lock(&common->lock); | |
| 733 | − res = vb2_poll(&common->buffer_queue, filep, wait); | |
| 734 | − mutex_unlock(&common->lock); | |
| 735 | − } | |
| 736 | − | |
| 737 | − return res; | |
| 738 | −} | |
| 739 | − | |
| 740 | −/* | |
| 741 | − * vpif_open: It creates object of file handle structure and stores it in | |
| 742 | − * private_data member of filepointer | |
| 743 | − */ | |
| 744 | −static int vpif_open(struct file *filep) | |
| 745 | −{ | |
| 746 | − struct video_device *vdev = video_devdata(filep); | |
| 747 | − struct channel_obj *ch = video_get_drvdata(vdev); | |
| 748 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 749 | − struct vpif_fh *fh; | |
| 750 | − | |
| 751 | − /* Allocate memory for the file handle object */ | |
| 752 | − fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); | |
| 753 | − if (fh == NULL) { | |
| 754 | − vpif_err("unable to allocate memory for file handle object\n"); | |
| 755 | − return -ENOMEM; | |
| 756 | − } | |
| 757 | − | |
| 758 | − if (mutex_lock_interruptible(&common->lock)) { | |
| 759 | − kfree(fh); | |
| 760 | − return -ERESTARTSYS; | |
| 761 | − } | |
| 762 | − /* store pointer to fh in private_data member of filep */ | |
| 763 | − filep->private_data = fh; | |
| 764 | − fh->channel = ch; | |
| 765 | − fh->initialized = 0; | |
| 766 | − if (!ch->initialized) { | |
| 767 | − fh->initialized = 1; | |
| 768 | − ch->initialized = 1; | |
| 769 | − memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); | |
| 770 | − } | |
| 771 | − | |
| 772 | − /* Increment channel usrs counter */ | |
| 773 | − atomic_inc(&ch->usrs); | |
| 774 | − /* Set io_allowed[VPIF_VIDEO_INDEX] member to false */ | |
| 775 | − fh->io_allowed[VPIF_VIDEO_INDEX] = 0; | |
| 776 | − /* Initialize priority of this instance to default priority */ | |
| 777 | − fh->prio = V4L2_PRIORITY_UNSET; | |
| 778 | − v4l2_prio_open(&ch->prio, &fh->prio); | |
| 779 | − mutex_unlock(&common->lock); | |
| 780 | − | |
| 781 | − return 0; | |
| 782 | −} | |
| 783 | − | |
| 784 | −/* | |
| 785 | − * vpif_release: This function deletes buffer queue, frees the buffers and | |
| 786 | − * the vpif file handle | |
| 787 | − */ | |
| 788 | −static int vpif_release(struct file *filep) | |
| 789 | −{ | |
| 790 | − struct vpif_fh *fh = filep->private_data; | |
| 791 | − struct channel_obj *ch = fh->channel; | |
| 792 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 793 | − | |
| 794 | − mutex_lock(&common->lock); | |
| 795 | − /* if this instance is doing IO */ | |
| 796 | − if (fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 797 | − /* Reset io_usrs member of channel object */ | |
| 798 | − common->io_usrs = 0; | |
| 799 | − /* Free buffers allocated */ | |
| 800 | − vb2_queue_release(&common->buffer_queue); | |
| 801 | − vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 802 | − | |
| 803 | − common->numbuffers = | |
| 804 | − config_params.numbuffers[ch->channel_id]; | |
| 805 | − } | |
| 806 | − | |
| 807 | − /* Decrement channel usrs counter */ | |
| 808 | − atomic_dec(&ch->usrs); | |
| 809 | − /* If this file handle has initialize encoder device, reset it */ | |
| 810 | − if (fh->initialized) | |
| 811 | − ch->initialized = 0; | |
| 812 | − | |
| 813 | − /* Close the priority */ | |
| 814 | − v4l2_prio_close(&ch->prio, fh->prio); | |
| 815 | − filep->private_data = NULL; | |
| 816 | − fh->initialized = 0; | |
| 817 | − mutex_unlock(&common->lock); | |
| 818 | − kfree(fh); | |
| 819 | − | |
| 820 | − return 0; | |
| 821 | −} | |
| 822 | − | |
| 823 | 574 | /* functions implementing ioctls */ |
| 824 | 575 | /** |
| 825 | 576 | * vpif_querycap() - QUERYCAP handler |
| @@ -834,7 +585,7 @@ static int vpif_querycap(struct file *file, void *priv, · 8 unmodified lines | ||
| 834 | 585 | |
| 835 | 586 | cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; |
| 836 | 587 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
| 837 | − snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); | |
| 588 | + strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); | |
| 838 | 589 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
| 839 | 590 | dev_name(vpif_dev)); |
| 840 | 591 | strlcpy(cap->card, config->card_name, sizeof(cap->card)); |
| @@ -845,24 +596,22 @@ static int vpif_querycap(struct file *file, void *priv, · 4 unmodified lines | ||
| 845 | 596 | static int vpif_enum_fmt_vid_out(struct file *file, void *priv, |
| 846 | 597 | struct v4l2_fmtdesc *fmt) |
| 847 | 598 | { |
| 848 | − if (fmt->index != 0) { | |
| 849 | − vpif_err("Invalid format index\n"); | |
| 599 | + if (fmt->index != 0) | |
| 850 | 600 | return -EINVAL; |
| 851 | − } | |
| 852 | 601 | |
| 853 | 602 | /* Fill in the information about format */ |
| 854 | 603 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
| 855 | 604 | strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); |
| 856 | 605 | fmt->pixelformat = V4L2_PIX_FMT_YUV422P; |
| 857 | − | |
| 606 | + fmt->flags = 0; | |
| 858 | 607 | return 0; |
| 859 | 608 | } |
| 860 | 609 | |
| 861 | 610 | static int vpif_g_fmt_vid_out(struct file *file, void *priv, |
| 862 | 611 | struct v4l2_format *fmt) |
| 863 | 612 | { |
| 864 | − struct vpif_fh *fh = priv; | |
| 865 | − struct channel_obj *ch = fh->channel; | |
| 613 | + struct video_device *vdev = video_devdata(file); | |
| 614 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 866 | 615 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 867 | 616 | |
| 868 | 617 | /* Check the validity of the buffer type */ |
| @@ -875,193 +624,84 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv, · 6 unmodified lines | ||
| 875 | 624 | return 0; |
| 876 | 625 | } |
| 877 | 626 | |
| 878 | −static int vpif_s_fmt_vid_out(struct file *file, void *priv, | |
| 627 | +static int vpif_try_fmt_vid_out(struct file *file, void *priv, | |
| 879 | 628 | struct v4l2_format *fmt) |
| 880 | 629 | { |
| 881 | − struct vpif_fh *fh = priv; | |
| 882 | − struct v4l2_pix_format *pixfmt; | |
| 883 | − struct channel_obj *ch = fh->channel; | |
| 630 | + struct video_device *vdev = video_devdata(file); | |
| 631 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 884 | 632 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 885 | − int ret = 0; | |
| 886 | − | |
| 887 | − if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) | |
| 888 | − || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { | |
| 889 | − if (!fh->initialized) { | |
| 890 | − vpif_dbg(1, debug, "Channel Busy\n"); | |
| 891 | − return -EBUSY; | |
| 892 | − } | |
| 633 | + struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | |
| 893 | 634 | |
| 894 | − /* Check for the priority */ | |
| 895 | − ret = v4l2_prio_check(&ch->prio, fh->prio); | |
| 896 | − if (0 != ret) | |
| 897 | − return ret; | |
| 898 | − fh->initialized = 1; | |
| 899 | − } | |
| 635 | + /* | |
| 636 | + * to supress v4l-compliance warnings silently correct | |
| 637 | + * the pixelformat | |
| 638 | + */ | |
| 639 | + if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) | |
| 640 | + pixfmt->pixelformat = common->fmt.fmt.pix.pixelformat; | |
| 900 | 641 | |
| 901 | − if (common->started) { | |
| 902 | − vpif_dbg(1, debug, "Streaming in progress\n"); | |
| 903 | − return -EBUSY; | |
| 904 | − } | |
| 642 | + if (vpif_update_resolution(ch)) | |
| 643 | + return -EINVAL; | |
| 905 | 644 | |
| 906 | − pixfmt = &fmt->fmt.pix; | |
| 907 | − /* Check for valid field format */ | |
| 908 | − ret = vpif_check_format(ch, pixfmt); | |
| 909 | − if (ret) | |
| 910 | − return ret; | |
| 645 | + pixfmt->colorspace = common->fmt.fmt.pix.colorspace; | |
| 646 | + pixfmt->field = common->fmt.fmt.pix.field; | |
| 647 | + pixfmt->bytesperline = common->fmt.fmt.pix.width; | |
| 648 | + pixfmt->width = common->fmt.fmt.pix.width; | |
| 649 | + pixfmt->height = common->fmt.fmt.pix.height; | |
| 650 | + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2; | |
| 651 | + pixfmt->priv = 0; | |
| 911 | 652 | |
| 912 | − /* store the pix format in the channel object */ | |
| 913 | − common->fmt.fmt.pix = *pixfmt; | |
| 914 | − /* store the format in the channel object */ | |
| 915 | − common->fmt = *fmt; | |
| 916 | 653 | return 0; |
| 917 | 654 | } |
| 918 | 655 | |
| 919 | −static int vpif_try_fmt_vid_out(struct file *file, void *priv, | |
| 656 | +static int vpif_s_fmt_vid_out(struct file *file, void *priv, | |
| 920 | 657 | struct v4l2_format *fmt) |
| 921 | 658 | { |
| 922 | − struct vpif_fh *fh = priv; | |
| 923 | − struct channel_obj *ch = fh->channel; | |
| 659 | + struct video_device *vdev = video_devdata(file); | |
| 660 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 924 | 661 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 925 | 662 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; |
| 926 | − int ret = 0; | |
| 927 | − | |
| 928 | − ret = vpif_check_format(ch, pixfmt); | |
| 929 | − if (ret) { | |
| 930 | − *pixfmt = common->fmt.fmt.pix; | |
| 931 | − pixfmt->sizeimage = pixfmt->width * pixfmt->height * 2; | |
| 932 | − } | |
| 933 | − | |
| 934 | − return ret; | |
| 935 | −} | |
| 936 | − | |
| 937 | −static int vpif_reqbufs(struct file *file, void *priv, | |
| 938 | − struct v4l2_requestbuffers *reqbuf) | |
| 939 | −{ | |
| 940 | − struct vpif_fh *fh = priv; | |
| 941 | − struct channel_obj *ch = fh->channel; | |
| 942 | − struct common_obj *common; | |
| 943 | − enum v4l2_field field; | |
| 944 | − struct vb2_queue *q; | |
| 945 | − u8 index = 0; | |
| 946 | 663 | int ret; |
| 947 | 664 | |
| 948 | − /* This file handle has not initialized the channel, | |
| 949 | − It is not allowed to do settings */ | |
| 950 | − if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) | |
| 951 | − || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { | |
| 952 | − if (!fh->initialized) { | |
| 953 | − vpif_err("Channel Busy\n"); | |
| 954 | − return -EBUSY; | |
| 955 | − } | |
| 956 | − } | |
| 957 | − | |
| 958 | − if (V4L2_BUF_TYPE_VIDEO_OUTPUT != reqbuf->type) | |
| 959 | − return -EINVAL; | |
| 960 | − | |
| 961 | − index = VPIF_VIDEO_INDEX; | |
| 962 | − | |
| 963 | − common = &ch->common[index]; | |
| 964 | − | |
| 965 | − if (common->fmt.type != reqbuf->type || !vpif_dev) | |
| 966 | − return -EINVAL; | |
| 967 | − if (0 != common->io_usrs) | |
| 665 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 968 | 666 | return -EBUSY; |
| 969 | 667 | |
| 970 | − if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
| 971 | − if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY) | |
| 972 | − field = V4L2_FIELD_INTERLACED; | |
| 973 | − else | |
| 974 | − field = common->fmt.fmt.pix.field; | |
| 975 | − } else { | |
| 976 | − field = V4L2_VBI_INTERLACED; | |
| 977 | − } | |
| 978 | − /* Initialize videobuf2 queue as per the buffer type */ | |
| 979 | − common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); | |
| 980 | − if (IS_ERR(common->alloc_ctx)) { | |
| 981 | − vpif_err("Failed to get the context\n"); | |
| 982 | − return PTR_ERR(common->alloc_ctx); | |
| 983 | − } | |
| 984 | − q = &common->buffer_queue; | |
| 985 | − q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | |
| 986 | − q->io_modes = VB2_MMAP | VB2_USERPTR; | |
| 987 | − q->drv_priv = fh; | |
| 988 | − q->ops = &video_qops; | |
| 989 | − q->mem_ops = &vb2_dma_contig_memops; | |
| 990 | − q->buf_struct_size = sizeof(struct vpif_disp_buffer); | |
| 991 | − q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 992 | − q->min_buffers_needed = 1; | |
| 993 | − | |
| 994 | − ret = vb2_queue_init(q); | |
| 995 | − if (ret) { | |
| 996 | − vpif_err("vpif_display: vb2_queue_init() failed\n"); | |
| 997 | − vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 668 | + ret = vpif_try_fmt_vid_out(file, priv, fmt); | |
| 669 | + if (ret) | |
| 998 | 670 | return ret; |
| 999 | − } | |
| 1000 | − /* Set io allowed member of file handle to TRUE */ | |
| 1001 | − fh->io_allowed[index] = 1; | |
| 1002 | − /* Increment io usrs member of channel object to 1 */ | |
| 1003 | − common->io_usrs = 1; | |
| 1004 | − /* Store type of memory requested in channel object */ | |
| 1005 | − common->memory = reqbuf->memory; | |
| 1006 | − INIT_LIST_HEAD(&common->dma_queue); | |
| 1007 | − /* Allocate buffers */ | |
| 1008 | − return vb2_reqbufs(&common->buffer_queue, reqbuf); | |
| 1009 | −} | |
| 1010 | − | |
| 1011 | −static int vpif_querybuf(struct file *file, void *priv, | |
| 1012 | − struct v4l2_buffer *tbuf) | |
| 1013 | −{ | |
| 1014 | − struct vpif_fh *fh = priv; | |
| 1015 | − struct channel_obj *ch = fh->channel; | |
| 1016 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1017 | 671 | |
| 1018 | − if (common->fmt.type != tbuf->type) | |
| 1019 | − return -EINVAL; | |
| 672 | + /* store the pix format in the channel object */ | |
| 673 | + common->fmt.fmt.pix = *pixfmt; | |
| 1020 | 674 | |
| 1021 | − return vb2_querybuf(&common->buffer_queue, tbuf); | |
| 675 | + /* store the format in the channel object */ | |
| 676 | + common->fmt = *fmt; | |
| 677 | + return 0; | |
| 1022 | 678 | } |
| 1023 | 679 | |
| 1024 | −static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
| 680 | +static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) | |
| 1025 | 681 | { |
| 1026 | − struct vpif_fh *fh = NULL; | |
| 1027 | − struct channel_obj *ch = NULL; | |
| 1028 | − struct common_obj *common = NULL; | |
| 1029 | − | |
| 1030 | − if (!buf || !priv) | |
| 1031 | − return -EINVAL; | |
| 1032 | − | |
| 1033 | − fh = priv; | |
| 1034 | − ch = fh->channel; | |
| 1035 | − if (!ch) | |
| 1036 | − return -EINVAL; | |
| 682 | + struct vpif_display_config *config = vpif_dev->platform_data; | |
| 683 | + struct video_device *vdev = video_devdata(file); | |
| 684 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 685 | + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 686 | + struct vpif_display_chan_config *chan_cfg; | |
| 687 | + struct v4l2_output output; | |
| 688 | + int ret; | |
| 1037 | 689 | |
| 1038 | − common = &(ch->common[VPIF_VIDEO_INDEX]); | |
| 1039 | − if (common->fmt.type != buf->type) | |
| 1040 | − return -EINVAL; | |
| 690 | + if (config->chan_config[ch->channel_id].outputs == NULL) | |
| 691 | + return -ENODATA; | |
| 1041 | 692 | |
| 1042 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1043 | − vpif_err("fh->io_allowed\n"); | |
| 1044 | − return -EACCES; | |
| 1045 | − } | |
| 693 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 694 | + output = chan_cfg->outputs[ch->output_idx].output; | |
| 695 | + if (output.capabilities != V4L2_OUT_CAP_STD) | |
| 696 | + return -ENODATA; | |
| 1046 | 697 | |
| 1047 | − return vb2_qbuf(&common->buffer_queue, buf); | |
| 1048 | −} | |
| 698 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 699 | + return -EBUSY; | |
| 1049 | 700 | |
| 1050 | −static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) | |
| 1051 | −{ | |
| 1052 | − struct vpif_fh *fh = priv; | |
| 1053 | − struct channel_obj *ch = fh->channel; | |
| 1054 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1055 | − int ret = 0; | |
| 1056 | 701 | |
| 1057 | 702 | if (!(std_id & VPIF_V4L2_STD)) |
| 1058 | 703 | return -EINVAL; |
| 1059 | 704 | |
| 1060 | − if (common->started) { | |
| 1061 | − vpif_err("streaming in progress\n"); | |
| 1062 | − return -EBUSY; | |
| 1063 | − } | |
| 1064 | − | |
| 1065 | 705 | /* Call encoder subdevice function to set the standard */ |
| 1066 | 706 | ch->video.stdid = std_id; |
| 1067 | 707 | memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); |
| @@ -1069,16 +709,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) · 1 unmodified line | ||
| 1069 | 709 | if (vpif_update_resolution(ch)) |
| 1070 | 710 | return -EINVAL; |
| 1071 | 711 | |
| 1072 | − if ((ch->vpifparams.std_info.width * | |
| 1073 | − ch->vpifparams.std_info.height * 2) > | |
| 1074 | − config_params.channel_bufsize[ch->channel_id]) { | |
| 1075 | − vpif_err("invalid std for this size\n"); | |
| 1076 | − return -EINVAL; | |
| 1077 | − } | |
| 1078 | − | |
| 1079 | 712 | common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width; |
| 1080 | − /* Configure the default format information */ | |
| 1081 | − vpif_config_format(ch); | |
| 1082 | 713 | |
| 1083 | 714 | ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, |
| 1084 | 715 | s_std_output, std_id); |
| @@ -1087,7 +718,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) · 2 unmodified lines | ||
| 1087 | 718 | return ret; |
| 1088 | 719 | } |
| 1089 | 720 | |
| 1090 | − ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core, | |
| 721 | + ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, | |
| 1091 | 722 | s_std, std_id); |
| 1092 | 723 | if (ret < 0) |
| 1093 | 724 | vpif_err("Failed to set standard for sub devices\n"); |
| @@ -1096,132 +727,21 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) · 2 unmodified lines | ||
| 1096 | 727 | |
| 1097 | 728 | static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) |
| 1098 | 729 | { |
| 1099 | − struct vpif_fh *fh = priv; | |
| 1100 | − struct channel_obj *ch = fh->channel; | |
| 1101 | − | |
| 1102 | − *std = ch->video.stdid; | |
| 1103 | − return 0; | |
| 1104 | −} | |
| 1105 | − | |
| 1106 | −static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | |
| 1107 | −{ | |
| 1108 | − struct vpif_fh *fh = priv; | |
| 1109 | − struct channel_obj *ch = fh->channel; | |
| 1110 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1111 | − | |
| 1112 | − return vb2_dqbuf(&common->buffer_queue, p, | |
| 1113 | − (file->f_flags & O_NONBLOCK)); | |
| 1114 | −} | |
| 1115 | − | |
| 1116 | −static int vpif_streamon(struct file *file, void *priv, | |
| 1117 | − enum v4l2_buf_type buftype) | |
| 1118 | −{ | |
| 1119 | − struct vpif_fh *fh = priv; | |
| 1120 | − struct channel_obj *ch = fh->channel; | |
| 1121 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1122 | − struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; | |
| 1123 | − int ret = 0; | |
| 1124 | − | |
| 1125 | − if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
| 1126 | − vpif_err("buffer type not supported\n"); | |
| 1127 | − return -EINVAL; | |
| 1128 | − } | |
| 1129 | − | |
| 1130 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1131 | − vpif_err("fh->io_allowed\n"); | |
| 1132 | − return -EACCES; | |
| 1133 | − } | |
| 1134 | − | |
| 1135 | − /* If Streaming is already started, return error */ | |
| 1136 | − if (common->started) { | |
| 1137 | − vpif_err("channel->started\n"); | |
| 1138 | − return -EBUSY; | |
| 1139 | − } | |
| 1140 | − | |
| 1141 | − if ((ch->channel_id == VPIF_CHANNEL2_VIDEO | |
| 1142 | − && oth_ch->common[VPIF_VIDEO_INDEX].started && | |
| 1143 | − ch->vpifparams.std_info.ycmux_mode == 0) | |
| 1144 | − || ((ch->channel_id == VPIF_CHANNEL3_VIDEO) | |
| 1145 | − && (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) { | |
| 1146 | − vpif_err("other channel is using\n"); | |
| 1147 | − return -EBUSY; | |
| 1148 | − } | |
| 1149 | − | |
| 1150 | − ret = vpif_check_format(ch, &common->fmt.fmt.pix); | |
| 1151 | − if (ret < 0) | |
| 1152 | − return ret; | |
| 1153 | − | |
| 1154 | − /* Call vb2_streamon to start streaming in videobuf2 */ | |
| 1155 | − ret = vb2_streamon(&common->buffer_queue, buftype); | |
| 1156 | − if (ret < 0) { | |
| 1157 | − vpif_err("vb2_streamon\n"); | |
| 1158 | − return ret; | |
| 1159 | − } | |
| 1160 | − | |
| 1161 | − return ret; | |
| 1162 | −} | |
| 1163 | − | |
| 1164 | −static int vpif_streamoff(struct file *file, void *priv, | |
| 1165 | − enum v4l2_buf_type buftype) | |
| 1166 | −{ | |
| 1167 | − struct vpif_fh *fh = priv; | |
| 1168 | − struct channel_obj *ch = fh->channel; | |
| 1169 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1170 | − struct vpif_display_config *vpif_config_data = | |
| 1171 | − vpif_dev->platform_data; | |
| 1172 | − | |
| 1173 | − if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
| 1174 | − vpif_err("buffer type not supported\n"); | |
| 1175 | − return -EINVAL; | |
| 1176 | − } | |
| 1177 | − | |
| 1178 | − if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { | |
| 1179 | − vpif_err("fh->io_allowed\n"); | |
| 1180 | − return -EACCES; | |
| 1181 | − } | |
| 1182 | − | |
| 1183 | − if (!common->started) { | |
| 1184 | − vpif_err("channel->started\n"); | |
| 1185 | − return -EINVAL; | |
| 1186 | − } | |
| 1187 | − | |
| 1188 | − if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
| 1189 | − /* disable channel */ | |
| 1190 | − if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { | |
| 1191 | − if (vpif_config_data-> | |
| 1192 | − chan_config[VPIF_CHANNEL2_VIDEO].clip_en) | |
| 1193 | − channel2_clipping_enable(0); | |
| 1194 | − enable_channel2(0); | |
| 1195 | − channel2_intr_enable(0); | |
| 1196 | − } | |
| 1197 | − if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || | |
| 1198 | − (2 == common->started)) { | |
| 1199 | − if (vpif_config_data-> | |
| 1200 | − chan_config[VPIF_CHANNEL3_VIDEO].clip_en) | |
| 1201 | − channel3_clipping_enable(0); | |
| 1202 | − enable_channel3(0); | |
| 1203 | − channel3_intr_enable(0); | |
| 1204 | − } | |
| 1205 | − } | |
| 1206 | − | |
| 1207 | − common->started = 0; | |
| 1208 | − return vb2_streamoff(&common->buffer_queue, buftype); | |
| 1209 | −} | |
| 730 | + struct vpif_display_config *config = vpif_dev->platform_data; | |
| 731 | + struct video_device *vdev = video_devdata(file); | |
| 732 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 733 | + struct vpif_display_chan_config *chan_cfg; | |
| 734 | + struct v4l2_output output; | |
| 1210 | 735 | |
| 1211 | −static int vpif_cropcap(struct file *file, void *priv, | |
| 1212 | − struct v4l2_cropcap *crop) | |
| 1213 | −{ | |
| 1214 | − struct vpif_fh *fh = priv; | |
| 1215 | − struct channel_obj *ch = fh->channel; | |
| 1216 | − struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1217 | − if (V4L2_BUF_TYPE_VIDEO_OUTPUT != crop->type) | |
| 1218 | − return -EINVAL; | |
| 736 | + if (config->chan_config[ch->channel_id].outputs == NULL) | |
| 737 | + return -ENODATA; | |
| 1219 | 738 | |
| 1220 | − crop->bounds.left = crop->bounds.top = 0; | |
| 1221 | − crop->defrect.left = crop->defrect.top = 0; | |
| 1222 | − crop->defrect.height = crop->bounds.height = common->height; | |
| 1223 | − crop->defrect.width = crop->bounds.width = common->width; | |
| 739 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 740 | + output = chan_cfg->outputs[ch->output_idx].output; | |
| 741 | + if (output.capabilities != V4L2_OUT_CAP_STD) | |
| 742 | + return -ENODATA; | |
| 1224 | 743 | |
| 744 | + *std = ch->video.stdid; | |
| 1225 | 745 | return 0; |
| 1226 | 746 | } |
| 1227 | 747 | |
| @@ -1230,9 +750,9 @@ static int vpif_enum_output(struct file *file, void *fh, · 2 unmodified lines | ||
| 1230 | 750 | { |
| 1231 | 751 | |
| 1232 | 752 | struct vpif_display_config *config = vpif_dev->platform_data; |
| 753 | + struct video_device *vdev = video_devdata(file); | |
| 754 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1233 | 755 | struct vpif_display_chan_config *chan_cfg; |
| 1234 | − struct vpif_fh *vpif_handler = fh; | |
| 1235 | − struct channel_obj *ch = vpif_handler->channel; | |
| 1236 | 756 | |
| 1237 | 757 | chan_cfg = &config->chan_config[ch->channel_id]; |
| 1238 | 758 | if (output->index >= chan_cfg->output_count) { |
| @@ -1326,52 +846,32 @@ static int vpif_set_output(struct vpif_display_config *vpif_cfg, · 87 unmodified lines | ||
| 1326 | 846 | static int vpif_s_output(struct file *file, void *priv, unsigned int i) |
| 1327 | 847 | { |
| 1328 | 848 | struct vpif_display_config *config = vpif_dev->platform_data; |
| 849 | + struct video_device *vdev = video_devdata(file); | |
| 850 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1329 | 851 | struct vpif_display_chan_config *chan_cfg; |
| 1330 | − struct vpif_fh *fh = priv; | |
| 1331 | − struct channel_obj *ch = fh->channel; | |
| 1332 | 852 | struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1333 | 853 | |
| 854 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 855 | + return -EBUSY; | |
| 856 | + | |
| 1334 | 857 | chan_cfg = &config->chan_config[ch->channel_id]; |
| 1335 | 858 | |
| 1336 | 859 | if (i >= chan_cfg->output_count) |
| 1337 | 860 | return -EINVAL; |
| 1338 | 861 | |
| 1339 | − if (common->started) { | |
| 1340 | − vpif_err("Streaming in progress\n"); | |
| 1341 | − return -EBUSY; | |
| 1342 | − } | |
| 1343 | − | |
| 1344 | 862 | return vpif_set_output(config, ch, i); |
| 1345 | 863 | } |
| 1346 | 864 | |
| 1347 | 865 | static int vpif_g_output(struct file *file, void *priv, unsigned int *i) |
| 1348 | 866 | { |
| 1349 | − struct vpif_fh *fh = priv; | |
| 1350 | − struct channel_obj *ch = fh->channel; | |
| 867 | + struct video_device *vdev = video_devdata(file); | |
| 868 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1351 | 869 | |
| 1352 | 870 | *i = ch->output_idx; |
| 1353 | 871 | |
| 1354 | 872 | return 0; |
| 1355 | 873 | } |
| 1356 | 874 | |
| 1357 | −static int vpif_g_priority(struct file *file, void *priv, enum v4l2_priority *p) | |
| 1358 | −{ | |
| 1359 | − struct vpif_fh *fh = priv; | |
| 1360 | − struct channel_obj *ch = fh->channel; | |
| 1361 | − | |
| 1362 | − *p = v4l2_prio_max(&ch->prio); | |
| 1363 | − | |
| 1364 | − return 0; | |
| 1365 | −} | |
| 1366 | − | |
| 1367 | −static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) | |
| 1368 | −{ | |
| 1369 | − struct vpif_fh *fh = priv; | |
| 1370 | − struct channel_obj *ch = fh->channel; | |
| 1371 | − | |
| 1372 | − return v4l2_prio_change(&ch->prio, &fh->prio, p); | |
| 1373 | −} | |
| 1374 | − | |
| 1375 | 875 | /** |
| 1376 | 876 | * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler |
| 1377 | 877 | * @file: file ptr |
| @@ -1382,11 +882,24 @@ static int · 4 unmodified lines | ||
| 1382 | 882 | vpif_enum_dv_timings(struct file *file, void *priv, |
| 1383 | 883 | struct v4l2_enum_dv_timings *timings) |
| 1384 | 884 | { |
| 1385 | − struct vpif_fh *fh = priv; | |
| 1386 | − struct channel_obj *ch = fh->channel; | |
| 885 | + struct vpif_display_config *config = vpif_dev->platform_data; | |
| 886 | + struct video_device *vdev = video_devdata(file); | |
| 887 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 888 | + struct vpif_display_chan_config *chan_cfg; | |
| 889 | + struct v4l2_output output; | |
| 1387 | 890 | int ret; |
| 1388 | 891 | |
| 1389 | − ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); | |
| 892 | + if (config->chan_config[ch->channel_id].outputs == NULL) | |
| 893 | + return -ENODATA; | |
| 894 | + | |
| 895 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 896 | + output = chan_cfg->outputs[ch->output_idx].output; | |
| 897 | + if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) | |
| 898 | + return -ENODATA; | |
| 899 | + | |
| 900 | + timings->pad = 0; | |
| 901 | + | |
| 902 | + ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings); | |
| 1390 | 903 | if (ret == -ENOIOCTLCMD || ret == -ENODEV) |
| 1391 | 904 | return -EINVAL; |
| 1392 | 905 | return ret; |
| @@ -1401,14 +914,29 @@ vpif_enum_dv_timings(struct file *file, void *priv, · 8 unmodified lines | ||
| 1401 | 914 | static int vpif_s_dv_timings(struct file *file, void *priv, |
| 1402 | 915 | struct v4l2_dv_timings *timings) |
| 1403 | 916 | { |
| 1404 | − struct vpif_fh *fh = priv; | |
| 1405 | − struct channel_obj *ch = fh->channel; | |
| 917 | + struct vpif_display_config *config = vpif_dev->platform_data; | |
| 918 | + struct video_device *vdev = video_devdata(file); | |
| 919 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1406 | 920 | struct vpif_params *vpifparams = &ch->vpifparams; |
| 921 | + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; | |
| 1407 | 922 | struct vpif_channel_config_params *std_info = &vpifparams->std_info; |
| 1408 | 923 | struct video_obj *vid_ch = &ch->video; |
| 1409 | 924 | struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; |
| 925 | + struct vpif_display_chan_config *chan_cfg; | |
| 926 | + struct v4l2_output output; | |
| 1410 | 927 | int ret; |
| 1411 | 928 | |
| 929 | + if (config->chan_config[ch->channel_id].outputs == NULL) | |
| 930 | + return -ENODATA; | |
| 931 | + | |
| 932 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 933 | + output = chan_cfg->outputs[ch->output_idx].output; | |
| 934 | + if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) | |
| 935 | + return -ENODATA; | |
| 936 | + | |
| 937 | + if (vb2_is_busy(&common->buffer_queue)) | |
| 938 | + return -EBUSY; | |
| 939 | + | |
| 1412 | 940 | if (timings->type != V4L2_DV_BT_656_1120) { |
| 1413 | 941 | vpif_dbg(2, debug, "Timing type not defined\n"); |
| 1414 | 942 | return -EINVAL; |
| @@ -1490,13 +1018,27 @@ static int vpif_s_dv_timings(struct file *file, void *priv, · 75 unmodified lines | ||
| 1490 | 1018 | static int vpif_g_dv_timings(struct file *file, void *priv, |
| 1491 | 1019 | struct v4l2_dv_timings *timings) |
| 1492 | 1020 | { |
| 1493 | − struct vpif_fh *fh = priv; | |
| 1494 | − struct channel_obj *ch = fh->channel; | |
| 1021 | + struct vpif_display_config *config = vpif_dev->platform_data; | |
| 1022 | + struct video_device *vdev = video_devdata(file); | |
| 1023 | + struct channel_obj *ch = video_get_drvdata(vdev); | |
| 1024 | + struct vpif_display_chan_config *chan_cfg; | |
| 1495 | 1025 | struct video_obj *vid_ch = &ch->video; |
| 1026 | + struct v4l2_output output; | |
| 1027 | + | |
| 1028 | + if (config->chan_config[ch->channel_id].outputs == NULL) | |
| 1029 | + goto error; | |
| 1030 | + | |
| 1031 | + chan_cfg = &config->chan_config[ch->channel_id]; | |
| 1032 | + output = chan_cfg->outputs[ch->output_idx].output; | |
| 1033 | + | |
| 1034 | + if (output.capabilities != V4L2_OUT_CAP_DV_TIMINGS) | |
| 1035 | + goto error; | |
| 1496 | 1036 | |
| 1497 | 1037 | *timings = vid_ch->dv_timings; |
| 1498 | 1038 | |
| 1499 | 1039 | return 0; |
| 1040 | +error: | |
| 1041 | + return -ENODATA; | |
| 1500 | 1042 | } |
| 1501 | 1043 | |
| 1502 | 1044 | /* |
| @@ -1516,83 +1058,49 @@ static int vpif_log_status(struct file *filep, void *priv) · 13 unmodified lines | ||
| 1516 | 1058 | |
| 1517 | 1059 | /* vpif display ioctl operations */ |
| 1518 | 1060 | static const struct v4l2_ioctl_ops vpif_ioctl_ops = { |
| 1519 | − .vidioc_querycap = vpif_querycap, | |
| 1520 | − .vidioc_g_priority = vpif_g_priority, | |
| 1521 | − .vidioc_s_priority = vpif_s_priority, | |
| 1061 | + .vidioc_querycap = vpif_querycap, | |
| 1522 | 1062 | .vidioc_enum_fmt_vid_out = vpif_enum_fmt_vid_out, |
| 1523 | − .vidioc_g_fmt_vid_out = vpif_g_fmt_vid_out, | |
| 1524 | − .vidioc_s_fmt_vid_out = vpif_s_fmt_vid_out, | |
| 1525 | − .vidioc_try_fmt_vid_out = vpif_try_fmt_vid_out, | |
| 1526 | − .vidioc_reqbufs = vpif_reqbufs, | |
| 1527 | − .vidioc_querybuf = vpif_querybuf, | |
| 1528 | − .vidioc_qbuf = vpif_qbuf, | |
| 1529 | − .vidioc_dqbuf = vpif_dqbuf, | |
| 1530 | − .vidioc_streamon = vpif_streamon, | |
| 1531 | − .vidioc_streamoff = vpif_streamoff, | |
| 1532 | − .vidioc_s_std = vpif_s_std, | |
| 1063 | + .vidioc_g_fmt_vid_out = vpif_g_fmt_vid_out, | |
| 1064 | + .vidioc_s_fmt_vid_out = vpif_s_fmt_vid_out, | |
| 1065 | + .vidioc_try_fmt_vid_out = vpif_try_fmt_vid_out, | |
| 1066 | + | |
| 1067 | + .vidioc_reqbufs = vb2_ioctl_reqbufs, | |
| 1068 | + .vidioc_create_bufs = vb2_ioctl_create_bufs, | |
| 1069 | + .vidioc_querybuf = vb2_ioctl_querybuf, | |
| 1070 | + .vidioc_qbuf = vb2_ioctl_qbuf, | |
| 1071 | + .vidioc_dqbuf = vb2_ioctl_dqbuf, | |
| 1072 | + .vidioc_expbuf = vb2_ioctl_expbuf, | |
| 1073 | + .vidioc_streamon = vb2_ioctl_streamon, | |
| 1074 | + .vidioc_streamoff = vb2_ioctl_streamoff, | |
| 1075 | + | |
| 1076 | + .vidioc_s_std = vpif_s_std, | |
| 1533 | 1077 | .vidioc_g_std = vpif_g_std, |
| 1078 | + | |
| 1534 | 1079 | .vidioc_enum_output = vpif_enum_output, |
| 1535 | 1080 | .vidioc_s_output = vpif_s_output, |
| 1536 | 1081 | .vidioc_g_output = vpif_g_output, |
| 1537 | − .vidioc_cropcap = vpif_cropcap, | |
| 1538 | − .vidioc_enum_dv_timings = vpif_enum_dv_timings, | |
| 1539 | − .vidioc_s_dv_timings = vpif_s_dv_timings, | |
| 1540 | − .vidioc_g_dv_timings = vpif_g_dv_timings, | |
| 1082 | + | |
| 1083 | + .vidioc_enum_dv_timings = vpif_enum_dv_timings, | |
| 1084 | + .vidioc_s_dv_timings = vpif_s_dv_timings, | |
| 1085 | + .vidioc_g_dv_timings = vpif_g_dv_timings, | |
| 1086 | + | |
| 1541 | 1087 | .vidioc_log_status = vpif_log_status, |
| 1542 | 1088 | }; |
| 1543 | 1089 | |
| 1544 | 1090 | static const struct v4l2_file_operations vpif_fops = { |
| 1545 | 1091 | .owner = THIS_MODULE, |
| 1546 | − .open = vpif_open, | |
| 1547 | − .release = vpif_release, | |
| 1092 | + .open = v4l2_fh_open, | |
| 1093 | + .release = vb2_fop_release, | |
| 1548 | 1094 | .unlocked_ioctl = video_ioctl2, |
| 1549 | − .mmap = vpif_mmap, | |
| 1550 | − .poll = vpif_poll | |
| 1551 | −}; | |
| 1552 | − | |
| 1553 | −static struct video_device vpif_video_template = { | |
| 1554 | − .name = "vpif", | |
| 1555 | − .fops = &vpif_fops, | |
| 1556 | − .ioctl_ops = &vpif_ioctl_ops, | |
| 1095 | + .mmap = vb2_fop_mmap, | |
| 1096 | + .poll = vb2_fop_poll | |
| 1557 | 1097 | }; |
| 1558 | 1098 | |
| 1559 | 1099 | /*Configure the channels, buffer sizei, request irq */ |
| 1560 | 1100 | static int initialize_vpif(void) |
| 1561 | 1101 | { |
| 1562 | 1102 | int free_channel_objects_index; |
| 1563 | − int free_buffer_channel_index; | |
| 1564 | − int free_buffer_index; | |
| 1565 | − int err = 0, i, j; | |
| 1566 | − | |
| 1567 | − /* Default number of buffers should be 3 */ | |
| 1568 | − if ((ch2_numbuffers > 0) && | |
| 1569 | − (ch2_numbuffers < config_params.min_numbuffers)) | |
| 1570 | − ch2_numbuffers = config_params.min_numbuffers; | |
| 1571 | − if ((ch3_numbuffers > 0) && | |
| 1572 | − (ch3_numbuffers < config_params.min_numbuffers)) | |
| 1573 | − ch3_numbuffers = config_params.min_numbuffers; | |
| 1574 | − | |
| 1575 | − /* Set buffer size to min buffers size if invalid buffer size is | |
| 1576 | − * given */ | |
| 1577 | − if (ch2_bufsize < config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]) | |
| 1578 | − ch2_bufsize = | |
| 1579 | − config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]; | |
| 1580 | − if (ch3_bufsize < config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]) | |
| 1581 | − ch3_bufsize = | |
| 1582 | − config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]; | |
| 1583 | − | |
| 1584 | − config_params.numbuffers[VPIF_CHANNEL2_VIDEO] = ch2_numbuffers; | |
| 1585 | − | |
| 1586 | − if (ch2_numbuffers) { | |
| 1587 | − config_params.channel_bufsize[VPIF_CHANNEL2_VIDEO] = | |
| 1588 | − ch2_bufsize; | |
| 1589 | − } | |
| 1590 | − config_params.numbuffers[VPIF_CHANNEL3_VIDEO] = ch3_numbuffers; | |
| 1591 | − | |
| 1592 | − if (ch3_numbuffers) { | |
| 1593 | − config_params.channel_bufsize[VPIF_CHANNEL3_VIDEO] = | |
| 1594 | − ch3_bufsize; | |
| 1595 | − } | |
| 1103 | + int err, i, j; | |
| 1596 | 1104 | |
| 1597 | 1105 | /* Allocate memory for six channel objects */ |
| 1598 | 1106 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { |
| @@ -1606,10 +1114,6 @@ static int initialize_vpif(void) · 7 unmodified lines | ||
| 1606 | 1114 | } |
| 1607 | 1115 | } |
| 1608 | 1116 | |
| 1609 | − free_channel_objects_index = VPIF_DISPLAY_MAX_DEVICES; | |
| 1610 | − free_buffer_channel_index = VPIF_DISPLAY_NUM_CHANNELS; | |
| 1611 | − free_buffer_index = config_params.numbuffers[i - 1]; | |
| 1612 | − | |
| 1613 | 1117 | return 0; |
| 1614 | 1118 | |
| 1615 | 1119 | vpif_init_free_channel_objects: |
| @@ -1638,21 +1142,18 @@ static int vpif_async_bound(struct v4l2_async_notifier *notifier, · 22 unmodified lines | ||
| 1638 | 1142 | static int vpif_probe_complete(void) |
| 1639 | 1143 | { |
| 1640 | 1144 | struct common_obj *common; |
| 1145 | + struct video_device *vdev; | |
| 1641 | 1146 | struct channel_obj *ch; |
| 1147 | + struct vb2_queue *q; | |
| 1642 | 1148 | int j, err, k; |
| 1643 | 1149 | |
| 1644 | 1150 | for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { |
| 1645 | 1151 | ch = vpif_obj.dev[j]; |
| 1646 | 1152 | /* Initialize field of the channel objects */ |
| 1647 | − atomic_set(&ch->usrs, 0); | |
| 1648 | 1153 | for (k = 0; k < VPIF_NUMOBJECTS; k++) { |
| 1649 | − ch->common[k].numbuffers = 0; | |
| 1650 | 1154 | common = &ch->common[k]; |
| 1651 | − common->io_usrs = 0; | |
| 1652 | − common->started = 0; | |
| 1653 | 1155 | spin_lock_init(&common->irqlock); |
| 1654 | 1156 | mutex_init(&common->lock); |
| 1655 | − common->numbuffers = 0; | |
| 1656 | 1157 | common->set_addr = NULL; |
| 1657 | 1158 | common->ytop_off = 0; |
| 1658 | 1159 | common->ybtm_off = 0; |
| @@ -1661,38 +1162,71 @@ static int vpif_probe_complete(void) · 2 unmodified lines | ||
| 1661 | 1162 | common->cur_frm = NULL; |
| 1662 | 1163 | common->next_frm = NULL; |
| 1663 | 1164 | memset(&common->fmt, 0, sizeof(common->fmt)); |
| 1664 | − common->numbuffers = config_params.numbuffers[k]; | |
| 1665 | 1165 | } |
| 1666 | 1166 | ch->initialized = 0; |
| 1667 | 1167 | if (vpif_obj.config->subdev_count) |
| 1668 | 1168 | ch->sd = vpif_obj.sd[0]; |
| 1669 | 1169 | ch->channel_id = j; |
| 1670 | − if (j < 2) | |
| 1671 | − ch->common[VPIF_VIDEO_INDEX].numbuffers = | |
| 1672 | − config_params.numbuffers[ch->channel_id]; | |
| 1673 | − else | |
| 1674 | − ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; | |
| 1675 | 1170 | |
| 1676 | 1171 | memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); |
| 1677 | 1172 | |
| 1678 | − /* Initialize prio member of channel object */ | |
| 1679 | − v4l2_prio_init(&ch->prio); | |
| 1680 | 1173 | ch->common[VPIF_VIDEO_INDEX].fmt.type = |
| 1681 | 1174 | V4L2_BUF_TYPE_VIDEO_OUTPUT; |
| 1682 | − ch->video_dev->lock = &common->lock; | |
| 1683 | − video_set_drvdata(ch->video_dev, ch); | |
| 1684 | 1175 | |
| 1685 | 1176 | /* select output 0 */ |
| 1686 | 1177 | err = vpif_set_output(vpif_obj.config, ch, 0); |
| 1687 | 1178 | if (err) |
| 1688 | 1179 | goto probe_out; |
| 1689 | 1180 | |
| 1181 | + /* set initial format */ | |
| 1182 | + ch->video.stdid = V4L2_STD_525_60; | |
| 1183 | + memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); | |
| 1184 | + vpif_update_resolution(ch); | |
| 1185 | + | |
| 1186 | + /* Initialize vb2 queue */ | |
| 1187 | + q = &common->buffer_queue; | |
| 1188 | + q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | |
| 1189 | + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; | |
| 1190 | + q->drv_priv = ch; | |
| 1191 | + q->ops = &video_qops; | |
| 1192 | + q->mem_ops = &vb2_dma_contig_memops; | |
| 1193 | + q->buf_struct_size = sizeof(struct vpif_disp_buffer); | |
| 1194 | + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
| 1195 | + q->min_buffers_needed = 1; | |
| 1196 | + q->lock = &common->lock; | |
| 1197 | + err = vb2_queue_init(q); | |
| 1198 | + if (err) { | |
| 1199 | + vpif_err("vpif_display: vb2_queue_init() failed\n"); | |
| 1200 | + goto probe_out; | |
| 1201 | + } | |
| 1202 | + | |
| 1203 | + common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); | |
| 1204 | + if (IS_ERR(common->alloc_ctx)) { | |
| 1205 | + vpif_err("Failed to get the context\n"); | |
| 1206 | + err = PTR_ERR(common->alloc_ctx); | |
| 1207 | + goto probe_out; | |
| 1208 | + } | |
| 1209 | + | |
| 1210 | + INIT_LIST_HEAD(&common->dma_queue); | |
| 1211 | + | |
| 1690 | 1212 | /* register video device */ |
| 1691 | 1213 | vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", |
| 1692 | 1214 | (int)ch, (int)&ch->video_dev); |
| 1693 | 1215 | |
| 1694 | − err = video_register_device(ch->video_dev, | |
| 1695 | − VFL_TYPE_GRABBER, (j ? 3 : 2)); | |
| 1216 | + /* Initialize the video_device structure */ | |
| 1217 | + vdev = ch->video_dev; | |
| 1218 | + strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); | |
| 1219 | + vdev->release = video_device_release; | |
| 1220 | + vdev->fops = &vpif_fops; | |
| 1221 | + vdev->ioctl_ops = &vpif_ioctl_ops; | |
| 1222 | + vdev->v4l2_dev = &vpif_obj.v4l2_dev; | |
| 1223 | + vdev->vfl_dir = VFL_DIR_TX; | |
| 1224 | + vdev->queue = q; | |
| 1225 | + vdev->lock = &common->lock; | |
| 1226 | + set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | |
| 1227 | + video_set_drvdata(ch->video_dev, ch); | |
| 1228 | + err = video_register_device(vdev, VFL_TYPE_GRABBER, | |
| 1229 | + (j ? 3 : 2)); | |
| 1696 | 1230 | if (err < 0) |
| 1697 | 1231 | goto probe_out; |
| 1698 | 1232 | } |
| @@ -1702,6 +1236,8 @@ static int vpif_probe_complete(void) · 3 unmodified lines | ||
| 1702 | 1236 | probe_out: |
| 1703 | 1237 | for (k = 0; k < j; k++) { |
| 1704 | 1238 | ch = vpif_obj.dev[k]; |
| 1239 | + common = &ch->common[k]; | |
| 1240 | + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 1705 | 1241 | video_unregister_device(ch->video_dev); |
| 1706 | 1242 | video_device_release(ch->video_dev); |
| 1707 | 1243 | ch->video_dev = NULL; |
| @@ -1728,7 +1264,6 @@ static __init int vpif_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 1728 | 1264 | struct video_device *vfd; |
| 1729 | 1265 | struct resource *res; |
| 1730 | 1266 | int subdev_count; |
| 1731 | − size_t size; | |
| 1732 | 1267 | |
| 1733 | 1268 | vpif_dev = &pdev->dev; |
| 1734 | 1269 | err = initialize_vpif(); |
| @@ -1746,7 +1281,7 @@ static __init int vpif_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 1746 | 1281 | |
| 1747 | 1282 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
| 1748 | 1283 | err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, |
| 1749 | − IRQF_SHARED, "VPIF_Display", | |
| 1284 | + IRQF_SHARED, VPIF_DRIVER_NAME, | |
| 1750 | 1285 | (void *)(&vpif_obj.dev[res_idx]-> |
| 1751 | 1286 | channel_id)); |
| 1752 | 1287 | if (err) { |
| @@ -1772,36 +1307,10 @@ static __init int vpif_probe(struct platform_device *pdev) · 19 unmodified lines | ||
| 1772 | 1307 | goto vpif_unregister; |
| 1773 | 1308 | } |
| 1774 | 1309 | |
| 1775 | − /* Initialize field of video device */ | |
| 1776 | − *vfd = vpif_video_template; | |
| 1777 | − vfd->v4l2_dev = &vpif_obj.v4l2_dev; | |
| 1778 | − vfd->release = video_device_release; | |
| 1779 | − vfd->vfl_dir = VFL_DIR_TX; | |
| 1780 | − snprintf(vfd->name, sizeof(vfd->name), | |
| 1781 | − "VPIF_Display_DRIVER_V%s", | |
| 1782 | − VPIF_DISPLAY_VERSION); | |
| 1783 | − | |
| 1784 | 1310 | /* Set video_dev to the video device */ |
| 1785 | 1311 | ch->video_dev = vfd; |
| 1786 | 1312 | } |
| 1787 | 1313 | |
| 1788 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 1789 | − if (res) { | |
| 1790 | − size = resource_size(res); | |
| 1791 | − /* The resources are divided into two equal memory and when | |
| 1792 | − * we have HD output we can add them together | |
| 1793 | − */ | |
| 1794 | − for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { | |
| 1795 | − ch = vpif_obj.dev[j]; | |
| 1796 | − ch->channel_id = j; | |
| 1797 | − | |
| 1798 | − /* only enabled if second resource exists */ | |
| 1799 | − config_params.video_limit[ch->channel_id] = 0; | |
| 1800 | − if (size) | |
| 1801 | − config_params.video_limit[ch->channel_id] = | |
| 1802 | − size/2; | |
| 1803 | − } | |
| 1804 | − } | |
| 1805 | 1314 | vpif_obj.config = pdev->dev.platform_data; |
| 1806 | 1315 | subdev_count = vpif_obj.config->subdev_count; |
| 1807 | 1316 | subdevdata = vpif_obj.config->subdevinfo; |
| @@ -1867,6 +1376,7 @@ vpif_unregister: · 59 unmodified lines | ||
| 1867 | 1376 | */ |
| 1868 | 1377 | static int vpif_remove(struct platform_device *device) |
| 1869 | 1378 | { |
| 1379 | + struct common_obj *common; | |
| 1870 | 1380 | struct channel_obj *ch; |
| 1871 | 1381 | int i; |
| 1872 | 1382 | |
| @@ -1877,6 +1387,8 @@ static int vpif_remove(struct platform_device *device) · 4 unmodified lines | ||
| 1877 | 1387 | for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { |
| 1878 | 1388 | /* Get the pointer to the channel object */ |
| 1879 | 1389 | ch = vpif_obj.dev[i]; |
| 1390 | + common = &ch->common[i]; | |
| 1391 | + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); | |
| 1880 | 1392 | /* Unregister video device */ |
| 1881 | 1393 | video_unregister_device(ch->video_dev); |
| 1882 | 1394 | |
| @@ -1887,7 +1399,7 @@ static int vpif_remove(struct platform_device *device) · 4 unmodified lines | ||
| 1887 | 1399 | return 0; |
| 1888 | 1400 | } |
| 1889 | 1401 | |
| 1890 | −#ifdef CONFIG_PM | |
| 1402 | +#ifdef CONFIG_PM_SLEEP | |
| 1891 | 1403 | static int vpif_suspend(struct device *dev) |
| 1892 | 1404 | { |
| 1893 | 1405 | struct common_obj *common; |
| @@ -1898,18 +1410,20 @@ static int vpif_suspend(struct device *dev) · 4 unmodified lines | ||
| 1898 | 1410 | /* Get the pointer to the channel object */ |
| 1899 | 1411 | ch = vpif_obj.dev[i]; |
| 1900 | 1412 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1413 | + | |
| 1414 | + if (!vb2_is_streaming(&common->buffer_queue)) | |
| 1415 | + continue; | |
| 1416 | + | |
| 1901 | 1417 | mutex_lock(&common->lock); |
| 1902 | − if (atomic_read(&ch->usrs) && common->io_usrs) { | |
| 1903 | − /* Disable channel */ | |
| 1904 | − if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { | |
| 1905 | − enable_channel2(0); | |
| 1906 | − channel2_intr_enable(0); | |
| 1907 | − } | |
| 1908 | − if (ch->channel_id == VPIF_CHANNEL3_VIDEO || | |
| 1909 | − common->started == 2) { | |
| 1910 | − enable_channel3(0); | |
| 1911 | − channel3_intr_enable(0); | |
| 1912 | − } | |
| 1418 | + /* Disable channel */ | |
| 1419 | + if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { | |
| 1420 | + enable_channel2(0); | |
| 1421 | + channel2_intr_enable(0); | |
| 1422 | + } | |
| 1423 | + if (ch->channel_id == VPIF_CHANNEL3_VIDEO || | |
| 1424 | + ycmux_mode == 2) { | |
| 1425 | + enable_channel3(0); | |
| 1426 | + channel3_intr_enable(0); | |
| 1913 | 1427 | } |
| 1914 | 1428 | mutex_unlock(&common->lock); |
| 1915 | 1429 | } |
| @@ -1928,18 +1442,20 @@ static int vpif_resume(struct device *dev) · 12 unmodified lines | ||
| 1928 | 1442 | /* Get the pointer to the channel object */ |
| 1929 | 1443 | ch = vpif_obj.dev[i]; |
| 1930 | 1444 | common = &ch->common[VPIF_VIDEO_INDEX]; |
| 1445 | + | |
| 1446 | + if (!vb2_is_streaming(&common->buffer_queue)) | |
| 1447 | + continue; | |
| 1448 | + | |
| 1931 | 1449 | mutex_lock(&common->lock); |
| 1932 | − if (atomic_read(&ch->usrs) && common->io_usrs) { | |
| 1933 | − /* Enable channel */ | |
| 1934 | − if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { | |
| 1935 | − enable_channel2(1); | |
| 1936 | − channel2_intr_enable(1); | |
| 1937 | − } | |
| 1938 | − if (ch->channel_id == VPIF_CHANNEL3_VIDEO || | |
| 1939 | − common->started == 2) { | |
| 1940 | − enable_channel3(1); | |
| 1941 | − channel3_intr_enable(1); | |
| 1942 | − } | |
| 1450 | + /* Enable channel */ | |
| 1451 | + if (ch->channel_id == VPIF_CHANNEL2_VIDEO) { | |
| 1452 | + enable_channel2(1); | |
| 1453 | + channel2_intr_enable(1); | |
| 1454 | + } | |
| 1455 | + if (ch->channel_id == VPIF_CHANNEL3_VIDEO || | |
| 1456 | + ycmux_mode == 2) { | |
| 1457 | + enable_channel3(1); | |
| 1458 | + channel3_intr_enable(1); | |
| 1943 | 1459 | } |
| 1944 | 1460 | mutex_unlock(&common->lock); |
| 1945 | 1461 | } |
| @@ -1947,21 +1463,15 @@ static int vpif_resume(struct device *dev) · 1 unmodified line | ||
| 1947 | 1463 | return 0; |
| 1948 | 1464 | } |
| 1949 | 1465 | |
| 1950 | −static const struct dev_pm_ops vpif_pm = { | |
| 1951 | − .suspend = vpif_suspend, | |
| 1952 | − .resume = vpif_resume, | |
| 1953 | −}; | |
| 1954 | − | |
| 1955 | −#define vpif_pm_ops (&vpif_pm) | |
| 1956 | −#else | |
| 1957 | −#define vpif_pm_ops NULL | |
| 1958 | 1466 | #endif |
| 1959 | 1467 | |
| 1468 | +static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); | |
| 1469 | + | |
| 1960 | 1470 | static __refdata struct platform_driver vpif_driver = { |
| 1961 | 1471 | .driver = { |
| 1962 | − .name = "vpif_display", | |
| 1472 | + .name = VPIF_DRIVER_NAME, | |
| 1963 | 1473 | .owner = THIS_MODULE, |
| 1964 | − .pm = vpif_pm_ops, | |
| 1474 | + .pm = &vpif_pm_ops, | |
| 1965 | 1475 | }, |
| 1966 | 1476 | .probe = vpif_probe, |
| 1967 | 1477 | .remove = vpif_remove, |
| @@ -13,8 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | * GNU General Public License for more details. |
| 14 | 14 | */ |
| 15 | 15 | |
| 16 | −#ifndef DAVINCIHD_DISPLAY_H | |
| 17 | −#define DAVINCIHD_DISPLAY_H | |
| 16 | +#ifndef VPIF_DISPLAY_H | |
| 17 | +#define VPIF_DISPLAY_H | |
| 18 | 18 | |
| 19 | 19 | /* Header files */ |
| 20 | 20 | #include <media/videobuf2-dma-contig.h> |
| @@ -67,17 +67,10 @@ struct vpif_disp_buffer { · 46 unmodified lines | ||
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | 69 | struct common_obj { |
| 70 | − /* Buffer specific parameters */ | |
| 71 | − u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for | |
| 72 | − * storing frames */ | |
| 73 | − u32 numbuffers; /* number of buffers */ | |
| 74 | 70 | struct vpif_disp_buffer *cur_frm; /* Pointer pointing to current |
| 75 | 71 | * vb2_buffer */ |
| 76 | 72 | struct vpif_disp_buffer *next_frm; /* Pointer pointing to next |
| 77 | 73 | * vb2_buffer */ |
| 78 | − enum v4l2_memory memory; /* This field keeps track of | |
| 79 | − * type of buffer exchange | |
| 80 | − * method user has selected */ | |
| 81 | 74 | struct v4l2_format fmt; /* Used to store the format */ |
| 82 | 75 | struct vb2_queue buffer_queue; /* Buffer queue used in |
| 83 | 76 | * video-buf */ |
| @@ -90,10 +83,6 @@ struct common_obj { · 6 unmodified lines | ||
| 90 | 83 | /* channel specific parameters */ |
| 91 | 84 | struct mutex lock; /* lock used to access this |
| 92 | 85 | * structure */ |
| 93 | − u32 io_usrs; /* number of users performing | |
| 94 | − * IO */ | |
| 95 | − u8 started; /* Indicates whether streaming | |
| 96 | − * started */ | |
| 97 | 86 | u32 ytop_off; /* offset of Y top from the |
| 98 | 87 | * starting of the buffer */ |
| 99 | 88 | u32 ybtm_off; /* offset of Y bottom from the |
| @@ -103,7 +92,7 @@ struct common_obj { · 3 unmodified lines | ||
| 103 | 92 | u32 cbtm_off; /* offset of C bottom from the |
| 104 | 93 | * starting of the buffer */ |
| 105 | 94 | /* Function pointer to set the addresses */ |
| 106 | − void (*set_addr) (unsigned long, unsigned long, | |
| 95 | + void (*set_addr)(unsigned long, unsigned long, | |
| 107 | 96 | unsigned long, unsigned long); |
| 108 | 97 | u32 height; |
| 109 | 98 | u32 width; |
| @@ -113,10 +102,6 @@ struct channel_obj { · 3 unmodified lines | ||
| 113 | 102 | /* V4l2 specific parameters */ |
| 114 | 103 | struct video_device *video_dev; /* Identifies video device for |
| 115 | 104 | * this channel */ |
| 116 | − struct v4l2_prio_state prio; /* Used to keep track of state of | |
| 117 | − * the priority */ | |
| 118 | − atomic_t usrs; /* number of open instances of | |
| 119 | − * the channel */ | |
| 120 | 105 | u32 field_id; /* Indicates id of the field |
| 121 | 106 | * which is being displayed */ |
| 122 | 107 | u8 initialized; /* flag to indicate whether |
| @@ -130,19 +115,6 @@ struct channel_obj { · 7 unmodified lines | ||
| 130 | 115 | struct video_obj video; |
| 131 | 116 | }; |
| 132 | 117 | |
| 133 | −/* File handle structure */ | |
| 134 | −struct vpif_fh { | |
| 135 | − struct channel_obj *channel; /* pointer to channel object for | |
| 136 | − * opened device */ | |
| 137 | − u8 io_allowed[VPIF_NUMOBJECTS]; /* Indicates whether this file handle | |
| 138 | − * is doing IO */ | |
| 139 | − enum v4l2_priority prio; /* Used to keep track priority of | |
| 140 | − * this instance */ | |
| 141 | − u8 initialized; /* Used to keep track of whether this | |
| 142 | − * file handle has initialized | |
| 143 | − * channel or not */ | |
| 144 | −}; | |
| 145 | − | |
| 146 | 118 | /* vpif device structure */ |
| 147 | 119 | struct vpif_device { |
| 148 | 120 | struct v4l2_device v4l2_dev; |
| @@ -152,12 +124,4 @@ struct vpif_device { · 3 unmodified lines | ||
| 152 | 124 | struct vpif_display_config *config; |
| 153 | 125 | }; |
| 154 | 126 | |
| 155 | −struct vpif_config_params { | |
| 156 | − u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; | |
| 157 | − u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; | |
| 158 | − u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS]; | |
| 159 | − u32 video_limit[VPIF_DISPLAY_NUM_CHANNELS]; | |
| 160 | − u8 min_numbuffers; | |
| 161 | −}; | |
| 162 | − | |
| 163 | −#endif /* DAVINCIHD_DISPLAY_H */ | |
| 127 | +#endif /* VPIF_DISPLAY_H */ | |
| @@ -66,15 +66,13 @@ static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) · 65 unmodified lines | ||
| 66 | 66 | return ret > 0 ? 0 : ret; |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | −static int gsc_m2m_stop_streaming(struct vb2_queue *q) | |
| 69 | +static void gsc_m2m_stop_streaming(struct vb2_queue *q) | |
| 70 | 70 | { |
| 71 | 71 | struct gsc_ctx *ctx = q->drv_priv; |
| 72 | 72 | |
| 73 | 73 | __gsc_m2m_job_abort(ctx); |
| 74 | 74 | |
| 75 | 75 | pm_runtime_put(&ctx->gsc_dev->pdev->dev); |
| 76 | − | |
| 77 | − return 0; | |
| 78 | 76 | } |
| 79 | 77 | |
| 80 | 78 | void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) |
| @@ -3,6 +3,7 @@ config VIDEO_SAMSUNG_EXYNOS4_IS · 2 unmodified lines | ||
| 3 | 3 | bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver" |
| 4 | 4 | depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API |
| 5 | 5 | depends on (PLAT_S5P || ARCH_EXYNOS) |
| 6 | + depends on OF && COMMON_CLK | |
| 6 | 7 | help |
| 7 | 8 | Say Y here to enable camera host interface devices for |
| 8 | 9 | Samsung S5P and EXYNOS SoC series. |
| @@ -17,7 +18,7 @@ config VIDEO_S5P_FIMC · 8 unmodified lines | ||
| 17 | 18 | depends on I2C |
| 18 | 19 | select VIDEOBUF2_DMA_CONTIG |
| 19 | 20 | select V4L2_MEM2MEM_DEV |
| 20 | − select MFD_SYSCON if OF | |
| 21 | + select MFD_SYSCON | |
| 21 | 22 | select VIDEO_EXYNOS4_IS_COMMON |
| 22 | 23 | help |
| 23 | 24 | This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | 12 | #include <linux/module.h> |
| 13 | −#include <media/s5p_fimc.h> | |
| 13 | +#include <media/exynos-fimc.h> | |
| 14 | 14 | #include "common.h" |
| 15 | 15 | |
| 16 | 16 | /* Called with the media graph mutex held or entity->stream_count > 0. */ |
| @@ -294,15 +294,15 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) · 293 unmodified lines | ||
| 294 | 294 | return 0; |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | −static int stop_streaming(struct vb2_queue *q) | |
| 297 | +static void stop_streaming(struct vb2_queue *q) | |
| 298 | 298 | { |
| 299 | 299 | struct fimc_ctx *ctx = q->drv_priv; |
| 300 | 300 | struct fimc_dev *fimc = ctx->fimc_dev; |
| 301 | 301 | |
| 302 | 302 | if (!fimc_capture_active(fimc)) |
| 303 | − return -EINVAL; | |
| 303 | + return; | |
| 304 | 304 | |
| 305 | − return fimc_stop_capture(fimc, false); | |
| 305 | + fimc_stop_capture(fimc, false); | |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | 308 | int fimc_capture_suspend(struct fimc_dev *fimc) |
| @@ -56,8 +56,8 @@ static struct fimc_fmt fimc_formats[] = { · 55 unmodified lines | ||
| 56 | 56 | .colplanes = 1, |
| 57 | 57 | .flags = FMT_FLAGS_M2M, |
| 58 | 58 | }, { |
| 59 | − .name = "ARGB8888, 32 bpp", | |
| 60 | − .fourcc = V4L2_PIX_FMT_RGB32, | |
| 59 | + .name = "BGRA8888, 32 bpp", | |
| 60 | + .fourcc = V4L2_PIX_FMT_BGR32, | |
| 61 | 61 | .depth = { 32 }, |
| 62 | 62 | .color = FIMC_FMT_RGB888, |
| 63 | 63 | .memplanes = 1, |
| @@ -450,7 +450,7 @@ void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) · 386 unmodified lines | ||
| 450 | 450 | bool pix_hoff = ctx->fimc_dev->drv_data->dma_pix_hoff; |
| 451 | 451 | u32 i, depth = 0; |
| 452 | 452 | |
| 453 | − for (i = 0; i < f->fmt->colplanes; i++) | |
| 453 | + for (i = 0; i < f->fmt->memplanes; i++) | |
| 454 | 454 | depth += f->fmt->depth[i]; |
| 455 | 455 | |
| 456 | 456 | f->dma_offset.y_h = f->offs_h; |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <media/v4l2-device.h> |
| 28 | 28 | #include <media/v4l2-mem2mem.h> |
| 29 | 29 | #include <media/v4l2-mediabus.h> |
| 30 | −#include <media/s5p_fimc.h> | |
| 30 | +#include <media/exynos-fimc.h> | |
| 31 | 31 | |
| 32 | 32 | #define dbg(fmt, args...) \ |
| 33 | 33 | pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) |
| @@ -367,6 +367,9 @@ static void fimc_is_free_cpu_memory(struct fimc_is *is) · 366 unmodified lines | ||
| 367 | 367 | { |
| 368 | 368 | struct device *dev = &is->pdev->dev; |
| 369 | 369 | |
| 370 | + if (is->memory.vaddr == NULL) | |
| 371 | + return; | |
| 372 | + | |
| 370 | 373 | dma_free_coherent(dev, is->memory.size, is->memory.vaddr, |
| 371 | 374 | is->memory.paddr); |
| 372 | 375 | } |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <media/v4l2-ioctl.h> |
| 31 | 31 | #include <media/videobuf2-core.h> |
| 32 | 32 | #include <media/videobuf2-dma-contig.h> |
| 33 | −#include <media/s5p_fimc.h> | |
| 33 | +#include <media/exynos-fimc.h> | |
| 34 | 34 | |
| 35 | 35 | #include "common.h" |
| 36 | 36 | #include "media-dev.h" |
| @@ -125,7 +125,7 @@ static int isp_video_capture_start_streaming(struct vb2_queue *q, · 88 unmodified lines | ||
| 125 | 125 | return ret; |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | −static int isp_video_capture_stop_streaming(struct vb2_queue *q) | |
| 128 | +static void isp_video_capture_stop_streaming(struct vb2_queue *q) | |
| 129 | 129 | { |
| 130 | 130 | struct fimc_isp *isp = vb2_get_drv_priv(q); |
| 131 | 131 | struct fimc_is *is = fimc_isp_to_is(isp); |
| @@ -134,7 +134,7 @@ static int isp_video_capture_stop_streaming(struct vb2_queue *q) · 2 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0); |
| 136 | 136 | if (ret < 0) |
| 137 | − return ret; | |
| 137 | + return; | |
| 138 | 138 | |
| 139 | 139 | dma->cmd = DMA_OUTPUT_COMMAND_DISABLE; |
| 140 | 140 | dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE; |
| @@ -155,7 +155,6 @@ static int isp_video_capture_stop_streaming(struct vb2_queue *q) · 14 unmodified lines | ||
| 155 | 155 | clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); |
| 156 | 156 | |
| 157 | 157 | isp->video_capture.buf_count = 0; |
| 158 | − return 0; | |
| 159 | 158 | } |
| 160 | 159 | |
| 161 | 160 | static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb) |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <media/videobuf2-core.h> |
| 25 | 25 | #include <media/v4l2-device.h> |
| 26 | 26 | #include <media/v4l2-mediabus.h> |
| 27 | −#include <media/s5p_fimc.h> | |
| 27 | +#include <media/exynos-fimc.h> | |
| 28 | 28 | |
| 29 | 29 | extern int fimc_isp_debug; |
| 30 | 30 | |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/bitops.h> |
| 13 | 13 | #include <linux/delay.h> |
| 14 | 14 | #include <linux/io.h> |
| 15 | −#include <media/s5p_fimc.h> | |
| 15 | +#include <media/exynos-fimc.h> | |
| 16 | 16 | |
| 17 | 17 | #include "fimc-lite-reg.h" |
| 18 | 18 | #include "fimc-lite.h" |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <media/v4l2-mem2mem.h> |
| 31 | 31 | #include <media/videobuf2-core.h> |
| 32 | 32 | #include <media/videobuf2-dma-contig.h> |
| 33 | −#include <media/s5p_fimc.h> | |
| 33 | +#include <media/exynos-fimc.h> | |
| 34 | 34 | |
| 35 | 35 | #include "common.h" |
| 36 | 36 | #include "fimc-core.h" |
| @@ -350,14 +350,14 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) · 313 unmodified lines | ||
| 350 | 350 | return 0; |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | −static int stop_streaming(struct vb2_queue *q) | |
| 353 | +static void stop_streaming(struct vb2_queue *q) | |
| 354 | 354 | { |
| 355 | 355 | struct fimc_lite *fimc = q->drv_priv; |
| 356 | 356 | |
| 357 | 357 | if (!fimc_lite_active(fimc)) |
| 358 | − return -EINVAL; | |
| 358 | + return; | |
| 359 | 359 | |
| 360 | − return fimc_lite_stop_capture(fimc, false); | |
| 360 | + fimc_lite_stop_capture(fimc, false); | |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | 363 | static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <media/v4l2-ctrls.h> |
| 24 | 24 | #include <media/v4l2-device.h> |
| 25 | 25 | #include <media/v4l2-mediabus.h> |
| 26 | −#include <media/s5p_fimc.h> | |
| 26 | +#include <media/exynos-fimc.h> | |
| 27 | 27 | |
| 28 | 28 | #define FIMC_LITE_DRV_NAME "exynos-fimc-lite" |
| 29 | 29 | #define FLITE_CLK_NAME "flite" |
| @@ -85,7 +85,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) · 84 unmodified lines | ||
| 85 | 85 | return ret > 0 ? 0 : ret; |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | −static int stop_streaming(struct vb2_queue *q) | |
| 88 | +static void stop_streaming(struct vb2_queue *q) | |
| 89 | 89 | { |
| 90 | 90 | struct fimc_ctx *ctx = q->drv_priv; |
| 91 | 91 | int ret; |
| @@ -95,7 +95,6 @@ static int stop_streaming(struct vb2_queue *q) · 3 unmodified lines | ||
| 95 | 95 | fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); |
| 96 | 96 | |
| 97 | 97 | pm_runtime_put(&ctx->fimc_dev->pdev->dev); |
| 98 | − return 0; | |
| 99 | 98 | } |
| 100 | 99 | |
| 101 | 100 | static void fimc_device_run(void *priv) |
| @@ -197,7 +196,7 @@ static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 95 unmodified lines | ||
| 197 | 196 | |
| 198 | 197 | *num_planes = f->fmt->memplanes; |
| 199 | 198 | for (i = 0; i < f->fmt->memplanes; i++) { |
| 200 | − sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8; | |
| 199 | + sizes[i] = f->payload[i]; | |
| 201 | 200 | allocators[i] = ctx->fimc_dev->alloc_ctx; |
| 202 | 201 | } |
| 203 | 202 | return 0; |
| @@ -342,7 +341,7 @@ static void __set_frame_format(struct fimc_frame *frame, struct fimc_fmt *fmt, · 138 unmodified lines | ||
| 342 | 341 | { |
| 343 | 342 | int i; |
| 344 | 343 | |
| 345 | − for (i = 0; i < fmt->colplanes; i++) { | |
| 344 | + for (i = 0; i < fmt->memplanes; i++) { | |
| 346 | 345 | frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline; |
| 347 | 346 | frame->payload[i] = pixm->plane_fmt[i].sizeimage; |
| 348 | 347 | } |
| @@ -461,7 +460,7 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) · 112 unmodified lines | ||
| 461 | 460 | else |
| 462 | 461 | halign = ffs(fimc->variant->min_vsize_align) - 1; |
| 463 | 462 | |
| 464 | − for (i = 0; i < f->fmt->colplanes; i++) | |
| 463 | + for (i = 0; i < f->fmt->memplanes; i++) | |
| 465 | 464 | depth += f->fmt->depth[i]; |
| 466 | 465 | |
| 467 | 466 | v4l_bound_align_image(&cr->c.width, min_size, f->o_width, |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/io.h> |
| 14 | 14 | #include <linux/regmap.h> |
| 15 | 15 | |
| 16 | −#include <media/s5p_fimc.h> | |
| 16 | +#include <media/exynos-fimc.h> | |
| 17 | 17 | #include "media-dev.h" |
| 18 | 18 | |
| 19 | 19 | #include "fimc-reg.h" |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <media/v4l2-ctrls.h> |
| 32 | 32 | #include <media/v4l2-of.h> |
| 33 | 33 | #include <media/media-device.h> |
| 34 | −#include <media/s5p_fimc.h> | |
| 34 | +#include <media/exynos-fimc.h> | |
| 35 | 35 | |
| 36 | 36 | #include "media-dev.h" |
| 37 | 37 | #include "fimc-core.h" |
| @@ -39,10 +39,6 @@ · 1 unmodified line | ||
| 39 | 39 | #include "fimc-lite.h" |
| 40 | 40 | #include "mipi-csis.h" |
| 41 | 41 | |
| 42 | −static int __fimc_md_set_camclk(struct fimc_md *fmd, | |
| 43 | − struct fimc_source_info *si, | |
| 44 | − bool on); | |
| 45 | − | |
| 46 | 42 | /* Set up image sensor subdev -> FIMC capture node notifications. */ |
| 47 | 43 | static void __setup_sensor_notification(struct fimc_md *fmd, |
| 48 | 44 | struct v4l2_subdev *sensor, |
| @@ -223,17 +219,10 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, · 174 unmodified lines | ||
| 223 | 219 | return ret; |
| 224 | 220 | } |
| 225 | 221 | |
| 226 | − ret = fimc_md_set_camclk(sd, true); | |
| 227 | − if (ret < 0) | |
| 228 | − goto err_wbclk; | |
| 229 | − | |
| 230 | 222 | ret = fimc_pipeline_s_power(p, 1); |
| 231 | 223 | if (!ret) |
| 232 | 224 | return 0; |
| 233 | 225 | |
| 234 | − fimc_md_set_camclk(sd, false); | |
| 235 | − | |
| 236 | −err_wbclk: | |
| 237 | 226 | if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) |
| 238 | 227 | clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); |
| 239 | 228 | |
| @@ -259,7 +248,6 @@ static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) · 19 unmodified lines | ||
| 259 | 248 | } |
| 260 | 249 | |
| 261 | 250 | ret = fimc_pipeline_s_power(p, 0); |
| 262 | − fimc_md_set_camclk(sd, false); | |
| 263 | 251 | |
| 264 | 252 | fmd = entity_to_fimc_mdev(&sd->entity); |
| 265 | 253 | |
| @@ -337,75 +325,14 @@ static void fimc_md_pipelines_free(struct fimc_md *fmd) · 71 unmodified lines | ||
| 337 | 325 | } |
| 338 | 326 | } |
| 339 | 327 | |
| 340 | −/* | |
| 341 | − * Sensor subdevice helper functions | |
| 342 | − */ | |
| 343 | −static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, | |
| 344 | − struct fimc_source_info *si) | |
| 345 | −{ | |
| 346 | − struct i2c_adapter *adapter; | |
| 347 | − struct v4l2_subdev *sd = NULL; | |
| 348 | − | |
| 349 | − if (!si || !fmd) | |
| 350 | − return NULL; | |
| 351 | − /* | |
| 352 | − * If FIMC bus type is not Writeback FIFO assume it is same | |
| 353 | − * as sensor_bus_type. | |
| 354 | − */ | |
| 355 | − si->fimc_bus_type = si->sensor_bus_type; | |
| 356 | − | |
| 357 | − adapter = i2c_get_adapter(si->i2c_bus_num); | |
| 358 | − if (!adapter) { | |
| 359 | − v4l2_warn(&fmd->v4l2_dev, | |
| 360 | − "Failed to get I2C adapter %d, deferring probe\n", | |
| 361 | − si->i2c_bus_num); | |
| 362 | − return ERR_PTR(-EPROBE_DEFER); | |
| 363 | − } | |
| 364 | − sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, | |
| 365 | − si->board_info, NULL); | |
| 366 | − if (IS_ERR_OR_NULL(sd)) { | |
| 367 | − i2c_put_adapter(adapter); | |
| 368 | − v4l2_warn(&fmd->v4l2_dev, | |
| 369 | − "Failed to acquire subdev %s, deferring probe\n", | |
| 370 | − si->board_info->type); | |
| 371 | − return ERR_PTR(-EPROBE_DEFER); | |
| 372 | − } | |
| 373 | − v4l2_set_subdev_hostdata(sd, si); | |
| 374 | − sd->grp_id = GRP_ID_SENSOR; | |
| 375 | − | |
| 376 | − v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", | |
| 377 | − sd->name); | |
| 378 | − return sd; | |
| 379 | −} | |
| 380 | − | |
| 381 | −static void fimc_md_unregister_sensor(struct v4l2_subdev *sd) | |
| 382 | −{ | |
| 383 | − struct i2c_client *client = v4l2_get_subdevdata(sd); | |
| 384 | − struct i2c_adapter *adapter; | |
| 385 | − | |
| 386 | − if (!client || client->dev.of_node) | |
| 387 | − return; | |
| 388 | − | |
| 389 | − v4l2_device_unregister_subdev(sd); | |
| 390 | − | |
| 391 | − adapter = client->adapter; | |
| 392 | − i2c_unregister_device(client); | |
| 393 | − if (adapter) | |
| 394 | − i2c_put_adapter(adapter); | |
| 395 | −} | |
| 396 | − | |
| 397 | −#ifdef CONFIG_OF | |
| 398 | 328 | /* Parse port node and register as a sub-device any sensor specified there. */ |
| 399 | 329 | static int fimc_md_parse_port_node(struct fimc_md *fmd, |
| 400 | 330 | struct device_node *port, |
| 401 | 331 | unsigned int index) |
| 402 | 332 | { |
| 333 | + struct fimc_source_info *pd = &fmd->sensor[index].pdata; | |
| 403 | 334 | struct device_node *rem, *ep, *np; |
| 404 | − struct fimc_source_info *pd; | |
| 405 | 335 | struct v4l2_of_endpoint endpoint; |
| 406 | − u32 val; | |
| 407 | − | |
| 408 | − pd = &fmd->sensor[index].pdata; | |
| 409 | 336 | |
| 410 | 337 | /* Assume here a port node can have only one endpoint node. */ |
| 411 | 338 | ep = of_get_next_child(port, NULL); |
| @@ -425,20 +352,6 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, · 13 unmodified lines | ||
| 425 | 352 | ep->full_name); |
| 426 | 353 | return 0; |
| 427 | 354 | } |
| 428 | − if (!of_property_read_u32(rem, "samsung,camclk-out", &val)) | |
| 429 | − pd->clk_id = val; | |
| 430 | − | |
| 431 | − if (!of_property_read_u32(rem, "clock-frequency", &val)) | |
| 432 | − pd->clk_frequency = val; | |
| 433 | − else | |
| 434 | − pd->clk_frequency = DEFAULT_SENSOR_CLK_FREQ; | |
| 435 | − | |
| 436 | − if (pd->clk_frequency == 0) { | |
| 437 | − v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n", | |
| 438 | − rem->full_name); | |
| 439 | − of_node_put(rem); | |
| 440 | − return -EINVAL; | |
| 441 | − } | |
| 442 | 355 | |
| 443 | 356 | if (fimc_input_is_parallel(endpoint.base.port)) { |
| 444 | 357 | if (endpoint.bus_type == V4L2_MBUS_PARALLEL) |
| @@ -485,14 +398,26 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, · 40 unmodified lines | ||
| 485 | 398 | } |
| 486 | 399 | |
| 487 | 400 | /* Register all SoC external sub-devices */ |
| 488 | −static int fimc_md_of_sensors_register(struct fimc_md *fmd, | |
| 489 | − struct device_node *np) | |
| 401 | +static int fimc_md_register_sensor_entities(struct fimc_md *fmd) | |
| 490 | 402 | { |
| 491 | 403 | struct device_node *parent = fmd->pdev->dev.of_node; |
| 492 | 404 | struct device_node *node, *ports; |
| 493 | 405 | int index = 0; |
| 494 | 406 | int ret; |
| 495 | 407 | |
| 408 | + /* | |
| 409 | + * Runtime resume one of the FIMC entities to make sure | |
| 410 | + * the sclk_cam clocks are not globally disabled. | |
| 411 | + */ | |
| 412 | + if (!fmd->pmf) | |
| 413 | + return -ENXIO; | |
| 414 | + | |
| 415 | + ret = pm_runtime_get_sync(fmd->pmf); | |
| 416 | + if (ret < 0) | |
| 417 | + return ret; | |
| 418 | + | |
| 419 | + fmd->num_sensors = 0; | |
| 420 | + | |
| 496 | 421 | /* Attach sensors linked to MIPI CSI-2 receivers */ |
| 497 | 422 | for_each_available_child_of_node(parent, node) { |
| 498 | 423 | struct device_node *port; |
| @@ -506,14 +431,14 @@ static int fimc_md_of_sensors_register(struct fimc_md *fmd, · 7 unmodified lines | ||
| 506 | 431 | |
| 507 | 432 | ret = fimc_md_parse_port_node(fmd, port, index); |
| 508 | 433 | if (ret < 0) |
| 509 | − return ret; | |
| 434 | + goto rpm_put; | |
| 510 | 435 | index++; |
| 511 | 436 | } |
| 512 | 437 | |
| 513 | 438 | /* Attach sensors listed in the parallel-ports node */ |
| 514 | 439 | ports = of_get_child_by_name(parent, "parallel-ports"); |
| 515 | 440 | if (!ports) |
| 516 | − return 0; | |
| 441 | + goto rpm_put; | |
| 517 | 442 | |
| 518 | 443 | for_each_child_of_node(ports, node) { |
| 519 | 444 | ret = fimc_md_parse_port_node(fmd, node, index); |
| @@ -521,8 +446,9 @@ static int fimc_md_of_sensors_register(struct fimc_md *fmd, · 1 unmodified line | ||
| 521 | 446 | break; |
| 522 | 447 | index++; |
| 523 | 448 | } |
| 524 | − | |
| 525 | − return 0; | |
| 449 | +rpm_put: | |
| 450 | + pm_runtime_put(fmd->pmf); | |
| 451 | + return ret; | |
| 526 | 452 | } |
| 527 | 453 | |
| 528 | 454 | static int __of_get_csis_id(struct device_node *np) |
| @@ -535,68 +461,10 @@ static int __of_get_csis_id(struct device_node *np) · 6 unmodified lines | ||
| 535 | 461 | of_property_read_u32(np, "reg", ®); |
| 536 | 462 | return reg - FIMC_INPUT_MIPI_CSI2_0; |
| 537 | 463 | } |
| 538 | −#else | |
| 539 | −#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS) | |
| 540 | −#define __of_get_csis_id(np) (-ENOSYS) | |
| 541 | −#endif | |
| 542 | − | |
| 543 | −static int fimc_md_register_sensor_entities(struct fimc_md *fmd) | |
| 544 | −{ | |
| 545 | − struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; | |
| 546 | − struct device_node *of_node = fmd->pdev->dev.of_node; | |
| 547 | − int num_clients = 0; | |
| 548 | − int ret, i; | |
| 549 | − | |
| 550 | − /* | |
| 551 | − * Runtime resume one of the FIMC entities to make sure | |
| 552 | − * the sclk_cam clocks are not globally disabled. | |
| 553 | − */ | |
| 554 | − if (!fmd->pmf) | |
| 555 | − return -ENXIO; | |
| 556 | − | |
| 557 | − ret = pm_runtime_get_sync(fmd->pmf); | |
| 558 | − if (ret < 0) | |
| 559 | − return ret; | |
| 560 | − | |
| 561 | − if (of_node) { | |
| 562 | − fmd->num_sensors = 0; | |
| 563 | − ret = fimc_md_of_sensors_register(fmd, of_node); | |
| 564 | − } else if (pdata) { | |
| 565 | − WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor)); | |
| 566 | − num_clients = min_t(u32, pdata->num_clients, | |
| 567 | − ARRAY_SIZE(fmd->sensor)); | |
| 568 | − fmd->num_sensors = num_clients; | |
| 569 | − | |
| 570 | − for (i = 0; i < num_clients; i++) { | |
| 571 | − struct fimc_sensor_info *si = &fmd->sensor[i]; | |
| 572 | − struct v4l2_subdev *sd; | |
| 573 | − | |
| 574 | − si->pdata = pdata->source_info[i]; | |
| 575 | − ret = __fimc_md_set_camclk(fmd, &si->pdata, true); | |
| 576 | − if (ret) | |
| 577 | − break; | |
| 578 | − sd = fimc_md_register_sensor(fmd, &si->pdata); | |
| 579 | − ret = __fimc_md_set_camclk(fmd, &si->pdata, false); | |
| 580 | − | |
| 581 | − if (IS_ERR(sd)) { | |
| 582 | − si->subdev = NULL; | |
| 583 | − ret = PTR_ERR(sd); | |
| 584 | − break; | |
| 585 | − } | |
| 586 | − si->subdev = sd; | |
| 587 | − if (ret) | |
| 588 | − break; | |
| 589 | − } | |
| 590 | − } | |
| 591 | − | |
| 592 | − pm_runtime_put(fmd->pmf); | |
| 593 | − return ret; | |
| 594 | −} | |
| 595 | 464 | |
| 596 | 465 | /* |
| 597 | 466 | * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration. |
| 598 | 467 | */ |
| 599 | − | |
| 600 | 468 | static int register_fimc_lite_entity(struct fimc_md *fmd, |
| 601 | 469 | struct fimc_lite *fimc_lite) |
| 602 | 470 | { |
| @@ -753,35 +621,9 @@ dev_unlock: · 150 unmodified lines | ||
| 753 | 621 | return ret; |
| 754 | 622 | } |
| 755 | 623 | |
| 756 | −static int fimc_md_pdev_match(struct device *dev, void *data) | |
| 757 | −{ | |
| 758 | − struct platform_device *pdev = to_platform_device(dev); | |
| 759 | − int plat_entity = -1; | |
| 760 | − int ret; | |
| 761 | − char *p; | |
| 762 | − | |
| 763 | − if (!get_device(dev)) | |
| 764 | − return -ENODEV; | |
| 765 | − | |
| 766 | − if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) { | |
| 767 | − plat_entity = IDX_CSIS; | |
| 768 | − } else { | |
| 769 | − p = strstr(pdev->name, "fimc"); | |
| 770 | − if (p && *(p + 4) == 0) | |
| 771 | − plat_entity = IDX_FIMC; | |
| 772 | − } | |
| 773 | − | |
| 774 | − if (plat_entity >= 0) | |
| 775 | − ret = fimc_md_register_platform_entity(data, pdev, | |
| 776 | − plat_entity); | |
| 777 | − put_device(dev); | |
| 778 | − return 0; | |
| 779 | −} | |
| 780 | − | |
| 781 | 624 | /* Register FIMC, FIMC-LITE and CSIS media entities */ |
| 782 | −#ifdef CONFIG_OF | |
| 783 | −static int fimc_md_register_of_platform_entities(struct fimc_md *fmd, | |
| 784 | − struct device_node *parent) | |
| 625 | +static int fimc_md_register_platform_entities(struct fimc_md *fmd, | |
| 626 | + struct device_node *parent) | |
| 785 | 627 | { |
| 786 | 628 | struct device_node *node; |
| 787 | 629 | int ret = 0; |
| @@ -815,9 +657,6 @@ static int fimc_md_register_of_platform_entities(struct fimc_md *fmd, · 27 unmodified lines | ||
| 815 | 657 | |
| 816 | 658 | return ret; |
| 817 | 659 | } |
| 818 | −#else | |
| 819 | −#define fimc_md_register_of_platform_entities(fmd, node) (-ENOSYS) | |
| 820 | −#endif | |
| 821 | 660 | |
| 822 | 661 | static void fimc_md_unregister_entities(struct fimc_md *fmd) |
| 823 | 662 | { |
| @@ -845,14 +684,6 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) · 21 unmodified lines | ||
| 845 | 684 | v4l2_device_unregister_subdev(fmd->csis[i].sd); |
| 846 | 685 | fmd->csis[i].sd = NULL; |
| 847 | 686 | } |
| 848 | − if (fmd->pdev->dev.of_node == NULL) { | |
| 849 | − for (i = 0; i < fmd->num_sensors; i++) { | |
| 850 | − if (fmd->sensor[i].subdev == NULL) | |
| 851 | − continue; | |
| 852 | − fimc_md_unregister_sensor(fmd->sensor[i].subdev); | |
| 853 | − fmd->sensor[i].subdev = NULL; | |
| 854 | − } | |
| 855 | − } | |
| 856 | 687 | |
| 857 | 688 | if (fmd->fimc_is) |
| 858 | 689 | v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev); |
| @@ -1137,7 +968,7 @@ static void fimc_md_put_clocks(struct fimc_md *fmd) · 278 unmodified lines | ||
| 1137 | 968 | |
| 1138 | 969 | static int fimc_md_get_clocks(struct fimc_md *fmd) |
| 1139 | 970 | { |
| 1140 | − struct device *dev = NULL; | |
| 971 | + struct device *dev = &fmd->pdev->dev; | |
| 1141 | 972 | char clk_name[32]; |
| 1142 | 973 | struct clk *clock; |
| 1143 | 974 | int i, ret = 0; |
| @@ -1145,16 +976,12 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) · 1 unmodified line | ||
| 1145 | 976 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) |
| 1146 | 977 | fmd->camclk[i].clock = ERR_PTR(-EINVAL); |
| 1147 | 978 | |
| 1148 | − if (fmd->pdev->dev.of_node) | |
| 1149 | − dev = &fmd->pdev->dev; | |
| 1150 | − | |
| 1151 | 979 | for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { |
| 1152 | 980 | snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); |
| 1153 | 981 | clock = clk_get(dev, clk_name); |
| 1154 | 982 | |
| 1155 | 983 | if (IS_ERR(clock)) { |
| 1156 | − dev_err(&fmd->pdev->dev, "Failed to get clock: %s\n", | |
| 1157 | − clk_name); | |
| 984 | + dev_err(dev, "Failed to get clock: %s\n", clk_name); | |
| 1158 | 985 | ret = PTR_ERR(clock); |
| 1159 | 986 | break; |
| 1160 | 987 | } |
| @@ -1188,86 +1015,6 @@ static int fimc_md_get_clocks(struct fimc_md *fmd) · 27 unmodified lines | ||
| 1188 | 1015 | return ret; |
| 1189 | 1016 | } |
| 1190 | 1017 | |
| 1191 | −static int __fimc_md_set_camclk(struct fimc_md *fmd, | |
| 1192 | − struct fimc_source_info *si, | |
| 1193 | − bool on) | |
| 1194 | −{ | |
| 1195 | − struct fimc_camclk_info *camclk; | |
| 1196 | − int ret = 0; | |
| 1197 | − | |
| 1198 | − /* | |
| 1199 | − * When device tree is used the sensor drivers are supposed to | |
| 1200 | − * control the clock themselves. This whole function will be | |
| 1201 | − * removed once S5PV210 platform is converted to the device tree. | |
| 1202 | − */ | |
| 1203 | − if (fmd->pdev->dev.of_node) | |
| 1204 | − return 0; | |
| 1205 | − | |
| 1206 | − if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf) | |
| 1207 | − return -EINVAL; | |
| 1208 | − | |
| 1209 | − camclk = &fmd->camclk[si->clk_id]; | |
| 1210 | − | |
| 1211 | − dbg("camclk %d, f: %lu, use_count: %d, on: %d", | |
| 1212 | − si->clk_id, si->clk_frequency, camclk->use_count, on); | |
| 1213 | − | |
| 1214 | − if (on) { | |
| 1215 | − if (camclk->use_count > 0 && | |
| 1216 | − camclk->frequency != si->clk_frequency) | |
| 1217 | − return -EINVAL; | |
| 1218 | − | |
| 1219 | − if (camclk->use_count++ == 0) { | |
| 1220 | − clk_set_rate(camclk->clock, si->clk_frequency); | |
| 1221 | − camclk->frequency = si->clk_frequency; | |
| 1222 | − ret = pm_runtime_get_sync(fmd->pmf); | |
| 1223 | − if (ret < 0) | |
| 1224 | − return ret; | |
| 1225 | − ret = clk_prepare_enable(camclk->clock); | |
| 1226 | − dbg("Enabled camclk %d: f: %lu", si->clk_id, | |
| 1227 | − clk_get_rate(camclk->clock)); | |
| 1228 | − } | |
| 1229 | − return ret; | |
| 1230 | − } | |
| 1231 | − | |
| 1232 | − if (WARN_ON(camclk->use_count == 0)) | |
| 1233 | − return 0; | |
| 1234 | − | |
| 1235 | − if (--camclk->use_count == 0) { | |
| 1236 | − clk_disable_unprepare(camclk->clock); | |
| 1237 | − pm_runtime_put(fmd->pmf); | |
| 1238 | − dbg("Disabled camclk %d", si->clk_id); | |
| 1239 | − } | |
| 1240 | − return ret; | |
| 1241 | −} | |
| 1242 | − | |
| 1243 | −/** | |
| 1244 | − * fimc_md_set_camclk - peripheral sensor clock setup | |
| 1245 | − * @sd: sensor subdev to configure sclk_cam clock for | |
| 1246 | − * @on: 1 to enable or 0 to disable the clock | |
| 1247 | − * | |
| 1248 | − * There are 2 separate clock outputs available in the SoC for external | |
| 1249 | − * image processors. These clocks are shared between all registered FIMC | |
| 1250 | − * devices to which sensors can be attached, either directly or through | |
| 1251 | − * the MIPI CSI receiver. The clock is allowed here to be used by | |
| 1252 | − * multiple sensors concurrently if they use same frequency. | |
| 1253 | − * This function should only be called when the graph mutex is held. | |
| 1254 | − */ | |
| 1255 | −int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) | |
| 1256 | −{ | |
| 1257 | − struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd); | |
| 1258 | − struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity); | |
| 1259 | − | |
| 1260 | − /* | |
| 1261 | − * If there is a clock provider registered the sensors will | |
| 1262 | − * handle their clock themselves, no need to control it on | |
| 1263 | − * the host interface side. | |
| 1264 | − */ | |
| 1265 | − if (fmd->clk_provider.num_clocks > 0) | |
| 1266 | − return 0; | |
| 1267 | − | |
| 1268 | − return __fimc_md_set_camclk(fmd, si, on); | |
| 1269 | −} | |
| 1270 | − | |
| 1271 | 1018 | static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) |
| 1272 | 1019 | { |
| 1273 | 1020 | struct exynos_video_entity *ve; |
| @@ -1426,7 +1173,6 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd) · 152 unmodified lines | ||
| 1426 | 1173 | return 0; |
| 1427 | 1174 | } |
| 1428 | 1175 | |
| 1429 | −#ifdef CONFIG_OF | |
| 1430 | 1176 | static int cam_clk_prepare(struct clk_hw *hw) |
| 1431 | 1177 | { |
| 1432 | 1178 | struct cam_clk *camclk = to_cam_clk(hw); |
| @@ -1518,10 +1264,6 @@ err: · 85 unmodified lines | ||
| 1518 | 1264 | fimc_md_unregister_clk_provider(fmd); |
| 1519 | 1265 | return ret; |
| 1520 | 1266 | } |
| 1521 | −#else | |
| 1522 | −#define fimc_md_register_clk_provider(fmd) (0) | |
| 1523 | −#define fimc_md_unregister_clk_provider(fmd) (0) | |
| 1524 | −#endif | |
| 1525 | 1267 | |
| 1526 | 1268 | static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, |
| 1527 | 1269 | struct v4l2_subdev *subdev, |
| @@ -1585,8 +1327,8 @@ static int fimc_md_probe(struct platform_device *pdev) · 57 unmodified lines | ||
| 1585 | 1327 | return -ENOMEM; |
| 1586 | 1328 | |
| 1587 | 1329 | spin_lock_init(&fmd->slock); |
| 1588 | − fmd->pdev = pdev; | |
| 1589 | 1330 | INIT_LIST_HEAD(&fmd->pipelines); |
| 1331 | + fmd->pdev = pdev; | |
| 1590 | 1332 | |
| 1591 | 1333 | strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", |
| 1592 | 1334 | sizeof(fmd->media_dev.model)); |
| @@ -1599,6 +1341,7 @@ static int fimc_md_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 1599 | 1341 | strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); |
| 1600 | 1342 | |
| 1601 | 1343 | fmd->use_isp = fimc_md_is_isp_available(dev->of_node); |
| 1344 | + fmd->user_subdev_api = true; | |
| 1602 | 1345 | |
| 1603 | 1346 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); |
| 1604 | 1347 | if (ret < 0) { |
| @@ -1616,8 +1359,6 @@ static int fimc_md_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 1616 | 1359 | if (ret) |
| 1617 | 1360 | goto err_md; |
| 1618 | 1361 | |
| 1619 | − fmd->user_subdev_api = (dev->of_node != NULL); | |
| 1620 | − | |
| 1621 | 1362 | ret = fimc_md_get_pinctrl(fmd); |
| 1622 | 1363 | if (ret < 0) { |
| 1623 | 1364 | if (ret != EPROBE_DEFER) |
| @@ -1630,22 +1371,16 @@ static int fimc_md_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 1630 | 1371 | /* Protect the media graph while we're registering entities */ |
| 1631 | 1372 | mutex_lock(&fmd->media_dev.graph_mutex); |
| 1632 | 1373 | |
| 1633 | − if (dev->of_node) | |
| 1634 | − ret = fimc_md_register_of_platform_entities(fmd, dev->of_node); | |
| 1635 | − else | |
| 1636 | − ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, | |
| 1637 | − fimc_md_pdev_match); | |
| 1374 | + ret = fimc_md_register_platform_entities(fmd, dev->of_node); | |
| 1638 | 1375 | if (ret) { |
| 1639 | 1376 | mutex_unlock(&fmd->media_dev.graph_mutex); |
| 1640 | 1377 | goto err_clk; |
| 1641 | 1378 | } |
| 1642 | 1379 | |
| 1643 | − if (dev->platform_data || dev->of_node) { | |
| 1644 | − ret = fimc_md_register_sensor_entities(fmd); | |
| 1645 | − if (ret) { | |
| 1646 | − mutex_unlock(&fmd->media_dev.graph_mutex); | |
| 1647 | − goto err_m_ent; | |
| 1648 | − } | |
| 1380 | + ret = fimc_md_register_sensor_entities(fmd); | |
| 1381 | + if (ret) { | |
| 1382 | + mutex_unlock(&fmd->media_dev.graph_mutex); | |
| 1383 | + goto err_m_ent; | |
| 1649 | 1384 | } |
| 1650 | 1385 | |
| 1651 | 1386 | mutex_unlock(&fmd->media_dev.graph_mutex); |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <media/media-entity.h> |
| 20 | 20 | #include <media/v4l2-device.h> |
| 21 | 21 | #include <media/v4l2-subdev.h> |
| 22 | −#include <media/s5p_fimc.h> | |
| 22 | +#include <media/exynos-fimc.h> | |
| 23 | 23 | |
| 24 | 24 | #include "fimc-core.h" |
| 25 | 25 | #include "fimc-lite.h" |
| @@ -22,14 +22,13 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/of.h> |
| 23 | 23 | #include <linux/of_graph.h> |
| 24 | 24 | #include <linux/phy/phy.h> |
| 25 | −#include <linux/platform_data/mipi-csis.h> | |
| 26 | 25 | #include <linux/platform_device.h> |
| 27 | 26 | #include <linux/pm_runtime.h> |
| 28 | 27 | #include <linux/regulator/consumer.h> |
| 29 | 28 | #include <linux/slab.h> |
| 30 | 29 | #include <linux/spinlock.h> |
| 31 | 30 | #include <linux/videodev2.h> |
| 32 | −#include <media/s5p_fimc.h> | |
| 31 | +#include <media/exynos-fimc.h> | |
| 33 | 32 | #include <media/v4l2-of.h> |
| 34 | 33 | #include <media/v4l2-subdev.h> |
| 35 | 34 | |
| @@ -730,26 +729,6 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) · 694 unmodified lines | ||
| 730 | 729 | return IRQ_HANDLED; |
| 731 | 730 | } |
| 732 | 731 | |
| 733 | −static int s5pcsis_get_platform_data(struct platform_device *pdev, | |
| 734 | − struct csis_state *state) | |
| 735 | −{ | |
| 736 | − struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data; | |
| 737 | − | |
| 738 | − if (pdata == NULL) { | |
| 739 | − dev_err(&pdev->dev, "Platform data not specified\n"); | |
| 740 | − return -EINVAL; | |
| 741 | − } | |
| 742 | − | |
| 743 | − state->clk_frequency = pdata->clk_rate; | |
| 744 | − state->num_lanes = pdata->lanes; | |
| 745 | − state->hs_settle = pdata->hs_settle; | |
| 746 | − state->index = max(0, pdev->id); | |
| 747 | − state->max_num_lanes = state->index ? CSIS1_MAX_LANES : | |
| 748 | − CSIS0_MAX_LANES; | |
| 749 | − return 0; | |
| 750 | −} | |
| 751 | − | |
| 752 | −#ifdef CONFIG_OF | |
| 753 | 732 | static int s5pcsis_parse_dt(struct platform_device *pdev, |
| 754 | 733 | struct csis_state *state) |
| 755 | 734 | { |
| @@ -787,9 +766,6 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, · 31 unmodified lines | ||
| 787 | 766 | |
| 788 | 767 | return 0; |
| 789 | 768 | } |
| 790 | −#else | |
| 791 | −#define s5pcsis_parse_dt(pdev, state) (-ENOSYS) | |
| 792 | −#endif | |
| 793 | 769 | |
| 794 | 770 | static int s5pcsis_pm_resume(struct device *dev, bool runtime); |
| 795 | 771 | static const struct of_device_id s5pcsis_of_match[]; |
| @@ -812,19 +788,14 @@ static int s5pcsis_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 812 | 788 | spin_lock_init(&state->slock); |
| 813 | 789 | state->pdev = pdev; |
| 814 | 790 | |
| 815 | − if (dev->of_node) { | |
| 816 | − of_id = of_match_node(s5pcsis_of_match, dev->of_node); | |
| 817 | − if (WARN_ON(of_id == NULL)) | |
| 818 | − return -EINVAL; | |
| 819 | − | |
| 820 | − drv_data = of_id->data; | |
| 821 | − state->interrupt_mask = drv_data->interrupt_mask; | |
| 791 | + of_id = of_match_node(s5pcsis_of_match, dev->of_node); | |
| 792 | + if (WARN_ON(of_id == NULL)) | |
| 793 | + return -EINVAL; | |
| 822 | 794 | |
| 823 | − ret = s5pcsis_parse_dt(pdev, state); | |
| 824 | − } else { | |
| 825 | − ret = s5pcsis_get_platform_data(pdev, state); | |
| 826 | − } | |
| 795 | + drv_data = of_id->data; | |
| 796 | + state->interrupt_mask = drv_data->interrupt_mask; | |
| 827 | 797 | |
| 798 | + ret = s5pcsis_parse_dt(pdev, state); | |
| 828 | 799 | if (ret < 0) |
| 829 | 800 | return ret; |
| 830 | 801 | |
| @@ -964,7 +964,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) · 963 unmodified lines | ||
| 964 | 964 | struct viu_fh *fh = priv; |
| 965 | 965 | |
| 966 | 966 | fh->dev->std = id; |
| 967 | − decoder_call(fh->dev, core, s_std, id); | |
| 967 | + decoder_call(fh->dev, video, s_std, id); | |
| 968 | 968 | return 0; |
| 969 | 969 | } |
| 970 | 970 | |
| @@ -1156,7 +1156,7 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) · 1155 unmodified lines | ||
| 1156 | 1156 | return mcam_read_setup(cam); |
| 1157 | 1157 | } |
| 1158 | 1158 | |
| 1159 | −static int mcam_vb_stop_streaming(struct vb2_queue *vq) | |
| 1159 | +static void mcam_vb_stop_streaming(struct vb2_queue *vq) | |
| 1160 | 1160 | { |
| 1161 | 1161 | struct mcam_camera *cam = vb2_get_drv_priv(vq); |
| 1162 | 1162 | unsigned long flags; |
| @@ -1164,10 +1164,10 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 1164 | 1164 | if (cam->state == S_BUFWAIT) { |
| 1165 | 1165 | /* They never gave us buffers */ |
| 1166 | 1166 | cam->state = S_IDLE; |
| 1167 | − return 0; | |
| 1167 | + return; | |
| 1168 | 1168 | } |
| 1169 | 1169 | if (cam->state != S_STREAMING) |
| 1170 | − return -EINVAL; | |
| 1170 | + return; | |
| 1171 | 1171 | mcam_ctlr_stop_dma(cam); |
| 1172 | 1172 | /* |
| 1173 | 1173 | * Reset the CCIC PHY after stopping streaming, |
| @@ -1182,7 +1182,6 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq) · 8 unmodified lines | ||
| 1182 | 1182 | spin_lock_irqsave(&cam->dev_lock, flags); |
| 1183 | 1183 | INIT_LIST_HEAD(&cam->buffers); |
| 1184 | 1184 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
| 1185 | − return 0; | |
| 1186 | 1185 | } |
| 1187 | 1186 | |
| 1188 | 1187 | |
| @@ -787,7 +787,7 @@ static int m2mtest_start_streaming(struct vb2_queue *q, unsigned count) · 786 unmodified lines | ||
| 787 | 787 | return 0; |
| 788 | 788 | } |
| 789 | 789 | |
| 790 | −static int m2mtest_stop_streaming(struct vb2_queue *q) | |
| 790 | +static void m2mtest_stop_streaming(struct vb2_queue *q) | |
| 791 | 791 | { |
| 792 | 792 | struct m2mtest_ctx *ctx = vb2_get_drv_priv(q); |
| 793 | 793 | struct vb2_buffer *vb; |
| @@ -799,12 +799,11 @@ static int m2mtest_stop_streaming(struct vb2_queue *q) · 5 unmodified lines | ||
| 799 | 799 | else |
| 800 | 800 | vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); |
| 801 | 801 | if (vb == NULL) |
| 802 | − return 0; | |
| 802 | + return; | |
| 803 | 803 | spin_lock_irqsave(&ctx->dev->irqlock, flags); |
| 804 | 804 | v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); |
| 805 | 805 | spin_unlock_irqrestore(&ctx->dev->irqlock, flags); |
| 806 | 806 | } |
| 807 | − return 0; | |
| 808 | 807 | } |
| 809 | 808 | |
| 810 | 809 | static struct vb2_ops m2mtest_qops = { |
| @@ -207,10 +207,8 @@ struct emmaprp_dev { · 206 unmodified lines | ||
| 207 | 207 | struct mutex dev_mutex; |
| 208 | 208 | spinlock_t irqlock; |
| 209 | 209 | |
| 210 | − int irq_emma; | |
| 211 | 210 | void __iomem *base_emma; |
| 212 | 211 | struct clk *clk_emma_ahb, *clk_emma_ipg; |
| 213 | − struct resource *res_emma; | |
| 214 | 212 | |
| 215 | 213 | struct v4l2_m2m_dev *m2m_dev; |
| 216 | 214 | struct vb2_alloc_ctx *alloc_ctx; |
| @@ -901,9 +899,8 @@ static int emmaprp_probe(struct platform_device *pdev) · 684 unmodified lines | ||
| 901 | 899 | { |
| 902 | 900 | struct emmaprp_dev *pcdev; |
| 903 | 901 | struct video_device *vfd; |
| 904 | − struct resource *res_emma; | |
| 905 | − int irq_emma; | |
| 906 | − int ret; | |
| 902 | + struct resource *res; | |
| 903 | + int irq, ret; | |
| 907 | 904 | |
| 908 | 905 | pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); |
| 909 | 906 | if (!pcdev) |
| @@ -920,12 +917,10 @@ static int emmaprp_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 920 | 917 | if (IS_ERR(pcdev->clk_emma_ahb)) |
| 921 | 918 | return PTR_ERR(pcdev->clk_emma_ahb); |
| 922 | 919 | |
| 923 | − irq_emma = platform_get_irq(pdev, 0); | |
| 924 | − res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 925 | − if (irq_emma < 0 || res_emma == NULL) { | |
| 926 | − dev_err(&pdev->dev, "Missing platform resources data\n"); | |
| 927 | − return -ENODEV; | |
| 928 | − } | |
| 920 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 921 | + pcdev->base_emma = devm_ioremap_resource(&pdev->dev, res); | |
| 922 | + if (IS_ERR(pcdev->base_emma)) | |
| 923 | + return PTR_ERR(pcdev->base_emma); | |
| 929 | 924 | |
| 930 | 925 | ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); |
| 931 | 926 | if (ret) |
| @@ -952,20 +947,11 @@ static int emmaprp_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 952 | 947 | |
| 953 | 948 | platform_set_drvdata(pdev, pcdev); |
| 954 | 949 | |
| 955 | − pcdev->base_emma = devm_ioremap_resource(&pdev->dev, res_emma); | |
| 956 | − if (IS_ERR(pcdev->base_emma)) { | |
| 957 | − ret = PTR_ERR(pcdev->base_emma); | |
| 958 | − goto rel_vdev; | |
| 959 | − } | |
| 960 | − | |
| 961 | − pcdev->irq_emma = irq_emma; | |
| 962 | − pcdev->res_emma = res_emma; | |
| 963 | − | |
| 964 | − if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, | |
| 965 | − 0, MEM2MEM_NAME, pcdev) < 0) { | |
| 966 | − ret = -ENODEV; | |
| 950 | + irq = platform_get_irq(pdev, 0); | |
| 951 | + ret = devm_request_irq(&pdev->dev, irq, emmaprp_irq, 0, | |
| 952 | + dev_name(&pdev->dev), pcdev); | |
| 953 | + if (ret) | |
| 967 | 954 | goto rel_vdev; |
| 968 | − } | |
| 969 | 955 | |
| 970 | 956 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
| 971 | 957 | if (IS_ERR(pcdev->alloc_ctx)) { |
| @@ -999,6 +985,8 @@ rel_vdev: · 27 unmodified lines | ||
| 999 | 985 | unreg_dev: |
| 1000 | 986 | v4l2_device_unregister(&pcdev->v4l2_dev); |
| 1001 | 987 | |
| 988 | + mutex_destroy(&pcdev->dev_mutex); | |
| 989 | + | |
| 1002 | 990 | return ret; |
| 1003 | 991 | } |
| 1004 | 992 | |
| @@ -1012,6 +1000,7 @@ static int emmaprp_remove(struct platform_device *pdev) · 7 unmodified lines | ||
| 1012 | 1000 | v4l2_m2m_release(pcdev->m2m_dev); |
| 1013 | 1001 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
| 1014 | 1002 | v4l2_device_unregister(&pcdev->v4l2_dev); |
| 1003 | + mutex_destroy(&pcdev->dev_mutex); | |
| 1015 | 1004 | |
| 1016 | 1005 | return 0; |
| 1017 | 1006 | } |
| @@ -435,10 +435,10 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 434 unmodified lines | ||
| 435 | 435 | return 0; |
| 436 | 436 | } |
| 437 | 437 | |
| 438 | −static int stop_streaming(struct vb2_queue *vq) | |
| 438 | +static void stop_streaming(struct vb2_queue *vq) | |
| 439 | 439 | { |
| 440 | 440 | struct camif_vp *vp = vb2_get_drv_priv(vq); |
| 441 | − return camif_stop_capture(vp); | |
| 441 | + camif_stop_capture(vp); | |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | 444 | static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt, |
| @@ -192,8 +192,7 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = { · 191 unmodified lines | ||
| 192 | 192 | .colplanes = 2, |
| 193 | 193 | .h_align = 4, |
| 194 | 194 | .v_align = 4, |
| 195 | − .flags = SJPEG_FMT_FLAG_ENC_OUTPUT | | |
| 196 | − SJPEG_FMT_FLAG_DEC_CAPTURE | | |
| 195 | + .flags = SJPEG_FMT_FLAG_DEC_CAPTURE | | |
| 197 | 196 | SJPEG_FMT_FLAG_S5P | |
| 198 | 197 | SJPEG_FMT_NON_RGB, |
| 199 | 198 | .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420, |
| @@ -959,7 +958,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) · 759 unmodified lines | ||
| 959 | 958 | static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx, |
| 960 | 959 | u32 pixelformat, unsigned int fmt_type) |
| 961 | 960 | { |
| 962 | − unsigned int k, fmt_flag, ver_flag; | |
| 961 | + unsigned int k, fmt_flag; | |
| 963 | 962 | |
| 964 | 963 | if (ctx->mode == S5P_JPEG_ENCODE) |
| 965 | 964 | fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ? |
| @@ -970,16 +969,11 @@ static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx, · 4 unmodified lines | ||
| 970 | 969 | SJPEG_FMT_FLAG_DEC_OUTPUT : |
| 971 | 970 | SJPEG_FMT_FLAG_DEC_CAPTURE; |
| 972 | 971 | |
| 973 | − if (ctx->jpeg->variant->version == SJPEG_S5P) | |
| 974 | − ver_flag = SJPEG_FMT_FLAG_S5P; | |
| 975 | − else | |
| 976 | − ver_flag = SJPEG_FMT_FLAG_EXYNOS4; | |
| 977 | − | |
| 978 | 972 | for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) { |
| 979 | 973 | struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k]; |
| 980 | 974 | if (fmt->fourcc == pixelformat && |
| 981 | 975 | fmt->flags & fmt_flag && |
| 982 | − fmt->flags & ver_flag) { | |
| 976 | + fmt->flags & ctx->jpeg->variant->fmt_ver_flag) { | |
| 983 | 977 | return fmt; |
| 984 | 978 | } |
| 985 | 979 | } |
| @@ -1069,15 +1063,17 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, · 83 unmodified lines | ||
| 1069 | 1063 | return -EINVAL; |
| 1070 | 1064 | } |
| 1071 | 1065 | |
| 1066 | + if ((ctx->jpeg->variant->version != SJPEG_EXYNOS4) || | |
| 1067 | + (ctx->mode != S5P_JPEG_DECODE)) | |
| 1068 | + goto exit; | |
| 1069 | + | |
| 1072 | 1070 | /* |
| 1073 | 1071 | * The exynos4x12 device requires resulting YUV image |
| 1074 | 1072 | * subsampling not to be lower than the input jpeg subsampling. |
| 1075 | 1073 | * If this requirement is not met then downgrade the requested |
| 1076 | 1074 | * capture format to the one with subsampling equal to the input jpeg. |
| 1077 | 1075 | */ |
| 1078 | − if ((ctx->jpeg->variant->version != SJPEG_S5P) && | |
| 1079 | − (ctx->mode == S5P_JPEG_DECODE) && | |
| 1080 | − (fmt->flags & SJPEG_FMT_NON_RGB) && | |
| 1076 | + if ((fmt->flags & SJPEG_FMT_NON_RGB) && | |
| 1081 | 1077 | (fmt->subsampling < ctx->subsampling)) { |
| 1082 | 1078 | ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling, |
| 1083 | 1079 | fmt->fourcc, |
| @@ -1090,6 +1086,23 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, · 6 unmodified lines | ||
| 1090 | 1086 | FMT_TYPE_CAPTURE); |
| 1091 | 1087 | } |
| 1092 | 1088 | |
| 1089 | + /* | |
| 1090 | + * Decompression of a JPEG file with 4:2:0 subsampling and odd | |
| 1091 | + * width to the YUV 4:2:0 compliant formats produces a raw image | |
| 1092 | + * with broken luma component. Adjust capture format to RGB565 | |
| 1093 | + * in such a case. | |
| 1094 | + */ | |
| 1095 | + if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 && | |
| 1096 | + (ctx->out_q.w & 1) && | |
| 1097 | + (pix->pixelformat == V4L2_PIX_FMT_NV12 || | |
| 1098 | + pix->pixelformat == V4L2_PIX_FMT_NV21 || | |
| 1099 | + pix->pixelformat == V4L2_PIX_FMT_YUV420)) { | |
| 1100 | + pix->pixelformat = V4L2_PIX_FMT_RGB565; | |
| 1101 | + fmt = s5p_jpeg_find_format(ctx, pix->pixelformat, | |
| 1102 | + FMT_TYPE_CAPTURE); | |
| 1103 | + } | |
| 1104 | + | |
| 1105 | +exit: | |
| 1093 | 1106 | return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE); |
| 1094 | 1107 | } |
| 1095 | 1108 | |
| @@ -1111,6 +1124,32 @@ static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, · 15 unmodified lines | ||
| 1111 | 1124 | return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT); |
| 1112 | 1125 | } |
| 1113 | 1126 | |
| 1127 | +static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx, | |
| 1128 | + struct v4l2_format *f, | |
| 1129 | + int fmt_depth) | |
| 1130 | +{ | |
| 1131 | + struct v4l2_pix_format *pix = &f->fmt.pix; | |
| 1132 | + u32 pix_fmt = f->fmt.pix.pixelformat; | |
| 1133 | + int w = pix->width, h = pix->height, wh_align; | |
| 1134 | + | |
| 1135 | + if (pix_fmt == V4L2_PIX_FMT_RGB32 || | |
| 1136 | + pix_fmt == V4L2_PIX_FMT_NV24 || | |
| 1137 | + pix_fmt == V4L2_PIX_FMT_NV42 || | |
| 1138 | + pix_fmt == V4L2_PIX_FMT_NV12 || | |
| 1139 | + pix_fmt == V4L2_PIX_FMT_NV21 || | |
| 1140 | + pix_fmt == V4L2_PIX_FMT_YUV420) | |
| 1141 | + wh_align = 4; | |
| 1142 | + else | |
| 1143 | + wh_align = 1; | |
| 1144 | + | |
| 1145 | + jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH, | |
| 1146 | + S5P_JPEG_MAX_WIDTH, wh_align, | |
| 1147 | + &h, S5P_JPEG_MIN_HEIGHT, | |
| 1148 | + S5P_JPEG_MAX_HEIGHT, wh_align); | |
| 1149 | + | |
| 1150 | + return w * h * fmt_depth >> 3; | |
| 1151 | +} | |
| 1152 | + | |
| 1114 | 1153 | static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) |
| 1115 | 1154 | { |
| 1116 | 1155 | struct vb2_queue *vq; |
| @@ -1137,10 +1176,24 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) · 20 unmodified lines | ||
| 1137 | 1176 | q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type); |
| 1138 | 1177 | q_data->w = pix->width; |
| 1139 | 1178 | q_data->h = pix->height; |
| 1140 | − if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) | |
| 1141 | − q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; | |
| 1142 | − else | |
| 1179 | + if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { | |
| 1180 | + /* | |
| 1181 | + * During encoding Exynos4x12 SoCs access wider memory area | |
| 1182 | + * than it results from Image_x and Image_y values written to | |
| 1183 | + * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu | |
| 1184 | + * page fault calculate proper buffer size in such a case. | |
| 1185 | + */ | |
| 1186 | + if (ct->jpeg->variant->version == SJPEG_EXYNOS4 && | |
| 1187 | + f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE) | |
| 1188 | + q_data->size = exynos4_jpeg_get_output_buffer_size(ct, | |
| 1189 | + f, | |
| 1190 | + q_data->fmt->depth); | |
| 1191 | + else | |
| 1192 | + q_data->size = q_data->w * q_data->h * | |
| 1193 | + q_data->fmt->depth >> 3; | |
| 1194 | + } else { | |
| 1143 | 1195 | q_data->size = pix->sizeimage; |
| 1196 | + } | |
| 1144 | 1197 | |
| 1145 | 1198 | if (f_type == FMT_TYPE_OUTPUT) { |
| 1146 | 1199 | ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler, |
| @@ -1182,8 +1235,7 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv, · 35 unmodified lines | ||
| 1182 | 1235 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
| 1183 | 1236 | |
| 1184 | 1237 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && |
| 1185 | − s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && | |
| 1186 | − ctx->jpeg->variant->version != SJPEG_S5P) | |
| 1238 | + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
| 1187 | 1239 | return -EINVAL; |
| 1188 | 1240 | |
| 1189 | 1241 | /* For JPEG blob active == default == bounds */ |
| @@ -1571,7 +1623,7 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { · 381 unmodified lines | ||
| 1571 | 1623 | .job_abort = s5p_jpeg_job_abort, |
| 1572 | 1624 | } |
| 1573 | 1625 | ; |
| 1574 | −static struct v4l2_m2m_ops exynos_jpeg_m2m_ops = { | |
| 1626 | +static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { | |
| 1575 | 1627 | .device_run = exynos4_jpeg_device_run, |
| 1576 | 1628 | .job_ready = s5p_jpeg_job_ready, |
| 1577 | 1629 | .job_abort = s5p_jpeg_job_abort, |
| @@ -1670,13 +1722,11 @@ static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) · 92 unmodified lines | ||
| 1670 | 1722 | return ret > 0 ? 0 : ret; |
| 1671 | 1723 | } |
| 1672 | 1724 | |
| 1673 | −static int s5p_jpeg_stop_streaming(struct vb2_queue *q) | |
| 1725 | +static void s5p_jpeg_stop_streaming(struct vb2_queue *q) | |
| 1674 | 1726 | { |
| 1675 | 1727 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q); |
| 1676 | 1728 | |
| 1677 | 1729 | pm_runtime_put(ctx->jpeg->dev); |
| 1678 | − | |
| 1679 | − return 0; | |
| 1680 | 1730 | } |
| 1681 | 1731 | |
| 1682 | 1732 | static struct vb2_ops s5p_jpeg_qops = { |
| @@ -1845,7 +1895,7 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv) · 162 unmodified lines | ||
| 1845 | 1895 | return IRQ_HANDLED; |
| 1846 | 1896 | } |
| 1847 | 1897 | |
| 1848 | −static void *jpeg_get_drv_data(struct platform_device *pdev); | |
| 1898 | +static void *jpeg_get_drv_data(struct device *dev); | |
| 1849 | 1899 | |
| 1850 | 1900 | /* |
| 1851 | 1901 | * ============================================================================ |
| @@ -1857,18 +1907,14 @@ static int s5p_jpeg_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 1857 | 1907 | { |
| 1858 | 1908 | struct s5p_jpeg *jpeg; |
| 1859 | 1909 | struct resource *res; |
| 1860 | − struct v4l2_m2m_ops *samsung_jpeg_m2m_ops; | |
| 1861 | 1910 | int ret; |
| 1862 | 1911 | |
| 1863 | − if (!pdev->dev.of_node) | |
| 1864 | − return -ENODEV; | |
| 1865 | − | |
| 1866 | 1912 | /* JPEG IP abstraction struct */ |
| 1867 | 1913 | jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL); |
| 1868 | 1914 | if (!jpeg) |
| 1869 | 1915 | return -ENOMEM; |
| 1870 | 1916 | |
| 1871 | − jpeg->variant = jpeg_get_drv_data(pdev); | |
| 1917 | + jpeg->variant = jpeg_get_drv_data(&pdev->dev); | |
| 1872 | 1918 | |
| 1873 | 1919 | mutex_init(&jpeg->lock); |
| 1874 | 1920 | spin_lock_init(&jpeg->slock); |
| @@ -1911,13 +1957,8 @@ static int s5p_jpeg_probe(struct platform_device *pdev) · 36 unmodified lines | ||
| 1911 | 1957 | goto clk_get_rollback; |
| 1912 | 1958 | } |
| 1913 | 1959 | |
| 1914 | − if (jpeg->variant->version == SJPEG_S5P) | |
| 1915 | − samsung_jpeg_m2m_ops = &s5p_jpeg_m2m_ops; | |
| 1916 | − else | |
| 1917 | − samsung_jpeg_m2m_ops = &exynos_jpeg_m2m_ops; | |
| 1918 | − | |
| 1919 | 1960 | /* mem2mem device */ |
| 1920 | − jpeg->m2m_dev = v4l2_m2m_init(samsung_jpeg_m2m_ops); | |
| 1961 | + jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops); | |
| 1921 | 1962 | if (IS_ERR(jpeg->m2m_dev)) { |
| 1922 | 1963 | v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n"); |
| 1923 | 1964 | ret = PTR_ERR(jpeg->m2m_dev); |
| @@ -2102,15 +2143,18 @@ static const struct dev_pm_ops s5p_jpeg_pm_ops = { · 178 unmodified lines | ||
| 2102 | 2143 | SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume, NULL) |
| 2103 | 2144 | }; |
| 2104 | 2145 | |
| 2105 | −#ifdef CONFIG_OF | |
| 2106 | 2146 | static struct s5p_jpeg_variant s5p_jpeg_drvdata = { |
| 2107 | 2147 | .version = SJPEG_S5P, |
| 2108 | 2148 | .jpeg_irq = s5p_jpeg_irq, |
| 2149 | + .m2m_ops = &s5p_jpeg_m2m_ops, | |
| 2150 | + .fmt_ver_flag = SJPEG_FMT_FLAG_S5P, | |
| 2109 | 2151 | }; |
| 2110 | 2152 | |
| 2111 | 2153 | static struct s5p_jpeg_variant exynos4_jpeg_drvdata = { |
| 2112 | 2154 | .version = SJPEG_EXYNOS4, |
| 2113 | 2155 | .jpeg_irq = exynos4_jpeg_irq, |
| 2156 | + .m2m_ops = &exynos4_jpeg_m2m_ops, | |
| 2157 | + .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS4, | |
| 2114 | 2158 | }; |
| 2115 | 2159 | |
| 2116 | 2160 | static const struct of_device_id samsung_jpeg_match[] = { |
| @@ -2129,19 +2173,21 @@ static const struct of_device_id samsung_jpeg_match[] = { · 12 unmodified lines | ||
| 2129 | 2173 | |
| 2130 | 2174 | MODULE_DEVICE_TABLE(of, samsung_jpeg_match); |
| 2131 | 2175 | |
| 2132 | −static void *jpeg_get_drv_data(struct platform_device *pdev) | |
| 2176 | +static void *jpeg_get_drv_data(struct device *dev) | |
| 2133 | 2177 | { |
| 2134 | 2178 | struct s5p_jpeg_variant *driver_data = NULL; |
| 2135 | 2179 | const struct of_device_id *match; |
| 2136 | 2180 | |
| 2137 | − match = of_match_node(of_match_ptr(samsung_jpeg_match), | |
| 2138 | − pdev->dev.of_node); | |
| 2181 | + if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) | |
| 2182 | + return &s5p_jpeg_drvdata; | |
| 2183 | + | |
| 2184 | + match = of_match_node(samsung_jpeg_match, dev->of_node); | |
| 2185 | + | |
| 2139 | 2186 | if (match) |
| 2140 | 2187 | driver_data = (struct s5p_jpeg_variant *)match->data; |
| 2141 | 2188 | |
| 2142 | 2189 | return driver_data; |
| 2143 | 2190 | } |
| 2144 | −#endif | |
| 2145 | 2191 | |
| 2146 | 2192 | static struct platform_driver s5p_jpeg_driver = { |
| 2147 | 2193 | .probe = s5p_jpeg_probe, |
| @@ -117,8 +117,10 @@ struct s5p_jpeg { · 116 unmodified lines | ||
| 117 | 117 | }; |
| 118 | 118 | |
| 119 | 119 | struct s5p_jpeg_variant { |
| 120 | − unsigned int version; | |
| 121 | − irqreturn_t (*jpeg_irq)(int irq, void *priv); | |
| 120 | + unsigned int version; | |
| 121 | + unsigned int fmt_ver_flag; | |
| 122 | + struct v4l2_m2m_ops *m2m_ops; | |
| 123 | + irqreturn_t (*jpeg_irq)(int irq, void *priv); | |
| 122 | 124 | }; |
| 123 | 125 | |
| 124 | 126 | /** |
| @@ -141,6 +141,7 @@ · 140 unmodified lines | ||
| 141 | 141 | #define S5P_FIMV_D_SLICE_IF_ENABLE_V6 0xf4c4 |
| 142 | 142 | #define S5P_FIMV_D_PICTURE_TAG_V6 0xf4c8 |
| 143 | 143 | #define S5P_FIMV_D_STREAM_DATA_SIZE_V6 0xf4d0 |
| 144 | +#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6 0xf47c | |
| 144 | 145 | |
| 145 | 146 | /* Display information register */ |
| 146 | 147 | #define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6 0xf500 |
| @@ -381,8 +382,7 @@ · 234 unmodified lines | ||
| 381 | 382 | (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) |
| 382 | 383 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64) |
| 383 | 384 | #define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \ |
| 384 | − ((w) * ((h) * 64 + 144) + (2048/16 * (h) * 64) + \ | |
| 385 | − (2048/16 * 256 + 8320)) | |
| 385 | + ((w) * 144 + 8192 * (h) + 49216 + 1048576) | |
| 386 | 386 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \ |
| 387 | 387 | (2096 * ((w) + (h) + 1)) |
| 388 | 388 | #define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h) ((w) * 400) |
| @@ -18,8 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #define S5P_FIMV_CODEC_VP8_ENC_V7 25 |
| 19 | 19 | |
| 20 | 20 | /* Additional registers for v7 */ |
| 21 | −#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7 0xf47c | |
| 22 | − | |
| 23 | 21 | #define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0 |
| 24 | 22 | #define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4 |
| 25 | 23 | #define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8 |
| @@ -56,6 +54,7 @@ · 30 unmodified lines | ||
| 56 | 54 | (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216) |
| 57 | 55 | |
| 58 | 56 | #define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \ |
| 59 | − (((w) * 48) + (((w) + 1) / 2 * 128) + 144 + 8192) | |
| 57 | + (((w) * 48) + 8192 + ((((w) + 1) / 2) * 128) + 144 + \ | |
| 58 | + ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4)) | |
| 60 | 59 | |
| 61 | 60 | #endif /*_REGS_MFC_V7_H*/ |
| @@ -0,0 +1,124 @@ | ||
| 1 | +/* | |
| 2 | + * Register definition file for Samsung MFC V8.x Interface (FIMV) driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2014 Samsung Electronics Co., Ltd. | |
| 5 | + * http://www.samsung.com/ | |
| 6 | + * | |
| 7 | + * This program is free software; you can redistribute it and/or modify | |
| 8 | + * it under the terms of the GNU General Public License version 2 as | |
| 9 | + * published by the Free Software Foundation. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef _REGS_MFC_V8_H | |
| 13 | +#define _REGS_MFC_V8_H | |
| 14 | + | |
| 15 | +#include <linux/sizes.h> | |
| 16 | +#include "regs-mfc-v7.h" | |
| 17 | + | |
| 18 | +/* Additional registers for v8 */ | |
| 19 | +#define S5P_FIMV_D_MVC_NUM_VIEWS_V8 0xf104 | |
| 20 | +#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8 0xf144 | |
| 21 | +#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8 0xf148 | |
| 22 | +#define S5P_FIMV_D_MV_BUFFER_SIZE_V8 0xf150 | |
| 23 | + | |
| 24 | +#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8 0xf138 | |
| 25 | +#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8 0xf13c | |
| 26 | + | |
| 27 | +#define S5P_FIMV_D_FIRST_PLANE_DPB_V8 0xf160 | |
| 28 | +#define S5P_FIMV_D_SECOND_PLANE_DPB_V8 0xf260 | |
| 29 | +#define S5P_FIMV_D_MV_BUFFER_V8 0xf460 | |
| 30 | + | |
| 31 | +#define S5P_FIMV_D_NUM_MV_V8 0xf134 | |
| 32 | +#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8 0xf154 | |
| 33 | + | |
| 34 | +#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8 0xf560 | |
| 35 | +#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8 0xf564 | |
| 36 | + | |
| 37 | +#define S5P_FIMV_D_CPB_BUFFER_ADDR_V8 0xf5b0 | |
| 38 | +#define S5P_FIMV_D_CPB_BUFFER_SIZE_V8 0xf5b4 | |
| 39 | +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8 0xf5bc | |
| 40 | +#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V8 0xf5c0 | |
| 41 | +#define S5P_FIMV_D_SLICE_IF_ENABLE_V8 0xf5c4 | |
| 42 | +#define S5P_FIMV_D_STREAM_DATA_SIZE_V8 0xf5d0 | |
| 43 | + | |
| 44 | +/* Display information register */ | |
| 45 | +#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8 0xf600 | |
| 46 | +#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8 0xf604 | |
| 47 | + | |
| 48 | +/* Display status */ | |
| 49 | +#define S5P_FIMV_D_DISPLAY_STATUS_V8 0xf608 | |
| 50 | + | |
| 51 | +#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8 0xf60c | |
| 52 | +#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8 0xf610 | |
| 53 | + | |
| 54 | +#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8 0xf618 | |
| 55 | +#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V8 0xf61c | |
| 56 | +#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V8 0xf620 | |
| 57 | +#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V8 0xf624 | |
| 58 | + | |
| 59 | +/* Decoded picture information register */ | |
| 60 | +#define S5P_FIMV_D_DECODED_STATUS_V8 0xf644 | |
| 61 | +#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8 0xf648 | |
| 62 | +#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8 0xf64c | |
| 63 | +#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR_V8 0xf650 | |
| 64 | +#define S5P_FIMV_D_DECODED_FRAME_TYPE_V8 0xf654 | |
| 65 | +#define S5P_FIMV_D_DECODED_NAL_SIZE_V8 0xf664 | |
| 66 | + | |
| 67 | +/* Returned value register for specific setting */ | |
| 68 | +#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8 0xf674 | |
| 69 | +#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8 0xf678 | |
| 70 | +#define S5P_FIMV_D_MVC_VIEW_ID_V8 0xf6d8 | |
| 71 | + | |
| 72 | +/* SEI related information */ | |
| 73 | +#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8 0xf6dc | |
| 74 | + | |
| 75 | +/* Encoder Registers */ | |
| 76 | +#define S5P_FIMV_E_FIXED_PICTURE_QP_V8 0xf794 | |
| 77 | +#define S5P_FIMV_E_RC_CONFIG_V8 0xf798 | |
| 78 | +#define S5P_FIMV_E_RC_QP_BOUND_V8 0xf79c | |
| 79 | +#define S5P_FIMV_E_RC_RPARAM_V8 0xf7a4 | |
| 80 | +#define S5P_FIMV_E_MB_RC_CONFIG_V8 0xf7a8 | |
| 81 | +#define S5P_FIMV_E_PADDING_CTRL_V8 0xf7ac | |
| 82 | +#define S5P_FIMV_E_MV_HOR_RANGE_V8 0xf7b4 | |
| 83 | +#define S5P_FIMV_E_MV_VER_RANGE_V8 0xf7b8 | |
| 84 | + | |
| 85 | +#define S5P_FIMV_E_VBV_BUFFER_SIZE_V8 0xf78c | |
| 86 | +#define S5P_FIMV_E_VBV_INIT_DELAY_V8 0xf790 | |
| 87 | + | |
| 88 | +#define S5P_FIMV_E_ASPECT_RATIO_V8 0xfb4c | |
| 89 | +#define S5P_FIMV_E_EXTENDED_SAR_V8 0xfb50 | |
| 90 | +#define S5P_FIMV_E_H264_OPTIONS_V8 0xfb54 | |
| 91 | + | |
| 92 | +/* MFCv8 Context buffer sizes */ | |
| 93 | +#define MFC_CTX_BUF_SIZE_V8 (30 * SZ_1K) /* 30KB */ | |
| 94 | +#define MFC_H264_DEC_CTX_BUF_SIZE_V8 (2 * SZ_1M) /* 2MB */ | |
| 95 | +#define MFC_OTHER_DEC_CTX_BUF_SIZE_V8 (20 * SZ_1K) /* 20KB */ | |
| 96 | +#define MFC_H264_ENC_CTX_BUF_SIZE_V8 (100 * SZ_1K) /* 100KB */ | |
| 97 | +#define MFC_OTHER_ENC_CTX_BUF_SIZE_V8 (10 * SZ_1K) /* 10KB */ | |
| 98 | + | |
| 99 | +/* Buffer size defines */ | |
| 100 | +#define S5P_FIMV_TMV_BUFFER_SIZE_V8(w, h) (((w) + 1) * ((h) + 1) * 8) | |
| 101 | + | |
| 102 | +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(w, h) (((w) * 704) + 2176) | |
| 103 | +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(w, h) \ | |
| 104 | + (((w) * 576 + (h) * 128) + 4128) | |
| 105 | + | |
| 106 | +#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(w, h) \ | |
| 107 | + (((w) * 592) + 2336) | |
| 108 | +#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(w, h) \ | |
| 109 | + (((w) * 576) + 10512 + \ | |
| 110 | + ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4)) | |
| 111 | +#define S5P_FIMV_ME_BUFFER_SIZE_V8(imw, imh, mbw, mbh) \ | |
| 112 | + ((DIV_ROUND_UP((mbw * 16), 64) * DIV_ROUND_UP((mbh * 16), 64) * 256) \ | |
| 113 | + + (DIV_ROUND_UP((mbw) * (mbh), 32) * 16)) | |
| 114 | + | |
| 115 | +/* BUffer alignment defines */ | |
| 116 | +#define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64 | |
| 117 | + | |
| 118 | +/* MFCv8 variant defines */ | |
| 119 | +#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */ | |
| 120 | +#define MAX_CPB_SIZE_V8 (3 * SZ_1M) /* 3MB */ | |
| 121 | +#define MFC_VERSION_V8 0x80 | |
| 122 | +#define MFC_NUM_PORTS_V8 1 | |
| 123 | + | |
| 124 | +#endif /*_REGS_MFC_V8_H*/ | |
| @@ -309,12 +309,15 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, · 308 unmodified lines | ||
| 309 | 309 | { |
| 310 | 310 | struct s5p_mfc_dev *dev = ctx->dev; |
| 311 | 311 | unsigned int dst_frame_status; |
| 312 | + unsigned int dec_frame_status; | |
| 312 | 313 | struct s5p_mfc_buf *src_buf; |
| 313 | 314 | unsigned long flags; |
| 314 | 315 | unsigned int res_change; |
| 315 | 316 | |
| 316 | 317 | dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
| 317 | 318 | & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; |
| 319 | + dec_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dec_status, dev) | |
| 320 | + & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK; | |
| 318 | 321 | res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev) |
| 319 | 322 | & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK) |
| 320 | 323 | >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT; |
| @@ -339,16 +342,23 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, · 18 unmodified lines | ||
| 339 | 342 | /* All frames remaining in the buffer have been extracted */ |
| 340 | 343 | if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) { |
| 341 | 344 | if (ctx->state == MFCINST_RES_CHANGE_FLUSH) { |
| 345 | + static const struct v4l2_event ev_src_ch = { | |
| 346 | + .type = V4L2_EVENT_SOURCE_CHANGE, | |
| 347 | + .u.src_change.changes = | |
| 348 | + V4L2_EVENT_SRC_CH_RESOLUTION, | |
| 349 | + }; | |
| 350 | + | |
| 342 | 351 | s5p_mfc_handle_frame_all_extracted(ctx); |
| 343 | 352 | ctx->state = MFCINST_RES_CHANGE_END; |
| 353 | + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); | |
| 354 | + | |
| 344 | 355 | goto leave_handle_frame; |
| 345 | 356 | } else { |
| 346 | 357 | s5p_mfc_handle_frame_all_extracted(ctx); |
| 347 | 358 | } |
| 348 | 359 | } |
| 349 | 360 | |
| 350 | − if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY || | |
| 351 | − dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY) | |
| 361 | + if (dec_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) | |
| 352 | 362 | s5p_mfc_handle_frame_copy_time(ctx); |
| 353 | 363 | |
| 354 | 364 | /* A frame has been decoded and is in the buffer */ |
| @@ -366,6 +376,7 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx, · 11 unmodified lines | ||
| 366 | 376 | ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops, |
| 367 | 377 | get_consumed_stream, dev); |
| 368 | 378 | if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC && |
| 379 | + ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC && | |
| 369 | 380 | ctx->consumed_stream + STUFF_BYTE < |
| 370 | 381 | src_buf->b->v4l2_planes[0].bytesused) { |
| 371 | 382 | /* Run MFC again on the same buffer */ |
| @@ -641,6 +652,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) · 269 unmodified lines | ||
| 641 | 652 | |
| 642 | 653 | case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET: |
| 643 | 654 | clear_work_bit(ctx); |
| 655 | + ctx->inst_no = MFC_NO_INSTANCE_SET; | |
| 644 | 656 | ctx->state = MFCINST_FREE; |
| 645 | 657 | wake_up(&ctx->queue); |
| 646 | 658 | goto irq_cleanup_hw; |
| @@ -761,7 +773,7 @@ static int s5p_mfc_open(struct file *file) · 114 unmodified lines | ||
| 761 | 773 | goto err_bad_node; |
| 762 | 774 | } |
| 763 | 775 | ctx->fh.ctrl_handler = &ctx->ctrl_handler; |
| 764 | − ctx->inst_no = -1; | |
| 776 | + ctx->inst_no = MFC_NO_INSTANCE_SET; | |
| 765 | 777 | /* Load firmware if this is the first instance */ |
| 766 | 778 | if (dev->num_inst == 1) { |
| 767 | 779 | dev->watchdog_timer.expires = jiffies + |
| @@ -871,29 +883,11 @@ static int s5p_mfc_release(struct file *file) · 103 unmodified lines | ||
| 871 | 883 | vb2_queue_release(&ctx->vq_dst); |
| 872 | 884 | /* Mark context as idle */ |
| 873 | 885 | clear_work_bit_irqsave(ctx); |
| 874 | − /* If instance was initialised then | |
| 886 | + /* If instance was initialised and not yet freed, | |
| 875 | 887 | * return instance and free resources */ |
| 876 | − if (ctx->inst_no != MFC_NO_INSTANCE_SET) { | |
| 888 | + if (ctx->state != MFCINST_FREE && ctx->state != MFCINST_INIT) { | |
| 877 | 889 | mfc_debug(2, "Has to free instance\n"); |
| 878 | − ctx->state = MFCINST_RETURN_INST; | |
| 879 | − set_work_bit_irqsave(ctx); | |
| 880 | − s5p_mfc_clean_ctx_int_flags(ctx); | |
| 881 | − s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | |
| 882 | − /* Wait until instance is returned or timeout occurred */ | |
| 883 | − if (s5p_mfc_wait_for_done_ctx | |
| 884 | − (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) { | |
| 885 | − s5p_mfc_clock_off(); | |
| 886 | − mfc_err("Err returning instance\n"); | |
| 887 | − } | |
| 888 | − mfc_debug(2, "After free instance\n"); | |
| 889 | − /* Free resources */ | |
| 890 | − s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); | |
| 891 | − s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); | |
| 892 | − if (ctx->type == MFCINST_DECODER) | |
| 893 | − s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, | |
| 894 | − ctx); | |
| 895 | − | |
| 896 | − ctx->inst_no = MFC_NO_INSTANCE_SET; | |
| 890 | + s5p_mfc_close_mfc_inst(dev, ctx); | |
| 897 | 891 | } |
| 898 | 892 | /* hardware locking scheme */ |
| 899 | 893 | if (dev->curr_ctx == ctx->num) |
| @@ -1207,6 +1201,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) · 307 unmodified lines | ||
| 1207 | 1201 | /* Initialize HW ops and commands based on MFC version */ |
| 1208 | 1202 | s5p_mfc_init_hw_ops(dev); |
| 1209 | 1203 | s5p_mfc_init_hw_cmds(dev); |
| 1204 | + s5p_mfc_init_regs(dev); | |
| 1210 | 1205 | |
| 1211 | 1206 | pr_debug("%s--\n", __func__); |
| 1212 | 1207 | return 0; |
| @@ -1352,6 +1347,7 @@ struct s5p_mfc_buf_align mfc_buf_align_v5 = { · 139 unmodified lines | ||
| 1352 | 1347 | |
| 1353 | 1348 | static struct s5p_mfc_variant mfc_drvdata_v5 = { |
| 1354 | 1349 | .version = MFC_VERSION, |
| 1350 | + .version_bit = MFC_V5_BIT, | |
| 1355 | 1351 | .port_num = MFC_NUM_PORTS, |
| 1356 | 1352 | .buf_size = &buf_size_v5, |
| 1357 | 1353 | .buf_align = &mfc_buf_align_v5, |
| @@ -1378,6 +1374,7 @@ struct s5p_mfc_buf_align mfc_buf_align_v6 = { · 20 unmodified lines | ||
| 1378 | 1374 | |
| 1379 | 1375 | static struct s5p_mfc_variant mfc_drvdata_v6 = { |
| 1380 | 1376 | .version = MFC_VERSION_V6, |
| 1377 | + .version_bit = MFC_V6_BIT, | |
| 1381 | 1378 | .port_num = MFC_NUM_PORTS_V6, |
| 1382 | 1379 | .buf_size = &buf_size_v6, |
| 1383 | 1380 | .buf_align = &mfc_buf_align_v6, |
| @@ -1404,12 +1401,40 @@ struct s5p_mfc_buf_align mfc_buf_align_v7 = { · 20 unmodified lines | ||
| 1404 | 1401 | |
| 1405 | 1402 | static struct s5p_mfc_variant mfc_drvdata_v7 = { |
| 1406 | 1403 | .version = MFC_VERSION_V7, |
| 1404 | + .version_bit = MFC_V7_BIT, | |
| 1407 | 1405 | .port_num = MFC_NUM_PORTS_V7, |
| 1408 | 1406 | .buf_size = &buf_size_v7, |
| 1409 | 1407 | .buf_align = &mfc_buf_align_v7, |
| 1410 | 1408 | .fw_name = "s5p-mfc-v7.fw", |
| 1411 | 1409 | }; |
| 1412 | 1410 | |
| 1411 | +struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { | |
| 1412 | + .dev_ctx = MFC_CTX_BUF_SIZE_V8, | |
| 1413 | + .h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V8, | |
| 1414 | + .other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V8, | |
| 1415 | + .h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V8, | |
| 1416 | + .other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V8, | |
| 1417 | +}; | |
| 1418 | + | |
| 1419 | +struct s5p_mfc_buf_size buf_size_v8 = { | |
| 1420 | + .fw = MAX_FW_SIZE_V8, | |
| 1421 | + .cpb = MAX_CPB_SIZE_V8, | |
| 1422 | + .priv = &mfc_buf_size_v8, | |
| 1423 | +}; | |
| 1424 | + | |
| 1425 | +struct s5p_mfc_buf_align mfc_buf_align_v8 = { | |
| 1426 | + .base = 0, | |
| 1427 | +}; | |
| 1428 | + | |
| 1429 | +static struct s5p_mfc_variant mfc_drvdata_v8 = { | |
| 1430 | + .version = MFC_VERSION_V8, | |
| 1431 | + .version_bit = MFC_V8_BIT, | |
| 1432 | + .port_num = MFC_NUM_PORTS_V8, | |
| 1433 | + .buf_size = &buf_size_v8, | |
| 1434 | + .buf_align = &mfc_buf_align_v8, | |
| 1435 | + .fw_name = "s5p-mfc-v8.fw", | |
| 1436 | +}; | |
| 1437 | + | |
| 1413 | 1438 | static struct platform_device_id mfc_driver_ids[] = { |
| 1414 | 1439 | { |
| 1415 | 1440 | .name = "s5p-mfc", |
| @@ -1423,6 +1448,9 @@ static struct platform_device_id mfc_driver_ids[] = { · 7 unmodified lines | ||
| 1423 | 1448 | }, { |
| 1424 | 1449 | .name = "s5p-mfc-v7", |
| 1425 | 1450 | .driver_data = (unsigned long)&mfc_drvdata_v7, |
| 1451 | + }, { | |
| 1452 | + .name = "s5p-mfc-v8", | |
| 1453 | + .driver_data = (unsigned long)&mfc_drvdata_v8, | |
| 1426 | 1454 | }, |
| 1427 | 1455 | {}, |
| 1428 | 1456 | }; |
| @@ -1438,6 +1466,9 @@ static const struct of_device_id exynos_mfc_match[] = { · 9 unmodified lines | ||
| 1438 | 1466 | }, { |
| 1439 | 1467 | .compatible = "samsung,mfc-v7", |
| 1440 | 1468 | .data = &mfc_drvdata_v7, |
| 1469 | + }, { | |
| 1470 | + .compatible = "samsung,mfc-v8", | |
| 1471 | + .data = &mfc_drvdata_v8, | |
| 1441 | 1472 | }, |
| 1442 | 1473 | {}, |
| 1443 | 1474 | }; |
| @@ -23,8 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <media/v4l2-ioctl.h> |
| 24 | 24 | #include <media/videobuf2-core.h> |
| 25 | 25 | #include "regs-mfc.h" |
| 26 | −#include "regs-mfc-v6.h" | |
| 27 | −#include "regs-mfc-v7.h" | |
| 26 | +#include "regs-mfc-v8.h" | |
| 28 | 27 | |
| 29 | 28 | /* Definitions related to MFC memory */ |
| 30 | 29 | |
| @@ -223,6 +222,7 @@ struct s5p_mfc_buf_align { · 192 unmodified lines | ||
| 223 | 222 | struct s5p_mfc_variant { |
| 224 | 223 | unsigned int version; |
| 225 | 224 | unsigned int port_num; |
| 225 | + u32 version_bit; | |
| 226 | 226 | struct s5p_mfc_buf_size *buf_size; |
| 227 | 227 | struct s5p_mfc_buf_align *buf_align; |
| 228 | 228 | char *fw_name; |
| @@ -330,6 +330,7 @@ struct s5p_mfc_dev { · 101 unmodified lines | ||
| 330 | 330 | int warn_start; |
| 331 | 331 | struct s5p_mfc_hw_ops *mfc_ops; |
| 332 | 332 | struct s5p_mfc_hw_cmds *mfc_cmds; |
| 333 | + const struct s5p_mfc_regs *mfc_regs; | |
| 333 | 334 | }; |
| 334 | 335 | |
| 335 | 336 | /** |
| @@ -663,6 +664,7 @@ struct s5p_mfc_fmt { · 327 unmodified lines | ||
| 663 | 664 | u32 codec_mode; |
| 664 | 665 | enum s5p_mfc_fmt_type type; |
| 665 | 666 | u32 num_planes; |
| 667 | + u32 versions; | |
| 666 | 668 | }; |
| 667 | 669 | |
| 668 | 670 | /** |
| @@ -700,6 +702,13 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); · 31 unmodified lines | ||
| 700 | 702 | (dev->variant->port_num ? 1 : 0) : 0) : 0) |
| 701 | 703 | #define IS_TWOPORT(dev) (dev->variant->port_num == 2 ? 1 : 0) |
| 702 | 704 | #define IS_MFCV6_PLUS(dev) (dev->variant->version >= 0x60 ? 1 : 0) |
| 703 | −#define IS_MFCV7(dev) (dev->variant->version >= 0x70 ? 1 : 0) | |
| 705 | +#define IS_MFCV7_PLUS(dev) (dev->variant->version >= 0x70 ? 1 : 0) | |
| 706 | +#define IS_MFCV8(dev) (dev->variant->version >= 0x80 ? 1 : 0) | |
| 707 | + | |
| 708 | +#define MFC_V5_BIT BIT(0) | |
| 709 | +#define MFC_V6_BIT BIT(1) | |
| 710 | +#define MFC_V7_BIT BIT(2) | |
| 711 | +#define MFC_V8_BIT BIT(3) | |
| 712 | + | |
| 704 | 713 | |
| 705 | 714 | #endif /* S5P_MFC_COMMON_H_ */ |
| @@ -400,3 +400,65 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) · 399 unmodified lines | ||
| 400 | 400 | return 0; |
| 401 | 401 | } |
| 402 | 402 | |
| 403 | +int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) | |
| 404 | +{ | |
| 405 | + int ret = 0; | |
| 406 | + | |
| 407 | + ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); | |
| 408 | + if (ret) { | |
| 409 | + mfc_err("Failed allocating instance buffer\n"); | |
| 410 | + goto err; | |
| 411 | + } | |
| 412 | + | |
| 413 | + if (ctx->type == MFCINST_DECODER) { | |
| 414 | + ret = s5p_mfc_hw_call(dev->mfc_ops, | |
| 415 | + alloc_dec_temp_buffers, ctx); | |
| 416 | + if (ret) { | |
| 417 | + mfc_err("Failed allocating temporary buffers\n"); | |
| 418 | + goto err_free_inst_buf; | |
| 419 | + } | |
| 420 | + } | |
| 421 | + | |
| 422 | + set_work_bit_irqsave(ctx); | |
| 423 | + s5p_mfc_clean_ctx_int_flags(ctx); | |
| 424 | + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | |
| 425 | + if (s5p_mfc_wait_for_done_ctx(ctx, | |
| 426 | + S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { | |
| 427 | + /* Error or timeout */ | |
| 428 | + mfc_err("Error getting instance from hardware\n"); | |
| 429 | + ret = -EIO; | |
| 430 | + goto err_free_desc_buf; | |
| 431 | + } | |
| 432 | + | |
| 433 | + mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | |
| 434 | + return ret; | |
| 435 | + | |
| 436 | +err_free_desc_buf: | |
| 437 | + if (ctx->type == MFCINST_DECODER) | |
| 438 | + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); | |
| 439 | +err_free_inst_buf: | |
| 440 | + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); | |
| 441 | +err: | |
| 442 | + return ret; | |
| 443 | +} | |
| 444 | + | |
| 445 | +void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) | |
| 446 | +{ | |
| 447 | + ctx->state = MFCINST_RETURN_INST; | |
| 448 | + set_work_bit_irqsave(ctx); | |
| 449 | + s5p_mfc_clean_ctx_int_flags(ctx); | |
| 450 | + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | |
| 451 | + /* Wait until instance is returned or timeout occurred */ | |
| 452 | + if (s5p_mfc_wait_for_done_ctx(ctx, | |
| 453 | + S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) | |
| 454 | + mfc_err("Err returning instance\n"); | |
| 455 | + | |
| 456 | + /* Free resources */ | |
| 457 | + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); | |
| 458 | + s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); | |
| 459 | + if (ctx->type == MFCINST_DECODER) | |
| 460 | + s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); | |
| 461 | + | |
| 462 | + ctx->inst_no = MFC_NO_INSTANCE_SET; | |
| 463 | + ctx->state = MFCINST_FREE; | |
| 464 | +} | |
| @@ -28,4 +28,7 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev); · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | int s5p_mfc_reset(struct s5p_mfc_dev *dev); |
| 30 | 30 | |
| 31 | +int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx); | |
| 32 | +void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx); | |
| 33 | + | |
| 31 | 34 | #endif /* S5P_MFC_CTRL_H */ |
| @@ -25,15 +25,13 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <media/v4l2-event.h> |
| 26 | 26 | #include <media/videobuf2-core.h> |
| 27 | 27 | #include "s5p_mfc_common.h" |
| 28 | +#include "s5p_mfc_ctrl.h" | |
| 28 | 29 | #include "s5p_mfc_debug.h" |
| 29 | 30 | #include "s5p_mfc_dec.h" |
| 30 | 31 | #include "s5p_mfc_intr.h" |
| 31 | 32 | #include "s5p_mfc_opr.h" |
| 32 | 33 | #include "s5p_mfc_pm.h" |
| 33 | 34 | |
| 34 | −#define DEF_SRC_FMT_DEC V4L2_PIX_FMT_H264 | |
| 35 | −#define DEF_DST_FMT_DEC V4L2_PIX_FMT_NV12MT_16X16 | |
| 36 | − | |
| 37 | 35 | static struct s5p_mfc_fmt formats[] = { |
| 38 | 36 | { |
| 39 | 37 | .name = "4:2:0 2 Planes 16x16 Tiles", |
| @@ -41,6 +39,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 41 | 39 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 42 | 40 | .type = MFC_FMT_RAW, |
| 43 | 41 | .num_planes = 2, |
| 42 | + .versions = MFC_V6_BIT | MFC_V7_BIT, | |
| 44 | 43 | }, |
| 45 | 44 | { |
| 46 | 45 | .name = "4:2:0 2 Planes 64x32 Tiles", |
| @@ -48,6 +47,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 48 | 47 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 49 | 48 | .type = MFC_FMT_RAW, |
| 50 | 49 | .num_planes = 2, |
| 50 | + .versions = MFC_V5_BIT, | |
| 51 | 51 | }, |
| 52 | 52 | { |
| 53 | 53 | .name = "4:2:0 2 Planes Y/CbCr", |
| @@ -55,6 +55,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 55 | 55 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 56 | 56 | .type = MFC_FMT_RAW, |
| 57 | 57 | .num_planes = 2, |
| 58 | + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, | |
| 58 | 59 | }, |
| 59 | 60 | { |
| 60 | 61 | .name = "4:2:0 2 Planes Y/CrCb", |
| @@ -62,6 +63,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 62 | 63 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 63 | 64 | .type = MFC_FMT_RAW, |
| 64 | 65 | .num_planes = 2, |
| 66 | + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, | |
| 65 | 67 | }, |
| 66 | 68 | { |
| 67 | 69 | .name = "H264 Encoded Stream", |
| @@ -69,6 +71,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 69 | 71 | .codec_mode = S5P_MFC_CODEC_H264_DEC, |
| 70 | 72 | .type = MFC_FMT_DEC, |
| 71 | 73 | .num_planes = 1, |
| 74 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 75 | + MFC_V8_BIT, | |
| 72 | 76 | }, |
| 73 | 77 | { |
| 74 | 78 | .name = "H264/MVC Encoded Stream", |
| @@ -76,6 +80,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 76 | 80 | .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC, |
| 77 | 81 | .type = MFC_FMT_DEC, |
| 78 | 82 | .num_planes = 1, |
| 83 | + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, | |
| 79 | 84 | }, |
| 80 | 85 | { |
| 81 | 86 | .name = "H263 Encoded Stream", |
| @@ -83,6 +88,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 83 | 88 | .codec_mode = S5P_MFC_CODEC_H263_DEC, |
| 84 | 89 | .type = MFC_FMT_DEC, |
| 85 | 90 | .num_planes = 1, |
| 91 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 92 | + MFC_V8_BIT, | |
| 86 | 93 | }, |
| 87 | 94 | { |
| 88 | 95 | .name = "MPEG1 Encoded Stream", |
| @@ -90,6 +97,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 90 | 97 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, |
| 91 | 98 | .type = MFC_FMT_DEC, |
| 92 | 99 | .num_planes = 1, |
| 100 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 101 | + MFC_V8_BIT, | |
| 93 | 102 | }, |
| 94 | 103 | { |
| 95 | 104 | .name = "MPEG2 Encoded Stream", |
| @@ -97,6 +106,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 97 | 106 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, |
| 98 | 107 | .type = MFC_FMT_DEC, |
| 99 | 108 | .num_planes = 1, |
| 109 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 110 | + MFC_V8_BIT, | |
| 100 | 111 | }, |
| 101 | 112 | { |
| 102 | 113 | .name = "MPEG4 Encoded Stream", |
| @@ -104,6 +115,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 104 | 115 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, |
| 105 | 116 | .type = MFC_FMT_DEC, |
| 106 | 117 | .num_planes = 1, |
| 118 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 119 | + MFC_V8_BIT, | |
| 107 | 120 | }, |
| 108 | 121 | { |
| 109 | 122 | .name = "XviD Encoded Stream", |
| @@ -111,6 +124,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 111 | 124 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, |
| 112 | 125 | .type = MFC_FMT_DEC, |
| 113 | 126 | .num_planes = 1, |
| 127 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 128 | + MFC_V8_BIT, | |
| 114 | 129 | }, |
| 115 | 130 | { |
| 116 | 131 | .name = "VC1 Encoded Stream", |
| @@ -118,6 +133,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 118 | 133 | .codec_mode = S5P_MFC_CODEC_VC1_DEC, |
| 119 | 134 | .type = MFC_FMT_DEC, |
| 120 | 135 | .num_planes = 1, |
| 136 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 137 | + MFC_V8_BIT, | |
| 121 | 138 | }, |
| 122 | 139 | { |
| 123 | 140 | .name = "VC1 RCV Encoded Stream", |
| @@ -125,6 +142,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 125 | 142 | .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC, |
| 126 | 143 | .type = MFC_FMT_DEC, |
| 127 | 144 | .num_planes = 1, |
| 145 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 146 | + MFC_V8_BIT, | |
| 128 | 147 | }, |
| 129 | 148 | { |
| 130 | 149 | .name = "VP8 Encoded Stream", |
| @@ -132,6 +151,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 132 | 151 | .codec_mode = S5P_MFC_CODEC_VP8_DEC, |
| 133 | 152 | .type = MFC_FMT_DEC, |
| 134 | 153 | .num_planes = 1, |
| 154 | + .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT, | |
| 135 | 155 | }, |
| 136 | 156 | }; |
| 137 | 157 | |
| @@ -262,8 +282,10 @@ static int vidioc_querycap(struct file *file, void *priv, · 124 unmodified lines | ||
| 262 | 282 | } |
| 263 | 283 | |
| 264 | 284 | /* Enumerate format */ |
| 265 | −static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) | |
| 285 | +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, | |
| 286 | + bool mplane, bool out) | |
| 266 | 287 | { |
| 288 | + struct s5p_mfc_dev *dev = video_drvdata(file); | |
| 267 | 289 | struct s5p_mfc_fmt *fmt; |
| 268 | 290 | int i, j = 0; |
| 269 | 291 | |
| @@ -276,6 +298,8 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) · 6 unmodified lines | ||
| 276 | 298 | continue; |
| 277 | 299 | else if (!out && formats[i].type != MFC_FMT_RAW) |
| 278 | 300 | continue; |
| 301 | + else if ((dev->variant->version_bit & formats[i].versions) == 0) | |
| 302 | + continue; | |
| 279 | 303 | |
| 280 | 304 | if (j == f->index) |
| 281 | 305 | break; |
| @@ -292,25 +316,25 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) · 10 unmodified lines | ||
| 292 | 316 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, |
| 293 | 317 | struct v4l2_fmtdesc *f) |
| 294 | 318 | { |
| 295 | − return vidioc_enum_fmt(f, false, false); | |
| 319 | + return vidioc_enum_fmt(file, f, false, false); | |
| 296 | 320 | } |
| 297 | 321 | |
| 298 | 322 | static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, |
| 299 | 323 | struct v4l2_fmtdesc *f) |
| 300 | 324 | { |
| 301 | − return vidioc_enum_fmt(f, true, false); | |
| 325 | + return vidioc_enum_fmt(file, f, true, false); | |
| 302 | 326 | } |
| 303 | 327 | |
| 304 | −static int vidioc_enum_fmt_vid_out(struct file *file, void *prov, | |
| 328 | +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, | |
| 305 | 329 | struct v4l2_fmtdesc *f) |
| 306 | 330 | { |
| 307 | − return vidioc_enum_fmt(f, false, true); | |
| 331 | + return vidioc_enum_fmt(file, f, false, true); | |
| 308 | 332 | } |
| 309 | 333 | |
| 310 | −static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, | |
| 334 | +static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv, | |
| 311 | 335 | struct v4l2_fmtdesc *f) |
| 312 | 336 | { |
| 313 | − return vidioc_enum_fmt(f, true, true); | |
| 337 | + return vidioc_enum_fmt(file, f, true, true); | |
| 314 | 338 | } |
| 315 | 339 | |
| 316 | 340 | /* Get format */ |
| @@ -386,11 +410,9 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) · 69 unmodified lines | ||
| 386 | 410 | mfc_err("Unknown codec\n"); |
| 387 | 411 | return -EINVAL; |
| 388 | 412 | } |
| 389 | − if (!IS_MFCV6_PLUS(dev)) { | |
| 390 | − if (fmt->fourcc == V4L2_PIX_FMT_VP8) { | |
| 391 | − mfc_err("Not supported format.\n"); | |
| 392 | − return -EINVAL; | |
| 393 | − } | |
| 413 | + if ((dev->variant->version_bit & fmt->versions) == 0) { | |
| 414 | + mfc_err("Unsupported format by this MFC version.\n"); | |
| 415 | + return -EINVAL; | |
| 394 | 416 | } |
| 395 | 417 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
| 396 | 418 | fmt = find_format(f, MFC_FMT_RAW); |
| @@ -398,13 +420,8 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) · 1 unmodified line | ||
| 398 | 420 | mfc_err("Unsupported format for destination.\n"); |
| 399 | 421 | return -EINVAL; |
| 400 | 422 | } |
| 401 | − if (IS_MFCV6_PLUS(dev) && | |
| 402 | − (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { | |
| 403 | − mfc_err("Not supported format.\n"); | |
| 404 | − return -EINVAL; | |
| 405 | − } else if (!IS_MFCV6_PLUS(dev) && | |
| 406 | − (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { | |
| 407 | − mfc_err("Not supported format.\n"); | |
| 423 | + if ((dev->variant->version_bit & fmt->versions) == 0) { | |
| 424 | + mfc_err("Unsupported format by this MFC version.\n"); | |
| 408 | 425 | return -EINVAL; |
| 409 | 426 | } |
| 410 | 427 | } |
| @@ -462,104 +479,131 @@ out: · 51 unmodified lines | ||
| 462 | 479 | return ret; |
| 463 | 480 | } |
| 464 | 481 | |
| 465 | −/* Reqeust buffers */ | |
| 466 | −static int vidioc_reqbufs(struct file *file, void *priv, | |
| 467 | − struct v4l2_requestbuffers *reqbufs) | |
| 482 | +static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, | |
| 483 | + struct v4l2_requestbuffers *reqbufs) | |
| 468 | 484 | { |
| 469 | − struct s5p_mfc_dev *dev = video_drvdata(file); | |
| 470 | − struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
| 471 | 485 | int ret = 0; |
| 472 | 486 | |
| 473 | − if (reqbufs->memory != V4L2_MEMORY_MMAP) { | |
| 474 | − mfc_err("Only V4L2_MEMORY_MAP is supported\n"); | |
| 475 | − return -EINVAL; | |
| 476 | − } | |
| 477 | − if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
| 478 | − /* Can only request buffers after an instance has been opened.*/ | |
| 479 | − if (ctx->state == MFCINST_INIT) { | |
| 480 | − ctx->src_bufs_cnt = 0; | |
| 481 | − if (reqbufs->count == 0) { | |
| 482 | − mfc_debug(2, "Freeing buffers\n"); | |
| 483 | − s5p_mfc_clock_on(); | |
| 484 | − ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
| 485 | − s5p_mfc_clock_off(); | |
| 486 | − return ret; | |
| 487 | − } | |
| 488 | − /* Decoding */ | |
| 489 | − if (ctx->output_state != QUEUE_FREE) { | |
| 490 | − mfc_err("Bufs have already been requested\n"); | |
| 491 | − return -EINVAL; | |
| 492 | − } | |
| 493 | − s5p_mfc_clock_on(); | |
| 494 | − ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
| 495 | − s5p_mfc_clock_off(); | |
| 496 | − if (ret) { | |
| 497 | − mfc_err("vb2_reqbufs on output failed\n"); | |
| 498 | − return ret; | |
| 499 | − } | |
| 500 | − mfc_debug(2, "vb2_reqbufs: %d\n", ret); | |
| 501 | − ctx->output_state = QUEUE_BUFS_REQUESTED; | |
| 502 | − } | |
| 503 | − } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
| 504 | − ctx->dst_bufs_cnt = 0; | |
| 505 | − if (reqbufs->count == 0) { | |
| 506 | − mfc_debug(2, "Freeing buffers\n"); | |
| 507 | − s5p_mfc_clock_on(); | |
| 508 | − ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 509 | − s5p_mfc_clock_off(); | |
| 510 | − return ret; | |
| 487 | + s5p_mfc_clock_on(); | |
| 488 | + | |
| 489 | + if (reqbufs->count == 0) { | |
| 490 | + mfc_debug(2, "Freeing buffers\n"); | |
| 491 | + ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
| 492 | + if (ret) | |
| 493 | + goto out; | |
| 494 | + s5p_mfc_close_mfc_inst(dev, ctx); | |
| 495 | + ctx->src_bufs_cnt = 0; | |
| 496 | + ctx->output_state = QUEUE_FREE; | |
| 497 | + } else if (ctx->output_state == QUEUE_FREE) { | |
| 498 | + /* Can only request buffers when we have a valid format set. */ | |
| 499 | + WARN_ON(ctx->src_bufs_cnt != 0); | |
| 500 | + if (ctx->state != MFCINST_INIT) { | |
| 501 | + mfc_err("Reqbufs called in an invalid state\n"); | |
| 502 | + ret = -EINVAL; | |
| 503 | + goto out; | |
| 511 | 504 | } |
| 512 | − if (ctx->capture_state != QUEUE_FREE) { | |
| 513 | − mfc_err("Bufs have already been requested\n"); | |
| 514 | − return -EINVAL; | |
| 515 | − } | |
| 516 | − ctx->capture_state = QUEUE_BUFS_REQUESTED; | |
| 517 | − s5p_mfc_clock_on(); | |
| 518 | − ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 519 | − s5p_mfc_clock_off(); | |
| 505 | + | |
| 506 | + mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n", | |
| 507 | + reqbufs->count); | |
| 508 | + ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
| 509 | + if (ret) | |
| 510 | + goto out; | |
| 511 | + | |
| 512 | + ret = s5p_mfc_open_mfc_inst(dev, ctx); | |
| 520 | 513 | if (ret) { |
| 521 | − mfc_err("vb2_reqbufs on capture failed\n"); | |
| 522 | − return ret; | |
| 523 | − } | |
| 524 | − if (reqbufs->count < ctx->pb_count) { | |
| 525 | − mfc_err("Not enough buffers allocated\n"); | |
| 526 | 514 | reqbufs->count = 0; |
| 527 | − s5p_mfc_clock_on(); | |
| 528 | − ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 529 | − s5p_mfc_clock_off(); | |
| 530 | − return -ENOMEM; | |
| 515 | + vb2_reqbufs(&ctx->vq_src, reqbufs); | |
| 516 | + goto out; | |
| 531 | 517 | } |
| 518 | + | |
| 519 | + ctx->output_state = QUEUE_BUFS_REQUESTED; | |
| 520 | + } else { | |
| 521 | + mfc_err("Buffers have already been requested\n"); | |
| 522 | + ret = -EINVAL; | |
| 523 | + } | |
| 524 | +out: | |
| 525 | + s5p_mfc_clock_off(); | |
| 526 | + if (ret) | |
| 527 | + mfc_err("Failed allocating buffers for OUTPUT queue\n"); | |
| 528 | + return ret; | |
| 529 | +} | |
| 530 | + | |
| 531 | +static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, | |
| 532 | + struct v4l2_requestbuffers *reqbufs) | |
| 533 | +{ | |
| 534 | + int ret = 0; | |
| 535 | + | |
| 536 | + s5p_mfc_clock_on(); | |
| 537 | + | |
| 538 | + if (reqbufs->count == 0) { | |
| 539 | + mfc_debug(2, "Freeing buffers\n"); | |
| 540 | + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 541 | + if (ret) | |
| 542 | + goto out; | |
| 543 | + s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); | |
| 544 | + ctx->dst_bufs_cnt = 0; | |
| 545 | + } else if (ctx->capture_state == QUEUE_FREE) { | |
| 546 | + WARN_ON(ctx->dst_bufs_cnt != 0); | |
| 547 | + mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n", | |
| 548 | + reqbufs->count); | |
| 549 | + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 550 | + if (ret) | |
| 551 | + goto out; | |
| 552 | + | |
| 553 | + ctx->capture_state = QUEUE_BUFS_REQUESTED; | |
| 532 | 554 | ctx->total_dpb_count = reqbufs->count; |
| 555 | + | |
| 533 | 556 | ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); |
| 534 | 557 | if (ret) { |
| 535 | 558 | mfc_err("Failed to allocate decoding buffers\n"); |
| 536 | 559 | reqbufs->count = 0; |
| 537 | − s5p_mfc_clock_on(); | |
| 538 | − ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 539 | − s5p_mfc_clock_off(); | |
| 540 | − return -ENOMEM; | |
| 541 | − } | |
| 542 | − if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { | |
| 543 | − ctx->capture_state = QUEUE_BUFS_MMAPED; | |
| 544 | − } else { | |
| 545 | − mfc_err("Not all buffers passed to buf_init\n"); | |
| 546 | − reqbufs->count = 0; | |
| 547 | − s5p_mfc_clock_on(); | |
| 548 | − ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 549 | − s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, | |
| 550 | − ctx); | |
| 551 | − s5p_mfc_clock_off(); | |
| 552 | − return -ENOMEM; | |
| 560 | + vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
| 561 | + ret = -ENOMEM; | |
| 562 | + ctx->capture_state = QUEUE_FREE; | |
| 563 | + goto out; | |
| 553 | 564 | } |
| 565 | + | |
| 566 | + WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); | |
| 567 | + ctx->capture_state = QUEUE_BUFS_MMAPED; | |
| 568 | + | |
| 554 | 569 | if (s5p_mfc_ctx_ready(ctx)) |
| 555 | 570 | set_work_bit_irqsave(ctx); |
| 556 | 571 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
| 557 | − s5p_mfc_wait_for_done_ctx(ctx, | |
| 558 | − S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); | |
| 572 | + s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, | |
| 573 | + 0); | |
| 574 | + } else { | |
| 575 | + mfc_err("Buffers have already been requested\n"); | |
| 576 | + ret = -EINVAL; | |
| 559 | 577 | } |
| 578 | +out: | |
| 579 | + s5p_mfc_clock_off(); | |
| 580 | + if (ret) | |
| 581 | + mfc_err("Failed allocating buffers for CAPTURE queue\n"); | |
| 560 | 582 | return ret; |
| 561 | 583 | } |
| 562 | 584 | |
| 585 | +/* Reqeust buffers */ | |
| 586 | +static int vidioc_reqbufs(struct file *file, void *priv, | |
| 587 | + struct v4l2_requestbuffers *reqbufs) | |
| 588 | +{ | |
| 589 | + struct s5p_mfc_dev *dev = video_drvdata(file); | |
| 590 | + struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
| 591 | + | |
| 592 | + if (reqbufs->memory != V4L2_MEMORY_MMAP) { | |
| 593 | + mfc_err("Only V4L2_MEMORY_MAP is supported\n"); | |
| 594 | + return -EINVAL; | |
| 595 | + } | |
| 596 | + | |
| 597 | + if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
| 598 | + return reqbufs_output(dev, ctx, reqbufs); | |
| 599 | + } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
| 600 | + return reqbufs_capture(dev, ctx, reqbufs); | |
| 601 | + } else { | |
| 602 | + mfc_err("Invalid type requested\n"); | |
| 603 | + return -EINVAL; | |
| 604 | + } | |
| 605 | +} | |
| 606 | + | |
| 563 | 607 | /* Query buffer */ |
| 564 | 608 | static int vidioc_querybuf(struct file *file, void *priv, |
| 565 | 609 | struct v4l2_buffer *buf) |
| @@ -573,7 +617,7 @@ static int vidioc_querybuf(struct file *file, void *priv, · 7 unmodified lines | ||
| 573 | 617 | return -EINVAL; |
| 574 | 618 | } |
| 575 | 619 | mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); |
| 576 | − if (ctx->state == MFCINST_INIT && | |
| 620 | + if (ctx->state == MFCINST_GOT_INST && | |
| 577 | 621 | buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| 578 | 622 | ret = vb2_querybuf(&ctx->vq_src, buf); |
| 579 | 623 | } else if (ctx->state == MFCINST_RUNNING && |
| @@ -649,39 +693,11 @@ static int vidioc_streamon(struct file *file, void *priv, · 69 unmodified lines | ||
| 649 | 693 | enum v4l2_buf_type type) |
| 650 | 694 | { |
| 651 | 695 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
| 652 | − struct s5p_mfc_dev *dev = ctx->dev; | |
| 653 | 696 | int ret = -EINVAL; |
| 654 | 697 | |
| 655 | 698 | mfc_debug_enter(); |
| 656 | − if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
| 657 | − | |
| 658 | − if (ctx->state == MFCINST_INIT) { | |
| 659 | − ctx->dst_bufs_cnt = 0; | |
| 660 | − ctx->src_bufs_cnt = 0; | |
| 661 | − ctx->capture_state = QUEUE_FREE; | |
| 662 | − ctx->output_state = QUEUE_FREE; | |
| 663 | − s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, | |
| 664 | − ctx); | |
| 665 | − s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, | |
| 666 | − ctx); | |
| 667 | − set_work_bit_irqsave(ctx); | |
| 668 | − s5p_mfc_clean_ctx_int_flags(ctx); | |
| 669 | − s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | |
| 670 | − | |
| 671 | − if (s5p_mfc_wait_for_done_ctx(ctx, | |
| 672 | − S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { | |
| 673 | − /* Error or timeout */ | |
| 674 | − mfc_err("Error getting instance from hardware\n"); | |
| 675 | − s5p_mfc_hw_call(dev->mfc_ops, | |
| 676 | − release_instance_buffer, ctx); | |
| 677 | − s5p_mfc_hw_call(dev->mfc_ops, | |
| 678 | − release_dec_desc_buffer, ctx); | |
| 679 | − return -EIO; | |
| 680 | − } | |
| 681 | − mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | |
| 682 | − } | |
| 699 | + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | |
| 683 | 700 | ret = vb2_streamon(&ctx->vq_src, type); |
| 684 | − } | |
| 685 | 701 | else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
| 686 | 702 | ret = vb2_streamon(&ctx->vq_dst, type); |
| 687 | 703 | mfc_debug_leave(); |
| @@ -851,6 +867,8 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh, · 163 unmodified lines | ||
| 851 | 867 | switch (sub->type) { |
| 852 | 868 | case V4L2_EVENT_EOS: |
| 853 | 869 | return v4l2_event_subscribe(fh, sub, 2, NULL); |
| 870 | + case V4L2_EVENT_SOURCE_CHANGE: | |
| 871 | + return v4l2_src_change_event_subscribe(fh, sub); | |
| 854 | 872 | default: |
| 855 | 873 | return -EINVAL; |
| 856 | 874 | } |
| @@ -1027,7 +1045,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) · 170 unmodified lines | ||
| 1027 | 1045 | return 0; |
| 1028 | 1046 | } |
| 1029 | 1047 | |
| 1030 | −static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |
| 1048 | +static void s5p_mfc_stop_streaming(struct vb2_queue *q) | |
| 1031 | 1049 | { |
| 1032 | 1050 | unsigned long flags; |
| 1033 | 1051 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); |
| @@ -1071,7 +1089,6 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) · 37 unmodified lines | ||
| 1071 | 1089 | } |
| 1072 | 1090 | if (aborted) |
| 1073 | 1091 | ctx->state = MFCINST_RUNNING; |
| 1074 | − return 0; | |
| 1075 | 1092 | } |
| 1076 | 1093 | |
| 1077 | 1094 | |
| @@ -1191,9 +1208,14 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) · 113 unmodified lines | ||
| 1191 | 1208 | void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx) |
| 1192 | 1209 | { |
| 1193 | 1210 | struct v4l2_format f; |
| 1194 | − f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_DEC; | |
| 1211 | + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; | |
| 1195 | 1212 | ctx->src_fmt = find_format(&f, MFC_FMT_DEC); |
| 1196 | − f.fmt.pix_mp.pixelformat = DEF_DST_FMT_DEC; | |
| 1213 | + if (IS_MFCV8(ctx->dev)) | |
| 1214 | + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; | |
| 1215 | + else if (IS_MFCV6_PLUS(ctx->dev)) | |
| 1216 | + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; | |
| 1217 | + else | |
| 1218 | + f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; | |
| 1197 | 1219 | ctx->dst_fmt = find_format(&f, MFC_FMT_RAW); |
| 1198 | 1220 | mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n", |
| 1199 | 1221 | (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt); |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <media/v4l2-ctrls.h> |
| 27 | 27 | #include <media/videobuf2-core.h> |
| 28 | 28 | #include "s5p_mfc_common.h" |
| 29 | +#include "s5p_mfc_ctrl.h" | |
| 29 | 30 | #include "s5p_mfc_debug.h" |
| 30 | 31 | #include "s5p_mfc_enc.h" |
| 31 | 32 | #include "s5p_mfc_intr.h" |
| @@ -41,6 +42,7 @@ static struct s5p_mfc_fmt formats[] = { · 9 unmodified lines | ||
| 41 | 42 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 42 | 43 | .type = MFC_FMT_RAW, |
| 43 | 44 | .num_planes = 2, |
| 45 | + .versions = MFC_V6_BIT | MFC_V7_BIT, | |
| 44 | 46 | }, |
| 45 | 47 | { |
| 46 | 48 | .name = "4:2:0 2 Planes 64x32 Tiles", |
| @@ -48,6 +50,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 48 | 50 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 49 | 51 | .type = MFC_FMT_RAW, |
| 50 | 52 | .num_planes = 2, |
| 53 | + .versions = MFC_V5_BIT, | |
| 51 | 54 | }, |
| 52 | 55 | { |
| 53 | 56 | .name = "4:2:0 2 Planes Y/CbCr", |
| @@ -55,6 +58,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 55 | 58 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 56 | 59 | .type = MFC_FMT_RAW, |
| 57 | 60 | .num_planes = 2, |
| 61 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 62 | + MFC_V8_BIT, | |
| 58 | 63 | }, |
| 59 | 64 | { |
| 60 | 65 | .name = "4:2:0 2 Planes Y/CrCb", |
| @@ -62,6 +67,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 62 | 67 | .codec_mode = S5P_MFC_CODEC_NONE, |
| 63 | 68 | .type = MFC_FMT_RAW, |
| 64 | 69 | .num_planes = 2, |
| 70 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 71 | + MFC_V8_BIT, | |
| 65 | 72 | }, |
| 66 | 73 | { |
| 67 | 74 | .name = "H264 Encoded Stream", |
| @@ -69,6 +76,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 69 | 76 | .codec_mode = S5P_MFC_CODEC_H264_ENC, |
| 70 | 77 | .type = MFC_FMT_ENC, |
| 71 | 78 | .num_planes = 1, |
| 79 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 80 | + MFC_V8_BIT, | |
| 72 | 81 | }, |
| 73 | 82 | { |
| 74 | 83 | .name = "MPEG4 Encoded Stream", |
| @@ -76,6 +85,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 76 | 85 | .codec_mode = S5P_MFC_CODEC_MPEG4_ENC, |
| 77 | 86 | .type = MFC_FMT_ENC, |
| 78 | 87 | .num_planes = 1, |
| 88 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 89 | + MFC_V8_BIT, | |
| 79 | 90 | }, |
| 80 | 91 | { |
| 81 | 92 | .name = "H263 Encoded Stream", |
| @@ -83,6 +94,8 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 83 | 94 | .codec_mode = S5P_MFC_CODEC_H263_ENC, |
| 84 | 95 | .type = MFC_FMT_ENC, |
| 85 | 96 | .num_planes = 1, |
| 97 | + .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | | |
| 98 | + MFC_V8_BIT, | |
| 86 | 99 | }, |
| 87 | 100 | { |
| 88 | 101 | .name = "VP8 Encoded Stream", |
| @@ -90,6 +103,7 @@ static struct s5p_mfc_fmt formats[] = { · 1 unmodified line | ||
| 90 | 103 | .codec_mode = S5P_MFC_CODEC_VP8_ENC, |
| 91 | 104 | .type = MFC_FMT_ENC, |
| 92 | 105 | .num_planes = 1, |
| 106 | + .versions = MFC_V7_BIT | MFC_V8_BIT, | |
| 93 | 107 | }, |
| 94 | 108 | }; |
| 95 | 109 | |
| @@ -772,13 +786,16 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) · 676 unmodified lines | ||
| 772 | 786 | |
| 773 | 787 | if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) { |
| 774 | 788 | spin_lock_irqsave(&dev->irqlock, flags); |
| 775 | − dst_mb = list_entry(ctx->dst_queue.next, | |
| 776 | − struct s5p_mfc_buf, list); | |
| 777 | − list_del(&dst_mb->list); | |
| 778 | − ctx->dst_queue_cnt--; | |
| 779 | − vb2_set_plane_payload(dst_mb->b, 0, | |
| 780 | − s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev)); | |
| 781 | − vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); | |
| 789 | + if (!list_empty(&ctx->dst_queue)) { | |
| 790 | + dst_mb = list_entry(ctx->dst_queue.next, | |
| 791 | + struct s5p_mfc_buf, list); | |
| 792 | + list_del(&dst_mb->list); | |
| 793 | + ctx->dst_queue_cnt--; | |
| 794 | + vb2_set_plane_payload(dst_mb->b, 0, | |
| 795 | + s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, | |
| 796 | + dev)); | |
| 797 | + vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE); | |
| 798 | + } | |
| 782 | 799 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 783 | 800 | } |
| 784 | 801 | |
| @@ -883,8 +900,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) · 98 unmodified lines | ||
| 883 | 900 | mfc_debug(2, "enc src count: %d, enc ref count: %d\n", |
| 884 | 901 | ctx->src_queue_cnt, ctx->ref_queue_cnt); |
| 885 | 902 | } |
| 886 | − if (strm_size > 0) { | |
| 887 | − /* at least one more dest. buffers exist always */ | |
| 903 | + if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) { | |
| 888 | 904 | mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, |
| 889 | 905 | list); |
| 890 | 906 | list_del(&mb_entry->list); |
| @@ -937,8 +953,10 @@ static int vidioc_querycap(struct file *file, void *priv, · 46 unmodified lines | ||
| 937 | 953 | return 0; |
| 938 | 954 | } |
| 939 | 955 | |
| 940 | −static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) | |
| 956 | +static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, | |
| 957 | + bool mplane, bool out) | |
| 941 | 958 | { |
| 959 | + struct s5p_mfc_dev *dev = video_drvdata(file); | |
| 942 | 960 | struct s5p_mfc_fmt *fmt; |
| 943 | 961 | int i, j = 0; |
| 944 | 962 | |
| @@ -951,6 +969,9 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) · 6 unmodified lines | ||
| 951 | 969 | continue; |
| 952 | 970 | else if (!out && formats[i].type != MFC_FMT_ENC) |
| 953 | 971 | continue; |
| 972 | + else if ((dev->variant->version_bit & formats[i].versions) == 0) | |
| 973 | + continue; | |
| 974 | + | |
| 954 | 975 | if (j == f->index) { |
| 955 | 976 | fmt = &formats[i]; |
| 956 | 977 | strlcpy(f->description, fmt->name, |
| @@ -966,25 +987,25 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) · 9 unmodified lines | ||
| 966 | 987 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, |
| 967 | 988 | struct v4l2_fmtdesc *f) |
| 968 | 989 | { |
| 969 | − return vidioc_enum_fmt(f, false, false); | |
| 990 | + return vidioc_enum_fmt(file, f, false, false); | |
| 970 | 991 | } |
| 971 | 992 | |
| 972 | 993 | static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, |
| 973 | 994 | struct v4l2_fmtdesc *f) |
| 974 | 995 | { |
| 975 | − return vidioc_enum_fmt(f, true, false); | |
| 996 | + return vidioc_enum_fmt(file, f, true, false); | |
| 976 | 997 | } |
| 977 | 998 | |
| 978 | 999 | static int vidioc_enum_fmt_vid_out(struct file *file, void *prov, |
| 979 | 1000 | struct v4l2_fmtdesc *f) |
| 980 | 1001 | { |
| 981 | − return vidioc_enum_fmt(f, false, true); | |
| 1002 | + return vidioc_enum_fmt(file, f, false, true); | |
| 982 | 1003 | } |
| 983 | 1004 | |
| 984 | 1005 | static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, |
| 985 | 1006 | struct v4l2_fmtdesc *f) |
| 986 | 1007 | { |
| 987 | − return vidioc_enum_fmt(f, true, true); | |
| 1008 | + return vidioc_enum_fmt(file, f, true, true); | |
| 988 | 1009 | } |
| 989 | 1010 | |
| 990 | 1011 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) |
| @@ -1035,16 +1056,14 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) · 44 unmodified lines | ||
| 1035 | 1056 | mfc_err("failed to try output format\n"); |
| 1036 | 1057 | return -EINVAL; |
| 1037 | 1058 | } |
| 1038 | − | |
| 1039 | − if (!IS_MFCV7(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { | |
| 1040 | − mfc_err("VP8 is supported only in MFC v7\n"); | |
| 1041 | − return -EINVAL; | |
| 1042 | − } | |
| 1043 | − | |
| 1044 | 1059 | if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { |
| 1045 | 1060 | mfc_err("must be set encoding output size\n"); |
| 1046 | 1061 | return -EINVAL; |
| 1047 | 1062 | } |
| 1063 | + if ((dev->variant->version_bit & fmt->versions) == 0) { | |
| 1064 | + mfc_err("Unsupported format by this MFC version.\n"); | |
| 1065 | + return -EINVAL; | |
| 1066 | + } | |
| 1048 | 1067 | |
| 1049 | 1068 | pix_fmt_mp->plane_fmt[0].bytesperline = |
| 1050 | 1069 | pix_fmt_mp->plane_fmt[0].sizeimage; |
| @@ -1055,22 +1074,15 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) · 4 unmodified lines | ||
| 1055 | 1074 | return -EINVAL; |
| 1056 | 1075 | } |
| 1057 | 1076 | |
| 1058 | − if (!IS_MFCV6_PLUS(dev)) { | |
| 1059 | − if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { | |
| 1060 | − mfc_err("Not supported format.\n"); | |
| 1061 | − return -EINVAL; | |
| 1062 | − } | |
| 1063 | − } else if (IS_MFCV6_PLUS(dev)) { | |
| 1064 | − if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { | |
| 1065 | − mfc_err("Not supported format.\n"); | |
| 1066 | − return -EINVAL; | |
| 1067 | − } | |
| 1068 | − } | |
| 1069 | − | |
| 1070 | 1077 | if (fmt->num_planes != pix_fmt_mp->num_planes) { |
| 1071 | 1078 | mfc_err("failed to try output format\n"); |
| 1072 | 1079 | return -EINVAL; |
| 1073 | 1080 | } |
| 1081 | + if ((dev->variant->version_bit & fmt->versions) == 0) { | |
| 1082 | + mfc_err("Unsupported format by this MFC version.\n"); | |
| 1083 | + return -EINVAL; | |
| 1084 | + } | |
| 1085 | + | |
| 1074 | 1086 | v4l_bound_align_image(&pix_fmt_mp->width, 8, 1920, 1, |
| 1075 | 1087 | &pix_fmt_mp->height, 4, 1080, 1, 0); |
| 1076 | 1088 | } else { |
| @@ -1104,20 +1116,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · 27 unmodified lines | ||
| 1104 | 1116 | pix_fmt_mp->plane_fmt[0].bytesperline = 0; |
| 1105 | 1117 | ctx->dst_bufs_cnt = 0; |
| 1106 | 1118 | ctx->capture_state = QUEUE_FREE; |
| 1107 | − s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); | |
| 1108 | − set_work_bit_irqsave(ctx); | |
| 1109 | − s5p_mfc_clean_ctx_int_flags(ctx); | |
| 1110 | − s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); | |
| 1111 | − if (s5p_mfc_wait_for_done_ctx(ctx, \ | |
| 1112 | − S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 1)) { | |
| 1113 | − /* Error or timeout */ | |
| 1114 | − mfc_err("Error getting instance from hardware\n"); | |
| 1115 | − s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, | |
| 1116 | − ctx); | |
| 1117 | − ret = -EIO; | |
| 1118 | − goto out; | |
| 1119 | − } | |
| 1120 | − mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | |
| 1119 | + ret = s5p_mfc_open_mfc_inst(dev, ctx); | |
| 1121 | 1120 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| 1122 | 1121 | /* src_fmt is validated by call to vidioc_try_fmt */ |
| 1123 | 1122 | ctx->src_fmt = find_format(f, MFC_FMT_RAW); |
| @@ -1138,7 +1137,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · 14 unmodified lines | ||
| 1138 | 1137 | ctx->output_state = QUEUE_FREE; |
| 1139 | 1138 | } else { |
| 1140 | 1139 | mfc_err("invalid buf type\n"); |
| 1141 | − return -EINVAL; | |
| 1140 | + ret = -EINVAL; | |
| 1142 | 1141 | } |
| 1143 | 1142 | out: |
| 1144 | 1143 | mfc_debug_leave(); |
| @@ -1954,7 +1953,7 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) · 809 unmodified lines | ||
| 1954 | 1953 | return 0; |
| 1955 | 1954 | } |
| 1956 | 1955 | |
| 1957 | −static int s5p_mfc_stop_streaming(struct vb2_queue *q) | |
| 1956 | +static void s5p_mfc_stop_streaming(struct vb2_queue *q) | |
| 1958 | 1957 | { |
| 1959 | 1958 | unsigned long flags; |
| 1960 | 1959 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); |
| @@ -1983,7 +1982,6 @@ static int s5p_mfc_stop_streaming(struct vb2_queue *q) · 22 unmodified lines | ||
| 1983 | 1982 | ctx->src_queue_cnt = 0; |
| 1984 | 1983 | } |
| 1985 | 1984 | spin_unlock_irqrestore(&dev->irqlock, flags); |
| 1986 | − return 0; | |
| 1987 | 1985 | } |
| 1988 | 1986 | |
| 1989 | 1987 | static void s5p_mfc_buf_queue(struct vb2_buffer *vb) |
| @@ -31,6 +31,12 @@ void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) · 30 unmodified lines | ||
| 31 | 31 | dev->mfc_ops = s5p_mfc_ops; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | +void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) | |
| 35 | +{ | |
| 36 | + if (IS_MFCV6_PLUS(dev)) | |
| 37 | + dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); | |
| 38 | +} | |
| 39 | + | |
| 34 | 40 | int s5p_mfc_alloc_priv_buf(struct device *dev, |
| 35 | 41 | struct s5p_mfc_priv_buf *b) |
| 36 | 42 | { |
| @@ -17,6 +17,259 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include "s5p_mfc_common.h" |
| 19 | 19 | |
| 20 | +struct s5p_mfc_regs { | |
| 21 | + | |
| 22 | + /* codec common registers */ | |
| 23 | + void *risc_on; | |
| 24 | + void *risc2host_int; | |
| 25 | + void *host2risc_int; | |
| 26 | + void *risc_base_address; | |
| 27 | + void *mfc_reset; | |
| 28 | + void *host2risc_command; | |
| 29 | + void *risc2host_command; | |
| 30 | + void *mfc_bus_reset_ctrl; | |
| 31 | + void *firmware_version; | |
| 32 | + void *instance_id; | |
| 33 | + void *codec_type; | |
| 34 | + void *context_mem_addr; | |
| 35 | + void *context_mem_size; | |
| 36 | + void *pixel_format; | |
| 37 | + void *metadata_enable; | |
| 38 | + void *mfc_version; | |
| 39 | + void *dbg_info_enable; | |
| 40 | + void *dbg_buffer_addr; | |
| 41 | + void *dbg_buffer_size; | |
| 42 | + void *hed_control; | |
| 43 | + void *mfc_timeout_value; | |
| 44 | + void *hed_shared_mem_addr; | |
| 45 | + void *dis_shared_mem_addr;/* only v7 */ | |
| 46 | + void *ret_instance_id; | |
| 47 | + void *error_code; | |
| 48 | + void *dbg_buffer_output_size; | |
| 49 | + void *metadata_status; | |
| 50 | + void *metadata_addr_mb_info; | |
| 51 | + void *metadata_size_mb_info; | |
| 52 | + void *dbg_info_stage_counter; | |
| 53 | + | |
| 54 | + /* decoder registers */ | |
| 55 | + void *d_crc_ctrl; | |
| 56 | + void *d_dec_options; | |
| 57 | + void *d_display_delay; | |
| 58 | + void *d_set_frame_width; | |
| 59 | + void *d_set_frame_height; | |
| 60 | + void *d_sei_enable; | |
| 61 | + void *d_min_num_dpb; | |
| 62 | + void *d_min_first_plane_dpb_size; | |
| 63 | + void *d_min_second_plane_dpb_size; | |
| 64 | + void *d_min_third_plane_dpb_size;/* only v8 */ | |
| 65 | + void *d_min_num_mv; | |
| 66 | + void *d_mvc_num_views; | |
| 67 | + void *d_min_num_dis;/* only v7 */ | |
| 68 | + void *d_min_first_dis_size;/* only v7 */ | |
| 69 | + void *d_min_second_dis_size;/* only v7 */ | |
| 70 | + void *d_min_third_dis_size;/* only v7 */ | |
| 71 | + void *d_post_filter_luma_dpb0;/* v7 and v8 */ | |
| 72 | + void *d_post_filter_luma_dpb1;/* v7 and v8 */ | |
| 73 | + void *d_post_filter_luma_dpb2;/* only v7 */ | |
| 74 | + void *d_post_filter_chroma_dpb0;/* v7 and v8 */ | |
| 75 | + void *d_post_filter_chroma_dpb1;/* v7 and v8 */ | |
| 76 | + void *d_post_filter_chroma_dpb2;/* only v7 */ | |
| 77 | + void *d_num_dpb; | |
| 78 | + void *d_num_mv; | |
| 79 | + void *d_init_buffer_options; | |
| 80 | + void *d_first_plane_dpb_stride_size;/* only v8 */ | |
| 81 | + void *d_second_plane_dpb_stride_size;/* only v8 */ | |
| 82 | + void *d_third_plane_dpb_stride_size;/* only v8 */ | |
| 83 | + void *d_first_plane_dpb_size; | |
| 84 | + void *d_second_plane_dpb_size; | |
| 85 | + void *d_third_plane_dpb_size;/* only v8 */ | |
| 86 | + void *d_mv_buffer_size; | |
| 87 | + void *d_first_plane_dpb; | |
| 88 | + void *d_second_plane_dpb; | |
| 89 | + void *d_third_plane_dpb; | |
| 90 | + void *d_mv_buffer; | |
| 91 | + void *d_scratch_buffer_addr; | |
| 92 | + void *d_scratch_buffer_size; | |
| 93 | + void *d_metadata_buffer_addr; | |
| 94 | + void *d_metadata_buffer_size; | |
| 95 | + void *d_nal_start_options;/* v7 and v8 */ | |
| 96 | + void *d_cpb_buffer_addr; | |
| 97 | + void *d_cpb_buffer_size; | |
| 98 | + void *d_available_dpb_flag_upper; | |
| 99 | + void *d_available_dpb_flag_lower; | |
| 100 | + void *d_cpb_buffer_offset; | |
| 101 | + void *d_slice_if_enable; | |
| 102 | + void *d_picture_tag; | |
| 103 | + void *d_stream_data_size; | |
| 104 | + void *d_dynamic_dpb_flag_upper;/* v7 and v8 */ | |
| 105 | + void *d_dynamic_dpb_flag_lower;/* v7 and v8 */ | |
| 106 | + void *d_display_frame_width; | |
| 107 | + void *d_display_frame_height; | |
| 108 | + void *d_display_status; | |
| 109 | + void *d_display_first_plane_addr; | |
| 110 | + void *d_display_second_plane_addr; | |
| 111 | + void *d_display_third_plane_addr;/* only v8 */ | |
| 112 | + void *d_display_frame_type; | |
| 113 | + void *d_display_crop_info1; | |
| 114 | + void *d_display_crop_info2; | |
| 115 | + void *d_display_picture_profile; | |
| 116 | + void *d_display_luma_crc;/* v7 and v8 */ | |
| 117 | + void *d_display_chroma0_crc;/* v7 and v8 */ | |
| 118 | + void *d_display_chroma1_crc;/* only v8 */ | |
| 119 | + void *d_display_luma_crc_top;/* only v6 */ | |
| 120 | + void *d_display_chroma_crc_top;/* only v6 */ | |
| 121 | + void *d_display_luma_crc_bot;/* only v6 */ | |
| 122 | + void *d_display_chroma_crc_bot;/* only v6 */ | |
| 123 | + void *d_display_aspect_ratio; | |
| 124 | + void *d_display_extended_ar; | |
| 125 | + void *d_decoded_frame_width; | |
| 126 | + void *d_decoded_frame_height; | |
| 127 | + void *d_decoded_status; | |
| 128 | + void *d_decoded_first_plane_addr; | |
| 129 | + void *d_decoded_second_plane_addr; | |
| 130 | + void *d_decoded_third_plane_addr;/* only v8 */ | |
| 131 | + void *d_decoded_frame_type; | |
| 132 | + void *d_decoded_crop_info1; | |
| 133 | + void *d_decoded_crop_info2; | |
| 134 | + void *d_decoded_picture_profile; | |
| 135 | + void *d_decoded_nal_size; | |
| 136 | + void *d_decoded_luma_crc; | |
| 137 | + void *d_decoded_chroma0_crc; | |
| 138 | + void *d_decoded_chroma1_crc;/* only v8 */ | |
| 139 | + void *d_ret_picture_tag_top; | |
| 140 | + void *d_ret_picture_tag_bot; | |
| 141 | + void *d_ret_picture_time_top; | |
| 142 | + void *d_ret_picture_time_bot; | |
| 143 | + void *d_chroma_format; | |
| 144 | + void *d_vc1_info;/* v7 and v8 */ | |
| 145 | + void *d_mpeg4_info; | |
| 146 | + void *d_h264_info; | |
| 147 | + void *d_metadata_addr_concealed_mb; | |
| 148 | + void *d_metadata_size_concealed_mb; | |
| 149 | + void *d_metadata_addr_vc1_param; | |
| 150 | + void *d_metadata_size_vc1_param; | |
| 151 | + void *d_metadata_addr_sei_nal; | |
| 152 | + void *d_metadata_size_sei_nal; | |
| 153 | + void *d_metadata_addr_vui; | |
| 154 | + void *d_metadata_size_vui; | |
| 155 | + void *d_metadata_addr_mvcvui;/* v7 and v8 */ | |
| 156 | + void *d_metadata_size_mvcvui;/* v7 and v8 */ | |
| 157 | + void *d_mvc_view_id; | |
| 158 | + void *d_frame_pack_sei_avail; | |
| 159 | + void *d_frame_pack_arrgment_id; | |
| 160 | + void *d_frame_pack_sei_info; | |
| 161 | + void *d_frame_pack_grid_pos; | |
| 162 | + void *d_display_recovery_sei_info;/* v7 and v8 */ | |
| 163 | + void *d_decoded_recovery_sei_info;/* v7 and v8 */ | |
| 164 | + void *d_display_first_addr;/* only v7 */ | |
| 165 | + void *d_display_second_addr;/* only v7 */ | |
| 166 | + void *d_display_third_addr;/* only v7 */ | |
| 167 | + void *d_decoded_first_addr;/* only v7 */ | |
| 168 | + void *d_decoded_second_addr;/* only v7 */ | |
| 169 | + void *d_decoded_third_addr;/* only v7 */ | |
| 170 | + void *d_used_dpb_flag_upper;/* v7 and v8 */ | |
| 171 | + void *d_used_dpb_flag_lower;/* v7 and v8 */ | |
| 172 | + | |
| 173 | + /* encoder registers */ | |
| 174 | + void *e_frame_width; | |
| 175 | + void *e_frame_height; | |
| 176 | + void *e_cropped_frame_width; | |
| 177 | + void *e_cropped_frame_height; | |
| 178 | + void *e_frame_crop_offset; | |
| 179 | + void *e_enc_options; | |
| 180 | + void *e_picture_profile; | |
| 181 | + void *e_vbv_buffer_size; | |
| 182 | + void *e_vbv_init_delay; | |
| 183 | + void *e_fixed_picture_qp; | |
| 184 | + void *e_rc_config; | |
| 185 | + void *e_rc_qp_bound; | |
| 186 | + void *e_rc_qp_bound_pb;/* v7 and v8 */ | |
| 187 | + void *e_rc_mode; | |
| 188 | + void *e_mb_rc_config; | |
| 189 | + void *e_padding_ctrl; | |
| 190 | + void *e_air_threshold; | |
| 191 | + void *e_mv_hor_range; | |
| 192 | + void *e_mv_ver_range; | |
| 193 | + void *e_num_dpb; | |
| 194 | + void *e_luma_dpb; | |
| 195 | + void *e_chroma_dpb; | |
| 196 | + void *e_me_buffer; | |
| 197 | + void *e_scratch_buffer_addr; | |
| 198 | + void *e_scratch_buffer_size; | |
| 199 | + void *e_tmv_buffer0; | |
| 200 | + void *e_tmv_buffer1; | |
| 201 | + void *e_ir_buffer_addr;/* v7 and v8 */ | |
| 202 | + void *e_source_first_plane_addr; | |
| 203 | + void *e_source_second_plane_addr; | |
| 204 | + void *e_source_third_plane_addr;/* v7 and v8 */ | |
| 205 | + void *e_source_first_plane_stride;/* v7 and v8 */ | |
| 206 | + void *e_source_second_plane_stride;/* v7 and v8 */ | |
| 207 | + void *e_source_third_plane_stride;/* v7 and v8 */ | |
| 208 | + void *e_stream_buffer_addr; | |
| 209 | + void *e_stream_buffer_size; | |
| 210 | + void *e_roi_buffer_addr; | |
| 211 | + void *e_param_change; | |
| 212 | + void *e_ir_size; | |
| 213 | + void *e_gop_config; | |
| 214 | + void *e_mslice_mode; | |
| 215 | + void *e_mslice_size_mb; | |
| 216 | + void *e_mslice_size_bits; | |
| 217 | + void *e_frame_insertion; | |
| 218 | + void *e_rc_frame_rate; | |
| 219 | + void *e_rc_bit_rate; | |
| 220 | + void *e_rc_roi_ctrl; | |
| 221 | + void *e_picture_tag; | |
| 222 | + void *e_bit_count_enable; | |
| 223 | + void *e_max_bit_count; | |
| 224 | + void *e_min_bit_count; | |
| 225 | + void *e_metadata_buffer_addr; | |
| 226 | + void *e_metadata_buffer_size; | |
| 227 | + void *e_encoded_source_first_plane_addr; | |
| 228 | + void *e_encoded_source_second_plane_addr; | |
| 229 | + void *e_encoded_source_third_plane_addr;/* v7 and v8 */ | |
| 230 | + void *e_stream_size; | |
| 231 | + void *e_slice_type; | |
| 232 | + void *e_picture_count; | |
| 233 | + void *e_ret_picture_tag; | |
| 234 | + void *e_stream_buffer_write_pointer; /* only v6 */ | |
| 235 | + void *e_recon_luma_dpb_addr; | |
| 236 | + void *e_recon_chroma_dpb_addr; | |
| 237 | + void *e_metadata_addr_enc_slice; | |
| 238 | + void *e_metadata_size_enc_slice; | |
| 239 | + void *e_mpeg4_options; | |
| 240 | + void *e_mpeg4_hec_period; | |
| 241 | + void *e_aspect_ratio; | |
| 242 | + void *e_extended_sar; | |
| 243 | + void *e_h264_options; | |
| 244 | + void *e_h264_options_2;/* v7 and v8 */ | |
| 245 | + void *e_h264_lf_alpha_offset; | |
| 246 | + void *e_h264_lf_beta_offset; | |
| 247 | + void *e_h264_i_period; | |
| 248 | + void *e_h264_fmo_slice_grp_map_type; | |
| 249 | + void *e_h264_fmo_num_slice_grp_minus1; | |
| 250 | + void *e_h264_fmo_slice_grp_change_dir; | |
| 251 | + void *e_h264_fmo_slice_grp_change_rate_minus1; | |
| 252 | + void *e_h264_fmo_run_length_minus1_0; | |
| 253 | + void *e_h264_aso_slice_order_0; | |
| 254 | + void *e_h264_chroma_qp_offset; | |
| 255 | + void *e_h264_num_t_layer; | |
| 256 | + void *e_h264_hierarchical_qp_layer0; | |
| 257 | + void *e_h264_frame_packing_sei_info; | |
| 258 | + void *e_h264_nal_control;/* v7 and v8 */ | |
| 259 | + void *e_mvc_frame_qp_view1; | |
| 260 | + void *e_mvc_rc_bit_rate_view1; | |
| 261 | + void *e_mvc_rc_qbound_view1; | |
| 262 | + void *e_mvc_rc_mode_view1; | |
| 263 | + void *e_mvc_inter_view_prediction_on; | |
| 264 | + void *e_vp8_options;/* v7 and v8 */ | |
| 265 | + void *e_vp8_filter_options;/* v7 and v8 */ | |
| 266 | + void *e_vp8_golden_frame_option;/* v7 and v8 */ | |
| 267 | + void *e_vp8_num_t_layer;/* v7 and v8 */ | |
| 268 | + void *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */ | |
| 269 | + void *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */ | |
| 270 | + void *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */ | |
| 271 | +}; | |
| 272 | + | |
| 20 | 273 | struct s5p_mfc_hw_ops { |
| 21 | 274 | int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx); |
| 22 | 275 | void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx); |
| @@ -80,6 +333,7 @@ struct s5p_mfc_hw_ops { · 57 unmodified lines | ||
| 80 | 333 | }; |
| 81 | 334 | |
| 82 | 335 | void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); |
| 336 | +void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); | |
| 83 | 337 | int s5p_mfc_alloc_priv_buf(struct device *dev, |
| 84 | 338 | struct s5p_mfc_priv_buf *b); |
| 85 | 339 | void s5p_mfc_release_priv_buf(struct device *dev, |
| @@ -43,10 +43,10 @@ · 42 unmodified lines | ||
| 43 | 43 | } while (0) |
| 44 | 44 | #endif /* S5P_MFC_DEBUG_REGWRITE */ |
| 45 | 45 | |
| 46 | −#define READL(offset) readl(dev->regs_base + (offset)) | |
| 47 | −#define WRITEL(data, offset) writel((data), dev->regs_base + (offset)) | |
| 48 | −#define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET) | |
| 49 | −#define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET) | |
| 46 | +#define READL(reg) \ | |
| 47 | + (WARN_ON_ONCE(!(reg)) ? 0 : readl(reg)) | |
| 48 | +#define WRITEL(data, reg) \ | |
| 49 | + (WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg))) | |
| 50 | 50 | |
| 51 | 51 | /* Allocate temporary buffers for decoding */ |
| 52 | 52 | static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx) |
| @@ -77,7 +77,12 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 24 unmodified lines | ||
| 77 | 77 | ctx->luma_size, ctx->chroma_size, ctx->mv_size); |
| 78 | 78 | mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count); |
| 79 | 79 | } else if (ctx->type == MFCINST_ENCODER) { |
| 80 | − ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | |
| 80 | + if (IS_MFCV8(dev)) | |
| 81 | + ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | |
| 82 | + ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height), | |
| 83 | + S5P_FIMV_TMV_BUFFER_ALIGN_V6); | |
| 84 | + else | |
| 85 | + ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 * | |
| 81 | 86 | ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height), |
| 82 | 87 | S5P_FIMV_TMV_BUFFER_ALIGN_V6); |
| 83 | 88 | |
| @@ -87,10 +92,16 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 87 | 92 | ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * |
| 88 | 93 | S5P_FIMV_CHROMA_MB_TO_PIXEL_V6, |
| 89 | 94 | S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6); |
| 90 | − ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( | |
| 91 | − ctx->img_width, ctx->img_height, | |
| 92 | − mb_width, mb_height), | |
| 93 | − S5P_FIMV_ME_BUFFER_ALIGN_V6); | |
| 95 | + if (IS_MFCV8(dev)) | |
| 96 | + ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8( | |
| 97 | + ctx->img_width, ctx->img_height, | |
| 98 | + mb_width, mb_height), | |
| 99 | + S5P_FIMV_ME_BUFFER_ALIGN_V6); | |
| 100 | + else | |
| 101 | + ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6( | |
| 102 | + ctx->img_width, ctx->img_height, | |
| 103 | + mb_width, mb_height), | |
| 104 | + S5P_FIMV_ME_BUFFER_ALIGN_V6); | |
| 94 | 105 | |
| 95 | 106 | mfc_debug(2, "recon luma size: %d chroma size: %d\n", |
| 96 | 107 | ctx->luma_dpb_size, ctx->chroma_dpb_size); |
| @@ -102,8 +113,14 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 5 unmodified lines | ||
| 102 | 113 | switch (ctx->codec_mode) { |
| 103 | 114 | case S5P_MFC_CODEC_H264_DEC: |
| 104 | 115 | case S5P_MFC_CODEC_H264_MVC_DEC: |
| 105 | − ctx->scratch_buf_size = | |
| 106 | − S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( | |
| 116 | + if (IS_MFCV8(dev)) | |
| 117 | + ctx->scratch_buf_size = | |
| 118 | + S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8( | |
| 119 | + mb_width, | |
| 120 | + mb_height); | |
| 121 | + else | |
| 122 | + ctx->scratch_buf_size = | |
| 123 | + S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6( | |
| 107 | 124 | mb_width, |
| 108 | 125 | mb_height); |
| 109 | 126 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
| @@ -113,7 +130,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 113 | 130 | (ctx->mv_count * ctx->mv_size); |
| 114 | 131 | break; |
| 115 | 132 | case S5P_MFC_CODEC_MPEG4_DEC: |
| 116 | − if (IS_MFCV7(dev)) { | |
| 133 | + if (IS_MFCV7_PLUS(dev)) { | |
| 117 | 134 | ctx->scratch_buf_size = |
| 118 | 135 | S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7( |
| 119 | 136 | mb_width, |
| @@ -153,19 +170,31 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 33 unmodified lines | ||
| 153 | 170 | ctx->bank1.size = ctx->scratch_buf_size; |
| 154 | 171 | break; |
| 155 | 172 | case S5P_MFC_CODEC_VP8_DEC: |
| 156 | − ctx->scratch_buf_size = | |
| 157 | − S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( | |
| 158 | − mb_width, | |
| 159 | − mb_height); | |
| 173 | + if (IS_MFCV8(dev)) | |
| 174 | + ctx->scratch_buf_size = | |
| 175 | + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8( | |
| 176 | + mb_width, | |
| 177 | + mb_height); | |
| 178 | + else | |
| 179 | + ctx->scratch_buf_size = | |
| 180 | + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6( | |
| 181 | + mb_width, | |
| 182 | + mb_height); | |
| 160 | 183 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
| 161 | 184 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 162 | 185 | ctx->bank1.size = ctx->scratch_buf_size; |
| 163 | 186 | break; |
| 164 | 187 | case S5P_MFC_CODEC_H264_ENC: |
| 165 | − ctx->scratch_buf_size = | |
| 166 | − S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( | |
| 188 | + if (IS_MFCV8(dev)) | |
| 189 | + ctx->scratch_buf_size = | |
| 190 | + S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8( | |
| 167 | 191 | mb_width, |
| 168 | 192 | mb_height); |
| 193 | + else | |
| 194 | + ctx->scratch_buf_size = | |
| 195 | + S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6( | |
| 196 | + mb_width, | |
| 197 | + mb_height); | |
| 169 | 198 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
| 170 | 199 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 171 | 200 | ctx->bank1.size = |
| @@ -189,10 +218,16 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) · 17 unmodified lines | ||
| 189 | 218 | ctx->bank2.size = 0; |
| 190 | 219 | break; |
| 191 | 220 | case S5P_MFC_CODEC_VP8_ENC: |
| 192 | − ctx->scratch_buf_size = | |
| 193 | − S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( | |
| 221 | + if (IS_MFCV8(dev)) | |
| 222 | + ctx->scratch_buf_size = | |
| 223 | + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8( | |
| 194 | 224 | mb_width, |
| 195 | 225 | mb_height); |
| 226 | + else | |
| 227 | + ctx->scratch_buf_size = | |
| 228 | + S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7( | |
| 229 | + mb_width, | |
| 230 | + mb_height); | |
| 196 | 231 | ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, |
| 197 | 232 | S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6); |
| 198 | 233 | ctx->bank1.size = |
| @@ -332,6 +367,12 @@ static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx) · 133 unmodified lines | ||
| 332 | 367 | |
| 333 | 368 | ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height); |
| 334 | 369 | ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1)); |
| 370 | + if (IS_MFCV8(ctx->dev)) { | |
| 371 | + /* MFCv8 needs additional 64 bytes for luma,chroma dpb*/ | |
| 372 | + ctx->luma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8; | |
| 373 | + ctx->chroma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8; | |
| 374 | + } | |
| 375 | + | |
| 335 | 376 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || |
| 336 | 377 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { |
| 337 | 378 | ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width, |
| @@ -354,7 +395,7 @@ static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx) · 16 unmodified lines | ||
| 354 | 395 | ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256); |
| 355 | 396 | |
| 356 | 397 | /* MFCv7 needs pad bytes for Luma and Chroma */ |
| 357 | − if (IS_MFCV7(ctx->dev)) { | |
| 398 | + if (IS_MFCV7_PLUS(ctx->dev)) { | |
| 358 | 399 | ctx->luma_size += MFC_LUMA_PAD_BYTES_V7; |
| 359 | 400 | ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7; |
| 360 | 401 | } |
| @@ -366,16 +407,17 @@ static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx, · 5 unmodified lines | ||
| 366 | 407 | unsigned int strm_size) |
| 367 | 408 | { |
| 368 | 409 | struct s5p_mfc_dev *dev = ctx->dev; |
| 410 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 369 | 411 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; |
| 370 | 412 | |
| 371 | 413 | mfc_debug_enter(); |
| 372 | 414 | mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n" |
| 373 | 415 | "buf_size: 0x%08x (%d)\n", |
| 374 | 416 | ctx->inst_no, buf_addr, strm_size, strm_size); |
| 375 | − WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6); | |
| 376 | − WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); | |
| 377 | − WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); | |
| 378 | − WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); | |
| 417 | + WRITEL(strm_size, mfc_regs->d_stream_data_size); | |
| 418 | + WRITEL(buf_addr, mfc_regs->d_cpb_buffer_addr); | |
| 419 | + WRITEL(buf_size->cpb, mfc_regs->d_cpb_buffer_size); | |
| 420 | + WRITEL(start_num_byte, mfc_regs->d_cpb_buffer_offset); | |
| 379 | 421 | |
| 380 | 422 | mfc_debug_leave(); |
| 381 | 423 | return 0; |
| @@ -387,6 +429,7 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) · 5 unmodified lines | ||
| 387 | 429 | unsigned int frame_size, i; |
| 388 | 430 | unsigned int frame_size_ch, frame_size_mv; |
| 389 | 431 | struct s5p_mfc_dev *dev = ctx->dev; |
| 432 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 390 | 433 | size_t buf_addr1; |
| 391 | 434 | int buf_size1; |
| 392 | 435 | int align_gap; |
| @@ -398,19 +441,27 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) · 5 unmodified lines | ||
| 398 | 441 | mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count); |
| 399 | 442 | mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay); |
| 400 | 443 | |
| 401 | − WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB_V6); | |
| 402 | − WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); | |
| 403 | − WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); | |
| 444 | + WRITEL(ctx->total_dpb_count, mfc_regs->d_num_dpb); | |
| 445 | + WRITEL(ctx->luma_size, mfc_regs->d_first_plane_dpb_size); | |
| 446 | + WRITEL(ctx->chroma_size, mfc_regs->d_second_plane_dpb_size); | |
| 447 | + | |
| 448 | + WRITEL(buf_addr1, mfc_regs->d_scratch_buffer_addr); | |
| 449 | + WRITEL(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size); | |
| 450 | + | |
| 451 | + if (IS_MFCV8(dev)) { | |
| 452 | + WRITEL(ctx->img_width, | |
| 453 | + mfc_regs->d_first_plane_dpb_stride_size); | |
| 454 | + WRITEL(ctx->img_width, | |
| 455 | + mfc_regs->d_second_plane_dpb_stride_size); | |
| 456 | + } | |
| 404 | 457 | |
| 405 | − WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); | |
| 406 | − WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); | |
| 407 | 458 | buf_addr1 += ctx->scratch_buf_size; |
| 408 | 459 | buf_size1 -= ctx->scratch_buf_size; |
| 409 | 460 | |
| 410 | 461 | if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC || |
| 411 | 462 | ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC){ |
| 412 | − WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6); | |
| 413 | − WRITEL(ctx->mv_count, S5P_FIMV_D_NUM_MV_V6); | |
| 463 | + WRITEL(ctx->mv_size, mfc_regs->d_mv_buffer_size); | |
| 464 | + WRITEL(ctx->mv_count, mfc_regs->d_num_mv); | |
| 414 | 465 | } |
| 415 | 466 | |
| 416 | 467 | frame_size = ctx->luma_size; |
| @@ -424,11 +475,11 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) · 7 unmodified lines | ||
| 424 | 475 | mfc_debug(2, "Luma %d: %x\n", i, |
| 425 | 476 | ctx->dst_bufs[i].cookie.raw.luma); |
| 426 | 477 | WRITEL(ctx->dst_bufs[i].cookie.raw.luma, |
| 427 | − S5P_FIMV_D_LUMA_DPB_V6 + i * 4); | |
| 478 | + mfc_regs->d_first_plane_dpb + i * 4); | |
| 428 | 479 | mfc_debug(2, "\tChroma %d: %x\n", i, |
| 429 | 480 | ctx->dst_bufs[i].cookie.raw.chroma); |
| 430 | 481 | WRITEL(ctx->dst_bufs[i].cookie.raw.chroma, |
| 431 | − S5P_FIMV_D_CHROMA_DPB_V6 + i * 4); | |
| 482 | + mfc_regs->d_second_plane_dpb + i * 4); | |
| 432 | 483 | } |
| 433 | 484 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC || |
| 434 | 485 | ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) { |
| @@ -441,7 +492,7 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) · 6 unmodified lines | ||
| 441 | 492 | |
| 442 | 493 | mfc_debug(2, "\tBuf1: %x, size: %d\n", |
| 443 | 494 | buf_addr1, buf_size1); |
| 444 | − WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER_V6 + i * 4); | |
| 495 | + WRITEL(buf_addr1, mfc_regs->d_mv_buffer + i * 4); | |
| 445 | 496 | buf_addr1 += frame_size_mv; |
| 446 | 497 | buf_size1 -= frame_size_mv; |
| 447 | 498 | } |
| @@ -454,7 +505,7 @@ static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx) · 6 unmodified lines | ||
| 454 | 505 | return -ENOMEM; |
| 455 | 506 | } |
| 456 | 507 | |
| 457 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 508 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 458 | 509 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 459 | 510 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); |
| 460 | 511 | |
| @@ -467,9 +518,10 @@ static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx, · 6 unmodified lines | ||
| 467 | 518 | unsigned long addr, unsigned int size) |
| 468 | 519 | { |
| 469 | 520 | struct s5p_mfc_dev *dev = ctx->dev; |
| 521 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 470 | 522 | |
| 471 | − WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); /* 16B align */ | |
| 472 | − WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); | |
| 523 | + WRITEL(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */ | |
| 524 | + WRITEL(size, mfc_regs->e_stream_buffer_size); | |
| 473 | 525 | |
| 474 | 526 | mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d\n", |
| 475 | 527 | addr, size); |
| @@ -481,14 +533,10 @@ static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, · 5 unmodified lines | ||
| 481 | 533 | unsigned long y_addr, unsigned long c_addr) |
| 482 | 534 | { |
| 483 | 535 | struct s5p_mfc_dev *dev = ctx->dev; |
| 536 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 484 | 537 | |
| 485 | − if (IS_MFCV7(dev)) { | |
| 486 | − WRITEL(y_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); | |
| 487 | − WRITEL(c_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); | |
| 488 | − } else { | |
| 489 | − WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); | |
| 490 | − WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | |
| 491 | − } | |
| 538 | + WRITEL(y_addr, mfc_regs->e_source_first_plane_addr); | |
| 539 | + WRITEL(c_addr, mfc_regs->e_source_second_plane_addr); | |
| 492 | 540 | |
| 493 | 541 | mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr); |
| 494 | 542 | mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr); |
| @@ -498,18 +546,14 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, · 3 unmodified lines | ||
| 498 | 546 | unsigned long *y_addr, unsigned long *c_addr) |
| 499 | 547 | { |
| 500 | 548 | struct s5p_mfc_dev *dev = ctx->dev; |
| 549 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 501 | 550 | unsigned long enc_recon_y_addr, enc_recon_c_addr; |
| 502 | 551 | |
| 503 | − if (IS_MFCV7(dev)) { | |
| 504 | − *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); | |
| 505 | − *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); | |
| 506 | − } else { | |
| 507 | − *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | |
| 508 | − *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | |
| 509 | − } | |
| 552 | + *y_addr = READL(mfc_regs->e_encoded_source_first_plane_addr); | |
| 553 | + *c_addr = READL(mfc_regs->e_encoded_source_second_plane_addr); | |
| 510 | 554 | |
| 511 | − enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | |
| 512 | − enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | |
| 555 | + enc_recon_y_addr = READL(mfc_regs->e_recon_luma_dpb_addr); | |
| 556 | + enc_recon_c_addr = READL(mfc_regs->e_recon_chroma_dpb_addr); | |
| 513 | 557 | |
| 514 | 558 | mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr); |
| 515 | 559 | mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr); |
| @@ -519,6 +563,7 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx, · 3 unmodified lines | ||
| 519 | 563 | static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) |
| 520 | 564 | { |
| 521 | 565 | struct s5p_mfc_dev *dev = ctx->dev; |
| 566 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 522 | 567 | size_t buf_addr1; |
| 523 | 568 | int i, buf_size1; |
| 524 | 569 | |
| @@ -530,24 +575,24 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) · 5 unmodified lines | ||
| 530 | 575 | mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1); |
| 531 | 576 | |
| 532 | 577 | for (i = 0; i < ctx->pb_count; i++) { |
| 533 | − WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i)); | |
| 578 | + WRITEL(buf_addr1, mfc_regs->e_luma_dpb + (4 * i)); | |
| 534 | 579 | buf_addr1 += ctx->luma_dpb_size; |
| 535 | − WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i)); | |
| 580 | + WRITEL(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i)); | |
| 536 | 581 | buf_addr1 += ctx->chroma_dpb_size; |
| 537 | − WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i)); | |
| 582 | + WRITEL(buf_addr1, mfc_regs->e_me_buffer + (4 * i)); | |
| 538 | 583 | buf_addr1 += ctx->me_buffer_size; |
| 539 | 584 | buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size + |
| 540 | 585 | ctx->me_buffer_size); |
| 541 | 586 | } |
| 542 | 587 | |
| 543 | − WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6); | |
| 544 | − WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); | |
| 588 | + WRITEL(buf_addr1, mfc_regs->e_scratch_buffer_addr); | |
| 589 | + WRITEL(ctx->scratch_buf_size, mfc_regs->e_scratch_buffer_size); | |
| 545 | 590 | buf_addr1 += ctx->scratch_buf_size; |
| 546 | 591 | buf_size1 -= ctx->scratch_buf_size; |
| 547 | 592 | |
| 548 | − WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0_V6); | |
| 593 | + WRITEL(buf_addr1, mfc_regs->e_tmv_buffer0); | |
| 549 | 594 | buf_addr1 += ctx->tmv_buffer_size >> 1; |
| 550 | − WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1_V6); | |
| 595 | + WRITEL(buf_addr1, mfc_regs->e_tmv_buffer1); | |
| 551 | 596 | buf_addr1 += ctx->tmv_buffer_size >> 1; |
| 552 | 597 | buf_size1 -= ctx->tmv_buffer_size; |
| 553 | 598 | |
| @@ -558,7 +603,7 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 558 | 603 | return -ENOMEM; |
| 559 | 604 | } |
| 560 | 605 | |
| 561 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 606 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 562 | 607 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 563 | 608 | S5P_FIMV_CH_INIT_BUFS_V6, NULL); |
| 564 | 609 | |
| @@ -570,18 +615,19 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx) · 5 unmodified lines | ||
| 570 | 615 | static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) |
| 571 | 616 | { |
| 572 | 617 | struct s5p_mfc_dev *dev = ctx->dev; |
| 618 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 573 | 619 | |
| 574 | 620 | /* multi-slice control */ |
| 575 | 621 | /* multi-slice MB number or bit size */ |
| 576 | − WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE_V6); | |
| 622 | + WRITEL(ctx->slice_mode, mfc_regs->e_mslice_mode); | |
| 577 | 623 | if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { |
| 578 | − WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | |
| 624 | + WRITEL(ctx->slice_size.mb, mfc_regs->e_mslice_size_mb); | |
| 579 | 625 | } else if (ctx->slice_mode == |
| 580 | 626 | V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { |
| 581 | − WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | |
| 627 | + WRITEL(ctx->slice_size.bits, mfc_regs->e_mslice_size_bits); | |
| 582 | 628 | } else { |
| 583 | − WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | |
| 584 | − WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | |
| 629 | + WRITEL(0x0, mfc_regs->e_mslice_size_mb); | |
| 630 | + WRITEL(0x0, mfc_regs->e_mslice_size_bits); | |
| 585 | 631 | } |
| 586 | 632 | |
| 587 | 633 | return 0; |
| @@ -590,27 +636,28 @@ static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx) · 2 unmodified lines | ||
| 590 | 636 | static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) |
| 591 | 637 | { |
| 592 | 638 | struct s5p_mfc_dev *dev = ctx->dev; |
| 639 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 593 | 640 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 594 | 641 | unsigned int reg = 0; |
| 595 | 642 | |
| 596 | 643 | mfc_debug_enter(); |
| 597 | 644 | |
| 598 | 645 | /* width */ |
| 599 | − WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH_V6); /* 16 align */ | |
| 646 | + WRITEL(ctx->img_width, mfc_regs->e_frame_width); /* 16 align */ | |
| 600 | 647 | /* height */ |
| 601 | − WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT_V6); /* 16 align */ | |
| 648 | + WRITEL(ctx->img_height, mfc_regs->e_frame_height); /* 16 align */ | |
| 602 | 649 | |
| 603 | 650 | /* cropped width */ |
| 604 | − WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); | |
| 651 | + WRITEL(ctx->img_width, mfc_regs->e_cropped_frame_width); | |
| 605 | 652 | /* cropped height */ |
| 606 | − WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | |
| 653 | + WRITEL(ctx->img_height, mfc_regs->e_cropped_frame_height); | |
| 607 | 654 | /* cropped offset */ |
| 608 | − WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); | |
| 655 | + WRITEL(0x0, mfc_regs->e_frame_crop_offset); | |
| 609 | 656 | |
| 610 | 657 | /* pictype : IDR period */ |
| 611 | 658 | reg = 0; |
| 612 | 659 | reg |= p->gop_size & 0xFFFF; |
| 613 | − WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | |
| 660 | + WRITEL(reg, mfc_regs->e_gop_config); | |
| 614 | 661 | |
| 615 | 662 | /* multi-slice control */ |
| 616 | 663 | /* multi-slice MB number or bit size */ |
| @@ -618,65 +665,65 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 618 | 665 | reg = 0; |
| 619 | 666 | if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) { |
| 620 | 667 | reg |= (0x1 << 3); |
| 621 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 668 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 622 | 669 | ctx->slice_size.mb = p->slice_mb; |
| 623 | 670 | } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) { |
| 624 | 671 | reg |= (0x1 << 3); |
| 625 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 672 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 626 | 673 | ctx->slice_size.bits = p->slice_bit; |
| 627 | 674 | } else { |
| 628 | 675 | reg &= ~(0x1 << 3); |
| 629 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 676 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 630 | 677 | } |
| 631 | 678 | |
| 632 | 679 | s5p_mfc_set_slice_mode(ctx); |
| 633 | 680 | |
| 634 | 681 | /* cyclic intra refresh */ |
| 635 | − WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE_V6); | |
| 636 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 682 | + WRITEL(p->intra_refresh_mb, mfc_regs->e_ir_size); | |
| 683 | + reg = READL(mfc_regs->e_enc_options); | |
| 637 | 684 | if (p->intra_refresh_mb == 0) |
| 638 | 685 | reg &= ~(0x1 << 4); |
| 639 | 686 | else |
| 640 | 687 | reg |= (0x1 << 4); |
| 641 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 688 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 642 | 689 | |
| 643 | 690 | /* 'NON_REFERENCE_STORE_ENABLE' for debugging */ |
| 644 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 691 | + reg = READL(mfc_regs->e_enc_options); | |
| 645 | 692 | reg &= ~(0x1 << 9); |
| 646 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 693 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 647 | 694 | |
| 648 | 695 | /* memory structure cur. frame */ |
| 649 | 696 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) { |
| 650 | 697 | /* 0: Linear, 1: 2D tiled*/ |
| 651 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 698 | + reg = READL(mfc_regs->e_enc_options); | |
| 652 | 699 | reg &= ~(0x1 << 7); |
| 653 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 700 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 654 | 701 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
| 655 | − WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 702 | + WRITEL(0x0, mfc_regs->pixel_format); | |
| 656 | 703 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) { |
| 657 | 704 | /* 0: Linear, 1: 2D tiled*/ |
| 658 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 705 | + reg = READL(mfc_regs->e_enc_options); | |
| 659 | 706 | reg &= ~(0x1 << 7); |
| 660 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 707 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 661 | 708 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
| 662 | − WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 709 | + WRITEL(0x1, mfc_regs->pixel_format); | |
| 663 | 710 | } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { |
| 664 | 711 | /* 0: Linear, 1: 2D tiled*/ |
| 665 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 712 | + reg = READL(mfc_regs->e_enc_options); | |
| 666 | 713 | reg |= (0x1 << 7); |
| 667 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 714 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 668 | 715 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
| 669 | − WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 716 | + WRITEL(0x0, mfc_regs->pixel_format); | |
| 670 | 717 | } |
| 671 | 718 | |
| 672 | 719 | /* memory structure recon. frame */ |
| 673 | 720 | /* 0: Linear, 1: 2D tiled */ |
| 674 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 721 | + reg = READL(mfc_regs->e_enc_options); | |
| 675 | 722 | reg |= (0x1 << 8); |
| 676 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 723 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 677 | 724 | |
| 678 | 725 | /* padding control & value */ |
| 679 | − WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL_V6); | |
| 726 | + WRITEL(0x0, mfc_regs->e_padding_ctrl); | |
| 680 | 727 | if (p->pad) { |
| 681 | 728 | reg = 0; |
| 682 | 729 | /** enable */ |
| @@ -687,64 +734,64 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 687 | 734 | reg |= ((p->pad_cb & 0xFF) << 8); |
| 688 | 735 | /** y value */ |
| 689 | 736 | reg |= p->pad_luma & 0xFF; |
| 690 | − WRITEL(reg, S5P_FIMV_E_PADDING_CTRL_V6); | |
| 737 | + WRITEL(reg, mfc_regs->e_padding_ctrl); | |
| 691 | 738 | } |
| 692 | 739 | |
| 693 | 740 | /* rate control config. */ |
| 694 | 741 | reg = 0; |
| 695 | 742 | /* frame-level rate control */ |
| 696 | 743 | reg |= ((p->rc_frame & 0x1) << 9); |
| 697 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 744 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 698 | 745 | |
| 699 | 746 | /* bit rate */ |
| 700 | 747 | if (p->rc_frame) |
| 701 | 748 | WRITEL(p->rc_bitrate, |
| 702 | − S5P_FIMV_E_RC_BIT_RATE_V6); | |
| 749 | + mfc_regs->e_rc_bit_rate); | |
| 703 | 750 | else |
| 704 | − WRITEL(1, S5P_FIMV_E_RC_BIT_RATE_V6); | |
| 751 | + WRITEL(1, mfc_regs->e_rc_bit_rate); | |
| 705 | 752 | |
| 706 | 753 | /* reaction coefficient */ |
| 707 | 754 | if (p->rc_frame) { |
| 708 | 755 | if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */ |
| 709 | − WRITEL(1, S5P_FIMV_E_RC_RPARAM_V6); | |
| 756 | + WRITEL(1, mfc_regs->e_rc_mode); | |
| 710 | 757 | else /* loose CBR */ |
| 711 | − WRITEL(2, S5P_FIMV_E_RC_RPARAM_V6); | |
| 758 | + WRITEL(2, mfc_regs->e_rc_mode); | |
| 712 | 759 | } |
| 713 | 760 | |
| 714 | 761 | /* seq header ctrl */ |
| 715 | − reg = READL(S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 762 | + reg = READL(mfc_regs->e_enc_options); | |
| 716 | 763 | reg &= ~(0x1 << 2); |
| 717 | 764 | reg |= ((p->seq_hdr_mode & 0x1) << 2); |
| 718 | 765 | |
| 719 | 766 | /* frame skip mode */ |
| 720 | 767 | reg &= ~(0x3); |
| 721 | 768 | reg |= (p->frame_skip_mode & 0x3); |
| 722 | − WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 769 | + WRITEL(reg, mfc_regs->e_enc_options); | |
| 723 | 770 | |
| 724 | 771 | /* 'DROP_CONTROL_ENABLE', disable */ |
| 725 | − reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | |
| 772 | + reg = READL(mfc_regs->e_rc_config); | |
| 726 | 773 | reg &= ~(0x1 << 10); |
| 727 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 774 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 728 | 775 | |
| 729 | 776 | /* setting for MV range [16, 256] */ |
| 730 | 777 | reg = (p->mv_h_range & S5P_FIMV_E_MV_RANGE_V6_MASK); |
| 731 | − WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE_V6); | |
| 778 | + WRITEL(reg, mfc_regs->e_mv_hor_range); | |
| 732 | 779 | |
| 733 | 780 | reg = (p->mv_v_range & S5P_FIMV_E_MV_RANGE_V6_MASK); |
| 734 | − WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE_V6); | |
| 781 | + WRITEL(reg, mfc_regs->e_mv_ver_range); | |
| 735 | 782 | |
| 736 | − WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION_V6); | |
| 737 | − WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); | |
| 738 | − WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE_V6); | |
| 739 | − WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL_V6); | |
| 740 | − WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG_V6); | |
| 783 | + WRITEL(0x0, mfc_regs->e_frame_insertion); | |
| 784 | + WRITEL(0x0, mfc_regs->e_roi_buffer_addr); | |
| 785 | + WRITEL(0x0, mfc_regs->e_param_change); | |
| 786 | + WRITEL(0x0, mfc_regs->e_rc_roi_ctrl); | |
| 787 | + WRITEL(0x0, mfc_regs->e_picture_tag); | |
| 741 | 788 | |
| 742 | − WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); | |
| 743 | − WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT_V6); | |
| 744 | − WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT_V6); | |
| 789 | + WRITEL(0x0, mfc_regs->e_bit_count_enable); | |
| 790 | + WRITEL(0x0, mfc_regs->e_max_bit_count); | |
| 791 | + WRITEL(0x0, mfc_regs->e_min_bit_count); | |
| 745 | 792 | |
| 746 | − WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); | |
| 747 | − WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); | |
| 793 | + WRITEL(0x0, mfc_regs->e_metadata_buffer_addr); | |
| 794 | + WRITEL(0x0, mfc_regs->e_metadata_buffer_size); | |
| 748 | 795 | |
| 749 | 796 | mfc_debug_leave(); |
| 750 | 797 | |
| @@ -754,6 +801,7 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 754 | 801 | static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) |
| 755 | 802 | { |
| 756 | 803 | struct s5p_mfc_dev *dev = ctx->dev; |
| 804 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 757 | 805 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 758 | 806 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; |
| 759 | 807 | unsigned int reg = 0; |
| @@ -764,10 +812,10 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 764 | 812 | s5p_mfc_set_enc_params(ctx); |
| 765 | 813 | |
| 766 | 814 | /* pictype : number of B */ |
| 767 | − reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | |
| 815 | + reg = READL(mfc_regs->e_gop_config); | |
| 768 | 816 | reg &= ~(0x3 << 16); |
| 769 | 817 | reg |= ((p->num_b_frame & 0x3) << 16); |
| 770 | − WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | |
| 818 | + WRITEL(reg, mfc_regs->e_gop_config); | |
| 771 | 819 | |
| 772 | 820 | /* profile & level */ |
| 773 | 821 | reg = 0; |
| @@ -775,18 +823,19 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 775 | 823 | reg |= ((p_h264->level & 0xFF) << 8); |
| 776 | 824 | /** profile - 0 ~ 3 */ |
| 777 | 825 | reg |= p_h264->profile & 0x3F; |
| 778 | − WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
| 826 | + WRITEL(reg, mfc_regs->e_picture_profile); | |
| 779 | 827 | |
| 780 | 828 | /* rate control config. */ |
| 781 | − reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | |
| 829 | + reg = READL(mfc_regs->e_rc_config); | |
| 782 | 830 | /** macroblock level rate control */ |
| 783 | 831 | reg &= ~(0x1 << 8); |
| 784 | 832 | reg |= ((p->rc_mb & 0x1) << 8); |
| 785 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 833 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 834 | + | |
| 786 | 835 | /** frame QP */ |
| 787 | 836 | reg &= ~(0x3F); |
| 788 | 837 | reg |= p_h264->rc_frame_qp & 0x3F; |
| 789 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 838 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 790 | 839 | |
| 791 | 840 | /* max & min value of QP */ |
| 792 | 841 | reg = 0; |
| @@ -794,16 +843,16 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 794 | 843 | reg |= ((p_h264->rc_max_qp & 0x3F) << 8); |
| 795 | 844 | /** min QP */ |
| 796 | 845 | reg |= p_h264->rc_min_qp & 0x3F; |
| 797 | − WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | |
| 846 | + WRITEL(reg, mfc_regs->e_rc_qp_bound); | |
| 798 | 847 | |
| 799 | 848 | /* other QPs */ |
| 800 | − WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 849 | + WRITEL(0x0, mfc_regs->e_fixed_picture_qp); | |
| 801 | 850 | if (!p->rc_frame && !p->rc_mb) { |
| 802 | 851 | reg = 0; |
| 803 | 852 | reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16); |
| 804 | 853 | reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8); |
| 805 | 854 | reg |= p_h264->rc_frame_qp & 0x3F; |
| 806 | − WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 855 | + WRITEL(reg, mfc_regs->e_fixed_picture_qp); | |
| 807 | 856 | } |
| 808 | 857 | |
| 809 | 858 | /* frame rate */ |
| @@ -811,38 +860,38 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 811 | 860 | reg = 0; |
| 812 | 861 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); |
| 813 | 862 | reg |= p->rc_framerate_denom & 0xFFFF; |
| 814 | − WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
| 863 | + WRITEL(reg, mfc_regs->e_rc_frame_rate); | |
| 815 | 864 | } |
| 816 | 865 | |
| 817 | 866 | /* vbv buffer size */ |
| 818 | 867 | if (p->frame_skip_mode == |
| 819 | 868 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { |
| 820 | 869 | WRITEL(p_h264->cpb_size & 0xFFFF, |
| 821 | − S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
| 870 | + mfc_regs->e_vbv_buffer_size); | |
| 822 | 871 | |
| 823 | 872 | if (p->rc_frame) |
| 824 | − WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
| 873 | + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); | |
| 825 | 874 | } |
| 826 | 875 | |
| 827 | 876 | /* interlace */ |
| 828 | 877 | reg = 0; |
| 829 | 878 | reg |= ((p_h264->interlace & 0x1) << 3); |
| 830 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 879 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 831 | 880 | |
| 832 | 881 | /* height */ |
| 833 | 882 | if (p_h264->interlace) { |
| 834 | 883 | WRITEL(ctx->img_height >> 1, |
| 835 | − S5P_FIMV_E_FRAME_HEIGHT_V6); /* 32 align */ | |
| 884 | + mfc_regs->e_frame_height); /* 32 align */ | |
| 836 | 885 | /* cropped height */ |
| 837 | 886 | WRITEL(ctx->img_height >> 1, |
| 838 | − S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | |
| 887 | + mfc_regs->e_cropped_frame_height); | |
| 839 | 888 | } |
| 840 | 889 | |
| 841 | 890 | /* loop filter ctrl */ |
| 842 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 891 | + reg = READL(mfc_regs->e_h264_options); | |
| 843 | 892 | reg &= ~(0x3 << 1); |
| 844 | 893 | reg |= ((p_h264->loop_filter_mode & 0x3) << 1); |
| 845 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 894 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 846 | 895 | |
| 847 | 896 | /* loopfilter alpha offset */ |
| 848 | 897 | if (p_h264->loop_filter_alpha < 0) { |
| @@ -852,7 +901,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 852 | 901 | reg = 0x00; |
| 853 | 902 | reg |= (p_h264->loop_filter_alpha & 0xF); |
| 854 | 903 | } |
| 855 | − WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); | |
| 904 | + WRITEL(reg, mfc_regs->e_h264_lf_alpha_offset); | |
| 856 | 905 | |
| 857 | 906 | /* loopfilter beta offset */ |
| 858 | 907 | if (p_h264->loop_filter_beta < 0) { |
| @@ -862,28 +911,28 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 862 | 911 | reg = 0x00; |
| 863 | 912 | reg |= (p_h264->loop_filter_beta & 0xF); |
| 864 | 913 | } |
| 865 | − WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); | |
| 914 | + WRITEL(reg, mfc_regs->e_h264_lf_beta_offset); | |
| 866 | 915 | |
| 867 | 916 | /* entropy coding mode */ |
| 868 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 917 | + reg = READL(mfc_regs->e_h264_options); | |
| 869 | 918 | reg &= ~(0x1); |
| 870 | 919 | reg |= p_h264->entropy_mode & 0x1; |
| 871 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 920 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 872 | 921 | |
| 873 | 922 | /* number of ref. picture */ |
| 874 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 923 | + reg = READL(mfc_regs->e_h264_options); | |
| 875 | 924 | reg &= ~(0x1 << 7); |
| 876 | 925 | reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7); |
| 877 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 926 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 878 | 927 | |
| 879 | 928 | /* 8x8 transform enable */ |
| 880 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 929 | + reg = READL(mfc_regs->e_h264_options); | |
| 881 | 930 | reg &= ~(0x3 << 12); |
| 882 | 931 | reg |= ((p_h264->_8x8_transform & 0x3) << 12); |
| 883 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 932 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 884 | 933 | |
| 885 | 934 | /* macroblock adaptive scaling features */ |
| 886 | − WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG_V6); | |
| 935 | + WRITEL(0x0, mfc_regs->e_mb_rc_config); | |
| 887 | 936 | if (p->rc_mb) { |
| 888 | 937 | reg = 0; |
| 889 | 938 | /** dark region */ |
| @@ -894,92 +943,95 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 894 | 943 | reg |= ((p_h264->rc_mb_static & 0x1) << 1); |
| 895 | 944 | /** high activity region */ |
| 896 | 945 | reg |= p_h264->rc_mb_activity & 0x1; |
| 897 | − WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG_V6); | |
| 946 | + WRITEL(reg, mfc_regs->e_mb_rc_config); | |
| 898 | 947 | } |
| 899 | 948 | |
| 900 | 949 | /* aspect ratio VUI */ |
| 901 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 950 | + READL(mfc_regs->e_h264_options); | |
| 902 | 951 | reg &= ~(0x1 << 5); |
| 903 | 952 | reg |= ((p_h264->vui_sar & 0x1) << 5); |
| 904 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 953 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 905 | 954 | |
| 906 | − WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO_V6); | |
| 907 | − WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR_V6); | |
| 955 | + WRITEL(0x0, mfc_regs->e_aspect_ratio); | |
| 956 | + WRITEL(0x0, mfc_regs->e_extended_sar); | |
| 908 | 957 | if (p_h264->vui_sar) { |
| 909 | 958 | /* aspect ration IDC */ |
| 910 | 959 | reg = 0; |
| 911 | 960 | reg |= p_h264->vui_sar_idc & 0xFF; |
| 912 | − WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO_V6); | |
| 961 | + WRITEL(reg, mfc_regs->e_aspect_ratio); | |
| 913 | 962 | if (p_h264->vui_sar_idc == 0xFF) { |
| 914 | 963 | /* extended SAR */ |
| 915 | 964 | reg = 0; |
| 916 | 965 | reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16; |
| 917 | 966 | reg |= p_h264->vui_ext_sar_height & 0xFFFF; |
| 918 | − WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR_V6); | |
| 967 | + WRITEL(reg, mfc_regs->e_extended_sar); | |
| 919 | 968 | } |
| 920 | 969 | } |
| 921 | 970 | |
| 922 | 971 | /* intra picture period for H.264 open GOP */ |
| 923 | 972 | /* control */ |
| 924 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 973 | + READL(mfc_regs->e_h264_options); | |
| 925 | 974 | reg &= ~(0x1 << 4); |
| 926 | 975 | reg |= ((p_h264->open_gop & 0x1) << 4); |
| 927 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 976 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 977 | + | |
| 928 | 978 | /* value */ |
| 929 | − WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD_V6); | |
| 979 | + WRITEL(0x0, mfc_regs->e_h264_i_period); | |
| 930 | 980 | if (p_h264->open_gop) { |
| 931 | 981 | reg = 0; |
| 932 | 982 | reg |= p_h264->open_gop_size & 0xFFFF; |
| 933 | − WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD_V6); | |
| 983 | + WRITEL(reg, mfc_regs->e_h264_i_period); | |
| 934 | 984 | } |
| 935 | 985 | |
| 936 | 986 | /* 'WEIGHTED_BI_PREDICTION' for B is disable */ |
| 937 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 987 | + READL(mfc_regs->e_h264_options); | |
| 938 | 988 | reg &= ~(0x3 << 9); |
| 939 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 989 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 940 | 990 | |
| 941 | 991 | /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */ |
| 942 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 992 | + READL(mfc_regs->e_h264_options); | |
| 943 | 993 | reg &= ~(0x1 << 14); |
| 944 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 994 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 945 | 995 | |
| 946 | 996 | /* ASO */ |
| 947 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 997 | + READL(mfc_regs->e_h264_options); | |
| 948 | 998 | reg &= ~(0x1 << 6); |
| 949 | 999 | reg |= ((p_h264->aso & 0x1) << 6); |
| 950 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 1000 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 951 | 1001 | |
| 952 | 1002 | /* hier qp enable */ |
| 953 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 1003 | + READL(mfc_regs->e_h264_options); | |
| 954 | 1004 | reg &= ~(0x1 << 8); |
| 955 | 1005 | reg |= ((p_h264->open_gop & 0x1) << 8); |
| 956 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 1006 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 957 | 1007 | reg = 0; |
| 958 | 1008 | if (p_h264->hier_qp && p_h264->hier_qp_layer) { |
| 959 | 1009 | reg |= (p_h264->hier_qp_type & 0x1) << 0x3; |
| 960 | 1010 | reg |= p_h264->hier_qp_layer & 0x7; |
| 961 | − WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | |
| 1011 | + WRITEL(reg, mfc_regs->e_h264_num_t_layer); | |
| 962 | 1012 | /* QP value for each layer */ |
| 963 | − for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++) | |
| 1013 | + for (i = 0; i < p_h264->hier_qp_layer && | |
| 1014 | + i < ARRAY_SIZE(p_h264->hier_qp_layer_qp); i++) { | |
| 964 | 1015 | WRITEL(p_h264->hier_qp_layer_qp[i], |
| 965 | − S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6 + | |
| 966 | − i * 4); | |
| 1016 | + mfc_regs->e_h264_hierarchical_qp_layer0 | |
| 1017 | + + i * 4); | |
| 1018 | + } | |
| 967 | 1019 | } |
| 968 | 1020 | /* number of coding layer should be zero when hierarchical is disable */ |
| 969 | − WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | |
| 1021 | + WRITEL(reg, mfc_regs->e_h264_num_t_layer); | |
| 970 | 1022 | |
| 971 | 1023 | /* frame packing SEI generation */ |
| 972 | − reg = READL(S5P_FIMV_E_H264_OPTIONS_V6); | |
| 1024 | + READL(mfc_regs->e_h264_options); | |
| 973 | 1025 | reg &= ~(0x1 << 25); |
| 974 | 1026 | reg |= ((p_h264->sei_frame_packing & 0x1) << 25); |
| 975 | − WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 1027 | + WRITEL(reg, mfc_regs->e_h264_options); | |
| 976 | 1028 | if (p_h264->sei_frame_packing) { |
| 977 | 1029 | reg = 0; |
| 978 | 1030 | /** current frame0 flag */ |
| 979 | 1031 | reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2); |
| 980 | 1032 | /** arrangement type */ |
| 981 | 1033 | reg |= p_h264->sei_fp_arrangement_type & 0x3; |
| 982 | − WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6); | |
| 1034 | + WRITEL(reg, mfc_regs->e_h264_frame_packing_sei_info); | |
| 983 | 1035 | } |
| 984 | 1036 | |
| 985 | 1037 | if (p_h264->fmo) { |
| @@ -989,8 +1041,8 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 989 | 1041 | p_h264->fmo_slice_grp = 4; |
| 990 | 1042 | for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++) |
| 991 | 1043 | WRITEL(p_h264->fmo_run_len[i] - 1, |
| 992 | − S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6 + | |
| 993 | − i * 4); | |
| 1044 | + mfc_regs->e_h264_fmo_run_length_minus1_0 | |
| 1045 | + + i * 4); | |
| 994 | 1046 | break; |
| 995 | 1047 | case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES: |
| 996 | 1048 | if (p_h264->fmo_slice_grp > 4) |
| @@ -1001,10 +1053,10 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1001 | 1053 | if (p_h264->fmo_slice_grp > 2) |
| 1002 | 1054 | p_h264->fmo_slice_grp = 2; |
| 1003 | 1055 | WRITEL(p_h264->fmo_chg_dir & 0x1, |
| 1004 | − S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6); | |
| 1056 | + mfc_regs->e_h264_fmo_slice_grp_change_dir); | |
| 1005 | 1057 | /* the valid range is 0 ~ number of macroblocks -1 */ |
| 1006 | 1058 | WRITEL(p_h264->fmo_chg_rate, |
| 1007 | − S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6); | |
| 1059 | + mfc_regs->e_h264_fmo_slice_grp_change_rate_minus1); | |
| 1008 | 1060 | break; |
| 1009 | 1061 | default: |
| 1010 | 1062 | mfc_err("Unsupported map type for FMO: %d\n", |
| @@ -1015,11 +1067,11 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1015 | 1067 | } |
| 1016 | 1068 | |
| 1017 | 1069 | WRITEL(p_h264->fmo_map_type, |
| 1018 | − S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); | |
| 1070 | + mfc_regs->e_h264_fmo_slice_grp_map_type); | |
| 1019 | 1071 | WRITEL(p_h264->fmo_slice_grp - 1, |
| 1020 | − S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | |
| 1072 | + mfc_regs->e_h264_fmo_num_slice_grp_minus1); | |
| 1021 | 1073 | } else { |
| 1022 | − WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | |
| 1074 | + WRITEL(0, mfc_regs->e_h264_fmo_num_slice_grp_minus1); | |
| 1023 | 1075 | } |
| 1024 | 1076 | |
| 1025 | 1077 | mfc_debug_leave(); |
| @@ -1030,6 +1082,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1030 | 1082 | static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) |
| 1031 | 1083 | { |
| 1032 | 1084 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1085 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1033 | 1086 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 1034 | 1087 | struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4; |
| 1035 | 1088 | unsigned int reg = 0; |
| @@ -1039,10 +1092,10 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 1039 | 1092 | s5p_mfc_set_enc_params(ctx); |
| 1040 | 1093 | |
| 1041 | 1094 | /* pictype : number of B */ |
| 1042 | − reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | |
| 1095 | + reg = READL(mfc_regs->e_gop_config); | |
| 1043 | 1096 | reg &= ~(0x3 << 16); |
| 1044 | 1097 | reg |= ((p->num_b_frame & 0x3) << 16); |
| 1045 | − WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | |
| 1098 | + WRITEL(reg, mfc_regs->e_gop_config); | |
| 1046 | 1099 | |
| 1047 | 1100 | /* profile & level */ |
| 1048 | 1101 | reg = 0; |
| @@ -1050,18 +1103,19 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1050 | 1103 | reg |= ((p_mpeg4->level & 0xFF) << 8); |
| 1051 | 1104 | /** profile - 0 ~ 1 */ |
| 1052 | 1105 | reg |= p_mpeg4->profile & 0x3F; |
| 1053 | − WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
| 1106 | + WRITEL(reg, mfc_regs->e_picture_profile); | |
| 1054 | 1107 | |
| 1055 | 1108 | /* rate control config. */ |
| 1056 | − reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | |
| 1109 | + reg = READL(mfc_regs->e_rc_config); | |
| 1057 | 1110 | /** macroblock level rate control */ |
| 1058 | 1111 | reg &= ~(0x1 << 8); |
| 1059 | 1112 | reg |= ((p->rc_mb & 0x1) << 8); |
| 1060 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1113 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1114 | + | |
| 1061 | 1115 | /** frame QP */ |
| 1062 | 1116 | reg &= ~(0x3F); |
| 1063 | 1117 | reg |= p_mpeg4->rc_frame_qp & 0x3F; |
| 1064 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1118 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1065 | 1119 | |
| 1066 | 1120 | /* max & min value of QP */ |
| 1067 | 1121 | reg = 0; |
| @@ -1069,16 +1123,16 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1069 | 1123 | reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8); |
| 1070 | 1124 | /** min QP */ |
| 1071 | 1125 | reg |= p_mpeg4->rc_min_qp & 0x3F; |
| 1072 | − WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | |
| 1126 | + WRITEL(reg, mfc_regs->e_rc_qp_bound); | |
| 1073 | 1127 | |
| 1074 | 1128 | /* other QPs */ |
| 1075 | − WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1129 | + WRITEL(0x0, mfc_regs->e_fixed_picture_qp); | |
| 1076 | 1130 | if (!p->rc_frame && !p->rc_mb) { |
| 1077 | 1131 | reg = 0; |
| 1078 | 1132 | reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16); |
| 1079 | 1133 | reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8); |
| 1080 | 1134 | reg |= p_mpeg4->rc_frame_qp & 0x3F; |
| 1081 | − WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1135 | + WRITEL(reg, mfc_regs->e_fixed_picture_qp); | |
| 1082 | 1136 | } |
| 1083 | 1137 | |
| 1084 | 1138 | /* frame rate */ |
| @@ -1086,21 +1140,21 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1086 | 1140 | reg = 0; |
| 1087 | 1141 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); |
| 1088 | 1142 | reg |= p->rc_framerate_denom & 0xFFFF; |
| 1089 | − WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
| 1143 | + WRITEL(reg, mfc_regs->e_rc_frame_rate); | |
| 1090 | 1144 | } |
| 1091 | 1145 | |
| 1092 | 1146 | /* vbv buffer size */ |
| 1093 | 1147 | if (p->frame_skip_mode == |
| 1094 | 1148 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { |
| 1095 | − WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
| 1149 | + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); | |
| 1096 | 1150 | |
| 1097 | 1151 | if (p->rc_frame) |
| 1098 | − WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
| 1152 | + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); | |
| 1099 | 1153 | } |
| 1100 | 1154 | |
| 1101 | 1155 | /* Disable HEC */ |
| 1102 | − WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS_V6); | |
| 1103 | − WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); | |
| 1156 | + WRITEL(0x0, mfc_regs->e_mpeg4_options); | |
| 1157 | + WRITEL(0x0, mfc_regs->e_mpeg4_hec_period); | |
| 1104 | 1158 | |
| 1105 | 1159 | mfc_debug_leave(); |
| 1106 | 1160 | |
| @@ -1110,6 +1164,7 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 1110 | 1164 | static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) |
| 1111 | 1165 | { |
| 1112 | 1166 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1167 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1113 | 1168 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 1114 | 1169 | struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4; |
| 1115 | 1170 | unsigned int reg = 0; |
| @@ -1122,18 +1177,19 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) · 6 unmodified lines | ||
| 1122 | 1177 | reg = 0; |
| 1123 | 1178 | /** profile */ |
| 1124 | 1179 | reg |= (0x1 << 4); |
| 1125 | − WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
| 1180 | + WRITEL(reg, mfc_regs->e_picture_profile); | |
| 1126 | 1181 | |
| 1127 | 1182 | /* rate control config. */ |
| 1128 | − reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | |
| 1183 | + reg = READL(mfc_regs->e_rc_config); | |
| 1129 | 1184 | /** macroblock level rate control */ |
| 1130 | 1185 | reg &= ~(0x1 << 8); |
| 1131 | 1186 | reg |= ((p->rc_mb & 0x1) << 8); |
| 1132 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1187 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1188 | + | |
| 1133 | 1189 | /** frame QP */ |
| 1134 | 1190 | reg &= ~(0x3F); |
| 1135 | 1191 | reg |= p_h263->rc_frame_qp & 0x3F; |
| 1136 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1192 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1137 | 1193 | |
| 1138 | 1194 | /* max & min value of QP */ |
| 1139 | 1195 | reg = 0; |
| @@ -1141,16 +1197,16 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1141 | 1197 | reg |= ((p_h263->rc_max_qp & 0x3F) << 8); |
| 1142 | 1198 | /** min QP */ |
| 1143 | 1199 | reg |= p_h263->rc_min_qp & 0x3F; |
| 1144 | − WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | |
| 1200 | + WRITEL(reg, mfc_regs->e_rc_qp_bound); | |
| 1145 | 1201 | |
| 1146 | 1202 | /* other QPs */ |
| 1147 | − WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1203 | + WRITEL(0x0, mfc_regs->e_fixed_picture_qp); | |
| 1148 | 1204 | if (!p->rc_frame && !p->rc_mb) { |
| 1149 | 1205 | reg = 0; |
| 1150 | 1206 | reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16); |
| 1151 | 1207 | reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8); |
| 1152 | 1208 | reg |= p_h263->rc_frame_qp & 0x3F; |
| 1153 | − WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1209 | + WRITEL(reg, mfc_regs->e_fixed_picture_qp); | |
| 1154 | 1210 | } |
| 1155 | 1211 | |
| 1156 | 1212 | /* frame rate */ |
| @@ -1158,16 +1214,16 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1158 | 1214 | reg = 0; |
| 1159 | 1215 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); |
| 1160 | 1216 | reg |= p->rc_framerate_denom & 0xFFFF; |
| 1161 | − WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
| 1217 | + WRITEL(reg, mfc_regs->e_rc_frame_rate); | |
| 1162 | 1218 | } |
| 1163 | 1219 | |
| 1164 | 1220 | /* vbv buffer size */ |
| 1165 | 1221 | if (p->frame_skip_mode == |
| 1166 | 1222 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { |
| 1167 | − WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
| 1223 | + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); | |
| 1168 | 1224 | |
| 1169 | 1225 | if (p->rc_frame) |
| 1170 | − WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
| 1226 | + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); | |
| 1171 | 1227 | } |
| 1172 | 1228 | |
| 1173 | 1229 | mfc_debug_leave(); |
| @@ -1178,6 +1234,7 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1178 | 1234 | static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) |
| 1179 | 1235 | { |
| 1180 | 1236 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1237 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1181 | 1238 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 1182 | 1239 | struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8; |
| 1183 | 1240 | unsigned int reg = 0; |
| @@ -1188,57 +1245,57 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1188 | 1245 | s5p_mfc_set_enc_params(ctx); |
| 1189 | 1246 | |
| 1190 | 1247 | /* pictype : number of B */ |
| 1191 | − reg = READL(S5P_FIMV_E_GOP_CONFIG_V6); | |
| 1248 | + reg = READL(mfc_regs->e_gop_config); | |
| 1192 | 1249 | reg &= ~(0x3 << 16); |
| 1193 | 1250 | reg |= ((p->num_b_frame & 0x3) << 16); |
| 1194 | − WRITEL(reg, S5P_FIMV_E_GOP_CONFIG_V6); | |
| 1251 | + WRITEL(reg, mfc_regs->e_gop_config); | |
| 1195 | 1252 | |
| 1196 | 1253 | /* profile - 0 ~ 3 */ |
| 1197 | 1254 | reg = p_vp8->profile & 0x3; |
| 1198 | − WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
| 1255 | + WRITEL(reg, mfc_regs->e_picture_profile); | |
| 1199 | 1256 | |
| 1200 | 1257 | /* rate control config. */ |
| 1201 | − reg = READL(S5P_FIMV_E_RC_CONFIG_V6); | |
| 1258 | + reg = READL(mfc_regs->e_rc_config); | |
| 1202 | 1259 | /** macroblock level rate control */ |
| 1203 | 1260 | reg &= ~(0x1 << 8); |
| 1204 | 1261 | reg |= ((p->rc_mb & 0x1) << 8); |
| 1205 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1262 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1206 | 1263 | |
| 1207 | 1264 | /* frame rate */ |
| 1208 | 1265 | if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) { |
| 1209 | 1266 | reg = 0; |
| 1210 | 1267 | reg |= ((p->rc_framerate_num & 0xFFFF) << 16); |
| 1211 | 1268 | reg |= p->rc_framerate_denom & 0xFFFF; |
| 1212 | − WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
| 1269 | + WRITEL(reg, mfc_regs->e_rc_frame_rate); | |
| 1213 | 1270 | } |
| 1214 | 1271 | |
| 1215 | 1272 | /* frame QP */ |
| 1216 | 1273 | reg &= ~(0x7F); |
| 1217 | 1274 | reg |= p_vp8->rc_frame_qp & 0x7F; |
| 1218 | − WRITEL(reg, S5P_FIMV_E_RC_CONFIG_V6); | |
| 1275 | + WRITEL(reg, mfc_regs->e_rc_config); | |
| 1219 | 1276 | |
| 1220 | 1277 | /* other QPs */ |
| 1221 | − WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1278 | + WRITEL(0x0, mfc_regs->e_fixed_picture_qp); | |
| 1222 | 1279 | if (!p->rc_frame && !p->rc_mb) { |
| 1223 | 1280 | reg = 0; |
| 1224 | 1281 | reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8); |
| 1225 | 1282 | reg |= p_vp8->rc_frame_qp & 0x7F; |
| 1226 | − WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 1283 | + WRITEL(reg, mfc_regs->e_fixed_picture_qp); | |
| 1227 | 1284 | } |
| 1228 | 1285 | |
| 1229 | 1286 | /* max QP */ |
| 1230 | 1287 | reg = ((p_vp8->rc_max_qp & 0x7F) << 8); |
| 1231 | 1288 | /* min QP */ |
| 1232 | 1289 | reg |= p_vp8->rc_min_qp & 0x7F; |
| 1233 | − WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_V6); | |
| 1290 | + WRITEL(reg, mfc_regs->e_rc_qp_bound); | |
| 1234 | 1291 | |
| 1235 | 1292 | /* vbv buffer size */ |
| 1236 | 1293 | if (p->frame_skip_mode == |
| 1237 | 1294 | V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) { |
| 1238 | − WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
| 1295 | + WRITEL(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size); | |
| 1239 | 1296 | |
| 1240 | 1297 | if (p->rc_frame) |
| 1241 | − WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
| 1298 | + WRITEL(p->vbv_delay, mfc_regs->e_vbv_init_delay); | |
| 1242 | 1299 | } |
| 1243 | 1300 | |
| 1244 | 1301 | /* VP8 specific params */ |
| @@ -1260,7 +1317,7 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) · 15 unmodified lines | ||
| 1260 | 1317 | } |
| 1261 | 1318 | reg |= (val & 0xF) << 3; |
| 1262 | 1319 | reg |= (p_vp8->num_ref & 0x2); |
| 1263 | − WRITEL(reg, S5P_FIMV_E_VP8_OPTIONS_V7); | |
| 1320 | + WRITEL(reg, mfc_regs->e_vp8_options); | |
| 1264 | 1321 | |
| 1265 | 1322 | mfc_debug_leave(); |
| 1266 | 1323 | |
| @@ -1271,6 +1328,7 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1271 | 1328 | static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) |
| 1272 | 1329 | { |
| 1273 | 1330 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1331 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1274 | 1332 | unsigned int reg = 0; |
| 1275 | 1333 | int fmo_aso_ctrl = 0; |
| 1276 | 1334 | |
| @@ -1278,9 +1336,9 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) · 1 unmodified line | ||
| 1278 | 1336 | mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, |
| 1279 | 1337 | S5P_FIMV_CH_SEQ_HEADER_V6); |
| 1280 | 1338 | mfc_debug(2, "BUFs: %08x %08x %08x\n", |
| 1281 | − READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), | |
| 1282 | − READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6), | |
| 1283 | − READL(S5P_FIMV_D_CPB_BUFFER_ADDR_V6)); | |
| 1339 | + READL(mfc_regs->d_cpb_buffer_addr), | |
| 1340 | + READL(mfc_regs->d_cpb_buffer_addr), | |
| 1341 | + READL(mfc_regs->d_cpb_buffer_addr)); | |
| 1284 | 1342 | |
| 1285 | 1343 | /* FMO_ASO_CTRL - 0: Enable, 1: Disable */ |
| 1286 | 1344 | reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6); |
| @@ -1291,11 +1349,11 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1291 | 1349 | * set to negative value. */ |
| 1292 | 1350 | if (ctx->display_delay >= 0) { |
| 1293 | 1351 | reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6); |
| 1294 | − WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | |
| 1352 | + WRITEL(ctx->display_delay, mfc_regs->d_display_delay); | |
| 1295 | 1353 | } |
| 1296 | 1354 | |
| 1297 | − if (IS_MFCV7(dev)) { | |
| 1298 | − WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | |
| 1355 | + if (IS_MFCV7_PLUS(dev)) { | |
| 1356 | + WRITEL(reg, mfc_regs->d_dec_options); | |
| 1299 | 1357 | reg = 0; |
| 1300 | 1358 | } |
| 1301 | 1359 | |
| @@ -1309,22 +1367,22 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) · 7 unmodified lines | ||
| 1309 | 1367 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) |
| 1310 | 1368 | reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6); |
| 1311 | 1369 | |
| 1312 | − if (IS_MFCV7(dev)) | |
| 1313 | − WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7); | |
| 1370 | + if (IS_MFCV7_PLUS(dev)) | |
| 1371 | + WRITEL(reg, mfc_regs->d_init_buffer_options); | |
| 1314 | 1372 | else |
| 1315 | − WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6); | |
| 1373 | + WRITEL(reg, mfc_regs->d_dec_options); | |
| 1316 | 1374 | |
| 1317 | 1375 | /* 0: NV12(CbCr), 1: NV21(CrCb) */ |
| 1318 | 1376 | if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M) |
| 1319 | − WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 1377 | + WRITEL(0x1, mfc_regs->pixel_format); | |
| 1320 | 1378 | else |
| 1321 | − WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 1379 | + WRITEL(0x0, mfc_regs->pixel_format); | |
| 1322 | 1380 | |
| 1323 | 1381 | |
| 1324 | 1382 | /* sei parse */ |
| 1325 | − WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE_V6); | |
| 1383 | + WRITEL(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable); | |
| 1326 | 1384 | |
| 1327 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 1385 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 1328 | 1386 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 1329 | 1387 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); |
| 1330 | 1388 | |
| @@ -1335,11 +1393,12 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1335 | 1393 | static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) |
| 1336 | 1394 | { |
| 1337 | 1395 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1396 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1338 | 1397 | |
| 1339 | 1398 | if (flush) { |
| 1340 | 1399 | dev->curr_ctx = ctx->num; |
| 1341 | 1400 | s5p_mfc_clean_ctx_int_flags(ctx); |
| 1342 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 1401 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 1343 | 1402 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 1344 | 1403 | S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); |
| 1345 | 1404 | } |
| @@ -1350,11 +1409,12 @@ static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, · 4 unmodified lines | ||
| 1350 | 1409 | enum s5p_mfc_decode_arg last_frame) |
| 1351 | 1410 | { |
| 1352 | 1411 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1412 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1353 | 1413 | |
| 1354 | − WRITEL(ctx->dec_dst_flag, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); | |
| 1355 | − WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE_V6); | |
| 1414 | + WRITEL(ctx->dec_dst_flag, mfc_regs->d_available_dpb_flag_lower); | |
| 1415 | + WRITEL(ctx->slice_interface & 0x1, mfc_regs->d_slice_if_enable); | |
| 1356 | 1416 | |
| 1357 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 1417 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 1358 | 1418 | /* Issue different commands to instance basing on whether it |
| 1359 | 1419 | * is the last frame or not. */ |
| 1360 | 1420 | switch (last_frame) { |
| @@ -1378,6 +1438,7 @@ static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx, · 17 unmodified lines | ||
| 1378 | 1438 | static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) |
| 1379 | 1439 | { |
| 1380 | 1440 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1441 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1381 | 1442 | |
| 1382 | 1443 | if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) |
| 1383 | 1444 | s5p_mfc_set_enc_params_h264(ctx); |
| @@ -1393,13 +1454,13 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) · 9 unmodified lines | ||
| 1393 | 1454 | return -EINVAL; |
| 1394 | 1455 | } |
| 1395 | 1456 | |
| 1396 | − /* Set stride lengths */ | |
| 1397 | − if (IS_MFCV7(dev)) { | |
| 1398 | − WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); | |
| 1399 | − WRITEL(ctx->img_width, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); | |
| 1457 | + /* Set stride lengths for v7 & above */ | |
| 1458 | + if (IS_MFCV7_PLUS(dev)) { | |
| 1459 | + WRITEL(ctx->img_width, mfc_regs->e_source_first_plane_stride); | |
| 1460 | + WRITEL(ctx->img_width, mfc_regs->e_source_second_plane_stride); | |
| 1400 | 1461 | } |
| 1401 | 1462 | |
| 1402 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 1463 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 1403 | 1464 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 1404 | 1465 | S5P_FIMV_CH_SEQ_HEADER_V6, NULL); |
| 1405 | 1466 | |
| @@ -1409,14 +1470,16 @@ static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx) · 3 unmodified lines | ||
| 1409 | 1470 | static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) |
| 1410 | 1471 | { |
| 1411 | 1472 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1473 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1412 | 1474 | struct s5p_mfc_enc_params *p = &ctx->enc_params; |
| 1413 | 1475 | struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264; |
| 1414 | 1476 | int i; |
| 1415 | 1477 | |
| 1416 | 1478 | if (p_h264->aso) { |
| 1417 | − for (i = 0; i < 8; i++) | |
| 1479 | + for (i = 0; i < ARRAY_SIZE(p_h264->aso_slice_order); i++) { | |
| 1418 | 1480 | WRITEL(p_h264->aso_slice_order[i], |
| 1419 | − S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6 + i * 4); | |
| 1481 | + mfc_regs->e_h264_aso_slice_order_0 + i * 4); | |
| 1482 | + } | |
| 1420 | 1483 | } |
| 1421 | 1484 | return 0; |
| 1422 | 1485 | } |
| @@ -1425,6 +1488,7 @@ static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx) · 2 unmodified lines | ||
| 1425 | 1488 | static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) |
| 1426 | 1489 | { |
| 1427 | 1490 | struct s5p_mfc_dev *dev = ctx->dev; |
| 1491 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1428 | 1492 | |
| 1429 | 1493 | mfc_debug(2, "++\n"); |
| 1430 | 1494 | |
| @@ -1435,7 +1499,7 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx) · 4 unmodified lines | ||
| 1435 | 1499 | |
| 1436 | 1500 | s5p_mfc_set_slice_mode(ctx); |
| 1437 | 1501 | |
| 1438 | − WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6); | |
| 1502 | + WRITEL(ctx->inst_no, mfc_regs->instance_id); | |
| 1439 | 1503 | s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, |
| 1440 | 1504 | S5P_FIMV_CH_FRAME_START_V6, NULL); |
| 1441 | 1505 | |
| @@ -1810,28 +1874,26 @@ static void s5p_mfc_cleanup_queue_v6(struct list_head *lh, struct vb2_queue *vq) · 368 unmodified lines | ||
| 1810 | 1874 | |
| 1811 | 1875 | static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev) |
| 1812 | 1876 | { |
| 1813 | − mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6); | |
| 1814 | − mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT_V6); | |
| 1877 | + const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs; | |
| 1878 | + WRITEL(0, mfc_regs->risc2host_command); | |
| 1879 | + WRITEL(0, mfc_regs->risc2host_int); | |
| 1815 | 1880 | } |
| 1816 | 1881 | |
| 1817 | 1882 | static void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data, |
| 1818 | 1883 | unsigned int ofs) |
| 1819 | 1884 | { |
| 1820 | − struct s5p_mfc_dev *dev = ctx->dev; | |
| 1821 | − | |
| 1822 | 1885 | s5p_mfc_clock_on(); |
| 1823 | − WRITEL(data, ofs); | |
| 1886 | + WRITEL(data, (void *)ofs); | |
| 1824 | 1887 | s5p_mfc_clock_off(); |
| 1825 | 1888 | } |
| 1826 | 1889 | |
| 1827 | 1890 | static unsigned int |
| 1828 | 1891 | s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) |
| 1829 | 1892 | { |
| 1830 | − struct s5p_mfc_dev *dev = ctx->dev; | |
| 1831 | 1893 | int ret; |
| 1832 | 1894 | |
| 1833 | 1895 | s5p_mfc_clock_on(); |
| 1834 | − ret = READL(ofs); | |
| 1896 | + ret = READL((void *)ofs); | |
| 1835 | 1897 | s5p_mfc_clock_off(); |
| 1836 | 1898 | |
| 1837 | 1899 | return ret; |
| @@ -1839,50 +1901,51 @@ s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs) · 1 unmodified line | ||
| 1839 | 1901 | |
| 1840 | 1902 | static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev) |
| 1841 | 1903 | { |
| 1842 | − return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); | |
| 1904 | + return READL(dev->mfc_regs->d_display_first_plane_addr); | |
| 1843 | 1905 | } |
| 1844 | 1906 | |
| 1845 | 1907 | static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev) |
| 1846 | 1908 | { |
| 1847 | − return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); | |
| 1909 | + return READL(dev->mfc_regs->d_decoded_first_plane_addr); | |
| 1848 | 1910 | } |
| 1849 | 1911 | |
| 1850 | 1912 | static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev) |
| 1851 | 1913 | { |
| 1852 | − return mfc_read(dev, S5P_FIMV_D_DISPLAY_STATUS_V6); | |
| 1914 | + return READL(dev->mfc_regs->d_display_status); | |
| 1853 | 1915 | } |
| 1854 | 1916 | |
| 1855 | 1917 | static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev) |
| 1856 | 1918 | { |
| 1857 | − return mfc_read(dev, S5P_FIMV_D_DECODED_STATUS_V6); | |
| 1919 | + return READL(dev->mfc_regs->d_decoded_status); | |
| 1858 | 1920 | } |
| 1859 | 1921 | |
| 1860 | 1922 | static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev) |
| 1861 | 1923 | { |
| 1862 | − return mfc_read(dev, S5P_FIMV_D_DECODED_FRAME_TYPE_V6) & | |
| 1924 | + return READL(dev->mfc_regs->d_decoded_frame_type) & | |
| 1863 | 1925 | S5P_FIMV_DECODE_FRAME_MASK_V6; |
| 1864 | 1926 | } |
| 1865 | 1927 | |
| 1866 | 1928 | static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx) |
| 1867 | 1929 | { |
| 1868 | − return mfc_read(ctx->dev, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6) & | |
| 1930 | + struct s5p_mfc_dev *dev = ctx->dev; | |
| 1931 | + return READL(dev->mfc_regs->d_display_frame_type) & | |
| 1869 | 1932 | S5P_FIMV_DECODE_FRAME_MASK_V6; |
| 1870 | 1933 | } |
| 1871 | 1934 | |
| 1872 | 1935 | static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev) |
| 1873 | 1936 | { |
| 1874 | − return mfc_read(dev, S5P_FIMV_D_DECODED_NAL_SIZE_V6); | |
| 1937 | + return READL(dev->mfc_regs->d_decoded_nal_size); | |
| 1875 | 1938 | } |
| 1876 | 1939 | |
| 1877 | 1940 | static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev) |
| 1878 | 1941 | { |
| 1879 | − return mfc_read(dev, S5P_FIMV_RISC2HOST_CMD_V6) & | |
| 1942 | + return READL(dev->mfc_regs->risc2host_command) & | |
| 1880 | 1943 | S5P_FIMV_RISC2HOST_CMD_MASK; |
| 1881 | 1944 | } |
| 1882 | 1945 | |
| 1883 | 1946 | static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev) |
| 1884 | 1947 | { |
| 1885 | − return mfc_read(dev, S5P_FIMV_ERROR_CODE_V6); | |
| 1948 | + return READL(dev->mfc_regs->error_code); | |
| 1886 | 1949 | } |
| 1887 | 1950 | |
| 1888 | 1951 | static int s5p_mfc_err_dec_v6(unsigned int err) |
| @@ -1897,82 +1960,323 @@ static int s5p_mfc_err_dspl_v6(unsigned int err) · 8 unmodified lines | ||
| 1897 | 1960 | |
| 1898 | 1961 | static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev) |
| 1899 | 1962 | { |
| 1900 | − return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); | |
| 1963 | + return READL(dev->mfc_regs->d_display_frame_width); | |
| 1901 | 1964 | } |
| 1902 | 1965 | |
| 1903 | 1966 | static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev) |
| 1904 | 1967 | { |
| 1905 | − return mfc_read(dev, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); | |
| 1968 | + return READL(dev->mfc_regs->d_display_frame_height); | |
| 1906 | 1969 | } |
| 1907 | 1970 | |
| 1908 | 1971 | static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev) |
| 1909 | 1972 | { |
| 1910 | − return mfc_read(dev, S5P_FIMV_D_MIN_NUM_DPB_V6); | |
| 1973 | + return READL(dev->mfc_regs->d_min_num_dpb); | |
| 1911 | 1974 | } |
| 1912 | 1975 | |
| 1913 | 1976 | static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev) |
| 1914 | 1977 | { |
| 1915 | − return mfc_read(dev, S5P_FIMV_D_MIN_NUM_MV_V6); | |
| 1978 | + return READL(dev->mfc_regs->d_min_num_mv); | |
| 1916 | 1979 | } |
| 1917 | 1980 | |
| 1918 | 1981 | static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev) |
| 1919 | 1982 | { |
| 1920 | − return mfc_read(dev, S5P_FIMV_RET_INSTANCE_ID_V6); | |
| 1983 | + return READL(dev->mfc_regs->ret_instance_id); | |
| 1921 | 1984 | } |
| 1922 | 1985 | |
| 1923 | 1986 | static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev) |
| 1924 | 1987 | { |
| 1925 | − return mfc_read(dev, S5P_FIMV_E_NUM_DPB_V6); | |
| 1988 | + return READL(dev->mfc_regs->e_num_dpb); | |
| 1926 | 1989 | } |
| 1927 | 1990 | |
| 1928 | 1991 | static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev) |
| 1929 | 1992 | { |
| 1930 | − return mfc_read(dev, S5P_FIMV_E_STREAM_SIZE_V6); | |
| 1993 | + return READL(dev->mfc_regs->e_stream_size); | |
| 1931 | 1994 | } |
| 1932 | 1995 | |
| 1933 | 1996 | static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev) |
| 1934 | 1997 | { |
| 1935 | − return mfc_read(dev, S5P_FIMV_E_SLICE_TYPE_V6); | |
| 1998 | + return READL(dev->mfc_regs->e_slice_type); | |
| 1936 | 1999 | } |
| 1937 | 2000 | |
| 1938 | 2001 | static int s5p_mfc_get_enc_pic_count_v6(struct s5p_mfc_dev *dev) |
| 1939 | 2002 | { |
| 1940 | − return mfc_read(dev, S5P_FIMV_E_PICTURE_COUNT_V6); | |
| 2003 | + return READL(dev->mfc_regs->e_picture_count); | |
| 1941 | 2004 | } |
| 1942 | 2005 | |
| 1943 | 2006 | static int s5p_mfc_get_sei_avail_status_v6(struct s5p_mfc_ctx *ctx) |
| 1944 | 2007 | { |
| 1945 | − return mfc_read(ctx->dev, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); | |
| 2008 | + struct s5p_mfc_dev *dev = ctx->dev; | |
| 2009 | + return READL(dev->mfc_regs->d_frame_pack_sei_avail); | |
| 1946 | 2010 | } |
| 1947 | 2011 | |
| 1948 | 2012 | static int s5p_mfc_get_mvc_num_views_v6(struct s5p_mfc_dev *dev) |
| 1949 | 2013 | { |
| 1950 | − return mfc_read(dev, S5P_FIMV_D_MVC_NUM_VIEWS_V6); | |
| 2014 | + return READL(dev->mfc_regs->d_mvc_num_views); | |
| 1951 | 2015 | } |
| 1952 | 2016 | |
| 1953 | 2017 | static int s5p_mfc_get_mvc_view_id_v6(struct s5p_mfc_dev *dev) |
| 1954 | 2018 | { |
| 1955 | − return mfc_read(dev, S5P_FIMV_D_MVC_VIEW_ID_V6); | |
| 2019 | + return READL(dev->mfc_regs->d_mvc_view_id); | |
| 1956 | 2020 | } |
| 1957 | 2021 | |
| 1958 | 2022 | static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx) |
| 1959 | 2023 | { |
| 1960 | − return s5p_mfc_read_info_v6(ctx, PIC_TIME_TOP_V6); | |
| 2024 | + return s5p_mfc_read_info_v6(ctx, | |
| 2025 | + (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_top); | |
| 1961 | 2026 | } |
| 1962 | 2027 | |
| 1963 | 2028 | static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx) |
| 1964 | 2029 | { |
| 1965 | − return s5p_mfc_read_info_v6(ctx, PIC_TIME_BOT_V6); | |
| 2030 | + return s5p_mfc_read_info_v6(ctx, | |
| 2031 | + (unsigned int) ctx->dev->mfc_regs->d_ret_picture_tag_bot); | |
| 1966 | 2032 | } |
| 1967 | 2033 | |
| 1968 | 2034 | static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx) |
| 1969 | 2035 | { |
| 1970 | − return s5p_mfc_read_info_v6(ctx, CROP_INFO_H_V6); | |
| 2036 | + return s5p_mfc_read_info_v6(ctx, | |
| 2037 | + (unsigned int) ctx->dev->mfc_regs->d_display_crop_info1); | |
| 1971 | 2038 | } |
| 1972 | 2039 | |
| 1973 | 2040 | static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx) |
| 1974 | 2041 | { |
| 1975 | − return s5p_mfc_read_info_v6(ctx, CROP_INFO_V_V6); | |
| 2042 | + return s5p_mfc_read_info_v6(ctx, | |
| 2043 | + (unsigned int) ctx->dev->mfc_regs->d_display_crop_info2); | |
| 2044 | +} | |
| 2045 | + | |
| 2046 | +static struct s5p_mfc_regs mfc_regs; | |
| 2047 | + | |
| 2048 | +/* Initialize registers for MFC v6 onwards */ | |
| 2049 | +const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev) | |
| 2050 | +{ | |
| 2051 | + memset(&mfc_regs, 0, sizeof(mfc_regs)); | |
| 2052 | + | |
| 2053 | +#define S5P_MFC_REG_ADDR(dev, reg) ((dev)->regs_base + (reg)) | |
| 2054 | +#define R(m, r) mfc_regs.m = S5P_MFC_REG_ADDR(dev, r) | |
| 2055 | + /* codec common registers */ | |
| 2056 | + R(risc_on, S5P_FIMV_RISC_ON_V6); | |
| 2057 | + R(risc2host_int, S5P_FIMV_RISC2HOST_INT_V6); | |
| 2058 | + R(host2risc_int, S5P_FIMV_HOST2RISC_INT_V6); | |
| 2059 | + R(risc_base_address, S5P_FIMV_RISC_BASE_ADDRESS_V6); | |
| 2060 | + R(mfc_reset, S5P_FIMV_MFC_RESET_V6); | |
| 2061 | + R(host2risc_command, S5P_FIMV_HOST2RISC_CMD_V6); | |
| 2062 | + R(risc2host_command, S5P_FIMV_RISC2HOST_CMD_V6); | |
| 2063 | + R(firmware_version, S5P_FIMV_FW_VERSION_V6); | |
| 2064 | + R(instance_id, S5P_FIMV_INSTANCE_ID_V6); | |
| 2065 | + R(codec_type, S5P_FIMV_CODEC_TYPE_V6); | |
| 2066 | + R(context_mem_addr, S5P_FIMV_CONTEXT_MEM_ADDR_V6); | |
| 2067 | + R(context_mem_size, S5P_FIMV_CONTEXT_MEM_SIZE_V6); | |
| 2068 | + R(pixel_format, S5P_FIMV_PIXEL_FORMAT_V6); | |
| 2069 | + R(ret_instance_id, S5P_FIMV_RET_INSTANCE_ID_V6); | |
| 2070 | + R(error_code, S5P_FIMV_ERROR_CODE_V6); | |
| 2071 | + | |
| 2072 | + /* decoder registers */ | |
| 2073 | + R(d_crc_ctrl, S5P_FIMV_D_CRC_CTRL_V6); | |
| 2074 | + R(d_dec_options, S5P_FIMV_D_DEC_OPTIONS_V6); | |
| 2075 | + R(d_display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6); | |
| 2076 | + R(d_sei_enable, S5P_FIMV_D_SEI_ENABLE_V6); | |
| 2077 | + R(d_min_num_dpb, S5P_FIMV_D_MIN_NUM_DPB_V6); | |
| 2078 | + R(d_min_num_mv, S5P_FIMV_D_MIN_NUM_MV_V6); | |
| 2079 | + R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V6); | |
| 2080 | + R(d_num_dpb, S5P_FIMV_D_NUM_DPB_V6); | |
| 2081 | + R(d_num_mv, S5P_FIMV_D_NUM_MV_V6); | |
| 2082 | + R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6); | |
| 2083 | + R(d_first_plane_dpb_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6); | |
| 2084 | + R(d_second_plane_dpb_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6); | |
| 2085 | + R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6); | |
| 2086 | + R(d_first_plane_dpb, S5P_FIMV_D_LUMA_DPB_V6); | |
| 2087 | + R(d_second_plane_dpb, S5P_FIMV_D_CHROMA_DPB_V6); | |
| 2088 | + R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V6); | |
| 2089 | + R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6); | |
| 2090 | + R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6); | |
| 2091 | + R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6); | |
| 2092 | + R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V6); | |
| 2093 | + R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6); | |
| 2094 | + R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6); | |
| 2095 | + R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V6); | |
| 2096 | + R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6); | |
| 2097 | + R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6); | |
| 2098 | + R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6); | |
| 2099 | + R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V6); | |
| 2100 | + R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6); | |
| 2101 | + R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6); | |
| 2102 | + R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6); | |
| 2103 | + R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V6); | |
| 2104 | + R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V6); | |
| 2105 | + R(d_display_aspect_ratio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6); | |
| 2106 | + R(d_display_extended_ar, S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6); | |
| 2107 | + R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V6); | |
| 2108 | + R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_LUMA_ADDR_V6); | |
| 2109 | + R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_CHROMA_ADDR_V6); | |
| 2110 | + R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V6); | |
| 2111 | + R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V6); | |
| 2112 | + R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6); | |
| 2113 | + R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6); | |
| 2114 | + R(d_h264_info, S5P_FIMV_D_H264_INFO_V6); | |
| 2115 | + R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V6); | |
| 2116 | + R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6); | |
| 2117 | + | |
| 2118 | + /* encoder registers */ | |
| 2119 | + R(e_frame_width, S5P_FIMV_E_FRAME_WIDTH_V6); | |
| 2120 | + R(e_frame_height, S5P_FIMV_E_FRAME_HEIGHT_V6); | |
| 2121 | + R(e_cropped_frame_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6); | |
| 2122 | + R(e_cropped_frame_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6); | |
| 2123 | + R(e_frame_crop_offset, S5P_FIMV_E_FRAME_CROP_OFFSET_V6); | |
| 2124 | + R(e_enc_options, S5P_FIMV_E_ENC_OPTIONS_V6); | |
| 2125 | + R(e_picture_profile, S5P_FIMV_E_PICTURE_PROFILE_V6); | |
| 2126 | + R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V6); | |
| 2127 | + R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6); | |
| 2128 | + R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V6); | |
| 2129 | + R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V6); | |
| 2130 | + R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V6); | |
| 2131 | + R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V6); | |
| 2132 | + R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V6); | |
| 2133 | + R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V6); | |
| 2134 | + R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V6); | |
| 2135 | + R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V6); | |
| 2136 | + R(e_num_dpb, S5P_FIMV_E_NUM_DPB_V6); | |
| 2137 | + R(e_luma_dpb, S5P_FIMV_E_LUMA_DPB_V6); | |
| 2138 | + R(e_chroma_dpb, S5P_FIMV_E_CHROMA_DPB_V6); | |
| 2139 | + R(e_me_buffer, S5P_FIMV_E_ME_BUFFER_V6); | |
| 2140 | + R(e_scratch_buffer_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6); | |
| 2141 | + R(e_scratch_buffer_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6); | |
| 2142 | + R(e_tmv_buffer0, S5P_FIMV_E_TMV_BUFFER0_V6); | |
| 2143 | + R(e_tmv_buffer1, S5P_FIMV_E_TMV_BUFFER1_V6); | |
| 2144 | + R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6); | |
| 2145 | + R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6); | |
| 2146 | + R(e_stream_buffer_addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6); | |
| 2147 | + R(e_stream_buffer_size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6); | |
| 2148 | + R(e_roi_buffer_addr, S5P_FIMV_E_ROI_BUFFER_ADDR_V6); | |
| 2149 | + R(e_param_change, S5P_FIMV_E_PARAM_CHANGE_V6); | |
| 2150 | + R(e_ir_size, S5P_FIMV_E_IR_SIZE_V6); | |
| 2151 | + R(e_gop_config, S5P_FIMV_E_GOP_CONFIG_V6); | |
| 2152 | + R(e_mslice_mode, S5P_FIMV_E_MSLICE_MODE_V6); | |
| 2153 | + R(e_mslice_size_mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6); | |
| 2154 | + R(e_mslice_size_bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6); | |
| 2155 | + R(e_frame_insertion, S5P_FIMV_E_FRAME_INSERTION_V6); | |
| 2156 | + R(e_rc_frame_rate, S5P_FIMV_E_RC_FRAME_RATE_V6); | |
| 2157 | + R(e_rc_bit_rate, S5P_FIMV_E_RC_BIT_RATE_V6); | |
| 2158 | + R(e_rc_roi_ctrl, S5P_FIMV_E_RC_ROI_CTRL_V6); | |
| 2159 | + R(e_picture_tag, S5P_FIMV_E_PICTURE_TAG_V6); | |
| 2160 | + R(e_bit_count_enable, S5P_FIMV_E_BIT_COUNT_ENABLE_V6); | |
| 2161 | + R(e_max_bit_count, S5P_FIMV_E_MAX_BIT_COUNT_V6); | |
| 2162 | + R(e_min_bit_count, S5P_FIMV_E_MIN_BIT_COUNT_V6); | |
| 2163 | + R(e_metadata_buffer_addr, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6); | |
| 2164 | + R(e_metadata_buffer_size, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6); | |
| 2165 | + R(e_encoded_source_first_plane_addr, | |
| 2166 | + S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6); | |
| 2167 | + R(e_encoded_source_second_plane_addr, | |
| 2168 | + S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6); | |
| 2169 | + R(e_stream_size, S5P_FIMV_E_STREAM_SIZE_V6); | |
| 2170 | + R(e_slice_type, S5P_FIMV_E_SLICE_TYPE_V6); | |
| 2171 | + R(e_picture_count, S5P_FIMV_E_PICTURE_COUNT_V6); | |
| 2172 | + R(e_ret_picture_tag, S5P_FIMV_E_RET_PICTURE_TAG_V6); | |
| 2173 | + R(e_recon_luma_dpb_addr, S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6); | |
| 2174 | + R(e_recon_chroma_dpb_addr, S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6); | |
| 2175 | + R(e_mpeg4_options, S5P_FIMV_E_MPEG4_OPTIONS_V6); | |
| 2176 | + R(e_mpeg4_hec_period, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6); | |
| 2177 | + R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V6); | |
| 2178 | + R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V6); | |
| 2179 | + R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V6); | |
| 2180 | + R(e_h264_lf_alpha_offset, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6); | |
| 2181 | + R(e_h264_lf_beta_offset, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6); | |
| 2182 | + R(e_h264_i_period, S5P_FIMV_E_H264_I_PERIOD_V6); | |
| 2183 | + R(e_h264_fmo_slice_grp_map_type, | |
| 2184 | + S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6); | |
| 2185 | + R(e_h264_fmo_num_slice_grp_minus1, | |
| 2186 | + S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6); | |
| 2187 | + R(e_h264_fmo_slice_grp_change_dir, | |
| 2188 | + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6); | |
| 2189 | + R(e_h264_fmo_slice_grp_change_rate_minus1, | |
| 2190 | + S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6); | |
| 2191 | + R(e_h264_fmo_run_length_minus1_0, | |
| 2192 | + S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6); | |
| 2193 | + R(e_h264_aso_slice_order_0, S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6); | |
| 2194 | + R(e_h264_num_t_layer, S5P_FIMV_E_H264_NUM_T_LAYER_V6); | |
| 2195 | + R(e_h264_hierarchical_qp_layer0, | |
| 2196 | + S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6); | |
| 2197 | + R(e_h264_frame_packing_sei_info, | |
| 2198 | + S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6); | |
| 2199 | + | |
| 2200 | + if (!IS_MFCV7_PLUS(dev)) | |
| 2201 | + goto done; | |
| 2202 | + | |
| 2203 | + /* Initialize registers used in MFC v7+ */ | |
| 2204 | + R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7); | |
| 2205 | + R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7); | |
| 2206 | + R(e_source_third_plane_addr, S5P_FIMV_E_SOURCE_THIRD_ADDR_V7); | |
| 2207 | + R(e_source_first_plane_stride, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7); | |
| 2208 | + R(e_source_second_plane_stride, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7); | |
| 2209 | + R(e_source_third_plane_stride, S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7); | |
| 2210 | + R(e_encoded_source_first_plane_addr, | |
| 2211 | + S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7); | |
| 2212 | + R(e_encoded_source_second_plane_addr, | |
| 2213 | + S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7); | |
| 2214 | + R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7); | |
| 2215 | + | |
| 2216 | + if (!IS_MFCV8(dev)) | |
| 2217 | + goto done; | |
| 2218 | + | |
| 2219 | + /* Initialize registers used in MFC v8 only. | |
| 2220 | + * Also, over-write the registers which have | |
| 2221 | + * a different offset for MFC v8. */ | |
| 2222 | + R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V8); | |
| 2223 | + R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V8); | |
| 2224 | + R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V8); | |
| 2225 | + R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V8); | |
| 2226 | + R(d_first_plane_dpb_size, S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8); | |
| 2227 | + R(d_second_plane_dpb_size, S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8); | |
| 2228 | + R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8); | |
| 2229 | + R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8); | |
| 2230 | + R(d_first_plane_dpb_stride_size, | |
| 2231 | + S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8); | |
| 2232 | + R(d_second_plane_dpb_stride_size, | |
| 2233 | + S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8); | |
| 2234 | + R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V8); | |
| 2235 | + R(d_num_mv, S5P_FIMV_D_NUM_MV_V8); | |
| 2236 | + R(d_first_plane_dpb, S5P_FIMV_D_FIRST_PLANE_DPB_V8); | |
| 2237 | + R(d_second_plane_dpb, S5P_FIMV_D_SECOND_PLANE_DPB_V8); | |
| 2238 | + R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V8); | |
| 2239 | + R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8); | |
| 2240 | + R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8); | |
| 2241 | + R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V8); | |
| 2242 | + R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8); | |
| 2243 | + R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8); | |
| 2244 | + R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8); | |
| 2245 | + R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8); | |
| 2246 | + R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V8); | |
| 2247 | + R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V8); | |
| 2248 | + R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V8); | |
| 2249 | + R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8); | |
| 2250 | + R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V8); | |
| 2251 | + R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8); | |
| 2252 | + R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8); | |
| 2253 | + R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8); | |
| 2254 | + R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V8); | |
| 2255 | + R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V8); | |
| 2256 | + R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8); | |
| 2257 | + R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8); | |
| 2258 | + R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V8); | |
| 2259 | + R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V8); | |
| 2260 | + | |
| 2261 | + /* encoder registers */ | |
| 2262 | + R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V8); | |
| 2263 | + R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V8); | |
| 2264 | + R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V8); | |
| 2265 | + R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V8); | |
| 2266 | + R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V8); | |
| 2267 | + R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V8); | |
| 2268 | + R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V8); | |
| 2269 | + R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V8); | |
| 2270 | + R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V8); | |
| 2271 | + R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V8); | |
| 2272 | + R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V8); | |
| 2273 | + R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V8); | |
| 2274 | + R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8); | |
| 2275 | + | |
| 2276 | +done: | |
| 2277 | + return &mfc_regs; | |
| 2278 | +#undef S5P_MFC_REG_ADDR | |
| 2279 | +#undef R | |
| 1976 | 2280 | } |
| 1977 | 2281 | |
| 1978 | 2282 | /* Initialize opr function pointers for MFC v6 */ |
| @@ -40,11 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | #define FRAME_DELTA_H264_H263 1 |
| 41 | 41 | #define TIGHT_CBR_MAX 10 |
| 42 | 42 | |
| 43 | −/* Definitions for shared memory compatibility */ | |
| 44 | −#define PIC_TIME_TOP_V6 S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6 | |
| 45 | −#define PIC_TIME_BOT_V6 S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6 | |
| 46 | −#define CROP_INFO_H_V6 S5P_FIMV_D_DISPLAY_CROP_INFO1_V6 | |
| 47 | −#define CROP_INFO_V_V6 S5P_FIMV_D_DISPLAY_CROP_INFO2_V6 | |
| 48 | − | |
| 49 | 43 | struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void); |
| 44 | +const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev); | |
| 50 | 45 | #endif /* S5P_MFC_OPR_V6_H_ */ |
| @@ -674,6 +674,8 @@ static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, · 673 unmodified lines | ||
| 674 | 674 | static int hdmi_enum_dv_timings(struct v4l2_subdev *sd, |
| 675 | 675 | struct v4l2_enum_dv_timings *timings) |
| 676 | 676 | { |
| 677 | + if (timings->pad != 0) | |
| 678 | + return -EINVAL; | |
| 677 | 679 | if (timings->index >= ARRAY_SIZE(hdmi_timings)) |
| 678 | 680 | return -EINVAL; |
| 679 | 681 | timings->timings = hdmi_timings[timings->index].dv_timings; |
| @@ -687,8 +689,11 @@ static int hdmi_dv_timings_cap(struct v4l2_subdev *sd, · 7 unmodified lines | ||
| 687 | 689 | { |
| 688 | 690 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); |
| 689 | 691 | |
| 692 | + if (cap->pad != 0) | |
| 693 | + return -EINVAL; | |
| 694 | + | |
| 690 | 695 | /* Let the phy fill in the pixelclock range */ |
| 691 | − v4l2_subdev_call(hdev->phy_sd, video, dv_timings_cap, cap); | |
| 696 | + v4l2_subdev_call(hdev->phy_sd, pad, dv_timings_cap, cap); | |
| 692 | 697 | cap->type = V4L2_DV_BT_656_1120; |
| 693 | 698 | cap->bt.min_width = 720; |
| 694 | 699 | cap->bt.max_width = 1920; |
| @@ -707,12 +712,15 @@ static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { · 12 unmodified lines | ||
| 707 | 712 | static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = { |
| 708 | 713 | .s_dv_timings = hdmi_s_dv_timings, |
| 709 | 714 | .g_dv_timings = hdmi_g_dv_timings, |
| 710 | − .enum_dv_timings = hdmi_enum_dv_timings, | |
| 711 | − .dv_timings_cap = hdmi_dv_timings_cap, | |
| 712 | 715 | .g_mbus_fmt = hdmi_g_mbus_fmt, |
| 713 | 716 | .s_stream = hdmi_s_stream, |
| 714 | 717 | }; |
| 715 | 718 | |
| 719 | +static const struct v4l2_subdev_pad_ops hdmi_sd_pad_ops = { | |
| 720 | + .enum_dv_timings = hdmi_enum_dv_timings, | |
| 721 | + .dv_timings_cap = hdmi_dv_timings_cap, | |
| 722 | +}; | |
| 723 | + | |
| 716 | 724 | static const struct v4l2_subdev_ops hdmi_sd_ops = { |
| 717 | 725 | .core = &hdmi_sd_core_ops, |
| 718 | 726 | .video = &hdmi_sd_video_ops, |
| @@ -225,6 +225,9 @@ static int hdmiphy_s_dv_timings(struct v4l2_subdev *sd, · 224 unmodified lines | ||
| 225 | 225 | static int hdmiphy_dv_timings_cap(struct v4l2_subdev *sd, |
| 226 | 226 | struct v4l2_dv_timings_cap *cap) |
| 227 | 227 | { |
| 228 | + if (cap->pad != 0) | |
| 229 | + return -EINVAL; | |
| 230 | + | |
| 228 | 231 | cap->type = V4L2_DV_BT_656_1120; |
| 229 | 232 | /* The phy only determines the pixelclock, leave the other values |
| 230 | 233 | * at 0 to signify that we have no information for them. */ |
| @@ -259,13 +262,17 @@ static const struct v4l2_subdev_core_ops hdmiphy_core_ops = { · 28 unmodified lines | ||
| 259 | 262 | |
| 260 | 263 | static const struct v4l2_subdev_video_ops hdmiphy_video_ops = { |
| 261 | 264 | .s_dv_timings = hdmiphy_s_dv_timings, |
| 262 | − .dv_timings_cap = hdmiphy_dv_timings_cap, | |
| 263 | 265 | .s_stream = hdmiphy_s_stream, |
| 264 | 266 | }; |
| 265 | 267 | |
| 268 | +static const struct v4l2_subdev_pad_ops hdmiphy_pad_ops = { | |
| 269 | + .dv_timings_cap = hdmiphy_dv_timings_cap, | |
| 270 | +}; | |
| 271 | + | |
| 266 | 272 | static const struct v4l2_subdev_ops hdmiphy_ops = { |
| 267 | 273 | .core = &hdmiphy_core_ops, |
| 268 | 274 | .video = &hdmiphy_video_ops, |
| 275 | + .pad = &hdmiphy_pad_ops, | |
| 269 | 276 | }; |
| 270 | 277 | |
| 271 | 278 | static int hdmiphy_probe(struct i2c_client *client, |
| @@ -509,9 +509,11 @@ static int mxr_enum_dv_timings(struct file *file, void *fh, · 508 unmodified lines | ||
| 509 | 509 | struct mxr_device *mdev = layer->mdev; |
| 510 | 510 | int ret; |
| 511 | 511 | |
| 512 | + timings->pad = 0; | |
| 513 | + | |
| 512 | 514 | /* lock protects from changing sd_out */ |
| 513 | 515 | mutex_lock(&mdev->mutex); |
| 514 | − ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_timings, timings); | |
| 516 | + ret = v4l2_subdev_call(to_outsd(mdev), pad, enum_dv_timings, timings); | |
| 515 | 517 | mutex_unlock(&mdev->mutex); |
| 516 | 518 | |
| 517 | 519 | return ret ? -EINVAL : 0; |
| @@ -567,9 +569,11 @@ static int mxr_dv_timings_cap(struct file *file, void *fh, · 49 unmodified lines | ||
| 567 | 569 | struct mxr_device *mdev = layer->mdev; |
| 568 | 570 | int ret; |
| 569 | 571 | |
| 572 | + cap->pad = 0; | |
| 573 | + | |
| 570 | 574 | /* lock protects from changing sd_out */ |
| 571 | 575 | mutex_lock(&mdev->mutex); |
| 572 | − ret = v4l2_subdev_call(to_outsd(mdev), video, dv_timings_cap, cap); | |
| 576 | + ret = v4l2_subdev_call(to_outsd(mdev), pad, dv_timings_cap, cap); | |
| 573 | 577 | mutex_unlock(&mdev->mutex); |
| 574 | 578 | |
| 575 | 579 | return ret ? -EINVAL : 0; |
| @@ -985,7 +989,7 @@ static void mxr_watchdog(unsigned long arg) · 409 unmodified lines | ||
| 985 | 989 | spin_unlock_irqrestore(&layer->enq_slock, flags); |
| 986 | 990 | } |
| 987 | 991 | |
| 988 | −static int stop_streaming(struct vb2_queue *vq) | |
| 992 | +static void stop_streaming(struct vb2_queue *vq) | |
| 989 | 993 | { |
| 990 | 994 | struct mxr_layer *layer = vb2_get_drv_priv(vq); |
| 991 | 995 | struct mxr_device *mdev = layer->mdev; |
| @@ -1031,7 +1035,6 @@ static int stop_streaming(struct vb2_queue *vq) · 39 unmodified lines | ||
| 1031 | 1035 | mxr_streamer_put(mdev); |
| 1032 | 1036 | /* allow changes in output configuration */ |
| 1033 | 1037 | mxr_output_put(mdev); |
| 1034 | − return 0; | |
| 1035 | 1038 | } |
| 1036 | 1039 | |
| 1037 | 1040 | static struct vb2_ops mxr_video_qops = { |
| @@ -406,7 +406,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 405 unmodified lines | ||
| 406 | 406 | } |
| 407 | 407 | |
| 408 | 408 | /* abort streaming and wait for last buffer */ |
| 409 | −static int stop_streaming(struct vb2_queue *vq) | |
| 409 | +static void stop_streaming(struct vb2_queue *vq) | |
| 410 | 410 | { |
| 411 | 411 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); |
| 412 | 412 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| @@ -433,7 +433,7 @@ static int stop_streaming(struct vb2_queue *vq) · 20 unmodified lines | ||
| 433 | 433 | if (time_after(jiffies, timeout)) { |
| 434 | 434 | dev_err(icd->parent, |
| 435 | 435 | "Timeout waiting for finishing codec request\n"); |
| 436 | − return -ETIMEDOUT; | |
| 436 | + return; | |
| 437 | 437 | } |
| 438 | 438 | |
| 439 | 439 | /* Disable interrupts */ |
| @@ -444,8 +444,6 @@ static int stop_streaming(struct vb2_queue *vq) · 4 unmodified lines | ||
| 444 | 444 | ret = atmel_isi_wait_status(isi, WAIT_ISI_DISABLE); |
| 445 | 445 | if (ret < 0) |
| 446 | 446 | dev_err(icd->parent, "Disable ISI timed out\n"); |
| 447 | − | |
| 448 | − return ret; | |
| 449 | 447 | } |
| 450 | 448 | |
| 451 | 449 | static struct vb2_ops isi_video_qops = { |
| @@ -741,7 +741,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) · 740 unmodified lines | ||
| 741 | 741 | return 0; |
| 742 | 742 | } |
| 743 | 743 | |
| 744 | −static int mx2_stop_streaming(struct vb2_queue *q) | |
| 744 | +static void mx2_stop_streaming(struct vb2_queue *q) | |
| 745 | 745 | { |
| 746 | 746 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); |
| 747 | 747 | struct soc_camera_host *ici = |
| @@ -773,8 +773,6 @@ static int mx2_stop_streaming(struct vb2_queue *q) · 25 unmodified lines | ||
| 773 | 773 | |
| 774 | 774 | dma_free_coherent(ici->v4l2_dev.dev, |
| 775 | 775 | pcdev->discard_size, b, pcdev->discard_buffer_dma); |
| 776 | − | |
| 777 | − return 0; | |
| 778 | 776 | } |
| 779 | 777 | |
| 780 | 778 | static struct vb2_ops mx2_videobuf_ops = { |
| @@ -406,7 +406,7 @@ static int mx3_videobuf_init(struct vb2_buffer *vb) · 405 unmodified lines | ||
| 406 | 406 | return 0; |
| 407 | 407 | } |
| 408 | 408 | |
| 409 | −static int mx3_stop_streaming(struct vb2_queue *q) | |
| 409 | +static void mx3_stop_streaming(struct vb2_queue *q) | |
| 410 | 410 | { |
| 411 | 411 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); |
| 412 | 412 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| @@ -430,8 +430,6 @@ static int mx3_stop_streaming(struct vb2_queue *q) · 17 unmodified lines | ||
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | spin_unlock_irqrestore(&mx3_cam->lock, flags); |
| 433 | − | |
| 434 | − return 0; | |
| 435 | 433 | } |
| 436 | 434 | |
| 437 | 435 | static struct vb2_ops mx3_videobuf_ops = { |
| @@ -513,7 +513,7 @@ static int rcar_vin_videobuf_init(struct vb2_buffer *vb) · 512 unmodified lines | ||
| 513 | 513 | return 0; |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | −static int rcar_vin_stop_streaming(struct vb2_queue *vq) | |
| 516 | +static void rcar_vin_stop_streaming(struct vb2_queue *vq) | |
| 517 | 517 | { |
| 518 | 518 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); |
| 519 | 519 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| @@ -524,8 +524,6 @@ static int rcar_vin_stop_streaming(struct vb2_queue *vq) · 4 unmodified lines | ||
| 524 | 524 | list_for_each_safe(buf_head, tmp, &priv->capture) |
| 525 | 525 | list_del_init(buf_head); |
| 526 | 526 | spin_unlock_irq(&priv->lock); |
| 527 | − | |
| 528 | − return 0; | |
| 529 | 527 | } |
| 530 | 528 | |
| 531 | 529 | static struct vb2_ops rcar_vin_vb2_ops = { |
| @@ -471,7 +471,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) · 470 unmodified lines | ||
| 471 | 471 | return 0; |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | −static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q) | |
| 474 | +static void sh_mobile_ceu_stop_streaming(struct vb2_queue *q) | |
| 475 | 475 | { |
| 476 | 476 | struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq); |
| 477 | 477 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| @@ -487,7 +487,7 @@ static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q) · 9 unmodified lines | ||
| 487 | 487 | |
| 488 | 488 | spin_unlock_irq(&pcdev->lock); |
| 489 | 489 | |
| 490 | − return sh_mobile_ceu_soft_reset(pcdev); | |
| 490 | + sh_mobile_ceu_soft_reset(pcdev); | |
| 491 | 491 | } |
| 492 | 492 | |
| 493 | 493 | static struct vb2_ops sh_mobile_ceu_videobuf_ops = { |
| @@ -314,7 +314,7 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id a) · 313 unmodified lines | ||
| 314 | 314 | struct soc_camera_device *icd = file->private_data; |
| 315 | 315 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
| 316 | 316 | |
| 317 | − return v4l2_subdev_call(sd, core, s_std, a); | |
| 317 | + return v4l2_subdev_call(sd, video, s_std, a); | |
| 318 | 318 | } |
| 319 | 319 | |
| 320 | 320 | static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a) |
| @@ -322,7 +322,7 @@ static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a) · 1 unmodified line | ||
| 322 | 322 | struct soc_camera_device *icd = file->private_data; |
| 323 | 323 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
| 324 | 324 | |
| 325 | − return v4l2_subdev_call(sd, core, g_std, a); | |
| 325 | + return v4l2_subdev_call(sd, video, g_std, a); | |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | 328 | static int soc_camera_enum_framesizes(struct file *file, void *fh, |
| @@ -1277,6 +1277,8 @@ static int soc_camera_probe_finish(struct soc_camera_device *icd) · 948 unmodified lines | ||
| 1277 | 1277 | sd->grp_id = soc_camera_grp_id(icd); |
| 1278 | 1278 | v4l2_set_subdev_hostdata(sd, icd); |
| 1279 | 1279 | |
| 1280 | + v4l2_subdev_call(sd, video, g_tvnorms, &icd->vdev->tvnorms); | |
| 1281 | + | |
| 1280 | 1282 | ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); |
| 1281 | 1283 | if (ret < 0) |
| 1282 | 1284 | return ret; |
| @@ -1997,6 +1999,12 @@ static int soc_camera_video_start(struct soc_camera_device *icd) · 714 unmodified lines | ||
| 1997 | 1999 | return -ENODEV; |
| 1998 | 2000 | |
| 1999 | 2001 | video_set_drvdata(icd->vdev, icd); |
| 2002 | + if (icd->vdev->tvnorms == 0) { | |
| 2003 | + /* disable the STD API if there are no tvnorms defined */ | |
| 2004 | + v4l2_disable_ioctl(icd->vdev, VIDIOC_G_STD); | |
| 2005 | + v4l2_disable_ioctl(icd->vdev, VIDIOC_S_STD); | |
| 2006 | + v4l2_disable_ioctl(icd->vdev, VIDIOC_ENUMSTD); | |
| 2007 | + } | |
| 2000 | 2008 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1); |
| 2001 | 2009 | if (ret < 0) { |
| 2002 | 2010 | dev_err(icd->pdev, "video_register_device failed: %d\n", ret); |
| @@ -180,16 +180,16 @@ struct csc_data *csc_create(struct platform_device *pdev) · 179 unmodified lines | ||
| 180 | 180 | csc->pdev = pdev; |
| 181 | 181 | |
| 182 | 182 | csc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
| 183 | − "vpe_csc"); | |
| 183 | + "csc"); | |
| 184 | 184 | if (csc->res == NULL) { |
| 185 | 185 | dev_err(&pdev->dev, "missing platform resources data\n"); |
| 186 | 186 | return ERR_PTR(-ENODEV); |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 189 | csc->base = devm_ioremap_resource(&pdev->dev, csc->res); |
| 190 | − if (!csc->base) { | |
| 190 | + if (IS_ERR(csc->base)) { | |
| 191 | 191 | dev_err(&pdev->dev, "failed to ioremap\n"); |
| 192 | − return ERR_PTR(-ENOMEM); | |
| 192 | + return csc->base; | |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 195 | return csc; |
| @@ -302,9 +302,9 @@ struct sc_data *sc_create(struct platform_device *pdev) · 301 unmodified lines | ||
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | sc->base = devm_ioremap_resource(&pdev->dev, sc->res); |
| 305 | − if (!sc->base) { | |
| 305 | + if (IS_ERR(sc->base)) { | |
| 306 | 306 | dev_err(&pdev->dev, "failed to ioremap\n"); |
| 307 | − return ERR_PTR(-ENOMEM); | |
| 307 | + return sc->base; | |
| 308 | 308 | } |
| 309 | 309 | |
| 310 | 310 | return sc; |
| @@ -614,8 +614,17 @@ static void dump_dtd(struct vpdma_dtd *dtd) · 613 unmodified lines | ||
| 614 | 614 | /* |
| 615 | 615 | * append an outbound data transfer descriptor to the given descriptor list, |
| 616 | 616 | * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel |
| 617 | + * | |
| 618 | + * @list: vpdma desc list to which we add this decriptor | |
| 619 | + * @width: width of the image in pixels in memory | |
| 620 | + * @c_rect: compose params of output image | |
| 621 | + * @fmt: vpdma data format of the buffer | |
| 622 | + * dma_addr: dma address as seen by VPDMA | |
| 623 | + * chan: VPDMA channel | |
| 624 | + * flags: VPDMA flags to configure some descriptor fileds | |
| 617 | 625 | */ |
| 618 | −void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, | |
| 626 | +void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, | |
| 627 | + const struct v4l2_rect *c_rect, | |
| 619 | 628 | const struct vpdma_data_format *fmt, dma_addr_t dma_addr, |
| 620 | 629 | enum vpdma_channel chan, u32 flags) |
| 621 | 630 | { |
| @@ -623,6 +632,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, · 1 unmodified line | ||
| 623 | 632 | int field = 0; |
| 624 | 633 | int notify = 1; |
| 625 | 634 | int channel, next_chan; |
| 635 | + struct v4l2_rect rect = *c_rect; | |
| 626 | 636 | int depth = fmt->depth; |
| 627 | 637 | int stride; |
| 628 | 638 | struct vpdma_dtd *dtd; |
| @@ -630,11 +640,15 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, · 1 unmodified line | ||
| 630 | 640 | channel = next_chan = chan_info[chan].num; |
| 631 | 641 | |
| 632 | 642 | if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV && |
| 633 | − fmt->data_type == DATA_TYPE_C420) | |
| 643 | + fmt->data_type == DATA_TYPE_C420) { | |
| 644 | + rect.height >>= 1; | |
| 645 | + rect.top >>= 1; | |
| 634 | 646 | depth = 8; |
| 647 | + } | |
| 635 | 648 | |
| 636 | − stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN); | |
| 637 | − dma_addr += (c_rect->left * depth) >> 3; | |
| 649 | + stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN); | |
| 650 | + | |
| 651 | + dma_addr += rect.top * stride + (rect.left * depth >> 3); | |
| 638 | 652 | |
| 639 | 653 | dtd = list->next; |
| 640 | 654 | WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); |
| @@ -664,31 +678,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, · 23 unmodified lines | ||
| 664 | 678 | /* |
| 665 | 679 | * append an inbound data transfer descriptor to the given descriptor list, |
| 666 | 680 | * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel |
| 681 | + * | |
| 682 | + * @list: vpdma desc list to which we add this decriptor | |
| 683 | + * @width: width of the image in pixels in memory(not the cropped width) | |
| 684 | + * @c_rect: crop params of input image | |
| 685 | + * @fmt: vpdma data format of the buffer | |
| 686 | + * dma_addr: dma address as seen by VPDMA | |
| 687 | + * chan: VPDMA channel | |
| 688 | + * field: top or bottom field info of the input image | |
| 689 | + * flags: VPDMA flags to configure some descriptor fileds | |
| 690 | + * frame_width/height: the complete width/height of the image presented to the | |
| 691 | + * client (this makes sense when multiple channels are | |
| 692 | + * connected to the same client, forming a larger frame) | |
| 693 | + * start_h, start_v: position where the given channel starts providing pixel | |
| 694 | + * data to the client (makes sense when multiple channels | |
| 695 | + * contribute to the client) | |
| 667 | 696 | */ |
| 668 | −void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, | |
| 669 | − int frame_height, struct v4l2_rect *c_rect, | |
| 697 | +void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, | |
| 698 | + const struct v4l2_rect *c_rect, | |
| 670 | 699 | const struct vpdma_data_format *fmt, dma_addr_t dma_addr, |
| 671 | − enum vpdma_channel chan, int field, u32 flags) | |
| 700 | + enum vpdma_channel chan, int field, u32 flags, int frame_width, | |
| 701 | + int frame_height, int start_h, int start_v) | |
| 672 | 702 | { |
| 673 | 703 | int priority = 0; |
| 674 | 704 | int notify = 1; |
| 675 | 705 | int depth = fmt->depth; |
| 676 | 706 | int channel, next_chan; |
| 707 | + struct v4l2_rect rect = *c_rect; | |
| 677 | 708 | int stride; |
| 678 | − int height = c_rect->height; | |
| 679 | 709 | struct vpdma_dtd *dtd; |
| 680 | 710 | |
| 681 | 711 | channel = next_chan = chan_info[chan].num; |
| 682 | 712 | |
| 683 | 713 | if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV && |
| 684 | 714 | fmt->data_type == DATA_TYPE_C420) { |
| 685 | − height >>= 1; | |
| 686 | − frame_height >>= 1; | |
| 715 | + rect.height >>= 1; | |
| 716 | + rect.top >>= 1; | |
| 687 | 717 | depth = 8; |
| 688 | 718 | } |
| 689 | 719 | |
| 690 | − stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN); | |
| 691 | − dma_addr += (c_rect->left * depth) >> 3; | |
| 720 | + stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN); | |
| 721 | + | |
| 722 | + dma_addr += rect.top * stride + (rect.left * depth >> 3); | |
| 692 | 723 | |
| 693 | 724 | dtd = list->next; |
| 694 | 725 | WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); |
| @@ -701,13 +732,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, · 6 unmodified lines | ||
| 701 | 732 | !!(flags & VPDMA_DATA_ODD_LINE_SKIP), |
| 702 | 733 | stride); |
| 703 | 734 | |
| 704 | − dtd->xfer_length_height = dtd_xfer_length_height(c_rect->width, height); | |
| 735 | + dtd->xfer_length_height = dtd_xfer_length_height(rect.width, | |
| 736 | + rect.height); | |
| 705 | 737 | dtd->start_addr = (u32) dma_addr; |
| 706 | 738 | dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED), |
| 707 | 739 | DTD_DIR_IN, channel, priority, next_chan); |
| 708 | 740 | dtd->frame_width_height = dtd_frame_width_height(frame_width, |
| 709 | 741 | frame_height); |
| 710 | − dtd->start_h_v = dtd_start_h_v(c_rect->left, c_rect->top); | |
| 742 | + dtd->start_h_v = dtd_start_h_v(start_h, start_v); | |
| 711 | 743 | dtd->client_attr0 = 0; |
| 712 | 744 | dtd->client_attr1 = 0; |
| 713 | 745 | |
| @@ -781,7 +813,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) · 67 unmodified lines | ||
| 781 | 813 | /* already initialized */ |
| 782 | 814 | if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK, |
| 783 | 815 | VPDMA_LIST_RDY_SHFT)) { |
| 784 | − vpdma->ready = true; | |
| 816 | + vpdma->cb(vpdma->pdev); | |
| 785 | 817 | return; |
| 786 | 818 | } |
| 787 | 819 | |
| @@ -811,7 +843,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) · 23 unmodified lines | ||
| 811 | 843 | goto free_buf; |
| 812 | 844 | } |
| 813 | 845 | |
| 814 | − vpdma->ready = true; | |
| 846 | + vpdma->cb(vpdma->pdev); | |
| 815 | 847 | |
| 816 | 848 | free_buf: |
| 817 | 849 | vpdma_unmap_desc_buf(vpdma, &fw_dma_buf); |
| @@ -839,7 +871,8 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma) · 21 unmodified lines | ||
| 839 | 871 | return 0; |
| 840 | 872 | } |
| 841 | 873 | |
| 842 | −struct vpdma_data *vpdma_create(struct platform_device *pdev) | |
| 874 | +struct vpdma_data *vpdma_create(struct platform_device *pdev, | |
| 875 | + void (*cb)(struct platform_device *pdev)) | |
| 843 | 876 | { |
| 844 | 877 | struct resource *res; |
| 845 | 878 | struct vpdma_data *vpdma; |
| @@ -854,6 +887,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) · 8 unmodified lines | ||
| 854 | 887 | } |
| 855 | 888 | |
| 856 | 889 | vpdma->pdev = pdev; |
| 890 | + vpdma->cb = cb; | |
| 857 | 891 | |
| 858 | 892 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma"); |
| 859 | 893 | if (res == NULL) { |
| @@ -35,8 +35,8 @@ struct vpdma_data { · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | struct platform_device *pdev; |
| 37 | 37 | |
| 38 | − /* tells whether vpdma firmware is loaded or not */ | |
| 39 | − bool ready; | |
| 38 | + /* callback to VPE driver when the firmware is loaded */ | |
| 39 | + void (*cb)(struct platform_device *pdev); | |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | 42 | enum vpdma_data_format_type { |
| @@ -186,13 +186,15 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, · 143 unmodified lines | ||
| 186 | 186 | struct vpdma_buf *adb); |
| 187 | 187 | void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, |
| 188 | 188 | enum vpdma_channel chan); |
| 189 | −void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, | |
| 189 | +void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width, | |
| 190 | + const struct v4l2_rect *c_rect, | |
| 190 | 191 | const struct vpdma_data_format *fmt, dma_addr_t dma_addr, |
| 191 | 192 | enum vpdma_channel chan, u32 flags); |
| 192 | −void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, | |
| 193 | − int frame_height, struct v4l2_rect *c_rect, | |
| 193 | +void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width, | |
| 194 | + const struct v4l2_rect *c_rect, | |
| 194 | 195 | const struct vpdma_data_format *fmt, dma_addr_t dma_addr, |
| 195 | − enum vpdma_channel chan, int field, u32 flags); | |
| 196 | + enum vpdma_channel chan, int field, u32 flags, int frame_width, | |
| 197 | + int frame_height, int start_h, int start_v); | |
| 196 | 198 | |
| 197 | 199 | /* vpdma list interrupt management */ |
| 198 | 200 | void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num, |
| @@ -208,6 +210,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma, · 9 unmodified lines | ||
| 208 | 210 | void vpdma_dump_regs(struct vpdma_data *vpdma); |
| 209 | 211 | |
| 210 | 212 | /* initialize vpdma, passed with VPE's platform device pointer */ |
| 211 | −struct vpdma_data *vpdma_create(struct platform_device *pdev); | |
| 213 | +struct vpdma_data *vpdma_create(struct platform_device *pdev, | |
| 214 | + void (*cb)(struct platform_device *pdev)); | |
| 212 | 215 | |
| 213 | 216 | #endif |
| @@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, · 409 unmodified lines | ||
| 410 | 410 | { |
| 411 | 411 | switch (type) { |
| 412 | 412 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
| 413 | + case V4L2_BUF_TYPE_VIDEO_OUTPUT: | |
| 413 | 414 | return &ctx->q_data[Q_DATA_SRC]; |
| 414 | 415 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
| 416 | + case V4L2_BUF_TYPE_VIDEO_CAPTURE: | |
| 415 | 417 | return &ctx->q_data[Q_DATA_DST]; |
| 416 | 418 | default: |
| 417 | 419 | BUG(); |
| @@ -986,7 +988,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port) · 568 unmodified lines | ||
| 986 | 988 | struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST]; |
| 987 | 989 | const struct vpe_port_data *p_data = &port_data[port]; |
| 988 | 990 | struct vb2_buffer *vb = ctx->dst_vb; |
| 989 | − struct v4l2_rect *c_rect = &q_data->c_rect; | |
| 990 | 991 | struct vpe_fmt *fmt = q_data->fmt; |
| 991 | 992 | const struct vpdma_data_format *vpdma_fmt; |
| 992 | 993 | int mv_buf_selector = !ctx->src_mv_buf_selector; |
| @@ -1015,8 +1016,8 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port) · 22 unmodified lines | ||
| 1015 | 1016 | if (q_data->flags & Q_DATA_MODE_TILED) |
| 1016 | 1017 | flags |= VPDMA_DATA_MODE_TILED; |
| 1017 | 1018 | |
| 1018 | − vpdma_add_out_dtd(&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, | |
| 1019 | − p_data->channel, flags); | |
| 1019 | + vpdma_add_out_dtd(&ctx->desc_list, q_data->width, &q_data->c_rect, | |
| 1020 | + vpdma_fmt, dma_addr, p_data->channel, flags); | |
| 1020 | 1021 | } |
| 1021 | 1022 | |
| 1022 | 1023 | static void add_in_dtd(struct vpe_ctx *ctx, int port) |
| @@ -1024,11 +1025,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port) · 1 unmodified line | ||
| 1024 | 1025 | struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC]; |
| 1025 | 1026 | const struct vpe_port_data *p_data = &port_data[port]; |
| 1026 | 1027 | struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; |
| 1027 | − struct v4l2_rect *c_rect = &q_data->c_rect; | |
| 1028 | 1028 | struct vpe_fmt *fmt = q_data->fmt; |
| 1029 | 1029 | const struct vpdma_data_format *vpdma_fmt; |
| 1030 | 1030 | int mv_buf_selector = ctx->src_mv_buf_selector; |
| 1031 | 1031 | int field = vb->v4l2_buf.field == V4L2_FIELD_BOTTOM; |
| 1032 | + int frame_width, frame_height; | |
| 1032 | 1033 | dma_addr_t dma_addr; |
| 1033 | 1034 | u32 flags = 0; |
| 1034 | 1035 | |
| @@ -1055,8 +1056,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port) · 20 unmodified lines | ||
| 1055 | 1056 | if (q_data->flags & Q_DATA_MODE_TILED) |
| 1056 | 1057 | flags |= VPDMA_DATA_MODE_TILED; |
| 1057 | 1058 | |
| 1058 | − vpdma_add_in_dtd(&ctx->desc_list, q_data->width, q_data->height, | |
| 1059 | − c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); | |
| 1059 | + frame_width = q_data->c_rect.width; | |
| 1060 | + frame_height = q_data->c_rect.height; | |
| 1061 | + | |
| 1062 | + if (p_data->vb_part && fmt->fourcc == V4L2_PIX_FMT_NV12) | |
| 1063 | + frame_height /= 2; | |
| 1064 | + | |
| 1065 | + vpdma_add_in_dtd(&ctx->desc_list, q_data->width, &q_data->c_rect, | |
| 1066 | + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, | |
| 1067 | + frame_height, 0, 0); | |
| 1060 | 1068 | } |
| 1061 | 1069 | |
| 1062 | 1070 | /* |
| @@ -1585,6 +1593,151 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · 522 unmodified lines | ||
| 1585 | 1593 | return set_srcdst_params(ctx); |
| 1586 | 1594 | } |
| 1587 | 1595 | |
| 1596 | +static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s) | |
| 1597 | +{ | |
| 1598 | + struct vpe_q_data *q_data; | |
| 1599 | + | |
| 1600 | + if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | |
| 1601 | + (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) | |
| 1602 | + return -EINVAL; | |
| 1603 | + | |
| 1604 | + q_data = get_q_data(ctx, s->type); | |
| 1605 | + if (!q_data) | |
| 1606 | + return -EINVAL; | |
| 1607 | + | |
| 1608 | + switch (s->target) { | |
| 1609 | + case V4L2_SEL_TGT_COMPOSE: | |
| 1610 | + /* | |
| 1611 | + * COMPOSE target is only valid for capture buffer type, return | |
| 1612 | + * error for output buffer type | |
| 1613 | + */ | |
| 1614 | + if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | |
| 1615 | + return -EINVAL; | |
| 1616 | + break; | |
| 1617 | + case V4L2_SEL_TGT_CROP: | |
| 1618 | + /* | |
| 1619 | + * CROP target is only valid for output buffer type, return | |
| 1620 | + * error for capture buffer type | |
| 1621 | + */ | |
| 1622 | + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
| 1623 | + return -EINVAL; | |
| 1624 | + break; | |
| 1625 | + /* | |
| 1626 | + * bound and default crop/compose targets are invalid targets to | |
| 1627 | + * try/set | |
| 1628 | + */ | |
| 1629 | + default: | |
| 1630 | + return -EINVAL; | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + if (s->r.top < 0 || s->r.left < 0) { | |
| 1634 | + vpe_err(ctx->dev, "negative values for top and left\n"); | |
| 1635 | + s->r.top = s->r.left = 0; | |
| 1636 | + } | |
| 1637 | + | |
| 1638 | + v4l_bound_align_image(&s->r.width, MIN_W, q_data->width, 1, | |
| 1639 | + &s->r.height, MIN_H, q_data->height, H_ALIGN, S_ALIGN); | |
| 1640 | + | |
| 1641 | + /* adjust left/top if cropping rectangle is out of bounds */ | |
| 1642 | + if (s->r.left + s->r.width > q_data->width) | |
| 1643 | + s->r.left = q_data->width - s->r.width; | |
| 1644 | + if (s->r.top + s->r.height > q_data->height) | |
| 1645 | + s->r.top = q_data->height - s->r.height; | |
| 1646 | + | |
| 1647 | + return 0; | |
| 1648 | +} | |
| 1649 | + | |
| 1650 | +static int vpe_g_selection(struct file *file, void *fh, | |
| 1651 | + struct v4l2_selection *s) | |
| 1652 | +{ | |
| 1653 | + struct vpe_ctx *ctx = file2ctx(file); | |
| 1654 | + struct vpe_q_data *q_data; | |
| 1655 | + bool use_c_rect = false; | |
| 1656 | + | |
| 1657 | + if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && | |
| 1658 | + (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) | |
| 1659 | + return -EINVAL; | |
| 1660 | + | |
| 1661 | + q_data = get_q_data(ctx, s->type); | |
| 1662 | + if (!q_data) | |
| 1663 | + return -EINVAL; | |
| 1664 | + | |
| 1665 | + switch (s->target) { | |
| 1666 | + case V4L2_SEL_TGT_COMPOSE_DEFAULT: | |
| 1667 | + case V4L2_SEL_TGT_COMPOSE_BOUNDS: | |
| 1668 | + if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | |
| 1669 | + return -EINVAL; | |
| 1670 | + break; | |
| 1671 | + case V4L2_SEL_TGT_CROP_BOUNDS: | |
| 1672 | + case V4L2_SEL_TGT_CROP_DEFAULT: | |
| 1673 | + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
| 1674 | + return -EINVAL; | |
| 1675 | + break; | |
| 1676 | + case V4L2_SEL_TGT_COMPOSE: | |
| 1677 | + if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | |
| 1678 | + return -EINVAL; | |
| 1679 | + use_c_rect = true; | |
| 1680 | + break; | |
| 1681 | + case V4L2_SEL_TGT_CROP: | |
| 1682 | + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
| 1683 | + return -EINVAL; | |
| 1684 | + use_c_rect = true; | |
| 1685 | + break; | |
| 1686 | + default: | |
| 1687 | + return -EINVAL; | |
| 1688 | + } | |
| 1689 | + | |
| 1690 | + if (use_c_rect) { | |
| 1691 | + /* | |
| 1692 | + * for CROP/COMPOSE target type, return c_rect params from the | |
| 1693 | + * respective buffer type | |
| 1694 | + */ | |
| 1695 | + s->r = q_data->c_rect; | |
| 1696 | + } else { | |
| 1697 | + /* | |
| 1698 | + * for DEFAULT/BOUNDS target type, return width and height from | |
| 1699 | + * S_FMT of the respective buffer type | |
| 1700 | + */ | |
| 1701 | + s->r.left = 0; | |
| 1702 | + s->r.top = 0; | |
| 1703 | + s->r.width = q_data->width; | |
| 1704 | + s->r.height = q_data->height; | |
| 1705 | + } | |
| 1706 | + | |
| 1707 | + return 0; | |
| 1708 | +} | |
| 1709 | + | |
| 1710 | + | |
| 1711 | +static int vpe_s_selection(struct file *file, void *fh, | |
| 1712 | + struct v4l2_selection *s) | |
| 1713 | +{ | |
| 1714 | + struct vpe_ctx *ctx = file2ctx(file); | |
| 1715 | + struct vpe_q_data *q_data; | |
| 1716 | + struct v4l2_selection sel = *s; | |
| 1717 | + int ret; | |
| 1718 | + | |
| 1719 | + ret = __vpe_try_selection(ctx, &sel); | |
| 1720 | + if (ret) | |
| 1721 | + return ret; | |
| 1722 | + | |
| 1723 | + q_data = get_q_data(ctx, sel.type); | |
| 1724 | + if (!q_data) | |
| 1725 | + return -EINVAL; | |
| 1726 | + | |
| 1727 | + if ((q_data->c_rect.left == sel.r.left) && | |
| 1728 | + (q_data->c_rect.top == sel.r.top) && | |
| 1729 | + (q_data->c_rect.width == sel.r.width) && | |
| 1730 | + (q_data->c_rect.height == sel.r.height)) { | |
| 1731 | + vpe_dbg(ctx->dev, | |
| 1732 | + "requested crop/compose values are already set\n"); | |
| 1733 | + return 0; | |
| 1734 | + } | |
| 1735 | + | |
| 1736 | + q_data->c_rect = sel.r; | |
| 1737 | + | |
| 1738 | + return set_srcdst_params(ctx); | |
| 1739 | +} | |
| 1740 | + | |
| 1588 | 1741 | static int vpe_reqbufs(struct file *file, void *priv, |
| 1589 | 1742 | struct v4l2_requestbuffers *reqbufs) |
| 1590 | 1743 | { |
| @@ -1672,6 +1825,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { · 81 unmodified lines | ||
| 1672 | 1825 | .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, |
| 1673 | 1826 | .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, |
| 1674 | 1827 | |
| 1828 | + .vidioc_g_selection = vpe_g_selection, | |
| 1829 | + .vidioc_s_selection = vpe_s_selection, | |
| 1830 | + | |
| 1675 | 1831 | .vidioc_reqbufs = vpe_reqbufs, |
| 1676 | 1832 | .vidioc_querybuf = vpe_querybuf, |
| 1677 | 1833 | |
| @@ -1784,7 +1940,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, · 106 unmodified lines | ||
| 1784 | 1940 | |
| 1785 | 1941 | memset(src_vq, 0, sizeof(*src_vq)); |
| 1786 | 1942 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1787 | − src_vq->io_modes = VB2_MMAP; | |
| 1943 | + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; | |
| 1788 | 1944 | src_vq->drv_priv = ctx; |
| 1789 | 1945 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); |
| 1790 | 1946 | src_vq->ops = &vpe_qops; |
| @@ -1797,7 +1953,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, · 6 unmodified lines | ||
| 1797 | 1953 | |
| 1798 | 1954 | memset(dst_vq, 0, sizeof(*dst_vq)); |
| 1799 | 1955 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1800 | − dst_vq->io_modes = VB2_MMAP; | |
| 1956 | + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; | |
| 1801 | 1957 | dst_vq->drv_priv = ctx; |
| 1802 | 1958 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); |
| 1803 | 1959 | dst_vq->ops = &vpe_qops; |
| @@ -1831,11 +1987,6 @@ static int vpe_open(struct file *file) · 27 unmodified lines | ||
| 1831 | 1987 | |
| 1832 | 1988 | vpe_dbg(dev, "vpe_open\n"); |
| 1833 | 1989 | |
| 1834 | − if (!dev->vpdma->ready) { | |
| 1835 | − vpe_err(dev, "vpdma firmware not loaded\n"); | |
| 1836 | − return -ENODEV; | |
| 1837 | − } | |
| 1838 | − | |
| 1839 | 1990 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
| 1840 | 1991 | if (!ctx) |
| 1841 | 1992 | return -ENOMEM; |
| @@ -2055,10 +2206,40 @@ static void vpe_runtime_put(struct platform_device *pdev) · 213 unmodified lines | ||
| 2055 | 2206 | WARN_ON(r < 0 && r != -ENOSYS); |
| 2056 | 2207 | } |
| 2057 | 2208 | |
| 2209 | +static void vpe_fw_cb(struct platform_device *pdev) | |
| 2210 | +{ | |
| 2211 | + struct vpe_dev *dev = platform_get_drvdata(pdev); | |
| 2212 | + struct video_device *vfd; | |
| 2213 | + int ret; | |
| 2214 | + | |
| 2215 | + vfd = &dev->vfd; | |
| 2216 | + *vfd = vpe_videodev; | |
| 2217 | + vfd->lock = &dev->dev_mutex; | |
| 2218 | + vfd->v4l2_dev = &dev->v4l2_dev; | |
| 2219 | + | |
| 2220 | + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | |
| 2221 | + if (ret) { | |
| 2222 | + vpe_err(dev, "Failed to register video device\n"); | |
| 2223 | + | |
| 2224 | + vpe_set_clock_enable(dev, 0); | |
| 2225 | + vpe_runtime_put(pdev); | |
| 2226 | + pm_runtime_disable(&pdev->dev); | |
| 2227 | + v4l2_m2m_release(dev->m2m_dev); | |
| 2228 | + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | |
| 2229 | + v4l2_device_unregister(&dev->v4l2_dev); | |
| 2230 | + | |
| 2231 | + return; | |
| 2232 | + } | |
| 2233 | + | |
| 2234 | + video_set_drvdata(vfd, dev); | |
| 2235 | + snprintf(vfd->name, sizeof(vfd->name), "%s", vpe_videodev.name); | |
| 2236 | + dev_info(dev->v4l2_dev.dev, "Device registered as /dev/video%d\n", | |
| 2237 | + vfd->num); | |
| 2238 | +} | |
| 2239 | + | |
| 2058 | 2240 | static int vpe_probe(struct platform_device *pdev) |
| 2059 | 2241 | { |
| 2060 | 2242 | struct vpe_dev *dev; |
| 2061 | − struct video_device *vfd; | |
| 2062 | 2243 | int ret, irq, func; |
| 2063 | 2244 | |
| 2064 | 2245 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); |
| @@ -2139,28 +2320,12 @@ static int vpe_probe(struct platform_device *pdev) · 74 unmodified lines | ||
| 2139 | 2320 | goto runtime_put; |
| 2140 | 2321 | } |
| 2141 | 2322 | |
| 2142 | − dev->vpdma = vpdma_create(pdev); | |
| 2323 | + dev->vpdma = vpdma_create(pdev, vpe_fw_cb); | |
| 2143 | 2324 | if (IS_ERR(dev->vpdma)) { |
| 2144 | 2325 | ret = PTR_ERR(dev->vpdma); |
| 2145 | 2326 | goto runtime_put; |
| 2146 | 2327 | } |
| 2147 | 2328 | |
| 2148 | − vfd = &dev->vfd; | |
| 2149 | − *vfd = vpe_videodev; | |
| 2150 | − vfd->lock = &dev->dev_mutex; | |
| 2151 | − vfd->v4l2_dev = &dev->v4l2_dev; | |
| 2152 | − | |
| 2153 | − ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | |
| 2154 | − if (ret) { | |
| 2155 | − vpe_err(dev, "Failed to register video device\n"); | |
| 2156 | − goto runtime_put; | |
| 2157 | − } | |
| 2158 | − | |
| 2159 | − video_set_drvdata(vfd, dev); | |
| 2160 | − snprintf(vfd->name, sizeof(vfd->name), "%s", vpe_videodev.name); | |
| 2161 | − dev_info(dev->v4l2_dev.dev, "Device registered as /dev/video%d\n", | |
| 2162 | − vfd->num); | |
| 2163 | − | |
| 2164 | 2329 | return 0; |
| 2165 | 2330 | |
| 2166 | 2331 | runtime_put: |
| @@ -347,7 +347,7 @@ static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id std) · 346 unmodified lines | ||
| 347 | 347 | mutex_lock(&lw->lock); |
| 348 | 348 | |
| 349 | 349 | if (TIMBLOGIW_HAS_DECODER(lw)) |
| 350 | − err = v4l2_subdev_call(lw->sd_enc, core, s_std, std); | |
| 350 | + err = v4l2_subdev_call(lw->sd_enc, video, s_std, std); | |
| 351 | 351 | |
| 352 | 352 | if (!err) |
| 353 | 353 | fh->cur_norm = timblogiw_get_norm(std); |
| @@ -800,7 +800,7 @@ static int timblogiw_probe(struct platform_device *pdev) · 446 unmodified lines | ||
| 800 | 800 | if (!pdata->encoder.module_name) |
| 801 | 801 | dev_info(&pdev->dev, "Running without decoder\n"); |
| 802 | 802 | |
| 803 | − lw = kzalloc(sizeof(*lw), GFP_KERNEL); | |
| 803 | + lw = devm_kzalloc(&pdev->dev, sizeof(*lw), GFP_KERNEL); | |
| 804 | 804 | if (!lw) { |
| 805 | 805 | err = -ENOMEM; |
| 806 | 806 | goto err; |
| @@ -820,7 +820,7 @@ static int timblogiw_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 820 | 820 | strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name)); |
| 821 | 821 | err = v4l2_device_register(NULL, &lw->v4l2_dev); |
| 822 | 822 | if (err) |
| 823 | − goto err_register; | |
| 823 | + goto err; | |
| 824 | 824 | |
| 825 | 825 | lw->video_dev.v4l2_dev = &lw->v4l2_dev; |
| 826 | 826 | |
| @@ -837,8 +837,6 @@ static int timblogiw_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 837 | 837 | |
| 838 | 838 | err_request: |
| 839 | 839 | v4l2_device_unregister(&lw->v4l2_dev); |
| 840 | −err_register: | |
| 841 | − kfree(lw); | |
| 842 | 840 | err: |
| 843 | 841 | dev_err(&pdev->dev, "Failed to register: %d\n", err); |
| 844 | 842 | |
| @@ -853,8 +851,6 @@ static int timblogiw_remove(struct platform_device *pdev) · 8 unmodified lines | ||
| 853 | 851 | |
| 854 | 852 | v4l2_device_unregister(&lw->v4l2_dev); |
| 855 | 853 | |
| 856 | − kfree(lw); | |
| 857 | − | |
| 858 | 854 | return 0; |
| 859 | 855 | } |
| 860 | 856 | |
| @@ -2586,7 +2586,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) · 2585 unmodified lines | ||
| 2586 | 2586 | } |
| 2587 | 2587 | if (data_norm == 3) |
| 2588 | 2588 | data_norm = VINO_DATA_NORM_PAL; |
| 2589 | − ret = decoder_call(core, s_std, norm); | |
| 2589 | + ret = decoder_call(video, s_std, norm); | |
| 2590 | 2590 | } |
| 2591 | 2591 | |
| 2592 | 2592 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
| @@ -2675,7 +2675,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) · 82 unmodified lines | ||
| 2675 | 2675 | } |
| 2676 | 2676 | if (data_norm == 3) |
| 2677 | 2677 | data_norm = VINO_DATA_NORM_PAL; |
| 2678 | − ret = decoder_call(core, s_std, norm); | |
| 2678 | + ret = decoder_call(video, s_std, norm); | |
| 2679 | 2679 | } |
| 2680 | 2680 | |
| 2681 | 2681 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
| @@ -2809,7 +2809,7 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, · 127 unmodified lines | ||
| 2809 | 2809 | * as it may take a while... */ |
| 2810 | 2810 | |
| 2811 | 2811 | norm = vino_data_norms[data_norm].std; |
| 2812 | − err = decoder_call(core, s_std, norm); | |
| 2812 | + err = decoder_call(video, s_std, norm); | |
| 2813 | 2813 | |
| 2814 | 2814 | spin_lock_irqsave(&vino_drvdata->input_lock, *flags); |
| 2815 | 2815 | |
| @@ -906,12 +906,11 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 905 unmodified lines | ||
| 906 | 906 | } |
| 907 | 907 | |
| 908 | 908 | /* abort streaming and wait for last buffer */ |
| 909 | −static int stop_streaming(struct vb2_queue *vq) | |
| 909 | +static void stop_streaming(struct vb2_queue *vq) | |
| 910 | 910 | { |
| 911 | 911 | struct vivi_dev *dev = vb2_get_drv_priv(vq); |
| 912 | 912 | dprintk(dev, 1, "%s\n", __func__); |
| 913 | 913 | vivi_stop_generating(dev); |
| 914 | − return 0; | |
| 915 | 914 | } |
| 916 | 915 | |
| 917 | 916 | static void vivi_lock(struct vb2_queue *vq) |
| @@ -720,7 +720,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) · 719 unmodified lines | ||
| 720 | 720 | return 0; |
| 721 | 721 | } |
| 722 | 722 | |
| 723 | −static int vsp1_video_stop_streaming(struct vb2_queue *vq) | |
| 723 | +static void vsp1_video_stop_streaming(struct vb2_queue *vq) | |
| 724 | 724 | { |
| 725 | 725 | struct vsp1_video *video = vb2_get_drv_priv(vq); |
| 726 | 726 | struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); |
| @@ -743,8 +743,6 @@ static int vsp1_video_stop_streaming(struct vb2_queue *vq) · 16 unmodified lines | ||
| 743 | 743 | spin_lock_irqsave(&video->irqlock, flags); |
| 744 | 744 | INIT_LIST_HEAD(&video->irqqueue); |
| 745 | 745 | spin_unlock_irqrestore(&video->irqlock, flags); |
| 746 | − | |
| 747 | − return 0; | |
| 748 | 746 | } |
| 749 | 747 | |
| 750 | 748 | static struct vb2_ops vsp1_video_queue_qops = { |
| @@ -747,11 +747,19 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, · 746 unmodified lines | ||
| 747 | 747 | } |
| 748 | 748 | |
| 749 | 749 | /* outbound data */ |
| 750 | − pipe = usb_sndintpipe(ir->usbdev, | |
| 751 | − ir->usb_ep_out->bEndpointAddress); | |
| 752 | − usb_fill_int_urb(async_urb, ir->usbdev, pipe, | |
| 753 | − async_buf, size, mce_async_callback, | |
| 754 | − ir, ir->usb_ep_out->bInterval); | |
| 750 | + if (usb_endpoint_xfer_int(ir->usb_ep_out)) { | |
| 751 | + pipe = usb_sndintpipe(ir->usbdev, | |
| 752 | + ir->usb_ep_out->bEndpointAddress); | |
| 753 | + usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf, | |
| 754 | + size, mce_async_callback, ir, | |
| 755 | + ir->usb_ep_out->bInterval); | |
| 756 | + } else { | |
| 757 | + pipe = usb_sndbulkpipe(ir->usbdev, | |
| 758 | + ir->usb_ep_out->bEndpointAddress); | |
| 759 | + usb_fill_bulk_urb(async_urb, ir->usbdev, pipe, | |
| 760 | + async_buf, size, mce_async_callback, | |
| 761 | + ir); | |
| 762 | + } | |
| 755 | 763 | memcpy(async_buf, data, size); |
| 756 | 764 | |
| 757 | 765 | } else if (urb_type == MCEUSB_RX) { |
| @@ -1269,32 +1277,26 @@ static int mceusb_dev_probe(struct usb_interface *intf, · 511 unmodified lines | ||
| 1269 | 1277 | for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { |
| 1270 | 1278 | ep = &idesc->endpoint[i].desc; |
| 1271 | 1279 | |
| 1272 | − if ((ep_in == NULL) | |
| 1273 | − && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | |
| 1274 | − == USB_DIR_IN) | |
| 1275 | − && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 1276 | − == USB_ENDPOINT_XFER_BULK) | |
| 1277 | − || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 1278 | − == USB_ENDPOINT_XFER_INT))) { | |
| 1279 | − | |
| 1280 | − ep_in = ep; | |
| 1281 | − ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; | |
| 1282 | − ep_in->bInterval = 1; | |
| 1283 | − dev_dbg(&intf->dev, "acceptable inbound endpoint found"); | |
| 1280 | + if (ep_in == NULL) { | |
| 1281 | + if (usb_endpoint_is_bulk_in(ep)) { | |
| 1282 | + ep_in = ep; | |
| 1283 | + dev_dbg(&intf->dev, "acceptable bulk inbound endpoint found\n"); | |
| 1284 | + } else if (usb_endpoint_is_int_in(ep)) { | |
| 1285 | + ep_in = ep; | |
| 1286 | + ep_in->bInterval = 1; | |
| 1287 | + dev_dbg(&intf->dev, "acceptable interrupt inbound endpoint found\n"); | |
| 1288 | + } | |
| 1284 | 1289 | } |
| 1285 | 1290 | |
| 1286 | − if ((ep_out == NULL) | |
| 1287 | − && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | |
| 1288 | − == USB_DIR_OUT) | |
| 1289 | − && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 1290 | − == USB_ENDPOINT_XFER_BULK) | |
| 1291 | − || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | |
| 1292 | − == USB_ENDPOINT_XFER_INT))) { | |
| 1293 | − | |
| 1294 | − ep_out = ep; | |
| 1295 | − ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; | |
| 1296 | − ep_out->bInterval = 1; | |
| 1297 | − dev_dbg(&intf->dev, "acceptable outbound endpoint found"); | |
| 1291 | + if (ep_out == NULL) { | |
| 1292 | + if (usb_endpoint_is_bulk_out(ep)) { | |
| 1293 | + ep_out = ep; | |
| 1294 | + dev_dbg(&intf->dev, "acceptable bulk outbound endpoint found\n"); | |
| 1295 | + } else if (usb_endpoint_is_int_out(ep)) { | |
| 1296 | + ep_out = ep; | |
| 1297 | + ep_out->bInterval = 1; | |
| 1298 | + dev_dbg(&intf->dev, "acceptable interrupt outbound endpoint found\n"); | |
| 1299 | + } | |
| 1298 | 1300 | } |
| 1299 | 1301 | } |
| 1300 | 1302 | if (ep_in == NULL) { |
| @@ -1302,7 +1304,10 @@ static int mceusb_dev_probe(struct usb_interface *intf, · 1 unmodified line | ||
| 1302 | 1304 | return -ENODEV; |
| 1303 | 1305 | } |
| 1304 | 1306 | |
| 1305 | − pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); | |
| 1307 | + if (usb_endpoint_xfer_int(ep_in)) | |
| 1308 | + pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); | |
| 1309 | + else | |
| 1310 | + pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress); | |
| 1306 | 1311 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
| 1307 | 1312 | |
| 1308 | 1313 | ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); |
| @@ -230,6 +230,13 @@ config MEDIA_TUNER_TUA9001 · 229 unmodified lines | ||
| 230 | 230 | help |
| 231 | 231 | Infineon TUA 9001 silicon tuner driver. |
| 232 | 232 | |
| 233 | +config MEDIA_TUNER_SI2157 | |
| 234 | + tristate "Silicon Labs Si2157 silicon tuner" | |
| 235 | + depends on MEDIA_SUPPORT && I2C | |
| 236 | + default m if !MEDIA_SUBDRV_AUTOSELECT | |
| 237 | + help | |
| 238 | + Silicon Labs Si2157 silicon tuner driver. | |
| 239 | + | |
| 233 | 240 | config MEDIA_TUNER_IT913X |
| 234 | 241 | tristate "ITE Tech IT913x silicon tuner" |
| 235 | 242 | depends on MEDIA_SUPPORT && I2C |
| @@ -31,6 +31,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o · 30 unmodified lines | ||
| 31 | 31 | obj-$(CONFIG_MEDIA_TUNER_E4000) += e4000.o |
| 32 | 32 | obj-$(CONFIG_MEDIA_TUNER_FC2580) += fc2580.o |
| 33 | 33 | obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o |
| 34 | +obj-$(CONFIG_MEDIA_TUNER_SI2157) += si2157.o | |
| 34 | 35 | obj-$(CONFIG_MEDIA_TUNER_M88TS2022) += m88ts2022.o |
| 35 | 36 | obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o |
| 36 | 37 | obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o |
| @@ -0,0 +1,260 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2157 silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#include "si2157_priv.h" | |
| 18 | + | |
| 19 | +/* execute firmware command */ | |
| 20 | +static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd) | |
| 21 | +{ | |
| 22 | + int ret; | |
| 23 | + u8 buf[1]; | |
| 24 | + unsigned long timeout; | |
| 25 | + | |
| 26 | + mutex_lock(&s->i2c_mutex); | |
| 27 | + | |
| 28 | + if (cmd->len) { | |
| 29 | + /* write cmd and args for firmware */ | |
| 30 | + ret = i2c_master_send(s->client, cmd->args, cmd->len); | |
| 31 | + if (ret < 0) { | |
| 32 | + goto err_mutex_unlock; | |
| 33 | + } else if (ret != cmd->len) { | |
| 34 | + ret = -EREMOTEIO; | |
| 35 | + goto err_mutex_unlock; | |
| 36 | + } | |
| 37 | + } | |
| 38 | + | |
| 39 | + /* wait cmd execution terminate */ | |
| 40 | + #define TIMEOUT 80 | |
| 41 | + timeout = jiffies + msecs_to_jiffies(TIMEOUT); | |
| 42 | + while (!time_after(jiffies, timeout)) { | |
| 43 | + ret = i2c_master_recv(s->client, buf, 1); | |
| 44 | + if (ret < 0) { | |
| 45 | + goto err_mutex_unlock; | |
| 46 | + } else if (ret != 1) { | |
| 47 | + ret = -EREMOTEIO; | |
| 48 | + goto err_mutex_unlock; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /* firmware ready? */ | |
| 52 | + if ((buf[0] >> 7) & 0x01) | |
| 53 | + break; | |
| 54 | + } | |
| 55 | + | |
| 56 | + dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", __func__, | |
| 57 | + jiffies_to_msecs(jiffies) - | |
| 58 | + (jiffies_to_msecs(timeout) - TIMEOUT)); | |
| 59 | + | |
| 60 | + if (!(buf[0] >> 7) & 0x01) { | |
| 61 | + ret = -ETIMEDOUT; | |
| 62 | + goto err_mutex_unlock; | |
| 63 | + } else { | |
| 64 | + ret = 0; | |
| 65 | + } | |
| 66 | + | |
| 67 | +err_mutex_unlock: | |
| 68 | + mutex_unlock(&s->i2c_mutex); | |
| 69 | + if (ret) | |
| 70 | + goto err; | |
| 71 | + | |
| 72 | + return 0; | |
| 73 | +err: | |
| 74 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 75 | + return ret; | |
| 76 | +} | |
| 77 | + | |
| 78 | +static int si2157_init(struct dvb_frontend *fe) | |
| 79 | +{ | |
| 80 | + struct si2157 *s = fe->tuner_priv; | |
| 81 | + | |
| 82 | + dev_dbg(&s->client->dev, "%s:\n", __func__); | |
| 83 | + | |
| 84 | + s->active = true; | |
| 85 | + | |
| 86 | + return 0; | |
| 87 | +} | |
| 88 | + | |
| 89 | +static int si2157_sleep(struct dvb_frontend *fe) | |
| 90 | +{ | |
| 91 | + struct si2157 *s = fe->tuner_priv; | |
| 92 | + | |
| 93 | + dev_dbg(&s->client->dev, "%s:\n", __func__); | |
| 94 | + | |
| 95 | + s->active = false; | |
| 96 | + | |
| 97 | + return 0; | |
| 98 | +} | |
| 99 | + | |
| 100 | +static int si2157_set_params(struct dvb_frontend *fe) | |
| 101 | +{ | |
| 102 | + struct si2157 *s = fe->tuner_priv; | |
| 103 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 104 | + int ret; | |
| 105 | + struct si2157_cmd cmd; | |
| 106 | + | |
| 107 | + dev_dbg(&s->client->dev, | |
| 108 | + "%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n", | |
| 109 | + __func__, c->delivery_system, c->frequency, | |
| 110 | + c->bandwidth_hz); | |
| 111 | + | |
| 112 | + if (!s->active) { | |
| 113 | + ret = -EAGAIN; | |
| 114 | + goto err; | |
| 115 | + } | |
| 116 | + | |
| 117 | + /* configure? */ | |
| 118 | + cmd.args[0] = 0xc0; | |
| 119 | + cmd.args[1] = 0x00; | |
| 120 | + cmd.args[2] = 0x0c; | |
| 121 | + cmd.args[3] = 0x00; | |
| 122 | + cmd.args[4] = 0x00; | |
| 123 | + cmd.args[5] = 0x01; | |
| 124 | + cmd.args[6] = 0x01; | |
| 125 | + cmd.args[7] = 0x01; | |
| 126 | + cmd.args[8] = 0x01; | |
| 127 | + cmd.args[9] = 0x01; | |
| 128 | + cmd.args[10] = 0x01; | |
| 129 | + cmd.args[11] = 0x02; | |
| 130 | + cmd.args[12] = 0x00; | |
| 131 | + cmd.args[13] = 0x00; | |
| 132 | + cmd.args[14] = 0x01; | |
| 133 | + cmd.len = 15; | |
| 134 | + ret = si2157_cmd_execute(s, &cmd); | |
| 135 | + if (ret) | |
| 136 | + goto err; | |
| 137 | + | |
| 138 | + cmd.args[0] = 0x02; | |
| 139 | + cmd.len = 1; | |
| 140 | + ret = si2157_cmd_execute(s, &cmd); | |
| 141 | + if (ret) | |
| 142 | + goto err; | |
| 143 | + | |
| 144 | + cmd.args[0] = 0x01; | |
| 145 | + cmd.args[1] = 0x01; | |
| 146 | + cmd.len = 2; | |
| 147 | + ret = si2157_cmd_execute(s, &cmd); | |
| 148 | + if (ret) | |
| 149 | + goto err; | |
| 150 | + | |
| 151 | + /* set frequency */ | |
| 152 | + cmd.args[0] = 0x41; | |
| 153 | + cmd.args[1] = 0x00; | |
| 154 | + cmd.args[2] = 0x00; | |
| 155 | + cmd.args[3] = 0x00; | |
| 156 | + cmd.args[4] = (c->frequency >> 0) & 0xff; | |
| 157 | + cmd.args[5] = (c->frequency >> 8) & 0xff; | |
| 158 | + cmd.args[6] = (c->frequency >> 16) & 0xff; | |
| 159 | + cmd.args[7] = (c->frequency >> 24) & 0xff; | |
| 160 | + cmd.len = 8; | |
| 161 | + ret = si2157_cmd_execute(s, &cmd); | |
| 162 | + if (ret) | |
| 163 | + goto err; | |
| 164 | + | |
| 165 | + return 0; | |
| 166 | +err: | |
| 167 | + dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret); | |
| 168 | + return ret; | |
| 169 | +} | |
| 170 | + | |
| 171 | +static const struct dvb_tuner_ops si2157_tuner_ops = { | |
| 172 | + .info = { | |
| 173 | + .name = "Silicon Labs Si2157", | |
| 174 | + .frequency_min = 110000000, | |
| 175 | + .frequency_max = 862000000, | |
| 176 | + }, | |
| 177 | + | |
| 178 | + .init = si2157_init, | |
| 179 | + .sleep = si2157_sleep, | |
| 180 | + .set_params = si2157_set_params, | |
| 181 | +}; | |
| 182 | + | |
| 183 | +static int si2157_probe(struct i2c_client *client, | |
| 184 | + const struct i2c_device_id *id) | |
| 185 | +{ | |
| 186 | + struct si2157_config *cfg = client->dev.platform_data; | |
| 187 | + struct dvb_frontend *fe = cfg->fe; | |
| 188 | + struct si2157 *s; | |
| 189 | + struct si2157_cmd cmd; | |
| 190 | + int ret; | |
| 191 | + | |
| 192 | + s = kzalloc(sizeof(struct si2157), GFP_KERNEL); | |
| 193 | + if (!s) { | |
| 194 | + ret = -ENOMEM; | |
| 195 | + dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | |
| 196 | + goto err; | |
| 197 | + } | |
| 198 | + | |
| 199 | + s->client = client; | |
| 200 | + s->fe = cfg->fe; | |
| 201 | + mutex_init(&s->i2c_mutex); | |
| 202 | + | |
| 203 | + /* check if the tuner is there */ | |
| 204 | + cmd.len = 0; | |
| 205 | + ret = si2157_cmd_execute(s, &cmd); | |
| 206 | + if (ret) | |
| 207 | + goto err; | |
| 208 | + | |
| 209 | + fe->tuner_priv = s; | |
| 210 | + memcpy(&fe->ops.tuner_ops, &si2157_tuner_ops, | |
| 211 | + sizeof(struct dvb_tuner_ops)); | |
| 212 | + | |
| 213 | + i2c_set_clientdata(client, s); | |
| 214 | + | |
| 215 | + dev_info(&s->client->dev, | |
| 216 | + "%s: Silicon Labs Si2157 successfully attached\n", | |
| 217 | + KBUILD_MODNAME); | |
| 218 | + return 0; | |
| 219 | +err: | |
| 220 | + dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret); | |
| 221 | + kfree(s); | |
| 222 | + | |
| 223 | + return ret; | |
| 224 | +} | |
| 225 | + | |
| 226 | +static int si2157_remove(struct i2c_client *client) | |
| 227 | +{ | |
| 228 | + struct si2157 *s = i2c_get_clientdata(client); | |
| 229 | + struct dvb_frontend *fe = s->fe; | |
| 230 | + | |
| 231 | + dev_dbg(&client->dev, "%s:\n", __func__); | |
| 232 | + | |
| 233 | + memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); | |
| 234 | + fe->tuner_priv = NULL; | |
| 235 | + kfree(s); | |
| 236 | + | |
| 237 | + return 0; | |
| 238 | +} | |
| 239 | + | |
| 240 | +static const struct i2c_device_id si2157_id[] = { | |
| 241 | + {"si2157", 0}, | |
| 242 | + {} | |
| 243 | +}; | |
| 244 | +MODULE_DEVICE_TABLE(i2c, si2157_id); | |
| 245 | + | |
| 246 | +static struct i2c_driver si2157_driver = { | |
| 247 | + .driver = { | |
| 248 | + .owner = THIS_MODULE, | |
| 249 | + .name = "si2157", | |
| 250 | + }, | |
| 251 | + .probe = si2157_probe, | |
| 252 | + .remove = si2157_remove, | |
| 253 | + .id_table = si2157_id, | |
| 254 | +}; | |
| 255 | + | |
| 256 | +module_i2c_driver(si2157_driver); | |
| 257 | + | |
| 258 | +MODULE_DESCRIPTION("Silicon Labs Si2157 silicon tuner driver"); | |
| 259 | +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
| 260 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,34 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2157 silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef SI2157_H | |
| 18 | +#define SI2157_H | |
| 19 | + | |
| 20 | +#include <linux/kconfig.h> | |
| 21 | +#include "dvb_frontend.h" | |
| 22 | + | |
| 23 | +/* | |
| 24 | + * I2C address | |
| 25 | + * 0x60 | |
| 26 | + */ | |
| 27 | +struct si2157_config { | |
| 28 | + /* | |
| 29 | + * frontend | |
| 30 | + */ | |
| 31 | + struct dvb_frontend *fe; | |
| 32 | +}; | |
| 33 | + | |
| 34 | +#endif | |
| @@ -0,0 +1,37 @@ | ||
| 1 | +/* | |
| 2 | + * Silicon Labs Si2157 silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef SI2157_PRIV_H | |
| 18 | +#define SI2157_PRIV_H | |
| 19 | + | |
| 20 | +#include "si2157.h" | |
| 21 | + | |
| 22 | +/* state struct */ | |
| 23 | +struct si2157 { | |
| 24 | + struct mutex i2c_mutex; | |
| 25 | + struct i2c_client *client; | |
| 26 | + struct dvb_frontend *fe; | |
| 27 | + bool active; | |
| 28 | +}; | |
| 29 | + | |
| 30 | +/* firmare command struct */ | |
| 31 | +#define SI2157_ARGLEN 30 | |
| 32 | +struct si2157_cmd { | |
| 33 | + u8 args[SI2157_ARGLEN]; | |
| 34 | + unsigned len; | |
| 35 | +}; | |
| 36 | + | |
| 37 | +#endif | |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/moduleparam.h> |
| 26 | 26 | #include <linux/videodev2.h> |
| 27 | 27 | #include <linux/delay.h> |
| 28 | +#include <linux/workqueue.h> | |
| 28 | 29 | #include <linux/dvb/frontend.h> |
| 29 | 30 | #include <linux/i2c.h> |
| 30 | 31 | |
| @@ -65,26 +66,25 @@ struct xc5000_priv { · 34 unmodified lines | ||
| 65 | 66 | u16 pll_register_no; |
| 66 | 67 | u8 init_status_supported; |
| 67 | 68 | u8 fw_checksum_supported; |
| 69 | + | |
| 70 | + struct dvb_frontend *fe; | |
| 71 | + struct delayed_work timer_sleep; | |
| 68 | 72 | }; |
| 69 | 73 | |
| 70 | 74 | /* Misc Defines */ |
| 71 | 75 | #define MAX_TV_STANDARD 24 |
| 72 | 76 | #define XC_MAX_I2C_WRITE_LENGTH 64 |
| 73 | 77 | |
| 78 | +/* Time to suspend after the .sleep callback is called */ | |
| 79 | +#define XC5000_SLEEP_TIME 5000 /* ms */ | |
| 80 | + | |
| 74 | 81 | /* Signal Types */ |
| 75 | 82 | #define XC_RF_MODE_AIR 0 |
| 76 | 83 | #define XC_RF_MODE_CABLE 1 |
| 77 | 84 | |
| 78 | −/* Result codes */ | |
| 79 | −#define XC_RESULT_SUCCESS 0 | |
| 80 | −#define XC_RESULT_RESET_FAILURE 1 | |
| 81 | −#define XC_RESULT_I2C_WRITE_FAILURE 2 | |
| 82 | −#define XC_RESULT_I2C_READ_FAILURE 3 | |
| 83 | −#define XC_RESULT_OUT_OF_RANGE 5 | |
| 84 | − | |
| 85 | 85 | /* Product id */ |
| 86 | 86 | #define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 |
| 87 | −#define XC_PRODUCT_ID_FW_LOADED 0x1388 | |
| 87 | +#define XC_PRODUCT_ID_FW_LOADED 0x1388 | |
| 88 | 88 | |
| 89 | 89 | /* Registers */ |
| 90 | 90 | #define XREG_INIT 0x00 |
| @@ -152,16 +152,16 @@ struct xc5000_priv { · 61 unmodified lines | ||
| 152 | 152 | |
| 153 | 153 | */ |
| 154 | 154 | struct XC_TV_STANDARD { |
| 155 | − char *Name; | |
| 156 | − u16 AudioMode; | |
| 157 | − u16 VideoMode; | |
| 155 | + char *name; | |
| 156 | + u16 audio_mode; | |
| 157 | + u16 video_mode; | |
| 158 | 158 | }; |
| 159 | 159 | |
| 160 | 160 | /* Tuner standards */ |
| 161 | 161 | #define MN_NTSC_PAL_BTSC 0 |
| 162 | 162 | #define MN_NTSC_PAL_A2 1 |
| 163 | 163 | #define MN_NTSC_PAL_EIAJ 2 |
| 164 | −#define MN_NTSC_PAL_Mono 3 | |
| 164 | +#define MN_NTSC_PAL_MONO 3 | |
| 165 | 165 | #define BG_PAL_A2 4 |
| 166 | 166 | #define BG_PAL_NICAM 5 |
| 167 | 167 | #define BG_PAL_MONO 6 |
| @@ -171,19 +171,19 @@ struct XC_TV_STANDARD { · 3 unmodified lines | ||
| 171 | 171 | #define DK_PAL_NICAM 10 |
| 172 | 172 | #define DK_PAL_MONO 11 |
| 173 | 173 | #define DK_SECAM_A2DK1 12 |
| 174 | −#define DK_SECAM_A2LDK3 13 | |
| 175 | −#define DK_SECAM_A2MONO 14 | |
| 174 | +#define DK_SECAM_A2LDK3 13 | |
| 175 | +#define DK_SECAM_A2MONO 14 | |
| 176 | 176 | #define L_SECAM_NICAM 15 |
| 177 | 177 | #define LC_SECAM_NICAM 16 |
| 178 | 178 | #define DTV6 17 |
| 179 | 179 | #define DTV8 18 |
| 180 | 180 | #define DTV7_8 19 |
| 181 | 181 | #define DTV7 20 |
| 182 | −#define FM_Radio_INPUT2 21 | |
| 183 | −#define FM_Radio_INPUT1 22 | |
| 184 | −#define FM_Radio_INPUT1_MONO 23 | |
| 182 | +#define FM_RADIO_INPUT2 21 | |
| 183 | +#define FM_RADIO_INPUT1 22 | |
| 184 | +#define FM_RADIO_INPUT1_MONO 23 | |
| 185 | 185 | |
| 186 | −static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | |
| 186 | +static struct XC_TV_STANDARD xc5000_standard[MAX_TV_STANDARD] = { | |
| 187 | 187 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, |
| 188 | 188 | {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, |
| 189 | 189 | {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, |
| @@ -249,7 +249,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) · 59 unmodified lines | ||
| 249 | 249 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force); |
| 250 | 250 | static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); |
| 251 | 251 | static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); |
| 252 | −static int xc5000_TunerReset(struct dvb_frontend *fe); | |
| 252 | +static int xc5000_tuner_reset(struct dvb_frontend *fe); | |
| 253 | 253 | |
| 254 | 254 | static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) |
| 255 | 255 | { |
| @@ -258,9 +258,9 @@ static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) · 2 unmodified lines | ||
| 258 | 258 | |
| 259 | 259 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
| 260 | 260 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len); |
| 261 | − return XC_RESULT_I2C_WRITE_FAILURE; | |
| 261 | + return -EREMOTEIO; | |
| 262 | 262 | } |
| 263 | − return XC_RESULT_SUCCESS; | |
| 263 | + return 0; | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | #if 0 |
| @@ -297,15 +297,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) · 30 unmodified lines | ||
| 297 | 297 | } |
| 298 | 298 | |
| 299 | 299 | *val = (bval[0] << 8) | bval[1]; |
| 300 | − return XC_RESULT_SUCCESS; | |
| 301 | −} | |
| 302 | − | |
| 303 | −static void xc_wait(int wait_ms) | |
| 304 | −{ | |
| 305 | − msleep(wait_ms); | |
| 300 | + return 0; | |
| 306 | 301 | } |
| 307 | 302 | |
| 308 | −static int xc5000_TunerReset(struct dvb_frontend *fe) | |
| 303 | +static int xc5000_tuner_reset(struct dvb_frontend *fe) | |
| 309 | 304 | { |
| 310 | 305 | struct xc5000_priv *priv = fe->tuner_priv; |
| 311 | 306 | int ret; |
| @@ -320,43 +315,43 @@ static int xc5000_TunerReset(struct dvb_frontend *fe) · 8 unmodified lines | ||
| 320 | 315 | XC5000_TUNER_RESET, 0); |
| 321 | 316 | if (ret) { |
| 322 | 317 | printk(KERN_ERR "xc5000: reset failed\n"); |
| 323 | − return XC_RESULT_RESET_FAILURE; | |
| 318 | + return ret; | |
| 324 | 319 | } |
| 325 | 320 | } else { |
| 326 | 321 | printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); |
| 327 | − return XC_RESULT_RESET_FAILURE; | |
| 322 | + return -EINVAL; | |
| 328 | 323 | } |
| 329 | − return XC_RESULT_SUCCESS; | |
| 324 | + return 0; | |
| 330 | 325 | } |
| 331 | 326 | |
| 332 | −static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) | |
| 327 | +static int xc_write_reg(struct xc5000_priv *priv, u16 reg_addr, u16 i2c_data) | |
| 333 | 328 | { |
| 334 | 329 | u8 buf[4]; |
| 335 | − int WatchDogTimer = 100; | |
| 330 | + int watch_dog_timer = 100; | |
| 336 | 331 | int result; |
| 337 | 332 | |
| 338 | − buf[0] = (regAddr >> 8) & 0xFF; | |
| 339 | − buf[1] = regAddr & 0xFF; | |
| 340 | − buf[2] = (i2cData >> 8) & 0xFF; | |
| 341 | − buf[3] = i2cData & 0xFF; | |
| 333 | + buf[0] = (reg_addr >> 8) & 0xFF; | |
| 334 | + buf[1] = reg_addr & 0xFF; | |
| 335 | + buf[2] = (i2c_data >> 8) & 0xFF; | |
| 336 | + buf[3] = i2c_data & 0xFF; | |
| 342 | 337 | result = xc_send_i2c_data(priv, buf, 4); |
| 343 | − if (result == XC_RESULT_SUCCESS) { | |
| 338 | + if (result == 0) { | |
| 344 | 339 | /* wait for busy flag to clear */ |
| 345 | − while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) { | |
| 340 | + while ((watch_dog_timer > 0) && (result == 0)) { | |
| 346 | 341 | result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf); |
| 347 | − if (result == XC_RESULT_SUCCESS) { | |
| 342 | + if (result == 0) { | |
| 348 | 343 | if ((buf[0] == 0) && (buf[1] == 0)) { |
| 349 | 344 | /* busy flag cleared */ |
| 350 | 345 | break; |
| 351 | 346 | } else { |
| 352 | − xc_wait(5); /* wait 5 ms */ | |
| 353 | − WatchDogTimer--; | |
| 347 | + msleep(5); /* wait 5 ms */ | |
| 348 | + watch_dog_timer--; | |
| 354 | 349 | } |
| 355 | 350 | } |
| 356 | 351 | } |
| 357 | 352 | } |
| 358 | − if (WatchDogTimer <= 0) | |
| 359 | − result = XC_RESULT_I2C_WRITE_FAILURE; | |
| 353 | + if (watch_dog_timer <= 0) | |
| 354 | + result = -EREMOTEIO; | |
| 360 | 355 | |
| 361 | 356 | return result; |
| 362 | 357 | } |
| @@ -375,13 +370,13 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) · 12 unmodified lines | ||
| 375 | 370 | len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; |
| 376 | 371 | if (len == 0x0000) { |
| 377 | 372 | /* RESET command */ |
| 378 | − result = xc5000_TunerReset(fe); | |
| 373 | + result = xc5000_tuner_reset(fe); | |
| 379 | 374 | index += 2; |
| 380 | − if (result != XC_RESULT_SUCCESS) | |
| 375 | + if (result != 0) | |
| 381 | 376 | return result; |
| 382 | 377 | } else if (len & 0x8000) { |
| 383 | 378 | /* WAIT command */ |
| 384 | − xc_wait(len & 0x7FFF); | |
| 379 | + msleep(len & 0x7FFF); | |
| 385 | 380 | index += 2; |
| 386 | 381 | } else { |
| 387 | 382 | /* Send i2c data whilst ensuring individual transactions |
| @@ -404,7 +399,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) · 16 unmodified lines | ||
| 404 | 399 | result = xc_send_i2c_data(priv, buf, |
| 405 | 400 | nbytes_to_send); |
| 406 | 401 | |
| 407 | − if (result != XC_RESULT_SUCCESS) | |
| 402 | + if (result != 0) | |
| 408 | 403 | return result; |
| 409 | 404 | |
| 410 | 405 | pos += nbytes_to_send - 2; |
| @@ -412,7 +407,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) · 1 unmodified line | ||
| 412 | 407 | index += len; |
| 413 | 408 | } |
| 414 | 409 | } |
| 415 | − return XC_RESULT_SUCCESS; | |
| 410 | + return 0; | |
| 416 | 411 | } |
| 417 | 412 | |
| 418 | 413 | static int xc_initialize(struct xc5000_priv *priv) |
| @@ -421,29 +416,29 @@ static int xc_initialize(struct xc5000_priv *priv) · 2 unmodified lines | ||
| 421 | 416 | return xc_write_reg(priv, XREG_INIT, 0); |
| 422 | 417 | } |
| 423 | 418 | |
| 424 | −static int xc_SetTVStandard(struct xc5000_priv *priv, | |
| 425 | − u16 VideoMode, u16 AudioMode, u8 RadioMode) | |
| 419 | +static int xc_set_tv_standard(struct xc5000_priv *priv, | |
| 420 | + u16 video_mode, u16 audio_mode, u8 radio_mode) | |
| 426 | 421 | { |
| 427 | 422 | int ret; |
| 428 | − dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode); | |
| 429 | − if (RadioMode) { | |
| 423 | + dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode); | |
| 424 | + if (radio_mode) { | |
| 430 | 425 | dprintk(1, "%s() Standard = %s\n", |
| 431 | 426 | __func__, |
| 432 | − XC5000_Standard[RadioMode].Name); | |
| 427 | + xc5000_standard[radio_mode].name); | |
| 433 | 428 | } else { |
| 434 | 429 | dprintk(1, "%s() Standard = %s\n", |
| 435 | 430 | __func__, |
| 436 | − XC5000_Standard[priv->video_standard].Name); | |
| 431 | + xc5000_standard[priv->video_standard].name); | |
| 437 | 432 | } |
| 438 | 433 | |
| 439 | − ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); | |
| 440 | − if (ret == XC_RESULT_SUCCESS) | |
| 441 | − ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); | |
| 434 | + ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode); | |
| 435 | + if (ret == 0) | |
| 436 | + ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode); | |
| 442 | 437 | |
| 443 | 438 | return ret; |
| 444 | 439 | } |
| 445 | 440 | |
| 446 | −static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) | |
| 441 | +static int xc_set_signal_source(struct xc5000_priv *priv, u16 rf_mode) | |
| 447 | 442 | { |
| 448 | 443 | dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, |
| 449 | 444 | rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); |
| @@ -459,7 +454,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) · 9 unmodified lines | ||
| 459 | 454 | |
| 460 | 455 | static const struct dvb_tuner_ops xc5000_tuner_ops; |
| 461 | 456 | |
| 462 | −static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) | |
| 457 | +static int xc_set_rf_frequency(struct xc5000_priv *priv, u32 freq_hz) | |
| 463 | 458 | { |
| 464 | 459 | u16 freq_code; |
| 465 | 460 | |
| @@ -467,7 +462,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) · 1 unmodified line | ||
| 467 | 462 | |
| 468 | 463 | if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || |
| 469 | 464 | (freq_hz < xc5000_tuner_ops.info.frequency_min)) |
| 470 | − return XC_RESULT_OUT_OF_RANGE; | |
| 465 | + return -EINVAL; | |
| 471 | 466 | |
| 472 | 467 | freq_code = (u16)(freq_hz / 15625); |
| 473 | 468 | |
| @@ -488,7 +483,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) · 14 unmodified lines | ||
| 488 | 483 | } |
| 489 | 484 | |
| 490 | 485 | |
| 491 | −static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) | |
| 486 | +static int xc_get_adc_envelope(struct xc5000_priv *priv, u16 *adc_envelope) | |
| 492 | 487 | { |
| 493 | 488 | return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope); |
| 494 | 489 | } |
| @@ -496,14 +491,14 @@ static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) · 1 unmodified line | ||
| 496 | 491 | static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) |
| 497 | 492 | { |
| 498 | 493 | int result; |
| 499 | − u16 regData; | |
| 494 | + u16 reg_data; | |
| 500 | 495 | u32 tmp; |
| 501 | 496 | |
| 502 | − result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); | |
| 503 | − if (result != XC_RESULT_SUCCESS) | |
| 497 | + result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®_data); | |
| 498 | + if (result != 0) | |
| 504 | 499 | return result; |
| 505 | 500 | |
| 506 | − tmp = (u32)regData; | |
| 501 | + tmp = (u32)reg_data; | |
| 507 | 502 | (*freq_error_hz) = (tmp * 15625) / 1000; |
| 508 | 503 | return result; |
| 509 | 504 | } |
| @@ -521,7 +516,7 @@ static int xc_get_version(struct xc5000_priv *priv, · 11 unmodified lines | ||
| 521 | 516 | int result; |
| 522 | 517 | |
| 523 | 518 | result = xc5000_readreg(priv, XREG_VERSION, &data); |
| 524 | − if (result != XC_RESULT_SUCCESS) | |
| 519 | + if (result != 0) | |
| 525 | 520 | return result; |
| 526 | 521 | |
| 527 | 522 | (*hw_majorversion) = (data >> 12) & 0x0F; |
| @@ -539,14 +534,14 @@ static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev) · 11 unmodified lines | ||
| 539 | 534 | |
| 540 | 535 | static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) |
| 541 | 536 | { |
| 542 | − u16 regData; | |
| 537 | + u16 reg_data; | |
| 543 | 538 | int result; |
| 544 | 539 | |
| 545 | − result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); | |
| 546 | − if (result != XC_RESULT_SUCCESS) | |
| 540 | + result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®_data); | |
| 541 | + if (result != 0) | |
| 547 | 542 | return result; |
| 548 | 543 | |
| 549 | − (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; | |
| 544 | + (*hsync_freq_hz) = ((reg_data & 0x0fff) * 763)/100; | |
| 550 | 545 | return result; |
| 551 | 546 | } |
| 552 | 547 | |
| @@ -570,19 +565,19 @@ static int xc_get_totalgain(struct xc5000_priv *priv, u16 *totalgain) · 17 unmodified lines | ||
| 570 | 565 | return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain); |
| 571 | 566 | } |
| 572 | 567 | |
| 573 | −static u16 WaitForLock(struct xc5000_priv *priv) | |
| 568 | +static u16 wait_for_lock(struct xc5000_priv *priv) | |
| 574 | 569 | { |
| 575 | − u16 lockState = 0; | |
| 576 | − int watchDogCount = 40; | |
| 577 | − | |
| 578 | − while ((lockState == 0) && (watchDogCount > 0)) { | |
| 579 | − xc_get_lock_status(priv, &lockState); | |
| 580 | − if (lockState != 1) { | |
| 581 | − xc_wait(5); | |
| 582 | − watchDogCount--; | |
| 570 | + u16 lock_state = 0; | |
| 571 | + int watch_dog_count = 40; | |
| 572 | + | |
| 573 | + while ((lock_state == 0) && (watch_dog_count > 0)) { | |
| 574 | + xc_get_lock_status(priv, &lock_state); | |
| 575 | + if (lock_state != 1) { | |
| 576 | + msleep(5); | |
| 577 | + watch_dog_count--; | |
| 583 | 578 | } |
| 584 | 579 | } |
| 585 | − return lockState; | |
| 580 | + return lock_state; | |
| 586 | 581 | } |
| 587 | 582 | |
| 588 | 583 | #define XC_TUNE_ANALOG 0 |
| @@ -593,11 +588,11 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) · 4 unmodified lines | ||
| 593 | 588 | |
| 594 | 589 | dprintk(1, "%s(%u)\n", __func__, freq_hz); |
| 595 | 590 | |
| 596 | − if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) | |
| 591 | + if (xc_set_rf_frequency(priv, freq_hz) != 0) | |
| 597 | 592 | return 0; |
| 598 | 593 | |
| 599 | 594 | if (mode == XC_TUNE_ANALOG) { |
| 600 | − if (WaitForLock(priv) == 1) | |
| 595 | + if (wait_for_lock(priv) == 1) | |
| 601 | 596 | found = 1; |
| 602 | 597 | } |
| 603 | 598 | |
| @@ -607,7 +602,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode) · 3 unmodified lines | ||
| 607 | 602 | static int xc_set_xtal(struct dvb_frontend *fe) |
| 608 | 603 | { |
| 609 | 604 | struct xc5000_priv *priv = fe->tuner_priv; |
| 610 | − int ret = XC_RESULT_SUCCESS; | |
| 605 | + int ret = 0; | |
| 611 | 606 | |
| 612 | 607 | switch (priv->chip_id) { |
| 613 | 608 | default: |
| @@ -649,23 +644,22 @@ static int xc5000_fwupload(struct dvb_frontend *fe) · 35 unmodified lines | ||
| 649 | 644 | priv->i2c_props.adap->dev.parent); |
| 650 | 645 | if (ret) { |
| 651 | 646 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); |
| 652 | − ret = XC_RESULT_RESET_FAILURE; | |
| 653 | 647 | goto out; |
| 654 | 648 | } else { |
| 655 | 649 | printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n", |
| 656 | 650 | fw->size); |
| 657 | − ret = XC_RESULT_SUCCESS; | |
| 651 | + ret = 0; | |
| 658 | 652 | } |
| 659 | 653 | |
| 660 | 654 | if (fw->size != desired_fw->size) { |
| 661 | 655 | printk(KERN_ERR "xc5000: firmware incorrect size\n"); |
| 662 | − ret = XC_RESULT_RESET_FAILURE; | |
| 656 | + ret = -EINVAL; | |
| 663 | 657 | } else { |
| 664 | 658 | printk(KERN_INFO "xc5000: firmware uploading...\n"); |
| 665 | 659 | ret = xc_load_i2c_sequence(fe, fw->data); |
| 666 | − if (XC_RESULT_SUCCESS == ret) | |
| 660 | + if (0 == ret) | |
| 667 | 661 | ret = xc_set_xtal(fe); |
| 668 | − if (XC_RESULT_SUCCESS == ret) | |
| 662 | + if (0 == ret) | |
| 669 | 663 | printk(KERN_INFO "xc5000: firmware upload complete...\n"); |
| 670 | 664 | else |
| 671 | 665 | printk(KERN_ERR "xc5000: firmware upload failed...\n"); |
| @@ -695,9 +689,9 @@ static void xc_debug_dump(struct xc5000_priv *priv) · 23 unmodified lines | ||
| 695 | 689 | * Frame Lines needs two frame times after initial lock |
| 696 | 690 | * before it is valid. |
| 697 | 691 | */ |
| 698 | − xc_wait(100); | |
| 692 | + msleep(100); | |
| 699 | 693 | |
| 700 | − xc_get_ADC_Envelope(priv, &adc_envelope); | |
| 694 | + xc_get_adc_envelope(priv, &adc_envelope); | |
| 701 | 695 | dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope); |
| 702 | 696 | |
| 703 | 697 | xc_get_frequency_error(priv, &freq_error_hz); |
| @@ -744,7 +738,7 @@ static int xc5000_set_params(struct dvb_frontend *fe) · 40 unmodified lines | ||
| 744 | 738 | u32 freq = fe->dtv_property_cache.frequency; |
| 745 | 739 | u32 delsys = fe->dtv_property_cache.delivery_system; |
| 746 | 740 | |
| 747 | − if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { | |
| 741 | + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { | |
| 748 | 742 | dprintk(1, "Unable to load firmware and init tuner\n"); |
| 749 | 743 | return -EINVAL; |
| 750 | 744 | } |
| @@ -820,24 +814,24 @@ static int xc5000_set_params(struct dvb_frontend *fe) · 69 unmodified lines | ||
| 820 | 814 | dprintk(1, "%s() frequency=%d (compensated to %d)\n", |
| 821 | 815 | __func__, freq, priv->freq_hz); |
| 822 | 816 | |
| 823 | − ret = xc_SetSignalSource(priv, priv->rf_mode); | |
| 824 | − if (ret != XC_RESULT_SUCCESS) { | |
| 817 | + ret = xc_set_signal_source(priv, priv->rf_mode); | |
| 818 | + if (ret != 0) { | |
| 825 | 819 | printk(KERN_ERR |
| 826 | − "xc5000: xc_SetSignalSource(%d) failed\n", | |
| 820 | + "xc5000: xc_set_signal_source(%d) failed\n", | |
| 827 | 821 | priv->rf_mode); |
| 828 | 822 | return -EREMOTEIO; |
| 829 | 823 | } |
| 830 | 824 | |
| 831 | − ret = xc_SetTVStandard(priv, | |
| 832 | − XC5000_Standard[priv->video_standard].VideoMode, | |
| 833 | − XC5000_Standard[priv->video_standard].AudioMode, 0); | |
| 834 | − if (ret != XC_RESULT_SUCCESS) { | |
| 835 | − printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | |
| 825 | + ret = xc_set_tv_standard(priv, | |
| 826 | + xc5000_standard[priv->video_standard].video_mode, | |
| 827 | + xc5000_standard[priv->video_standard].audio_mode, 0); | |
| 828 | + if (ret != 0) { | |
| 829 | + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); | |
| 836 | 830 | return -EREMOTEIO; |
| 837 | 831 | } |
| 838 | 832 | |
| 839 | 833 | ret = xc_set_IF_frequency(priv, priv->if_khz); |
| 840 | − if (ret != XC_RESULT_SUCCESS) { | |
| 834 | + if (ret != 0) { | |
| 841 | 835 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", |
| 842 | 836 | priv->if_khz); |
| 843 | 837 | return -EIO; |
| @@ -862,15 +856,15 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) · 18 unmodified lines | ||
| 862 | 856 | u16 id; |
| 863 | 857 | |
| 864 | 858 | ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id); |
| 865 | − if (ret == XC_RESULT_SUCCESS) { | |
| 859 | + if (ret == 0) { | |
| 866 | 860 | if (id == XC_PRODUCT_ID_FW_NOT_LOADED) |
| 867 | − ret = XC_RESULT_RESET_FAILURE; | |
| 861 | + ret = -ENOENT; | |
| 868 | 862 | else |
| 869 | − ret = XC_RESULT_SUCCESS; | |
| 863 | + ret = 0; | |
| 870 | 864 | } |
| 871 | 865 | |
| 872 | 866 | dprintk(1, "%s() returns %s id = 0x%x\n", __func__, |
| 873 | − ret == XC_RESULT_SUCCESS ? "True" : "False", id); | |
| 867 | + ret == 0 ? "True" : "False", id); | |
| 874 | 868 | return ret; |
| 875 | 869 | } |
| 876 | 870 | |
| @@ -936,19 +930,19 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe, · 59 unmodified lines | ||
| 936 | 930 | } |
| 937 | 931 | |
| 938 | 932 | tune_channel: |
| 939 | − ret = xc_SetSignalSource(priv, priv->rf_mode); | |
| 940 | − if (ret != XC_RESULT_SUCCESS) { | |
| 933 | + ret = xc_set_signal_source(priv, priv->rf_mode); | |
| 934 | + if (ret != 0) { | |
| 941 | 935 | printk(KERN_ERR |
| 942 | − "xc5000: xc_SetSignalSource(%d) failed\n", | |
| 936 | + "xc5000: xc_set_signal_source(%d) failed\n", | |
| 943 | 937 | priv->rf_mode); |
| 944 | 938 | return -EREMOTEIO; |
| 945 | 939 | } |
| 946 | 940 | |
| 947 | − ret = xc_SetTVStandard(priv, | |
| 948 | − XC5000_Standard[priv->video_standard].VideoMode, | |
| 949 | − XC5000_Standard[priv->video_standard].AudioMode, 0); | |
| 950 | − if (ret != XC_RESULT_SUCCESS) { | |
| 951 | − printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | |
| 941 | + ret = xc_set_tv_standard(priv, | |
| 942 | + xc5000_standard[priv->video_standard].video_mode, | |
| 943 | + xc5000_standard[priv->video_standard].audio_mode, 0); | |
| 944 | + if (ret != 0) { | |
| 945 | + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); | |
| 952 | 946 | return -EREMOTEIO; |
| 953 | 947 | } |
| 954 | 948 | |
| @@ -966,7 +960,7 @@ tune_channel: · 11 unmodified lines | ||
| 966 | 960 | /* PLL is unlocked, force reload of the firmware */ |
| 967 | 961 | dprintk(1, "xc5000: PLL not locked (0x%x). Reloading...\n", |
| 968 | 962 | pll_lock_status); |
| 969 | − if (xc_load_fw_and_init_tuner(fe, 1) != XC_RESULT_SUCCESS) { | |
| 963 | + if (xc_load_fw_and_init_tuner(fe, 1) != 0) { | |
| 970 | 964 | printk(KERN_ERR "xc5000: Unable to reload fw\n"); |
| 971 | 965 | return -EREMOTEIO; |
| 972 | 966 | } |
| @@ -993,11 +987,11 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, · 20 unmodified lines | ||
| 993 | 987 | } |
| 994 | 988 | |
| 995 | 989 | if (priv->radio_input == XC5000_RADIO_FM1) |
| 996 | − radio_input = FM_Radio_INPUT1; | |
| 990 | + radio_input = FM_RADIO_INPUT1; | |
| 997 | 991 | else if (priv->radio_input == XC5000_RADIO_FM2) |
| 998 | − radio_input = FM_Radio_INPUT2; | |
| 992 | + radio_input = FM_RADIO_INPUT2; | |
| 999 | 993 | else if (priv->radio_input == XC5000_RADIO_FM1_MONO) |
| 1000 | − radio_input = FM_Radio_INPUT1_MONO; | |
| 994 | + radio_input = FM_RADIO_INPUT1_MONO; | |
| 1001 | 995 | else { |
| 1002 | 996 | dprintk(1, "%s() unknown radio input %d\n", __func__, |
| 1003 | 997 | priv->radio_input); |
| @@ -1008,18 +1002,18 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, · 4 unmodified lines | ||
| 1008 | 1002 | |
| 1009 | 1003 | priv->rf_mode = XC_RF_MODE_AIR; |
| 1010 | 1004 | |
| 1011 | − ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode, | |
| 1012 | − XC5000_Standard[radio_input].AudioMode, radio_input); | |
| 1005 | + ret = xc_set_tv_standard(priv, xc5000_standard[radio_input].video_mode, | |
| 1006 | + xc5000_standard[radio_input].audio_mode, radio_input); | |
| 1013 | 1007 | |
| 1014 | − if (ret != XC_RESULT_SUCCESS) { | |
| 1015 | − printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | |
| 1008 | + if (ret != 0) { | |
| 1009 | + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); | |
| 1016 | 1010 | return -EREMOTEIO; |
| 1017 | 1011 | } |
| 1018 | 1012 | |
| 1019 | − ret = xc_SetSignalSource(priv, priv->rf_mode); | |
| 1020 | − if (ret != XC_RESULT_SUCCESS) { | |
| 1013 | + ret = xc_set_signal_source(priv, priv->rf_mode); | |
| 1014 | + if (ret != 0) { | |
| 1021 | 1015 | printk(KERN_ERR |
| 1022 | − "xc5000: xc_SetSignalSource(%d) failed\n", | |
| 1016 | + "xc5000: xc_set_signal_source(%d) failed\n", | |
| 1023 | 1017 | priv->rf_mode); |
| 1024 | 1018 | return -EREMOTEIO; |
| 1025 | 1019 | } |
| @@ -1044,7 +1038,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, · 18 unmodified lines | ||
| 1044 | 1038 | if (priv->i2c_props.adap == NULL) |
| 1045 | 1039 | return -EINVAL; |
| 1046 | 1040 | |
| 1047 | − if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { | |
| 1041 | + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { | |
| 1048 | 1042 | dprintk(1, "Unable to load firmware and init tuner\n"); |
| 1049 | 1043 | return -EINVAL; |
| 1050 | 1044 | } |
| @@ -1105,23 +1099,25 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) · 54 unmodified lines | ||
| 1105 | 1099 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) |
| 1106 | 1100 | { |
| 1107 | 1101 | struct xc5000_priv *priv = fe->tuner_priv; |
| 1108 | − int ret = XC_RESULT_SUCCESS; | |
| 1102 | + int ret = 0; | |
| 1109 | 1103 | u16 pll_lock_status; |
| 1110 | 1104 | u16 fw_ck; |
| 1111 | 1105 | |
| 1112 | − if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { | |
| 1106 | + cancel_delayed_work(&priv->timer_sleep); | |
| 1107 | + | |
| 1108 | + if (force || xc5000_is_firmware_loaded(fe) != 0) { | |
| 1113 | 1109 | |
| 1114 | 1110 | fw_retry: |
| 1115 | 1111 | |
| 1116 | 1112 | ret = xc5000_fwupload(fe); |
| 1117 | − if (ret != XC_RESULT_SUCCESS) | |
| 1113 | + if (ret != 0) | |
| 1118 | 1114 | return ret; |
| 1119 | 1115 | |
| 1120 | 1116 | msleep(20); |
| 1121 | 1117 | |
| 1122 | 1118 | if (priv->fw_checksum_supported) { |
| 1123 | 1119 | if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck) |
| 1124 | − != XC_RESULT_SUCCESS) { | |
| 1120 | + != 0) { | |
| 1125 | 1121 | dprintk(1, "%s() FW checksum reading failed.\n", |
| 1126 | 1122 | __func__); |
| 1127 | 1123 | goto fw_retry; |
| @@ -1137,7 +1133,7 @@ fw_retry: · 9 unmodified lines | ||
| 1137 | 1133 | /* Start the tuner self-calibration process */ |
| 1138 | 1134 | ret |= xc_initialize(priv); |
| 1139 | 1135 | |
| 1140 | − if (ret != XC_RESULT_SUCCESS) | |
| 1136 | + if (ret != 0) | |
| 1141 | 1137 | goto fw_retry; |
| 1142 | 1138 | |
| 1143 | 1139 | /* Wait for calibration to complete. |
| @@ -1145,10 +1141,10 @@ fw_retry: · 1 unmodified line | ||
| 1145 | 1141 | * I2C transactions until calibration is complete. This way we |
| 1146 | 1142 | * don't have to rely on clock stretching working. |
| 1147 | 1143 | */ |
| 1148 | − xc_wait(100); | |
| 1144 | + msleep(100); | |
| 1149 | 1145 | |
| 1150 | 1146 | if (priv->init_status_supported) { |
| 1151 | − if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != XC_RESULT_SUCCESS) { | |
| 1147 | + if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) { | |
| 1152 | 1148 | dprintk(1, "%s() FW failed reading init status.\n", |
| 1153 | 1149 | __func__); |
| 1154 | 1150 | goto fw_retry; |
| @@ -1177,27 +1173,39 @@ fw_retry: · 22 unmodified lines | ||
| 1177 | 1173 | return ret; |
| 1178 | 1174 | } |
| 1179 | 1175 | |
| 1180 | −static int xc5000_sleep(struct dvb_frontend *fe) | |
| 1176 | +static void xc5000_do_timer_sleep(struct work_struct *timer_sleep) | |
| 1181 | 1177 | { |
| 1178 | + struct xc5000_priv *priv =container_of(timer_sleep, struct xc5000_priv, | |
| 1179 | + timer_sleep.work); | |
| 1180 | + struct dvb_frontend *fe = priv->fe; | |
| 1182 | 1181 | int ret; |
| 1183 | 1182 | |
| 1184 | 1183 | dprintk(1, "%s()\n", __func__); |
| 1185 | 1184 | |
| 1186 | − /* Avoid firmware reload on slow devices */ | |
| 1187 | − if (no_poweroff) | |
| 1188 | − return 0; | |
| 1189 | − | |
| 1190 | 1185 | /* According to Xceive technical support, the "powerdown" register |
| 1191 | 1186 | was removed in newer versions of the firmware. The "supported" |
| 1192 | 1187 | way to sleep the tuner is to pull the reset pin low for 10ms */ |
| 1193 | − ret = xc5000_TunerReset(fe); | |
| 1194 | − if (ret != XC_RESULT_SUCCESS) { | |
| 1188 | + ret = xc5000_tuner_reset(fe); | |
| 1189 | + if (ret != 0) | |
| 1195 | 1190 | printk(KERN_ERR |
| 1196 | 1191 | "xc5000: %s() unable to shutdown tuner\n", |
| 1197 | 1192 | __func__); |
| 1198 | − return -EREMOTEIO; | |
| 1199 | − } else | |
| 1200 | − return XC_RESULT_SUCCESS; | |
| 1193 | +} | |
| 1194 | + | |
| 1195 | +static int xc5000_sleep(struct dvb_frontend *fe) | |
| 1196 | +{ | |
| 1197 | + struct xc5000_priv *priv = fe->tuner_priv; | |
| 1198 | + | |
| 1199 | + dprintk(1, "%s()\n", __func__); | |
| 1200 | + | |
| 1201 | + /* Avoid firmware reload on slow devices */ | |
| 1202 | + if (no_poweroff) | |
| 1203 | + return 0; | |
| 1204 | + | |
| 1205 | + schedule_delayed_work(&priv->timer_sleep, | |
| 1206 | + msecs_to_jiffies(XC5000_SLEEP_TIME)); | |
| 1207 | + | |
| 1208 | + return 0; | |
| 1201 | 1209 | } |
| 1202 | 1210 | |
| 1203 | 1211 | static int xc5000_init(struct dvb_frontend *fe) |
| @@ -1205,7 +1213,7 @@ static int xc5000_init(struct dvb_frontend *fe) · 1 unmodified line | ||
| 1205 | 1213 | struct xc5000_priv *priv = fe->tuner_priv; |
| 1206 | 1214 | dprintk(1, "%s()\n", __func__); |
| 1207 | 1215 | |
| 1208 | − if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { | |
| 1216 | + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { | |
| 1209 | 1217 | printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); |
| 1210 | 1218 | return -EREMOTEIO; |
| 1211 | 1219 | } |
| @@ -1224,8 +1232,10 @@ static int xc5000_release(struct dvb_frontend *fe) · 12 unmodified lines | ||
| 1224 | 1232 | |
| 1225 | 1233 | mutex_lock(&xc5000_list_mutex); |
| 1226 | 1234 | |
| 1227 | − if (priv) | |
| 1235 | + if (priv) { | |
| 1236 | + cancel_delayed_work(&priv->timer_sleep); | |
| 1228 | 1237 | hybrid_tuner_release_state(priv); |
| 1238 | + } | |
| 1229 | 1239 | |
| 1230 | 1240 | mutex_unlock(&xc5000_list_mutex); |
| 1231 | 1241 | |
| @@ -1297,6 +1307,8 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, · 65 unmodified lines | ||
| 1297 | 1307 | /* new tuner instance */ |
| 1298 | 1308 | priv->bandwidth = 6000000; |
| 1299 | 1309 | fe->tuner_priv = priv; |
| 1310 | + priv->fe = fe; | |
| 1311 | + INIT_DELAYED_WORK(&priv->timer_sleep, xc5000_do_timer_sleep); | |
| 1300 | 1312 | break; |
| 1301 | 1313 | default: |
| 1302 | 1314 | /* existing tuner instance */ |
| @@ -1327,7 +1339,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, · 24 unmodified lines | ||
| 1327 | 1339 | /* Check if firmware has been loaded. It is possible that another |
| 1328 | 1340 | instance of the driver has loaded the firmware. |
| 1329 | 1341 | */ |
| 1330 | − if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS) | |
| 1342 | + if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) | |
| 1331 | 1343 | goto fail; |
| 1332 | 1344 | |
| 1333 | 1345 | switch (id) { |
| @@ -114,16 +114,20 @@ static void urb_completion(struct urb *purb) · 113 unmodified lines | ||
| 114 | 114 | int ptype = usb_pipetype(purb->pipe); |
| 115 | 115 | unsigned char *ptr; |
| 116 | 116 | |
| 117 | − dprintk(2, "%s()\n", __func__); | |
| 117 | + dprintk(2, "%s: %d\n", __func__, purb->actual_length); | |
| 118 | 118 | |
| 119 | − if (!dev) | |
| 119 | + if (!dev) { | |
| 120 | + dprintk(2, "%s: no dev!\n", __func__); | |
| 120 | 121 | return; |
| 122 | + } | |
| 121 | 123 | |
| 122 | − if (dev->urb_streaming == 0) | |
| 124 | + if (dev->urb_streaming == 0) { | |
| 125 | + dprintk(2, "%s: not streaming!\n", __func__); | |
| 123 | 126 | return; |
| 127 | + } | |
| 124 | 128 | |
| 125 | 129 | if (ptype != PIPE_BULK) { |
| 126 | − printk(KERN_ERR "%s() Unsupported URB type %d\n", | |
| 130 | + printk(KERN_ERR "%s: Unsupported URB type %d\n", | |
| 127 | 131 | __func__, ptype); |
| 128 | 132 | return; |
| 129 | 133 | } |
| @@ -252,8 +256,6 @@ static void au0828_stop_transport(struct au0828_dev *dev, int full_stop) · 122 unmodified lines | ||
| 252 | 256 | au0828_write(dev, 0x60b, 0x00); |
| 253 | 257 | } |
| 254 | 258 | |
| 255 | − | |
| 256 | − | |
| 257 | 259 | static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) |
| 258 | 260 | { |
| 259 | 261 | struct dvb_demux *demux = feed->demux; |
| @@ -296,6 +298,8 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) · 36 unmodified lines | ||
| 296 | 298 | dprintk(1, "%s()\n", __func__); |
| 297 | 299 | |
| 298 | 300 | if (dvb) { |
| 301 | + cancel_work_sync(&dev->restart_streaming); | |
| 302 | + | |
| 299 | 303 | mutex_lock(&dvb->lock); |
| 300 | 304 | dvb->stop_count++; |
| 301 | 305 | dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__, |
| @@ -338,6 +342,41 @@ static void au0828_restart_dvb_streaming(struct work_struct *work) · 36 unmodified lines | ||
| 338 | 342 | mutex_unlock(&dvb->lock); |
| 339 | 343 | } |
| 340 | 344 | |
| 345 | +static int au0828_set_frontend(struct dvb_frontend *fe) | |
| 346 | +{ | |
| 347 | + struct au0828_dev *dev = fe->dvb->priv; | |
| 348 | + struct au0828_dvb *dvb = &dev->dvb; | |
| 349 | + int ret, was_streaming; | |
| 350 | + | |
| 351 | + mutex_lock(&dvb->lock); | |
| 352 | + was_streaming = dev->urb_streaming; | |
| 353 | + if (was_streaming) { | |
| 354 | + au0828_stop_transport(dev, 1); | |
| 355 | + | |
| 356 | + /* | |
| 357 | + * We can't hold a mutex here, as the restart_streaming | |
| 358 | + * kthread may also hold it. | |
| 359 | + */ | |
| 360 | + mutex_unlock(&dvb->lock); | |
| 361 | + cancel_work_sync(&dev->restart_streaming); | |
| 362 | + mutex_lock(&dvb->lock); | |
| 363 | + | |
| 364 | + stop_urb_transfer(dev); | |
| 365 | + } | |
| 366 | + mutex_unlock(&dvb->lock); | |
| 367 | + | |
| 368 | + ret = dvb->set_frontend(fe); | |
| 369 | + | |
| 370 | + if (was_streaming) { | |
| 371 | + mutex_lock(&dvb->lock); | |
| 372 | + au0828_start_transport(dev); | |
| 373 | + start_urb_transfer(dev); | |
| 374 | + mutex_unlock(&dvb->lock); | |
| 375 | + } | |
| 376 | + | |
| 377 | + return ret; | |
| 378 | +} | |
| 379 | + | |
| 341 | 380 | static int dvb_register(struct au0828_dev *dev) |
| 342 | 381 | { |
| 343 | 382 | struct au0828_dvb *dvb = &dev->dvb; |
| @@ -382,6 +421,10 @@ static int dvb_register(struct au0828_dev *dev) · 38 unmodified lines | ||
| 382 | 421 | goto fail_frontend; |
| 383 | 422 | } |
| 384 | 423 | |
| 424 | + /* Hook dvb frontend */ | |
| 425 | + dvb->set_frontend = dvb->frontend->ops.set_frontend; | |
| 426 | + dvb->frontend->ops.set_frontend = au0828_set_frontend; | |
| 427 | + | |
| 385 | 428 | /* register demux stuff */ |
| 386 | 429 | dvb->demux.dmx.capabilities = |
| 387 | 430 | DMX_TS_FILTERING | DMX_SECTION_FILTERING | |
| @@ -471,6 +514,8 @@ void au0828_dvb_unregister(struct au0828_dev *dev) · 83 unmodified lines | ||
| 471 | 514 | if (dvb->frontend == NULL) |
| 472 | 515 | return; |
| 473 | 516 | |
| 517 | + cancel_work_sync(&dev->restart_streaming); | |
| 518 | + | |
| 474 | 519 | dvb_net_release(&dvb->net); |
| 475 | 520 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); |
| 476 | 521 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); |
| @@ -1109,7 +1109,7 @@ static void au0828_init_tuner(struct au0828_dev *dev) · 1108 unmodified lines | ||
| 1109 | 1109 | /* If we've never sent the standard in tuner core, do so now. |
| 1110 | 1110 | We don't do this at device probe because we don't want to |
| 1111 | 1111 | incur the cost of a firmware load */ |
| 1112 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->std); | |
| 1112 | + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, dev->std); | |
| 1113 | 1113 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); |
| 1114 | 1114 | i2c_gate_ctrl(dev, 0); |
| 1115 | 1115 | } |
| @@ -1368,7 +1368,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) · 252 unmodified lines | ||
| 1368 | 1368 | have to make the au0828 bridge adjust the size of its capture |
| 1369 | 1369 | buffer, which is currently hardcoded at 720x480 */ |
| 1370 | 1370 | |
| 1371 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, norm); | |
| 1371 | + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm); | |
| 1372 | 1372 | |
| 1373 | 1373 | i2c_gate_ctrl(dev, 0); |
| 1374 | 1374 | |
| @@ -104,6 +104,8 @@ struct au0828_dvb { · 103 unmodified lines | ||
| 104 | 104 | int feeding; |
| 105 | 105 | int start_count; |
| 106 | 106 | int stop_count; |
| 107 | + | |
| 108 | + int (*set_frontend)(struct dvb_frontend *fe); | |
| 107 | 109 | }; |
| 108 | 110 | |
| 109 | 111 | enum au0828_stream_state { |
| @@ -1516,7 +1516,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) · 1515 unmodified lines | ||
| 1516 | 1516 | dev->ts1.height = 576; |
| 1517 | 1517 | cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, true); |
| 1518 | 1518 | } |
| 1519 | − call_all(dev, core, s_std, dev->norm); | |
| 1519 | + call_all(dev, video, s_std, dev->norm); | |
| 1520 | 1520 | /* do mode control overrides */ |
| 1521 | 1521 | cx231xx_do_mode_ctrl_overrides(dev); |
| 1522 | 1522 | |
| @@ -1009,7 +1009,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) · 1008 unmodified lines | ||
| 1009 | 1009 | dev->width = 720; |
| 1010 | 1010 | dev->height = (dev->norm & V4L2_STD_625_50) ? 576 : 480; |
| 1011 | 1011 | |
| 1012 | − call_all(dev, core, s_std, dev->norm); | |
| 1012 | + call_all(dev, video, s_std, dev->norm); | |
| 1013 | 1013 | |
| 1014 | 1014 | /* We need to reset basic properties in the decoder related to |
| 1015 | 1015 | resolution (since a standard change effects things like the number |
| @@ -1108,7 +1108,7 @@ int cx231xx_s_input(struct file *file, void *priv, unsigned int i) · 92 unmodified lines | ||
| 1108 | 1108 | /* There's a tuner, so reset the standard and put it on the |
| 1109 | 1109 | last known frequency (since it was probably powered down |
| 1110 | 1110 | until now */ |
| 1111 | − call_all(dev, core, s_std, dev->norm); | |
| 1111 | + call_all(dev, video, s_std, dev->norm); | |
| 1112 | 1112 | } |
| 1113 | 1113 | |
| 1114 | 1114 | return 0; |
| @@ -2099,7 +2099,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) · 984 unmodified lines | ||
| 2099 | 2099 | /* Set the initial input */ |
| 2100 | 2100 | video_mux(dev, dev->video_input); |
| 2101 | 2101 | |
| 2102 | − call_all(dev, core, s_std, dev->norm); | |
| 2102 | + call_all(dev, video, s_std, dev->norm); | |
| 2103 | 2103 | |
| 2104 | 2104 | v4l2_ctrl_handler_init(&dev->ctrl_handler, 10); |
| 2105 | 2105 | v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 5); |
| @@ -1537,6 +1537,12 @@ static const struct usb_device_id rtl28xxu_id_table[] = { · 1536 unmodified lines | ||
| 1537 | 1537 | &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, |
| 1538 | 1538 | { DVB_USB_DEVICE(USB_VID_KYE, 0x707f, |
| 1539 | 1539 | &rtl2832u_props, "Genius TVGo DVB-T03", NULL) }, |
| 1540 | + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd395, | |
| 1541 | + &rtl2832u_props, "Peak DVB-T USB", NULL) }, | |
| 1542 | + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U, | |
| 1543 | + &rtl2832u_props, "Sveon STV20", NULL) }, | |
| 1544 | + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27, | |
| 1545 | + &rtl2832u_props, "Sveon STV27", NULL) }, | |
| 1540 | 1546 | |
| 1541 | 1547 | /* RTL2832P devices: */ |
| 1542 | 1548 | { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, |
| @@ -1088,6 +1088,7 @@ static struct usb_device_id az6027_usb_table[] = { · 1087 unmodified lines | ||
| 1088 | 1088 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) }, |
| 1089 | 1089 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) }, |
| 1090 | 1090 | { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) }, |
| 1091 | + { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V2) }, | |
| 1091 | 1092 | { }, |
| 1092 | 1093 | }; |
| 1093 | 1094 | |
| @@ -1136,7 +1137,7 @@ static struct dvb_usb_device_properties az6027_properties = { · 42 unmodified lines | ||
| 1136 | 1137 | |
| 1137 | 1138 | .i2c_algo = &az6027_i2c_algo, |
| 1138 | 1139 | |
| 1139 | − .num_device_descs = 6, | |
| 1140 | + .num_device_descs = 7, | |
| 1140 | 1141 | .devices = { |
| 1141 | 1142 | { |
| 1142 | 1143 | .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", |
| @@ -1162,6 +1163,10 @@ static struct dvb_usb_device_properties az6027_properties = { · 19 unmodified lines | ||
| 1162 | 1163 | .name = "Elgato EyeTV Sat", |
| 1163 | 1164 | .cold_ids = { &az6027_usb_table[5], NULL }, |
| 1164 | 1165 | .warm_ids = { NULL }, |
| 1166 | + }, { | |
| 1167 | + .name = "Elgato EyeTV Sat", | |
| 1168 | + .cold_ids = { &az6027_usb_table[6], NULL }, | |
| 1169 | + .warm_ids = { NULL }, | |
| 1165 | 1170 | }, |
| 1166 | 1171 | { NULL }, |
| 1167 | 1172 | } |
| @@ -59,7 +59,7 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 · 58 unmodified lines | ||
| 59 | 59 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); |
| 60 | 60 | extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); |
| 61 | 61 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); |
| 62 | −extern int dib0700_rc_setup(struct dvb_usb_device *d); | |
| 62 | +extern int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf); | |
| 63 | 63 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); |
| 64 | 64 | extern struct i2c_algorithm dib0700_i2c_algo; |
| 65 | 65 | extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
| @@ -754,17 +754,20 @@ resubmit: · 753 unmodified lines | ||
| 754 | 754 | usb_submit_urb(purb, GFP_ATOMIC); |
| 755 | 755 | } |
| 756 | 756 | |
| 757 | −int dib0700_rc_setup(struct dvb_usb_device *d) | |
| 757 | +int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) | |
| 758 | 758 | { |
| 759 | 759 | struct dib0700_state *st = d->priv; |
| 760 | 760 | struct urb *purb; |
| 761 | − int ret; | |
| 761 | + const struct usb_endpoint_descriptor *e; | |
| 762 | + int ret, rc_ep = 1; | |
| 763 | + unsigned int pipe = 0; | |
| 762 | 764 | |
| 763 | 765 | /* Poll-based. Don't initialize bulk mode */ |
| 764 | − if (st->fw_version < 0x10200) | |
| 766 | + if (st->fw_version < 0x10200 || !intf) | |
| 765 | 767 | return 0; |
| 766 | 768 | |
| 767 | 769 | /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ |
| 770 | + | |
| 768 | 771 | purb = usb_alloc_urb(0, GFP_KERNEL); |
| 769 | 772 | if (purb == NULL) { |
| 770 | 773 | err("rc usb alloc urb failed"); |
| @@ -779,9 +782,35 @@ int dib0700_rc_setup(struct dvb_usb_device *d) · 8 unmodified lines | ||
| 779 | 782 | } |
| 780 | 783 | |
| 781 | 784 | purb->status = -EINPROGRESS; |
| 782 | − usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1), | |
| 783 | − purb->transfer_buffer, RC_MSG_SIZE_V1_20, | |
| 784 | − dib0700_rc_urb_completion, d); | |
| 785 | + | |
| 786 | + /* | |
| 787 | + * Some devices like the Hauppauge NovaTD model 52009 use an interrupt | |
| 788 | + * endpoint, while others use a bulk one. | |
| 789 | + */ | |
| 790 | + e = &intf->altsetting[0].endpoint[rc_ep].desc; | |
| 791 | + if (usb_endpoint_dir_in(e)) { | |
| 792 | + if (usb_endpoint_xfer_bulk(e)) { | |
| 793 | + pipe = usb_rcvbulkpipe(d->udev, rc_ep); | |
| 794 | + usb_fill_bulk_urb(purb, d->udev, pipe, | |
| 795 | + purb->transfer_buffer, | |
| 796 | + RC_MSG_SIZE_V1_20, | |
| 797 | + dib0700_rc_urb_completion, d); | |
| 798 | + | |
| 799 | + } else if (usb_endpoint_xfer_int(e)) { | |
| 800 | + pipe = usb_rcvintpipe(d->udev, rc_ep); | |
| 801 | + usb_fill_int_urb(purb, d->udev, pipe, | |
| 802 | + purb->transfer_buffer, | |
| 803 | + RC_MSG_SIZE_V1_20, | |
| 804 | + dib0700_rc_urb_completion, d, 1); | |
| 805 | + } | |
| 806 | + } | |
| 807 | + | |
| 808 | + if (!pipe) { | |
| 809 | + err("There's no endpoint for remote controller"); | |
| 810 | + kfree(purb->transfer_buffer); | |
| 811 | + usb_free_urb(purb); | |
| 812 | + return 0; | |
| 813 | + } | |
| 785 | 814 | |
| 786 | 815 | ret = usb_submit_urb(purb, GFP_ATOMIC); |
| 787 | 816 | if (ret) { |
| @@ -820,7 +849,7 @@ static int dib0700_probe(struct usb_interface *intf, · 32 unmodified lines | ||
| 820 | 849 | else |
| 821 | 850 | dev->props.rc.core.bulk_mode = false; |
| 822 | 851 | |
| 823 | − dib0700_rc_setup(dev); | |
| 852 | + dib0700_rc_setup(dev, intf); | |
| 824 | 853 | |
| 825 | 854 | return 0; |
| 826 | 855 | } |
| @@ -514,7 +514,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) · 513 unmodified lines | ||
| 514 | 514 | |
| 515 | 515 | /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */ |
| 516 | 516 | |
| 517 | − dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */ | |
| 517 | + dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ | |
| 518 | 518 | |
| 519 | 519 | d->last_event = 0; |
| 520 | 520 | switch (d->props.rc.core.protocol) { |
| @@ -214,10 +214,10 @@ static void technisat_usb2_frontend_reset(struct usb_device *udev) · 213 unmodified lines | ||
| 214 | 214 | |
| 215 | 215 | /* LED control */ |
| 216 | 216 | enum technisat_usb2_led_state { |
| 217 | − LED_OFF, | |
| 218 | − LED_BLINK, | |
| 219 | − LED_ON, | |
| 220 | − LED_UNDEFINED | |
| 217 | + TECH_LED_OFF, | |
| 218 | + TECH_LED_BLINK, | |
| 219 | + TECH_LED_ON, | |
| 220 | + TECH_LED_UNDEFINED | |
| 221 | 221 | }; |
| 222 | 222 | |
| 223 | 223 | static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state) |
| @@ -229,14 +229,14 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni · 5 unmodified lines | ||
| 229 | 229 | 0 |
| 230 | 230 | }; |
| 231 | 231 | |
| 232 | − if (disable_led_control && state != LED_OFF) | |
| 232 | + if (disable_led_control && state != TECH_LED_OFF) | |
| 233 | 233 | return 0; |
| 234 | 234 | |
| 235 | 235 | switch (state) { |
| 236 | − case LED_ON: | |
| 236 | + case TECH_LED_ON: | |
| 237 | 237 | led[1] = 0x82; |
| 238 | 238 | break; |
| 239 | − case LED_BLINK: | |
| 239 | + case TECH_LED_BLINK: | |
| 240 | 240 | led[1] = 0x82; |
| 241 | 241 | if (red) { |
| 242 | 242 | led[2] = 0x02; |
| @@ -251,7 +251,7 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni · 8 unmodified lines | ||
| 251 | 251 | break; |
| 252 | 252 | |
| 253 | 253 | default: |
| 254 | − case LED_OFF: | |
| 254 | + case TECH_LED_OFF: | |
| 255 | 255 | led[1] = 0x80; |
| 256 | 256 | break; |
| 257 | 257 | } |
| @@ -310,11 +310,11 @@ static void technisat_usb2_green_led_control(struct work_struct *work) · 52 unmodified lines | ||
| 310 | 310 | goto schedule; |
| 311 | 311 | |
| 312 | 312 | if (ber > 1000) |
| 313 | − technisat_usb2_set_led(state->dev, 0, LED_BLINK); | |
| 313 | + technisat_usb2_set_led(state->dev, 0, TECH_LED_BLINK); | |
| 314 | 314 | else |
| 315 | − technisat_usb2_set_led(state->dev, 0, LED_ON); | |
| 315 | + technisat_usb2_set_led(state->dev, 0, TECH_LED_ON); | |
| 316 | 316 | } else |
| 317 | − technisat_usb2_set_led(state->dev, 0, LED_OFF); | |
| 317 | + technisat_usb2_set_led(state->dev, 0, TECH_LED_OFF); | |
| 318 | 318 | } |
| 319 | 319 | |
| 320 | 320 | schedule: |
| @@ -365,9 +365,9 @@ static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level) · 44 unmodified lines | ||
| 365 | 365 | return 0; |
| 366 | 366 | |
| 367 | 367 | /* green led is turned off in any case - will be turned on when tuning */ |
| 368 | − technisat_usb2_set_led(d, 0, LED_OFF); | |
| 368 | + technisat_usb2_set_led(d, 0, TECH_LED_OFF); | |
| 369 | 369 | /* red led is turned on all the time */ |
| 370 | − technisat_usb2_set_led(d, 1, LED_ON); | |
| 370 | + technisat_usb2_set_led(d, 1, TECH_LED_ON); | |
| 371 | 371 | return 0; |
| 372 | 372 | } |
| 373 | 373 | |
| @@ -667,7 +667,7 @@ static int technisat_usb2_rc_query(struct dvb_usb_device *d) · 293 unmodified lines | ||
| 667 | 667 | return 0; |
| 668 | 668 | |
| 669 | 669 | if (!disable_led_control) |
| 670 | − technisat_usb2_set_led(d, 1, LED_BLINK); | |
| 670 | + technisat_usb2_set_led(d, 1, TECH_LED_BLINK); | |
| 671 | 671 | |
| 672 | 672 | return 0; |
| 673 | 673 | } |
| @@ -57,6 +57,8 @@ config VIDEO_EM28XX_DVB · 56 unmodified lines | ||
| 57 | 57 | select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT |
| 58 | 58 | select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT |
| 59 | 59 | select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT |
| 60 | + select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT | |
| 61 | + select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT | |
| 60 | 62 | ---help--- |
| 61 | 63 | This adds support for DVB cards based on the |
| 62 | 64 | Empiatech em28xx chips. |
| @@ -92,7 +92,7 @@ static void em28xx_audio_isocirq(struct urb *urb) · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | if (dev->disconnected) { |
| 94 | 94 | dprintk("device disconnected while streaming. URB status=%d.\n", urb->status); |
| 95 | − atomic_set(&dev->stream_started, 0); | |
| 95 | + atomic_set(&dev->adev.stream_started, 0); | |
| 96 | 96 | return; |
| 97 | 97 | } |
| 98 | 98 | |
| @@ -109,7 +109,7 @@ static void em28xx_audio_isocirq(struct urb *urb) · 10 unmodified lines | ||
| 109 | 109 | break; |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | − if (atomic_read(&dev->stream_started) == 0) | |
| 112 | + if (atomic_read(&dev->adev.stream_started) == 0) | |
| 113 | 113 | return; |
| 114 | 114 | |
| 115 | 115 | if (dev->adev.capture_pcm_substream) { |
| @@ -185,7 +185,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) · 69 unmodified lines | ||
| 185 | 185 | em28xx_errdev("submit of audio urb failed (error=%i)\n", |
| 186 | 186 | errCode); |
| 187 | 187 | em28xx_deinit_isoc_audio(dev); |
| 188 | − atomic_set(&dev->stream_started, 0); | |
| 188 | + atomic_set(&dev->adev.stream_started, 0); | |
| 189 | 189 | return errCode; |
| 190 | 190 | } |
| 191 | 191 | |
| @@ -332,9 +332,9 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) · 140 unmodified lines | ||
| 332 | 332 | dev->mute = 1; |
| 333 | 333 | mutex_lock(&dev->lock); |
| 334 | 334 | dev->adev.users--; |
| 335 | − if (atomic_read(&dev->stream_started) > 0) { | |
| 336 | − atomic_set(&dev->stream_started, 0); | |
| 337 | − schedule_work(&dev->wq_trigger); | |
| 335 | + if (atomic_read(&dev->adev.stream_started) > 0) { | |
| 336 | + atomic_set(&dev->adev.stream_started, 0); | |
| 337 | + schedule_work(&dev->adev.wq_trigger); | |
| 338 | 338 | } |
| 339 | 339 | |
| 340 | 340 | em28xx_audio_analog_set(dev); |
| @@ -381,12 +381,13 @@ static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream, · 40 unmodified lines | ||
| 381 | 381 | static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) |
| 382 | 382 | { |
| 383 | 383 | struct em28xx *dev = snd_pcm_substream_chip(substream); |
| 384 | + struct em28xx_audio *adev = &dev->adev; | |
| 384 | 385 | |
| 385 | 386 | dprintk("Stop capture, if needed\n"); |
| 386 | 387 | |
| 387 | − if (atomic_read(&dev->stream_started) > 0) { | |
| 388 | − atomic_set(&dev->stream_started, 0); | |
| 389 | − schedule_work(&dev->wq_trigger); | |
| 388 | + if (atomic_read(&adev->stream_started) > 0) { | |
| 389 | + atomic_set(&adev->stream_started, 0); | |
| 390 | + schedule_work(&adev->wq_trigger); | |
| 390 | 391 | } |
| 391 | 392 | |
| 392 | 393 | return 0; |
| @@ -407,9 +408,11 @@ static int snd_em28xx_prepare(struct snd_pcm_substream *substream) · 14 unmodified lines | ||
| 407 | 408 | |
| 408 | 409 | static void audio_trigger(struct work_struct *work) |
| 409 | 410 | { |
| 410 | − struct em28xx *dev = container_of(work, struct em28xx, wq_trigger); | |
| 411 | + struct em28xx_audio *adev = | |
| 412 | + container_of(work, struct em28xx_audio, wq_trigger); | |
| 413 | + struct em28xx *dev = container_of(adev, struct em28xx, adev); | |
| 411 | 414 | |
| 412 | − if (atomic_read(&dev->stream_started)) { | |
| 415 | + if (atomic_read(&adev->stream_started)) { | |
| 413 | 416 | dprintk("starting capture"); |
| 414 | 417 | em28xx_init_audio_isoc(dev); |
| 415 | 418 | } else { |
| @@ -431,17 +434,17 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, · 15 unmodified lines | ||
| 431 | 434 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
| 432 | 435 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
| 433 | 436 | case SNDRV_PCM_TRIGGER_START: |
| 434 | − atomic_set(&dev->stream_started, 1); | |
| 437 | + atomic_set(&dev->adev.stream_started, 1); | |
| 435 | 438 | break; |
| 436 | 439 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
| 437 | 440 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
| 438 | 441 | case SNDRV_PCM_TRIGGER_STOP: |
| 439 | − atomic_set(&dev->stream_started, 0); | |
| 442 | + atomic_set(&dev->adev.stream_started, 0); | |
| 440 | 443 | break; |
| 441 | 444 | default: |
| 442 | 445 | retval = -EINVAL; |
| 443 | 446 | } |
| 444 | − schedule_work(&dev->wq_trigger); | |
| 447 | + schedule_work(&dev->adev.wq_trigger); | |
| 445 | 448 | return retval; |
| 446 | 449 | } |
| 447 | 450 | |
| @@ -928,7 +931,7 @@ static int em28xx_audio_init(struct em28xx *dev) · 480 unmodified lines | ||
| 928 | 931 | strcpy(card->shortname, "Em28xx Audio"); |
| 929 | 932 | strcpy(card->longname, "Empia Em28xx Audio"); |
| 930 | 933 | |
| 931 | − INIT_WORK(&dev->wq_trigger, audio_trigger); | |
| 934 | + INIT_WORK(&adev->wq_trigger, audio_trigger); | |
| 932 | 935 | |
| 933 | 936 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { |
| 934 | 937 | em28xx_cvol_new(card, dev, "Video", AC97_VIDEO); |
| @@ -983,7 +986,7 @@ static int em28xx_audio_fini(struct em28xx *dev) · 48 unmodified lines | ||
| 983 | 986 | |
| 984 | 987 | if (dev->adev.sndcard) { |
| 985 | 988 | snd_card_disconnect(dev->adev.sndcard); |
| 986 | − flush_work(&dev->wq_trigger); | |
| 989 | + flush_work(&dev->adev.wq_trigger); | |
| 987 | 990 | |
| 988 | 991 | em28xx_audio_free_urb(dev); |
| 989 | 992 | |
| @@ -1005,7 +1008,7 @@ static int em28xx_audio_suspend(struct em28xx *dev) · 15 unmodified lines | ||
| 1005 | 1008 | |
| 1006 | 1009 | em28xx_info("Suspending audio extension"); |
| 1007 | 1010 | em28xx_deinit_isoc_audio(dev); |
| 1008 | − atomic_set(&dev->stream_started, 0); | |
| 1011 | + atomic_set(&dev->adev.stream_started, 0); | |
| 1009 | 1012 | return 0; |
| 1010 | 1013 | } |
| 1011 | 1014 | |
| @@ -1019,7 +1022,7 @@ static int em28xx_audio_resume(struct em28xx *dev) · 7 unmodified lines | ||
| 1019 | 1022 | |
| 1020 | 1023 | em28xx_info("Resuming audio extension"); |
| 1021 | 1024 | /* Nothing to do other than schedule_work() ?? */ |
| 1022 | − schedule_work(&dev->wq_trigger); | |
| 1025 | + schedule_work(&dev->adev.wq_trigger); | |
| 1023 | 1026 | return 0; |
| 1024 | 1027 | } |
| 1025 | 1028 | |
| @@ -330,13 +330,14 @@ int em28xx_init_camera(struct em28xx *dev) · 329 unmodified lines | ||
| 330 | 330 | char clk_name[V4L2_SUBDEV_NAME_SIZE]; |
| 331 | 331 | struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; |
| 332 | 332 | struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus]; |
| 333 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 333 | 334 | int ret = 0; |
| 334 | 335 | |
| 335 | 336 | v4l2_clk_name_i2c(clk_name, sizeof(clk_name), |
| 336 | 337 | i2c_adapter_id(adap), client->addr); |
| 337 | − dev->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL); | |
| 338 | − if (IS_ERR(dev->clk)) | |
| 339 | − return PTR_ERR(dev->clk); | |
| 338 | + v4l2->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL); | |
| 339 | + if (IS_ERR(v4l2->clk)) | |
| 340 | + return PTR_ERR(v4l2->clk); | |
| 340 | 341 | |
| 341 | 342 | switch (dev->em28xx_sensor) { |
| 342 | 343 | case EM28XX_MT9V011: |
| @@ -348,8 +349,8 @@ int em28xx_init_camera(struct em28xx *dev) · 5 unmodified lines | ||
| 348 | 349 | .platform_data = &pdata, |
| 349 | 350 | }; |
| 350 | 351 | |
| 351 | − dev->sensor_xres = 640; | |
| 352 | − dev->sensor_yres = 480; | |
| 352 | + v4l2->sensor_xres = 640; | |
| 353 | + v4l2->sensor_yres = 480; | |
| 353 | 354 | |
| 354 | 355 | /* |
| 355 | 356 | * FIXME: mt9v011 uses I2S speed as xtal clk - at least with |
| @@ -362,41 +363,41 @@ int em28xx_init_camera(struct em28xx *dev) · 6 unmodified lines | ||
| 362 | 363 | */ |
| 363 | 364 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; |
| 364 | 365 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); |
| 365 | − dev->sensor_xtal = 4300000; | |
| 366 | − pdata.xtal = dev->sensor_xtal; | |
| 366 | + v4l2->sensor_xtal = 4300000; | |
| 367 | + pdata.xtal = v4l2->sensor_xtal; | |
| 367 | 368 | if (NULL == |
| 368 | − v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap, | |
| 369 | + v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap, | |
| 369 | 370 | &mt9v011_info, NULL)) { |
| 370 | 371 | ret = -ENODEV; |
| 371 | 372 | break; |
| 372 | 373 | } |
| 373 | 374 | /* probably means GRGB 16 bit bayer */ |
| 374 | − dev->vinmode = 0x0d; | |
| 375 | − dev->vinctl = 0x00; | |
| 375 | + v4l2->vinmode = 0x0d; | |
| 376 | + v4l2->vinctl = 0x00; | |
| 376 | 377 | |
| 377 | 378 | break; |
| 378 | 379 | } |
| 379 | 380 | case EM28XX_MT9M001: |
| 380 | − dev->sensor_xres = 1280; | |
| 381 | − dev->sensor_yres = 1024; | |
| 381 | + v4l2->sensor_xres = 1280; | |
| 382 | + v4l2->sensor_yres = 1024; | |
| 382 | 383 | |
| 383 | 384 | em28xx_initialize_mt9m001(dev); |
| 384 | 385 | |
| 385 | 386 | /* probably means BGGR 16 bit bayer */ |
| 386 | − dev->vinmode = 0x0c; | |
| 387 | − dev->vinctl = 0x00; | |
| 387 | + v4l2->vinmode = 0x0c; | |
| 388 | + v4l2->vinctl = 0x00; | |
| 388 | 389 | |
| 389 | 390 | break; |
| 390 | 391 | case EM28XX_MT9M111: |
| 391 | − dev->sensor_xres = 640; | |
| 392 | − dev->sensor_yres = 512; | |
| 392 | + v4l2->sensor_xres = 640; | |
| 393 | + v4l2->sensor_yres = 512; | |
| 393 | 394 | |
| 394 | 395 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; |
| 395 | 396 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); |
| 396 | 397 | em28xx_initialize_mt9m111(dev); |
| 397 | 398 | |
| 398 | − dev->vinmode = 0x0a; | |
| 399 | − dev->vinctl = 0x00; | |
| 399 | + v4l2->vinmode = 0x0a; | |
| 400 | + v4l2->vinctl = 0x00; | |
| 400 | 401 | |
| 401 | 402 | break; |
| 402 | 403 | case EM28XX_OV2640: |
| @@ -418,11 +419,11 @@ int em28xx_init_camera(struct em28xx *dev) · 15 unmodified lines | ||
| 418 | 419 | * - adjust bridge xclk |
| 419 | 420 | * - disable 16 bit (12 bit) output formats on high resolutions |
| 420 | 421 | */ |
| 421 | − dev->sensor_xres = 640; | |
| 422 | − dev->sensor_yres = 480; | |
| 422 | + v4l2->sensor_xres = 640; | |
| 423 | + v4l2->sensor_yres = 480; | |
| 423 | 424 | |
| 424 | 425 | subdev = |
| 425 | − v4l2_i2c_new_subdev_board(&dev->v4l2_dev, adap, | |
| 426 | + v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap, | |
| 426 | 427 | &ov2640_info, NULL); |
| 427 | 428 | if (NULL == subdev) { |
| 428 | 429 | ret = -ENODEV; |
| @@ -437,8 +438,8 @@ int em28xx_init_camera(struct em28xx *dev) · 8 unmodified lines | ||
| 437 | 438 | /* NOTE: for UXGA=1600x1200 switch to 12MHz */ |
| 438 | 439 | dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ; |
| 439 | 440 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); |
| 440 | − dev->vinmode = 0x08; | |
| 441 | − dev->vinctl = 0x00; | |
| 441 | + v4l2->vinmode = 0x08; | |
| 442 | + v4l2->vinctl = 0x00; | |
| 442 | 443 | |
| 443 | 444 | break; |
| 444 | 445 | } |
| @@ -448,8 +449,8 @@ int em28xx_init_camera(struct em28xx *dev) · 3 unmodified lines | ||
| 448 | 449 | } |
| 449 | 450 | |
| 450 | 451 | if (ret < 0) { |
| 451 | − v4l2_clk_unregister_fixed(dev->clk); | |
| 452 | − dev->clk = NULL; | |
| 452 | + v4l2_clk_unregister_fixed(v4l2->clk); | |
| 453 | + v4l2->clk = NULL; | |
| 453 | 454 | } |
| 454 | 455 | |
| 455 | 456 | return ret; |
| @@ -467,6 +467,18 @@ static struct em28xx_reg_seq speedlink_vad_laplace_reg_seq[] = { · 466 unmodified lines | ||
| 467 | 467 | { -1, -1, -1, -1}, |
| 468 | 468 | }; |
| 469 | 469 | |
| 470 | +static struct em28xx_reg_seq pctv_292e[] = { | |
| 471 | + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0}, | |
| 472 | + {0x0d, 0xff, 0xff, 950}, | |
| 473 | + {EM2874_R80_GPIO_P0_CTRL, 0xbd, 0xff, 100}, | |
| 474 | + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 410}, | |
| 475 | + {EM2874_R80_GPIO_P0_CTRL, 0x7d, 0xff, 300}, | |
| 476 | + {EM2874_R80_GPIO_P0_CTRL, 0x7c, 0xff, 60}, | |
| 477 | + {0x0d, 0x42, 0xff, 50}, | |
| 478 | + {EM2874_R5F_TS_ENABLE, 0x85, 0xff, 0}, | |
| 479 | + {-1, -1, -1, -1}, | |
| 480 | +}; | |
| 481 | + | |
| 470 | 482 | /* |
| 471 | 483 | * Button definitions |
| 472 | 484 | */ |
| @@ -2220,6 +2232,17 @@ struct em28xx_board em28xx_boards[] = { · 1747 unmodified lines | ||
| 2220 | 2232 | .has_dvb = 1, |
| 2221 | 2233 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, |
| 2222 | 2234 | }, |
| 2235 | + /* 2013:025f PCTV tripleStick (292e). | |
| 2236 | + * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 */ | |
| 2237 | + [EM28178_BOARD_PCTV_292E] = { | |
| 2238 | + .name = "PCTV tripleStick (292e)", | |
| 2239 | + .def_i2c_bus = 1, | |
| 2240 | + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, | |
| 2241 | + .tuner_type = TUNER_ABSENT, | |
| 2242 | + .tuner_gpio = pctv_292e, | |
| 2243 | + .has_dvb = 1, | |
| 2244 | + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, | |
| 2245 | + }, | |
| 2223 | 2246 | }; |
| 2224 | 2247 | EXPORT_SYMBOL_GPL(em28xx_boards); |
| 2225 | 2248 | |
| @@ -2397,6 +2420,8 @@ struct usb_device_id em28xx_id_table[] = { · 171 unmodified lines | ||
| 2397 | 2420 | .driver_info = EM2765_BOARD_SPEEDLINK_VAD_LAPLACE }, |
| 2398 | 2421 | { USB_DEVICE(0x2013, 0x0258), |
| 2399 | 2422 | .driver_info = EM28178_BOARD_PCTV_461E }, |
| 2423 | + { USB_DEVICE(0x2013, 0x025f), | |
| 2424 | + .driver_info = EM28178_BOARD_PCTV_292E }, | |
| 2400 | 2425 | { }, |
| 2401 | 2426 | }; |
| 2402 | 2427 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
| @@ -2682,8 +2707,6 @@ static void em28xx_card_setup(struct em28xx *dev) · 279 unmodified lines | ||
| 2682 | 2707 | if (dev->board.is_webcam) { |
| 2683 | 2708 | if (em28xx_detect_sensor(dev) < 0) |
| 2684 | 2709 | dev->board.is_webcam = 0; |
| 2685 | − else | |
| 2686 | − dev->progressive = 1; | |
| 2687 | 2710 | } |
| 2688 | 2711 | |
| 2689 | 2712 | switch (dev->model) { |
| @@ -2718,11 +2741,6 @@ static void em28xx_card_setup(struct em28xx *dev) · 28 unmodified lines | ||
| 2718 | 2741 | dev->board.name, dev->model); |
| 2719 | 2742 | |
| 2720 | 2743 | dev->tuner_type = em28xx_boards[dev->model].tuner_type; |
| 2721 | − if (em28xx_boards[dev->model].tuner_addr) | |
| 2722 | − dev->tuner_addr = em28xx_boards[dev->model].tuner_addr; | |
| 2723 | − | |
| 2724 | − if (em28xx_boards[dev->model].tda9887_conf) | |
| 2725 | − dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; | |
| 2726 | 2744 | |
| 2727 | 2745 | /* request some modules */ |
| 2728 | 2746 | switch (dev->model) { |
| @@ -2991,8 +3009,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, · 262 unmodified lines | ||
| 2991 | 3009 | const char *chip_name = default_chip_name; |
| 2992 | 3010 | |
| 2993 | 3011 | dev->udev = udev; |
| 2994 | − mutex_init(&dev->vb_queue_lock); | |
| 2995 | − mutex_init(&dev->vb_vbi_queue_lock); | |
| 2996 | 3012 | mutex_init(&dev->ctrl_urb_lock); |
| 2997 | 3013 | spin_lock_init(&dev->slock); |
| 2998 | 3014 | |
| @@ -3416,15 +3432,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, · 417 unmodified lines | ||
| 3416 | 3432 | |
| 3417 | 3433 | /* Select USB transfer types to use */ |
| 3418 | 3434 | if (has_video) { |
| 3419 | − if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) | |
| 3420 | − dev->analog_xfer_bulk = 1; | |
| 3421 | − em28xx_info("analog set to %s mode.\n", | |
| 3422 | − dev->analog_xfer_bulk ? "bulk" : "isoc"); | |
| 3435 | + if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) | |
| 3436 | + dev->analog_xfer_bulk = 1; | |
| 3437 | + em28xx_info("analog set to %s mode.\n", | |
| 3438 | + dev->analog_xfer_bulk ? "bulk" : "isoc"); | |
| 3423 | 3439 | } |
| 3424 | 3440 | if (has_dvb) { |
| 3425 | − if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk)) | |
| 3426 | − dev->dvb_xfer_bulk = 1; | |
| 3427 | − | |
| 3441 | + if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk)) | |
| 3442 | + dev->dvb_xfer_bulk = 1; | |
| 3428 | 3443 | em28xx_info("dvb set to %s mode.\n", |
| 3429 | 3444 | dev->dvb_xfer_bulk ? "bulk" : "isoc"); |
| 3430 | 3445 | } |
| @@ -55,6 +55,8 @@ · 54 unmodified lines | ||
| 55 | 55 | #include "mb86a20s.h" |
| 56 | 56 | #include "m88ds3103.h" |
| 57 | 57 | #include "m88ts2022.h" |
| 58 | +#include "si2168.h" | |
| 59 | +#include "si2157.h" | |
| 58 | 60 | |
| 59 | 61 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
| 60 | 62 | MODULE_LICENSE("GPL"); |
| @@ -93,6 +95,7 @@ struct em28xx_dvb { · 32 unmodified lines | ||
| 93 | 95 | struct semaphore pll_mutex; |
| 94 | 96 | bool dont_attach_fe1; |
| 95 | 97 | int lna_gpio; |
| 98 | + struct i2c_client *i2c_client_demod; | |
| 96 | 99 | struct i2c_client *i2c_client_tuner; |
| 97 | 100 | }; |
| 98 | 101 | |
| @@ -743,6 +746,21 @@ static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) · 644 unmodified lines | ||
| 743 | 746 | #endif |
| 744 | 747 | } |
| 745 | 748 | |
| 749 | +static int em28xx_pctv_292e_set_lna(struct dvb_frontend *fe) | |
| 750 | +{ | |
| 751 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 752 | + struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; | |
| 753 | + struct em28xx *dev = i2c_bus->dev; | |
| 754 | + u8 lna; | |
| 755 | + | |
| 756 | + if (c->lna == 1) | |
| 757 | + lna = 0x01; | |
| 758 | + else | |
| 759 | + lna = 0x00; | |
| 760 | + | |
| 761 | + return em28xx_write_reg_bits(dev, EM2874_R80_GPIO_P0_CTRL, lna, 0x01); | |
| 762 | +} | |
| 763 | + | |
| 746 | 764 | static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) |
| 747 | 765 | { |
| 748 | 766 | /* Values extracted from a USB trace of the Terratec Windows driver */ |
| @@ -1496,6 +1514,63 @@ static int em28xx_dvb_init(struct em28xx *dev) · 747 unmodified lines | ||
| 1496 | 1514 | dvb->i2c_client_tuner = client; |
| 1497 | 1515 | } |
| 1498 | 1516 | break; |
| 1517 | + case EM28178_BOARD_PCTV_292E: | |
| 1518 | + { | |
| 1519 | + struct i2c_adapter *adapter; | |
| 1520 | + struct i2c_client *client; | |
| 1521 | + struct i2c_board_info info; | |
| 1522 | + struct si2168_config si2168_config; | |
| 1523 | + struct si2157_config si2157_config; | |
| 1524 | + | |
| 1525 | + /* attach demod */ | |
| 1526 | + si2168_config.i2c_adapter = &adapter; | |
| 1527 | + si2168_config.fe = &dvb->fe[0]; | |
| 1528 | + memset(&info, 0, sizeof(struct i2c_board_info)); | |
| 1529 | + strlcpy(info.type, "si2168", I2C_NAME_SIZE); | |
| 1530 | + info.addr = 0x64; | |
| 1531 | + info.platform_data = &si2168_config; | |
| 1532 | + request_module(info.type); | |
| 1533 | + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); | |
| 1534 | + if (client == NULL || client->dev.driver == NULL) { | |
| 1535 | + result = -ENODEV; | |
| 1536 | + goto out_free; | |
| 1537 | + } | |
| 1538 | + | |
| 1539 | + if (!try_module_get(client->dev.driver->owner)) { | |
| 1540 | + i2c_unregister_device(client); | |
| 1541 | + result = -ENODEV; | |
| 1542 | + goto out_free; | |
| 1543 | + } | |
| 1544 | + | |
| 1545 | + dvb->i2c_client_demod = client; | |
| 1546 | + | |
| 1547 | + /* attach tuner */ | |
| 1548 | + si2157_config.fe = dvb->fe[0]; | |
| 1549 | + memset(&info, 0, sizeof(struct i2c_board_info)); | |
| 1550 | + strlcpy(info.type, "si2157", I2C_NAME_SIZE); | |
| 1551 | + info.addr = 0x60; | |
| 1552 | + info.platform_data = &si2157_config; | |
| 1553 | + request_module(info.type); | |
| 1554 | + client = i2c_new_device(adapter, &info); | |
| 1555 | + if (client == NULL || client->dev.driver == NULL) { | |
| 1556 | + module_put(dvb->i2c_client_demod->dev.driver->owner); | |
| 1557 | + i2c_unregister_device(dvb->i2c_client_demod); | |
| 1558 | + result = -ENODEV; | |
| 1559 | + goto out_free; | |
| 1560 | + } | |
| 1561 | + | |
| 1562 | + if (!try_module_get(client->dev.driver->owner)) { | |
| 1563 | + i2c_unregister_device(client); | |
| 1564 | + module_put(dvb->i2c_client_demod->dev.driver->owner); | |
| 1565 | + i2c_unregister_device(dvb->i2c_client_demod); | |
| 1566 | + result = -ENODEV; | |
| 1567 | + goto out_free; | |
| 1568 | + } | |
| 1569 | + | |
| 1570 | + dvb->i2c_client_tuner = client; | |
| 1571 | + dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna; | |
| 1572 | + } | |
| 1573 | + break; | |
| 1499 | 1574 | default: |
| 1500 | 1575 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
| 1501 | 1576 | " isn't supported yet\n"); |
| @@ -1582,6 +1657,13 @@ static int em28xx_dvb_fini(struct em28xx *dev) · 80 unmodified lines | ||
| 1582 | 1657 | i2c_unregister_device(client); |
| 1583 | 1658 | } |
| 1584 | 1659 | |
| 1660 | + /* remove I2C demod */ | |
| 1661 | + client = dvb->i2c_client_demod; | |
| 1662 | + if (client) { | |
| 1663 | + module_put(client->dev.driver->owner); | |
| 1664 | + i2c_unregister_device(client); | |
| 1665 | + } | |
| 1666 | + | |
| 1585 | 1667 | em28xx_unregister_dvb(dvb); |
| 1586 | 1668 | kfree(dvb); |
| 1587 | 1669 | dev->dvb = NULL; |
| @@ -1647,6 +1729,13 @@ static int em28xx_dvb_resume(struct em28xx *dev) · 59 unmodified lines | ||
| 1647 | 1729 | i2c_unregister_device(client); |
| 1648 | 1730 | } |
| 1649 | 1731 | |
| 1732 | + /* remove I2C demod */ | |
| 1733 | + client = dvb->i2c_client_demod; | |
| 1734 | + if (client) { | |
| 1735 | + module_put(client->dev.driver->owner); | |
| 1736 | + i2c_unregister_device(client); | |
| 1737 | + } | |
| 1738 | + | |
| 1650 | 1739 | em28xx_unregister_dvb(dvb); |
| 1651 | 1740 | kfree(dvb); |
| 1652 | 1741 | dev->dvb = NULL; |
| @@ -939,7 +939,6 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned bus, · 938 unmodified lines | ||
| 939 | 939 | dev->i2c_bus[bus].algo_type = algo_type; |
| 940 | 940 | dev->i2c_bus[bus].dev = dev; |
| 941 | 941 | dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus]; |
| 942 | − i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev); | |
| 943 | 942 | |
| 944 | 943 | retval = i2c_add_adapter(&dev->i2c_adap[bus]); |
| 945 | 944 | if (retval < 0) { |
| @@ -16,5 +16,5 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | |
| 18 | 18 | int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count); |
| 19 | −int em28xx_stop_vbi_streaming(struct vb2_queue *vq); | |
| 19 | +void em28xx_stop_vbi_streaming(struct vb2_queue *vq); | |
| 20 | 20 | extern struct vb2_ops em28xx_vbi_qops; |
| @@ -47,12 +47,13 @@ static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 46 unmodified lines | ||
| 47 | 47 | unsigned int sizes[], void *alloc_ctxs[]) |
| 48 | 48 | { |
| 49 | 49 | struct em28xx *dev = vb2_get_drv_priv(vq); |
| 50 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 50 | 51 | unsigned long size; |
| 51 | 52 | |
| 52 | 53 | if (fmt) |
| 53 | 54 | size = fmt->fmt.pix.sizeimage; |
| 54 | 55 | else |
| 55 | − size = dev->vbi_width * dev->vbi_height * 2; | |
| 56 | + size = v4l2->vbi_width * v4l2->vbi_height * 2; | |
| 56 | 57 | |
| 57 | 58 | if (0 == *nbuffers) |
| 58 | 59 | *nbuffers = 32; |
| @@ -69,11 +70,12 @@ static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 10 unmodified lines | ||
| 69 | 70 | |
| 70 | 71 | static int vbi_buffer_prepare(struct vb2_buffer *vb) |
| 71 | 72 | { |
| 72 | − struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); | |
| 73 | − struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); | |
| 73 | + struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); | |
| 74 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 75 | + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); | |
| 74 | 76 | unsigned long size; |
| 75 | 77 | |
| 76 | − size = dev->vbi_width * dev->vbi_height * 2; | |
| 78 | + size = v4l2->vbi_width * v4l2->vbi_height * 2; | |
| 77 | 79 | |
| 78 | 80 | if (vb2_plane_size(vb, 0) < size) { |
| 79 | 81 | printk(KERN_INFO "%s data will not fit into plane (%lu < %lu)\n", |
| @@ -141,6 +141,33 @@ static struct em28xx_fmt format[] = { · 140 unmodified lines | ||
| 141 | 141 | }, |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | +/*FIXME: maxw should be dependent of alt mode */ | |
| 145 | +static inline unsigned int norm_maxw(struct em28xx *dev) | |
| 146 | +{ | |
| 147 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 148 | + | |
| 149 | + if (dev->board.is_webcam) | |
| 150 | + return v4l2->sensor_xres; | |
| 151 | + | |
| 152 | + if (dev->board.max_range_640_480) | |
| 153 | + return 640; | |
| 154 | + | |
| 155 | + return 720; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static inline unsigned int norm_maxh(struct em28xx *dev) | |
| 159 | +{ | |
| 160 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 161 | + | |
| 162 | + if (dev->board.is_webcam) | |
| 163 | + return v4l2->sensor_yres; | |
| 164 | + | |
| 165 | + if (dev->board.max_range_640_480) | |
| 166 | + return 480; | |
| 167 | + | |
| 168 | + return (v4l2->norm & V4L2_STD_625_50) ? 576 : 480; | |
| 169 | +} | |
| 170 | + | |
| 144 | 171 | static int em28xx_vbi_supported(struct em28xx *dev) |
| 145 | 172 | { |
| 146 | 173 | /* Modprobe option to manually disable */ |
| @@ -166,10 +193,11 @@ static int em28xx_vbi_supported(struct em28xx *dev) · 19 unmodified lines | ||
| 166 | 193 | */ |
| 167 | 194 | static void em28xx_wake_i2c(struct em28xx *dev) |
| 168 | 195 | { |
| 169 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); | |
| 170 | − v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, | |
| 196 | + struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev; | |
| 197 | + v4l2_device_call_all(v4l2_dev, 0, core, reset, 0); | |
| 198 | + v4l2_device_call_all(v4l2_dev, 0, video, s_routing, | |
| 171 | 199 | INPUT(dev->ctl_input)->vmux, 0, 0); |
| 172 | − v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); | |
| 200 | + v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0); | |
| 173 | 201 | } |
| 174 | 202 | |
| 175 | 203 | static int em28xx_colorlevels_set_default(struct em28xx *dev) |
| @@ -194,8 +222,9 @@ static int em28xx_set_outfmt(struct em28xx *dev) · 18 unmodified lines | ||
| 194 | 222 | { |
| 195 | 223 | int ret; |
| 196 | 224 | u8 fmt, vinctrl; |
| 225 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 197 | 226 | |
| 198 | − fmt = dev->format->reg; | |
| 227 | + fmt = v4l2->format->reg; | |
| 199 | 228 | if (!dev->is_em25xx) |
| 200 | 229 | fmt |= 0x20; |
| 201 | 230 | /* |
| @@ -211,20 +240,20 @@ static int em28xx_set_outfmt(struct em28xx *dev) · 9 unmodified lines | ||
| 211 | 240 | if (ret < 0) |
| 212 | 241 | return ret; |
| 213 | 242 | |
| 214 | − ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode); | |
| 243 | + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode); | |
| 215 | 244 | if (ret < 0) |
| 216 | 245 | return ret; |
| 217 | 246 | |
| 218 | − vinctrl = dev->vinctl; | |
| 247 | + vinctrl = v4l2->vinctl; | |
| 219 | 248 | if (em28xx_vbi_supported(dev) == 1) { |
| 220 | 249 | vinctrl |= EM28XX_VINCTRL_VBI_RAW; |
| 221 | 250 | em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); |
| 222 | − em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4); | |
| 223 | − em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height); | |
| 224 | − if (dev->norm & V4L2_STD_525_60) { | |
| 251 | + em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4); | |
| 252 | + em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height); | |
| 253 | + if (v4l2->norm & V4L2_STD_525_60) { | |
| 225 | 254 | /* NTSC */ |
| 226 | 255 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); |
| 227 | − } else if (dev->norm & V4L2_STD_625_50) { | |
| 256 | + } else if (v4l2->norm & V4L2_STD_625_50) { | |
| 228 | 257 | /* PAL */ |
| 229 | 258 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07); |
| 230 | 259 | } |
| @@ -274,7 +303,7 @@ static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, · 43 unmodified lines | ||
| 274 | 303 | |
| 275 | 304 | static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) |
| 276 | 305 | { |
| 277 | − u8 mode; | |
| 306 | + u8 mode = 0x00; | |
| 278 | 307 | /* the em2800 scaler only supports scaling down to 50% */ |
| 279 | 308 | |
| 280 | 309 | if (dev->board.is_em2800) { |
| @@ -293,22 +322,22 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) · 12 unmodified lines | ||
| 293 | 322 | to work correctly */ |
| 294 | 323 | mode = (h || v) ? 0x30 : 0x00; |
| 295 | 324 | } |
| 296 | − return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); | |
| 325 | + return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode); | |
| 297 | 326 | } |
| 298 | 327 | |
| 299 | 328 | /* FIXME: this only function read values from dev */ |
| 300 | 329 | static int em28xx_resolution_set(struct em28xx *dev) |
| 301 | 330 | { |
| 302 | − int width, height; | |
| 303 | − width = norm_maxw(dev); | |
| 304 | − height = norm_maxh(dev); | |
| 331 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 332 | + int width = norm_maxw(dev); | |
| 333 | + int height = norm_maxh(dev); | |
| 305 | 334 | |
| 306 | 335 | /* Properly setup VBI */ |
| 307 | − dev->vbi_width = 720; | |
| 308 | − if (dev->norm & V4L2_STD_525_60) | |
| 309 | − dev->vbi_height = 12; | |
| 336 | + v4l2->vbi_width = 720; | |
| 337 | + if (v4l2->norm & V4L2_STD_525_60) | |
| 338 | + v4l2->vbi_height = 12; | |
| 310 | 339 | else |
| 311 | − dev->vbi_height = 18; | |
| 340 | + v4l2->vbi_height = 18; | |
| 312 | 341 | |
| 313 | 342 | em28xx_set_outfmt(dev); |
| 314 | 343 | |
| @@ -326,15 +355,16 @@ static int em28xx_resolution_set(struct em28xx *dev) · 11 unmodified lines | ||
| 326 | 355 | else |
| 327 | 356 | em28xx_capture_area_set(dev, 0, 0, width, height); |
| 328 | 357 | |
| 329 | − return em28xx_scaler_set(dev, dev->hscale, dev->vscale); | |
| 358 | + return em28xx_scaler_set(dev, v4l2->hscale, v4l2->vscale); | |
| 330 | 359 | } |
| 331 | 360 | |
| 332 | 361 | /* Set USB alternate setting for analog video */ |
| 333 | 362 | static int em28xx_set_alternate(struct em28xx *dev) |
| 334 | 363 | { |
| 364 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 335 | 365 | int errCode; |
| 336 | 366 | int i; |
| 337 | − unsigned int min_pkt_size = dev->width * 2 + 4; | |
| 367 | + unsigned int min_pkt_size = v4l2->width * 2 + 4; | |
| 338 | 368 | |
| 339 | 369 | /* NOTE: for isoc transfers, only alt settings > 0 are allowed |
| 340 | 370 | bulk transfers seem to work only with alt=0 ! */ |
| @@ -351,7 +381,7 @@ static int em28xx_set_alternate(struct em28xx *dev) · 10 unmodified lines | ||
| 351 | 381 | the frame size should be increased, otherwise, only |
| 352 | 382 | green screen will be received. |
| 353 | 383 | */ |
| 354 | − if (dev->width * 2 * dev->height > 720 * 240 * 2) | |
| 384 | + if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2) | |
| 355 | 385 | min_pkt_size *= 2; |
| 356 | 386 | |
| 357 | 387 | for (i = 0; i < dev->num_alt; i++) { |
| @@ -404,7 +434,7 @@ static inline void finish_buffer(struct em28xx *dev, · 46 unmodified lines | ||
| 404 | 434 | { |
| 405 | 435 | em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field); |
| 406 | 436 | |
| 407 | − buf->vb.v4l2_buf.sequence = dev->field_count++; | |
| 437 | + buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++; | |
| 408 | 438 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
| 409 | 439 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
| 410 | 440 | |
| @@ -419,9 +449,10 @@ static void em28xx_copy_video(struct em28xx *dev, · 8 unmodified lines | ||
| 419 | 449 | unsigned char *usb_buf, |
| 420 | 450 | unsigned long len) |
| 421 | 451 | { |
| 452 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 422 | 453 | void *fieldstart, *startwrite, *startread; |
| 423 | 454 | int linesdone, currlinedone, offset, lencopy, remain; |
| 424 | − int bytesperline = dev->width << 1; | |
| 455 | + int bytesperline = v4l2->width << 1; | |
| 425 | 456 | |
| 426 | 457 | if (buf->pos + len > buf->length) |
| 427 | 458 | len = buf->length - buf->pos; |
| @@ -429,7 +460,7 @@ static void em28xx_copy_video(struct em28xx *dev, · 1 unmodified line | ||
| 429 | 460 | startread = usb_buf; |
| 430 | 461 | remain = len; |
| 431 | 462 | |
| 432 | − if (dev->progressive || buf->top_field) | |
| 463 | + if (v4l2->progressive || buf->top_field) | |
| 433 | 464 | fieldstart = buf->vb_buf; |
| 434 | 465 | else /* interlaced mode, even nr. of lines */ |
| 435 | 466 | fieldstart = buf->vb_buf + bytesperline; |
| @@ -437,7 +468,7 @@ static void em28xx_copy_video(struct em28xx *dev, · 1 unmodified line | ||
| 437 | 468 | linesdone = buf->pos / bytesperline; |
| 438 | 469 | currlinedone = buf->pos % bytesperline; |
| 439 | 470 | |
| 440 | − if (dev->progressive) | |
| 471 | + if (v4l2->progressive) | |
| 441 | 472 | offset = linesdone * bytesperline + currlinedone; |
| 442 | 473 | else |
| 443 | 474 | offset = linesdone * bytesperline * 2 + currlinedone; |
| @@ -461,7 +492,7 @@ static void em28xx_copy_video(struct em28xx *dev, · 17 unmodified lines | ||
| 461 | 492 | remain -= lencopy; |
| 462 | 493 | |
| 463 | 494 | while (remain > 0) { |
| 464 | − if (dev->progressive) | |
| 495 | + if (v4l2->progressive) | |
| 465 | 496 | startwrite += lencopy; |
| 466 | 497 | else |
| 467 | 498 | startwrite += lencopy + bytesperline; |
| @@ -507,7 +538,7 @@ static void em28xx_copy_vbi(struct em28xx *dev, · 39 unmodified lines | ||
| 507 | 538 | offset = buf->pos; |
| 508 | 539 | /* Make sure the bottom field populates the second half of the frame */ |
| 509 | 540 | if (buf->top_field == 0) |
| 510 | − offset += dev->vbi_width * dev->vbi_height; | |
| 541 | + offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height; | |
| 511 | 542 | |
| 512 | 543 | memcpy(buf->vb_buf + offset, usb_buf, len); |
| 513 | 544 | buf->pos += len; |
| @@ -583,13 +614,15 @@ finish_field_prepare_next(struct em28xx *dev, · 69 unmodified lines | ||
| 583 | 614 | struct em28xx_buffer *buf, |
| 584 | 615 | struct em28xx_dmaqueue *dma_q) |
| 585 | 616 | { |
| 586 | − if (dev->progressive || dev->top_field) { /* Brand new frame */ | |
| 617 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 618 | + | |
| 619 | + if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */ | |
| 587 | 620 | if (buf != NULL) |
| 588 | 621 | finish_buffer(dev, buf); |
| 589 | 622 | buf = get_next_buf(dev, dma_q); |
| 590 | 623 | } |
| 591 | 624 | if (buf != NULL) { |
| 592 | − buf->top_field = dev->top_field; | |
| 625 | + buf->top_field = v4l2->top_field; | |
| 593 | 626 | buf->pos = 0; |
| 594 | 627 | } |
| 595 | 628 | |
| @@ -603,6 +636,7 @@ static inline void process_frame_data_em28xx(struct em28xx *dev, · 7 unmodified lines | ||
| 603 | 636 | unsigned char *data_pkt, |
| 604 | 637 | unsigned int data_len) |
| 605 | 638 | { |
| 639 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 606 | 640 | struct em28xx_buffer *buf = dev->usb_ctl.vid_buf; |
| 607 | 641 | struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf; |
| 608 | 642 | struct em28xx_dmaqueue *dma_q = &dev->vidq; |
| @@ -622,17 +656,17 @@ static inline void process_frame_data_em28xx(struct em28xx *dev, · 13 unmodified lines | ||
| 622 | 656 | data_len -= 4; |
| 623 | 657 | } else if (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) { |
| 624 | 658 | /* Field start (VBI mode) */ |
| 625 | − dev->capture_type = 0; | |
| 626 | − dev->vbi_read = 0; | |
| 659 | + v4l2->capture_type = 0; | |
| 660 | + v4l2->vbi_read = 0; | |
| 627 | 661 | em28xx_isocdbg("VBI START HEADER !!!\n"); |
| 628 | − dev->top_field = !(data_pkt[2] & 1); | |
| 662 | + v4l2->top_field = !(data_pkt[2] & 1); | |
| 629 | 663 | data_pkt += 4; |
| 630 | 664 | data_len -= 4; |
| 631 | 665 | } else if (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) { |
| 632 | 666 | /* Field start (VBI disabled) */ |
| 633 | − dev->capture_type = 2; | |
| 667 | + v4l2->capture_type = 2; | |
| 634 | 668 | em28xx_isocdbg("VIDEO START HEADER !!!\n"); |
| 635 | − dev->top_field = !(data_pkt[2] & 1); | |
| 669 | + v4l2->top_field = !(data_pkt[2] & 1); | |
| 636 | 670 | data_pkt += 4; |
| 637 | 671 | data_len -= 4; |
| 638 | 672 | } |
| @@ -640,37 +674,37 @@ static inline void process_frame_data_em28xx(struct em28xx *dev, · 1 unmodified line | ||
| 640 | 674 | /* NOTE: With bulk transfers, intermediate data packets |
| 641 | 675 | * have no continuation header */ |
| 642 | 676 | |
| 643 | − if (dev->capture_type == 0) { | |
| 677 | + if (v4l2->capture_type == 0) { | |
| 644 | 678 | vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q); |
| 645 | 679 | dev->usb_ctl.vbi_buf = vbi_buf; |
| 646 | − dev->capture_type = 1; | |
| 680 | + v4l2->capture_type = 1; | |
| 647 | 681 | } |
| 648 | 682 | |
| 649 | − if (dev->capture_type == 1) { | |
| 650 | − int vbi_size = dev->vbi_width * dev->vbi_height; | |
| 651 | − int vbi_data_len = ((dev->vbi_read + data_len) > vbi_size) ? | |
| 652 | − (vbi_size - dev->vbi_read) : data_len; | |
| 683 | + if (v4l2->capture_type == 1) { | |
| 684 | + int vbi_size = v4l2->vbi_width * v4l2->vbi_height; | |
| 685 | + int vbi_data_len = ((v4l2->vbi_read + data_len) > vbi_size) ? | |
| 686 | + (vbi_size - v4l2->vbi_read) : data_len; | |
| 653 | 687 | |
| 654 | 688 | /* Copy VBI data */ |
| 655 | 689 | if (vbi_buf != NULL) |
| 656 | 690 | em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len); |
| 657 | − dev->vbi_read += vbi_data_len; | |
| 691 | + v4l2->vbi_read += vbi_data_len; | |
| 658 | 692 | |
| 659 | 693 | if (vbi_data_len < data_len) { |
| 660 | 694 | /* Continue with copying video data */ |
| 661 | − dev->capture_type = 2; | |
| 695 | + v4l2->capture_type = 2; | |
| 662 | 696 | data_pkt += vbi_data_len; |
| 663 | 697 | data_len -= vbi_data_len; |
| 664 | 698 | } |
| 665 | 699 | } |
| 666 | 700 | |
| 667 | − if (dev->capture_type == 2) { | |
| 701 | + if (v4l2->capture_type == 2) { | |
| 668 | 702 | buf = finish_field_prepare_next(dev, buf, dma_q); |
| 669 | 703 | dev->usb_ctl.vid_buf = buf; |
| 670 | − dev->capture_type = 3; | |
| 704 | + v4l2->capture_type = 3; | |
| 671 | 705 | } |
| 672 | 706 | |
| 673 | − if (dev->capture_type == 3 && buf != NULL && data_len > 0) | |
| 707 | + if (v4l2->capture_type == 3 && buf != NULL && data_len > 0) | |
| 674 | 708 | em28xx_copy_video(dev, buf, data_pkt, data_len); |
| 675 | 709 | } |
| 676 | 710 | |
| @@ -683,6 +717,7 @@ static inline void process_frame_data_em25xx(struct em28xx *dev, · 6 unmodified lines | ||
| 683 | 717 | { |
| 684 | 718 | struct em28xx_buffer *buf = dev->usb_ctl.vid_buf; |
| 685 | 719 | struct em28xx_dmaqueue *dmaq = &dev->vidq; |
| 720 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 686 | 721 | bool frame_end = 0; |
| 687 | 722 | |
| 688 | 723 | /* Check for header */ |
| @@ -691,7 +726,7 @@ static inline void process_frame_data_em25xx(struct em28xx *dev, · 2 unmodified lines | ||
| 691 | 726 | if (data_len >= 2) { /* em25xx header is only 2 bytes long */ |
| 692 | 727 | if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) && |
| 693 | 728 | ((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) { |
| 694 | − dev->top_field = !(data_pkt[1] & | |
| 729 | + v4l2->top_field = !(data_pkt[1] & | |
| 695 | 730 | EM25XX_FRMDATAHDR_BYTE2_FRAME_ID); |
| 696 | 731 | frame_end = data_pkt[1] & |
| 697 | 732 | EM25XX_FRMDATAHDR_BYTE2_FRAME_END; |
| @@ -841,12 +876,14 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, · 143 unmodified lines | ||
| 841 | 876 | unsigned int sizes[], void *alloc_ctxs[]) |
| 842 | 877 | { |
| 843 | 878 | struct em28xx *dev = vb2_get_drv_priv(vq); |
| 879 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 844 | 880 | unsigned long size; |
| 845 | 881 | |
| 846 | 882 | if (fmt) |
| 847 | 883 | size = fmt->fmt.pix.sizeimage; |
| 848 | 884 | else |
| 849 | − size = (dev->width * dev->height * dev->format->depth + 7) >> 3; | |
| 885 | + size = | |
| 886 | + (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3; | |
| 850 | 887 | |
| 851 | 888 | if (size == 0) |
| 852 | 889 | return -EINVAL; |
| @@ -864,12 +901,13 @@ static int · 11 unmodified lines | ||
| 864 | 901 | buffer_prepare(struct vb2_buffer *vb) |
| 865 | 902 | { |
| 866 | 903 | struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); |
| 904 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 867 | 905 | struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); |
| 868 | 906 | unsigned long size; |
| 869 | 907 | |
| 870 | 908 | em28xx_videodbg("%s, field=%d\n", __func__, vb->v4l2_buf.field); |
| 871 | 909 | |
| 872 | − size = (dev->width * dev->height * dev->format->depth + 7) >> 3; | |
| 910 | + size = (v4l2->width * v4l2->height * v4l2->format->depth + 7) >> 3; | |
| 873 | 911 | |
| 874 | 912 | if (vb2_plane_size(vb, 0) < size) { |
| 875 | 913 | em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n", |
| @@ -884,6 +922,7 @@ buffer_prepare(struct vb2_buffer *vb) · 8 unmodified lines | ||
| 884 | 922 | int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) |
| 885 | 923 | { |
| 886 | 924 | struct em28xx *dev = vb2_get_drv_priv(vq); |
| 925 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 887 | 926 | struct v4l2_frequency f; |
| 888 | 927 | int rc = 0; |
| 889 | 928 | |
| @@ -895,7 +934,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) · 5 unmodified lines | ||
| 895 | 934 | if (rc) |
| 896 | 935 | return rc; |
| 897 | 936 | |
| 898 | − if (dev->streaming_users == 0) { | |
| 937 | + if (v4l2->streaming_users == 0) { | |
| 899 | 938 | /* First active streaming user, so allocate all the URBs */ |
| 900 | 939 | |
| 901 | 940 | /* Allocate the USB bandwidth */ |
| @@ -906,7 +945,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) · 4 unmodified lines | ||
| 906 | 945 | */ |
| 907 | 946 | em28xx_wake_i2c(dev); |
| 908 | 947 | |
| 909 | − dev->capture_type = -1; | |
| 948 | + v4l2->capture_type = -1; | |
| 910 | 949 | rc = em28xx_init_usb_xfer(dev, EM28XX_ANALOG_MODE, |
| 911 | 950 | dev->analog_xfer_bulk, |
| 912 | 951 | EM28XX_NUM_BUFS, |
| @@ -924,22 +963,24 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) · 11 unmodified lines | ||
| 924 | 963 | |
| 925 | 964 | /* Ask tuner to go to analog or radio mode */ |
| 926 | 965 | memset(&f, 0, sizeof(f)); |
| 927 | − f.frequency = dev->ctl_freq; | |
| 966 | + f.frequency = v4l2->frequency; | |
| 928 | 967 | if (vq->owner && vq->owner->vdev->vfl_type == VFL_TYPE_RADIO) |
| 929 | 968 | f.type = V4L2_TUNER_RADIO; |
| 930 | 969 | else |
| 931 | 970 | f.type = V4L2_TUNER_ANALOG_TV; |
| 932 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); | |
| 971 | + v4l2_device_call_all(&v4l2->v4l2_dev, | |
| 972 | + 0, tuner, s_frequency, &f); | |
| 933 | 973 | } |
| 934 | 974 | |
| 935 | − dev->streaming_users++; | |
| 975 | + v4l2->streaming_users++; | |
| 936 | 976 | |
| 937 | 977 | return rc; |
| 938 | 978 | } |
| 939 | 979 | |
| 940 | −static int em28xx_stop_streaming(struct vb2_queue *vq) | |
| 980 | +static void em28xx_stop_streaming(struct vb2_queue *vq) | |
| 941 | 981 | { |
| 942 | 982 | struct em28xx *dev = vb2_get_drv_priv(vq); |
| 983 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 943 | 984 | struct em28xx_dmaqueue *vidq = &dev->vidq; |
| 944 | 985 | unsigned long flags = 0; |
| 945 | 986 | |
| @@ -947,7 +988,7 @@ static int em28xx_stop_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 947 | 988 | |
| 948 | 989 | res_free(dev, vq->type); |
| 949 | 990 | |
| 950 | − if (dev->streaming_users-- == 1) { | |
| 991 | + if (v4l2->streaming_users-- == 1) { | |
| 951 | 992 | /* Last active user, so shutdown all the URBS */ |
| 952 | 993 | em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); |
| 953 | 994 | } |
| @@ -961,13 +1002,12 @@ static int em28xx_stop_streaming(struct vb2_queue *vq) · 7 unmodified lines | ||
| 961 | 1002 | } |
| 962 | 1003 | dev->usb_ctl.vid_buf = NULL; |
| 963 | 1004 | spin_unlock_irqrestore(&dev->slock, flags); |
| 964 | − | |
| 965 | − return 0; | |
| 966 | 1005 | } |
| 967 | 1006 | |
| 968 | −int em28xx_stop_vbi_streaming(struct vb2_queue *vq) | |
| 1007 | +void em28xx_stop_vbi_streaming(struct vb2_queue *vq) | |
| 969 | 1008 | { |
| 970 | 1009 | struct em28xx *dev = vb2_get_drv_priv(vq); |
| 1010 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 971 | 1011 | struct em28xx_dmaqueue *vbiq = &dev->vbiq; |
| 972 | 1012 | unsigned long flags = 0; |
| 973 | 1013 | |
| @@ -975,7 +1015,7 @@ int em28xx_stop_vbi_streaming(struct vb2_queue *vq) · 1 unmodified line | ||
| 975 | 1015 | |
| 976 | 1016 | res_free(dev, vq->type); |
| 977 | 1017 | |
| 978 | − if (dev->streaming_users-- == 1) { | |
| 1018 | + if (v4l2->streaming_users-- == 1) { | |
| 979 | 1019 | /* Last active user, so shutdown all the URBS */ |
| 980 | 1020 | em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); |
| 981 | 1021 | } |
| @@ -989,8 +1029,6 @@ int em28xx_stop_vbi_streaming(struct vb2_queue *vq) · 7 unmodified lines | ||
| 989 | 1029 | } |
| 990 | 1030 | dev->usb_ctl.vbi_buf = NULL; |
| 991 | 1031 | spin_unlock_irqrestore(&dev->slock, flags); |
| 992 | − | |
| 993 | − return 0; | |
| 994 | 1032 | } |
| 995 | 1033 | |
| 996 | 1034 | static void |
| @@ -1024,9 +1062,10 @@ static int em28xx_vb2_setup(struct em28xx *dev) · 27 unmodified lines | ||
| 1024 | 1062 | { |
| 1025 | 1063 | int rc; |
| 1026 | 1064 | struct vb2_queue *q; |
| 1065 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1027 | 1066 | |
| 1028 | 1067 | /* Setup Videobuf2 for Video capture */ |
| 1029 | − q = &dev->vb_vidq; | |
| 1068 | + q = &v4l2->vb_vidq; | |
| 1030 | 1069 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 1031 | 1070 | q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
| 1032 | 1071 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
| @@ -1040,7 +1079,7 @@ static int em28xx_vb2_setup(struct em28xx *dev) · 7 unmodified lines | ||
| 1040 | 1079 | return rc; |
| 1041 | 1080 | |
| 1042 | 1081 | /* Setup Videobuf2 for VBI capture */ |
| 1043 | − q = &dev->vb_vbiq; | |
| 1082 | + q = &v4l2->vb_vbiq; | |
| 1044 | 1083 | q->type = V4L2_BUF_TYPE_VBI_CAPTURE; |
| 1045 | 1084 | q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR; |
| 1046 | 1085 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; |
| @@ -1060,6 +1099,7 @@ static int em28xx_vb2_setup(struct em28xx *dev) · 13 unmodified lines | ||
| 1060 | 1099 | |
| 1061 | 1100 | static void video_mux(struct em28xx *dev, int index) |
| 1062 | 1101 | { |
| 1102 | + struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev; | |
| 1063 | 1103 | dev->ctl_input = index; |
| 1064 | 1104 | dev->ctl_ainput = INPUT(index)->amux; |
| 1065 | 1105 | dev->ctl_aoutput = INPUT(index)->aout; |
| @@ -1067,21 +1107,21 @@ static void video_mux(struct em28xx *dev, int index) · 1 unmodified line | ||
| 1067 | 1107 | if (!dev->ctl_aoutput) |
| 1068 | 1108 | dev->ctl_aoutput = EM28XX_AOUT_MASTER; |
| 1069 | 1109 | |
| 1070 | − v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, | |
| 1110 | + v4l2_device_call_all(v4l2_dev, 0, video, s_routing, | |
| 1071 | 1111 | INPUT(index)->vmux, 0, 0); |
| 1072 | 1112 | |
| 1073 | 1113 | if (dev->board.has_msp34xx) { |
| 1074 | 1114 | if (dev->i2s_speed) { |
| 1075 | − v4l2_device_call_all(&dev->v4l2_dev, 0, audio, | |
| 1115 | + v4l2_device_call_all(v4l2_dev, 0, audio, | |
| 1076 | 1116 | s_i2s_clock_freq, dev->i2s_speed); |
| 1077 | 1117 | } |
| 1078 | 1118 | /* Note: this is msp3400 specific */ |
| 1079 | − v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, | |
| 1119 | + v4l2_device_call_all(v4l2_dev, 0, audio, s_routing, | |
| 1080 | 1120 | dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); |
| 1081 | 1121 | } |
| 1082 | 1122 | |
| 1083 | 1123 | if (dev->board.adecoder != EM28XX_NOADECODER) { |
| 1084 | − v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, | |
| 1124 | + v4l2_device_call_all(v4l2_dev, 0, audio, s_routing, | |
| 1085 | 1125 | dev->ctl_ainput, dev->ctl_aoutput, 0); |
| 1086 | 1126 | } |
| 1087 | 1127 | |
| @@ -1112,7 +1152,9 @@ static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv) · 24 unmodified lines | ||
| 1112 | 1152 | |
| 1113 | 1153 | static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl) |
| 1114 | 1154 | { |
| 1115 | − struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler); | |
| 1155 | + struct em28xx_v4l2 *v4l2 = | |
| 1156 | + container_of(ctrl->handler, struct em28xx_v4l2, ctrl_handler); | |
| 1157 | + struct em28xx *dev = v4l2->dev; | |
| 1116 | 1158 | int ret = -EINVAL; |
| 1117 | 1159 | |
| 1118 | 1160 | switch (ctrl->id) { |
| @@ -1187,19 +1229,20 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, · 68 unmodified lines | ||
| 1187 | 1229 | { |
| 1188 | 1230 | struct em28xx_fh *fh = priv; |
| 1189 | 1231 | struct em28xx *dev = fh->dev; |
| 1232 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1190 | 1233 | |
| 1191 | − f->fmt.pix.width = dev->width; | |
| 1192 | − f->fmt.pix.height = dev->height; | |
| 1193 | − f->fmt.pix.pixelformat = dev->format->fourcc; | |
| 1194 | − f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; | |
| 1195 | − f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; | |
| 1234 | + f->fmt.pix.width = v4l2->width; | |
| 1235 | + f->fmt.pix.height = v4l2->height; | |
| 1236 | + f->fmt.pix.pixelformat = v4l2->format->fourcc; | |
| 1237 | + f->fmt.pix.bytesperline = (v4l2->width * v4l2->format->depth + 7) >> 3; | |
| 1238 | + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * v4l2->height; | |
| 1196 | 1239 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 1197 | 1240 | |
| 1198 | 1241 | /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ |
| 1199 | − if (dev->progressive) | |
| 1242 | + if (v4l2->progressive) | |
| 1200 | 1243 | f->fmt.pix.field = V4L2_FIELD_NONE; |
| 1201 | 1244 | else |
| 1202 | − f->fmt.pix.field = dev->interlaced ? | |
| 1245 | + f->fmt.pix.field = v4l2->interlaced_fieldmode ? | |
| 1203 | 1246 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; |
| 1204 | 1247 | return 0; |
| 1205 | 1248 | } |
| @@ -1220,6 +1263,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, · 14 unmodified lines | ||
| 1220 | 1263 | { |
| 1221 | 1264 | struct em28xx_fh *fh = priv; |
| 1222 | 1265 | struct em28xx *dev = fh->dev; |
| 1266 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1223 | 1267 | unsigned int width = f->fmt.pix.width; |
| 1224 | 1268 | unsigned int height = f->fmt.pix.height; |
| 1225 | 1269 | unsigned int maxw = norm_maxw(dev); |
| @@ -1261,10 +1305,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, · 35 unmodified lines | ||
| 1261 | 1305 | f->fmt.pix.bytesperline = (width * fmt->depth + 7) >> 3; |
| 1262 | 1306 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; |
| 1263 | 1307 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 1264 | − if (dev->progressive) | |
| 1308 | + if (v4l2->progressive) | |
| 1265 | 1309 | f->fmt.pix.field = V4L2_FIELD_NONE; |
| 1266 | 1310 | else |
| 1267 | − f->fmt.pix.field = dev->interlaced ? | |
| 1311 | + f->fmt.pix.field = v4l2->interlaced_fieldmode ? | |
| 1268 | 1312 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; |
| 1269 | 1313 | f->fmt.pix.priv = 0; |
| 1270 | 1314 | |
| @@ -1275,17 +1319,19 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, · 4 unmodified lines | ||
| 1275 | 1319 | unsigned width, unsigned height) |
| 1276 | 1320 | { |
| 1277 | 1321 | struct em28xx_fmt *fmt; |
| 1322 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1278 | 1323 | |
| 1279 | 1324 | fmt = format_by_fourcc(fourcc); |
| 1280 | 1325 | if (!fmt) |
| 1281 | 1326 | return -EINVAL; |
| 1282 | 1327 | |
| 1283 | − dev->format = fmt; | |
| 1284 | − dev->width = width; | |
| 1285 | − dev->height = height; | |
| 1328 | + v4l2->format = fmt; | |
| 1329 | + v4l2->width = width; | |
| 1330 | + v4l2->height = height; | |
| 1286 | 1331 | |
| 1287 | 1332 | /* set new image size */ |
| 1288 | − size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | |
| 1333 | + size_to_scale(dev, v4l2->width, v4l2->height, | |
| 1334 | + &v4l2->hscale, &v4l2->vscale); | |
| 1289 | 1335 | |
| 1290 | 1336 | em28xx_resolution_set(dev); |
| 1291 | 1337 | |
| @@ -1296,8 +1342,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, · 4 unmodified lines | ||
| 1296 | 1342 | struct v4l2_format *f) |
| 1297 | 1343 | { |
| 1298 | 1344 | struct em28xx *dev = video_drvdata(file); |
| 1345 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1299 | 1346 | |
| 1300 | − if (dev->streaming_users > 0) | |
| 1347 | + if (v4l2->streaming_users > 0) | |
| 1301 | 1348 | return -EBUSY; |
| 1302 | 1349 | |
| 1303 | 1350 | vidioc_try_fmt_vid_cap(file, priv, f); |
| @@ -1311,7 +1358,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) · 7 unmodified lines | ||
| 1311 | 1358 | struct em28xx_fh *fh = priv; |
| 1312 | 1359 | struct em28xx *dev = fh->dev; |
| 1313 | 1360 | |
| 1314 | − *norm = dev->norm; | |
| 1361 | + *norm = dev->v4l2->norm; | |
| 1315 | 1362 | |
| 1316 | 1363 | return 0; |
| 1317 | 1364 | } |
| @@ -1321,24 +1368,25 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) · 3 unmodified lines | ||
| 1321 | 1368 | struct em28xx_fh *fh = priv; |
| 1322 | 1369 | struct em28xx *dev = fh->dev; |
| 1323 | 1370 | |
| 1324 | − v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); | |
| 1371 | + v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm); | |
| 1325 | 1372 | |
| 1326 | 1373 | return 0; |
| 1327 | 1374 | } |
| 1328 | 1375 | |
| 1329 | 1376 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) |
| 1330 | 1377 | { |
| 1331 | − struct em28xx_fh *fh = priv; | |
| 1332 | − struct em28xx *dev = fh->dev; | |
| 1378 | + struct em28xx_fh *fh = priv; | |
| 1379 | + struct em28xx *dev = fh->dev; | |
| 1380 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1333 | 1381 | struct v4l2_format f; |
| 1334 | 1382 | |
| 1335 | − if (norm == dev->norm) | |
| 1383 | + if (norm == v4l2->norm) | |
| 1336 | 1384 | return 0; |
| 1337 | 1385 | |
| 1338 | − if (dev->streaming_users > 0) | |
| 1386 | + if (v4l2->streaming_users > 0) | |
| 1339 | 1387 | return -EBUSY; |
| 1340 | 1388 | |
| 1341 | − dev->norm = norm; | |
| 1389 | + v4l2->norm = norm; | |
| 1342 | 1390 | |
| 1343 | 1391 | /* Adjusts width/height, if needed */ |
| 1344 | 1392 | f.fmt.pix.width = 720; |
| @@ -1346,12 +1394,13 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) · 1 unmodified line | ||
| 1346 | 1394 | vidioc_try_fmt_vid_cap(file, priv, &f); |
| 1347 | 1395 | |
| 1348 | 1396 | /* set new image size */ |
| 1349 | − dev->width = f.fmt.pix.width; | |
| 1350 | − dev->height = f.fmt.pix.height; | |
| 1351 | − size_to_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | |
| 1397 | + v4l2->width = f.fmt.pix.width; | |
| 1398 | + v4l2->height = f.fmt.pix.height; | |
| 1399 | + size_to_scale(dev, v4l2->width, v4l2->height, | |
| 1400 | + &v4l2->hscale, &v4l2->vscale); | |
| 1352 | 1401 | |
| 1353 | 1402 | em28xx_resolution_set(dev); |
| 1354 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); | |
| 1403 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm); | |
| 1355 | 1404 | |
| 1356 | 1405 | return 0; |
| 1357 | 1406 | } |
| @@ -1359,16 +1408,17 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) · 1 unmodified line | ||
| 1359 | 1408 | static int vidioc_g_parm(struct file *file, void *priv, |
| 1360 | 1409 | struct v4l2_streamparm *p) |
| 1361 | 1410 | { |
| 1362 | − struct em28xx_fh *fh = priv; | |
| 1363 | − struct em28xx *dev = fh->dev; | |
| 1411 | + struct em28xx_fh *fh = priv; | |
| 1412 | + struct em28xx *dev = fh->dev; | |
| 1413 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1364 | 1414 | int rc = 0; |
| 1365 | 1415 | |
| 1366 | 1416 | p->parm.capture.readbuffers = EM28XX_MIN_BUF; |
| 1367 | 1417 | if (dev->board.is_webcam) |
| 1368 | − rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, | |
| 1418 | + rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0, | |
| 1369 | 1419 | video, g_parm, p); |
| 1370 | 1420 | else |
| 1371 | − v4l2_video_std_frame_period(dev->norm, | |
| 1421 | + v4l2_video_std_frame_period(v4l2->norm, | |
| 1372 | 1422 | &p->parm.capture.timeperframe); |
| 1373 | 1423 | |
| 1374 | 1424 | return rc; |
| @@ -1381,7 +1431,8 @@ static int vidioc_s_parm(struct file *file, void *priv, · 6 unmodified lines | ||
| 1381 | 1431 | struct em28xx *dev = fh->dev; |
| 1382 | 1432 | |
| 1383 | 1433 | p->parm.capture.readbuffers = EM28XX_MIN_BUF; |
| 1384 | − return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p); | |
| 1434 | + return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, | |
| 1435 | + 0, video, s_parm, p); | |
| 1385 | 1436 | } |
| 1386 | 1437 | |
| 1387 | 1438 | static const char *iname[] = { |
| @@ -1418,7 +1469,7 @@ static int vidioc_enum_input(struct file *file, void *priv, · 30 unmodified lines | ||
| 1418 | 1469 | (EM28XX_VMUX_CABLE == INPUT(n)->type)) |
| 1419 | 1470 | i->type = V4L2_INPUT_TYPE_TUNER; |
| 1420 | 1471 | |
| 1421 | − i->std = dev->vdev->tvnorms; | |
| 1472 | + i->std = dev->v4l2->vdev->tvnorms; | |
| 1422 | 1473 | /* webcams do not have the STD API */ |
| 1423 | 1474 | if (dev->board.is_webcam) |
| 1424 | 1475 | i->capabilities = 0; |
| @@ -1520,7 +1571,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, · 95 unmodified lines | ||
| 1520 | 1571 | |
| 1521 | 1572 | strcpy(t->name, "Tuner"); |
| 1522 | 1573 | |
| 1523 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); | |
| 1574 | + v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t); | |
| 1524 | 1575 | return 0; |
| 1525 | 1576 | } |
| 1526 | 1577 | |
| @@ -1533,7 +1584,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, · 6 unmodified lines | ||
| 1533 | 1584 | if (0 != t->index) |
| 1534 | 1585 | return -EINVAL; |
| 1535 | 1586 | |
| 1536 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); | |
| 1587 | + v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t); | |
| 1537 | 1588 | return 0; |
| 1538 | 1589 | } |
| 1539 | 1590 | |
| @@ -1542,27 +1593,29 @@ static int vidioc_g_frequency(struct file *file, void *priv, · 2 unmodified lines | ||
| 1542 | 1593 | { |
| 1543 | 1594 | struct em28xx_fh *fh = priv; |
| 1544 | 1595 | struct em28xx *dev = fh->dev; |
| 1596 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1545 | 1597 | |
| 1546 | 1598 | if (0 != f->tuner) |
| 1547 | 1599 | return -EINVAL; |
| 1548 | 1600 | |
| 1549 | − f->frequency = dev->ctl_freq; | |
| 1601 | + f->frequency = v4l2->frequency; | |
| 1550 | 1602 | return 0; |
| 1551 | 1603 | } |
| 1552 | 1604 | |
| 1553 | 1605 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 1554 | 1606 | const struct v4l2_frequency *f) |
| 1555 | 1607 | { |
| 1556 | − struct v4l2_frequency new_freq = *f; | |
| 1557 | − struct em28xx_fh *fh = priv; | |
| 1558 | − struct em28xx *dev = fh->dev; | |
| 1608 | + struct v4l2_frequency new_freq = *f; | |
| 1609 | + struct em28xx_fh *fh = priv; | |
| 1610 | + struct em28xx *dev = fh->dev; | |
| 1611 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1559 | 1612 | |
| 1560 | 1613 | if (0 != f->tuner) |
| 1561 | 1614 | return -EINVAL; |
| 1562 | 1615 | |
| 1563 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); | |
| 1564 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq); | |
| 1565 | − dev->ctl_freq = new_freq.frequency; | |
| 1616 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f); | |
| 1617 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, g_frequency, &new_freq); | |
| 1618 | + v4l2->frequency = new_freq.frequency; | |
| 1566 | 1619 | |
| 1567 | 1620 | return 0; |
| 1568 | 1621 | } |
| @@ -1579,7 +1632,8 @@ static int vidioc_g_chip_info(struct file *file, void *priv, · 10 unmodified lines | ||
| 1579 | 1632 | if (chip->match.addr == 1) |
| 1580 | 1633 | strlcpy(chip->name, "ac97", sizeof(chip->name)); |
| 1581 | 1634 | else |
| 1582 | − strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name)); | |
| 1635 | + strlcpy(chip->name, | |
| 1636 | + dev->v4l2->v4l2_dev.name, sizeof(chip->name)); | |
| 1583 | 1637 | return 0; |
| 1584 | 1638 | } |
| 1585 | 1639 | |
| @@ -1660,9 +1714,10 @@ static int vidioc_s_register(struct file *file, void *priv, · 74 unmodified lines | ||
| 1660 | 1714 | static int vidioc_querycap(struct file *file, void *priv, |
| 1661 | 1715 | struct v4l2_capability *cap) |
| 1662 | 1716 | { |
| 1663 | − struct video_device *vdev = video_devdata(file); | |
| 1664 | − struct em28xx_fh *fh = priv; | |
| 1665 | − struct em28xx *dev = fh->dev; | |
| 1717 | + struct video_device *vdev = video_devdata(file); | |
| 1718 | + struct em28xx_fh *fh = priv; | |
| 1719 | + struct em28xx *dev = fh->dev; | |
| 1720 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1666 | 1721 | |
| 1667 | 1722 | strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); |
| 1668 | 1723 | strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); |
| @@ -1684,9 +1739,9 @@ static int vidioc_querycap(struct file *file, void *priv, · 15 unmodified lines | ||
| 1684 | 1739 | |
| 1685 | 1740 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS | |
| 1686 | 1741 | V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
| 1687 | − if (dev->vbi_dev) | |
| 1742 | + if (v4l2->vbi_dev) | |
| 1688 | 1743 | cap->capabilities |= V4L2_CAP_VBI_CAPTURE; |
| 1689 | − if (dev->radio_dev) | |
| 1744 | + if (v4l2->radio_dev) | |
| 1690 | 1745 | cap->capabilities |= V4L2_CAP_RADIO; |
| 1691 | 1746 | return 0; |
| 1692 | 1747 | } |
| @@ -1751,24 +1806,25 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, · 58 unmodified lines | ||
| 1751 | 1806 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, |
| 1752 | 1807 | struct v4l2_format *format) |
| 1753 | 1808 | { |
| 1754 | − struct em28xx_fh *fh = priv; | |
| 1755 | − struct em28xx *dev = fh->dev; | |
| 1809 | + struct em28xx_fh *fh = priv; | |
| 1810 | + struct em28xx *dev = fh->dev; | |
| 1811 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1756 | 1812 | |
| 1757 | − format->fmt.vbi.samples_per_line = dev->vbi_width; | |
| 1813 | + format->fmt.vbi.samples_per_line = v4l2->vbi_width; | |
| 1758 | 1814 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
| 1759 | 1815 | format->fmt.vbi.offset = 0; |
| 1760 | 1816 | format->fmt.vbi.flags = 0; |
| 1761 | 1817 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; |
| 1762 | − format->fmt.vbi.count[0] = dev->vbi_height; | |
| 1763 | − format->fmt.vbi.count[1] = dev->vbi_height; | |
| 1818 | + format->fmt.vbi.count[0] = v4l2->vbi_height; | |
| 1819 | + format->fmt.vbi.count[1] = v4l2->vbi_height; | |
| 1764 | 1820 | memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved)); |
| 1765 | 1821 | |
| 1766 | 1822 | /* Varies by video standard (NTSC, PAL, etc.) */ |
| 1767 | − if (dev->norm & V4L2_STD_525_60) { | |
| 1823 | + if (v4l2->norm & V4L2_STD_525_60) { | |
| 1768 | 1824 | /* NTSC */ |
| 1769 | 1825 | format->fmt.vbi.start[0] = 10; |
| 1770 | 1826 | format->fmt.vbi.start[1] = 273; |
| 1771 | − } else if (dev->norm & V4L2_STD_625_50) { | |
| 1827 | + } else if (v4l2->norm & V4L2_STD_625_50) { | |
| 1772 | 1828 | /* PAL */ |
| 1773 | 1829 | format->fmt.vbi.start[0] = 6; |
| 1774 | 1830 | format->fmt.vbi.start[1] = 318; |
| @@ -1791,7 +1847,7 @@ static int radio_g_tuner(struct file *file, void *priv, · 16 unmodified lines | ||
| 1791 | 1847 | |
| 1792 | 1848 | strcpy(t->name, "Radio"); |
| 1793 | 1849 | |
| 1794 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); | |
| 1850 | + v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t); | |
| 1795 | 1851 | |
| 1796 | 1852 | return 0; |
| 1797 | 1853 | } |
| @@ -1804,11 +1860,26 @@ static int radio_s_tuner(struct file *file, void *priv, · 6 unmodified lines | ||
| 1804 | 1860 | if (0 != t->index) |
| 1805 | 1861 | return -EINVAL; |
| 1806 | 1862 | |
| 1807 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); | |
| 1863 | + v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t); | |
| 1808 | 1864 | |
| 1809 | 1865 | return 0; |
| 1810 | 1866 | } |
| 1811 | 1867 | |
| 1868 | +/* | |
| 1869 | + * em28xx_free_v4l2() - Free struct em28xx_v4l2 | |
| 1870 | + * | |
| 1871 | + * @ref: struct kref for struct em28xx_v4l2 | |
| 1872 | + * | |
| 1873 | + * Called when all users of struct em28xx_v4l2 are gone | |
| 1874 | + */ | |
| 1875 | +static void em28xx_free_v4l2(struct kref *ref) | |
| 1876 | +{ | |
| 1877 | + struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref); | |
| 1878 | + | |
| 1879 | + v4l2->dev->v4l2 = NULL; | |
| 1880 | + kfree(v4l2); | |
| 1881 | +} | |
| 1882 | + | |
| 1812 | 1883 | /* |
| 1813 | 1884 | * em28xx_v4l2_open() |
| 1814 | 1885 | * inits the device and starts isoc transfer |
| @@ -1817,6 +1888,7 @@ static int em28xx_v4l2_open(struct file *filp) · 2 unmodified lines | ||
| 1817 | 1888 | { |
| 1818 | 1889 | struct video_device *vdev = video_devdata(filp); |
| 1819 | 1890 | struct em28xx *dev = video_drvdata(filp); |
| 1891 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1820 | 1892 | enum v4l2_buf_type fh_type = 0; |
| 1821 | 1893 | struct em28xx_fh *fh; |
| 1822 | 1894 | |
| @@ -1835,7 +1907,7 @@ static int em28xx_v4l2_open(struct file *filp) · 12 unmodified lines | ||
| 1835 | 1907 | |
| 1836 | 1908 | em28xx_videodbg("open dev=%s type=%s users=%d\n", |
| 1837 | 1909 | video_device_node_name(vdev), v4l2_type_names[fh_type], |
| 1838 | − dev->users); | |
| 1910 | + v4l2->users); | |
| 1839 | 1911 | |
| 1840 | 1912 | if (mutex_lock_interruptible(&dev->lock)) |
| 1841 | 1913 | return -ERESTARTSYS; |
| @@ -1850,7 +1922,7 @@ static int em28xx_v4l2_open(struct file *filp) · 8 unmodified lines | ||
| 1850 | 1922 | fh->type = fh_type; |
| 1851 | 1923 | filp->private_data = fh; |
| 1852 | 1924 | |
| 1853 | − if (dev->users == 0) { | |
| 1925 | + if (v4l2->users == 0) { | |
| 1854 | 1926 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
| 1855 | 1927 | |
| 1856 | 1928 | if (vdev->vfl_type != VFL_TYPE_RADIO) |
| @@ -1865,11 +1937,12 @@ static int em28xx_v4l2_open(struct file *filp) · 8 unmodified lines | ||
| 1865 | 1937 | |
| 1866 | 1938 | if (vdev->vfl_type == VFL_TYPE_RADIO) { |
| 1867 | 1939 | em28xx_videodbg("video_open: setting radio device\n"); |
| 1868 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); | |
| 1940 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio); | |
| 1869 | 1941 | } |
| 1870 | 1942 | |
| 1871 | 1943 | kref_get(&dev->ref); |
| 1872 | − dev->users++; | |
| 1944 | + kref_get(&v4l2->ref); | |
| 1945 | + v4l2->users++; | |
| 1873 | 1946 | |
| 1874 | 1947 | mutex_unlock(&dev->lock); |
| 1875 | 1948 | v4l2_fh_add(&fh->fh); |
| @@ -1884,6 +1957,8 @@ static int em28xx_v4l2_open(struct file *filp) · 8 unmodified lines | ||
| 1884 | 1957 | */ |
| 1885 | 1958 | static int em28xx_v4l2_fini(struct em28xx *dev) |
| 1886 | 1959 | { |
| 1960 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1961 | + | |
| 1887 | 1962 | if (dev->is_audio_only) { |
| 1888 | 1963 | /* Shouldn't initialize IR for this interface */ |
| 1889 | 1964 | return 0; |
| @@ -1894,39 +1969,45 @@ static int em28xx_v4l2_fini(struct em28xx *dev) · 4 unmodified lines | ||
| 1894 | 1969 | return 0; |
| 1895 | 1970 | } |
| 1896 | 1971 | |
| 1972 | + if (v4l2 == NULL) | |
| 1973 | + return 0; | |
| 1974 | + | |
| 1897 | 1975 | em28xx_info("Closing video extension"); |
| 1898 | 1976 | |
| 1899 | 1977 | mutex_lock(&dev->lock); |
| 1900 | 1978 | |
| 1901 | − v4l2_device_disconnect(&dev->v4l2_dev); | |
| 1979 | + v4l2_device_disconnect(&v4l2->v4l2_dev); | |
| 1902 | 1980 | |
| 1903 | 1981 | em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); |
| 1904 | 1982 | |
| 1905 | − if (dev->radio_dev) { | |
| 1983 | + if (v4l2->radio_dev) { | |
| 1906 | 1984 | em28xx_info("V4L2 device %s deregistered\n", |
| 1907 | − video_device_node_name(dev->radio_dev)); | |
| 1908 | − video_unregister_device(dev->radio_dev); | |
| 1985 | + video_device_node_name(v4l2->radio_dev)); | |
| 1986 | + video_unregister_device(v4l2->radio_dev); | |
| 1909 | 1987 | } |
| 1910 | − if (dev->vbi_dev) { | |
| 1988 | + if (v4l2->vbi_dev) { | |
| 1911 | 1989 | em28xx_info("V4L2 device %s deregistered\n", |
| 1912 | − video_device_node_name(dev->vbi_dev)); | |
| 1913 | − video_unregister_device(dev->vbi_dev); | |
| 1990 | + video_device_node_name(v4l2->vbi_dev)); | |
| 1991 | + video_unregister_device(v4l2->vbi_dev); | |
| 1914 | 1992 | } |
| 1915 | − if (dev->vdev) { | |
| 1993 | + if (v4l2->vdev) { | |
| 1916 | 1994 | em28xx_info("V4L2 device %s deregistered\n", |
| 1917 | − video_device_node_name(dev->vdev)); | |
| 1918 | − video_unregister_device(dev->vdev); | |
| 1995 | + video_device_node_name(v4l2->vdev)); | |
| 1996 | + video_unregister_device(v4l2->vdev); | |
| 1919 | 1997 | } |
| 1920 | 1998 | |
| 1921 | − v4l2_ctrl_handler_free(&dev->ctrl_handler); | |
| 1922 | − v4l2_device_unregister(&dev->v4l2_dev); | |
| 1999 | + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); | |
| 2000 | + v4l2_device_unregister(&v4l2->v4l2_dev); | |
| 1923 | 2001 | |
| 1924 | − if (dev->clk) { | |
| 1925 | − v4l2_clk_unregister_fixed(dev->clk); | |
| 1926 | − dev->clk = NULL; | |
| 2002 | + if (v4l2->clk) { | |
| 2003 | + v4l2_clk_unregister_fixed(v4l2->clk); | |
| 2004 | + v4l2->clk = NULL; | |
| 1927 | 2005 | } |
| 1928 | 2006 | |
| 2007 | + kref_put(&v4l2->ref, em28xx_free_v4l2); | |
| 2008 | + | |
| 1929 | 2009 | mutex_unlock(&dev->lock); |
| 2010 | + | |
| 1930 | 2011 | kref_put(&dev->ref, em28xx_free_device); |
| 1931 | 2012 | |
| 1932 | 2013 | return 0; |
| @@ -1965,22 +2046,23 @@ static int em28xx_v4l2_resume(struct em28xx *dev) · 32 unmodified lines | ||
| 1965 | 2046 | */ |
| 1966 | 2047 | static int em28xx_v4l2_close(struct file *filp) |
| 1967 | 2048 | { |
| 1968 | − struct em28xx_fh *fh = filp->private_data; | |
| 1969 | − struct em28xx *dev = fh->dev; | |
| 2049 | + struct em28xx_fh *fh = filp->private_data; | |
| 2050 | + struct em28xx *dev = fh->dev; | |
| 2051 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 1970 | 2052 | int errCode; |
| 1971 | 2053 | |
| 1972 | − em28xx_videodbg("users=%d\n", dev->users); | |
| 2054 | + em28xx_videodbg("users=%d\n", v4l2->users); | |
| 1973 | 2055 | |
| 1974 | 2056 | vb2_fop_release(filp); |
| 1975 | 2057 | mutex_lock(&dev->lock); |
| 1976 | 2058 | |
| 1977 | − if (dev->users == 1) { | |
| 2059 | + if (v4l2->users == 1) { | |
| 1978 | 2060 | /* No sense to try to write to the device */ |
| 1979 | 2061 | if (dev->disconnected) |
| 1980 | 2062 | goto exit; |
| 1981 | 2063 | |
| 1982 | 2064 | /* Save some power by putting tuner to sleep */ |
| 1983 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); | |
| 2065 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0); | |
| 1984 | 2066 | |
| 1985 | 2067 | /* do this before setting alternate! */ |
| 1986 | 2068 | em28xx_set_mode(dev, EM28XX_SUSPEND); |
| @@ -1996,30 +2078,14 @@ static int em28xx_v4l2_close(struct file *filp) · 9 unmodified lines | ||
| 1996 | 2078 | } |
| 1997 | 2079 | |
| 1998 | 2080 | exit: |
| 1999 | − dev->users--; | |
| 2081 | + v4l2->users--; | |
| 2082 | + kref_put(&v4l2->ref, em28xx_free_v4l2); | |
| 2000 | 2083 | mutex_unlock(&dev->lock); |
| 2001 | 2084 | kref_put(&dev->ref, em28xx_free_device); |
| 2002 | 2085 | |
| 2003 | 2086 | return 0; |
| 2004 | 2087 | } |
| 2005 | 2088 | |
| 2006 | −/* | |
| 2007 | − * em28xx_videodevice_release() | |
| 2008 | − * called when the last user of the video device exits and frees the memeory | |
| 2009 | − */ | |
| 2010 | −static void em28xx_videodevice_release(struct video_device *vdev) | |
| 2011 | −{ | |
| 2012 | − struct em28xx *dev = video_get_drvdata(vdev); | |
| 2013 | − | |
| 2014 | − video_device_release(vdev); | |
| 2015 | − if (vdev == dev->vdev) | |
| 2016 | − dev->vdev = NULL; | |
| 2017 | − else if (vdev == dev->vbi_dev) | |
| 2018 | − dev->vbi_dev = NULL; | |
| 2019 | − else if (vdev == dev->radio_dev) | |
| 2020 | − dev->radio_dev = NULL; | |
| 2021 | −} | |
| 2022 | − | |
| 2023 | 2089 | static const struct v4l2_file_operations em28xx_v4l_fops = { |
| 2024 | 2090 | .owner = THIS_MODULE, |
| 2025 | 2091 | .open = em28xx_v4l2_open, |
| @@ -2076,7 +2142,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { · 50 unmodified lines | ||
| 2076 | 2142 | static const struct video_device em28xx_video_template = { |
| 2077 | 2143 | .fops = &em28xx_v4l_fops, |
| 2078 | 2144 | .ioctl_ops = &video_ioctl_ops, |
| 2079 | − .release = em28xx_videodevice_release, | |
| 2145 | + .release = video_device_release, | |
| 2080 | 2146 | .tvnorms = V4L2_STD_ALL, |
| 2081 | 2147 | }; |
| 2082 | 2148 | |
| @@ -2105,7 +2171,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { · 22 unmodified lines | ||
| 2105 | 2171 | static struct video_device em28xx_radio_template = { |
| 2106 | 2172 | .fops = &radio_fops, |
| 2107 | 2173 | .ioctl_ops = &radio_ioctl_ops, |
| 2108 | − .release = em28xx_videodevice_release, | |
| 2174 | + .release = video_device_release, | |
| 2109 | 2175 | }; |
| 2110 | 2176 | |
| 2111 | 2177 | /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ |
| @@ -2139,7 +2205,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, · 27 unmodified lines | ||
| 2139 | 2205 | return NULL; |
| 2140 | 2206 | |
| 2141 | 2207 | *vfd = *template; |
| 2142 | − vfd->v4l2_dev = &dev->v4l2_dev; | |
| 2208 | + vfd->v4l2_dev = &dev->v4l2->v4l2_dev; | |
| 2143 | 2209 | vfd->debug = video_debug; |
| 2144 | 2210 | vfd->lock = &dev->lock; |
| 2145 | 2211 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); |
| @@ -2153,13 +2219,12 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, · 7 unmodified lines | ||
| 2153 | 2219 | return vfd; |
| 2154 | 2220 | } |
| 2155 | 2221 | |
| 2156 | −static void em28xx_tuner_setup(struct em28xx *dev) | |
| 2222 | +static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr) | |
| 2157 | 2223 | { |
| 2158 | − struct tuner_setup tun_setup; | |
| 2159 | − struct v4l2_frequency f; | |
| 2160 | − | |
| 2161 | − if (dev->tuner_type == TUNER_ABSENT) | |
| 2162 | − return; | |
| 2224 | + struct em28xx_v4l2 *v4l2 = dev->v4l2; | |
| 2225 | + struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev; | |
| 2226 | + struct tuner_setup tun_setup; | |
| 2227 | + struct v4l2_frequency f; | |
| 2163 | 2228 | |
| 2164 | 2229 | memset(&tun_setup, 0, sizeof(tun_setup)); |
| 2165 | 2230 | |
| @@ -2170,23 +2235,26 @@ static void em28xx_tuner_setup(struct em28xx *dev) · 4 unmodified lines | ||
| 2170 | 2235 | tun_setup.type = dev->board.radio.type; |
| 2171 | 2236 | tun_setup.addr = dev->board.radio_addr; |
| 2172 | 2237 | |
| 2173 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); | |
| 2238 | + v4l2_device_call_all(v4l2_dev, | |
| 2239 | + 0, tuner, s_type_addr, &tun_setup); | |
| 2174 | 2240 | } |
| 2175 | 2241 | |
| 2176 | 2242 | if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { |
| 2177 | 2243 | tun_setup.type = dev->tuner_type; |
| 2178 | − tun_setup.addr = dev->tuner_addr; | |
| 2244 | + tun_setup.addr = tuner_addr; | |
| 2179 | 2245 | |
| 2180 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); | |
| 2246 | + v4l2_device_call_all(v4l2_dev, | |
| 2247 | + 0, tuner, s_type_addr, &tun_setup); | |
| 2181 | 2248 | } |
| 2182 | 2249 | |
| 2183 | − if (dev->tda9887_conf) { | |
| 2250 | + if (dev->board.tda9887_conf) { | |
| 2184 | 2251 | struct v4l2_priv_tun_config tda9887_cfg; |
| 2185 | 2252 | |
| 2186 | 2253 | tda9887_cfg.tuner = TUNER_TDA9887; |
| 2187 | − tda9887_cfg.priv = &dev->tda9887_conf; | |
| 2254 | + tda9887_cfg.priv = &dev->board.tda9887_conf; | |
| 2188 | 2255 | |
| 2189 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); | |
| 2256 | + v4l2_device_call_all(v4l2_dev, | |
| 2257 | + 0, tuner, s_config, &tda9887_cfg); | |
| 2190 | 2258 | } |
| 2191 | 2259 | |
| 2192 | 2260 | if (dev->tuner_type == TUNER_XC2028) { |
| @@ -2201,15 +2269,15 @@ static void em28xx_tuner_setup(struct em28xx *dev) · 8 unmodified lines | ||
| 2201 | 2269 | xc2028_cfg.tuner = TUNER_XC2028; |
| 2202 | 2270 | xc2028_cfg.priv = &ctl; |
| 2203 | 2271 | |
| 2204 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); | |
| 2272 | + v4l2_device_call_all(v4l2_dev, 0, tuner, s_config, &xc2028_cfg); | |
| 2205 | 2273 | } |
| 2206 | 2274 | |
| 2207 | 2275 | /* configure tuner */ |
| 2208 | 2276 | f.tuner = 0; |
| 2209 | 2277 | f.type = V4L2_TUNER_ANALOG_TV; |
| 2210 | 2278 | f.frequency = 9076; /* just a magic number */ |
| 2211 | − dev->ctl_freq = f.frequency; | |
| 2212 | − v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); | |
| 2279 | + v4l2->frequency = f.frequency; | |
| 2280 | + v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency, &f); | |
| 2213 | 2281 | } |
| 2214 | 2282 | |
| 2215 | 2283 | static int em28xx_v4l2_init(struct em28xx *dev) |
| @@ -2217,7 +2285,8 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 1 unmodified line | ||
| 2217 | 2285 | u8 val; |
| 2218 | 2286 | int ret; |
| 2219 | 2287 | unsigned int maxw; |
| 2220 | − struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; | |
| 2288 | + struct v4l2_ctrl_handler *hdl; | |
| 2289 | + struct em28xx_v4l2 *v4l2; | |
| 2221 | 2290 | |
| 2222 | 2291 | if (dev->is_audio_only) { |
| 2223 | 2292 | /* Shouldn't initialize IR for this interface */ |
| @@ -2233,71 +2302,93 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 9 unmodified lines | ||
| 2233 | 2302 | |
| 2234 | 2303 | mutex_lock(&dev->lock); |
| 2235 | 2304 | |
| 2236 | − ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); | |
| 2305 | + v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL); | |
| 2306 | + if (v4l2 == NULL) { | |
| 2307 | + em28xx_info("em28xx_v4l: memory allocation failed\n"); | |
| 2308 | + mutex_unlock(&dev->lock); | |
| 2309 | + return -ENOMEM; | |
| 2310 | + } | |
| 2311 | + kref_init(&v4l2->ref); | |
| 2312 | + v4l2->dev = dev; | |
| 2313 | + dev->v4l2 = v4l2; | |
| 2314 | + | |
| 2315 | + ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev); | |
| 2237 | 2316 | if (ret < 0) { |
| 2238 | 2317 | em28xx_errdev("Call to v4l2_device_register() failed!\n"); |
| 2239 | 2318 | goto err; |
| 2240 | 2319 | } |
| 2241 | 2320 | |
| 2321 | + hdl = &v4l2->ctrl_handler; | |
| 2242 | 2322 | v4l2_ctrl_handler_init(hdl, 8); |
| 2243 | − dev->v4l2_dev.ctrl_handler = hdl; | |
| 2323 | + v4l2->v4l2_dev.ctrl_handler = hdl; | |
| 2324 | + | |
| 2325 | + if (dev->board.is_webcam) | |
| 2326 | + v4l2->progressive = 1; | |
| 2244 | 2327 | |
| 2245 | 2328 | /* |
| 2246 | 2329 | * Default format, used for tvp5150 or saa711x output formats |
| 2247 | 2330 | */ |
| 2248 | − dev->vinmode = 0x10; | |
| 2249 | − dev->vinctl = EM28XX_VINCTRL_INTERLACED | | |
| 2250 | − EM28XX_VINCTRL_CCIR656_ENABLE; | |
| 2331 | + v4l2->vinmode = 0x10; | |
| 2332 | + v4l2->vinctl = EM28XX_VINCTRL_INTERLACED | | |
| 2333 | + EM28XX_VINCTRL_CCIR656_ENABLE; | |
| 2251 | 2334 | |
| 2252 | 2335 | /* request some modules */ |
| 2253 | 2336 | |
| 2254 | 2337 | if (dev->board.has_msp34xx) |
| 2255 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2256 | − "msp3400", 0, msp3400_addrs); | |
| 2338 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2339 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2340 | + "msp3400", 0, msp3400_addrs); | |
| 2257 | 2341 | |
| 2258 | 2342 | if (dev->board.decoder == EM28XX_SAA711X) |
| 2259 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2260 | − "saa7115_auto", 0, saa711x_addrs); | |
| 2343 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2344 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2345 | + "saa7115_auto", 0, saa711x_addrs); | |
| 2261 | 2346 | |
| 2262 | 2347 | if (dev->board.decoder == EM28XX_TVP5150) |
| 2263 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2264 | − "tvp5150", 0, tvp5150_addrs); | |
| 2348 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2349 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2350 | + "tvp5150", 0, tvp5150_addrs); | |
| 2265 | 2351 | |
| 2266 | 2352 | if (dev->board.adecoder == EM28XX_TVAUDIO) |
| 2267 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2268 | − "tvaudio", dev->board.tvaudio_addr, NULL); | |
| 2353 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2354 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2355 | + "tvaudio", dev->board.tvaudio_addr, NULL); | |
| 2269 | 2356 | |
| 2270 | 2357 | /* Initialize tuner and camera */ |
| 2271 | 2358 | |
| 2272 | 2359 | if (dev->board.tuner_type != TUNER_ABSENT) { |
| 2273 | − int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); | |
| 2360 | + unsigned short tuner_addr = dev->board.tuner_addr; | |
| 2361 | + int has_demod = (dev->board.tda9887_conf & TDA9887_PRESENT); | |
| 2274 | 2362 | |
| 2275 | 2363 | if (dev->board.radio.type) |
| 2276 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2277 | − "tuner", dev->board.radio_addr, NULL); | |
| 2364 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2365 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2366 | + "tuner", dev->board.radio_addr, NULL); | |
| 2278 | 2367 | |
| 2279 | 2368 | if (has_demod) |
| 2280 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, | |
| 2369 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2281 | 2370 | &dev->i2c_adap[dev->def_i2c_bus], "tuner", |
| 2282 | 2371 | 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); |
| 2283 | − if (dev->tuner_addr == 0) { | |
| 2372 | + if (tuner_addr == 0) { | |
| 2284 | 2373 | enum v4l2_i2c_tuner_type type = |
| 2285 | 2374 | has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; |
| 2286 | 2375 | struct v4l2_subdev *sd; |
| 2287 | 2376 | |
| 2288 | − sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, | |
| 2377 | + sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2289 | 2378 | &dev->i2c_adap[dev->def_i2c_bus], "tuner", |
| 2290 | 2379 | 0, v4l2_i2c_tuner_addrs(type)); |
| 2291 | 2380 | |
| 2292 | 2381 | if (sd) |
| 2293 | − dev->tuner_addr = v4l2_i2c_subdev_addr(sd); | |
| 2382 | + tuner_addr = v4l2_i2c_subdev_addr(sd); | |
| 2294 | 2383 | } else { |
| 2295 | − v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap[dev->def_i2c_bus], | |
| 2296 | − "tuner", dev->tuner_addr, NULL); | |
| 2384 | + v4l2_i2c_new_subdev(&v4l2->v4l2_dev, | |
| 2385 | + &dev->i2c_adap[dev->def_i2c_bus], | |
| 2386 | + "tuner", tuner_addr, NULL); | |
| 2297 | 2387 | } |
| 2388 | + | |
| 2389 | + em28xx_tuner_setup(dev, tuner_addr); | |
| 2298 | 2390 | } |
| 2299 | 2391 | |
| 2300 | − em28xx_tuner_setup(dev); | |
| 2301 | 2392 | if (dev->em28xx_sensor != EM28XX_NOSENSOR) |
| 2302 | 2393 | em28xx_init_camera(dev); |
| 2303 | 2394 | |
| @@ -2348,12 +2439,12 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 44 unmodified lines | ||
| 2348 | 2439 | } |
| 2349 | 2440 | |
| 2350 | 2441 | /* set default norm */ |
| 2351 | − dev->norm = V4L2_STD_PAL; | |
| 2352 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); | |
| 2353 | − dev->interlaced = EM28XX_INTERLACED_DEFAULT; | |
| 2442 | + v4l2->norm = V4L2_STD_PAL; | |
| 2443 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm); | |
| 2444 | + v4l2->interlaced_fieldmode = EM28XX_INTERLACED_DEFAULT; | |
| 2354 | 2445 | |
| 2355 | 2446 | /* Analog specific initialization */ |
| 2356 | − dev->format = &format[0]; | |
| 2447 | + v4l2->format = &format[0]; | |
| 2357 | 2448 | |
| 2358 | 2449 | maxw = norm_maxw(dev); |
| 2359 | 2450 | /* MaxPacketSize for em2800 is too small to capture at full resolution |
| @@ -2376,74 +2467,75 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 16 unmodified lines | ||
| 2376 | 2467 | (EM28XX_XCLK_AUDIO_UNMUTE | val)); |
| 2377 | 2468 | |
| 2378 | 2469 | em28xx_set_outfmt(dev); |
| 2379 | − em28xx_compression_disable(dev); | |
| 2380 | 2470 | |
| 2381 | 2471 | /* Add image controls */ |
| 2382 | 2472 | /* NOTE: at this point, the subdevices are already registered, so bridge |
| 2383 | 2473 | * controls are only added/enabled when no subdevice provides them */ |
| 2384 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST)) | |
| 2385 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2474 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST)) | |
| 2475 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2386 | 2476 | V4L2_CID_CONTRAST, |
| 2387 | 2477 | 0, 0x1f, 1, CONTRAST_DEFAULT); |
| 2388 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS)) | |
| 2389 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2478 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS)) | |
| 2479 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2390 | 2480 | V4L2_CID_BRIGHTNESS, |
| 2391 | 2481 | -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT); |
| 2392 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION)) | |
| 2393 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2482 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION)) | |
| 2483 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2394 | 2484 | V4L2_CID_SATURATION, |
| 2395 | 2485 | 0, 0x1f, 1, SATURATION_DEFAULT); |
| 2396 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE)) | |
| 2397 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2486 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE)) | |
| 2487 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2398 | 2488 | V4L2_CID_BLUE_BALANCE, |
| 2399 | 2489 | -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT); |
| 2400 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE)) | |
| 2401 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2490 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE)) | |
| 2491 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2402 | 2492 | V4L2_CID_RED_BALANCE, |
| 2403 | 2493 | -0x30, 0x30, 1, RED_BALANCE_DEFAULT); |
| 2404 | − if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS)) | |
| 2405 | − v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops, | |
| 2494 | + if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS)) | |
| 2495 | + v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | |
| 2406 | 2496 | V4L2_CID_SHARPNESS, |
| 2407 | 2497 | 0, 0x0f, 1, SHARPNESS_DEFAULT); |
| 2408 | 2498 | |
| 2409 | 2499 | /* Reset image controls */ |
| 2410 | 2500 | em28xx_colorlevels_set_default(dev); |
| 2411 | − v4l2_ctrl_handler_setup(&dev->ctrl_handler); | |
| 2412 | − ret = dev->ctrl_handler.error; | |
| 2501 | + v4l2_ctrl_handler_setup(hdl); | |
| 2502 | + ret = hdl->error; | |
| 2413 | 2503 | if (ret) |
| 2414 | 2504 | goto unregister_dev; |
| 2415 | 2505 | |
| 2416 | 2506 | /* allocate and fill video video_device struct */ |
| 2417 | − dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | |
| 2418 | − if (!dev->vdev) { | |
| 2507 | + v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | |
| 2508 | + if (!v4l2->vdev) { | |
| 2419 | 2509 | em28xx_errdev("cannot allocate video_device.\n"); |
| 2420 | 2510 | ret = -ENODEV; |
| 2421 | 2511 | goto unregister_dev; |
| 2422 | 2512 | } |
| 2423 | − dev->vdev->queue = &dev->vb_vidq; | |
| 2424 | − dev->vdev->queue->lock = &dev->vb_queue_lock; | |
| 2513 | + mutex_init(&v4l2->vb_queue_lock); | |
| 2514 | + mutex_init(&v4l2->vb_vbi_queue_lock); | |
| 2515 | + v4l2->vdev->queue = &v4l2->vb_vidq; | |
| 2516 | + v4l2->vdev->queue->lock = &v4l2->vb_queue_lock; | |
| 2425 | 2517 | |
| 2426 | 2518 | /* disable inapplicable ioctls */ |
| 2427 | 2519 | if (dev->board.is_webcam) { |
| 2428 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_QUERYSTD); | |
| 2429 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_G_STD); | |
| 2430 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_STD); | |
| 2520 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD); | |
| 2521 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD); | |
| 2522 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD); | |
| 2431 | 2523 | } else { |
| 2432 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM); | |
| 2524 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM); | |
| 2433 | 2525 | } |
| 2434 | 2526 | if (dev->tuner_type == TUNER_ABSENT) { |
| 2435 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_G_TUNER); | |
| 2436 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_TUNER); | |
| 2437 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_G_FREQUENCY); | |
| 2438 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_FREQUENCY); | |
| 2527 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER); | |
| 2528 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER); | |
| 2529 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY); | |
| 2530 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY); | |
| 2439 | 2531 | } |
| 2440 | 2532 | if (!dev->audio_mode.has_audio) { |
| 2441 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_G_AUDIO); | |
| 2442 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_AUDIO); | |
| 2533 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO); | |
| 2534 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO); | |
| 2443 | 2535 | } |
| 2444 | 2536 | |
| 2445 | 2537 | /* register v4l2 video video_device */ |
| 2446 | − ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | |
| 2538 | + ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER, | |
| 2447 | 2539 | video_nr[dev->devno]); |
| 2448 | 2540 | if (ret) { |
| 2449 | 2541 | em28xx_errdev("unable to register video device (error=%i).\n", |
| @@ -2453,27 +2545,27 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 3 unmodified lines | ||
| 2453 | 2545 | |
| 2454 | 2546 | /* Allocate and fill vbi video_device struct */ |
| 2455 | 2547 | if (em28xx_vbi_supported(dev) == 1) { |
| 2456 | − dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, | |
| 2548 | + v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, | |
| 2457 | 2549 | "vbi"); |
| 2458 | 2550 | |
| 2459 | − dev->vbi_dev->queue = &dev->vb_vbiq; | |
| 2460 | − dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock; | |
| 2551 | + v4l2->vbi_dev->queue = &v4l2->vb_vbiq; | |
| 2552 | + v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock; | |
| 2461 | 2553 | |
| 2462 | 2554 | /* disable inapplicable ioctls */ |
| 2463 | − v4l2_disable_ioctl(dev->vdev, VIDIOC_S_PARM); | |
| 2555 | + v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM); | |
| 2464 | 2556 | if (dev->tuner_type == TUNER_ABSENT) { |
| 2465 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_TUNER); | |
| 2466 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_TUNER); | |
| 2467 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_FREQUENCY); | |
| 2468 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_FREQUENCY); | |
| 2557 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER); | |
| 2558 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER); | |
| 2559 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY); | |
| 2560 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY); | |
| 2469 | 2561 | } |
| 2470 | 2562 | if (!dev->audio_mode.has_audio) { |
| 2471 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_G_AUDIO); | |
| 2472 | − v4l2_disable_ioctl(dev->vbi_dev, VIDIOC_S_AUDIO); | |
| 2563 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO); | |
| 2564 | + v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO); | |
| 2473 | 2565 | } |
| 2474 | 2566 | |
| 2475 | 2567 | /* register v4l2 vbi video_device */ |
| 2476 | − ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | |
| 2568 | + ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI, | |
| 2477 | 2569 | vbi_nr[dev->devno]); |
| 2478 | 2570 | if (ret < 0) { |
| 2479 | 2571 | em28xx_errdev("unable to register vbi device\n"); |
| @@ -2482,32 +2574,32 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 2 unmodified lines | ||
| 2482 | 2574 | } |
| 2483 | 2575 | |
| 2484 | 2576 | if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { |
| 2485 | − dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, | |
| 2486 | − "radio"); | |
| 2487 | − if (!dev->radio_dev) { | |
| 2577 | + v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, | |
| 2578 | + "radio"); | |
| 2579 | + if (!v4l2->radio_dev) { | |
| 2488 | 2580 | em28xx_errdev("cannot allocate video_device.\n"); |
| 2489 | 2581 | ret = -ENODEV; |
| 2490 | 2582 | goto unregister_dev; |
| 2491 | 2583 | } |
| 2492 | − ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, | |
| 2584 | + ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO, | |
| 2493 | 2585 | radio_nr[dev->devno]); |
| 2494 | 2586 | if (ret < 0) { |
| 2495 | 2587 | em28xx_errdev("can't register radio device\n"); |
| 2496 | 2588 | goto unregister_dev; |
| 2497 | 2589 | } |
| 2498 | 2590 | em28xx_info("Registered radio device as %s\n", |
| 2499 | − video_device_node_name(dev->radio_dev)); | |
| 2591 | + video_device_node_name(v4l2->radio_dev)); | |
| 2500 | 2592 | } |
| 2501 | 2593 | |
| 2502 | 2594 | em28xx_info("V4L2 video device registered as %s\n", |
| 2503 | − video_device_node_name(dev->vdev)); | |
| 2595 | + video_device_node_name(v4l2->vdev)); | |
| 2504 | 2596 | |
| 2505 | − if (dev->vbi_dev) | |
| 2597 | + if (v4l2->vbi_dev) | |
| 2506 | 2598 | em28xx_info("V4L2 VBI device registered as %s\n", |
| 2507 | − video_device_node_name(dev->vbi_dev)); | |
| 2599 | + video_device_node_name(v4l2->vbi_dev)); | |
| 2508 | 2600 | |
| 2509 | 2601 | /* Save some power by putting tuner to sleep */ |
| 2510 | − v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); | |
| 2602 | + v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0); | |
| 2511 | 2603 | |
| 2512 | 2604 | /* initialize videobuf2 stuff */ |
| 2513 | 2605 | em28xx_vb2_setup(dev); |
| @@ -2520,9 +2612,11 @@ static int em28xx_v4l2_init(struct em28xx *dev) · 6 unmodified lines | ||
| 2520 | 2612 | return 0; |
| 2521 | 2613 | |
| 2522 | 2614 | unregister_dev: |
| 2523 | − v4l2_ctrl_handler_free(&dev->ctrl_handler); | |
| 2524 | − v4l2_device_unregister(&dev->v4l2_dev); | |
| 2615 | + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); | |
| 2616 | + v4l2_device_unregister(&v4l2->v4l2_dev); | |
| 2525 | 2617 | err: |
| 2618 | + dev->v4l2 = NULL; | |
| 2619 | + kref_put(&v4l2->ref, em28xx_free_v4l2); | |
| 2526 | 2620 | mutex_unlock(&dev->lock); |
| 2527 | 2621 | return ret; |
| 2528 | 2622 | } |
| @@ -140,6 +140,7 @@ · 139 unmodified lines | ||
| 140 | 140 | #define EM2765_BOARD_SPEEDLINK_VAD_LAPLACE 91 |
| 141 | 141 | #define EM28178_BOARD_PCTV_461E 92 |
| 142 | 142 | #define EM2874_BOARD_KWORLD_UB435Q_V3 93 |
| 143 | +#define EM28178_BOARD_PCTV_292E 94 | |
| 143 | 144 | |
| 144 | 145 | /* Limits minimum and default number of buffers */ |
| 145 | 146 | #define EM28XX_MIN_BUF 4 |
| @@ -497,6 +498,60 @@ struct em28xx_eeprom { · 351 unmodified lines | ||
| 497 | 498 | #define EM28XX_RESOURCE_VIDEO 0x01 |
| 498 | 499 | #define EM28XX_RESOURCE_VBI 0x02 |
| 499 | 500 | |
| 501 | +struct em28xx_v4l2 { | |
| 502 | + struct kref ref; | |
| 503 | + struct em28xx *dev; | |
| 504 | + | |
| 505 | + struct v4l2_device v4l2_dev; | |
| 506 | + struct v4l2_ctrl_handler ctrl_handler; | |
| 507 | + struct v4l2_clk *clk; | |
| 508 | + | |
| 509 | + struct video_device *vdev; | |
| 510 | + struct video_device *vbi_dev; | |
| 511 | + struct video_device *radio_dev; | |
| 512 | + | |
| 513 | + /* Videobuf2 */ | |
| 514 | + struct vb2_queue vb_vidq; | |
| 515 | + struct vb2_queue vb_vbiq; | |
| 516 | + struct mutex vb_queue_lock; | |
| 517 | + struct mutex vb_vbi_queue_lock; | |
| 518 | + | |
| 519 | + u8 vinmode; | |
| 520 | + u8 vinctl; | |
| 521 | + | |
| 522 | + /* Camera specific fields */ | |
| 523 | + int sensor_xres; | |
| 524 | + int sensor_yres; | |
| 525 | + int sensor_xtal; | |
| 526 | + | |
| 527 | + int users; /* user count for exclusive use */ | |
| 528 | + int streaming_users; /* number of actively streaming users */ | |
| 529 | + | |
| 530 | + u32 frequency; /* selected tuner frequency */ | |
| 531 | + | |
| 532 | + struct em28xx_fmt *format; | |
| 533 | + v4l2_std_id norm; /* selected tv norm */ | |
| 534 | + | |
| 535 | + /* Progressive/interlaced mode */ | |
| 536 | + bool progressive; | |
| 537 | + int interlaced_fieldmode; /* 1=interlaced fields, 0=just top fields */ | |
| 538 | + /* FIXME: everything else than interlaced_fieldmode=1 doesn't work */ | |
| 539 | + | |
| 540 | + /* Frame properties */ | |
| 541 | + int width; /* current frame width */ | |
| 542 | + int height; /* current frame height */ | |
| 543 | + unsigned hscale; /* horizontal scale factor (see datasheet) */ | |
| 544 | + unsigned vscale; /* vertical scale factor (see datasheet) */ | |
| 545 | + unsigned int vbi_width; | |
| 546 | + unsigned int vbi_height; /* lines per field */ | |
| 547 | + | |
| 548 | + /* Capture state tracking */ | |
| 549 | + int capture_type; | |
| 550 | + bool top_field; | |
| 551 | + int vbi_read; | |
| 552 | + unsigned int field_count; | |
| 553 | +}; | |
| 554 | + | |
| 500 | 555 | struct em28xx_audio { |
| 501 | 556 | char name[50]; |
| 502 | 557 | unsigned num_urb; |
| @@ -513,6 +568,10 @@ struct em28xx_audio { · 10 unmodified lines | ||
| 513 | 568 | |
| 514 | 569 | int users; |
| 515 | 570 | spinlock_t slock; |
| 571 | + | |
| 572 | + /* Controls streaming */ | |
| 573 | + struct work_struct wq_trigger; /* trigger to start/stop audio */ | |
| 574 | + atomic_t stream_started; /* stream should be running if true */ | |
| 516 | 575 | }; |
| 517 | 576 | |
| 518 | 577 | struct em28xx; |
| @@ -541,6 +600,12 @@ struct em28xx_i2c_bus { · 22 unmodified lines | ||
| 541 | 600 | struct em28xx { |
| 542 | 601 | struct kref ref; |
| 543 | 602 | |
| 603 | + /* Sub-module data */ | |
| 604 | + struct em28xx_v4l2 *v4l2; | |
| 605 | + struct em28xx_dvb *dvb; | |
| 606 | + struct em28xx_audio adev; | |
| 607 | + struct em28xx_IR *ir; | |
| 608 | + | |
| 544 | 609 | /* generic device properties */ |
| 545 | 610 | char name[30]; /* name (including minor) of the device */ |
| 546 | 611 | int model; /* index in the device_data struct */ |
| @@ -554,29 +619,9 @@ struct em28xx { · 7 unmodified lines | ||
| 554 | 619 | unsigned int has_alsa_audio:1; |
| 555 | 620 | unsigned int is_audio_only:1; |
| 556 | 621 | |
| 557 | − struct v4l2_device v4l2_dev; | |
| 558 | − struct v4l2_ctrl_handler ctrl_handler; | |
| 559 | − struct v4l2_clk *clk; | |
| 560 | 622 | struct em28xx_board board; |
| 561 | 623 | |
| 562 | − /* Webcam specific fields */ | |
| 563 | − enum em28xx_sensor em28xx_sensor; | |
| 564 | − int sensor_xres, sensor_yres; | |
| 565 | − int sensor_xtal; | |
| 566 | − | |
| 567 | − /* Progressive (non-interlaced) mode */ | |
| 568 | − int progressive; | |
| 569 | − | |
| 570 | − /* Vinmode/Vinctl used at the driver */ | |
| 571 | − int vinmode, vinctl; | |
| 572 | − | |
| 573 | − /* Controls audio streaming */ | |
| 574 | − struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ | |
| 575 | − atomic_t stream_started; /* stream should be running if true */ | |
| 576 | − | |
| 577 | − struct em28xx_fmt *format; | |
| 578 | − | |
| 579 | − struct em28xx_IR *ir; | |
| 624 | + enum em28xx_sensor em28xx_sensor; /* camera specific */ | |
| 580 | 625 | |
| 581 | 626 | /* Some older em28xx chips needs a waiting time after writing */ |
| 582 | 627 | unsigned int wait_after_write; |
| @@ -588,8 +633,6 @@ struct em28xx { · 5 unmodified lines | ||
| 588 | 633 | struct em28xx_audio_mode audio_mode; |
| 589 | 634 | |
| 590 | 635 | int tuner_type; /* type of the tuner */ |
| 591 | − int tuner_addr; /* tuner address */ | |
| 592 | − int tda9887_conf; | |
| 593 | 636 | |
| 594 | 637 | /* i2c i/o */ |
| 595 | 638 | struct i2c_adapter i2c_adap[NUM_I2C_BUSES]; |
| @@ -602,52 +645,21 @@ struct em28xx { · 6 unmodified lines | ||
| 602 | 645 | struct rt_mutex i2c_bus_lock; |
| 603 | 646 | |
| 604 | 647 | /* video for linux */ |
| 605 | − int users; /* user count for exclusive use */ | |
| 606 | − int streaming_users; /* Number of actively streaming users */ | |
| 607 | − struct video_device *vdev; /* video for linux device struct */ | |
| 608 | − v4l2_std_id norm; /* selected tv norm */ | |
| 609 | − int ctl_freq; /* selected frequency */ | |
| 610 | 648 | unsigned int ctl_input; /* selected input */ |
| 611 | 649 | unsigned int ctl_ainput;/* selected audio input */ |
| 612 | 650 | unsigned int ctl_aoutput;/* selected audio output */ |
| 613 | 651 | int mute; |
| 614 | 652 | int volume; |
| 615 | − /* frame properties */ | |
| 616 | − int width; /* current frame width */ | |
| 617 | − int height; /* current frame height */ | |
| 618 | − unsigned hscale; /* horizontal scale factor (see datasheet) */ | |
| 619 | − unsigned vscale; /* vertical scale factor (see datasheet) */ | |
| 620 | − int interlaced; /* 1=interlace fileds, 0=just top fileds */ | |
| 621 | − unsigned int video_bytesread; /* Number of bytes read */ | |
| 622 | 653 | |
| 623 | 654 | unsigned long hash; /* eeprom hash - for boards with generic ID */ |
| 624 | 655 | unsigned long i2c_hash; /* i2c devicelist hash - |
| 625 | 656 | for boards with generic ID */ |
| 626 | 657 | |
| 627 | − struct em28xx_audio adev; | |
| 628 | − | |
| 629 | − /* capture state tracking */ | |
| 630 | − int capture_type; | |
| 631 | − unsigned char top_field:1; | |
| 632 | − int vbi_read; | |
| 633 | − unsigned int vbi_width; | |
| 634 | − unsigned int vbi_height; /* lines per field */ | |
| 635 | − | |
| 636 | 658 | struct work_struct request_module_wk; |
| 637 | 659 | |
| 638 | 660 | /* locks */ |
| 639 | 661 | struct mutex lock; |
| 640 | 662 | struct mutex ctrl_urb_lock; /* protects urb_buf */ |
| 641 | − /* spinlock_t queue_lock; */ | |
| 642 | − struct list_head inqueue, outqueue; | |
| 643 | − struct video_device *vbi_dev; | |
| 644 | − struct video_device *radio_dev; | |
| 645 | − | |
| 646 | − /* Videobuf2 */ | |
| 647 | − struct vb2_queue vb_vidq; | |
| 648 | − struct vb2_queue vb_vbiq; | |
| 649 | − struct mutex vb_queue_lock; | |
| 650 | − struct mutex vb_vbi_queue_lock; | |
| 651 | 663 | |
| 652 | 664 | /* resources in use */ |
| 653 | 665 | unsigned int resources; |
| @@ -662,9 +674,6 @@ struct em28xx { · 8 unmodified lines | ||
| 662 | 674 | struct em28xx_usb_ctl usb_ctl; |
| 663 | 675 | spinlock_t slock; |
| 664 | 676 | |
| 665 | − unsigned int field_count; | |
| 666 | − unsigned int vbi_field_count; | |
| 667 | − | |
| 668 | 677 | /* usb transfer */ |
| 669 | 678 | struct usb_device *udev; /* the usb device */ |
| 670 | 679 | u8 ifnum; /* number of the assigned usb interface */ |
| @@ -708,8 +717,6 @@ struct em28xx { · 37 unmodified lines | ||
| 708 | 717 | /* Snapshot button input device */ |
| 709 | 718 | char snapshot_button_path[30]; /* path of the input dev */ |
| 710 | 719 | struct input_dev *sbutton_input_dev; |
| 711 | − | |
| 712 | − struct em28xx_dvb *dvb; | |
| 713 | 720 | }; |
| 714 | 721 | |
| 715 | 722 | #define kref_to_dev(d) container_of(d, struct em28xx, ref) |
| @@ -797,32 +804,4 @@ int em28xx_init_camera(struct em28xx *dev); · 81 unmodified lines | ||
| 797 | 804 | printk(KERN_WARNING "%s: "fmt,\ |
| 798 | 805 | dev->name , ##arg); } while (0) |
| 799 | 806 | |
| 800 | −static inline int em28xx_compression_disable(struct em28xx *dev) | |
| 801 | −{ | |
| 802 | − /* side effect of disabling scaler and mixer */ | |
| 803 | − return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00); | |
| 804 | −} | |
| 805 | − | |
| 806 | −/*FIXME: maxw should be dependent of alt mode */ | |
| 807 | −static inline unsigned int norm_maxw(struct em28xx *dev) | |
| 808 | −{ | |
| 809 | − if (dev->board.is_webcam) | |
| 810 | − return dev->sensor_xres; | |
| 811 | − | |
| 812 | − if (dev->board.max_range_640_480) | |
| 813 | − return 640; | |
| 814 | − | |
| 815 | − return 720; | |
| 816 | −} | |
| 817 | − | |
| 818 | −static inline unsigned int norm_maxh(struct em28xx *dev) | |
| 819 | −{ | |
| 820 | − if (dev->board.is_webcam) | |
| 821 | − return dev->sensor_yres; | |
| 822 | − | |
| 823 | − if (dev->board.max_range_640_480) | |
| 824 | − return 480; | |
| 825 | − | |
| 826 | − return (dev->norm & V4L2_STD_625_50) ? 576 : 480; | |
| 827 | −} | |
| 828 | 807 | #endif |
| @@ -50,6 +50,16 @@ config USB_GSPCA_CPIA1 · 49 unmodified lines | ||
| 50 | 50 | To compile this driver as a module, choose M here: the |
| 51 | 51 | module will be called gspca_cpia1. |
| 52 | 52 | |
| 53 | +config USB_GSPCA_DTCS033 | |
| 54 | + tristate "DTCS033 (Scopium) USB Astro-Camera Driver" | |
| 55 | + depends on VIDEO_V4L2 && USB_GSPCA | |
| 56 | + help | |
| 57 | + Say Y here if you want support for the Scopium camera | |
| 58 | + for planetary astrophotography. | |
| 59 | + | |
| 60 | + To compile this driver as a module, choose M here: the | |
| 61 | + module will be called gspca_dtcs033. | |
| 62 | + | |
| 53 | 63 | config USB_GSPCA_ETOMS |
| 54 | 64 | tristate "Etoms USB Camera Driver" |
| 55 | 65 | depends on VIDEO_V4L2 && USB_GSPCA |
| @@ -2,6 +2,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o · 1 unmodified line | ||
| 2 | 2 | obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o |
| 3 | 3 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
| 4 | 4 | obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o |
| 5 | +obj-$(CONFIG_USB_GSPCA_DTCS033) += gspca_dtcs033.o | |
| 5 | 6 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
| 6 | 7 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
| 7 | 8 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o |
| @@ -48,6 +49,7 @@ gspca_main-objs := gspca.o autogain_functions.o · 40 unmodified lines | ||
| 48 | 49 | gspca_benq-objs := benq.o |
| 49 | 50 | gspca_conex-objs := conex.o |
| 50 | 51 | gspca_cpia1-objs := cpia1.o |
| 52 | +gspca_dtcs033-objs := dtcs033.o | |
| 51 | 53 | gspca_etoms-objs := etoms.o |
| 52 | 54 | gspca_finepix-objs := finepix.o |
| 53 | 55 | gspca_jeilinj-objs := jeilinj.o |
| @@ -0,0 +1,441 @@ | ||
| 1 | +/* | |
| 2 | + * Subdriver for Scopium astro-camera (DTCS033, 0547:7303) | |
| 3 | + * | |
| 4 | + * Copyright (C) 2014 Robert Butora (robert.butora.fi@gmail.com) | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
| 18 | +#define MODULE_NAME "dtcs033" | |
| 19 | +#include "gspca.h" | |
| 20 | + | |
| 21 | +MODULE_AUTHOR("Robert Butora <robert.butora.fi@gmail.com>"); | |
| 22 | +MODULE_DESCRIPTION("Scopium DTCS033 astro-cam USB Camera Driver"); | |
| 23 | +MODULE_LICENSE("GPL"); | |
| 24 | + | |
| 25 | +struct dtcs033_usb_requests { | |
| 26 | + u8 bRequestType; | |
| 27 | + u8 bRequest; | |
| 28 | + u16 wValue; | |
| 29 | + u16 wIndex; | |
| 30 | + u16 wLength; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +/* send a usb request */ | |
| 34 | +static void reg_rw(struct gspca_dev *gspca_dev, | |
| 35 | + u8 bRequestType, u8 bRequest, | |
| 36 | + u16 wValue, u16 wIndex, u16 wLength) | |
| 37 | +{ | |
| 38 | + struct usb_device *udev = gspca_dev->dev; | |
| 39 | + int ret; | |
| 40 | + | |
| 41 | + if (gspca_dev->usb_err < 0) | |
| 42 | + return; | |
| 43 | + | |
| 44 | + ret = usb_control_msg(udev, | |
| 45 | + usb_rcvctrlpipe(udev, 0), | |
| 46 | + bRequest, | |
| 47 | + bRequestType, | |
| 48 | + wValue, wIndex, | |
| 49 | + gspca_dev->usb_buf, wLength, 500); | |
| 50 | + | |
| 51 | + if (ret < 0) { | |
| 52 | + gspca_dev->usb_err = ret; | |
| 53 | + pr_err("usb_control_msg error %d\n", ret); | |
| 54 | + } | |
| 55 | + | |
| 56 | + return; | |
| 57 | +} | |
| 58 | +/* send several usb in/out requests */ | |
| 59 | +static int reg_reqs(struct gspca_dev *gspca_dev, | |
| 60 | + const struct dtcs033_usb_requests *preqs, int n_reqs) | |
| 61 | +{ | |
| 62 | + int i = 0; | |
| 63 | + const struct dtcs033_usb_requests *preq; | |
| 64 | + | |
| 65 | + while ((i < n_reqs) && (gspca_dev->usb_err >= 0)) { | |
| 66 | + | |
| 67 | + preq = &preqs[i]; | |
| 68 | + | |
| 69 | + reg_rw(gspca_dev, preq->bRequestType, preq->bRequest, | |
| 70 | + preq->wValue, preq->wIndex, preq->wLength); | |
| 71 | + | |
| 72 | + if (gspca_dev->usb_err < 0) { | |
| 73 | + | |
| 74 | + PERR("usb error request no: %d / %d\n", | |
| 75 | + i, n_reqs); | |
366 more lines aren’t shown here.
This diff is large: its 499 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1621 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 337 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 1048 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.