diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 12:37:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 12:37:45 -0400 |
commit | fb091be08d1acf184e8801dfdcace6e0cb19b1fe (patch) | |
tree | cbd0c4200fd8628d592167589ca790e36fc4ae26 | |
parent | bd7fc2f2d807fdb254f7efc542f8eec3f23e289e (diff) | |
parent | e8d0416796d43a950ec7b65629e53419b2e22453 (diff) |
Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (534 commits)
V4L/DVB (13554a): v4l: Use the video_drvdata function in drivers
V4L/DVB: vivi and mem2mem_testdev need slab.h to build
V4L/DVB: tm6000: bugfix image position
V4L/DVB: IR/imon: remove dead IMON_KEY_RELEASE_OFFSET
V4L/DVB: tm6000: README - add vbi
V4L/DVB: Fix unlock logic at medusa_video_init
V4L/DVB: fix dvb frontend lockup
V4L/DVB: s2255drv: remove dead code
V4L/DVB: s2255drv: return if vdev not found
V4L/DVB: ov511: cleanup: remove unneeded null check
V4L/DVB: media/mem2mem: dereferencing free memory
V4L/DVB: media/IR: Add missing include file to rc-map.c
V4L/DVB: dvb/stv6110x: cleanup error handling
V4L/DVB: ngene: Add lgdt3303 and mt2131 deps to Kconfig
V4L/DVB: ngene: start separating out DVB functions into separate file
V4L/DVB: ngene: split out card specific code into a separate file
V4L/DVB: ngene: split out i2c code into a separate file
V4L/DVB: ngene: add initial support for digital side of Avermedia m780
V4L/DVB: ngene: properly support boards where channel 0 isn't a TS input
V4L-DVB: ngene: make sure that tuner headers are included
...
387 files changed, 36270 insertions, 11937 deletions
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index c725cb852c54..5d4d40f429a5 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl | |||
@@ -17,6 +17,7 @@ | |||
17 | <!ENTITY VIDIOC-DBG-G-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_G_REGISTER</constant></link>"> | 17 | <!ENTITY VIDIOC-DBG-G-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_G_REGISTER</constant></link>"> |
18 | <!ENTITY VIDIOC-DBG-S-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_S_REGISTER</constant></link>"> | 18 | <!ENTITY VIDIOC-DBG-S-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_S_REGISTER</constant></link>"> |
19 | <!ENTITY VIDIOC-DQBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_DQBUF</constant></link>"> | 19 | <!ENTITY VIDIOC-DQBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_DQBUF</constant></link>"> |
20 | <!ENTITY VIDIOC-DQEVENT "<link linkend='vidioc-dqevent'><constant>VIDIOC_DQEVENT</constant></link>"> | ||
20 | <!ENTITY VIDIOC-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_ENCODER_CMD</constant></link>"> | 21 | <!ENTITY VIDIOC-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_ENCODER_CMD</constant></link>"> |
21 | <!ENTITY VIDIOC-ENUMAUDIO "<link linkend='vidioc-enumaudio'><constant>VIDIOC_ENUMAUDIO</constant></link>"> | 22 | <!ENTITY VIDIOC-ENUMAUDIO "<link linkend='vidioc-enumaudio'><constant>VIDIOC_ENUMAUDIO</constant></link>"> |
22 | <!ENTITY VIDIOC-ENUMAUDOUT "<link linkend='vidioc-enumaudioout'><constant>VIDIOC_ENUMAUDOUT</constant></link>"> | 23 | <!ENTITY VIDIOC-ENUMAUDOUT "<link linkend='vidioc-enumaudioout'><constant>VIDIOC_ENUMAUDOUT</constant></link>"> |
@@ -60,6 +61,7 @@ | |||
60 | <!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>"> | 61 | <!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>"> |
61 | <!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>"> | 62 | <!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>"> |
62 | <!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>"> | 63 | <!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>"> |
64 | <!ENTITY VIDIOC-SUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_SUBSCRIBE_EVENT</constant></link>"> | ||
63 | <!ENTITY VIDIOC-S-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_S_AUDIO</constant></link>"> | 65 | <!ENTITY VIDIOC-S-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_S_AUDIO</constant></link>"> |
64 | <!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>"> | 66 | <!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>"> |
65 | <!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>"> | 67 | <!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>"> |
@@ -83,6 +85,7 @@ | |||
83 | <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>"> | 85 | <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>"> |
84 | <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>"> | 86 | <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>"> |
85 | <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>"> | 87 | <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>"> |
88 | <!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>"> | ||
86 | 89 | ||
87 | <!-- Types --> | 90 | <!-- Types --> |
88 | <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>"> | 91 | <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>"> |
@@ -141,6 +144,9 @@ | |||
141 | <!ENTITY v4l2-enc-idx "struct <link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>"> | 144 | <!ENTITY v4l2-enc-idx "struct <link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>"> |
142 | <!ENTITY v4l2-enc-idx-entry "struct <link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>"> | 145 | <!ENTITY v4l2-enc-idx-entry "struct <link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>"> |
143 | <!ENTITY v4l2-encoder-cmd "struct <link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>"> | 146 | <!ENTITY v4l2-encoder-cmd "struct <link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>"> |
147 | <!ENTITY v4l2-event "struct <link linkend='v4l2-event'>v4l2_event</link>"> | ||
148 | <!ENTITY v4l2-event-subscription "struct <link linkend='v4l2-event-subscription'>v4l2_event_subscription</link>"> | ||
149 | <!ENTITY v4l2-event-vsync "struct <link linkend='v4l2-event-vsync'>v4l2_event_vsync</link>"> | ||
144 | <!ENTITY v4l2-ext-control "struct <link linkend='v4l2-ext-control'>v4l2_ext_control</link>"> | 150 | <!ENTITY v4l2-ext-control "struct <link linkend='v4l2-ext-control'>v4l2_ext_control</link>"> |
145 | <!ENTITY v4l2-ext-controls "struct <link linkend='v4l2-ext-controls'>v4l2_ext_controls</link>"> | 151 | <!ENTITY v4l2-ext-controls "struct <link linkend='v4l2-ext-controls'>v4l2_ext_controls</link>"> |
146 | <!ENTITY v4l2-fmtdesc "struct <link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link>"> | 152 | <!ENTITY v4l2-fmtdesc "struct <link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link>"> |
@@ -200,6 +206,7 @@ | |||
200 | <!ENTITY sub-controls SYSTEM "v4l/controls.xml"> | 206 | <!ENTITY sub-controls SYSTEM "v4l/controls.xml"> |
201 | <!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml"> | 207 | <!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml"> |
202 | <!ENTITY sub-dev-codec SYSTEM "v4l/dev-codec.xml"> | 208 | <!ENTITY sub-dev-codec SYSTEM "v4l/dev-codec.xml"> |
209 | <!ENTITY sub-dev-event SYSTEM "v4l/dev-event.xml"> | ||
203 | <!ENTITY sub-dev-effect SYSTEM "v4l/dev-effect.xml"> | 210 | <!ENTITY sub-dev-effect SYSTEM "v4l/dev-effect.xml"> |
204 | <!ENTITY sub-dev-osd SYSTEM "v4l/dev-osd.xml"> | 211 | <!ENTITY sub-dev-osd SYSTEM "v4l/dev-osd.xml"> |
205 | <!ENTITY sub-dev-output SYSTEM "v4l/dev-output.xml"> | 212 | <!ENTITY sub-dev-output SYSTEM "v4l/dev-output.xml"> |
@@ -292,6 +299,8 @@ | |||
292 | <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml"> | 299 | <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml"> |
293 | <!ENTITY sub-videodev2-h SYSTEM "v4l/videodev2.h.xml"> | 300 | <!ENTITY sub-videodev2-h SYSTEM "v4l/videodev2.h.xml"> |
294 | <!ENTITY sub-v4l2 SYSTEM "v4l/v4l2.xml"> | 301 | <!ENTITY sub-v4l2 SYSTEM "v4l/v4l2.xml"> |
302 | <!ENTITY sub-dqevent SYSTEM "v4l/vidioc-dqevent.xml"> | ||
303 | <!ENTITY sub-subscribe-event SYSTEM "v4l/vidioc-subscribe-event.xml"> | ||
295 | <!ENTITY sub-intro SYSTEM "dvb/intro.xml"> | 304 | <!ENTITY sub-intro SYSTEM "dvb/intro.xml"> |
296 | <!ENTITY sub-frontend SYSTEM "dvb/frontend.xml"> | 305 | <!ENTITY sub-frontend SYSTEM "dvb/frontend.xml"> |
297 | <!ENTITY sub-dvbproperty SYSTEM "dvb/dvbproperty.xml"> | 306 | <!ENTITY sub-dvbproperty SYSTEM "dvb/dvbproperty.xml"> |
@@ -381,3 +390,5 @@ | |||
381 | <!ENTITY reqbufs SYSTEM "v4l/vidioc-reqbufs.xml"> | 390 | <!ENTITY reqbufs SYSTEM "v4l/vidioc-reqbufs.xml"> |
382 | <!ENTITY s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml"> | 391 | <!ENTITY s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml"> |
383 | <!ENTITY streamon SYSTEM "v4l/vidioc-streamon.xml"> | 392 | <!ENTITY streamon SYSTEM "v4l/vidioc-streamon.xml"> |
393 | <!ENTITY dqevent SYSTEM "v4l/vidioc-dqevent.xml"> | ||
394 | <!ENTITY subscribe_event SYSTEM "v4l/vidioc-subscribe-event.xml"> | ||
diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index b9dbdf9e6d29..b42b935913cd 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml | |||
@@ -2332,15 +2332,26 @@ more information.</para> | |||
2332 | </listitem> | 2332 | </listitem> |
2333 | </orderedlist> | 2333 | </orderedlist> |
2334 | </section> | 2334 | </section> |
2335 | </section> | 2335 | <section> |
2336 | <title>V4L2 in Linux 2.6.34</title> | ||
2337 | <orderedlist> | ||
2338 | <listitem> | ||
2339 | <para>Added | ||
2340 | <constant>V4L2_CID_IRIS_ABSOLUTE</constant> and | ||
2341 | <constant>V4L2_CID_IRIS_RELATIVE</constant> controls to the | ||
2342 | <link linkend="camera-controls">Camera controls class</link>. | ||
2343 | </para> | ||
2344 | </listitem> | ||
2345 | </orderedlist> | ||
2346 | </section> | ||
2336 | 2347 | ||
2337 | <section id="other"> | 2348 | <section id="other"> |
2338 | <title>Relation of V4L2 to other Linux multimedia APIs</title> | 2349 | <title>Relation of V4L2 to other Linux multimedia APIs</title> |
2339 | 2350 | ||
2340 | <section id="xvideo"> | 2351 | <section id="xvideo"> |
2341 | <title>X Video Extension</title> | 2352 | <title>X Video Extension</title> |
2342 | 2353 | ||
2343 | <para>The X Video Extension (abbreviated XVideo or just Xv) is | 2354 | <para>The X Video Extension (abbreviated XVideo or just Xv) is |
2344 | an extension of the X Window system, implemented for example by the | 2355 | an extension of the X Window system, implemented for example by the |
2345 | XFree86 project. Its scope is similar to V4L2, an API to video capture | 2356 | XFree86 project. Its scope is similar to V4L2, an API to video capture |
2346 | and output devices for X clients. Xv allows applications to display | 2357 | and output devices for X clients. Xv allows applications to display |
@@ -2351,7 +2362,7 @@ capture or output still images in XPixmaps<footnote> | |||
2351 | extension available across many operating systems and | 2362 | extension available across many operating systems and |
2352 | architectures.</para> | 2363 | architectures.</para> |
2353 | 2364 | ||
2354 | <para>Because the driver is embedded into the X server Xv has a | 2365 | <para>Because the driver is embedded into the X server Xv has a |
2355 | number of advantages over the V4L2 <link linkend="overlay">video | 2366 | number of advantages over the V4L2 <link linkend="overlay">video |
2356 | overlay interface</link>. The driver can easily determine the overlay | 2367 | overlay interface</link>. The driver can easily determine the overlay |
2357 | target, &ie; visible graphics memory or off-screen buffers for a | 2368 | target, &ie; visible graphics memory or off-screen buffers for a |
@@ -2360,16 +2371,16 @@ overlay, scaling or color-keying, or the clipping functions of the | |||
2360 | video capture hardware, always in sync with drawing operations or | 2371 | video capture hardware, always in sync with drawing operations or |
2361 | windows moving or changing their stacking order.</para> | 2372 | windows moving or changing their stacking order.</para> |
2362 | 2373 | ||
2363 | <para>To combine the advantages of Xv and V4L a special Xv | 2374 | <para>To combine the advantages of Xv and V4L a special Xv |
2364 | driver exists in XFree86 and XOrg, just programming any overlay capable | 2375 | driver exists in XFree86 and XOrg, just programming any overlay capable |
2365 | Video4Linux device it finds. To enable it | 2376 | Video4Linux device it finds. To enable it |
2366 | <filename>/etc/X11/XF86Config</filename> must contain these lines:</para> | 2377 | <filename>/etc/X11/XF86Config</filename> must contain these lines:</para> |
2367 | <para><screen> | 2378 | <para><screen> |
2368 | Section "Module" | 2379 | Section "Module" |
2369 | Load "v4l" | 2380 | Load "v4l" |
2370 | EndSection</screen></para> | 2381 | EndSection</screen></para> |
2371 | 2382 | ||
2372 | <para>As of XFree86 4.2 this driver still supports only V4L | 2383 | <para>As of XFree86 4.2 this driver still supports only V4L |
2373 | ioctls, however it should work just fine with all V4L2 devices through | 2384 | ioctls, however it should work just fine with all V4L2 devices through |
2374 | the V4L2 backward-compatibility layer. Since V4L2 permits multiple | 2385 | the V4L2 backward-compatibility layer. Since V4L2 permits multiple |
2375 | opens it is possible (if supported by the V4L2 driver) to capture | 2386 | opens it is possible (if supported by the V4L2 driver) to capture |
@@ -2377,83 +2388,84 @@ video while an X client requested video overlay. Restrictions of | |||
2377 | simultaneous capturing and overlay are discussed in <xref | 2388 | simultaneous capturing and overlay are discussed in <xref |
2378 | linkend="overlay" /> apply.</para> | 2389 | linkend="overlay" /> apply.</para> |
2379 | 2390 | ||
2380 | <para>Only marginally related to V4L2, XFree86 extended Xv to | 2391 | <para>Only marginally related to V4L2, XFree86 extended Xv to |
2381 | support hardware YUV to RGB conversion and scaling for faster video | 2392 | support hardware YUV to RGB conversion and scaling for faster video |
2382 | playback, and added an interface to MPEG-2 decoding hardware. This API | 2393 | playback, and added an interface to MPEG-2 decoding hardware. This API |
2383 | is useful to display images captured with V4L2 devices.</para> | 2394 | is useful to display images captured with V4L2 devices.</para> |
2384 | </section> | 2395 | </section> |
2385 | 2396 | ||
2386 | <section> | 2397 | <section> |
2387 | <title>Digital Video</title> | 2398 | <title>Digital Video</title> |
2388 | 2399 | ||
2389 | <para>V4L2 does not support digital terrestrial, cable or | 2400 | <para>V4L2 does not support digital terrestrial, cable or |
2390 | satellite broadcast. A separate project aiming at digital receivers | 2401 | satellite broadcast. A separate project aiming at digital receivers |
2391 | exists. You can find its homepage at <ulink | 2402 | exists. You can find its homepage at <ulink |
2392 | url="http://linuxtv.org">http://linuxtv.org</ulink>. The Linux DVB API | 2403 | url="http://linuxtv.org">http://linuxtv.org</ulink>. The Linux DVB API |
2393 | has no connection to the V4L2 API except that drivers for hybrid | 2404 | has no connection to the V4L2 API except that drivers for hybrid |
2394 | hardware may support both.</para> | 2405 | hardware may support both.</para> |
2395 | </section> | 2406 | </section> |
2396 | 2407 | ||
2397 | <section> | 2408 | <section> |
2398 | <title>Audio Interfaces</title> | 2409 | <title>Audio Interfaces</title> |
2399 | 2410 | ||
2400 | <para>[to do - OSS/ALSA]</para> | 2411 | <para>[to do - OSS/ALSA]</para> |
2412 | </section> | ||
2401 | </section> | 2413 | </section> |
2402 | </section> | ||
2403 | 2414 | ||
2404 | <section id="experimental"> | 2415 | <section id="experimental"> |
2405 | <title>Experimental API Elements</title> | 2416 | <title>Experimental API Elements</title> |
2406 | 2417 | ||
2407 | <para>The following V4L2 API elements are currently experimental | 2418 | <para>The following V4L2 API elements are currently experimental |
2408 | and may change in the future.</para> | 2419 | and may change in the future.</para> |
2409 | 2420 | ||
2410 | <itemizedlist> | 2421 | <itemizedlist> |
2411 | <listitem> | 2422 | <listitem> |
2412 | <para>Video Output Overlay (OSD) Interface, <xref | 2423 | <para>Video Output Overlay (OSD) Interface, <xref |
2413 | linkend="osd" />.</para> | 2424 | linkend="osd" />.</para> |
2414 | </listitem> | 2425 | </listitem> |
2415 | <listitem> | 2426 | <listitem> |
2416 | <para><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant>, | 2427 | <para><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant>, |
2417 | &v4l2-buf-type;, <xref linkend="v4l2-buf-type" />.</para> | 2428 | &v4l2-buf-type;, <xref linkend="v4l2-buf-type" />.</para> |
2418 | </listitem> | 2429 | </listitem> |
2419 | <listitem> | 2430 | <listitem> |
2420 | <para><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant>, | 2431 | <para><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant>, |
2421 | &VIDIOC-QUERYCAP; ioctl, <xref linkend="device-capabilities" />.</para> | 2432 | &VIDIOC-QUERYCAP; ioctl, <xref linkend="device-capabilities" />.</para> |
2422 | </listitem> | 2433 | </listitem> |
2423 | <listitem> | 2434 | <listitem> |
2424 | <para>&VIDIOC-ENUM-FRAMESIZES; and | 2435 | <para>&VIDIOC-ENUM-FRAMESIZES; and |
2425 | &VIDIOC-ENUM-FRAMEINTERVALS; ioctls.</para> | 2436 | &VIDIOC-ENUM-FRAMEINTERVALS; ioctls.</para> |
2426 | </listitem> | 2437 | </listitem> |
2427 | <listitem> | 2438 | <listitem> |
2428 | <para>&VIDIOC-G-ENC-INDEX; ioctl.</para> | 2439 | <para>&VIDIOC-G-ENC-INDEX; ioctl.</para> |
2429 | </listitem> | 2440 | </listitem> |
2430 | <listitem> | 2441 | <listitem> |
2431 | <para>&VIDIOC-ENCODER-CMD; and &VIDIOC-TRY-ENCODER-CMD; | 2442 | <para>&VIDIOC-ENCODER-CMD; and &VIDIOC-TRY-ENCODER-CMD; |
2432 | ioctls.</para> | 2443 | ioctls.</para> |
2433 | </listitem> | 2444 | </listitem> |
2434 | <listitem> | 2445 | <listitem> |
2435 | <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER; | 2446 | <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER; |
2436 | ioctls.</para> | 2447 | ioctls.</para> |
2437 | </listitem> | 2448 | </listitem> |
2438 | <listitem> | 2449 | <listitem> |
2439 | <para>&VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para> | 2450 | <para>&VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para> |
2440 | </listitem> | 2451 | </listitem> |
2441 | </itemizedlist> | 2452 | </itemizedlist> |
2442 | </section> | 2453 | </section> |
2443 | 2454 | ||
2444 | <section id="obsolete"> | 2455 | <section id="obsolete"> |
2445 | <title>Obsolete API Elements</title> | 2456 | <title>Obsolete API Elements</title> |
2446 | 2457 | ||
2447 | <para>The following V4L2 API elements were superseded by new | 2458 | <para>The following V4L2 API elements were superseded by new |
2448 | interfaces and should not be implemented in new drivers.</para> | 2459 | interfaces and should not be implemented in new drivers.</para> |
2449 | 2460 | ||
2450 | <itemizedlist> | 2461 | <itemizedlist> |
2451 | <listitem> | 2462 | <listitem> |
2452 | <para><constant>VIDIOC_G_MPEGCOMP</constant> and | 2463 | <para><constant>VIDIOC_G_MPEGCOMP</constant> and |
2453 | <constant>VIDIOC_S_MPEGCOMP</constant> ioctls. Use Extended Controls, | 2464 | <constant>VIDIOC_S_MPEGCOMP</constant> ioctls. Use Extended Controls, |
2454 | <xref linkend="extended-controls" />.</para> | 2465 | <xref linkend="extended-controls" />.</para> |
2455 | </listitem> | 2466 | </listitem> |
2456 | </itemizedlist> | 2467 | </itemizedlist> |
2468 | </section> | ||
2457 | </section> | 2469 | </section> |
2458 | 2470 | ||
2459 | <!-- | 2471 | <!-- |
diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml index f46450610412..8408caaee276 100644 --- a/Documentation/DocBook/v4l/controls.xml +++ b/Documentation/DocBook/v4l/controls.xml | |||
@@ -267,6 +267,12 @@ minimum value disables backlight compensation.</entry> | |||
267 | <entry>Chroma automatic gain control.</entry> | 267 | <entry>Chroma automatic gain control.</entry> |
268 | </row> | 268 | </row> |
269 | <row> | 269 | <row> |
270 | <entry><constant>V4L2_CID_CHROMA_GAIN</constant></entry> | ||
271 | <entry>integer</entry> | ||
272 | <entry>Adjusts the Chroma gain control (for use when chroma AGC | ||
273 | is disabled).</entry> | ||
274 | </row> | ||
275 | <row> | ||
270 | <entry><constant>V4L2_CID_COLOR_KILLER</constant></entry> | 276 | <entry><constant>V4L2_CID_COLOR_KILLER</constant></entry> |
271 | <entry>boolean</entry> | 277 | <entry>boolean</entry> |
272 | <entry>Enable the color killer (&ie; force a black & white image in case of a weak video signal).</entry> | 278 | <entry>Enable the color killer (&ie; force a black & white image in case of a weak video signal).</entry> |
@@ -277,8 +283,15 @@ minimum value disables backlight compensation.</entry> | |||
277 | <entry>Selects a color effect. Possible values for | 283 | <entry>Selects a color effect. Possible values for |
278 | <constant>enum v4l2_colorfx</constant> are: | 284 | <constant>enum v4l2_colorfx</constant> are: |
279 | <constant>V4L2_COLORFX_NONE</constant> (0), | 285 | <constant>V4L2_COLORFX_NONE</constant> (0), |
280 | <constant>V4L2_COLORFX_BW</constant> (1) and | 286 | <constant>V4L2_COLORFX_BW</constant> (1), |
281 | <constant>V4L2_COLORFX_SEPIA</constant> (2).</entry> | 287 | <constant>V4L2_COLORFX_SEPIA</constant> (2), |
288 | <constant>V4L2_COLORFX_NEGATIVE</constant> (3), | ||
289 | <constant>V4L2_COLORFX_EMBOSS</constant> (4), | ||
290 | <constant>V4L2_COLORFX_SKETCH</constant> (5), | ||
291 | <constant>V4L2_COLORFX_SKY_BLUE</constant> (6), | ||
292 | <constant>V4L2_COLORFX_GRASS_GREEN</constant> (7), | ||
293 | <constant>V4L2_COLORFX_SKIN_WHITEN</constant> (8) and | ||
294 | <constant>V4L2_COLORFX_VIVID</constant> (9).</entry> | ||
282 | </row> | 295 | </row> |
283 | <row> | 296 | <row> |
284 | <entry><constant>V4L2_CID_ROTATE</constant></entry> | 297 | <entry><constant>V4L2_CID_ROTATE</constant></entry> |
@@ -1825,6 +1838,25 @@ wide-angle direction. The zoom speed unit is driver-specific.</entry> | |||
1825 | <row><entry></entry></row> | 1838 | <row><entry></entry></row> |
1826 | 1839 | ||
1827 | <row> | 1840 | <row> |
1841 | <entry spanname="id"><constant>V4L2_CID_IRIS_ABSOLUTE</constant> </entry> | ||
1842 | <entry>integer</entry> | ||
1843 | </row><row><entry spanname="descr">This control sets the | ||
1844 | camera's aperture to the specified value. The unit is undefined. | ||
1845 | Larger values open the iris wider, smaller values close it.</entry> | ||
1846 | </row> | ||
1847 | <row><entry></entry></row> | ||
1848 | |||
1849 | <row> | ||
1850 | <entry spanname="id"><constant>V4L2_CID_IRIS_RELATIVE</constant> </entry> | ||
1851 | <entry>integer</entry> | ||
1852 | </row><row><entry spanname="descr">This control modifies the | ||
1853 | camera's aperture by the specified amount. The unit is undefined. | ||
1854 | Positive values open the iris one step further, negative values close | ||
1855 | it one step further. This is a write-only control.</entry> | ||
1856 | </row> | ||
1857 | <row><entry></entry></row> | ||
1858 | |||
1859 | <row> | ||
1828 | <entry spanname="id"><constant>V4L2_CID_PRIVACY</constant> </entry> | 1860 | <entry spanname="id"><constant>V4L2_CID_PRIVACY</constant> </entry> |
1829 | <entry>boolean</entry> | 1861 | <entry>boolean</entry> |
1830 | </row><row><entry spanname="descr">Prevent video from being acquired | 1862 | </row><row><entry spanname="descr">Prevent video from being acquired |
diff --git a/Documentation/DocBook/v4l/dev-event.xml b/Documentation/DocBook/v4l/dev-event.xml new file mode 100644 index 000000000000..be5a98fb4fab --- /dev/null +++ b/Documentation/DocBook/v4l/dev-event.xml | |||
@@ -0,0 +1,31 @@ | |||
1 | <title>Event Interface</title> | ||
2 | |||
3 | <para>The V4L2 event interface provides means for user to get | ||
4 | immediately notified on certain conditions taking place on a device. | ||
5 | This might include start of frame or loss of signal events, for | ||
6 | example. | ||
7 | </para> | ||
8 | |||
9 | <para>To receive events, the events the user is interested in first must | ||
10 | be subscribed using the &VIDIOC-SUBSCRIBE-EVENT; ioctl. Once an event is | ||
11 | subscribed, the events of subscribed types are dequeueable using the | ||
12 | &VIDIOC-DQEVENT; ioctl. Events may be unsubscribed using | ||
13 | VIDIOC_UNSUBSCRIBE_EVENT ioctl. The special event type V4L2_EVENT_ALL may | ||
14 | be used to unsubscribe all the events the driver supports.</para> | ||
15 | |||
16 | <para>The event subscriptions and event queues are specific to file | ||
17 | handles. Subscribing an event on one file handle does not affect | ||
18 | other file handles. | ||
19 | </para> | ||
20 | |||
21 | <para>The information on dequeueable events is obtained by using select or | ||
22 | poll system calls on video devices. The V4L2 events use POLLPRI events on | ||
23 | poll system call and exceptions on select system call. </para> | ||
24 | |||
25 | <!-- | ||
26 | Local Variables: | ||
27 | mode: sgml | ||
28 | sgml-parent-document: "v4l2.sgml" | ||
29 | indent-tabs-mode: nil | ||
30 | End: | ||
31 | --> | ||
diff --git a/Documentation/DocBook/v4l/io.xml b/Documentation/DocBook/v4l/io.xml index e870330cbf77..d424886beda0 100644 --- a/Documentation/DocBook/v4l/io.xml +++ b/Documentation/DocBook/v4l/io.xml | |||
@@ -702,6 +702,16 @@ They can be both cleared however, then the buffer is in "dequeued" | |||
702 | state, in the application domain to say so.</entry> | 702 | state, in the application domain to say so.</entry> |
703 | </row> | 703 | </row> |
704 | <row> | 704 | <row> |
705 | <entry><constant>V4L2_BUF_FLAG_ERROR</constant></entry> | ||
706 | <entry>0x0040</entry> | ||
707 | <entry>When this flag is set, the buffer has been dequeued | ||
708 | successfully, although the data might have been corrupted. | ||
709 | This is recoverable, streaming may continue as normal and | ||
710 | the buffer may be reused normally. | ||
711 | Drivers set this flag when the <constant>VIDIOC_DQBUF</constant> | ||
712 | ioctl is called.</entry> | ||
713 | </row> | ||
714 | <row> | ||
705 | <entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry> | 715 | <entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry> |
706 | <entry>0x0008</entry> | 716 | <entry>0x0008</entry> |
707 | <entry>Drivers set or clear this flag when calling the | 717 | <entry>Drivers set or clear this flag when calling the |
@@ -918,8 +928,8 @@ order</emphasis>.</para> | |||
918 | 928 | ||
919 | <para>When the driver provides or accepts images field by field | 929 | <para>When the driver provides or accepts images field by field |
920 | rather than interleaved, it is also important applications understand | 930 | rather than interleaved, it is also important applications understand |
921 | how the fields combine to frames. We distinguish between top and | 931 | how the fields combine to frames. We distinguish between top (aka odd) and |
922 | bottom fields, the <emphasis>spatial order</emphasis>: The first line | 932 | bottom (aka even) fields, the <emphasis>spatial order</emphasis>: The first line |
923 | of the top field is the first line of an interlaced frame, the first | 933 | of the top field is the first line of an interlaced frame, the first |
924 | line of the bottom field is the second line of that frame.</para> | 934 | line of the bottom field is the second line of that frame.</para> |
925 | 935 | ||
@@ -972,12 +982,12 @@ between <constant>V4L2_FIELD_TOP</constant> and | |||
972 | <row> | 982 | <row> |
973 | <entry><constant>V4L2_FIELD_TOP</constant></entry> | 983 | <entry><constant>V4L2_FIELD_TOP</constant></entry> |
974 | <entry>2</entry> | 984 | <entry>2</entry> |
975 | <entry>Images consist of the top field only.</entry> | 985 | <entry>Images consist of the top (aka odd) field only.</entry> |
976 | </row> | 986 | </row> |
977 | <row> | 987 | <row> |
978 | <entry><constant>V4L2_FIELD_BOTTOM</constant></entry> | 988 | <entry><constant>V4L2_FIELD_BOTTOM</constant></entry> |
979 | <entry>3</entry> | 989 | <entry>3</entry> |
980 | <entry>Images consist of the bottom field only. | 990 | <entry>Images consist of the bottom (aka even) field only. |
981 | Applications may wish to prevent a device from capturing interlaced | 991 | Applications may wish to prevent a device from capturing interlaced |
982 | images because they will have "comb" or "feathering" artefacts around | 992 | images because they will have "comb" or "feathering" artefacts around |
983 | moving objects.</entry> | 993 | moving objects.</entry> |
diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml index 885968d6a2fc..c4ad0a8e42dc 100644 --- a/Documentation/DocBook/v4l/pixfmt.xml +++ b/Documentation/DocBook/v4l/pixfmt.xml | |||
@@ -792,6 +792,18 @@ http://www.thedirks.org/winnov/</ulink></para></entry> | |||
792 | <entry>'YYUV'</entry> | 792 | <entry>'YYUV'</entry> |
793 | <entry>unknown</entry> | 793 | <entry>unknown</entry> |
794 | </row> | 794 | </row> |
795 | <row id="V4L2-PIX-FMT-Y4"> | ||
796 | <entry><constant>V4L2_PIX_FMT_Y4</constant></entry> | ||
797 | <entry>'Y04 '</entry> | ||
798 | <entry>Old 4-bit greyscale format. Only the least significant 4 bits of each byte are used, | ||
799 | the other bits are set to 0.</entry> | ||
800 | </row> | ||
801 | <row id="V4L2-PIX-FMT-Y6"> | ||
802 | <entry><constant>V4L2_PIX_FMT_Y6</constant></entry> | ||
803 | <entry>'Y06 '</entry> | ||
804 | <entry>Old 6-bit greyscale format. Only the least significant 6 bits of each byte are used, | ||
805 | the other bits are set to 0.</entry> | ||
806 | </row> | ||
795 | </tbody> | 807 | </tbody> |
796 | </tgroup> | 808 | </tgroup> |
797 | </table> | 809 | </table> |
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 060105af49e5..9737243377a3 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml | |||
@@ -401,6 +401,7 @@ and discussions on the V4L mailing list.</revremark> | |||
401 | <section id="ttx"> &sub-dev-teletext; </section> | 401 | <section id="ttx"> &sub-dev-teletext; </section> |
402 | <section id="radio"> &sub-dev-radio; </section> | 402 | <section id="radio"> &sub-dev-radio; </section> |
403 | <section id="rds"> &sub-dev-rds; </section> | 403 | <section id="rds"> &sub-dev-rds; </section> |
404 | <section id="event"> &sub-dev-event; </section> | ||
404 | </chapter> | 405 | </chapter> |
405 | 406 | ||
406 | <chapter id="driver"> | 407 | <chapter id="driver"> |
@@ -426,6 +427,7 @@ and discussions on the V4L mailing list.</revremark> | |||
426 | &sub-cropcap; | 427 | &sub-cropcap; |
427 | &sub-dbg-g-chip-ident; | 428 | &sub-dbg-g-chip-ident; |
428 | &sub-dbg-g-register; | 429 | &sub-dbg-g-register; |
430 | &sub-dqevent; | ||
429 | &sub-encoder-cmd; | 431 | &sub-encoder-cmd; |
430 | &sub-enumaudio; | 432 | &sub-enumaudio; |
431 | &sub-enumaudioout; | 433 | &sub-enumaudioout; |
@@ -467,6 +469,7 @@ and discussions on the V4L mailing list.</revremark> | |||
467 | &sub-reqbufs; | 469 | &sub-reqbufs; |
468 | &sub-s-hw-freq-seek; | 470 | &sub-s-hw-freq-seek; |
469 | &sub-streamon; | 471 | &sub-streamon; |
472 | &sub-subscribe-event; | ||
470 | <!-- End of ioctls. --> | 473 | <!-- End of ioctls. --> |
471 | &sub-mmap; | 474 | &sub-mmap; |
472 | &sub-munmap; | 475 | &sub-munmap; |
diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 068325940658..865b06d9e679 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml | |||
@@ -1018,6 +1018,13 @@ enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> { | |||
1018 | V4L2_COLORFX_NONE = 0, | 1018 | V4L2_COLORFX_NONE = 0, |
1019 | V4L2_COLORFX_BW = 1, | 1019 | V4L2_COLORFX_BW = 1, |
1020 | V4L2_COLORFX_SEPIA = 2, | 1020 | V4L2_COLORFX_SEPIA = 2, |
1021 | V4L2_COLORFX_NEGATIVE = 3, | ||
1022 | V4L2_COLORFX_EMBOSS = 4, | ||
1023 | V4L2_COLORFX_SKETCH = 5, | ||
1024 | V4L2_COLORFX_SKY_BLUE = 6, | ||
1025 | V4L2_COLORFX_GRASS_GREEN = 7, | ||
1026 | V4L2_COLORFX_SKIN_WHITEN = 8, | ||
1027 | V4L2_COLORFX_VIVID = 9. | ||
1021 | }; | 1028 | }; |
1022 | #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) | 1029 | #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) |
1023 | #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) | 1030 | #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) |
@@ -1271,6 +1278,9 @@ enum <link linkend="v4l2-exposure-auto-type">v4l2_exposure_auto_type</link> { | |||
1271 | 1278 | ||
1272 | #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) | 1279 | #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) |
1273 | 1280 | ||
1281 | #define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) | ||
1282 | #define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) | ||
1283 | |||
1274 | /* FM Modulator class control IDs */ | 1284 | /* FM Modulator class control IDs */ |
1275 | #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) | 1285 | #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) |
1276 | #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) | 1286 | #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) |
diff --git a/Documentation/DocBook/v4l/vidioc-dqevent.xml b/Documentation/DocBook/v4l/vidioc-dqevent.xml new file mode 100644 index 000000000000..4e0a7cc30812 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-dqevent.xml | |||
@@ -0,0 +1,131 @@ | |||
1 | <refentry id="vidioc-dqevent"> | ||
2 | <refmeta> | ||
3 | <refentrytitle>ioctl VIDIOC_DQEVENT</refentrytitle> | ||
4 | &manvol; | ||
5 | </refmeta> | ||
6 | |||
7 | <refnamediv> | ||
8 | <refname>VIDIOC_DQEVENT</refname> | ||
9 | <refpurpose>Dequeue event</refpurpose> | ||
10 | </refnamediv> | ||
11 | |||
12 | <refsynopsisdiv> | ||
13 | <funcsynopsis> | ||
14 | <funcprototype> | ||
15 | <funcdef>int <function>ioctl</function></funcdef> | ||
16 | <paramdef>int <parameter>fd</parameter></paramdef> | ||
17 | <paramdef>int <parameter>request</parameter></paramdef> | ||
18 | <paramdef>struct v4l2_event | ||
19 | *<parameter>argp</parameter></paramdef> | ||
20 | </funcprototype> | ||
21 | </funcsynopsis> | ||
22 | </refsynopsisdiv> | ||
23 | |||
24 | <refsect1> | ||
25 | <title>Arguments</title> | ||
26 | |||
27 | <variablelist> | ||
28 | <varlistentry> | ||
29 | <term><parameter>fd</parameter></term> | ||
30 | <listitem> | ||
31 | <para>&fd;</para> | ||
32 | </listitem> | ||
33 | </varlistentry> | ||
34 | <varlistentry> | ||
35 | <term><parameter>request</parameter></term> | ||
36 | <listitem> | ||
37 | <para>VIDIOC_DQEVENT</para> | ||
38 | </listitem> | ||
39 | </varlistentry> | ||
40 | <varlistentry> | ||
41 | <term><parameter>argp</parameter></term> | ||
42 | <listitem> | ||
43 | <para></para> | ||
44 | </listitem> | ||
45 | </varlistentry> | ||
46 | </variablelist> | ||
47 | </refsect1> | ||
48 | |||
49 | <refsect1> | ||
50 | <title>Description</title> | ||
51 | |||
52 | <para>Dequeue an event from a video device. No input is required | ||
53 | for this ioctl. All the fields of the &v4l2-event; structure are | ||
54 | filled by the driver. The file handle will also receive exceptions | ||
55 | which the application may get by e.g. using the select system | ||
56 | call.</para> | ||
57 | |||
58 | <table frame="none" pgwide="1" id="v4l2-event"> | ||
59 | <title>struct <structname>v4l2_event</structname></title> | ||
60 | <tgroup cols="4"> | ||
61 | &cs-str; | ||
62 | <tbody valign="top"> | ||
63 | <row> | ||
64 | <entry>__u32</entry> | ||
65 | <entry><structfield>type</structfield></entry> | ||
66 | <entry></entry> | ||
67 | <entry>Type of the event.</entry> | ||
68 | </row> | ||
69 | <row> | ||
70 | <entry>union</entry> | ||
71 | <entry><structfield>u</structfield></entry> | ||
72 | <entry></entry> | ||
73 | <entry></entry> | ||
74 | </row> | ||
75 | <row> | ||
76 | <entry></entry> | ||
77 | <entry>&v4l2-event-vsync;</entry> | ||
78 | <entry><structfield>vsync</structfield></entry> | ||
79 | <entry>Event data for event V4L2_EVENT_VSYNC. | ||
80 | </entry> | ||
81 | </row> | ||
82 | <row> | ||
83 | <entry></entry> | ||
84 | <entry>__u8</entry> | ||
85 | <entry><structfield>data</structfield>[64]</entry> | ||
86 | <entry>Event data. Defined by the event type. The union | ||
87 | should be used to define easily accessible type for | ||
88 | events.</entry> | ||
89 | </row> | ||
90 | <row> | ||
91 | <entry>__u32</entry> | ||
92 | <entry><structfield>pending</structfield></entry> | ||
93 | <entry></entry> | ||
94 | <entry>Number of pending events excluding this one.</entry> | ||
95 | </row> | ||
96 | <row> | ||
97 | <entry>__u32</entry> | ||
98 | <entry><structfield>sequence</structfield></entry> | ||
99 | <entry></entry> | ||
100 | <entry>Event sequence number. The sequence number is | ||
101 | incremented for every subscribed event that takes place. | ||
102 | If sequence numbers are not contiguous it means that | ||
103 | events have been lost. | ||
104 | </entry> | ||
105 | </row> | ||
106 | <row> | ||
107 | <entry>struct timespec</entry> | ||
108 | <entry><structfield>timestamp</structfield></entry> | ||
109 | <entry></entry> | ||
110 | <entry>Event timestamp.</entry> | ||
111 | </row> | ||
112 | <row> | ||
113 | <entry>__u32</entry> | ||
114 | <entry><structfield>reserved</structfield>[9]</entry> | ||
115 | <entry></entry> | ||
116 | <entry>Reserved for future extensions. Drivers must set | ||
117 | the array to zero.</entry> | ||
118 | </row> | ||
119 | </tbody> | ||
120 | </tgroup> | ||
121 | </table> | ||
122 | |||
123 | </refsect1> | ||
124 | </refentry> | ||
125 | <!-- | ||
126 | Local Variables: | ||
127 | mode: sgml | ||
128 | sgml-parent-document: "v4l2.sgml" | ||
129 | indent-tabs-mode: nil | ||
130 | End: | ||
131 | --> | ||
diff --git a/Documentation/DocBook/v4l/vidioc-enuminput.xml b/Documentation/DocBook/v4l/vidioc-enuminput.xml index 71b868e2fb8f..476fe1d2bba0 100644 --- a/Documentation/DocBook/v4l/vidioc-enuminput.xml +++ b/Documentation/DocBook/v4l/vidioc-enuminput.xml | |||
@@ -283,7 +283,7 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009. | |||
283 | <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry> | 283 | <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry> |
284 | </row> | 284 | </row> |
285 | <row> | 285 | <row> |
286 | <entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry> | 286 | <entry><constant>V4L2_IN_CAP_CUSTOM_TIMINGS</constant></entry> |
287 | <entry>0x00000002</entry> | 287 | <entry>0x00000002</entry> |
288 | <entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry> | 288 | <entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry> |
289 | </row> | 289 | </row> |
diff --git a/Documentation/DocBook/v4l/vidioc-qbuf.xml b/Documentation/DocBook/v4l/vidioc-qbuf.xml index b843bd7b3897..ab691ebf3b93 100644 --- a/Documentation/DocBook/v4l/vidioc-qbuf.xml +++ b/Documentation/DocBook/v4l/vidioc-qbuf.xml | |||
@@ -111,7 +111,11 @@ from the driver's outgoing queue. They just set the | |||
111 | and <structfield>reserved</structfield> | 111 | and <structfield>reserved</structfield> |
112 | fields of a &v4l2-buffer; as above, when <constant>VIDIOC_DQBUF</constant> | 112 | fields of a &v4l2-buffer; as above, when <constant>VIDIOC_DQBUF</constant> |
113 | is called with a pointer to this structure the driver fills the | 113 | is called with a pointer to this structure the driver fills the |
114 | remaining fields or returns an error code.</para> | 114 | remaining fields or returns an error code. The driver may also set |
115 | <constant>V4L2_BUF_FLAG_ERROR</constant> in the <structfield>flags</structfield> | ||
116 | field. It indicates a non-critical (recoverable) streaming error. In such case | ||
117 | the application may continue as normal, but should be aware that data in the | ||
118 | dequeued buffer might be corrupted.</para> | ||
115 | 119 | ||
116 | <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no | 120 | <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no |
117 | buffer is in the outgoing queue. When the | 121 | buffer is in the outgoing queue. When the |
@@ -158,7 +162,13 @@ enqueue a user pointer buffer.</para> | |||
158 | <para><constant>VIDIOC_DQBUF</constant> failed due to an | 162 | <para><constant>VIDIOC_DQBUF</constant> failed due to an |
159 | internal error. Can also indicate temporary problems like signal | 163 | internal error. Can also indicate temporary problems like signal |
160 | loss. Note the driver might dequeue an (empty) buffer despite | 164 | loss. Note the driver might dequeue an (empty) buffer despite |
161 | returning an error, or even stop capturing.</para> | 165 | returning an error, or even stop capturing. Reusing such buffer may be unsafe |
166 | though and its details (e.g. <structfield>index</structfield>) may not be | ||
167 | returned either. It is recommended that drivers indicate recoverable errors | ||
168 | by setting the <constant>V4L2_BUF_FLAG_ERROR</constant> and returning 0 instead. | ||
169 | In that case the application should be able to safely reuse the buffer and | ||
170 | continue streaming. | ||
171 | </para> | ||
162 | </listitem> | 172 | </listitem> |
163 | </varlistentry> | 173 | </varlistentry> |
164 | </variablelist> | 174 | </variablelist> |
diff --git a/Documentation/DocBook/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/v4l/vidioc-queryctrl.xml index 4876ff1a1a04..8e0e055ac934 100644 --- a/Documentation/DocBook/v4l/vidioc-queryctrl.xml +++ b/Documentation/DocBook/v4l/vidioc-queryctrl.xml | |||
@@ -325,7 +325,7 @@ should be part of the control documentation.</entry> | |||
325 | <entry>n/a</entry> | 325 | <entry>n/a</entry> |
326 | <entry>This is not a control. When | 326 | <entry>This is not a control. When |
327 | <constant>VIDIOC_QUERYCTRL</constant> is called with a control ID | 327 | <constant>VIDIOC_QUERYCTRL</constant> is called with a control ID |
328 | equal to a control class code (see <xref linkend="ctrl-class" />), the | 328 | equal to a control class code (see <xref linkend="ctrl-class" />) + 1, the |
329 | ioctl returns the name of the control class and this control type. | 329 | ioctl returns the name of the control class and this control type. |
330 | Older drivers which do not support this feature return an | 330 | Older drivers which do not support this feature return an |
331 | &EINVAL;.</entry> | 331 | &EINVAL;.</entry> |
diff --git a/Documentation/DocBook/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/v4l/vidioc-reqbufs.xml index 1c0816372074..69800ae23348 100644 --- a/Documentation/DocBook/v4l/vidioc-reqbufs.xml +++ b/Documentation/DocBook/v4l/vidioc-reqbufs.xml | |||
@@ -61,7 +61,7 @@ fields of the <structname>v4l2_requestbuffers</structname> structure. | |||
61 | They set the <structfield>type</structfield> field to the respective | 61 | They set the <structfield>type</structfield> field to the respective |
62 | stream or buffer type, the <structfield>count</structfield> field to | 62 | stream or buffer type, the <structfield>count</structfield> field to |
63 | the desired number of buffers, <structfield>memory</structfield> | 63 | the desired number of buffers, <structfield>memory</structfield> |
64 | must be set to the requested I/O method and the reserved array | 64 | must be set to the requested I/O method and the <structfield>reserved</structfield> array |
65 | must be zeroed. When the ioctl | 65 | must be zeroed. When the ioctl |
66 | is called with a pointer to this structure the driver will attempt to allocate | 66 | is called with a pointer to this structure the driver will attempt to allocate |
67 | the requested number of buffers and it stores the actual number | 67 | the requested number of buffers and it stores the actual number |
diff --git a/Documentation/DocBook/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/v4l/vidioc-subscribe-event.xml new file mode 100644 index 000000000000..8b501791aa68 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subscribe-event.xml | |||
@@ -0,0 +1,133 @@ | |||
1 | <refentry id="vidioc-subscribe-event"> | ||
2 | <refmeta> | ||
3 | <refentrytitle>ioctl VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refentrytitle> | ||
4 | &manvol; | ||
5 | </refmeta> | ||
6 | |||
7 | <refnamediv> | ||
8 | <refname>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refname> | ||
9 | <refpurpose>Subscribe or unsubscribe event</refpurpose> | ||
10 | </refnamediv> | ||
11 | |||
12 | <refsynopsisdiv> | ||
13 | <funcsynopsis> | ||
14 | <funcprototype> | ||
15 | <funcdef>int <function>ioctl</function></funcdef> | ||
16 | <paramdef>int <parameter>fd</parameter></paramdef> | ||
17 | <paramdef>int <parameter>request</parameter></paramdef> | ||
18 | <paramdef>struct v4l2_event_subscription | ||
19 | *<parameter>argp</parameter></paramdef> | ||
20 | </funcprototype> | ||
21 | </funcsynopsis> | ||
22 | </refsynopsisdiv> | ||
23 | |||
24 | <refsect1> | ||
25 | <title>Arguments</title> | ||
26 | |||
27 | <variablelist> | ||
28 | <varlistentry> | ||
29 | <term><parameter>fd</parameter></term> | ||
30 | <listitem> | ||
31 | <para>&fd;</para> | ||
32 | </listitem> | ||
33 | </varlistentry> | ||
34 | <varlistentry> | ||
35 | <term><parameter>request</parameter></term> | ||
36 | <listitem> | ||
37 | <para>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</para> | ||
38 | </listitem> | ||
39 | </varlistentry> | ||
40 | <varlistentry> | ||
41 | <term><parameter>argp</parameter></term> | ||
42 | <listitem> | ||
43 | <para></para> | ||
44 | </listitem> | ||
45 | </varlistentry> | ||
46 | </variablelist> | ||
47 | </refsect1> | ||
48 | |||
49 | <refsect1> | ||
50 | <title>Description</title> | ||
51 | |||
52 | <para>Subscribe or unsubscribe V4L2 event. Subscribed events are | ||
53 | dequeued by using the &VIDIOC-DQEVENT; ioctl.</para> | ||
54 | |||
55 | <table frame="none" pgwide="1" id="v4l2-event-subscription"> | ||
56 | <title>struct <structname>v4l2_event_subscription</structname></title> | ||
57 | <tgroup cols="3"> | ||
58 | &cs-str; | ||
59 | <tbody valign="top"> | ||
60 | <row> | ||
61 | <entry>__u32</entry> | ||
62 | <entry><structfield>type</structfield></entry> | ||
63 | <entry>Type of the event.</entry> | ||
64 | </row> | ||
65 | <row> | ||
66 | <entry>__u32</entry> | ||
67 | <entry><structfield>reserved</structfield>[7]</entry> | ||
68 | <entry>Reserved for future extensions. Drivers and applications | ||
69 | must set the array to zero.</entry> | ||
70 | </row> | ||
71 | </tbody> | ||
72 | </tgroup> | ||
73 | </table> | ||
74 | |||
75 | <table frame="none" pgwide="1" id="event-type"> | ||
76 | <title>Event Types</title> | ||
77 | <tgroup cols="3"> | ||
78 | &cs-def; | ||
79 | <tbody valign="top"> | ||
80 | <row> | ||
81 | <entry><constant>V4L2_EVENT_ALL</constant></entry> | ||
82 | <entry>0</entry> | ||
83 | <entry>All events. V4L2_EVENT_ALL is valid only for | ||
84 | VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once. | ||
85 | </entry> | ||
86 | </row> | ||
87 | <row> | ||
88 | <entry><constant>V4L2_EVENT_VSYNC</constant></entry> | ||
89 | <entry>1</entry> | ||
90 | <entry>This event is triggered on the vertical sync. | ||
91 | This event has &v4l2-event-vsync; associated with it. | ||
92 | </entry> | ||
93 | </row> | ||
94 | <row> | ||
95 | <entry><constant>V4L2_EVENT_EOS</constant></entry> | ||
96 | <entry>2</entry> | ||
97 | <entry>This event is triggered when the end of a stream is reached. | ||
98 | This is typically used with MPEG decoders to report to the application | ||
99 | when the last of the MPEG stream has been decoded. | ||
100 | </entry> | ||
101 | </row> | ||
102 | <row> | ||
103 | <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry> | ||
104 | <entry>0x08000000</entry> | ||
105 | <entry>Base event number for driver-private events.</entry> | ||
106 | </row> | ||
107 | </tbody> | ||
108 | </tgroup> | ||
109 | </table> | ||
110 | |||
111 | <table frame="none" pgwide="1" id="v4l2-event-vsync"> | ||
112 | <title>struct <structname>v4l2_event_vsync</structname></title> | ||
113 | <tgroup cols="3"> | ||
114 | &cs-str; | ||
115 | <tbody valign="top"> | ||
116 | <row> | ||
117 | <entry>__u8</entry> | ||
118 | <entry><structfield>field</structfield></entry> | ||
119 | <entry>The upcoming field. See &v4l2-field;.</entry> | ||
120 | </row> | ||
121 | </tbody> | ||
122 | </tgroup> | ||
123 | </table> | ||
124 | |||
125 | </refsect1> | ||
126 | </refentry> | ||
127 | <!-- | ||
128 | Local Variables: | ||
129 | mode: sgml | ||
130 | sgml-parent-document: "v4l2.sgml" | ||
131 | indent-tabs-mode: nil | ||
132 | End: | ||
133 | --> | ||
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f11c583295e9..4739d5684305 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv | |||
@@ -100,7 +100,7 @@ | |||
100 | 99 -> AD-TVK503 | 100 | 99 -> AD-TVK503 |
101 | 100 -> Hercules Smart TV Stereo | 101 | 100 -> Hercules Smart TV Stereo |
102 | 101 -> Pace TV & Radio Card | 102 | 101 -> Pace TV & Radio Card |
103 | 102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155] | 103 | 102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155,0800:a155,0801:a155,0802:a155,0803:a155] |
104 | 103 -> Grand X-Guard / Trust 814PCI [0304:0102] | 104 | 103 -> Grand X-Guard / Trust 814PCI [0304:0102] |
105 | 104 -> Nebula Electronics DigiTV [0071:0101] | 105 | 104 -> Nebula Electronics DigiTV [0071:0101] |
106 | 105 -> ProVideo PV143 [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433] | 106 | 105 -> ProVideo PV143 [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433] |
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7ec3c4e4b60f..f2510541373b 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 | |||
@@ -82,3 +82,4 @@ | |||
82 | 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] | 82 | 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] |
83 | 82 -> WinFast DTV2000 H rev. J [107d:6f2b] | 83 | 82 -> WinFast DTV2000 H rev. J [107d:6f2b] |
84 | 83 -> Prof 7301 DVB-S/S2 [b034:3034] | 84 | 83 -> Prof 7301 DVB-S/S2 [b034:3034] |
85 | 84 -> Samsung SMT 7020 DVB-S [18ac:dc00,18ac:dccd] | ||
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 0c166ff003a0..3a623aaeae5f 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx | |||
@@ -1,5 +1,5 @@ | |||
1 | 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] | 1 | 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] |
2 | 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] | 2 | 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] |
3 | 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] | 3 | 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] |
4 | 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] | 4 | 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] |
5 | 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] | 5 | 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] |
@@ -27,6 +27,7 @@ | |||
27 | 26 -> Hercules Smart TV USB 2.0 (em2820/em2840) | 27 | 26 -> Hercules Smart TV USB 2.0 (em2820/em2840) |
28 | 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840) | 28 | 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840) |
29 | 28 -> Leadtek Winfast USB II Deluxe (em2820/em2840) | 29 | 28 -> Leadtek Winfast USB II Deluxe (em2820/em2840) |
30 | 29 -> EM2860/TVP5150 Reference Design (em2860) | ||
30 | 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) | 31 | 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) |
31 | 31 -> Usbgear VD204v9 (em2821) | 32 | 31 -> Usbgear VD204v9 (em2821) |
32 | 32 -> Supercomp USB 2.0 TV (em2821) | 33 | 32 -> Supercomp USB 2.0 TV (em2821) |
@@ -70,3 +71,4 @@ | |||
70 | 72 -> Gadmei UTV330+ (em2861) | 71 | 72 -> Gadmei UTV330+ (em2861) |
71 | 73 -> Reddo DVB-C USB TV Box (em2870) | 72 | 73 -> Reddo DVB-C USB TV Box (em2870) |
72 | 74 -> Actionmaster/LinXcel/Digitus VC211A (em2800) | 73 | 74 -> Actionmaster/LinXcel/Digitus VC211A (em2800) |
74 | 75 -> Dikom DK300 (em2882) | ||
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b4a767060ed7..070f2576707e 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
@@ -175,3 +175,6 @@ | |||
175 | 174 -> Asus Europa Hybrid OEM [1043:4847] | 175 | 174 -> Asus Europa Hybrid OEM [1043:4847] |
176 | 175 -> Leadtek Winfast DTV1000S [107d:6655] | 176 | 175 -> Leadtek Winfast DTV1000S [107d:6655] |
177 | 176 -> Beholder BeholdTV 505 RDS [0000:5051] | 177 | 176 -> Beholder BeholdTV 505 RDS [0000:5051] |
178 | 177 -> Hawell HW-404M7 | ||
179 | 179 -> Beholder BeholdTV H7 [5ace:7190] | ||
180 | 180 -> Beholder BeholdTV A7 [5ace:7090] | ||
diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl index 2cb816047fc1..47877deae6d7 100644 --- a/Documentation/video4linux/extract_xc3028.pl +++ b/Documentation/video4linux/extract_xc3028.pl | |||
@@ -5,12 +5,18 @@ | |||
5 | # | 5 | # |
6 | # In order to use, you need to: | 6 | # In order to use, you need to: |
7 | # 1) Download the windows driver with something like: | 7 | # 1) Download the windows driver with something like: |
8 | # Version 2.4 | ||
9 | # wget http://www.twinhan.com/files/AW/BDA T/20080303_V1.0.6.7.zip | ||
10 | # or wget http://www.stefanringel.de/pub/20080303_V1.0.6.7.zip | ||
11 | # Version 2.7 | ||
8 | # wget http://www.steventoth.net/linux/xc5000/HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip | 12 | # wget http://www.steventoth.net/linux/xc5000/HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip |
9 | # 2) Extract the file hcw85bda.sys from the zip into the current dir: | 13 | # 2) Extract the files from the zip into the current dir: |
14 | # unzip -j 20080303_V1.0.6.7.zip 20080303_v1.0.6.7/UDXTTM6000.sys | ||
10 | # unzip -j HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip Driver85/hcw85bda.sys | 15 | # unzip -j HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip Driver85/hcw85bda.sys |
11 | # 3) run the script: | 16 | # 3) run the script: |
12 | # ./extract_xc3028.pl | 17 | # ./extract_xc3028.pl |
13 | # 4) copy the generated file: | 18 | # 4) copy the generated files: |
19 | # cp xc3028-v24.fw /lib/firmware | ||
14 | # cp xc3028-v27.fw /lib/firmware | 20 | # cp xc3028-v27.fw /lib/firmware |
15 | 21 | ||
16 | #use strict; | 22 | #use strict; |
@@ -135,7 +141,7 @@ sub write_hunk_fix_endian($$) | |||
135 | } | 141 | } |
136 | } | 142 | } |
137 | 143 | ||
138 | sub main_firmware($$$$) | 144 | sub main_firmware_24($$$$) |
139 | { | 145 | { |
140 | my $out; | 146 | my $out; |
141 | my $j=0; | 147 | my $j=0; |
@@ -146,8 +152,774 @@ sub main_firmware($$$$) | |||
146 | 152 | ||
147 | for ($j = length($name); $j <32; $j++) { | 153 | for ($j = length($name); $j <32; $j++) { |
148 | $name = $name.chr(0); | 154 | $name = $name.chr(0); |
155 | } | ||
156 | |||
157 | open OUTFILE, ">$outfile"; | ||
158 | syswrite(OUTFILE, $name); | ||
159 | write_le16($version); | ||
160 | write_le16($nr_desc); | ||
161 | |||
162 | # | ||
163 | # Firmware 0, type: BASE FW F8MHZ (0x00000003), id: (0000000000000000), size: 6635 | ||
164 | # | ||
165 | |||
166 | write_le32(0x00000003); # Type | ||
167 | write_le64(0x00000000, 0x00000000); # ID | ||
168 | write_le32(6635); # Size | ||
169 | write_hunk_fix_endian(257752, 6635); | ||
170 | |||
171 | # | ||
172 | # Firmware 1, type: BASE FW F8MHZ MTS (0x00000007), id: (0000000000000000), size: 6635 | ||
173 | # | ||
174 | |||
175 | write_le32(0x00000007); # Type | ||
176 | write_le64(0x00000000, 0x00000000); # ID | ||
177 | write_le32(6635); # Size | ||
178 | write_hunk_fix_endian(264392, 6635); | ||
179 | |||
180 | # | ||
181 | # Firmware 2, type: BASE FW FM (0x00000401), id: (0000000000000000), size: 6525 | ||
182 | # | ||
183 | |||
184 | write_le32(0x00000401); # Type | ||
185 | write_le64(0x00000000, 0x00000000); # ID | ||
186 | write_le32(6525); # Size | ||
187 | write_hunk_fix_endian(271040, 6525); | ||
188 | |||
189 | # | ||
190 | # Firmware 3, type: BASE FW FM INPUT1 (0x00000c01), id: (0000000000000000), size: 6539 | ||
191 | # | ||
192 | |||
193 | write_le32(0x00000c01); # Type | ||
194 | write_le64(0x00000000, 0x00000000); # ID | ||
195 | write_le32(6539); # Size | ||
196 | write_hunk_fix_endian(277568, 6539); | ||
197 | |||
198 | # | ||
199 | # Firmware 4, type: BASE FW (0x00000001), id: (0000000000000000), size: 6633 | ||
200 | # | ||
201 | |||
202 | write_le32(0x00000001); # Type | ||
203 | write_le64(0x00000000, 0x00000000); # ID | ||
204 | write_le32(6633); # Size | ||
205 | write_hunk_fix_endian(284120, 6633); | ||
206 | |||
207 | # | ||
208 | # Firmware 5, type: BASE FW MTS (0x00000005), id: (0000000000000000), size: 6617 | ||
209 | # | ||
210 | |||
211 | write_le32(0x00000005); # Type | ||
212 | write_le64(0x00000000, 0x00000000); # ID | ||
213 | write_le32(6617); # Size | ||
214 | write_hunk_fix_endian(290760, 6617); | ||
215 | |||
216 | # | ||
217 | # Firmware 6, type: STD FW (0x00000000), id: PAL/BG A2/A (0000000100000007), size: 161 | ||
218 | # | ||
219 | |||
220 | write_le32(0x00000000); # Type | ||
221 | write_le64(0x00000001, 0x00000007); # ID | ||
222 | write_le32(161); # Size | ||
223 | write_hunk_fix_endian(297384, 161); | ||
224 | |||
225 | # | ||
226 | # Firmware 7, type: STD FW MTS (0x00000004), id: PAL/BG A2/A (0000000100000007), size: 169 | ||
227 | # | ||
228 | |||
229 | write_le32(0x00000004); # Type | ||
230 | write_le64(0x00000001, 0x00000007); # ID | ||
231 | write_le32(169); # Size | ||
232 | write_hunk_fix_endian(297552, 169); | ||
233 | |||
234 | # | ||
235 | # Firmware 8, type: STD FW (0x00000000), id: PAL/BG A2/B (0000000200000007), size: 161 | ||
236 | # | ||
237 | |||
238 | write_le32(0x00000000); # Type | ||
239 | write_le64(0x00000002, 0x00000007); # ID | ||
240 | write_le32(161); # Size | ||
241 | write_hunk_fix_endian(297728, 161); | ||
242 | |||
243 | # | ||
244 | # Firmware 9, type: STD FW MTS (0x00000004), id: PAL/BG A2/B (0000000200000007), size: 169 | ||
245 | # | ||
246 | |||
247 | write_le32(0x00000004); # Type | ||
248 | write_le64(0x00000002, 0x00000007); # ID | ||
249 | write_le32(169); # Size | ||
250 | write_hunk_fix_endian(297896, 169); | ||
251 | |||
252 | # | ||
253 | # Firmware 10, type: STD FW (0x00000000), id: PAL/BG NICAM/A (0000000400000007), size: 161 | ||
254 | # | ||
255 | |||
256 | write_le32(0x00000000); # Type | ||
257 | write_le64(0x00000004, 0x00000007); # ID | ||
258 | write_le32(161); # Size | ||
259 | write_hunk_fix_endian(298072, 161); | ||
260 | |||
261 | # | ||
262 | # Firmware 11, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/A (0000000400000007), size: 169 | ||
263 | # | ||
264 | |||
265 | write_le32(0x00000004); # Type | ||
266 | write_le64(0x00000004, 0x00000007); # ID | ||
267 | write_le32(169); # Size | ||
268 | write_hunk_fix_endian(298240, 169); | ||
269 | |||
270 | # | ||
271 | # Firmware 12, type: STD FW (0x00000000), id: PAL/BG NICAM/B (0000000800000007), size: 161 | ||
272 | # | ||
273 | |||
274 | write_le32(0x00000000); # Type | ||
275 | write_le64(0x00000008, 0x00000007); # ID | ||
276 | write_le32(161); # Size | ||
277 | write_hunk_fix_endian(298416, 161); | ||
278 | |||
279 | # | ||
280 | # Firmware 13, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/B (0000000800000007), size: 169 | ||
281 | # | ||
282 | |||
283 | write_le32(0x00000004); # Type | ||
284 | write_le64(0x00000008, 0x00000007); # ID | ||
285 | write_le32(169); # Size | ||
286 | write_hunk_fix_endian(298584, 169); | ||
287 | |||
288 | # | ||
289 | # Firmware 14, type: STD FW (0x00000000), id: PAL/DK A2 (00000003000000e0), size: 161 | ||
290 | # | ||
291 | |||
292 | write_le32(0x00000000); # Type | ||
293 | write_le64(0x00000003, 0x000000e0); # ID | ||
294 | write_le32(161); # Size | ||
295 | write_hunk_fix_endian(298760, 161); | ||
296 | |||
297 | # | ||
298 | # Firmware 15, type: STD FW MTS (0x00000004), id: PAL/DK A2 (00000003000000e0), size: 169 | ||
299 | # | ||
300 | |||
301 | write_le32(0x00000004); # Type | ||
302 | write_le64(0x00000003, 0x000000e0); # ID | ||
303 | write_le32(169); # Size | ||
304 | write_hunk_fix_endian(298928, 169); | ||
305 | |||
306 | # | ||
307 | # Firmware 16, type: STD FW (0x00000000), id: PAL/DK NICAM (0000000c000000e0), size: 161 | ||
308 | # | ||
309 | |||
310 | write_le32(0x00000000); # Type | ||
311 | write_le64(0x0000000c, 0x000000e0); # ID | ||
312 | write_le32(161); # Size | ||
313 | write_hunk_fix_endian(299104, 161); | ||
314 | |||
315 | # | ||
316 | # Firmware 17, type: STD FW MTS (0x00000004), id: PAL/DK NICAM (0000000c000000e0), size: 169 | ||
317 | # | ||
318 | |||
319 | write_le32(0x00000004); # Type | ||
320 | write_le64(0x0000000c, 0x000000e0); # ID | ||
321 | write_le32(169); # Size | ||
322 | write_hunk_fix_endian(299272, 169); | ||
323 | |||
324 | # | ||
325 | # Firmware 18, type: STD FW (0x00000000), id: SECAM/K1 (0000000000200000), size: 161 | ||
326 | # | ||
327 | |||
328 | write_le32(0x00000000); # Type | ||
329 | write_le64(0x00000000, 0x00200000); # ID | ||
330 | write_le32(161); # Size | ||
331 | write_hunk_fix_endian(299448, 161); | ||
332 | |||
333 | # | ||
334 | # Firmware 19, type: STD FW MTS (0x00000004), id: SECAM/K1 (0000000000200000), size: 169 | ||
335 | # | ||
336 | |||
337 | write_le32(0x00000004); # Type | ||
338 | write_le64(0x00000000, 0x00200000); # ID | ||
339 | write_le32(169); # Size | ||
340 | write_hunk_fix_endian(299616, 169); | ||
341 | |||
342 | # | ||
343 | # Firmware 20, type: STD FW (0x00000000), id: SECAM/K3 (0000000004000000), size: 161 | ||
344 | # | ||
345 | |||
346 | write_le32(0x00000000); # Type | ||
347 | write_le64(0x00000000, 0x04000000); # ID | ||
348 | write_le32(161); # Size | ||
349 | write_hunk_fix_endian(299792, 161); | ||
350 | |||
351 | # | ||
352 | # Firmware 21, type: STD FW MTS (0x00000004), id: SECAM/K3 (0000000004000000), size: 169 | ||
353 | # | ||
354 | |||
355 | write_le32(0x00000004); # Type | ||
356 | write_le64(0x00000000, 0x04000000); # ID | ||
357 | write_le32(169); # Size | ||
358 | write_hunk_fix_endian(299960, 169); | ||
359 | |||
360 | # | ||
361 | # Firmware 22, type: STD FW D2633 DTV6 ATSC (0x00010030), id: (0000000000000000), size: 149 | ||
362 | # | ||
363 | |||
364 | write_le32(0x00010030); # Type | ||
365 | write_le64(0x00000000, 0x00000000); # ID | ||
366 | write_le32(149); # Size | ||
367 | write_hunk_fix_endian(300136, 149); | ||
368 | |||
369 | # | ||
370 | # Firmware 23, type: STD FW D2620 DTV6 QAM (0x00000068), id: (0000000000000000), size: 149 | ||
371 | # | ||
372 | |||
373 | write_le32(0x00000068); # Type | ||
374 | write_le64(0x00000000, 0x00000000); # ID | ||
375 | write_le32(149); # Size | ||
376 | write_hunk_fix_endian(300296, 149); | ||
377 | |||
378 | # | ||
379 | # Firmware 24, type: STD FW D2633 DTV6 QAM (0x00000070), id: (0000000000000000), size: 149 | ||
380 | # | ||
381 | |||
382 | write_le32(0x00000070); # Type | ||
383 | write_le64(0x00000000, 0x00000000); # ID | ||
384 | write_le32(149); # Size | ||
385 | write_hunk_fix_endian(300448, 149); | ||
386 | |||
387 | # | ||
388 | # Firmware 25, type: STD FW D2620 DTV7 (0x00000088), id: (0000000000000000), size: 149 | ||
389 | # | ||
390 | |||
391 | write_le32(0x00000088); # Type | ||
392 | write_le64(0x00000000, 0x00000000); # ID | ||
393 | write_le32(149); # Size | ||
394 | write_hunk_fix_endian(300608, 149); | ||
395 | |||
396 | # | ||
397 | # Firmware 26, type: STD FW D2633 DTV7 (0x00000090), id: (0000000000000000), size: 149 | ||
398 | # | ||
399 | |||
400 | write_le32(0x00000090); # Type | ||
401 | write_le64(0x00000000, 0x00000000); # ID | ||
402 | write_le32(149); # Size | ||
403 | write_hunk_fix_endian(300760, 149); | ||
404 | |||
405 | # | ||
406 | # Firmware 27, type: STD FW D2620 DTV78 (0x00000108), id: (0000000000000000), size: 149 | ||
407 | # | ||
408 | |||
409 | write_le32(0x00000108); # Type | ||
410 | write_le64(0x00000000, 0x00000000); # ID | ||
411 | write_le32(149); # Size | ||
412 | write_hunk_fix_endian(300920, 149); | ||
413 | |||
414 | # | ||
415 | # Firmware 28, type: STD FW D2633 DTV78 (0x00000110), id: (0000000000000000), size: 149 | ||
416 | # | ||
417 | |||
418 | write_le32(0x00000110); # Type | ||
419 | write_le64(0x00000000, 0x00000000); # ID | ||
420 | write_le32(149); # Size | ||
421 | write_hunk_fix_endian(301072, 149); | ||
422 | |||
423 | # | ||
424 | # Firmware 29, type: STD FW D2620 DTV8 (0x00000208), id: (0000000000000000), size: 149 | ||
425 | # | ||
426 | |||
427 | write_le32(0x00000208); # Type | ||
428 | write_le64(0x00000000, 0x00000000); # ID | ||
429 | write_le32(149); # Size | ||
430 | write_hunk_fix_endian(301232, 149); | ||
431 | |||
432 | # | ||
433 | # Firmware 30, type: STD FW D2633 DTV8 (0x00000210), id: (0000000000000000), size: 149 | ||
434 | # | ||
435 | |||
436 | write_le32(0x00000210); # Type | ||
437 | write_le64(0x00000000, 0x00000000); # ID | ||
438 | write_le32(149); # Size | ||
439 | write_hunk_fix_endian(301384, 149); | ||
440 | |||
441 | # | ||
442 | # Firmware 31, type: STD FW FM (0x00000400), id: (0000000000000000), size: 135 | ||
443 | # | ||
444 | |||
445 | write_le32(0x00000400); # Type | ||
446 | write_le64(0x00000000, 0x00000000); # ID | ||
447 | write_le32(135); # Size | ||
448 | write_hunk_fix_endian(301554, 135); | ||
449 | |||
450 | # | ||
451 | # Firmware 32, type: STD FW (0x00000000), id: PAL/I (0000000000000010), size: 161 | ||
452 | # | ||
453 | |||
454 | write_le32(0x00000000); # Type | ||
455 | write_le64(0x00000000, 0x00000010); # ID | ||
456 | write_le32(161); # Size | ||
457 | write_hunk_fix_endian(301688, 161); | ||
458 | |||
459 | # | ||
460 | # Firmware 33, type: STD FW MTS (0x00000004), id: PAL/I (0000000000000010), size: 169 | ||
461 | # | ||
462 | |||
463 | write_le32(0x00000004); # Type | ||
464 | write_le64(0x00000000, 0x00000010); # ID | ||
465 | write_le32(169); # Size | ||
466 | write_hunk_fix_endian(301856, 169); | ||
467 | |||
468 | # | ||
469 | # Firmware 34, type: STD FW (0x00000000), id: SECAM/L AM (0000001000400000), size: 169 | ||
470 | # | ||
471 | |||
472 | # | ||
473 | # Firmware 35, type: STD FW (0x00000000), id: SECAM/L NICAM (0000000c00400000), size: 161 | ||
474 | # | ||
475 | |||
476 | write_le32(0x00000000); # Type | ||
477 | write_le64(0x0000000c, 0x00400000); # ID | ||
478 | write_le32(161); # Size | ||
479 | write_hunk_fix_endian(302032, 161); | ||
480 | |||
481 | # | ||
482 | # Firmware 36, type: STD FW (0x00000000), id: SECAM/Lc (0000000000800000), size: 161 | ||
483 | # | ||
484 | |||
485 | write_le32(0x00000000); # Type | ||
486 | write_le64(0x00000000, 0x00800000); # ID | ||
487 | write_le32(161); # Size | ||
488 | write_hunk_fix_endian(302200, 161); | ||
489 | |||
490 | # | ||
491 | # Firmware 37, type: STD FW (0x00000000), id: NTSC/M Kr (0000000000008000), size: 161 | ||
492 | # | ||
493 | |||
494 | write_le32(0x00000000); # Type | ||
495 | write_le64(0x00000000, 0x00008000); # ID | ||
496 | write_le32(161); # Size | ||
497 | write_hunk_fix_endian(302368, 161); | ||
498 | |||
499 | # | ||
500 | # Firmware 38, type: STD FW LCD (0x00001000), id: NTSC/M Kr (0000000000008000), size: 161 | ||
501 | # | ||
502 | |||
503 | write_le32(0x00001000); # Type | ||
504 | write_le64(0x00000000, 0x00008000); # ID | ||
505 | write_le32(161); # Size | ||
506 | write_hunk_fix_endian(302536, 161); | ||
507 | |||
508 | # | ||
509 | # Firmware 39, type: STD FW LCD NOGD (0x00003000), id: NTSC/M Kr (0000000000008000), size: 161 | ||
510 | # | ||
511 | |||
512 | write_le32(0x00003000); # Type | ||
513 | write_le64(0x00000000, 0x00008000); # ID | ||
514 | write_le32(161); # Size | ||
515 | write_hunk_fix_endian(302704, 161); | ||
516 | |||
517 | # | ||
518 | # Firmware 40, type: STD FW MTS (0x00000004), id: NTSC/M Kr (0000000000008000), size: 169 | ||
519 | # | ||
520 | |||
521 | write_le32(0x00000004); # Type | ||
522 | write_le64(0x00000000, 0x00008000); # ID | ||
523 | write_le32(169); # Size | ||
524 | write_hunk_fix_endian(302872, 169); | ||
525 | |||
526 | # | ||
527 | # Firmware 41, type: STD FW (0x00000000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 | ||
528 | # | ||
529 | |||
530 | write_le32(0x00000000); # Type | ||
531 | write_le64(0x00000000, 0x0000b700); # ID | ||
532 | write_le32(161); # Size | ||
533 | write_hunk_fix_endian(303048, 161); | ||
534 | |||
535 | # | ||
536 | # Firmware 42, type: STD FW LCD (0x00001000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 | ||
537 | # | ||
538 | |||
539 | write_le32(0x00001000); # Type | ||
540 | write_le64(0x00000000, 0x0000b700); # ID | ||
541 | write_le32(161); # Size | ||
542 | write_hunk_fix_endian(303216, 161); | ||
543 | |||
544 | # | ||
545 | # Firmware 43, type: STD FW LCD NOGD (0x00003000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161 | ||
546 | # | ||
547 | |||
548 | write_le32(0x00003000); # Type | ||
549 | write_le64(0x00000000, 0x0000b700); # ID | ||
550 | write_le32(161); # Size | ||
551 | write_hunk_fix_endian(303384, 161); | ||
552 | |||
553 | # | ||
554 | # Firmware 44, type: STD FW (0x00000000), id: NTSC/M Jp (0000000000002000), size: 161 | ||
555 | # | ||
556 | |||
557 | write_le32(0x00000000); # Type | ||
558 | write_le64(0x00000000, 0x00002000); # ID | ||
559 | write_le32(161); # Size | ||
560 | write_hunk_fix_endian(303552, 161); | ||
561 | |||
562 | # | ||
563 | # Firmware 45, type: STD FW MTS (0x00000004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 | ||
564 | # | ||
565 | |||
566 | write_le32(0x00000004); # Type | ||
567 | write_le64(0x00000000, 0x0000b700); # ID | ||
568 | write_le32(169); # Size | ||
569 | write_hunk_fix_endian(303720, 169); | ||
570 | |||
571 | # | ||
572 | # Firmware 46, type: STD FW MTS LCD (0x00001004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 | ||
573 | # | ||
574 | |||
575 | write_le32(0x00001004); # Type | ||
576 | write_le64(0x00000000, 0x0000b700); # ID | ||
577 | write_le32(169); # Size | ||
578 | write_hunk_fix_endian(303896, 169); | ||
579 | |||
580 | # | ||
581 | # Firmware 47, type: STD FW MTS LCD NOGD (0x00003004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169 | ||
582 | # | ||
583 | |||
584 | write_le32(0x00003004); # Type | ||
585 | write_le64(0x00000000, 0x0000b700); # ID | ||
586 | write_le32(169); # Size | ||
587 | write_hunk_fix_endian(304072, 169); | ||
588 | |||
589 | # | ||
590 | # Firmware 48, type: SCODE FW HAS IF (0x60000000), IF = 3.28 MHz id: (0000000000000000), size: 192 | ||
591 | # | ||
592 | |||
593 | write_le32(0x60000000); # Type | ||
594 | write_le64(0x00000000, 0x00000000); # ID | ||
595 | write_le16(3280); # IF | ||
596 | write_le32(192); # Size | ||
597 | write_hunk(309048, 192); | ||
598 | |||
599 | # | ||
600 | # Firmware 49, type: SCODE FW HAS IF (0x60000000), IF = 3.30 MHz id: (0000000000000000), size: 192 | ||
601 | # | ||
602 | |||
603 | # write_le32(0x60000000); # Type | ||
604 | # write_le64(0x00000000, 0x00000000); # ID | ||
605 | # write_le16(3300); # IF | ||
606 | # write_le32(192); # Size | ||
607 | # write_hunk(304440, 192); | ||
608 | |||
609 | # | ||
610 | # Firmware 50, type: SCODE FW HAS IF (0x60000000), IF = 3.44 MHz id: (0000000000000000), size: 192 | ||
611 | # | ||
612 | |||
613 | write_le32(0x60000000); # Type | ||
614 | write_le64(0x00000000, 0x00000000); # ID | ||
615 | write_le16(3440); # IF | ||
616 | write_le32(192); # Size | ||
617 | write_hunk(309432, 192); | ||
618 | |||
619 | # | ||
620 | # Firmware 51, type: SCODE FW HAS IF (0x60000000), IF = 3.46 MHz id: (0000000000000000), size: 192 | ||
621 | # | ||
622 | |||
623 | write_le32(0x60000000); # Type | ||
624 | write_le64(0x00000000, 0x00000000); # ID | ||
625 | write_le16(3460); # IF | ||
626 | write_le32(192); # Size | ||
627 | write_hunk(309624, 192); | ||
628 | |||
629 | # | ||
630 | # Firmware 52, type: SCODE FW DTV6 ATSC OREN36 HAS IF (0x60210020), IF = 3.80 MHz id: (0000000000000000), size: 192 | ||
631 | # | ||
632 | |||
633 | write_le32(0x60210020); # Type | ||
634 | write_le64(0x00000000, 0x00000000); # ID | ||
635 | write_le16(3800); # IF | ||
636 | write_le32(192); # Size | ||
637 | write_hunk(306936, 192); | ||
638 | |||
639 | # | ||
640 | # Firmware 53, type: SCODE FW HAS IF (0x60000000), IF = 4.00 MHz id: (0000000000000000), size: 192 | ||
641 | # | ||
642 | |||
643 | write_le32(0x60000000); # Type | ||
644 | write_le64(0x00000000, 0x00000000); # ID | ||
645 | write_le16(4000); # IF | ||
646 | write_le32(192); # Size | ||
647 | write_hunk(309240, 192); | ||
648 | |||
649 | # | ||
650 | # Firmware 54, type: SCODE FW DTV6 ATSC TOYOTA388 HAS IF (0x60410020), IF = 4.08 MHz id: (0000000000000000), size: 192 | ||
651 | # | ||
652 | |||
653 | write_le32(0x60410020); # Type | ||
654 | write_le64(0x00000000, 0x00000000); # ID | ||
655 | write_le16(4080); # IF | ||
656 | write_le32(192); # Size | ||
657 | write_hunk(307128, 192); | ||
658 | |||
659 | # | ||
660 | # Firmware 55, type: SCODE FW HAS IF (0x60000000), IF = 4.20 MHz id: (0000000000000000), size: 192 | ||
661 | # | ||
662 | |||
663 | write_le32(0x60000000); # Type | ||
664 | write_le64(0x00000000, 0x00000000); # ID | ||
665 | write_le16(4200); # IF | ||
666 | write_le32(192); # Size | ||
667 | write_hunk(308856, 192); | ||
668 | |||
669 | # | ||
670 | # Firmware 56, type: SCODE FW MONO HAS IF (0x60008000), IF = 4.32 MHz id: NTSC/M Kr (0000000000008000), size: 192 | ||
671 | # | ||
672 | |||
673 | write_le32(0x60008000); # Type | ||
674 | write_le64(0x00000000, 0x00008000); # ID | ||
675 | write_le16(4320); # IF | ||
676 | write_le32(192); # Size | ||
677 | write_hunk(305208, 192); | ||
678 | |||
679 | # | ||
680 | # Firmware 57, type: SCODE FW HAS IF (0x60000000), IF = 4.45 MHz id: (0000000000000000), size: 192 | ||
681 | # | ||
682 | |||
683 | write_le32(0x60000000); # Type | ||
684 | write_le64(0x00000000, 0x00000000); # ID | ||
685 | write_le16(4450); # IF | ||
686 | write_le32(192); # Size | ||
687 | write_hunk(309816, 192); | ||
688 | |||
689 | # | ||
690 | # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192 | ||
691 | # | ||
692 | |||
693 | write_le32(0x6002b004); # Type | ||
694 | write_le64(0x00000000, 0x0000b700); # ID | ||
695 | write_le16(4500); # IF | ||
696 | write_le32(192); # Size | ||
697 | write_hunk(304824, 192); | ||
698 | |||
699 | # | ||
700 | # Firmware 59, type: SCODE FW LCD NOGD IF HAS IF (0x60023000), IF = 4.60 MHz id: NTSC/M Kr (0000000000008000), size: 192 | ||
701 | # | ||
702 | |||
703 | write_le32(0x60023000); # Type | ||
704 | write_le64(0x00000000, 0x00008000); # ID | ||
705 | write_le16(4600); # IF | ||
706 | write_le32(192); # Size | ||
707 | write_hunk(305016, 192); | ||
708 | |||
709 | # | ||
710 | # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192 | ||
711 | # | ||
712 | |||
713 | write_le32(0x620003e0); # Type | ||
714 | write_le64(0x00000000, 0x00000000); # ID | ||
715 | write_le16(4760); # IF | ||
716 | write_le32(192); # Size | ||
717 | write_hunk(304440, 192); | ||
718 | |||
719 | # | ||
720 | # Firmware 61, type: SCODE FW HAS IF (0x60000000), IF = 4.94 MHz id: (0000000000000000), size: 192 | ||
721 | # | ||
722 | |||
723 | write_le32(0x60000000); # Type | ||
724 | write_le64(0x00000000, 0x00000000); # ID | ||
725 | write_le16(4940); # IF | ||
726 | write_le32(192); # Size | ||
727 | write_hunk(308664, 192); | ||
728 | |||
729 | # | ||
730 | # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192 | ||
731 | # | ||
732 | |||
733 | write_le32(0x60000000); # Type | ||
734 | write_le64(0x00000000, 0x00000000); # ID | ||
735 | write_le16(5260); # IF | ||
736 | write_le32(192); # Size | ||
737 | write_hunk(307704, 192); | ||
738 | |||
739 | # | ||
740 | # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192 | ||
741 | # | ||
742 | |||
743 | write_le32(0x60008000); # Type | ||
744 | write_le64(0x0000000f, 0x00000007); # ID | ||
745 | write_le16(5320); # IF | ||
746 | write_le32(192); # Size | ||
747 | write_hunk(307896, 192); | ||
748 | |||
749 | # | ||
750 | # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192 | ||
751 | # | ||
752 | |||
753 | write_le32(0x65000380); # Type | ||
754 | write_le64(0x00000000, 0x00000000); # ID | ||
755 | write_le16(5400); # IF | ||
756 | write_le32(192); # Size | ||
757 | write_hunk(304248, 192); | ||
758 | |||
759 | # | ||
760 | # Firmware 65, type: SCODE FW DTV6 ATSC OREN538 HAS IF (0x60110020), IF = 5.58 MHz id: (0000000000000000), size: 192 | ||
761 | # | ||
762 | |||
763 | write_le32(0x60110020); # Type | ||
764 | write_le64(0x00000000, 0x00000000); # ID | ||
765 | write_le16(5580); # IF | ||
766 | write_le32(192); # Size | ||
767 | write_hunk(306744, 192); | ||
768 | |||
769 | # | ||
770 | # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192 | ||
771 | # | ||
772 | |||
773 | write_le32(0x60000000); # Type | ||
774 | write_le64(0x00000003, 0x00000007); # ID | ||
775 | write_le16(5640); # IF | ||
776 | write_le32(192); # Size | ||
777 | write_hunk(305592, 192); | ||
778 | |||
779 | # | ||
780 | # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192 | ||
781 | # | ||
782 | |||
783 | write_le32(0x60000000); # Type | ||
784 | write_le64(0x0000000c, 0x00000007); # ID | ||
785 | write_le16(5740); # IF | ||
786 | write_le32(192); # Size | ||
787 | write_hunk(305784, 192); | ||
788 | |||
789 | # | ||
790 | # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192 | ||
791 | # | ||
792 | |||
793 | write_le32(0x60000000); # Type | ||
794 | write_le64(0x00000000, 0x00000000); # ID | ||
795 | write_le16(5900); # IF | ||
796 | write_le32(192); # Size | ||
797 | write_hunk(307512, 192); | ||
798 | |||
799 | # | ||
800 | # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192 | ||
801 | # | ||
802 | |||
803 | write_le32(0x60008000); # Type | ||
804 | write_le64(0x0000000c, 0x04c000f0); # ID | ||
805 | write_le16(6000); # IF | ||
806 | write_le32(192); # Size | ||
807 | write_hunk(305576, 192); | ||
808 | |||
809 | # | ||
810 | # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192 | ||
811 | # | ||
812 | |||
813 | write_le32(0x68050060); # Type | ||
814 | write_le64(0x00000000, 0x00000000); # ID | ||
815 | write_le16(6200); # IF | ||
816 | write_le32(192); # Size | ||
817 | write_hunk(306552, 192); | ||
818 | |||
819 | # | ||
820 | # Firmware 71, type: SCODE FW HAS IF (0x60000000), IF = 6.24 MHz id: PAL/I (0000000000000010), size: 192 | ||
821 | # | ||
822 | |||
823 | write_le32(0x60000000); # Type | ||
824 | write_le64(0x00000000, 0x00000010); # ID | ||
825 | write_le16(6240); # IF | ||
826 | write_le32(192); # Size | ||
827 | write_hunk(305400, 192); | ||
828 | |||
829 | # | ||
830 | # Firmware 72, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.32 MHz id: SECAM/K1 (0000000000200000), size: 192 | ||
831 | # | ||
832 | |||
833 | write_le32(0x60008000); # Type | ||
834 | write_le64(0x00000000, 0x00200000); # ID | ||
835 | write_le16(6320); # IF | ||
836 | write_le32(192); # Size | ||
837 | write_hunk(308472, 192); | ||
838 | |||
839 | # | ||
840 | # Firmware 73, type: SCODE FW HAS IF (0x60000000), IF = 6.34 MHz id: SECAM/K1 (0000000000200000), size: 192 | ||
841 | # | ||
842 | |||
843 | write_le32(0x60000000); # Type | ||
844 | write_le64(0x00000000, 0x00200000); # ID | ||
845 | write_le16(6340); # IF | ||
846 | write_le32(192); # Size | ||
847 | write_hunk(306360, 192); | ||
848 | |||
849 | # | ||
850 | # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192 | ||
851 | # | ||
852 | |||
853 | write_le32(0x60008000); # Type | ||
854 | write_le64(0x0000000c, 0x044000e0); # ID | ||
855 | write_le16(6500); # IF | ||
856 | write_le32(192); # Size | ||
857 | write_hunk(308280, 192); | ||
858 | |||
859 | # | ||
860 | # Firmware 75, type: SCODE FW DTV6 ATSC ATI638 HAS IF (0x60090020), IF = 6.58 MHz id: (0000000000000000), size: 192 | ||
861 | # | ||
862 | |||
863 | write_le32(0x60090020); # Type | ||
864 | write_le64(0x00000000, 0x00000000); # ID | ||
865 | write_le16(6580); # IF | ||
866 | write_le32(192); # Size | ||
867 | write_hunk(304632, 192); | ||
868 | |||
869 | # | ||
870 | # Firmware 76, type: SCODE FW HAS IF (0x60000000), IF = 6.60 MHz id: PAL/DK A2 (00000003000000e0), size: 192 | ||
871 | # | ||
872 | |||
873 | write_le32(0x60000000); # Type | ||
874 | write_le64(0x00000003, 0x000000e0); # ID | ||
875 | write_le16(6600); # IF | ||
876 | write_le32(192); # Size | ||
877 | write_hunk(306168, 192); | ||
878 | |||
879 | # | ||
880 | # Firmware 77, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.68 MHz id: PAL/DK A2 (00000003000000e0), size: 192 | ||
881 | # | ||
882 | |||
883 | write_le32(0x60008000); # Type | ||
884 | write_le64(0x00000003, 0x000000e0); # ID | ||
885 | write_le16(6680); # IF | ||
886 | write_le32(192); # Size | ||
887 | write_hunk(308088, 192); | ||
888 | |||
889 | # | ||
890 | # Firmware 78, type: SCODE FW DTV6 ATSC TOYOTA794 HAS IF (0x60810020), IF = 8.14 MHz id: (0000000000000000), size: 192 | ||
891 | # | ||
892 | |||
893 | write_le32(0x60810020); # Type | ||
894 | write_le64(0x00000000, 0x00000000); # ID | ||
895 | write_le16(8140); # IF | ||
896 | write_le32(192); # Size | ||
897 | write_hunk(307320, 192); | ||
898 | |||
899 | # | ||
900 | # Firmware 79, type: SCODE FW HAS IF (0x60000000), IF = 8.20 MHz id: (0000000000000000), size: 192 | ||
901 | # | ||
902 | |||
903 | # write_le32(0x60000000); # Type | ||
904 | # write_le64(0x00000000, 0x00000000); # ID | ||
905 | # write_le16(8200); # IF | ||
906 | # write_le32(192); # Size | ||
907 | # write_hunk(308088, 192); | ||
149 | } | 908 | } |
150 | 909 | ||
910 | sub main_firmware_27($$$$) | ||
911 | { | ||
912 | my $out; | ||
913 | my $j=0; | ||
914 | my $outfile = shift; | ||
915 | my $name = shift; | ||
916 | my $version = shift; | ||
917 | my $nr_desc = shift; | ||
918 | |||
919 | for ($j = length($name); $j <32; $j++) { | ||
920 | $name = $name.chr(0); | ||
921 | } | ||
922 | |||
151 | open OUTFILE, ">$outfile"; | 923 | open OUTFILE, ">$outfile"; |
152 | syswrite(OUTFILE, $name); | 924 | syswrite(OUTFILE, $name); |
153 | write_le16($version); | 925 | write_le16($version); |
@@ -906,20 +1678,39 @@ sub main_firmware($$$$) | |||
906 | write_hunk(812856, 192); | 1678 | write_hunk(812856, 192); |
907 | } | 1679 | } |
908 | 1680 | ||
1681 | |||
909 | sub extract_firmware { | 1682 | sub extract_firmware { |
910 | my $sourcefile = "hcw85bda.sys"; | 1683 | my $sourcefile_24 = "UDXTTM6000.sys"; |
911 | my $hash = "0e44dbf63bb0169d57446aec21881ff2"; | 1684 | my $hash_24 = "cb9deb5508a5e150af2880f5b0066d78"; |
912 | my $outfile = "xc3028-v27.fw"; | 1685 | my $outfile_24 = "xc3028-v24.fw"; |
913 | my $name = "xc2028 firmware"; | 1686 | my $name_24 = "xc2028 firmware"; |
914 | my $version = 519; | 1687 | my $version_24 = 516; |
915 | my $nr_desc = 80; | 1688 | my $nr_desc_24 = 77; |
1689 | my $out; | ||
1690 | |||
1691 | my $sourcefile_27 = "hcw85bda.sys"; | ||
1692 | my $hash_27 = "0e44dbf63bb0169d57446aec21881ff2"; | ||
1693 | my $outfile_27 = "xc3028-v27.fw"; | ||
1694 | my $name_27 = "xc2028 firmware"; | ||
1695 | my $version_27 = 519; | ||
1696 | my $nr_desc_27 = 80; | ||
916 | my $out; | 1697 | my $out; |
917 | 1698 | ||
918 | verify($sourcefile, $hash); | 1699 | if (-e $sourcefile_24) { |
1700 | verify($sourcefile_24, $hash_24); | ||
1701 | |||
1702 | open INFILE, "<$sourcefile_24"; | ||
1703 | main_firmware_24($outfile_24, $name_24, $version_24, $nr_desc_24); | ||
1704 | close INFILE; | ||
1705 | } | ||
919 | 1706 | ||
920 | open INFILE, "<$sourcefile"; | 1707 | if (-e $sourcefile_27) { |
921 | main_firmware($outfile, $name, $version, $nr_desc); | 1708 | verify($sourcefile_27, $hash_27); |
922 | close INFILE; | 1709 | |
1710 | open INFILE, "<$sourcefile_27"; | ||
1711 | main_firmware_27($outfile_27, $name_27, $version_27, $nr_desc_27); | ||
1712 | close INFILE; | ||
1713 | } | ||
923 | } | 1714 | } |
924 | 1715 | ||
925 | extract_firmware; | 1716 | extract_firmware; |
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 181b9e6fd984..8f3f5d33327c 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt | |||
@@ -50,6 +50,8 @@ zc3xx 0458:700f Genius VideoCam Web V2 | |||
50 | sonixj 0458:7025 Genius Eye 311Q | 50 | sonixj 0458:7025 Genius Eye 311Q |
51 | sn9c20x 0458:7029 Genius Look 320s | 51 | sn9c20x 0458:7029 Genius Look 320s |
52 | sonixj 0458:702e Genius Slim 310 NB | 52 | sonixj 0458:702e Genius Slim 310 NB |
53 | sn9c20x 0458:704a Genius Slim 1320 | ||
54 | sn9c20x 0458:704c Genius i-Look 1321 | ||
53 | sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650) | 55 | sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650) |
54 | sonixj 045e:00f5 MicroSoft VX3000 | 56 | sonixj 045e:00f5 MicroSoft VX3000 |
55 | sonixj 045e:00f7 MicroSoft VX1000 | 57 | sonixj 045e:00f7 MicroSoft VX1000 |
@@ -305,12 +307,14 @@ sonixj 0c45:6138 Sn9c120 Mo4000 | |||
305 | sonixj 0c45:613a Microdia Sonix PC Camera | 307 | sonixj 0c45:613a Microdia Sonix PC Camera |
306 | sonixj 0c45:613b Surfer SN-206 | 308 | sonixj 0c45:613b Surfer SN-206 |
307 | sonixj 0c45:613c Sonix Pccam168 | 309 | sonixj 0c45:613c Sonix Pccam168 |
310 | sonixj 0c45:6142 Hama PC-Webcam AC-150 | ||
308 | sonixj 0c45:6143 Sonix Pccam168 | 311 | sonixj 0c45:6143 Sonix Pccam168 |
309 | sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia | 312 | sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia |
310 | sonixj 0c45:614a Frontech E-Ccam (JIL-2225) | 313 | sonixj 0c45:614a Frontech E-Ccam (JIL-2225) |
311 | sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001) | 314 | sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001) |
312 | sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111) | 315 | sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111) |
313 | sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655) | 316 | sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655) |
317 | sn9c20x 0c45:624c PC Camera (SN9C201 + MT9M112) | ||
314 | sn9c20x 0c45:624e PC Camera (SN9C201 + SOI968) | 318 | sn9c20x 0c45:624e PC Camera (SN9C201 + SOI968) |
315 | sn9c20x 0c45:624f PC Camera (SN9C201 + OV9650) | 319 | sn9c20x 0c45:624f PC Camera (SN9C201 + OV9650) |
316 | sn9c20x 0c45:6251 PC Camera (SN9C201 + OV9650) | 320 | sn9c20x 0c45:6251 PC Camera (SN9C201 + OV9650) |
@@ -323,6 +327,7 @@ sn9c20x 0c45:627f PC Camera (SN9C201 + OV9650) | |||
323 | sn9c20x 0c45:6280 PC Camera (SN9C202 + MT9M001) | 327 | sn9c20x 0c45:6280 PC Camera (SN9C202 + MT9M001) |
324 | sn9c20x 0c45:6282 PC Camera (SN9C202 + MT9M111) | 328 | sn9c20x 0c45:6282 PC Camera (SN9C202 + MT9M111) |
325 | sn9c20x 0c45:6288 PC Camera (SN9C202 + OV9655) | 329 | sn9c20x 0c45:6288 PC Camera (SN9C202 + OV9655) |
330 | sn9c20x 0c45:628c PC Camera (SN9C201 + MT9M112) | ||
326 | sn9c20x 0c45:628e PC Camera (SN9C202 + SOI968) | 331 | sn9c20x 0c45:628e PC Camera (SN9C202 + SOI968) |
327 | sn9c20x 0c45:628f PC Camera (SN9C202 + OV9650) | 332 | sn9c20x 0c45:628f PC Camera (SN9C202 + OV9650) |
328 | sn9c20x 0c45:62a0 PC Camera (SN9C202 + OV7670) | 333 | sn9c20x 0c45:62a0 PC Camera (SN9C202 + OV7670) |
diff --git a/Documentation/video4linux/sh_mobile_ceu_camera.txt b/Documentation/video4linux/sh_mobile_ceu_camera.txt index 2ae16349a78d..cb47e723af74 100644 --- a/Documentation/video4linux/sh_mobile_ceu_camera.txt +++ b/Documentation/video4linux/sh_mobile_ceu_camera.txt | |||
@@ -17,18 +17,18 @@ Generic scaling / cropping scheme | |||
17 | -2-- -\ | 17 | -2-- -\ |
18 | | --\ | 18 | | --\ |
19 | | --\ | 19 | | --\ |
20 | +-5-- -\ -- -3-- | 20 | +-5-- . -- -3-- -\ |
21 | | ---\ | 21 | | `... -\ |
22 | | --- -4-- -\ | 22 | | `... -4-- . - -7.. |
23 | | -\ | 23 | | `. |
24 | | - -6-- | 24 | | `. .6-- |
25 | | | 25 | | |
26 | | - -6'- | 26 | | . .6'- |
27 | | -/ | 27 | | .´ |
28 | | --- -4'- -/ | 28 | | ... -4'- .´ |
29 | | ---/ | 29 | | ...´ - -7'. |
30 | +-5'- -/ | 30 | +-5'- .´ -/ |
31 | | -- -3'- | 31 | | -- -3'- -/ |
32 | | --/ | 32 | | --/ |
33 | | --/ | 33 | | --/ |
34 | -2'- -/ | 34 | -2'- -/ |
@@ -36,7 +36,11 @@ Generic scaling / cropping scheme | |||
36 | | | 36 | | |
37 | -1'- | 37 | -1'- |
38 | 38 | ||
39 | Produced by user requests: | 39 | In the above chart minuses and slashes represent "real" data amounts, points and |
40 | accents represent "useful" data, basically, CEU scaled amd cropped output, | ||
41 | mapped back onto the client's source plane. | ||
42 | |||
43 | Such a configuration can be produced by user requests: | ||
40 | 44 | ||
41 | S_CROP(left / top = (5) - (1), width / height = (5') - (5)) | 45 | S_CROP(left / top = (5) - (1), width / height = (5') - (5)) |
42 | S_FMT(width / height = (6') - (6)) | 46 | S_FMT(width / height = (6') - (6)) |
@@ -106,52 +110,30 @@ window: | |||
106 | S_CROP | 110 | S_CROP |
107 | ------ | 111 | ------ |
108 | 112 | ||
109 | If old scale applied to new crop is invalid produce nearest new scale possible | 113 | The API at http://v4l2spec.bytesex.org/spec/x1904.htm says: |
110 | |||
111 | 1. Calculate current combined scales. | ||
112 | |||
113 | scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3))) | ||
114 | |||
115 | 2. Apply iterative sensor S_CROP for new input window. | ||
116 | |||
117 | 3. If old combined scales applied to new crop produce an impossible user window, | ||
118 | adjust scales to produce nearest possible window. | ||
119 | |||
120 | width_u_out = ((5') - (5)) / scale_comb | ||
121 | 114 | ||
122 | if (width_u_out > max) | 115 | "...specification does not define an origin or units. However by convention |
123 | scale_comb = ((5') - (5)) / max; | 116 | drivers should horizontally count unscaled samples relative to 0H." |
124 | else if (width_u_out < min) | ||
125 | scale_comb = ((5') - (5)) / min; | ||
126 | 117 | ||
127 | 4. Issue G_CROP to retrieve actual input window. | 118 | We choose to follow the advise and interpret cropping units as client input |
119 | pixels. | ||
128 | 120 | ||
129 | 5. Using actual input window and calculated combined scales calculate sensor | 121 | Cropping is performed in the following 6 steps: |
130 | target output window. | ||
131 | |||
132 | width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb | ||
133 | |||
134 | 6. Apply iterative S_FMT for new sensor target output window. | ||
135 | |||
136 | 7. Issue G_FMT to retrieve the actual sensor output window. | ||
137 | |||
138 | 8. Calculate sensor scales. | ||
139 | |||
140 | scale_s = ((3') - (3)) / ((2') - (2)) | ||
141 | 122 | ||
142 | 9. Calculate sensor output subwindow to be cropped on CEU by applying sensor | 123 | 1. Request exactly user rectangle from the sensor. |
143 | scales to the requested window. | ||
144 | 124 | ||
145 | width_ceu = ((5') - (5)) / scale_s | 125 | 2. If smaller - iterate until a larger one is obtained. Result: sensor cropped |
126 | to 2 : 2', target crop 5 : 5', current output format 6' - 6. | ||
146 | 127 | ||
147 | 10. Use CEU cropping for above calculated window. | 128 | 3. In the previous step the sensor has tried to preserve its output frame as |
129 | good as possible, but it could have changed. Retrieve it again. | ||
148 | 130 | ||
149 | 11. Calculate CEU scales from sensor scales from results of (10) and user window | 131 | 4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate |
150 | from (3) | 132 | intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2) |
151 | 133 | ||
152 | scale_ceu = calc_scale(((5') - (5)), &width_u_out) | 134 | 5. Calculate and apply host scale = (6' - 6) / (4' - 4) |
153 | 135 | ||
154 | 12. Apply CEU scales. | 136 | 6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5) |
155 | 137 | ||
156 | -- | 138 | -- |
157 | Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 139 | Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 5155700c206b..e831aaca66f8 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt | |||
@@ -545,12 +545,11 @@ unregister them: | |||
545 | This will remove the device nodes from sysfs (causing udev to remove them | 545 | This will remove the device nodes from sysfs (causing udev to remove them |
546 | from /dev). | 546 | from /dev). |
547 | 547 | ||
548 | After video_unregister_device() returns no new opens can be done. | 548 | After video_unregister_device() returns no new opens can be done. However, |
549 | 549 | in the case of USB devices some application might still have one of these | |
550 | However, in the case of USB devices some application might still have one | 550 | device nodes open. So after the unregister all file operations will return |
551 | of these device nodes open. You should block all new accesses to read, | 551 | an error as well, except for the ioctl and unlocked_ioctl file operations: |
552 | write, poll, etc. except possibly for certain ioctl operations like | 552 | those will still be passed on since some buffer ioctls may still be needed. |
553 | queueing buffers. | ||
554 | 553 | ||
555 | When the last user of the video device node exits, then the vdev->release() | 554 | When the last user of the video device node exits, then the vdev->release() |
556 | callback is called and you can do the final cleanup there. | 555 | callback is called and you can do the final cleanup there. |
@@ -609,3 +608,135 @@ scatter/gather method (videobuf-dma-sg), DMA with linear access | |||
609 | 608 | ||
610 | Please see Documentation/video4linux/videobuf for more information on how | 609 | Please see Documentation/video4linux/videobuf for more information on how |
611 | to use the videobuf layer. | 610 | to use the videobuf layer. |
611 | |||
612 | struct v4l2_fh | ||
613 | -------------- | ||
614 | |||
615 | struct v4l2_fh provides a way to easily keep file handle specific data | ||
616 | that is used by the V4L2 framework. Using v4l2_fh is optional for | ||
617 | drivers. | ||
618 | |||
619 | The users of v4l2_fh (in the V4L2 framework, not the driver) know | ||
620 | whether a driver uses v4l2_fh as its file->private_data pointer by | ||
621 | testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. | ||
622 | |||
623 | Useful functions: | ||
624 | |||
625 | - v4l2_fh_init() | ||
626 | |||
627 | Initialise the file handle. This *MUST* be performed in the driver's | ||
628 | v4l2_file_operations->open() handler. | ||
629 | |||
630 | - v4l2_fh_add() | ||
631 | |||
632 | Add a v4l2_fh to video_device file handle list. May be called after | ||
633 | initialising the file handle. | ||
634 | |||
635 | - v4l2_fh_del() | ||
636 | |||
637 | Unassociate the file handle from video_device(). The file handle | ||
638 | exit function may now be called. | ||
639 | |||
640 | - v4l2_fh_exit() | ||
641 | |||
642 | Uninitialise the file handle. After uninitialisation the v4l2_fh | ||
643 | memory can be freed. | ||
644 | |||
645 | struct v4l2_fh is allocated as a part of the driver's own file handle | ||
646 | structure and is set to file->private_data in the driver's open | ||
647 | function by the driver. Drivers can extract their own file handle | ||
648 | structure by using the container_of macro. Example: | ||
649 | |||
650 | struct my_fh { | ||
651 | int blah; | ||
652 | struct v4l2_fh fh; | ||
653 | }; | ||
654 | |||
655 | ... | ||
656 | |||
657 | int my_open(struct file *file) | ||
658 | { | ||
659 | struct my_fh *my_fh; | ||
660 | struct video_device *vfd; | ||
661 | int ret; | ||
662 | |||
663 | ... | ||
664 | |||
665 | ret = v4l2_fh_init(&my_fh->fh, vfd); | ||
666 | if (ret) | ||
667 | return ret; | ||
668 | |||
669 | v4l2_fh_add(&my_fh->fh); | ||
670 | |||
671 | file->private_data = &my_fh->fh; | ||
672 | |||
673 | ... | ||
674 | } | ||
675 | |||
676 | int my_release(struct file *file) | ||
677 | { | ||
678 | struct v4l2_fh *fh = file->private_data; | ||
679 | struct my_fh *my_fh = container_of(fh, struct my_fh, fh); | ||
680 | |||
681 | ... | ||
682 | } | ||
683 | |||
684 | V4L2 events | ||
685 | ----------- | ||
686 | |||
687 | The V4L2 events provide a generic way to pass events to user space. | ||
688 | The driver must use v4l2_fh to be able to support V4L2 events. | ||
689 | |||
690 | Useful functions: | ||
691 | |||
692 | - v4l2_event_alloc() | ||
693 | |||
694 | To use events, the driver must allocate events for the file handle. By | ||
695 | calling the function more than once, the driver may assure that at least n | ||
696 | events in total have been allocated. The function may not be called in | ||
697 | atomic context. | ||
698 | |||
699 | - v4l2_event_queue() | ||
700 | |||
701 | Queue events to video device. The driver's only responsibility is to fill | ||
702 | in the type and the data fields. The other fields will be filled in by | ||
703 | V4L2. | ||
704 | |||
705 | - v4l2_event_subscribe() | ||
706 | |||
707 | The video_device->ioctl_ops->vidioc_subscribe_event must check the driver | ||
708 | is able to produce events with specified event id. Then it calls | ||
709 | v4l2_event_subscribe() to subscribe the event. | ||
710 | |||
711 | - v4l2_event_unsubscribe() | ||
712 | |||
713 | vidioc_unsubscribe_event in struct v4l2_ioctl_ops. A driver may use | ||
714 | v4l2_event_unsubscribe() directly unless it wants to be involved in | ||
715 | unsubscription process. | ||
716 | |||
717 | The special type V4L2_EVENT_ALL may be used to unsubscribe all events. The | ||
718 | drivers may want to handle this in a special way. | ||
719 | |||
720 | - v4l2_event_pending() | ||
721 | |||
722 | Returns the number of pending events. Useful when implementing poll. | ||
723 | |||
724 | Drivers do not initialise events directly. The events are initialised | ||
725 | through v4l2_fh_init() if video_device->ioctl_ops->vidioc_subscribe_event is | ||
726 | non-NULL. This *MUST* be performed in the driver's | ||
727 | v4l2_file_operations->open() handler. | ||
728 | |||
729 | Events are delivered to user space through the poll system call. The driver | ||
730 | can use v4l2_fh->events->wait wait_queue_head_t as the argument for | ||
731 | poll_wait(). | ||
732 | |||
733 | There are standard and private events. New standard events must use the | ||
734 | smallest available event type. The drivers must allocate their events from | ||
735 | their own class starting from class base. Class base is | ||
736 | V4L2_EVENT_PRIVATE_START + n * 1000 where n is the lowest available number. | ||
737 | The first event type in the class is reserved for future use, so the first | ||
738 | available event type is 'class base + 1'. | ||
739 | |||
740 | An example on how the V4L2 events may be used can be found in the OMAP | ||
741 | 3 ISP driver available at <URL:http://gitorious.org/omap3camera> as of | ||
742 | writing this. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 2f5510cc142d..f860e2ec1b71 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5963,7 +5963,7 @@ M: Laurent Pinchart <laurent.pinchart@skynet.be> | |||
5963 | L: linux-uvc-devel@lists.berlios.de (subscribers-only) | 5963 | L: linux-uvc-devel@lists.berlios.de (subscribers-only) |
5964 | L: linux-media@vger.kernel.org | 5964 | L: linux-media@vger.kernel.org |
5965 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git | 5965 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git |
5966 | W: http://linux-uvc.berlios.de | 5966 | W: http://www.ideasonboard.org/uvc/ |
5967 | S: Maintained | 5967 | S: Maintained |
5968 | F: drivers/media/video/uvc/ | 5968 | F: drivers/media/video/uvc/ |
5969 | 5969 | ||
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 4dde7d180a32..195c6cf359f6 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig | |||
@@ -7,3 +7,62 @@ config VIDEO_IR | |||
7 | tristate | 7 | tristate |
8 | depends on IR_CORE | 8 | depends on IR_CORE |
9 | default IR_CORE | 9 | default IR_CORE |
10 | |||
11 | source "drivers/media/IR/keymaps/Kconfig" | ||
12 | |||
13 | config IR_NEC_DECODER | ||
14 | tristate "Enable IR raw decoder for the NEC protocol" | ||
15 | depends on IR_CORE | ||
16 | default y | ||
17 | |||
18 | ---help--- | ||
19 | Enable this option if you have IR with NEC protocol, and | ||
20 | if the IR is decoded in software | ||
21 | |||
22 | config IR_RC5_DECODER | ||
23 | tristate "Enable IR raw decoder for the RC-5 protocol" | ||
24 | depends on IR_CORE | ||
25 | default y | ||
26 | |||
27 | ---help--- | ||
28 | Enable this option if you have IR with RC-5 protocol, and | ||
29 | if the IR is decoded in software | ||
30 | |||
31 | config IR_RC6_DECODER | ||
32 | tristate "Enable IR raw decoder for the RC6 protocol" | ||
33 | depends on IR_CORE | ||
34 | default y | ||
35 | |||
36 | ---help--- | ||
37 | Enable this option if you have an infrared remote control which | ||
38 | uses the RC6 protocol, and you need software decoding support. | ||
39 | |||
40 | config IR_JVC_DECODER | ||
41 | tristate "Enable IR raw decoder for the JVC protocol" | ||
42 | depends on IR_CORE | ||
43 | default y | ||
44 | |||
45 | ---help--- | ||
46 | Enable this option if you have an infrared remote control which | ||
47 | uses the JVC protocol, and you need software decoding support. | ||
48 | |||
49 | config IR_SONY_DECODER | ||
50 | tristate "Enable IR raw decoder for the Sony protocol" | ||
51 | depends on IR_CORE | ||
52 | default y | ||
53 | |||
54 | ---help--- | ||
55 | Enable this option if you have an infrared remote control which | ||
56 | uses the Sony protocol, and you need software decoding support. | ||
57 | |||
58 | config IR_IMON | ||
59 | tristate "SoundGraph iMON Receiver and Display" | ||
60 | depends on USB_ARCH_HAS_HCD | ||
61 | depends on IR_CORE | ||
62 | select USB | ||
63 | ---help--- | ||
64 | Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) | ||
65 | IR Receiver and/or LCD/VFD/VGA display. | ||
66 | |||
67 | To compile this driver as a module, choose M here: the | ||
68 | module will be called imon. | ||
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 171890e7a41d..b998fcced2e4 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile | |||
@@ -1,5 +1,15 @@ | |||
1 | ir-common-objs := ir-functions.o ir-keymaps.o | 1 | ir-common-objs := ir-functions.o |
2 | ir-core-objs := ir-keytable.o ir-sysfs.o | 2 | ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o |
3 | |||
4 | obj-y += keymaps/ | ||
3 | 5 | ||
4 | obj-$(CONFIG_IR_CORE) += ir-core.o | 6 | obj-$(CONFIG_IR_CORE) += ir-core.o |
5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o | 7 | obj-$(CONFIG_VIDEO_IR) += ir-common.o |
8 | obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o | ||
9 | obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o | ||
10 | obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o | ||
11 | obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o | ||
12 | obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o | ||
13 | |||
14 | # stand-alone IR receivers/transmitters | ||
15 | obj-$(CONFIG_IR_IMON) += imon.o | ||
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c new file mode 100644 index 000000000000..5e2045670004 --- /dev/null +++ b/drivers/media/IR/imon.c | |||
@@ -0,0 +1,2396 @@ | |||
1 | /* | ||
2 | * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD | ||
3 | * | ||
4 | * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com> | ||
5 | * Portions based on the original lirc_imon driver, | ||
6 | * Copyright(C) 2004 Venky Raju(dev@venky.ws) | ||
7 | * | ||
8 | * Huge thanks to R. Geoff Newbury for invaluable debugging on the | ||
9 | * 0xffdc iMON devices, and for sending me one to hack on, without | ||
10 | * which the support for them wouldn't be nearly as good. Thanks | ||
11 | * also to the numerous 0xffdc device owners that tested auto-config | ||
12 | * support for me and provided debug dumps from their devices. | ||
13 | * | ||
14 | * imon is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | |||
36 | #include <linux/input.h> | ||
37 | #include <linux/usb.h> | ||
38 | #include <linux/usb/input.h> | ||
39 | #include <media/ir-core.h> | ||
40 | |||
41 | #include <linux/time.h> | ||
42 | #include <linux/timer.h> | ||
43 | |||
44 | #define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" | ||
45 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" | ||
46 | #define MOD_NAME "imon" | ||
47 | #define MOD_VERSION "0.9.1" | ||
48 | |||
49 | #define DISPLAY_MINOR_BASE 144 | ||
50 | #define DEVICE_NAME "lcd%d" | ||
51 | |||
52 | #define BUF_CHUNK_SIZE 8 | ||
53 | #define BUF_SIZE 128 | ||
54 | |||
55 | #define BIT_DURATION 250 /* each bit received is 250us */ | ||
56 | |||
57 | #define IMON_CLOCK_ENABLE_PACKETS 2 | ||
58 | |||
59 | /*** P R O T O T Y P E S ***/ | ||
60 | |||
61 | /* USB Callback prototypes */ | ||
62 | static int imon_probe(struct usb_interface *interface, | ||
63 | const struct usb_device_id *id); | ||
64 | static void imon_disconnect(struct usb_interface *interface); | ||
65 | static void usb_rx_callback_intf0(struct urb *urb); | ||
66 | static void usb_rx_callback_intf1(struct urb *urb); | ||
67 | static void usb_tx_callback(struct urb *urb); | ||
68 | |||
69 | /* suspend/resume support */ | ||
70 | static int imon_resume(struct usb_interface *intf); | ||
71 | static int imon_suspend(struct usb_interface *intf, pm_message_t message); | ||
72 | |||
73 | /* Display file_operations function prototypes */ | ||
74 | static int display_open(struct inode *inode, struct file *file); | ||
75 | static int display_close(struct inode *inode, struct file *file); | ||
76 | |||
77 | /* VFD write operation */ | ||
78 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
79 | size_t n_bytes, loff_t *pos); | ||
80 | |||
81 | /* LCD file_operations override function prototypes */ | ||
82 | static ssize_t lcd_write(struct file *file, const char *buf, | ||
83 | size_t n_bytes, loff_t *pos); | ||
84 | |||
85 | /*** G L O B A L S ***/ | ||
86 | |||
87 | struct imon_context { | ||
88 | struct device *dev; | ||
89 | struct ir_dev_props *props; | ||
90 | struct ir_input_dev *ir; | ||
91 | /* Newer devices have two interfaces */ | ||
92 | struct usb_device *usbdev_intf0; | ||
93 | struct usb_device *usbdev_intf1; | ||
94 | |||
95 | bool display_supported; /* not all controllers do */ | ||
96 | bool display_isopen; /* display port has been opened */ | ||
97 | bool rf_isassociating; /* RF remote associating */ | ||
98 | bool dev_present_intf0; /* USB device presence, interface 0 */ | ||
99 | bool dev_present_intf1; /* USB device presence, interface 1 */ | ||
100 | |||
101 | struct mutex lock; /* to lock this object */ | ||
102 | wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ | ||
103 | |||
104 | struct usb_endpoint_descriptor *rx_endpoint_intf0; | ||
105 | struct usb_endpoint_descriptor *rx_endpoint_intf1; | ||
106 | struct usb_endpoint_descriptor *tx_endpoint; | ||
107 | struct urb *rx_urb_intf0; | ||
108 | struct urb *rx_urb_intf1; | ||
109 | struct urb *tx_urb; | ||
110 | bool tx_control; | ||
111 | unsigned char usb_rx_buf[8]; | ||
112 | unsigned char usb_tx_buf[8]; | ||
113 | |||
114 | struct tx_t { | ||
115 | unsigned char data_buf[35]; /* user data buffer */ | ||
116 | struct completion finished; /* wait for write to finish */ | ||
117 | bool busy; /* write in progress */ | ||
118 | int status; /* status of tx completion */ | ||
119 | } tx; | ||
120 | |||
121 | u16 vendor; /* usb vendor ID */ | ||
122 | u16 product; /* usb product ID */ | ||
123 | |||
124 | struct input_dev *idev; /* input device for remote */ | ||
125 | struct input_dev *touch; /* input device for touchscreen */ | ||
126 | |||
127 | u32 kc; /* current input keycode */ | ||
128 | u32 last_keycode; /* last reported input keycode */ | ||
129 | u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ | ||
130 | u8 mce_toggle_bit; /* last mce toggle bit */ | ||
131 | bool release_code; /* some keys send a release code */ | ||
132 | |||
133 | u8 display_type; /* store the display type */ | ||
134 | bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ | ||
135 | |||
136 | char name_idev[128]; /* input device name */ | ||
137 | char phys_idev[64]; /* input device phys path */ | ||
138 | struct timer_list itimer; /* input device timer, need for rc6 */ | ||
139 | |||
140 | char name_touch[128]; /* touch screen name */ | ||
141 | char phys_touch[64]; /* touch screen phys path */ | ||
142 | struct timer_list ttimer; /* touch screen timer */ | ||
143 | int touch_x; /* x coordinate on touchscreen */ | ||
144 | int touch_y; /* y coordinate on touchscreen */ | ||
145 | }; | ||
146 | |||
147 | #define TOUCH_TIMEOUT (HZ/30) | ||
148 | |||
149 | /* vfd character device file operations */ | ||
150 | static const struct file_operations vfd_fops = { | ||
151 | .owner = THIS_MODULE, | ||
152 | .open = &display_open, | ||
153 | .write = &vfd_write, | ||
154 | .release = &display_close | ||
155 | }; | ||
156 | |||
157 | /* lcd character device file operations */ | ||
158 | static const struct file_operations lcd_fops = { | ||
159 | .owner = THIS_MODULE, | ||
160 | .open = &display_open, | ||
161 | .write = &lcd_write, | ||
162 | .release = &display_close | ||
163 | }; | ||
164 | |||
165 | enum { | ||
166 | IMON_DISPLAY_TYPE_AUTO = 0, | ||
167 | IMON_DISPLAY_TYPE_VFD = 1, | ||
168 | IMON_DISPLAY_TYPE_LCD = 2, | ||
169 | IMON_DISPLAY_TYPE_VGA = 3, | ||
170 | IMON_DISPLAY_TYPE_NONE = 4, | ||
171 | }; | ||
172 | |||
173 | enum { | ||
174 | IMON_KEY_IMON = 0, | ||
175 | IMON_KEY_MCE = 1, | ||
176 | IMON_KEY_PANEL = 2, | ||
177 | }; | ||
178 | |||
179 | /* | ||
180 | * USB Device ID for iMON USB Control Boards | ||
181 | * | ||
182 | * The Windows drivers contain 6 different inf files, more or less one for | ||
183 | * each new device until the 0x0034-0x0046 devices, which all use the same | ||
184 | * driver. Some of the devices in the 34-46 range haven't been definitively | ||
185 | * identified yet. Early devices have either a TriGem Computer, Inc. or a | ||
186 | * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later | ||
187 | * devices use the SoundGraph vendor ID (0x15c2). This driver only supports | ||
188 | * the ffdc and later devices, which do onboard decoding. | ||
189 | */ | ||
190 | static struct usb_device_id imon_usb_id_table[] = { | ||
191 | /* | ||
192 | * Several devices with this same device ID, all use iMON_PAD.inf | ||
193 | * SoundGraph iMON PAD (IR & VFD) | ||
194 | * SoundGraph iMON PAD (IR & LCD) | ||
195 | * SoundGraph iMON Knob (IR only) | ||
196 | */ | ||
197 | { USB_DEVICE(0x15c2, 0xffdc) }, | ||
198 | |||
199 | /* | ||
200 | * Newer devices, all driven by the latest iMON Windows driver, full | ||
201 | * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2' | ||
202 | * Need user input to fill in details on unknown devices. | ||
203 | */ | ||
204 | /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */ | ||
205 | { USB_DEVICE(0x15c2, 0x0034) }, | ||
206 | /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */ | ||
207 | { USB_DEVICE(0x15c2, 0x0035) }, | ||
208 | /* SoundGraph iMON OEM VFD (IR & VFD) */ | ||
209 | { USB_DEVICE(0x15c2, 0x0036) }, | ||
210 | /* device specifics unknown */ | ||
211 | { USB_DEVICE(0x15c2, 0x0037) }, | ||
212 | /* SoundGraph iMON OEM LCD (IR & LCD) */ | ||
213 | { USB_DEVICE(0x15c2, 0x0038) }, | ||
214 | /* SoundGraph iMON UltraBay (IR & LCD) */ | ||
215 | { USB_DEVICE(0x15c2, 0x0039) }, | ||
216 | /* device specifics unknown */ | ||
217 | { USB_DEVICE(0x15c2, 0x003a) }, | ||
218 | /* device specifics unknown */ | ||
219 | { USB_DEVICE(0x15c2, 0x003b) }, | ||
220 | /* SoundGraph iMON OEM Inside (IR only) */ | ||
221 | { USB_DEVICE(0x15c2, 0x003c) }, | ||
222 | /* device specifics unknown */ | ||
223 | { USB_DEVICE(0x15c2, 0x003d) }, | ||
224 | /* device specifics unknown */ | ||
225 | { USB_DEVICE(0x15c2, 0x003e) }, | ||
226 | /* device specifics unknown */ | ||
227 | { USB_DEVICE(0x15c2, 0x003f) }, | ||
228 | /* device specifics unknown */ | ||
229 | { USB_DEVICE(0x15c2, 0x0040) }, | ||
230 | /* SoundGraph iMON MINI (IR only) */ | ||
231 | { USB_DEVICE(0x15c2, 0x0041) }, | ||
232 | /* Antec Veris Multimedia Station EZ External (IR only) */ | ||
233 | { USB_DEVICE(0x15c2, 0x0042) }, | ||
234 | /* Antec Veris Multimedia Station Basic Internal (IR only) */ | ||
235 | { USB_DEVICE(0x15c2, 0x0043) }, | ||
236 | /* Antec Veris Multimedia Station Elite (IR & VFD) */ | ||
237 | { USB_DEVICE(0x15c2, 0x0044) }, | ||
238 | /* Antec Veris Multimedia Station Premiere (IR & LCD) */ | ||
239 | { USB_DEVICE(0x15c2, 0x0045) }, | ||
240 | /* device specifics unknown */ | ||
241 | { USB_DEVICE(0x15c2, 0x0046) }, | ||
242 | {} | ||
243 | }; | ||
244 | |||
245 | /* USB Device data */ | ||
246 | static struct usb_driver imon_driver = { | ||
247 | .name = MOD_NAME, | ||
248 | .probe = imon_probe, | ||
249 | .disconnect = imon_disconnect, | ||
250 | .suspend = imon_suspend, | ||
251 | .resume = imon_resume, | ||
252 | .id_table = imon_usb_id_table, | ||
253 | }; | ||
254 | |||
255 | static struct usb_class_driver imon_vfd_class = { | ||
256 | .name = DEVICE_NAME, | ||
257 | .fops = &vfd_fops, | ||
258 | .minor_base = DISPLAY_MINOR_BASE, | ||
259 | }; | ||
260 | |||
261 | static struct usb_class_driver imon_lcd_class = { | ||
262 | .name = DEVICE_NAME, | ||
263 | .fops = &lcd_fops, | ||
264 | .minor_base = DISPLAY_MINOR_BASE, | ||
265 | }; | ||
266 | |||
267 | /* imon receiver front panel/knob key table */ | ||
268 | static const struct { | ||
269 | u64 hw_code; | ||
270 | u32 keycode; | ||
271 | } imon_panel_key_table[] = { | ||
272 | { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ | ||
273 | { 0x000000001f00ffeell, KEY_AUDIO }, | ||
274 | { 0x000000002000ffeell, KEY_VIDEO }, | ||
275 | { 0x000000002100ffeell, KEY_CAMERA }, | ||
276 | { 0x000000002700ffeell, KEY_DVD }, | ||
277 | { 0x000000002300ffeell, KEY_TV }, | ||
278 | { 0x000000000500ffeell, KEY_PREVIOUS }, | ||
279 | { 0x000000000700ffeell, KEY_REWIND }, | ||
280 | { 0x000000000400ffeell, KEY_STOP }, | ||
281 | { 0x000000003c00ffeell, KEY_PLAYPAUSE }, | ||
282 | { 0x000000000800ffeell, KEY_FASTFORWARD }, | ||
283 | { 0x000000000600ffeell, KEY_NEXT }, | ||
284 | { 0x000000010000ffeell, KEY_RIGHT }, | ||
285 | { 0x000001000000ffeell, KEY_LEFT }, | ||
286 | { 0x000000003d00ffeell, KEY_SELECT }, | ||
287 | { 0x000100000000ffeell, KEY_VOLUMEUP }, | ||
288 | { 0x010000000000ffeell, KEY_VOLUMEDOWN }, | ||
289 | { 0x000000000100ffeell, KEY_MUTE }, | ||
290 | /* iMON Knob values */ | ||
291 | { 0x000100ffffffffeell, KEY_VOLUMEUP }, | ||
292 | { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, | ||
293 | { 0x000008ffffffffeell, KEY_MUTE }, | ||
294 | }; | ||
295 | |||
296 | /* to prevent races between open() and disconnect(), probing, etc */ | ||
297 | static DEFINE_MUTEX(driver_lock); | ||
298 | |||
299 | /* Module bookkeeping bits */ | ||
300 | MODULE_AUTHOR(MOD_AUTHOR); | ||
301 | MODULE_DESCRIPTION(MOD_DESC); | ||
302 | MODULE_VERSION(MOD_VERSION); | ||
303 | MODULE_LICENSE("GPL"); | ||
304 | MODULE_DEVICE_TABLE(usb, imon_usb_id_table); | ||
305 | |||
306 | static bool debug; | ||
307 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
308 | MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); | ||
309 | |||
310 | /* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ | ||
311 | static int display_type; | ||
312 | module_param(display_type, int, S_IRUGO); | ||
313 | MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " | ||
314 | "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); | ||
315 | |||
316 | static int pad_stabilize = 1; | ||
317 | module_param(pad_stabilize, int, S_IRUGO | S_IWUSR); | ||
318 | MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD " | ||
319 | "presses in arrow key mode. 0=disable, 1=enable (default)."); | ||
320 | |||
321 | /* | ||
322 | * In certain use cases, mouse mode isn't really helpful, and could actually | ||
323 | * cause confusion, so allow disabling it when the IR device is open. | ||
324 | */ | ||
325 | static bool nomouse; | ||
326 | module_param(nomouse, bool, S_IRUGO | S_IWUSR); | ||
327 | MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is " | ||
328 | "open. 0=don't disable, 1=disable. (default: don't disable)"); | ||
329 | |||
330 | /* threshold at which a pad push registers as an arrow key in kbd mode */ | ||
331 | static int pad_thresh; | ||
332 | module_param(pad_thresh, int, S_IRUGO | S_IWUSR); | ||
333 | MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an " | ||
334 | "arrow key in kbd mode (default: 28)"); | ||
335 | |||
336 | |||
337 | static void free_imon_context(struct imon_context *ictx) | ||
338 | { | ||
339 | struct device *dev = ictx->dev; | ||
340 | |||
341 | usb_free_urb(ictx->tx_urb); | ||
342 | usb_free_urb(ictx->rx_urb_intf0); | ||
343 | usb_free_urb(ictx->rx_urb_intf1); | ||
344 | kfree(ictx); | ||
345 | |||
346 | dev_dbg(dev, "%s: iMON context freed\n", __func__); | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * Called when the Display device (e.g. /dev/lcd0) | ||
351 | * is opened by the application. | ||
352 | */ | ||
353 | static int display_open(struct inode *inode, struct file *file) | ||
354 | { | ||
355 | struct usb_interface *interface; | ||
356 | struct imon_context *ictx = NULL; | ||
357 | int subminor; | ||
358 | int retval = 0; | ||
359 | |||
360 | /* prevent races with disconnect */ | ||
361 | mutex_lock(&driver_lock); | ||
362 | |||
363 | subminor = iminor(inode); | ||
364 | interface = usb_find_interface(&imon_driver, subminor); | ||
365 | if (!interface) { | ||
366 | err("%s: could not find interface for minor %d", | ||
367 | __func__, subminor); | ||
368 | retval = -ENODEV; | ||
369 | goto exit; | ||
370 | } | ||
371 | ictx = usb_get_intfdata(interface); | ||
372 | |||
373 | if (!ictx) { | ||
374 | err("%s: no context found for minor %d", __func__, subminor); | ||
375 | retval = -ENODEV; | ||
376 | goto exit; | ||
377 | } | ||
378 | |||
379 | mutex_lock(&ictx->lock); | ||
380 | |||
381 | if (!ictx->display_supported) { | ||
382 | err("%s: display not supported by device", __func__); | ||
383 | retval = -ENODEV; | ||
384 | } else if (ictx->display_isopen) { | ||
385 | err("%s: display port is already open", __func__); | ||
386 | retval = -EBUSY; | ||
387 | } else { | ||
388 | ictx->display_isopen = 1; | ||
389 | file->private_data = ictx; | ||
390 | dev_dbg(ictx->dev, "display port opened\n"); | ||
391 | } | ||
392 | |||
393 | mutex_unlock(&ictx->lock); | ||
394 | |||
395 | exit: | ||
396 | mutex_unlock(&driver_lock); | ||
397 | return retval; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * Called when the display device (e.g. /dev/lcd0) | ||
402 | * is closed by the application. | ||
403 | */ | ||
404 | static int display_close(struct inode *inode, struct file *file) | ||
405 | { | ||
406 | struct imon_context *ictx = NULL; | ||
407 | int retval = 0; | ||
408 | |||
409 | ictx = (struct imon_context *)file->private_data; | ||
410 | |||
411 | if (!ictx) { | ||
412 | err("%s: no context for device", __func__); | ||
413 | return -ENODEV; | ||
414 | } | ||
415 | |||
416 | mutex_lock(&ictx->lock); | ||
417 | |||
418 | if (!ictx->display_supported) { | ||
419 | err("%s: display not supported by device", __func__); | ||
420 | retval = -ENODEV; | ||
421 | } else if (!ictx->display_isopen) { | ||
422 | err("%s: display is not open", __func__); | ||
423 | retval = -EIO; | ||
424 | } else { | ||
425 | ictx->display_isopen = 0; | ||
426 | dev_dbg(ictx->dev, "display port closed\n"); | ||
427 | if (!ictx->dev_present_intf0) { | ||
428 | /* | ||
429 | * Device disconnected before close and IR port is not | ||
430 | * open. If IR port is open, context will be deleted by | ||
431 | * ir_close. | ||
432 | */ | ||
433 | mutex_unlock(&ictx->lock); | ||
434 | free_imon_context(ictx); | ||
435 | return retval; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | mutex_unlock(&ictx->lock); | ||
440 | return retval; | ||
441 | } | ||
442 | |||
443 | /** | ||
444 | * Sends a packet to the device -- this function must be called | ||
445 | * with ictx->lock held. | ||
446 | */ | ||
447 | static int send_packet(struct imon_context *ictx) | ||
448 | { | ||
449 | unsigned int pipe; | ||
450 | unsigned long timeout; | ||
451 | int interval = 0; | ||
452 | int retval = 0; | ||
453 | struct usb_ctrlrequest *control_req = NULL; | ||
454 | |||
455 | /* Check if we need to use control or interrupt urb */ | ||
456 | if (!ictx->tx_control) { | ||
457 | pipe = usb_sndintpipe(ictx->usbdev_intf0, | ||
458 | ictx->tx_endpoint->bEndpointAddress); | ||
459 | interval = ictx->tx_endpoint->bInterval; | ||
460 | |||
461 | usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe, | ||
462 | ictx->usb_tx_buf, | ||
463 | sizeof(ictx->usb_tx_buf), | ||
464 | usb_tx_callback, ictx, interval); | ||
465 | |||
466 | ictx->tx_urb->actual_length = 0; | ||
467 | } else { | ||
468 | /* fill request into kmalloc'ed space: */ | ||
469 | control_req = kmalloc(sizeof(struct usb_ctrlrequest), | ||
470 | GFP_KERNEL); | ||
471 | if (control_req == NULL) | ||
472 | return -ENOMEM; | ||
473 | |||
474 | /* setup packet is '21 09 0200 0001 0008' */ | ||
475 | control_req->bRequestType = 0x21; | ||
476 | control_req->bRequest = 0x09; | ||
477 | control_req->wValue = cpu_to_le16(0x0200); | ||
478 | control_req->wIndex = cpu_to_le16(0x0001); | ||
479 | control_req->wLength = cpu_to_le16(0x0008); | ||
480 | |||
481 | /* control pipe is endpoint 0x00 */ | ||
482 | pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0); | ||
483 | |||
484 | /* build the control urb */ | ||
485 | usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0, | ||
486 | pipe, (unsigned char *)control_req, | ||
487 | ictx->usb_tx_buf, | ||
488 | sizeof(ictx->usb_tx_buf), | ||
489 | usb_tx_callback, ictx); | ||
490 | ictx->tx_urb->actual_length = 0; | ||
491 | } | ||
492 | |||
493 | init_completion(&ictx->tx.finished); | ||
494 | ictx->tx.busy = 1; | ||
495 | smp_rmb(); /* ensure later readers know we're busy */ | ||
496 | |||
497 | retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); | ||
498 | if (retval) { | ||
499 | ictx->tx.busy = 0; | ||
500 | smp_rmb(); /* ensure later readers know we're not busy */ | ||
501 | err("%s: error submitting urb(%d)", __func__, retval); | ||
502 | } else { | ||
503 | /* Wait for transmission to complete (or abort) */ | ||
504 | mutex_unlock(&ictx->lock); | ||
505 | retval = wait_for_completion_interruptible( | ||
506 | &ictx->tx.finished); | ||
507 | if (retval) | ||
508 | err("%s: task interrupted", __func__); | ||
509 | mutex_lock(&ictx->lock); | ||
510 | |||
511 | retval = ictx->tx.status; | ||
512 | if (retval) | ||
513 | err("%s: packet tx failed (%d)", __func__, retval); | ||
514 | } | ||
515 | |||
516 | kfree(control_req); | ||
517 | |||
518 | /* | ||
519 | * Induce a mandatory 5ms delay before returning, as otherwise, | ||
520 | * send_packet can get called so rapidly as to overwhelm the device, | ||
521 | * particularly on faster systems and/or those with quirky usb. | ||
522 | */ | ||
523 | timeout = msecs_to_jiffies(5); | ||
524 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
525 | schedule_timeout(timeout); | ||
526 | |||
527 | return retval; | ||
528 | } | ||
529 | |||
530 | /** | ||
531 | * Sends an associate packet to the iMON 2.4G. | ||
532 | * | ||
533 | * This might not be such a good idea, since it has an id collision with | ||
534 | * some versions of the "IR & VFD" combo. The only way to determine if it | ||
535 | * is an RF version is to look at the product description string. (Which | ||
536 | * we currently do not fetch). | ||
537 | */ | ||
538 | static int send_associate_24g(struct imon_context *ictx) | ||
539 | { | ||
540 | int retval; | ||
541 | const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, | ||
542 | 0x00, 0x00, 0x00, 0x20 }; | ||
543 | |||
544 | if (!ictx) { | ||
545 | err("%s: no context for device", __func__); | ||
546 | return -ENODEV; | ||
547 | } | ||
548 | |||
549 | if (!ictx->dev_present_intf0) { | ||
550 | err("%s: no iMON device present", __func__); | ||
551 | return -ENODEV; | ||
552 | } | ||
553 | |||
554 | memcpy(ictx->usb_tx_buf, packet, sizeof(packet)); | ||
555 | retval = send_packet(ictx); | ||
556 | |||
557 | return retval; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * Sends packets to setup and show clock on iMON display | ||
562 | * | ||
563 | * Arguments: year - last 2 digits of year, month - 1..12, | ||
564 | * day - 1..31, dow - day of the week (0-Sun...6-Sat), | ||
565 | * hour - 0..23, minute - 0..59, second - 0..59 | ||
566 | */ | ||
567 | static int send_set_imon_clock(struct imon_context *ictx, | ||
568 | unsigned int year, unsigned int month, | ||
569 | unsigned int day, unsigned int dow, | ||
570 | unsigned int hour, unsigned int minute, | ||
571 | unsigned int second) | ||
572 | { | ||
573 | unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8]; | ||
574 | int retval = 0; | ||
575 | int i; | ||
576 | |||
577 | if (!ictx) { | ||
578 | err("%s: no context for device", __func__); | ||
579 | return -ENODEV; | ||
580 | } | ||
581 | |||
582 | switch (ictx->display_type) { | ||
583 | case IMON_DISPLAY_TYPE_LCD: | ||
584 | clock_enable_pkt[0][0] = 0x80; | ||
585 | clock_enable_pkt[0][1] = year; | ||
586 | clock_enable_pkt[0][2] = month-1; | ||
587 | clock_enable_pkt[0][3] = day; | ||
588 | clock_enable_pkt[0][4] = hour; | ||
589 | clock_enable_pkt[0][5] = minute; | ||
590 | clock_enable_pkt[0][6] = second; | ||
591 | |||
592 | clock_enable_pkt[1][0] = 0x80; | ||
593 | clock_enable_pkt[1][1] = 0; | ||
594 | clock_enable_pkt[1][2] = 0; | ||
595 | clock_enable_pkt[1][3] = 0; | ||
596 | clock_enable_pkt[1][4] = 0; | ||
597 | clock_enable_pkt[1][5] = 0; | ||
598 | clock_enable_pkt[1][6] = 0; | ||
599 | |||
600 | if (ictx->product == 0xffdc) { | ||
601 | clock_enable_pkt[0][7] = 0x50; | ||
602 | clock_enable_pkt[1][7] = 0x51; | ||
603 | } else { | ||
604 | clock_enable_pkt[0][7] = 0x88; | ||
605 | clock_enable_pkt[1][7] = 0x8a; | ||
606 | } | ||
607 | |||
608 | break; | ||
609 | |||
610 | case IMON_DISPLAY_TYPE_VFD: | ||
611 | clock_enable_pkt[0][0] = year; | ||
612 | clock_enable_pkt[0][1] = month-1; | ||
613 | clock_enable_pkt[0][2] = day; | ||
614 | clock_enable_pkt[0][3] = dow; | ||
615 | clock_enable_pkt[0][4] = hour; | ||
616 | clock_enable_pkt[0][5] = minute; | ||
617 | clock_enable_pkt[0][6] = second; | ||
618 | clock_enable_pkt[0][7] = 0x40; | ||
619 | |||
620 | clock_enable_pkt[1][0] = 0; | ||
621 | clock_enable_pkt[1][1] = 0; | ||
622 | clock_enable_pkt[1][2] = 1; | ||
623 | clock_enable_pkt[1][3] = 0; | ||
624 | clock_enable_pkt[1][4] = 0; | ||
625 | clock_enable_pkt[1][5] = 0; | ||
626 | clock_enable_pkt[1][6] = 0; | ||
627 | clock_enable_pkt[1][7] = 0x42; | ||
628 | |||
629 | break; | ||
630 | |||
631 | default: | ||
632 | return -ENODEV; | ||
633 | } | ||
634 | |||
635 | for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) { | ||
636 | memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8); | ||
637 | retval = send_packet(ictx); | ||
638 | if (retval) { | ||
639 | err("%s: send_packet failed for packet %d", | ||
640 | __func__, i); | ||
641 | break; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | return retval; | ||
646 | } | ||
647 | |||
648 | /** | ||
649 | * These are the sysfs functions to handle the association on the iMON 2.4G LT. | ||
650 | */ | ||
651 | static ssize_t show_associate_remote(struct device *d, | ||
652 | struct device_attribute *attr, | ||
653 | char *buf) | ||
654 | { | ||
655 | struct imon_context *ictx = dev_get_drvdata(d); | ||
656 | |||
657 | if (!ictx) | ||
658 | return -ENODEV; | ||
659 | |||
660 | mutex_lock(&ictx->lock); | ||
661 | if (ictx->rf_isassociating) | ||
662 | strcpy(buf, "associating\n"); | ||
663 | else | ||
664 | strcpy(buf, "closed\n"); | ||
665 | |||
666 | dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for " | ||
667 | "instructions on how to associate your iMON 2.4G DT/LT " | ||
668 | "remote\n"); | ||
669 | mutex_unlock(&ictx->lock); | ||
670 | return strlen(buf); | ||
671 | } | ||
672 | |||
673 | static ssize_t store_associate_remote(struct device *d, | ||
674 | struct device_attribute *attr, | ||
675 | const char *buf, size_t count) | ||
676 | { | ||
677 | struct imon_context *ictx; | ||
678 | |||
679 | ictx = dev_get_drvdata(d); | ||
680 | |||
681 | if (!ictx) | ||
682 | return -ENODEV; | ||
683 | |||
684 | mutex_lock(&ictx->lock); | ||
685 | ictx->rf_isassociating = 1; | ||
686 | send_associate_24g(ictx); | ||
687 | mutex_unlock(&ictx->lock); | ||
688 | |||
689 | return count; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * sysfs functions to control internal imon clock | ||
694 | */ | ||
695 | static ssize_t show_imon_clock(struct device *d, | ||
696 | struct device_attribute *attr, char *buf) | ||
697 | { | ||
698 | struct imon_context *ictx = dev_get_drvdata(d); | ||
699 | size_t len; | ||
700 | |||
701 | if (!ictx) | ||
702 | return -ENODEV; | ||
703 | |||
704 | mutex_lock(&ictx->lock); | ||
705 | |||
706 | if (!ictx->display_supported) { | ||
707 | len = snprintf(buf, PAGE_SIZE, "Not supported."); | ||
708 | } else { | ||
709 | len = snprintf(buf, PAGE_SIZE, | ||
710 | "To set the clock on your iMON display:\n" | ||
711 | "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n" | ||
712 | "%s", ictx->display_isopen ? | ||
713 | "\nNOTE: imon device must be closed\n" : ""); | ||
714 | } | ||
715 | |||
716 | mutex_unlock(&ictx->lock); | ||
717 | |||
718 | return len; | ||
719 | } | ||
720 | |||
721 | static ssize_t store_imon_clock(struct device *d, | ||
722 | struct device_attribute *attr, | ||
723 | const char *buf, size_t count) | ||
724 | { | ||
725 | struct imon_context *ictx = dev_get_drvdata(d); | ||
726 | ssize_t retval; | ||
727 | unsigned int year, month, day, dow, hour, minute, second; | ||
728 | |||
729 | if (!ictx) | ||
730 | return -ENODEV; | ||
731 | |||
732 | mutex_lock(&ictx->lock); | ||
733 | |||
734 | if (!ictx->display_supported) { | ||
735 | retval = -ENODEV; | ||
736 | goto exit; | ||
737 | } else if (ictx->display_isopen) { | ||
738 | retval = -EBUSY; | ||
739 | goto exit; | ||
740 | } | ||
741 | |||
742 | if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow, | ||
743 | &hour, &minute, &second) != 7) { | ||
744 | retval = -EINVAL; | ||
745 | goto exit; | ||
746 | } | ||
747 | |||
748 | if ((month < 1 || month > 12) || | ||
749 | (day < 1 || day > 31) || (dow > 6) || | ||
750 | (hour > 23) || (minute > 59) || (second > 59)) { | ||
751 | retval = -EINVAL; | ||
752 | goto exit; | ||
753 | } | ||
754 | |||
755 | retval = send_set_imon_clock(ictx, year, month, day, dow, | ||
756 | hour, minute, second); | ||
757 | if (retval) | ||
758 | goto exit; | ||
759 | |||
760 | retval = count; | ||
761 | exit: | ||
762 | mutex_unlock(&ictx->lock); | ||
763 | |||
764 | return retval; | ||
765 | } | ||
766 | |||
767 | |||
768 | static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock, | ||
769 | store_imon_clock); | ||
770 | |||
771 | static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, | ||
772 | store_associate_remote); | ||
773 | |||
774 | static struct attribute *imon_display_sysfs_entries[] = { | ||
775 | &dev_attr_imon_clock.attr, | ||
776 | NULL | ||
777 | }; | ||
778 | |||
779 | static struct attribute_group imon_display_attribute_group = { | ||
780 | .attrs = imon_display_sysfs_entries | ||
781 | }; | ||
782 | |||
783 | static struct attribute *imon_rf_sysfs_entries[] = { | ||
784 | &dev_attr_associate_remote.attr, | ||
785 | NULL | ||
786 | }; | ||
787 | |||
788 | static struct attribute_group imon_rf_attribute_group = { | ||
789 | .attrs = imon_rf_sysfs_entries | ||
790 | }; | ||
791 | |||
792 | /** | ||
793 | * Writes data to the VFD. The iMON VFD is 2x16 characters | ||
794 | * and requires data in 5 consecutive USB interrupt packets, | ||
795 | * each packet but the last carrying 7 bytes. | ||
796 | * | ||
797 | * I don't know if the VFD board supports features such as | ||
798 | * scrolling, clearing rows, blanking, etc. so at | ||
799 | * the caller must provide a full screen of data. If fewer | ||
800 | * than 32 bytes are provided spaces will be appended to | ||
801 | * generate a full screen. | ||
802 | */ | ||
803 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
804 | size_t n_bytes, loff_t *pos) | ||
805 | { | ||
806 | int i; | ||
807 | int offset; | ||
808 | int seq; | ||
809 | int retval = 0; | ||
810 | struct imon_context *ictx; | ||
811 | const unsigned char vfd_packet6[] = { | ||
812 | 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; | ||
813 | |||
814 | ictx = (struct imon_context *)file->private_data; | ||
815 | if (!ictx) { | ||
816 | err("%s: no context for device", __func__); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | |||
820 | mutex_lock(&ictx->lock); | ||
821 | |||
822 | if (!ictx->dev_present_intf0) { | ||
823 | err("%s: no iMON device present", __func__); | ||
824 | retval = -ENODEV; | ||
825 | goto exit; | ||
826 | } | ||
827 | |||
828 | if (n_bytes <= 0 || n_bytes > 32) { | ||
829 | err("%s: invalid payload size", __func__); | ||
830 | retval = -EINVAL; | ||
831 | goto exit; | ||
832 | } | ||
833 | |||
834 | if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) { | ||
835 | retval = -EFAULT; | ||
836 | goto exit; | ||
837 | } | ||
838 | |||
839 | /* Pad with spaces */ | ||
840 | for (i = n_bytes; i < 32; ++i) | ||
841 | ictx->tx.data_buf[i] = ' '; | ||
842 | |||
843 | for (i = 32; i < 35; ++i) | ||
844 | ictx->tx.data_buf[i] = 0xFF; | ||
845 | |||
846 | offset = 0; | ||
847 | seq = 0; | ||
848 | |||
849 | do { | ||
850 | memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7); | ||
851 | ictx->usb_tx_buf[7] = (unsigned char) seq; | ||
852 | |||
853 | retval = send_packet(ictx); | ||
854 | if (retval) { | ||
855 | err("%s: send packet failed for packet #%d", | ||
856 | __func__, seq/2); | ||
857 | goto exit; | ||
858 | } else { | ||
859 | seq += 2; | ||
860 | offset += 7; | ||
861 | } | ||
862 | |||
863 | } while (offset < 35); | ||
864 | |||
865 | /* Send packet #6 */ | ||
866 | memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); | ||
867 | ictx->usb_tx_buf[7] = (unsigned char) seq; | ||
868 | retval = send_packet(ictx); | ||
869 | if (retval) | ||
870 | err("%s: send packet failed for packet #%d", | ||
871 | __func__, seq / 2); | ||
872 | |||
873 | exit: | ||
874 | mutex_unlock(&ictx->lock); | ||
875 | |||
876 | return (!retval) ? n_bytes : retval; | ||
877 | } | ||
878 | |||
879 | /** | ||
880 | * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte | ||
881 | * packets. We accept data as 16 hexadecimal digits, followed by a | ||
882 | * newline (to make it easy to drive the device from a command-line | ||
883 | * -- even though the actual binary data is a bit complicated). | ||
884 | * | ||
885 | * The device itself is not a "traditional" text-mode display. It's | ||
886 | * actually a 16x96 pixel bitmap display. That means if you want to | ||
887 | * display text, you've got to have your own "font" and translate the | ||
888 | * text into bitmaps for display. This is really flexible (you can | ||
889 | * display whatever diacritics you need, and so on), but it's also | ||
890 | * a lot more complicated than most LCDs... | ||
891 | */ | ||
892 | static ssize_t lcd_write(struct file *file, const char *buf, | ||
893 | size_t n_bytes, loff_t *pos) | ||
894 | { | ||
895 | int retval = 0; | ||
896 | struct imon_context *ictx; | ||
897 | |||
898 | ictx = (struct imon_context *)file->private_data; | ||
899 | if (!ictx) { | ||
900 | err("%s: no context for device", __func__); | ||
901 | return -ENODEV; | ||
902 | } | ||
903 | |||
904 | mutex_lock(&ictx->lock); | ||
905 | |||
906 | if (!ictx->display_supported) { | ||
907 | err("%s: no iMON display present", __func__); | ||
908 | retval = -ENODEV; | ||
909 | goto exit; | ||
910 | } | ||
911 | |||
912 | if (n_bytes != 8) { | ||
913 | err("%s: invalid payload size: %d (expecting 8)", | ||
914 | __func__, (int) n_bytes); | ||
915 | retval = -EINVAL; | ||
916 | goto exit; | ||
917 | } | ||
918 | |||
919 | if (copy_from_user(ictx->usb_tx_buf, buf, 8)) { | ||
920 | retval = -EFAULT; | ||
921 | goto exit; | ||
922 | } | ||
923 | |||
924 | retval = send_packet(ictx); | ||
925 | if (retval) { | ||
926 | err("%s: send packet failed!", __func__); | ||
927 | goto exit; | ||
928 | } else { | ||
929 | dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n", | ||
930 | __func__, (int) n_bytes); | ||
931 | } | ||
932 | exit: | ||
933 | mutex_unlock(&ictx->lock); | ||
934 | return (!retval) ? n_bytes : retval; | ||
935 | } | ||
936 | |||
937 | /** | ||
938 | * Callback function for USB core API: transmit data | ||
939 | */ | ||
940 | static void usb_tx_callback(struct urb *urb) | ||
941 | { | ||
942 | struct imon_context *ictx; | ||
943 | |||
944 | if (!urb) | ||
945 | return; | ||
946 | ictx = (struct imon_context *)urb->context; | ||
947 | if (!ictx) | ||
948 | return; | ||
949 | |||
950 | ictx->tx.status = urb->status; | ||
951 | |||
952 | /* notify waiters that write has finished */ | ||
953 | ictx->tx.busy = 0; | ||
954 | smp_rmb(); /* ensure later readers know we're not busy */ | ||
955 | complete(&ictx->tx.finished); | ||
956 | } | ||
957 | |||
958 | /** | ||
959 | * mce/rc6 keypresses have no distinct release code, use timer | ||
960 | */ | ||
961 | static void imon_mce_timeout(unsigned long data) | ||
962 | { | ||
963 | struct imon_context *ictx = (struct imon_context *)data; | ||
964 | |||
965 | input_report_key(ictx->idev, ictx->last_keycode, 0); | ||
966 | input_sync(ictx->idev); | ||
967 | } | ||
968 | |||
969 | /** | ||
970 | * report touchscreen input | ||
971 | */ | ||
972 | static void imon_touch_display_timeout(unsigned long data) | ||
973 | { | ||
974 | struct imon_context *ictx = (struct imon_context *)data; | ||
975 | |||
976 | if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) | ||
977 | return; | ||
978 | |||
979 | input_report_abs(ictx->touch, ABS_X, ictx->touch_x); | ||
980 | input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); | ||
981 | input_report_key(ictx->touch, BTN_TOUCH, 0x00); | ||
982 | input_sync(ictx->touch); | ||
983 | } | ||
984 | |||
985 | /** | ||
986 | * iMON IR receivers support two different signal sets -- those used by | ||
987 | * the iMON remotes, and those used by the Windows MCE remotes (which is | ||
988 | * really just RC-6), but only one or the other at a time, as the signals | ||
989 | * are decoded onboard the receiver. | ||
990 | */ | ||
991 | int imon_ir_change_protocol(void *priv, u64 ir_type) | ||
992 | { | ||
993 | int retval; | ||
994 | struct imon_context *ictx = priv; | ||
995 | struct device *dev = ictx->dev; | ||
996 | bool pad_mouse; | ||
997 | unsigned char ir_proto_packet[] = { | ||
998 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; | ||
999 | |||
1000 | if (ir_type && !(ir_type & ictx->props->allowed_protos)) | ||
1001 | dev_warn(dev, "Looks like you're trying to use an IR protocol " | ||
1002 | "this device does not support\n"); | ||
1003 | |||
1004 | switch (ir_type) { | ||
1005 | case IR_TYPE_RC6: | ||
1006 | dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); | ||
1007 | ir_proto_packet[0] = 0x01; | ||
1008 | pad_mouse = false; | ||
1009 | init_timer(&ictx->itimer); | ||
1010 | ictx->itimer.data = (unsigned long)ictx; | ||
1011 | ictx->itimer.function = imon_mce_timeout; | ||
1012 | break; | ||
1013 | case IR_TYPE_UNKNOWN: | ||
1014 | case IR_TYPE_OTHER: | ||
1015 | dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); | ||
1016 | if (pad_stabilize) | ||
1017 | pad_mouse = true; | ||
1018 | else { | ||
1019 | dev_dbg(dev, "PAD stabilize functionality disabled\n"); | ||
1020 | pad_mouse = false; | ||
1021 | } | ||
1022 | /* ir_proto_packet[0] = 0x00; // already the default */ | ||
1023 | ir_type = IR_TYPE_OTHER; | ||
1024 | break; | ||
1025 | default: | ||
1026 | dev_warn(dev, "Unsupported IR protocol specified, overriding " | ||
1027 | "to iMON IR protocol\n"); | ||
1028 | if (pad_stabilize) | ||
1029 | pad_mouse = true; | ||
1030 | else { | ||
1031 | dev_dbg(dev, "PAD stabilize functionality disabled\n"); | ||
1032 | pad_mouse = false; | ||
1033 | } | ||
1034 | /* ir_proto_packet[0] = 0x00; // already the default */ | ||
1035 | ir_type = IR_TYPE_OTHER; | ||
1036 | break; | ||
1037 | } | ||
1038 | |||
1039 | memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); | ||
1040 | |||
1041 | retval = send_packet(ictx); | ||
1042 | if (retval) | ||
1043 | goto out; | ||
1044 | |||
1045 | ictx->ir_type = ir_type; | ||
1046 | ictx->pad_mouse = pad_mouse; | ||
1047 | |||
1048 | out: | ||
1049 | return retval; | ||
1050 | } | ||
1051 | |||
1052 | static inline int tv2int(const struct timeval *a, const struct timeval *b) | ||
1053 | { | ||
1054 | int usecs = 0; | ||
1055 | int sec = 0; | ||
1056 | |||
1057 | if (b->tv_usec > a->tv_usec) { | ||
1058 | usecs = 1000000; | ||
1059 | sec--; | ||
1060 | } | ||
1061 | |||
1062 | usecs += a->tv_usec - b->tv_usec; | ||
1063 | |||
1064 | sec += a->tv_sec - b->tv_sec; | ||
1065 | sec *= 1000; | ||
1066 | usecs /= 1000; | ||
1067 | sec += usecs; | ||
1068 | |||
1069 | if (sec < 0) | ||
1070 | sec = 1000; | ||
1071 | |||
1072 | return sec; | ||
1073 | } | ||
1074 | |||
1075 | /** | ||
1076 | * The directional pad behaves a bit differently, depending on whether this is | ||
1077 | * one of the older ffdc devices or a newer device. Newer devices appear to | ||
1078 | * have a higher resolution matrix for more precise mouse movement, but it | ||
1079 | * makes things overly sensitive in keyboard mode, so we do some interesting | ||
1080 | * contortions to make it less touchy. Older devices run through the same | ||
1081 | * routine with shorter timeout and a smaller threshold. | ||
1082 | */ | ||
1083 | static int stabilize(int a, int b, u16 timeout, u16 threshold) | ||
1084 | { | ||
1085 | struct timeval ct; | ||
1086 | static struct timeval prev_time = {0, 0}; | ||
1087 | static struct timeval hit_time = {0, 0}; | ||
1088 | static int x, y, prev_result, hits; | ||
1089 | int result = 0; | ||
1090 | int msec, msec_hit; | ||
1091 | |||
1092 | do_gettimeofday(&ct); | ||
1093 | msec = tv2int(&ct, &prev_time); | ||
1094 | msec_hit = tv2int(&ct, &hit_time); | ||
1095 | |||
1096 | if (msec > 100) { | ||
1097 | x = 0; | ||
1098 | y = 0; | ||
1099 | hits = 0; | ||
1100 | } | ||
1101 | |||
1102 | x += a; | ||
1103 | y += b; | ||
1104 | |||
1105 | prev_time = ct; | ||
1106 | |||
1107 | if (abs(x) > threshold || abs(y) > threshold) { | ||
1108 | if (abs(y) > abs(x)) | ||
1109 | result = (y > 0) ? 0x7F : 0x80; | ||
1110 | else | ||
1111 | result = (x > 0) ? 0x7F00 : 0x8000; | ||
1112 | |||
1113 | x = 0; | ||
1114 | y = 0; | ||
1115 | |||
1116 | if (result == prev_result) { | ||
1117 | hits++; | ||
1118 | |||
1119 | if (hits > 3) { | ||
1120 | switch (result) { | ||
1121 | case 0x7F: | ||
1122 | y = 17 * threshold / 30; | ||
1123 | break; | ||
1124 | case 0x80: | ||
1125 | y -= 17 * threshold / 30; | ||
1126 | break; | ||
1127 | case 0x7F00: | ||
1128 | x = 17 * threshold / 30; | ||
1129 | break; | ||
1130 | case 0x8000: | ||
1131 | x -= 17 * threshold / 30; | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1136 | if (hits == 2 && msec_hit < timeout) { | ||
1137 | result = 0; | ||
1138 | hits = 1; | ||
1139 | } | ||
1140 | } else { | ||
1141 | prev_result = result; | ||
1142 | hits = 1; | ||
1143 | hit_time = ct; | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | return result; | ||
1148 | } | ||
1149 | |||
1150 | static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code) | ||
1151 | { | ||
1152 | u32 scancode = be32_to_cpu(hw_code); | ||
1153 | u32 keycode; | ||
1154 | u32 release; | ||
1155 | bool is_release_code = false; | ||
1156 | |||
1157 | /* Look for the initial press of a button */ | ||
1158 | keycode = ir_g_keycode_from_table(ictx->idev, scancode); | ||
1159 | |||
1160 | /* Look for the release of a button */ | ||
1161 | if (keycode == KEY_RESERVED) { | ||
1162 | release = scancode & ~0x4000; | ||
1163 | keycode = ir_g_keycode_from_table(ictx->idev, release); | ||
1164 | if (keycode != KEY_RESERVED) | ||
1165 | is_release_code = true; | ||
1166 | } | ||
1167 | |||
1168 | ictx->release_code = is_release_code; | ||
1169 | |||
1170 | return keycode; | ||
1171 | } | ||
1172 | |||
1173 | static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code) | ||
1174 | { | ||
1175 | u32 scancode = be32_to_cpu(hw_code); | ||
1176 | u32 keycode; | ||
1177 | |||
1178 | #define MCE_KEY_MASK 0x7000 | ||
1179 | #define MCE_TOGGLE_BIT 0x8000 | ||
1180 | |||
1181 | /* | ||
1182 | * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx | ||
1183 | * (the toggle bit flipping between alternating key presses), while | ||
1184 | * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep | ||
1185 | * the table trim, we always or in the bits to look up 0x8000ff4xx, | ||
1186 | * but we can't or them into all codes, as some keys are decoded in | ||
1187 | * a different way w/o the same use of the toggle bit... | ||
1188 | */ | ||
1189 | if ((scancode >> 24) & 0x80) | ||
1190 | scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; | ||
1191 | |||
1192 | keycode = ir_g_keycode_from_table(ictx->idev, scancode); | ||
1193 | |||
1194 | return keycode; | ||
1195 | } | ||
1196 | |||
1197 | static u32 imon_panel_key_lookup(u64 hw_code) | ||
1198 | { | ||
1199 | int i; | ||
1200 | u64 code = be64_to_cpu(hw_code); | ||
1201 | u32 keycode = KEY_RESERVED; | ||
1202 | |||
1203 | for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { | ||
1204 | if (imon_panel_key_table[i].hw_code == (code | 0xffee)) { | ||
1205 | keycode = imon_panel_key_table[i].keycode; | ||
1206 | break; | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1210 | return keycode; | ||
1211 | } | ||
1212 | |||
1213 | static bool imon_mouse_event(struct imon_context *ictx, | ||
1214 | unsigned char *buf, int len) | ||
1215 | { | ||
1216 | char rel_x = 0x00, rel_y = 0x00; | ||
1217 | u8 right_shift = 1; | ||
1218 | bool mouse_input = 1; | ||
1219 | int dir = 0; | ||
1220 | |||
1221 | /* newer iMON device PAD or mouse button */ | ||
1222 | if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { | ||
1223 | rel_x = buf[2]; | ||
1224 | rel_y = buf[3]; | ||
1225 | right_shift = 1; | ||
1226 | /* 0xffdc iMON PAD or mouse button input */ | ||
1227 | } else if (ictx->product == 0xffdc && (buf[0] & 0x40) && | ||
1228 | !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) { | ||
1229 | rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | | ||
1230 | (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; | ||
1231 | if (buf[0] & 0x02) | ||
1232 | rel_x |= ~0x0f; | ||
1233 | rel_x = rel_x + rel_x / 2; | ||
1234 | rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | | ||
1235 | (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; | ||
1236 | if (buf[0] & 0x01) | ||
1237 | rel_y |= ~0x0f; | ||
1238 | rel_y = rel_y + rel_y / 2; | ||
1239 | right_shift = 2; | ||
1240 | /* some ffdc devices decode mouse buttons differently... */ | ||
1241 | } else if (ictx->product == 0xffdc && (buf[0] == 0x68)) { | ||
1242 | right_shift = 2; | ||
1243 | /* ch+/- buttons, which we use for an emulated scroll wheel */ | ||
1244 | } else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) { | ||
1245 | dir = 1; | ||
1246 | } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { | ||
1247 | dir = -1; | ||
1248 | } else | ||
1249 | mouse_input = 0; | ||
1250 | |||
1251 | if (mouse_input) { | ||
1252 | dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); | ||
1253 | |||
1254 | if (dir) { | ||
1255 | input_report_rel(ictx->idev, REL_WHEEL, dir); | ||
1256 | } else if (rel_x || rel_y) { | ||
1257 | input_report_rel(ictx->idev, REL_X, rel_x); | ||
1258 | input_report_rel(ictx->idev, REL_Y, rel_y); | ||
1259 | } else { | ||
1260 | input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1); | ||
1261 | input_report_key(ictx->idev, BTN_RIGHT, | ||
1262 | buf[1] >> right_shift & 0x1); | ||
1263 | } | ||
1264 | input_sync(ictx->idev); | ||
1265 | ictx->last_keycode = ictx->kc; | ||
1266 | } | ||
1267 | |||
1268 | return mouse_input; | ||
1269 | } | ||
1270 | |||
1271 | static void imon_touch_event(struct imon_context *ictx, unsigned char *buf) | ||
1272 | { | ||
1273 | mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT); | ||
1274 | ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4); | ||
1275 | ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf)); | ||
1276 | input_report_abs(ictx->touch, ABS_X, ictx->touch_x); | ||
1277 | input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); | ||
1278 | input_report_key(ictx->touch, BTN_TOUCH, 0x01); | ||
1279 | input_sync(ictx->touch); | ||
1280 | } | ||
1281 | |||
1282 | static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) | ||
1283 | { | ||
1284 | int dir = 0; | ||
1285 | char rel_x = 0x00, rel_y = 0x00; | ||
1286 | u16 timeout, threshold; | ||
1287 | u64 temp_key; | ||
1288 | u32 remote_key; | ||
1289 | |||
1290 | /* | ||
1291 | * The imon directional pad functions more like a touchpad. Bytes 3 & 4 | ||
1292 | * contain a position coordinate (x,y), with each component ranging | ||
1293 | * from -14 to 14. We want to down-sample this to only 4 discrete values | ||
1294 | * for up/down/left/right arrow keys. Also, when you get too close to | ||
1295 | * diagonals, it has a tendancy to jump back and forth, so lets try to | ||
1296 | * ignore when they get too close. | ||
1297 | */ | ||
1298 | if (ictx->product != 0xffdc) { | ||
1299 | /* first, pad to 8 bytes so it conforms with everything else */ | ||
1300 | buf[5] = buf[6] = buf[7] = 0; | ||
1301 | timeout = 500; /* in msecs */ | ||
1302 | /* (2*threshold) x (2*threshold) square */ | ||
1303 | threshold = pad_thresh ? pad_thresh : 28; | ||
1304 | rel_x = buf[2]; | ||
1305 | rel_y = buf[3]; | ||
1306 | |||
1307 | if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { | ||
1308 | if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { | ||
1309 | dir = stabilize((int)rel_x, (int)rel_y, | ||
1310 | timeout, threshold); | ||
1311 | if (!dir) { | ||
1312 | ictx->kc = KEY_UNKNOWN; | ||
1313 | return; | ||
1314 | } | ||
1315 | buf[2] = dir & 0xFF; | ||
1316 | buf[3] = (dir >> 8) & 0xFF; | ||
1317 | memcpy(&temp_key, buf, sizeof(temp_key)); | ||
1318 | remote_key = (u32) (le64_to_cpu(temp_key) | ||
1319 | & 0xffffffff); | ||
1320 | ictx->kc = imon_remote_key_lookup(ictx, | ||
1321 | remote_key); | ||
1322 | } | ||
1323 | } else { | ||
1324 | if (abs(rel_y) > abs(rel_x)) { | ||
1325 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; | ||
1326 | buf[3] = 0; | ||
1327 | ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; | ||
1328 | } else { | ||
1329 | buf[2] = 0; | ||
1330 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; | ||
1331 | ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; | ||
1332 | } | ||
1333 | } | ||
1334 | |||
1335 | /* | ||
1336 | * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad | ||
1337 | * device (15c2:ffdc). The remote generates various codes from | ||
1338 | * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates | ||
1339 | * 0x688301b7 and the right one 0x688481b7. All other keys generate | ||
1340 | * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with | ||
1341 | * reversed endianess. Extract direction from buffer, rotate endianess, | ||
1342 | * adjust sign and feed the values into stabilize(). The resulting codes | ||
1343 | * will be 0x01008000, 0x01007F00, which match the newer devices. | ||
1344 | */ | ||
1345 | } else { | ||
1346 | timeout = 10; /* in msecs */ | ||
1347 | /* (2*threshold) x (2*threshold) square */ | ||
1348 | threshold = pad_thresh ? pad_thresh : 15; | ||
1349 | |||
1350 | /* buf[1] is x */ | ||
1351 | rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | | ||
1352 | (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; | ||
1353 | if (buf[0] & 0x02) | ||
1354 | rel_x |= ~0x10+1; | ||
1355 | /* buf[2] is y */ | ||
1356 | rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | | ||
1357 | (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; | ||
1358 | if (buf[0] & 0x01) | ||
1359 | rel_y |= ~0x10+1; | ||
1360 | |||
1361 | buf[0] = 0x01; | ||
1362 | buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; | ||
1363 | |||
1364 | if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { | ||
1365 | dir = stabilize((int)rel_x, (int)rel_y, | ||
1366 | timeout, threshold); | ||
1367 | if (!dir) { | ||
1368 | ictx->kc = KEY_UNKNOWN; | ||
1369 | return; | ||
1370 | } | ||
1371 | buf[2] = dir & 0xFF; | ||
1372 | buf[3] = (dir >> 8) & 0xFF; | ||
1373 | memcpy(&temp_key, buf, sizeof(temp_key)); | ||
1374 | remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); | ||
1375 | ictx->kc = imon_remote_key_lookup(ictx, remote_key); | ||
1376 | } else { | ||
1377 | if (abs(rel_y) > abs(rel_x)) { | ||
1378 | buf[2] = (rel_y > 0) ? 0x7F : 0x80; | ||
1379 | buf[3] = 0; | ||
1380 | ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; | ||
1381 | } else { | ||
1382 | buf[2] = 0; | ||
1383 | buf[3] = (rel_x > 0) ? 0x7F : 0x80; | ||
1384 | ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; | ||
1385 | } | ||
1386 | } | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | static int imon_parse_press_type(struct imon_context *ictx, | ||
1391 | unsigned char *buf, u8 ktype) | ||
1392 | { | ||
1393 | int press_type = 0; | ||
1394 | int rep_delay = ictx->idev->rep[REP_DELAY]; | ||
1395 | int rep_period = ictx->idev->rep[REP_PERIOD]; | ||
1396 | |||
1397 | /* key release of 0x02XXXXXX key */ | ||
1398 | if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) | ||
1399 | ictx->kc = ictx->last_keycode; | ||
1400 | |||
1401 | /* mouse button release on (some) 0xffdc devices */ | ||
1402 | else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 && | ||
1403 | buf[2] == 0x81 && buf[3] == 0xb7) | ||
1404 | ictx->kc = ictx->last_keycode; | ||
1405 | |||
1406 | /* mouse button release on (some other) 0xffdc devices */ | ||
1407 | else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 && | ||
1408 | buf[2] == 0x81 && buf[3] == 0xb7) | ||
1409 | ictx->kc = ictx->last_keycode; | ||
1410 | |||
1411 | /* mce-specific button handling */ | ||
1412 | else if (ktype == IMON_KEY_MCE) { | ||
1413 | /* initial press */ | ||
1414 | if (ictx->kc != ictx->last_keycode | ||
1415 | || buf[2] != ictx->mce_toggle_bit) { | ||
1416 | ictx->last_keycode = ictx->kc; | ||
1417 | ictx->mce_toggle_bit = buf[2]; | ||
1418 | press_type = 1; | ||
1419 | mod_timer(&ictx->itimer, | ||
1420 | jiffies + msecs_to_jiffies(rep_delay)); | ||
1421 | /* repeat */ | ||
1422 | } else { | ||
1423 | press_type = 2; | ||
1424 | mod_timer(&ictx->itimer, | ||
1425 | jiffies + msecs_to_jiffies(rep_period)); | ||
1426 | } | ||
1427 | |||
1428 | /* incoherent or irrelevant data */ | ||
1429 | } else if (ictx->kc == KEY_RESERVED) | ||
1430 | press_type = -EINVAL; | ||
1431 | |||
1432 | /* key release of 0xXXXXXXb7 key */ | ||
1433 | else if (ictx->release_code) | ||
1434 | press_type = 0; | ||
1435 | |||
1436 | /* this is a button press */ | ||
1437 | else | ||
1438 | press_type = 1; | ||
1439 | |||
1440 | return press_type; | ||
1441 | } | ||
1442 | |||
1443 | /** | ||
1444 | * Process the incoming packet | ||
1445 | */ | ||
1446 | static void imon_incoming_packet(struct imon_context *ictx, | ||
1447 | struct urb *urb, int intf) | ||
1448 | { | ||
1449 | int len = urb->actual_length; | ||
1450 | unsigned char *buf = urb->transfer_buffer; | ||
1451 | struct device *dev = ictx->dev; | ||
1452 | u32 kc; | ||
1453 | bool norelease = 0; | ||
1454 | int i; | ||
1455 | u64 temp_key; | ||
1456 | u64 panel_key = 0; | ||
1457 | u32 remote_key = 0; | ||
1458 | struct input_dev *idev = NULL; | ||
1459 | int press_type = 0; | ||
1460 | int msec; | ||
1461 | struct timeval t; | ||
1462 | static struct timeval prev_time = { 0, 0 }; | ||
1463 | u8 ktype = IMON_KEY_IMON; | ||
1464 | |||
1465 | idev = ictx->idev; | ||
1466 | |||
1467 | /* filter out junk data on the older 0xffdc imon devices */ | ||
1468 | if ((buf[0] == 0xff) && (buf[7] == 0xff)) | ||
1469 | return; | ||
1470 | |||
1471 | /* Figure out what key was pressed */ | ||
1472 | memcpy(&temp_key, buf, sizeof(temp_key)); | ||
1473 | if (len == 8 && buf[7] == 0xee) { | ||
1474 | ktype = IMON_KEY_PANEL; | ||
1475 | panel_key = le64_to_cpu(temp_key); | ||
1476 | kc = imon_panel_key_lookup(panel_key); | ||
1477 | } else { | ||
1478 | remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); | ||
1479 | if (ictx->ir_type == IR_TYPE_RC6) { | ||
1480 | if (buf[0] == 0x80) | ||
1481 | ktype = IMON_KEY_MCE; | ||
1482 | kc = imon_mce_key_lookup(ictx, remote_key); | ||
1483 | } else | ||
1484 | kc = imon_remote_key_lookup(ictx, remote_key); | ||
1485 | } | ||
1486 | |||
1487 | /* keyboard/mouse mode toggle button */ | ||
1488 | if (kc == KEY_KEYBOARD && !ictx->release_code) { | ||
1489 | ictx->last_keycode = kc; | ||
1490 | if (!nomouse) { | ||
1491 | ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; | ||
1492 | dev_dbg(dev, "toggling to %s mode\n", | ||
1493 | ictx->pad_mouse ? "mouse" : "keyboard"); | ||
1494 | return; | ||
1495 | } else { | ||
1496 | ictx->pad_mouse = 0; | ||
1497 | dev_dbg(dev, "mouse mode disabled, passing key value\n"); | ||
1498 | } | ||
1499 | } | ||
1500 | |||
1501 | ictx->kc = kc; | ||
1502 | |||
1503 | /* send touchscreen events through input subsystem if touchpad data */ | ||
1504 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && | ||
1505 | buf[7] == 0x86) { | ||
1506 | imon_touch_event(ictx, buf); | ||
1507 | |||
1508 | /* look for mouse events with pad in mouse mode */ | ||
1509 | } else if (ictx->pad_mouse) { | ||
1510 | if (imon_mouse_event(ictx, buf, len)) | ||
1511 | return; | ||
1512 | } | ||
1513 | |||
1514 | /* Now for some special handling to convert pad input to arrow keys */ | ||
1515 | if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) || | ||
1516 | ((len == 8) && (buf[0] & 0x40) && | ||
1517 | !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { | ||
1518 | len = 8; | ||
1519 | imon_pad_to_keys(ictx, buf); | ||
1520 | norelease = 1; | ||
1521 | } | ||
1522 | |||
1523 | if (debug) { | ||
1524 | printk(KERN_INFO "intf%d decoded packet: ", intf); | ||
1525 | for (i = 0; i < len; ++i) | ||
1526 | printk("%02x ", buf[i]); | ||
1527 | printk("\n"); | ||
1528 | } | ||
1529 | |||
1530 | press_type = imon_parse_press_type(ictx, buf, ktype); | ||
1531 | if (press_type < 0) | ||
1532 | goto not_input_data; | ||
1533 | |||
1534 | if (ictx->kc == KEY_UNKNOWN) | ||
1535 | goto unknown_key; | ||
1536 | |||
1537 | /* KEY_MUTE repeats from MCE and knob need to be suppressed */ | ||
1538 | if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) | ||
1539 | && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) { | ||
1540 | do_gettimeofday(&t); | ||
1541 | msec = tv2int(&t, &prev_time); | ||
1542 | prev_time = t; | ||
1543 | if (msec < idev->rep[REP_DELAY]) | ||
1544 | return; | ||
1545 | } | ||
1546 | |||
1547 | input_report_key(idev, ictx->kc, press_type); | ||
1548 | input_sync(idev); | ||
1549 | |||
1550 | /* panel keys and some remote keys don't generate a release */ | ||
1551 | if (panel_key || norelease) { | ||
1552 | input_report_key(idev, ictx->kc, 0); | ||
1553 | input_sync(idev); | ||
1554 | } | ||
1555 | |||
1556 | ictx->last_keycode = ictx->kc; | ||
1557 | |||
1558 | return; | ||
1559 | |||
1560 | unknown_key: | ||
1561 | dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, | ||
1562 | (panel_key ? be64_to_cpu(panel_key) : | ||
1563 | be32_to_cpu(remote_key))); | ||
1564 | return; | ||
1565 | |||
1566 | not_input_data: | ||
1567 | if (len != 8) { | ||
1568 | dev_warn(dev, "imon %s: invalid incoming packet " | ||
1569 | "size (len = %d, intf%d)\n", __func__, len, intf); | ||
1570 | return; | ||
1571 | } | ||
1572 | |||
1573 | /* iMON 2.4G associate frame */ | ||
1574 | if (buf[0] == 0x00 && | ||
1575 | buf[2] == 0xFF && /* REFID */ | ||
1576 | buf[3] == 0xFF && | ||
1577 | buf[4] == 0xFF && | ||
1578 | buf[5] == 0xFF && /* iMON 2.4G */ | ||
1579 | ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ | ||
1580 | (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ | ||
1581 | dev_warn(dev, "%s: remote associated refid=%02X\n", | ||
1582 | __func__, buf[1]); | ||
1583 | ictx->rf_isassociating = 0; | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | /** | ||
1588 | * Callback function for USB core API: receive data | ||
1589 | */ | ||
1590 | static void usb_rx_callback_intf0(struct urb *urb) | ||
1591 | { | ||
1592 | struct imon_context *ictx; | ||
1593 | int intfnum = 0; | ||
1594 | |||
1595 | if (!urb) | ||
1596 | return; | ||
1597 | |||
1598 | ictx = (struct imon_context *)urb->context; | ||
1599 | if (!ictx) | ||
1600 | return; | ||
1601 | |||
1602 | switch (urb->status) { | ||
1603 | case -ENOENT: /* usbcore unlink successful! */ | ||
1604 | return; | ||
1605 | |||
1606 | case -ESHUTDOWN: /* transport endpoint was shut down */ | ||
1607 | break; | ||
1608 | |||
1609 | case 0: | ||
1610 | imon_incoming_packet(ictx, urb, intfnum); | ||
1611 | break; | ||
1612 | |||
1613 | default: | ||
1614 | dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", | ||
1615 | __func__, urb->status); | ||
1616 | break; | ||
1617 | } | ||
1618 | |||
1619 | usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); | ||
1620 | } | ||
1621 | |||
1622 | static void usb_rx_callback_intf1(struct urb *urb) | ||
1623 | { | ||
1624 | struct imon_context *ictx; | ||
1625 | int intfnum = 1; | ||
1626 | |||
1627 | if (!urb) | ||
1628 | return; | ||
1629 | |||
1630 | ictx = (struct imon_context *)urb->context; | ||
1631 | if (!ictx) | ||
1632 | return; | ||
1633 | |||
1634 | switch (urb->status) { | ||
1635 | case -ENOENT: /* usbcore unlink successful! */ | ||
1636 | return; | ||
1637 | |||
1638 | case -ESHUTDOWN: /* transport endpoint was shut down */ | ||
1639 | break; | ||
1640 | |||
1641 | case 0: | ||
1642 | imon_incoming_packet(ictx, urb, intfnum); | ||
1643 | break; | ||
1644 | |||
1645 | default: | ||
1646 | dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", | ||
1647 | __func__, urb->status); | ||
1648 | break; | ||
1649 | } | ||
1650 | |||
1651 | usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); | ||
1652 | } | ||
1653 | |||
1654 | static struct input_dev *imon_init_idev(struct imon_context *ictx) | ||
1655 | { | ||
1656 | struct input_dev *idev; | ||
1657 | struct ir_dev_props *props; | ||
1658 | struct ir_input_dev *ir; | ||
1659 | int ret, i; | ||
1660 | |||
1661 | idev = input_allocate_device(); | ||
1662 | if (!idev) { | ||
1663 | dev_err(ictx->dev, "remote input dev allocation failed\n"); | ||
1664 | goto idev_alloc_failed; | ||
1665 | } | ||
1666 | |||
1667 | props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
1668 | if (!props) { | ||
1669 | dev_err(ictx->dev, "remote ir dev props allocation failed\n"); | ||
1670 | goto props_alloc_failed; | ||
1671 | } | ||
1672 | |||
1673 | ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); | ||
1674 | if (!ir) { | ||
1675 | dev_err(ictx->dev, "remote ir input dev allocation failed\n"); | ||
1676 | goto ir_dev_alloc_failed; | ||
1677 | } | ||
1678 | |||
1679 | snprintf(ictx->name_idev, sizeof(ictx->name_idev), | ||
1680 | "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); | ||
1681 | idev->name = ictx->name_idev; | ||
1682 | |||
1683 | usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, | ||
1684 | sizeof(ictx->phys_idev)); | ||
1685 | strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev)); | ||
1686 | idev->phys = ictx->phys_idev; | ||
1687 | |||
1688 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); | ||
1689 | |||
1690 | idev->keybit[BIT_WORD(BTN_MOUSE)] = | ||
1691 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); | ||
1692 | idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | | ||
1693 | BIT_MASK(REL_WHEEL); | ||
1694 | |||
1695 | /* panel and/or knob code support */ | ||
1696 | for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { | ||
1697 | u32 kc = imon_panel_key_table[i].keycode; | ||
1698 | __set_bit(kc, idev->keybit); | ||
1699 | } | ||
1700 | |||
1701 | props->priv = ictx; | ||
1702 | props->driver_type = RC_DRIVER_SCANCODE; | ||
1703 | /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */ | ||
1704 | props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; | ||
1705 | props->change_protocol = imon_ir_change_protocol; | ||
1706 | ictx->props = props; | ||
1707 | |||
1708 | ictx->ir = ir; | ||
1709 | memcpy(&ir->dev, ictx->dev, sizeof(struct device)); | ||
1710 | |||
1711 | usb_to_input_id(ictx->usbdev_intf0, &idev->id); | ||
1712 | idev->dev.parent = ictx->dev; | ||
1713 | |||
1714 | input_set_drvdata(idev, ir); | ||
1715 | |||
1716 | ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); | ||
1717 | if (ret < 0) { | ||
1718 | dev_err(ictx->dev, "remote input dev register failed\n"); | ||
1719 | goto idev_register_failed; | ||
1720 | } | ||
1721 | |||
1722 | return idev; | ||
1723 | |||
1724 | idev_register_failed: | ||
1725 | kfree(ir); | ||
1726 | ir_dev_alloc_failed: | ||
1727 | kfree(props); | ||
1728 | props_alloc_failed: | ||
1729 | input_free_device(idev); | ||
1730 | idev_alloc_failed: | ||
1731 | |||
1732 | return NULL; | ||
1733 | } | ||
1734 | |||
1735 | static struct input_dev *imon_init_touch(struct imon_context *ictx) | ||
1736 | { | ||
1737 | struct input_dev *touch; | ||
1738 | int ret; | ||
1739 | |||
1740 | touch = input_allocate_device(); | ||
1741 | if (!touch) { | ||
1742 | dev_err(ictx->dev, "touchscreen input dev allocation failed\n"); | ||
1743 | goto touch_alloc_failed; | ||
1744 | } | ||
1745 | |||
1746 | snprintf(ictx->name_touch, sizeof(ictx->name_touch), | ||
1747 | "iMON USB Touchscreen (%04x:%04x)", | ||
1748 | ictx->vendor, ictx->product); | ||
1749 | touch->name = ictx->name_touch; | ||
1750 | |||
1751 | usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, | ||
1752 | sizeof(ictx->phys_touch)); | ||
1753 | strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch)); | ||
1754 | touch->phys = ictx->phys_touch; | ||
1755 | |||
1756 | touch->evbit[0] = | ||
1757 | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
1758 | touch->keybit[BIT_WORD(BTN_TOUCH)] = | ||
1759 | BIT_MASK(BTN_TOUCH); | ||
1760 | input_set_abs_params(touch, ABS_X, | ||
1761 | 0x00, 0xfff, 0, 0); | ||
1762 | input_set_abs_params(touch, ABS_Y, | ||
1763 | 0x00, 0xfff, 0, 0); | ||
1764 | |||
1765 | input_set_drvdata(touch, ictx); | ||
1766 | |||
1767 | usb_to_input_id(ictx->usbdev_intf1, &touch->id); | ||
1768 | touch->dev.parent = ictx->dev; | ||
1769 | ret = input_register_device(touch); | ||
1770 | if (ret < 0) { | ||
1771 | dev_info(ictx->dev, "touchscreen input dev register failed\n"); | ||
1772 | goto touch_register_failed; | ||
1773 | } | ||
1774 | |||
1775 | return touch; | ||
1776 | |||
1777 | touch_register_failed: | ||
1778 | input_free_device(ictx->touch); | ||
1779 | |||
1780 | touch_alloc_failed: | ||
1781 | return NULL; | ||
1782 | } | ||
1783 | |||
1784 | static bool imon_find_endpoints(struct imon_context *ictx, | ||
1785 | struct usb_host_interface *iface_desc) | ||
1786 | { | ||
1787 | struct usb_endpoint_descriptor *ep; | ||
1788 | struct usb_endpoint_descriptor *rx_endpoint = NULL; | ||
1789 | struct usb_endpoint_descriptor *tx_endpoint = NULL; | ||
1790 | int ifnum = iface_desc->desc.bInterfaceNumber; | ||
1791 | int num_endpts = iface_desc->desc.bNumEndpoints; | ||
1792 | int i, ep_dir, ep_type; | ||
1793 | bool ir_ep_found = 0; | ||
1794 | bool display_ep_found = 0; | ||
1795 | bool tx_control = 0; | ||
1796 | |||
1797 | /* | ||
1798 | * Scan the endpoint list and set: | ||
1799 | * first input endpoint = IR endpoint | ||
1800 | * first output endpoint = display endpoint | ||
1801 | */ | ||
1802 | for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { | ||
1803 | ep = &iface_desc->endpoint[i].desc; | ||
1804 | ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; | ||
1805 | ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
1806 | |||
1807 | if (!ir_ep_found && ep_dir == USB_DIR_IN && | ||
1808 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
1809 | |||
1810 | rx_endpoint = ep; | ||
1811 | ir_ep_found = 1; | ||
1812 | dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); | ||
1813 | |||
1814 | } else if (!display_ep_found && ep_dir == USB_DIR_OUT && | ||
1815 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
1816 | tx_endpoint = ep; | ||
1817 | display_ep_found = 1; | ||
1818 | dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); | ||
1819 | } | ||
1820 | } | ||
1821 | |||
1822 | if (ifnum == 0) { | ||
1823 | ictx->rx_endpoint_intf0 = rx_endpoint; | ||
1824 | /* | ||
1825 | * tx is used to send characters to lcd/vfd, associate RF | ||
1826 | * remotes, set IR protocol, and maybe more... | ||
1827 | */ | ||
1828 | ictx->tx_endpoint = tx_endpoint; | ||
1829 | } else { | ||
1830 | ictx->rx_endpoint_intf1 = rx_endpoint; | ||
1831 | } | ||
1832 | |||
1833 | /* | ||
1834 | * If we didn't find a display endpoint, this is probably one of the | ||
1835 | * newer iMON devices that use control urb instead of interrupt | ||
1836 | */ | ||
1837 | if (!display_ep_found) { | ||
1838 | tx_control = 1; | ||
1839 | display_ep_found = 1; | ||
1840 | dev_dbg(ictx->dev, "%s: device uses control endpoint, not " | ||
1841 | "interface OUT endpoint\n", __func__); | ||
1842 | } | ||
1843 | |||
1844 | /* | ||
1845 | * Some iMON receivers have no display. Unfortunately, it seems | ||
1846 | * that SoundGraph recycles device IDs between devices both with | ||
1847 | * and without... :\ | ||
1848 | */ | ||
1849 | if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { | ||
1850 | display_ep_found = 0; | ||
1851 | dev_dbg(ictx->dev, "%s: device has no display\n", __func__); | ||
1852 | } | ||
1853 | |||
1854 | /* | ||
1855 | * iMON Touch devices have a VGA touchscreen, but no "display", as | ||
1856 | * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). | ||
1857 | */ | ||
1858 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { | ||
1859 | display_ep_found = 0; | ||
1860 | dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); | ||
1861 | } | ||
1862 | |||
1863 | /* Input endpoint is mandatory */ | ||
1864 | if (!ir_ep_found) | ||
1865 | err("%s: no valid input (IR) endpoint found.", __func__); | ||
1866 | |||
1867 | ictx->tx_control = tx_control; | ||
1868 | |||
1869 | if (display_ep_found) | ||
1870 | ictx->display_supported = true; | ||
1871 | |||
1872 | return ir_ep_found; | ||
1873 | |||
1874 | } | ||
1875 | |||
1876 | static struct imon_context *imon_init_intf0(struct usb_interface *intf) | ||
1877 | { | ||
1878 | struct imon_context *ictx; | ||
1879 | struct urb *rx_urb; | ||
1880 | struct urb *tx_urb; | ||
1881 | struct device *dev = &intf->dev; | ||
1882 | struct usb_host_interface *iface_desc; | ||
1883 | int ret = -ENOMEM; | ||
1884 | |||
1885 | ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); | ||
1886 | if (!ictx) { | ||
1887 | dev_err(dev, "%s: kzalloc failed for context", __func__); | ||
1888 | goto exit; | ||
1889 | } | ||
1890 | rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1891 | if (!rx_urb) { | ||
1892 | dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__); | ||
1893 | goto rx_urb_alloc_failed; | ||
1894 | } | ||
1895 | tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1896 | if (!tx_urb) { | ||
1897 | dev_err(dev, "%s: usb_alloc_urb failed for display urb", | ||
1898 | __func__); | ||
1899 | goto tx_urb_alloc_failed; | ||
1900 | } | ||
1901 | |||
1902 | mutex_init(&ictx->lock); | ||
1903 | |||
1904 | mutex_lock(&ictx->lock); | ||
1905 | |||
1906 | ictx->dev = dev; | ||
1907 | ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); | ||
1908 | ictx->dev_present_intf0 = 1; | ||
1909 | ictx->rx_urb_intf0 = rx_urb; | ||
1910 | ictx->tx_urb = tx_urb; | ||
1911 | |||
1912 | ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); | ||
1913 | ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); | ||
1914 | |||
1915 | ret = -ENODEV; | ||
1916 | iface_desc = intf->cur_altsetting; | ||
1917 | if (!imon_find_endpoints(ictx, iface_desc)) { | ||
1918 | goto find_endpoint_failed; | ||
1919 | } | ||
1920 | |||
1921 | ictx->idev = imon_init_idev(ictx); | ||
1922 | if (!ictx->idev) { | ||
1923 | dev_err(dev, "%s: input device setup failed\n", __func__); | ||
1924 | goto idev_setup_failed; | ||
1925 | } | ||
1926 | |||
1927 | usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, | ||
1928 | usb_rcvintpipe(ictx->usbdev_intf0, | ||
1929 | ictx->rx_endpoint_intf0->bEndpointAddress), | ||
1930 | ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), | ||
1931 | usb_rx_callback_intf0, ictx, | ||
1932 | ictx->rx_endpoint_intf0->bInterval); | ||
1933 | |||
1934 | ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL); | ||
1935 | if (ret) { | ||
1936 | err("%s: usb_submit_urb failed for intf0 (%d)", | ||
1937 | __func__, ret); | ||
1938 | goto urb_submit_failed; | ||
1939 | } | ||
1940 | |||
1941 | return ictx; | ||
1942 | |||
1943 | urb_submit_failed: | ||
1944 | input_unregister_device(ictx->idev); | ||
1945 | input_free_device(ictx->idev); | ||
1946 | idev_setup_failed: | ||
1947 | find_endpoint_failed: | ||
1948 | mutex_unlock(&ictx->lock); | ||
1949 | usb_free_urb(tx_urb); | ||
1950 | tx_urb_alloc_failed: | ||
1951 | usb_free_urb(rx_urb); | ||
1952 | rx_urb_alloc_failed: | ||
1953 | kfree(ictx); | ||
1954 | exit: | ||
1955 | dev_err(dev, "unable to initialize intf0, err %d\n", ret); | ||
1956 | |||
1957 | return NULL; | ||
1958 | } | ||
1959 | |||
1960 | static struct imon_context *imon_init_intf1(struct usb_interface *intf, | ||
1961 | struct imon_context *ictx) | ||
1962 | { | ||
1963 | struct urb *rx_urb; | ||
1964 | struct usb_host_interface *iface_desc; | ||
1965 | int ret = -ENOMEM; | ||
1966 | |||
1967 | rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1968 | if (!rx_urb) { | ||
1969 | err("%s: usb_alloc_urb failed for IR urb", __func__); | ||
1970 | goto rx_urb_alloc_failed; | ||
1971 | } | ||
1972 | |||
1973 | mutex_lock(&ictx->lock); | ||
1974 | |||
1975 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { | ||
1976 | init_timer(&ictx->ttimer); | ||
1977 | ictx->ttimer.data = (unsigned long)ictx; | ||
1978 | ictx->ttimer.function = imon_touch_display_timeout; | ||
1979 | } | ||
1980 | |||
1981 | ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); | ||
1982 | ictx->dev_present_intf1 = 1; | ||
1983 | ictx->rx_urb_intf1 = rx_urb; | ||
1984 | |||
1985 | ret = -ENODEV; | ||
1986 | iface_desc = intf->cur_altsetting; | ||
1987 | if (!imon_find_endpoints(ictx, iface_desc)) | ||
1988 | goto find_endpoint_failed; | ||
1989 | |||
1990 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { | ||
1991 | ictx->touch = imon_init_touch(ictx); | ||
1992 | if (!ictx->touch) | ||
1993 | goto touch_setup_failed; | ||
1994 | } else | ||
1995 | ictx->touch = NULL; | ||
1996 | |||
1997 | usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, | ||
1998 | usb_rcvintpipe(ictx->usbdev_intf1, | ||
1999 | ictx->rx_endpoint_intf1->bEndpointAddress), | ||
2000 | ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), | ||
2001 | usb_rx_callback_intf1, ictx, | ||
2002 | ictx->rx_endpoint_intf1->bInterval); | ||
2003 | |||
2004 | ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL); | ||
2005 | |||
2006 | if (ret) { | ||
2007 | err("%s: usb_submit_urb failed for intf1 (%d)", | ||
2008 | __func__, ret); | ||
2009 | goto urb_submit_failed; | ||
2010 | } | ||
2011 | |||
2012 | return ictx; | ||
2013 | |||
2014 | urb_submit_failed: | ||
2015 | if (ictx->touch) { | ||
2016 | input_unregister_device(ictx->touch); | ||
2017 | input_free_device(ictx->touch); | ||
2018 | } | ||
2019 | touch_setup_failed: | ||
2020 | find_endpoint_failed: | ||
2021 | mutex_unlock(&ictx->lock); | ||
2022 | usb_free_urb(rx_urb); | ||
2023 | rx_urb_alloc_failed: | ||
2024 | dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret); | ||
2025 | |||
2026 | return NULL; | ||
2027 | } | ||
2028 | |||
2029 | /* | ||
2030 | * The 0x15c2:0xffdc device ID was used for umpteen different imon | ||
2031 | * devices, and all of them constantly spew interrupts, even when there | ||
2032 | * is no actual data to report. However, byte 6 of this buffer looks like | ||
2033 | * its unique across device variants, so we're trying to key off that to | ||
2034 | * figure out which display type (if any) and what IR protocol the device | ||
2035 | * actually supports. These devices have their IR protocol hard-coded into | ||
2036 | * their firmware, they can't be changed on the fly like the newer hardware. | ||
2037 | */ | ||
2038 | static void imon_get_ffdc_type(struct imon_context *ictx) | ||
2039 | { | ||
2040 | u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; | ||
2041 | u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; | ||
2042 | u64 allowed_protos = IR_TYPE_OTHER; | ||
2043 | |||
2044 | switch (ffdc_cfg_byte) { | ||
2045 | /* iMON Knob, no display, iMON IR + vol knob */ | ||
2046 | case 0x21: | ||
2047 | dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); | ||
2048 | ictx->display_supported = false; | ||
2049 | break; | ||
2050 | /* iMON VFD, no IR (does have vol knob tho) */ | ||
2051 | case 0x35: | ||
2052 | dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); | ||
2053 | detected_display_type = IMON_DISPLAY_TYPE_VFD; | ||
2054 | break; | ||
2055 | /* iMON VFD, iMON IR */ | ||
2056 | case 0x24: | ||
2057 | case 0x85: | ||
2058 | dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); | ||
2059 | detected_display_type = IMON_DISPLAY_TYPE_VFD; | ||
2060 | break; | ||
2061 | /* iMON LCD, MCE IR */ | ||
2062 | case 0x9f: | ||
2063 | dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); | ||
2064 | detected_display_type = IMON_DISPLAY_TYPE_LCD; | ||
2065 | allowed_protos = IR_TYPE_RC6; | ||
2066 | break; | ||
2067 | default: | ||
2068 | dev_info(ictx->dev, "Unknown 0xffdc device, " | ||
2069 | "defaulting to VFD and iMON IR"); | ||
2070 | detected_display_type = IMON_DISPLAY_TYPE_VFD; | ||
2071 | break; | ||
2072 | } | ||
2073 | |||
2074 | printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); | ||
2075 | |||
2076 | ictx->display_type = detected_display_type; | ||
2077 | ictx->props->allowed_protos = allowed_protos; | ||
2078 | ictx->ir_type = allowed_protos; | ||
2079 | } | ||
2080 | |||
2081 | static void imon_set_display_type(struct imon_context *ictx, | ||
2082 | struct usb_interface *intf) | ||
2083 | { | ||
2084 | u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; | ||
2085 | |||
2086 | /* | ||
2087 | * Try to auto-detect the type of display if the user hasn't set | ||
2088 | * it by hand via the display_type modparam. Default is VFD. | ||
2089 | */ | ||
2090 | |||
2091 | if (display_type == IMON_DISPLAY_TYPE_AUTO) { | ||
2092 | switch (ictx->product) { | ||
2093 | case 0xffdc: | ||
2094 | /* set in imon_get_ffdc_type() */ | ||
2095 | configured_display_type = ictx->display_type; | ||
2096 | break; | ||
2097 | case 0x0034: | ||
2098 | case 0x0035: | ||
2099 | configured_display_type = IMON_DISPLAY_TYPE_VGA; | ||
2100 | break; | ||
2101 | case 0x0038: | ||
2102 | case 0x0039: | ||
2103 | case 0x0045: | ||
2104 | configured_display_type = IMON_DISPLAY_TYPE_LCD; | ||
2105 | break; | ||
2106 | case 0x003c: | ||
2107 | case 0x0041: | ||
2108 | case 0x0042: | ||
2109 | case 0x0043: | ||
2110 | configured_display_type = IMON_DISPLAY_TYPE_NONE; | ||
2111 | ictx->display_supported = false; | ||
2112 | break; | ||
2113 | case 0x0036: | ||
2114 | case 0x0044: | ||
2115 | default: | ||
2116 | configured_display_type = IMON_DISPLAY_TYPE_VFD; | ||
2117 | break; | ||
2118 | } | ||
2119 | } else { | ||
2120 | configured_display_type = display_type; | ||
2121 | if (display_type == IMON_DISPLAY_TYPE_NONE) | ||
2122 | ictx->display_supported = false; | ||
2123 | else | ||
2124 | ictx->display_supported = true; | ||
2125 | dev_info(ictx->dev, "%s: overriding display type to %d via " | ||
2126 | "modparam\n", __func__, display_type); | ||
2127 | } | ||
2128 | |||
2129 | ictx->display_type = configured_display_type; | ||
2130 | } | ||
2131 | |||
2132 | static void imon_init_display(struct imon_context *ictx, | ||
2133 | struct usb_interface *intf) | ||
2134 | { | ||
2135 | int ret; | ||
2136 | |||
2137 | dev_dbg(ictx->dev, "Registering iMON display with sysfs\n"); | ||
2138 | |||
2139 | /* set up sysfs entry for built-in clock */ | ||
2140 | ret = sysfs_create_group(&intf->dev.kobj, | ||
2141 | &imon_display_attribute_group); | ||
2142 | if (ret) | ||
2143 | dev_err(ictx->dev, "Could not create display sysfs " | ||
2144 | "entries(%d)", ret); | ||
2145 | |||
2146 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) | ||
2147 | ret = usb_register_dev(intf, &imon_lcd_class); | ||
2148 | else | ||
2149 | ret = usb_register_dev(intf, &imon_vfd_class); | ||
2150 | if (ret) | ||
2151 | /* Not a fatal error, so ignore */ | ||
2152 | dev_info(ictx->dev, "could not get a minor number for " | ||
2153 | "display\n"); | ||
2154 | |||
2155 | } | ||
2156 | |||
2157 | /** | ||
2158 | * Callback function for USB core API: Probe | ||
2159 | */ | ||
2160 | static int __devinit imon_probe(struct usb_interface *interface, | ||
2161 | const struct usb_device_id *id) | ||
2162 | { | ||
2163 | struct usb_device *usbdev = NULL; | ||
2164 | struct usb_host_interface *iface_desc = NULL; | ||
2165 | struct usb_interface *first_if; | ||
2166 | struct device *dev = &interface->dev; | ||
2167 | int ifnum, code_length, sysfs_err; | ||
2168 | int ret = 0; | ||
2169 | struct imon_context *ictx = NULL; | ||
2170 | struct imon_context *first_if_ctx = NULL; | ||
2171 | u16 vendor, product; | ||
2172 | const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, | ||
2173 | 0x00, 0x00, 0x00, 0x88 }; | ||
2174 | |||
2175 | code_length = BUF_CHUNK_SIZE * 8; | ||
2176 | |||
2177 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | ||
2178 | iface_desc = interface->cur_altsetting; | ||
2179 | ifnum = iface_desc->desc.bInterfaceNumber; | ||
2180 | vendor = le16_to_cpu(usbdev->descriptor.idVendor); | ||
2181 | product = le16_to_cpu(usbdev->descriptor.idProduct); | ||
2182 | |||
2183 | dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", | ||
2184 | __func__, vendor, product, ifnum); | ||
2185 | |||
2186 | /* prevent races probing devices w/multiple interfaces */ | ||
2187 | mutex_lock(&driver_lock); | ||
2188 | |||
2189 | first_if = usb_ifnum_to_if(usbdev, 0); | ||
2190 | first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if); | ||
2191 | |||
2192 | if (ifnum == 0) { | ||
2193 | ictx = imon_init_intf0(interface); | ||
2194 | if (!ictx) { | ||
2195 | err("%s: failed to initialize context!\n", __func__); | ||
2196 | ret = -ENODEV; | ||
2197 | goto fail; | ||
2198 | } | ||
2199 | |||
2200 | if (product == 0xffdc) { | ||
2201 | /* RF products *also* use 0xffdc... sigh... */ | ||
2202 | sysfs_err = sysfs_create_group(&interface->dev.kobj, | ||
2203 | &imon_rf_attribute_group); | ||
2204 | if (sysfs_err) | ||
2205 | err("%s: Could not create RF sysfs entries(%d)", | ||
2206 | __func__, sysfs_err); | ||
2207 | } | ||
2208 | |||
2209 | } else { | ||
2210 | /* this is the secondary interface on the device */ | ||
2211 | ictx = imon_init_intf1(interface, first_if_ctx); | ||
2212 | if (!ictx) { | ||
2213 | err("%s: failed to attach to context!\n", __func__); | ||
2214 | ret = -ENODEV; | ||
2215 | goto fail; | ||
2216 | } | ||
2217 | |||
2218 | } | ||
2219 | |||
2220 | usb_set_intfdata(interface, ictx); | ||
2221 | |||
2222 | if (ifnum == 0) { | ||
2223 | /* Enable front-panel buttons and/or knobs */ | ||
2224 | memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); | ||
2225 | ret = send_packet(ictx); | ||
2226 | /* Not fatal, but warn about it */ | ||
2227 | if (ret) | ||
2228 | dev_info(dev, "failed to enable panel buttons " | ||
2229 | "and/or knobs\n"); | ||
2230 | |||
2231 | if (product == 0xffdc) | ||
2232 | imon_get_ffdc_type(ictx); | ||
2233 | |||
2234 | imon_set_display_type(ictx, interface); | ||
2235 | |||
2236 | if (ictx->display_supported) | ||
2237 | imon_init_display(ictx, interface); | ||
2238 | } | ||
2239 | |||
2240 | /* set IR protocol/remote type */ | ||
2241 | ret = imon_ir_change_protocol(ictx, ictx->ir_type); | ||
2242 | if (ret) { | ||
2243 | dev_warn(dev, "%s: failed to set IR protocol, falling back " | ||
2244 | "to standard iMON protocol mode\n", __func__); | ||
2245 | ictx->ir_type = IR_TYPE_OTHER; | ||
2246 | } | ||
2247 | |||
2248 | dev_info(dev, "iMON device (%04x:%04x, intf%d) on " | ||
2249 | "usb<%d:%d> initialized\n", vendor, product, ifnum, | ||
2250 | usbdev->bus->busnum, usbdev->devnum); | ||
2251 | |||
2252 | mutex_unlock(&ictx->lock); | ||
2253 | mutex_unlock(&driver_lock); | ||
2254 | |||
2255 | return 0; | ||
2256 | |||
2257 | fail: | ||
2258 | mutex_unlock(&driver_lock); | ||
2259 | dev_err(dev, "unable to register, err %d\n", ret); | ||
2260 | |||
2261 | return ret; | ||
2262 | } | ||
2263 | |||
2264 | /** | ||
2265 | * Callback function for USB core API: disconnect | ||
2266 | */ | ||
2267 | static void __devexit imon_disconnect(struct usb_interface *interface) | ||
2268 | { | ||
2269 | struct imon_context *ictx; | ||
2270 | struct device *dev; | ||
2271 | int ifnum; | ||
2272 | |||
2273 | /* prevent races with multi-interface device probing and display_open */ | ||
2274 | mutex_lock(&driver_lock); | ||
2275 | |||
2276 | ictx = usb_get_intfdata(interface); | ||
2277 | dev = ictx->dev; | ||
2278 | ifnum = interface->cur_altsetting->desc.bInterfaceNumber; | ||
2279 | |||
2280 | mutex_lock(&ictx->lock); | ||
2281 | |||
2282 | /* | ||
2283 | * sysfs_remove_group is safe to call even if sysfs_create_group | ||
2284 | * hasn't been called | ||
2285 | */ | ||
2286 | sysfs_remove_group(&interface->dev.kobj, | ||
2287 | &imon_display_attribute_group); | ||
2288 | sysfs_remove_group(&interface->dev.kobj, | ||
2289 | &imon_rf_attribute_group); | ||
2290 | |||
2291 | usb_set_intfdata(interface, NULL); | ||
2292 | |||
2293 | /* Abort ongoing write */ | ||
2294 | if (ictx->tx.busy) { | ||
2295 | usb_kill_urb(ictx->tx_urb); | ||
2296 | complete_all(&ictx->tx.finished); | ||
2297 | } | ||
2298 | |||
2299 | if (ifnum == 0) { | ||
2300 | ictx->dev_present_intf0 = 0; | ||
2301 | usb_kill_urb(ictx->rx_urb_intf0); | ||
2302 | input_unregister_device(ictx->idev); | ||
2303 | if (ictx->display_supported) { | ||
2304 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) | ||
2305 | usb_deregister_dev(interface, &imon_lcd_class); | ||
2306 | else | ||
2307 | usb_deregister_dev(interface, &imon_vfd_class); | ||
2308 | } | ||
2309 | } else { | ||
2310 | ictx->dev_present_intf1 = 0; | ||
2311 | usb_kill_urb(ictx->rx_urb_intf1); | ||
2312 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | ||
2313 | input_unregister_device(ictx->touch); | ||
2314 | } | ||
2315 | |||
2316 | if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { | ||
2317 | if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | ||
2318 | del_timer_sync(&ictx->ttimer); | ||
2319 | mutex_unlock(&ictx->lock); | ||
2320 | if (!ictx->display_isopen) | ||
2321 | free_imon_context(ictx); | ||
2322 | } else { | ||
2323 | if (ictx->ir_type == IR_TYPE_RC6) | ||
2324 | del_timer_sync(&ictx->itimer); | ||
2325 | mutex_unlock(&ictx->lock); | ||
2326 | } | ||
2327 | |||
2328 | mutex_unlock(&driver_lock); | ||
2329 | |||
2330 | dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n", | ||
2331 | __func__, ifnum); | ||
2332 | } | ||
2333 | |||
2334 | static int imon_suspend(struct usb_interface *intf, pm_message_t message) | ||
2335 | { | ||
2336 | struct imon_context *ictx = usb_get_intfdata(intf); | ||
2337 | int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
2338 | |||
2339 | if (ifnum == 0) | ||
2340 | usb_kill_urb(ictx->rx_urb_intf0); | ||
2341 | else | ||
2342 | usb_kill_urb(ictx->rx_urb_intf1); | ||
2343 | |||
2344 | return 0; | ||
2345 | } | ||
2346 | |||
2347 | static int imon_resume(struct usb_interface *intf) | ||
2348 | { | ||
2349 | int rc = 0; | ||
2350 | struct imon_context *ictx = usb_get_intfdata(intf); | ||
2351 | int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
2352 | |||
2353 | if (ifnum == 0) { | ||
2354 | usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, | ||
2355 | usb_rcvintpipe(ictx->usbdev_intf0, | ||
2356 | ictx->rx_endpoint_intf0->bEndpointAddress), | ||
2357 | ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), | ||
2358 | usb_rx_callback_intf0, ictx, | ||
2359 | ictx->rx_endpoint_intf0->bInterval); | ||
2360 | |||
2361 | rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); | ||
2362 | |||
2363 | } else { | ||
2364 | usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, | ||
2365 | usb_rcvintpipe(ictx->usbdev_intf1, | ||
2366 | ictx->rx_endpoint_intf1->bEndpointAddress), | ||
2367 | ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), | ||
2368 | usb_rx_callback_intf1, ictx, | ||
2369 | ictx->rx_endpoint_intf1->bInterval); | ||
2370 | |||
2371 | rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); | ||
2372 | } | ||
2373 | |||
2374 | return rc; | ||
2375 | } | ||
2376 | |||
2377 | static int __init imon_init(void) | ||
2378 | { | ||
2379 | int rc; | ||
2380 | |||
2381 | rc = usb_register(&imon_driver); | ||
2382 | if (rc) { | ||
2383 | err("%s: usb register failed(%d)", __func__, rc); | ||
2384 | rc = -ENODEV; | ||
2385 | } | ||
2386 | |||
2387 | return rc; | ||
2388 | } | ||
2389 | |||
2390 | static void __exit imon_exit(void) | ||
2391 | { | ||
2392 | usb_deregister(&imon_driver); | ||
2393 | } | ||
2394 | |||
2395 | module_init(imon_init); | ||
2396 | module_exit(imon_exit); | ||
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h new file mode 100644 index 000000000000..9a5e65a471a5 --- /dev/null +++ b/drivers/media/IR/ir-core-priv.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Remote Controller core raw events header | ||
3 | * | ||
4 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef _IR_RAW_EVENT | ||
17 | #define _IR_RAW_EVENT | ||
18 | |||
19 | #include <linux/slab.h> | ||
20 | #include <media/ir-core.h> | ||
21 | |||
22 | struct ir_raw_handler { | ||
23 | struct list_head list; | ||
24 | |||
25 | int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); | ||
26 | int (*raw_register)(struct input_dev *input_dev); | ||
27 | int (*raw_unregister)(struct input_dev *input_dev); | ||
28 | }; | ||
29 | |||
30 | struct ir_raw_event_ctrl { | ||
31 | struct work_struct rx_work; /* for the rx decoding workqueue */ | ||
32 | struct kfifo kfifo; /* fifo for the pulse/space durations */ | ||
33 | ktime_t last_event; /* when last event occurred */ | ||
34 | enum raw_event_type last_type; /* last event type */ | ||
35 | struct input_dev *input_dev; /* pointer to the parent input_dev */ | ||
36 | }; | ||
37 | |||
38 | /* macros for IR decoders */ | ||
39 | static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) | ||
40 | { | ||
41 | return d1 > (d2 - margin); | ||
42 | } | ||
43 | |||
44 | static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) | ||
45 | { | ||
46 | return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); | ||
47 | } | ||
48 | |||
49 | static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) | ||
50 | { | ||
51 | return x->pulse != y->pulse; | ||
52 | } | ||
53 | |||
54 | static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) | ||
55 | { | ||
56 | if (duration > ev->duration) | ||
57 | ev->duration = 0; | ||
58 | else | ||
59 | ev->duration -= duration; | ||
60 | } | ||
61 | |||
62 | #define TO_US(duration) (((duration) + 500) / 1000) | ||
63 | #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") | ||
64 | #define IS_RESET(ev) (ev.duration == 0) | ||
65 | |||
66 | /* | ||
67 | * Routines from ir-sysfs.c - Meant to be called only internally inside | ||
68 | * ir-core | ||
69 | */ | ||
70 | |||
71 | int ir_register_class(struct input_dev *input_dev); | ||
72 | void ir_unregister_class(struct input_dev *input_dev); | ||
73 | |||
74 | /* | ||
75 | * Routines from ir-raw-event.c to be used internally and by decoders | ||
76 | */ | ||
77 | int ir_raw_event_register(struct input_dev *input_dev); | ||
78 | void ir_raw_event_unregister(struct input_dev *input_dev); | ||
79 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); | ||
80 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); | ||
81 | void ir_raw_init(void); | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Decoder initialization code | ||
86 | * | ||
87 | * Those load logic are called during ir-core init, and automatically | ||
88 | * loads the compiled decoders for their usage with IR raw events | ||
89 | */ | ||
90 | |||
91 | /* from ir-nec-decoder.c */ | ||
92 | #ifdef CONFIG_IR_NEC_DECODER_MODULE | ||
93 | #define load_nec_decode() request_module("ir-nec-decoder") | ||
94 | #else | ||
95 | #define load_nec_decode() 0 | ||
96 | #endif | ||
97 | |||
98 | /* from ir-rc5-decoder.c */ | ||
99 | #ifdef CONFIG_IR_RC5_DECODER_MODULE | ||
100 | #define load_rc5_decode() request_module("ir-rc5-decoder") | ||
101 | #else | ||
102 | #define load_rc5_decode() 0 | ||
103 | #endif | ||
104 | |||
105 | /* from ir-rc6-decoder.c */ | ||
106 | #ifdef CONFIG_IR_RC6_DECODER_MODULE | ||
107 | #define load_rc6_decode() request_module("ir-rc6-decoder") | ||
108 | #else | ||
109 | #define load_rc6_decode() 0 | ||
110 | #endif | ||
111 | |||
112 | /* from ir-jvc-decoder.c */ | ||
113 | #ifdef CONFIG_IR_JVC_DECODER_MODULE | ||
114 | #define load_jvc_decode() request_module("ir-jvc-decoder") | ||
115 | #else | ||
116 | #define load_jvc_decode() 0 | ||
117 | #endif | ||
118 | |||
119 | /* from ir-sony-decoder.c */ | ||
120 | #ifdef CONFIG_IR_SONY_DECODER_MODULE | ||
121 | #define load_sony_decode() request_module("ir-sony-decoder") | ||
122 | #else | ||
123 | #define load_sony_decode() 0 | ||
124 | #endif | ||
125 | |||
126 | #endif /* _IR_RAW_EVENT */ | ||
diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index ab06919ad5fc..db591e421887 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
26 | #include <media/ir-common.h> | 26 | #include <media/ir-common.h> |
27 | #include "ir-core-priv.h" | ||
27 | 28 | ||
28 | /* -------------------------------------------------------------------------- */ | 29 | /* -------------------------------------------------------------------------- */ |
29 | 30 | ||
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c new file mode 100644 index 000000000000..0b804944cbb0 --- /dev/null +++ b/drivers/media/IR/ir-jvc-decoder.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2010 by David Härdeman <david@hardeman.nu> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/bitrev.h> | ||
16 | #include "ir-core-priv.h" | ||
17 | |||
18 | #define JVC_NBITS 16 /* dev(8) + func(8) */ | ||
19 | #define JVC_UNIT 525000 /* ns */ | ||
20 | #define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */ | ||
21 | #define JVC_HEADER_SPACE (8 * JVC_UNIT) | ||
22 | #define JVC_BIT_PULSE (1 * JVC_UNIT) | ||
23 | #define JVC_BIT_0_SPACE (1 * JVC_UNIT) | ||
24 | #define JVC_BIT_1_SPACE (3 * JVC_UNIT) | ||
25 | #define JVC_TRAILER_PULSE (1 * JVC_UNIT) | ||
26 | #define JVC_TRAILER_SPACE (35 * JVC_UNIT) | ||
27 | |||
28 | /* Used to register jvc_decoder clients */ | ||
29 | static LIST_HEAD(decoder_list); | ||
30 | DEFINE_SPINLOCK(decoder_lock); | ||
31 | |||
32 | enum jvc_state { | ||
33 | STATE_INACTIVE, | ||
34 | STATE_HEADER_SPACE, | ||
35 | STATE_BIT_PULSE, | ||
36 | STATE_BIT_SPACE, | ||
37 | STATE_TRAILER_PULSE, | ||
38 | STATE_TRAILER_SPACE, | ||
39 | }; | ||
40 | |||
41 | struct decoder_data { | ||
42 | struct list_head list; | ||
43 | struct ir_input_dev *ir_dev; | ||
44 | int enabled:1; | ||
45 | |||
46 | /* State machine control */ | ||
47 | enum jvc_state state; | ||
48 | u16 jvc_bits; | ||
49 | u16 jvc_old_bits; | ||
50 | unsigned count; | ||
51 | bool first; | ||
52 | bool toggle; | ||
53 | }; | ||
54 | |||
55 | |||
56 | /** | ||
57 | * get_decoder_data() - gets decoder data | ||
58 | * @input_dev: input device | ||
59 | * | ||
60 | * Returns the struct decoder_data that corresponds to a device | ||
61 | */ | ||
62 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
63 | { | ||
64 | struct decoder_data *data = NULL; | ||
65 | |||
66 | spin_lock(&decoder_lock); | ||
67 | list_for_each_entry(data, &decoder_list, list) { | ||
68 | if (data->ir_dev == ir_dev) | ||
69 | break; | ||
70 | } | ||
71 | spin_unlock(&decoder_lock); | ||
72 | return data; | ||
73 | } | ||
74 | |||
75 | static ssize_t store_enabled(struct device *d, | ||
76 | struct device_attribute *mattr, | ||
77 | const char *buf, | ||
78 | size_t len) | ||
79 | { | ||
80 | unsigned long value; | ||
81 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
82 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
83 | |||
84 | if (!data) | ||
85 | return -EINVAL; | ||
86 | |||
87 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
88 | return -EINVAL; | ||
89 | |||
90 | data->enabled = value; | ||
91 | |||
92 | return len; | ||
93 | } | ||
94 | |||
95 | static ssize_t show_enabled(struct device *d, | ||
96 | struct device_attribute *mattr, char *buf) | ||
97 | { | ||
98 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
99 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
100 | |||
101 | if (!data) | ||
102 | return -EINVAL; | ||
103 | |||
104 | if (data->enabled) | ||
105 | return sprintf(buf, "1\n"); | ||
106 | else | ||
107 | return sprintf(buf, "0\n"); | ||
108 | } | ||
109 | |||
110 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
111 | |||
112 | static struct attribute *decoder_attributes[] = { | ||
113 | &dev_attr_enabled.attr, | ||
114 | NULL | ||
115 | }; | ||
116 | |||
117 | static struct attribute_group decoder_attribute_group = { | ||
118 | .name = "jvc_decoder", | ||
119 | .attrs = decoder_attributes, | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * ir_jvc_decode() - Decode one JVC pulse or space | ||
124 | * @input_dev: the struct input_dev descriptor of the device | ||
125 | * @duration: the struct ir_raw_event descriptor of the pulse/space | ||
126 | * | ||
127 | * This function returns -EINVAL if the pulse violates the state machine | ||
128 | */ | ||
129 | static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | ||
130 | { | ||
131 | struct decoder_data *data; | ||
132 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
133 | |||
134 | data = get_decoder_data(ir_dev); | ||
135 | if (!data) | ||
136 | return -EINVAL; | ||
137 | |||
138 | if (!data->enabled) | ||
139 | return 0; | ||
140 | |||
141 | if (IS_RESET(ev)) { | ||
142 | data->state = STATE_INACTIVE; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2)) | ||
147 | goto out; | ||
148 | |||
149 | IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", | ||
150 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
151 | |||
152 | switch (data->state) { | ||
153 | |||
154 | case STATE_INACTIVE: | ||
155 | if (!ev.pulse) | ||
156 | break; | ||
157 | |||
158 | if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) | ||
159 | break; | ||
160 | |||
161 | data->count = 0; | ||
162 | data->first = true; | ||
163 | data->toggle = !data->toggle; | ||
164 | data->state = STATE_HEADER_SPACE; | ||
165 | return 0; | ||
166 | |||
167 | case STATE_HEADER_SPACE: | ||
168 | if (ev.pulse) | ||
169 | break; | ||
170 | |||
171 | if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2)) | ||
172 | break; | ||
173 | |||
174 | data->state = STATE_BIT_PULSE; | ||
175 | return 0; | ||
176 | |||
177 | case STATE_BIT_PULSE: | ||
178 | if (!ev.pulse) | ||
179 | break; | ||
180 | |||
181 | if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2)) | ||
182 | break; | ||
183 | |||
184 | data->state = STATE_BIT_SPACE; | ||
185 | return 0; | ||
186 | |||
187 | case STATE_BIT_SPACE: | ||
188 | if (ev.pulse) | ||
189 | break; | ||
190 | |||
191 | data->jvc_bits <<= 1; | ||
192 | if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { | ||
193 | data->jvc_bits |= 1; | ||
194 | decrease_duration(&ev, JVC_BIT_1_SPACE); | ||
195 | } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) | ||
196 | decrease_duration(&ev, JVC_BIT_0_SPACE); | ||
197 | else | ||
198 | break; | ||
199 | data->count++; | ||
200 | |||
201 | if (data->count == JVC_NBITS) | ||
202 | data->state = STATE_TRAILER_PULSE; | ||
203 | else | ||
204 | data->state = STATE_BIT_PULSE; | ||
205 | return 0; | ||
206 | |||
207 | case STATE_TRAILER_PULSE: | ||
208 | if (!ev.pulse) | ||
209 | break; | ||
210 | |||
211 | if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2)) | ||
212 | break; | ||
213 | |||
214 | data->state = STATE_TRAILER_SPACE; | ||
215 | return 0; | ||
216 | |||
217 | case STATE_TRAILER_SPACE: | ||
218 | if (ev.pulse) | ||
219 | break; | ||
220 | |||
221 | if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2)) | ||
222 | break; | ||
223 | |||
224 | if (data->first) { | ||
225 | u32 scancode; | ||
226 | scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) | | ||
227 | (bitrev8((data->jvc_bits >> 0) & 0xff) << 0); | ||
228 | IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); | ||
229 | ir_keydown(input_dev, scancode, data->toggle); | ||
230 | data->first = false; | ||
231 | data->jvc_old_bits = data->jvc_bits; | ||
232 | } else if (data->jvc_bits == data->jvc_old_bits) { | ||
233 | IR_dprintk(1, "JVC repeat\n"); | ||
234 | ir_repeat(input_dev); | ||
235 | } else { | ||
236 | IR_dprintk(1, "JVC invalid repeat msg\n"); | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | data->count = 0; | ||
241 | data->state = STATE_BIT_PULSE; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | out: | ||
246 | IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n", | ||
247 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
248 | data->state = STATE_INACTIVE; | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | static int ir_jvc_register(struct input_dev *input_dev) | ||
253 | { | ||
254 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
255 | struct decoder_data *data; | ||
256 | int rc; | ||
257 | |||
258 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
259 | if (rc < 0) | ||
260 | return rc; | ||
261 | |||
262 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
263 | if (!data) { | ||
264 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | data->ir_dev = ir_dev; | ||
269 | data->enabled = 1; | ||
270 | |||
271 | spin_lock(&decoder_lock); | ||
272 | list_add_tail(&data->list, &decoder_list); | ||
273 | spin_unlock(&decoder_lock); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int ir_jvc_unregister(struct input_dev *input_dev) | ||
279 | { | ||
280 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
281 | static struct decoder_data *data; | ||
282 | |||
283 | data = get_decoder_data(ir_dev); | ||
284 | if (!data) | ||
285 | return 0; | ||
286 | |||
287 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
288 | |||
289 | spin_lock(&decoder_lock); | ||
290 | list_del(&data->list); | ||
291 | spin_unlock(&decoder_lock); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static struct ir_raw_handler jvc_handler = { | ||
297 | .decode = ir_jvc_decode, | ||
298 | .raw_register = ir_jvc_register, | ||
299 | .raw_unregister = ir_jvc_unregister, | ||
300 | }; | ||
301 | |||
302 | static int __init ir_jvc_decode_init(void) | ||
303 | { | ||
304 | ir_raw_handler_register(&jvc_handler); | ||
305 | |||
306 | printk(KERN_INFO "IR JVC protocol handler initialized\n"); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static void __exit ir_jvc_decode_exit(void) | ||
311 | { | ||
312 | ir_raw_handler_unregister(&jvc_handler); | ||
313 | } | ||
314 | |||
315 | module_init(ir_jvc_decode_init); | ||
316 | module_exit(ir_jvc_decode_exit); | ||
317 | |||
318 | MODULE_LICENSE("GPL"); | ||
319 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); | ||
320 | MODULE_DESCRIPTION("JVC IR protocol decoder"); | ||
diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c deleted file mode 100644 index 0efdefe75f32..000000000000 --- a/drivers/media/IR/ir-keymaps.c +++ /dev/null | |||
@@ -1,3494 +0,0 @@ | |||
1 | /* | ||
2 | Keytables for supported remote controls, used on drivers/media | ||
3 | devices. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * NOTICE FOR DEVELOPERS: | ||
22 | * The IR mappings should be as close as possible to what's | ||
23 | * specified at: | ||
24 | * http://linuxtv.org/wiki/index.php/Remote_Controllers | ||
25 | */ | ||
26 | #include <linux/module.h> | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <media/ir-common.h> | ||
30 | |||
31 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | ||
32 | static struct ir_scancode ir_codes_empty[] = { | ||
33 | { 0x2a, KEY_COFFEE }, | ||
34 | }; | ||
35 | |||
36 | struct ir_scancode_table ir_codes_empty_table = { | ||
37 | .scan = ir_codes_empty, | ||
38 | .size = ARRAY_SIZE(ir_codes_empty), | ||
39 | }; | ||
40 | EXPORT_SYMBOL_GPL(ir_codes_empty_table); | ||
41 | |||
42 | /* Michal Majchrowicz <mmajchrowicz@gmail.com> */ | ||
43 | static struct ir_scancode ir_codes_proteus_2309[] = { | ||
44 | /* numeric */ | ||
45 | { 0x00, KEY_0 }, | ||
46 | { 0x01, KEY_1 }, | ||
47 | { 0x02, KEY_2 }, | ||
48 | { 0x03, KEY_3 }, | ||
49 | { 0x04, KEY_4 }, | ||
50 | { 0x05, KEY_5 }, | ||
51 | { 0x06, KEY_6 }, | ||
52 | { 0x07, KEY_7 }, | ||
53 | { 0x08, KEY_8 }, | ||
54 | { 0x09, KEY_9 }, | ||
55 | |||
56 | { 0x5c, KEY_POWER }, /* power */ | ||
57 | { 0x20, KEY_ZOOM }, /* full screen */ | ||
58 | { 0x0f, KEY_BACKSPACE }, /* recall */ | ||
59 | { 0x1b, KEY_ENTER }, /* mute */ | ||
60 | { 0x41, KEY_RECORD }, /* record */ | ||
61 | { 0x43, KEY_STOP }, /* stop */ | ||
62 | { 0x16, KEY_S }, | ||
63 | { 0x1a, KEY_POWER2 }, /* off */ | ||
64 | { 0x2e, KEY_RED }, | ||
65 | { 0x1f, KEY_CHANNELDOWN }, /* channel - */ | ||
66 | { 0x1c, KEY_CHANNELUP }, /* channel + */ | ||
67 | { 0x10, KEY_VOLUMEDOWN }, /* volume - */ | ||
68 | { 0x1e, KEY_VOLUMEUP }, /* volume + */ | ||
69 | { 0x14, KEY_F1 }, | ||
70 | }; | ||
71 | |||
72 | struct ir_scancode_table ir_codes_proteus_2309_table = { | ||
73 | .scan = ir_codes_proteus_2309, | ||
74 | .size = ARRAY_SIZE(ir_codes_proteus_2309), | ||
75 | }; | ||
76 | EXPORT_SYMBOL_GPL(ir_codes_proteus_2309_table); | ||
77 | |||
78 | /* Matt Jesson <dvb@jesson.eclipse.co.uk */ | ||
79 | static struct ir_scancode ir_codes_avermedia_dvbt[] = { | ||
80 | { 0x28, KEY_0 }, /* '0' / 'enter' */ | ||
81 | { 0x22, KEY_1 }, /* '1' */ | ||
82 | { 0x12, KEY_2 }, /* '2' / 'up arrow' */ | ||
83 | { 0x32, KEY_3 }, /* '3' */ | ||
84 | { 0x24, KEY_4 }, /* '4' / 'left arrow' */ | ||
85 | { 0x14, KEY_5 }, /* '5' */ | ||
86 | { 0x34, KEY_6 }, /* '6' / 'right arrow' */ | ||
87 | { 0x26, KEY_7 }, /* '7' */ | ||
88 | { 0x16, KEY_8 }, /* '8' / 'down arrow' */ | ||
89 | { 0x36, KEY_9 }, /* '9' */ | ||
90 | |||
91 | { 0x20, KEY_LIST }, /* 'source' */ | ||
92 | { 0x10, KEY_TEXT }, /* 'teletext' */ | ||
93 | { 0x00, KEY_POWER }, /* 'power' */ | ||
94 | { 0x04, KEY_AUDIO }, /* 'audio' */ | ||
95 | { 0x06, KEY_ZOOM }, /* 'full screen' */ | ||
96 | { 0x18, KEY_VIDEO }, /* 'display' */ | ||
97 | { 0x38, KEY_SEARCH }, /* 'loop' */ | ||
98 | { 0x08, KEY_INFO }, /* 'preview' */ | ||
99 | { 0x2a, KEY_REWIND }, /* 'backward <<' */ | ||
100 | { 0x1a, KEY_FASTFORWARD }, /* 'forward >>' */ | ||
101 | { 0x3a, KEY_RECORD }, /* 'capture' */ | ||
102 | { 0x0a, KEY_MUTE }, /* 'mute' */ | ||
103 | { 0x2c, KEY_RECORD }, /* 'record' */ | ||
104 | { 0x1c, KEY_PAUSE }, /* 'pause' */ | ||
105 | { 0x3c, KEY_STOP }, /* 'stop' */ | ||
106 | { 0x0c, KEY_PLAY }, /* 'play' */ | ||
107 | { 0x2e, KEY_RED }, /* 'red' */ | ||
108 | { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ | ||
109 | { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ | ||
110 | { 0x21, KEY_GREEN }, /* 'green' */ | ||
111 | { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ | ||
112 | { 0x31, KEY_CHANNELUP }, /* 'channel +' */ | ||
113 | { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ | ||
114 | { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ | ||
115 | }; | ||
116 | |||
117 | struct ir_scancode_table ir_codes_avermedia_dvbt_table = { | ||
118 | .scan = ir_codes_avermedia_dvbt, | ||
119 | .size = ARRAY_SIZE(ir_codes_avermedia_dvbt), | ||
120 | }; | ||
121 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt_table); | ||
122 | |||
123 | /* Mauro Carvalho Chehab <mchehab@infradead.org> */ | ||
124 | static struct ir_scancode ir_codes_avermedia_m135a[] = { | ||
125 | { 0x00, KEY_POWER2 }, | ||
126 | { 0x2e, KEY_DOT }, /* '.' */ | ||
127 | { 0x01, KEY_MODE }, /* TV/FM */ | ||
128 | |||
129 | { 0x05, KEY_1 }, | ||
130 | { 0x06, KEY_2 }, | ||
131 | { 0x07, KEY_3 }, | ||
132 | { 0x09, KEY_4 }, | ||
133 | { 0x0a, KEY_5 }, | ||
134 | { 0x0b, KEY_6 }, | ||
135 | { 0x0d, KEY_7 }, | ||
136 | { 0x0e, KEY_8 }, | ||
137 | { 0x0f, KEY_9 }, | ||
138 | { 0x11, KEY_0 }, | ||
139 | |||
140 | { 0x13, KEY_RIGHT }, /* -> */ | ||
141 | { 0x12, KEY_LEFT }, /* <- */ | ||
142 | |||
143 | { 0x17, KEY_SLEEP }, /* Capturar Imagem */ | ||
144 | { 0x10, KEY_SHUFFLE }, /* Amostra */ | ||
145 | |||
146 | /* FIXME: The keys bellow aren't ok */ | ||
147 | |||
148 | { 0x43, KEY_CHANNELUP }, | ||
149 | { 0x42, KEY_CHANNELDOWN }, | ||
150 | { 0x1f, KEY_VOLUMEUP }, | ||
151 | { 0x1e, KEY_VOLUMEDOWN }, | ||
152 | { 0x0c, KEY_ENTER }, | ||
153 | |||
154 | { 0x14, KEY_MUTE }, | ||
155 | { 0x08, KEY_AUDIO }, | ||
156 | |||
157 | { 0x03, KEY_TEXT }, | ||
158 | { 0x04, KEY_EPG }, | ||
159 | { 0x2b, KEY_TV2 }, /* TV2 */ | ||
160 | |||
161 | { 0x1d, KEY_RED }, | ||
162 | { 0x1c, KEY_YELLOW }, | ||
163 | { 0x41, KEY_GREEN }, | ||
164 | { 0x40, KEY_BLUE }, | ||
165 | |||
166 | { 0x1a, KEY_PLAYPAUSE }, | ||
167 | { 0x19, KEY_RECORD }, | ||
168 | { 0x18, KEY_PLAY }, | ||
169 | { 0x1b, KEY_STOP }, | ||
170 | }; | ||
171 | |||
172 | struct ir_scancode_table ir_codes_avermedia_m135a_table = { | ||
173 | .scan = ir_codes_avermedia_m135a, | ||
174 | .size = ARRAY_SIZE(ir_codes_avermedia_m135a), | ||
175 | }; | ||
176 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a_table); | ||
177 | |||
178 | /* Oldrich Jedlicka <oldium.pro@seznam.cz> */ | ||
179 | static struct ir_scancode ir_codes_avermedia_cardbus[] = { | ||
180 | { 0x00, KEY_POWER }, | ||
181 | { 0x01, KEY_TUNER }, /* TV/FM */ | ||
182 | { 0x03, KEY_TEXT }, /* Teletext */ | ||
183 | { 0x04, KEY_EPG }, | ||
184 | { 0x05, KEY_1 }, | ||
185 | { 0x06, KEY_2 }, | ||
186 | { 0x07, KEY_3 }, | ||
187 | { 0x08, KEY_AUDIO }, | ||
188 | { 0x09, KEY_4 }, | ||
189 | { 0x0a, KEY_5 }, | ||
190 | { 0x0b, KEY_6 }, | ||
191 | { 0x0c, KEY_ZOOM }, /* Full screen */ | ||
192 | { 0x0d, KEY_7 }, | ||
193 | { 0x0e, KEY_8 }, | ||
194 | { 0x0f, KEY_9 }, | ||
195 | { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ | ||
196 | { 0x11, KEY_0 }, | ||
197 | { 0x12, KEY_INFO }, | ||
198 | { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ | ||
199 | { 0x14, KEY_MUTE }, | ||
200 | { 0x15, KEY_EDIT }, /* Autoscan */ | ||
201 | { 0x17, KEY_SAVE }, /* Screenshot */ | ||
202 | { 0x18, KEY_PLAYPAUSE }, | ||
203 | { 0x19, KEY_RECORD }, | ||
204 | { 0x1a, KEY_PLAY }, | ||
205 | { 0x1b, KEY_STOP }, | ||
206 | { 0x1c, KEY_FASTFORWARD }, | ||
207 | { 0x1d, KEY_REWIND }, | ||
208 | { 0x1e, KEY_VOLUMEDOWN }, | ||
209 | { 0x1f, KEY_VOLUMEUP }, | ||
210 | { 0x22, KEY_SLEEP }, /* Sleep */ | ||
211 | { 0x23, KEY_ZOOM }, /* Aspect */ | ||
212 | { 0x26, KEY_SCREEN }, /* Pos */ | ||
213 | { 0x27, KEY_ANGLE }, /* Size */ | ||
214 | { 0x28, KEY_SELECT }, /* Select */ | ||
215 | { 0x29, KEY_BLUE }, /* Blue/Picture */ | ||
216 | { 0x2a, KEY_BACKSPACE }, /* Back */ | ||
217 | { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ | ||
218 | { 0x2c, KEY_DOWN }, | ||
219 | { 0x2e, KEY_DOT }, | ||
220 | { 0x2f, KEY_TV }, /* Live TV */ | ||
221 | { 0x32, KEY_LEFT }, | ||
222 | { 0x33, KEY_CLEAR }, /* Clear */ | ||
223 | { 0x35, KEY_RED }, /* Red/TV */ | ||
224 | { 0x36, KEY_UP }, | ||
225 | { 0x37, KEY_HOME }, /* Home */ | ||
226 | { 0x39, KEY_GREEN }, /* Green/Video */ | ||
227 | { 0x3d, KEY_YELLOW }, /* Yellow/Music */ | ||
228 | { 0x3e, KEY_OK }, /* Ok */ | ||
229 | { 0x3f, KEY_RIGHT }, | ||
230 | { 0x40, KEY_NEXT }, /* Next */ | ||
231 | { 0x41, KEY_PREVIOUS }, /* Previous */ | ||
232 | { 0x42, KEY_CHANNELDOWN }, /* Channel down */ | ||
233 | { 0x43, KEY_CHANNELUP }, /* Channel up */ | ||
234 | }; | ||
235 | |||
236 | struct ir_scancode_table ir_codes_avermedia_cardbus_table = { | ||
237 | .scan = ir_codes_avermedia_cardbus, | ||
238 | .size = ARRAY_SIZE(ir_codes_avermedia_cardbus), | ||
239 | }; | ||
240 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus_table); | ||
241 | |||
242 | /* Attila Kondoros <attila.kondoros@chello.hu> */ | ||
243 | static struct ir_scancode ir_codes_apac_viewcomp[] = { | ||
244 | |||
245 | { 0x01, KEY_1 }, | ||
246 | { 0x02, KEY_2 }, | ||
247 | { 0x03, KEY_3 }, | ||
248 | { 0x04, KEY_4 }, | ||
249 | { 0x05, KEY_5 }, | ||
250 | { 0x06, KEY_6 }, | ||
251 | { 0x07, KEY_7 }, | ||
252 | { 0x08, KEY_8 }, | ||
253 | { 0x09, KEY_9 }, | ||
254 | { 0x00, KEY_0 }, | ||
255 | { 0x17, KEY_LAST }, /* +100 */ | ||
256 | { 0x0a, KEY_LIST }, /* recall */ | ||
257 | |||
258 | |||
259 | { 0x1c, KEY_TUNER }, /* TV/FM */ | ||
260 | { 0x15, KEY_SEARCH }, /* scan */ | ||
261 | { 0x12, KEY_POWER }, /* power */ | ||
262 | { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ | ||
263 | { 0x1b, KEY_VOLUMEUP }, /* vol down */ | ||
264 | { 0x1e, KEY_CHANNELDOWN }, /* chn up */ | ||
265 | { 0x1a, KEY_CHANNELUP }, /* chn down */ | ||
266 | |||
267 | { 0x11, KEY_VIDEO }, /* video */ | ||
268 | { 0x0f, KEY_ZOOM }, /* full screen */ | ||
269 | { 0x13, KEY_MUTE }, /* mute/unmute */ | ||
270 | { 0x10, KEY_TEXT }, /* min */ | ||
271 | |||
272 | { 0x0d, KEY_STOP }, /* freeze */ | ||
273 | { 0x0e, KEY_RECORD }, /* record */ | ||
274 | { 0x1d, KEY_PLAYPAUSE }, /* stop */ | ||
275 | { 0x19, KEY_PLAY }, /* play */ | ||
276 | |||
277 | { 0x16, KEY_GOTO }, /* osd */ | ||
278 | { 0x14, KEY_REFRESH }, /* default */ | ||
279 | { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ | ||
280 | { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ | ||
281 | }; | ||
282 | |||
283 | struct ir_scancode_table ir_codes_apac_viewcomp_table = { | ||
284 | .scan = ir_codes_apac_viewcomp, | ||
285 | .size = ARRAY_SIZE(ir_codes_apac_viewcomp), | ||
286 | }; | ||
287 | EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp_table); | ||
288 | |||
289 | /* ---------------------------------------------------------------------- */ | ||
290 | |||
291 | static struct ir_scancode ir_codes_pixelview[] = { | ||
292 | |||
293 | { 0x1e, KEY_POWER }, /* power */ | ||
294 | { 0x07, KEY_MEDIA }, /* source */ | ||
295 | { 0x1c, KEY_SEARCH }, /* scan */ | ||
296 | |||
297 | |||
298 | { 0x03, KEY_TUNER }, /* TV/FM */ | ||
299 | |||
300 | { 0x00, KEY_RECORD }, | ||
301 | { 0x08, KEY_STOP }, | ||
302 | { 0x11, KEY_PLAY }, | ||
303 | |||
304 | { 0x1a, KEY_PLAYPAUSE }, /* freeze */ | ||
305 | { 0x19, KEY_ZOOM }, /* zoom */ | ||
306 | { 0x0f, KEY_TEXT }, /* min */ | ||
307 | |||
308 | { 0x01, KEY_1 }, | ||
309 | { 0x0b, KEY_2 }, | ||
310 | { 0x1b, KEY_3 }, | ||
311 | { 0x05, KEY_4 }, | ||
312 | { 0x09, KEY_5 }, | ||
313 | { 0x15, KEY_6 }, | ||
314 | { 0x06, KEY_7 }, | ||
315 | { 0x0a, KEY_8 }, | ||
316 | { 0x12, KEY_9 }, | ||
317 | { 0x02, KEY_0 }, | ||
318 | { 0x10, KEY_LAST }, /* +100 */ | ||
319 | { 0x13, KEY_LIST }, /* recall */ | ||
320 | |||
321 | { 0x1f, KEY_CHANNELUP }, /* chn down */ | ||
322 | { 0x17, KEY_CHANNELDOWN }, /* chn up */ | ||
323 | { 0x16, KEY_VOLUMEUP }, /* vol down */ | ||
324 | { 0x14, KEY_VOLUMEDOWN }, /* vol up */ | ||
325 | |||
326 | { 0x04, KEY_KPMINUS }, /* <<< */ | ||
327 | { 0x0e, KEY_SETUP }, /* function */ | ||
328 | { 0x0c, KEY_KPPLUS }, /* >>> */ | ||
329 | |||
330 | { 0x0d, KEY_GOTO }, /* mts */ | ||
331 | { 0x1d, KEY_REFRESH }, /* reset */ | ||
332 | { 0x18, KEY_MUTE }, /* mute/unmute */ | ||
333 | }; | ||
334 | |||
335 | struct ir_scancode_table ir_codes_pixelview_table = { | ||
336 | .scan = ir_codes_pixelview, | ||
337 | .size = ARRAY_SIZE(ir_codes_pixelview), | ||
338 | }; | ||
339 | EXPORT_SYMBOL_GPL(ir_codes_pixelview_table); | ||
340 | |||
341 | /* | ||
342 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
343 | present on PV MPEG 8000GT | ||
344 | */ | ||
345 | static struct ir_scancode ir_codes_pixelview_new[] = { | ||
346 | { 0x3c, KEY_TIME }, /* Timeshift */ | ||
347 | { 0x12, KEY_POWER }, | ||
348 | |||
349 | { 0x3d, KEY_1 }, | ||
350 | { 0x38, KEY_2 }, | ||
351 | { 0x18, KEY_3 }, | ||
352 | { 0x35, KEY_4 }, | ||
353 | { 0x39, KEY_5 }, | ||
354 | { 0x15, KEY_6 }, | ||
355 | { 0x36, KEY_7 }, | ||
356 | { 0x3a, KEY_8 }, | ||
357 | { 0x1e, KEY_9 }, | ||
358 | { 0x3e, KEY_0 }, | ||
359 | |||
360 | { 0x1c, KEY_AGAIN }, /* LOOP */ | ||
361 | { 0x3f, KEY_MEDIA }, /* Source */ | ||
362 | { 0x1f, KEY_LAST }, /* +100 */ | ||
363 | { 0x1b, KEY_MUTE }, | ||
364 | |||
365 | { 0x17, KEY_CHANNELDOWN }, | ||
366 | { 0x16, KEY_CHANNELUP }, | ||
367 | { 0x10, KEY_VOLUMEUP }, | ||
368 | { 0x14, KEY_VOLUMEDOWN }, | ||
369 | { 0x13, KEY_ZOOM }, | ||
370 | |||
371 | { 0x19, KEY_CAMERA }, /* SNAPSHOT */ | ||
372 | { 0x1a, KEY_SEARCH }, /* scan */ | ||
373 | |||
374 | { 0x37, KEY_REWIND }, /* << */ | ||
375 | { 0x32, KEY_RECORD }, /* o (red) */ | ||
376 | { 0x33, KEY_FORWARD }, /* >> */ | ||
377 | { 0x11, KEY_STOP }, /* square */ | ||
378 | { 0x3b, KEY_PLAY }, /* > */ | ||
379 | { 0x30, KEY_PLAYPAUSE }, /* || */ | ||
380 | |||
381 | { 0x31, KEY_TV }, | ||
382 | { 0x34, KEY_RADIO }, | ||
383 | }; | ||
384 | |||
385 | struct ir_scancode_table ir_codes_pixelview_new_table = { | ||
386 | .scan = ir_codes_pixelview_new, | ||
387 | .size = ARRAY_SIZE(ir_codes_pixelview_new), | ||
388 | }; | ||
389 | EXPORT_SYMBOL_GPL(ir_codes_pixelview_new_table); | ||
390 | |||
391 | static struct ir_scancode ir_codes_nebula[] = { | ||
392 | { 0x00, KEY_0 }, | ||
393 | { 0x01, KEY_1 }, | ||
394 | { 0x02, KEY_2 }, | ||
395 | { 0x03, KEY_3 }, | ||
396 | { 0x04, KEY_4 }, | ||
397 | { 0x05, KEY_5 }, | ||
398 | { 0x06, KEY_6 }, | ||
399 | { 0x07, KEY_7 }, | ||
400 | { 0x08, KEY_8 }, | ||
401 | { 0x09, KEY_9 }, | ||
402 | { 0x0a, KEY_TV }, | ||
403 | { 0x0b, KEY_AUX }, | ||
404 | { 0x0c, KEY_DVD }, | ||
405 | { 0x0d, KEY_POWER }, | ||
406 | { 0x0e, KEY_MHP }, /* labelled 'Picture' */ | ||
407 | { 0x0f, KEY_AUDIO }, | ||
408 | { 0x10, KEY_INFO }, | ||
409 | { 0x11, KEY_F13 }, /* 16:9 */ | ||
410 | { 0x12, KEY_F14 }, /* 14:9 */ | ||
411 | { 0x13, KEY_EPG }, | ||
412 | { 0x14, KEY_EXIT }, | ||
413 | { 0x15, KEY_MENU }, | ||
414 | { 0x16, KEY_UP }, | ||
415 | { 0x17, KEY_DOWN }, | ||
416 | { 0x18, KEY_LEFT }, | ||
417 | { 0x19, KEY_RIGHT }, | ||
418 | { 0x1a, KEY_ENTER }, | ||
419 | { 0x1b, KEY_CHANNELUP }, | ||
420 | { 0x1c, KEY_CHANNELDOWN }, | ||
421 | { 0x1d, KEY_VOLUMEUP }, | ||
422 | { 0x1e, KEY_VOLUMEDOWN }, | ||
423 | { 0x1f, KEY_RED }, | ||
424 | { 0x20, KEY_GREEN }, | ||
425 | { 0x21, KEY_YELLOW }, | ||
426 | { 0x22, KEY_BLUE }, | ||
427 | { 0x23, KEY_SUBTITLE }, | ||
428 | { 0x24, KEY_F15 }, /* AD */ | ||
429 | { 0x25, KEY_TEXT }, | ||
430 | { 0x26, KEY_MUTE }, | ||
431 | { 0x27, KEY_REWIND }, | ||
432 | { 0x28, KEY_STOP }, | ||
433 | { 0x29, KEY_PLAY }, | ||
434 | { 0x2a, KEY_FASTFORWARD }, | ||
435 | { 0x2b, KEY_F16 }, /* chapter */ | ||
436 | { 0x2c, KEY_PAUSE }, | ||
437 | { 0x2d, KEY_PLAY }, | ||
438 | { 0x2e, KEY_RECORD }, | ||
439 | { 0x2f, KEY_F17 }, /* picture in picture */ | ||
440 | { 0x30, KEY_KPPLUS }, /* zoom in */ | ||
441 | { 0x31, KEY_KPMINUS }, /* zoom out */ | ||
442 | { 0x32, KEY_F18 }, /* capture */ | ||
443 | { 0x33, KEY_F19 }, /* web */ | ||
444 | { 0x34, KEY_EMAIL }, | ||
445 | { 0x35, KEY_PHONE }, | ||
446 | { 0x36, KEY_PC }, | ||
447 | }; | ||
448 | |||
449 | struct ir_scancode_table ir_codes_nebula_table = { | ||
450 | .scan = ir_codes_nebula, | ||
451 | .size = ARRAY_SIZE(ir_codes_nebula), | ||
452 | }; | ||
453 | EXPORT_SYMBOL_GPL(ir_codes_nebula_table); | ||
454 | |||
455 | /* DigitalNow DNTV Live DVB-T Remote */ | ||
456 | static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { | ||
457 | { 0x00, KEY_ESC }, /* 'go up a level?' */ | ||
458 | /* Keys 0 to 9 */ | ||
459 | { 0x0a, KEY_0 }, | ||
460 | { 0x01, KEY_1 }, | ||
461 | { 0x02, KEY_2 }, | ||
462 | { 0x03, KEY_3 }, | ||
463 | { 0x04, KEY_4 }, | ||
464 | { 0x05, KEY_5 }, | ||
465 | { 0x06, KEY_6 }, | ||
466 | { 0x07, KEY_7 }, | ||
467 | { 0x08, KEY_8 }, | ||
468 | { 0x09, KEY_9 }, | ||
469 | |||
470 | { 0x0b, KEY_TUNER }, /* tv/fm */ | ||
471 | { 0x0c, KEY_SEARCH }, /* scan */ | ||
472 | { 0x0d, KEY_STOP }, | ||
473 | { 0x0e, KEY_PAUSE }, | ||
474 | { 0x0f, KEY_LIST }, /* source */ | ||
475 | |||
476 | { 0x10, KEY_MUTE }, | ||
477 | { 0x11, KEY_REWIND }, /* backward << */ | ||
478 | { 0x12, KEY_POWER }, | ||
479 | { 0x13, KEY_CAMERA }, /* snap */ | ||
480 | { 0x14, KEY_AUDIO }, /* stereo */ | ||
481 | { 0x15, KEY_CLEAR }, /* reset */ | ||
482 | { 0x16, KEY_PLAY }, | ||
483 | { 0x17, KEY_ENTER }, | ||
484 | { 0x18, KEY_ZOOM }, /* full screen */ | ||
485 | { 0x19, KEY_FASTFORWARD }, /* forward >> */ | ||
486 | { 0x1a, KEY_CHANNELUP }, | ||
487 | { 0x1b, KEY_VOLUMEUP }, | ||
488 | { 0x1c, KEY_INFO }, /* preview */ | ||
489 | { 0x1d, KEY_RECORD }, /* record */ | ||
490 | { 0x1e, KEY_CHANNELDOWN }, | ||
491 | { 0x1f, KEY_VOLUMEDOWN }, | ||
492 | }; | ||
493 | |||
494 | struct ir_scancode_table ir_codes_dntv_live_dvb_t_table = { | ||
495 | .scan = ir_codes_dntv_live_dvb_t, | ||
496 | .size = ARRAY_SIZE(ir_codes_dntv_live_dvb_t), | ||
497 | }; | ||
498 | EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t_table); | ||
499 | |||
500 | /* ---------------------------------------------------------------------- */ | ||
501 | |||
502 | /* IO-DATA BCTV7E Remote */ | ||
503 | static struct ir_scancode ir_codes_iodata_bctv7e[] = { | ||
504 | { 0x40, KEY_TV }, | ||
505 | { 0x20, KEY_RADIO }, /* FM */ | ||
506 | { 0x60, KEY_EPG }, | ||
507 | { 0x00, KEY_POWER }, | ||
508 | |||
509 | /* Keys 0 to 9 */ | ||
510 | { 0x44, KEY_0 }, /* 10 */ | ||
511 | { 0x50, KEY_1 }, | ||
512 | { 0x30, KEY_2 }, | ||
513 | { 0x70, KEY_3 }, | ||
514 | { 0x48, KEY_4 }, | ||
515 | { 0x28, KEY_5 }, | ||
516 | { 0x68, KEY_6 }, | ||
517 | { 0x58, KEY_7 }, | ||
518 | { 0x38, KEY_8 }, | ||
519 | { 0x78, KEY_9 }, | ||
520 | |||
521 | { 0x10, KEY_L }, /* Live */ | ||
522 | { 0x08, KEY_TIME }, /* Time Shift */ | ||
523 | |||
524 | { 0x18, KEY_PLAYPAUSE }, /* Play */ | ||
525 | |||
526 | { 0x24, KEY_ENTER }, /* 11 */ | ||
527 | { 0x64, KEY_ESC }, /* 12 */ | ||
528 | { 0x04, KEY_M }, /* Multi */ | ||
529 | |||
530 | { 0x54, KEY_VIDEO }, | ||
531 | { 0x34, KEY_CHANNELUP }, | ||
532 | { 0x74, KEY_VOLUMEUP }, | ||
533 | { 0x14, KEY_MUTE }, | ||
534 | |||
535 | { 0x4c, KEY_VCR }, /* SVIDEO */ | ||
536 | { 0x2c, KEY_CHANNELDOWN }, | ||
537 | { 0x6c, KEY_VOLUMEDOWN }, | ||
538 | { 0x0c, KEY_ZOOM }, | ||
539 | |||
540 | { 0x5c, KEY_PAUSE }, | ||
541 | { 0x3c, KEY_RED }, /* || (red) */ | ||
542 | { 0x7c, KEY_RECORD }, /* recording */ | ||
543 | { 0x1c, KEY_STOP }, | ||
544 | |||
545 | { 0x41, KEY_REWIND }, /* backward << */ | ||
546 | { 0x21, KEY_PLAY }, | ||
547 | { 0x61, KEY_FASTFORWARD }, /* forward >> */ | ||
548 | { 0x01, KEY_NEXT }, /* skip >| */ | ||
549 | }; | ||
550 | |||
551 | struct ir_scancode_table ir_codes_iodata_bctv7e_table = { | ||
552 | .scan = ir_codes_iodata_bctv7e, | ||
553 | .size = ARRAY_SIZE(ir_codes_iodata_bctv7e), | ||
554 | }; | ||
555 | EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e_table); | ||
556 | |||
557 | /* ---------------------------------------------------------------------- */ | ||
558 | |||
559 | /* ADS Tech Instant TV DVB-T PCI Remote */ | ||
560 | static struct ir_scancode ir_codes_adstech_dvb_t_pci[] = { | ||
561 | /* Keys 0 to 9 */ | ||
562 | { 0x4d, KEY_0 }, | ||
563 | { 0x57, KEY_1 }, | ||
564 | { 0x4f, KEY_2 }, | ||
565 | { 0x53, KEY_3 }, | ||
566 | { 0x56, KEY_4 }, | ||
567 | { 0x4e, KEY_5 }, | ||
568 | { 0x5e, KEY_6 }, | ||
569 | { 0x54, KEY_7 }, | ||
570 | { 0x4c, KEY_8 }, | ||
571 | { 0x5c, KEY_9 }, | ||
572 | |||
573 | { 0x5b, KEY_POWER }, | ||
574 | { 0x5f, KEY_MUTE }, | ||
575 | { 0x55, KEY_GOTO }, | ||
576 | { 0x5d, KEY_SEARCH }, | ||
577 | { 0x17, KEY_EPG }, /* Guide */ | ||
578 | { 0x1f, KEY_MENU }, | ||
579 | { 0x0f, KEY_UP }, | ||
580 | { 0x46, KEY_DOWN }, | ||
581 | { 0x16, KEY_LEFT }, | ||
582 | { 0x1e, KEY_RIGHT }, | ||
583 | { 0x0e, KEY_SELECT }, /* Enter */ | ||
584 | { 0x5a, KEY_INFO }, | ||
585 | { 0x52, KEY_EXIT }, | ||
586 | { 0x59, KEY_PREVIOUS }, | ||
587 | { 0x51, KEY_NEXT }, | ||
588 | { 0x58, KEY_REWIND }, | ||
589 | { 0x50, KEY_FORWARD }, | ||
590 | { 0x44, KEY_PLAYPAUSE }, | ||
591 | { 0x07, KEY_STOP }, | ||
592 | { 0x1b, KEY_RECORD }, | ||
593 | { 0x13, KEY_TUNER }, /* Live */ | ||
594 | { 0x0a, KEY_A }, | ||
595 | { 0x12, KEY_B }, | ||
596 | { 0x03, KEY_PROG1 }, /* 1 */ | ||
597 | { 0x01, KEY_PROG2 }, /* 2 */ | ||
598 | { 0x00, KEY_PROG3 }, /* 3 */ | ||
599 | { 0x06, KEY_DVD }, | ||
600 | { 0x48, KEY_AUX }, /* Photo */ | ||
601 | { 0x40, KEY_VIDEO }, | ||
602 | { 0x19, KEY_AUDIO }, /* Music */ | ||
603 | { 0x0b, KEY_CHANNELUP }, | ||
604 | { 0x08, KEY_CHANNELDOWN }, | ||
605 | { 0x15, KEY_VOLUMEUP }, | ||
606 | { 0x1c, KEY_VOLUMEDOWN }, | ||
607 | }; | ||
608 | |||
609 | struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table = { | ||
610 | .scan = ir_codes_adstech_dvb_t_pci, | ||
611 | .size = ARRAY_SIZE(ir_codes_adstech_dvb_t_pci), | ||
612 | }; | ||
613 | EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci_table); | ||
614 | |||
615 | /* ---------------------------------------------------------------------- */ | ||
616 | |||
617 | /* MSI TV@nywhere MASTER remote */ | ||
618 | |||
619 | static struct ir_scancode ir_codes_msi_tvanywhere[] = { | ||
620 | /* Keys 0 to 9 */ | ||
621 | { 0x00, KEY_0 }, | ||
622 | { 0x01, KEY_1 }, | ||
623 | { 0x02, KEY_2 }, | ||
624 | { 0x03, KEY_3 }, | ||
625 | { 0x04, KEY_4 }, | ||
626 | { 0x05, KEY_5 }, | ||
627 | { 0x06, KEY_6 }, | ||
628 | { 0x07, KEY_7 }, | ||
629 | { 0x08, KEY_8 }, | ||
630 | { 0x09, KEY_9 }, | ||
631 | |||
632 | { 0x0c, KEY_MUTE }, | ||
633 | { 0x0f, KEY_SCREEN }, /* Full Screen */ | ||
634 | { 0x10, KEY_FN }, /* Funtion */ | ||
635 | { 0x11, KEY_TIME }, /* Time shift */ | ||
636 | { 0x12, KEY_POWER }, | ||
637 | { 0x13, KEY_MEDIA }, /* MTS */ | ||
638 | { 0x14, KEY_SLOW }, | ||
639 | { 0x16, KEY_REWIND }, /* backward << */ | ||
640 | { 0x17, KEY_ENTER }, /* Return */ | ||
641 | { 0x18, KEY_FASTFORWARD }, /* forward >> */ | ||
642 | { 0x1a, KEY_CHANNELUP }, | ||
643 | { 0x1b, KEY_VOLUMEUP }, | ||
644 | { 0x1e, KEY_CHANNELDOWN }, | ||
645 | { 0x1f, KEY_VOLUMEDOWN }, | ||
646 | }; | ||
647 | |||
648 | struct ir_scancode_table ir_codes_msi_tvanywhere_table = { | ||
649 | .scan = ir_codes_msi_tvanywhere, | ||
650 | .size = ARRAY_SIZE(ir_codes_msi_tvanywhere), | ||
651 | }; | ||
652 | EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_table); | ||
653 | |||
654 | /* ---------------------------------------------------------------------- */ | ||
655 | |||
656 | /* | ||
657 | Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card | ||
658 | is marked "KS003". The controller is I2C at address 0x30, but does not seem | ||
659 | to respond to probes until a read is performed from a valid device. | ||
660 | I don't know why... | ||
661 | |||
662 | Note: This remote may be of similar or identical design to the | ||
663 | Pixelview remote (?). The raw codes and duplicate button codes | ||
664 | appear to be the same. | ||
665 | |||
666 | Henry Wong <henry@stuffedcow.net> | ||
667 | Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com> | ||
668 | |||
669 | */ | ||
670 | |||
671 | static struct ir_scancode ir_codes_msi_tvanywhere_plus[] = { | ||
672 | |||
673 | /* ---- Remote Button Layout ---- | ||
674 | |||
675 | POWER SOURCE SCAN MUTE | ||
676 | TV/FM 1 2 3 | ||
677 | |> 4 5 6 | ||
678 | <| 7 8 9 | ||
679 | ^^UP 0 + RECALL | ||
680 | vvDN RECORD STOP PLAY | ||
681 | |||
682 | MINIMIZE ZOOM | ||
683 | |||
684 | CH+ | ||
685 | VOL- VOL+ | ||
686 | CH- | ||
687 | |||
688 | SNAPSHOT MTS | ||
689 | |||
690 | << FUNC >> RESET | ||
691 | */ | ||
692 | |||
693 | { 0x01, KEY_1 }, /* 1 */ | ||
694 | { 0x0b, KEY_2 }, /* 2 */ | ||
695 | { 0x1b, KEY_3 }, /* 3 */ | ||
696 | { 0x05, KEY_4 }, /* 4 */ | ||
697 | { 0x09, KEY_5 }, /* 5 */ | ||
698 | { 0x15, KEY_6 }, /* 6 */ | ||
699 | { 0x06, KEY_7 }, /* 7 */ | ||
700 | { 0x0a, KEY_8 }, /* 8 */ | ||
701 | { 0x12, KEY_9 }, /* 9 */ | ||
702 | { 0x02, KEY_0 }, /* 0 */ | ||
703 | { 0x10, KEY_KPPLUS }, /* + */ | ||
704 | { 0x13, KEY_AGAIN }, /* Recall */ | ||
705 | |||
706 | { 0x1e, KEY_POWER }, /* Power */ | ||
707 | { 0x07, KEY_TUNER }, /* Source */ | ||
708 | { 0x1c, KEY_SEARCH }, /* Scan */ | ||
709 | { 0x18, KEY_MUTE }, /* Mute */ | ||
710 | |||
711 | { 0x03, KEY_RADIO }, /* TV/FM */ | ||
712 | /* The next four keys are duplicates that appear to send the | ||
713 | same IR code as Ch+, Ch-, >>, and << . The raw code assigned | ||
714 | to them is the actual code + 0x20 - they will never be | ||
715 | detected as such unless some way is discovered to distinguish | ||
716 | these buttons from those that have the same code. */ | ||
717 | { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ | ||
718 | { 0x37, KEY_LEFT }, /* <| and Ch- */ | ||
719 | { 0x2c, KEY_UP }, /* ^^Up and >> */ | ||
720 | { 0x24, KEY_DOWN }, /* vvDn and << */ | ||
721 | |||
722 | { 0x00, KEY_RECORD }, /* Record */ | ||
723 | { 0x08, KEY_STOP }, /* Stop */ | ||
724 | { 0x11, KEY_PLAY }, /* Play */ | ||
725 | |||
726 | { 0x0f, KEY_CLOSE }, /* Minimize */ | ||
727 | { 0x19, KEY_ZOOM }, /* Zoom */ | ||
728 | { 0x1a, KEY_CAMERA }, /* Snapshot */ | ||
729 | { 0x0d, KEY_LANGUAGE }, /* MTS */ | ||
730 | |||
731 | { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ | ||
732 | { 0x16, KEY_VOLUMEUP }, /* Vol+ */ | ||
733 | { 0x17, KEY_CHANNELDOWN }, /* Ch- */ | ||
734 | { 0x1f, KEY_CHANNELUP }, /* Ch+ */ | ||
735 | |||
736 | { 0x04, KEY_REWIND }, /* << */ | ||
737 | { 0x0e, KEY_MENU }, /* Function */ | ||
738 | { 0x0c, KEY_FASTFORWARD }, /* >> */ | ||
739 | { 0x1d, KEY_RESTART }, /* Reset */ | ||
740 | }; | ||
741 | |||
742 | struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table = { | ||
743 | .scan = ir_codes_msi_tvanywhere_plus, | ||
744 | .size = ARRAY_SIZE(ir_codes_msi_tvanywhere_plus), | ||
745 | }; | ||
746 | EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus_table); | ||
747 | |||
748 | /* ---------------------------------------------------------------------- */ | ||
749 | |||
750 | /* Cinergy 1400 DVB-T */ | ||
751 | static struct ir_scancode ir_codes_cinergy_1400[] = { | ||
752 | { 0x01, KEY_POWER }, | ||
753 | { 0x02, KEY_1 }, | ||
754 | { 0x03, KEY_2 }, | ||
755 | { 0x04, KEY_3 }, | ||
756 | { 0x05, KEY_4 }, | ||
757 | { 0x06, KEY_5 }, | ||
758 | { 0x07, KEY_6 }, | ||
759 | { 0x08, KEY_7 }, | ||
760 | { 0x09, KEY_8 }, | ||
761 | { 0x0a, KEY_9 }, | ||
762 | { 0x0c, KEY_0 }, | ||
763 | |||
764 | { 0x0b, KEY_VIDEO }, | ||
765 | { 0x0d, KEY_REFRESH }, | ||
766 | { 0x0e, KEY_SELECT }, | ||
767 | { 0x0f, KEY_EPG }, | ||
768 | { 0x10, KEY_UP }, | ||
769 | { 0x11, KEY_LEFT }, | ||
770 | { 0x12, KEY_OK }, | ||
771 | { 0x13, KEY_RIGHT }, | ||
772 | { 0x14, KEY_DOWN }, | ||
773 | { 0x15, KEY_TEXT }, | ||
774 | { 0x16, KEY_INFO }, | ||
775 | |||
776 | { 0x17, KEY_RED }, | ||
777 | { 0x18, KEY_GREEN }, | ||
778 | { 0x19, KEY_YELLOW }, | ||
779 | { 0x1a, KEY_BLUE }, | ||
780 | |||
781 | { 0x1b, KEY_CHANNELUP }, | ||
782 | { 0x1c, KEY_VOLUMEUP }, | ||
783 | { 0x1d, KEY_MUTE }, | ||
784 | { 0x1e, KEY_VOLUMEDOWN }, | ||
785 | { 0x1f, KEY_CHANNELDOWN }, | ||
786 | |||
787 | { 0x40, KEY_PAUSE }, | ||
788 | { 0x4c, KEY_PLAY }, | ||
789 | { 0x58, KEY_RECORD }, | ||
790 | { 0x54, KEY_PREVIOUS }, | ||
791 | { 0x48, KEY_STOP }, | ||
792 | { 0x5c, KEY_NEXT }, | ||
793 | }; | ||
794 | |||
795 | struct ir_scancode_table ir_codes_cinergy_1400_table = { | ||
796 | .scan = ir_codes_cinergy_1400, | ||
797 | .size = ARRAY_SIZE(ir_codes_cinergy_1400), | ||
798 | }; | ||
799 | EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400_table); | ||
800 | |||
801 | /* ---------------------------------------------------------------------- */ | ||
802 | |||
803 | /* AVERTV STUDIO 303 Remote */ | ||
804 | static struct ir_scancode ir_codes_avertv_303[] = { | ||
805 | { 0x2a, KEY_1 }, | ||
806 | { 0x32, KEY_2 }, | ||
807 | { 0x3a, KEY_3 }, | ||
808 | { 0x4a, KEY_4 }, | ||
809 | { 0x52, KEY_5 }, | ||
810 | { 0x5a, KEY_6 }, | ||
811 | { 0x6a, KEY_7 }, | ||
812 | { 0x72, KEY_8 }, | ||
813 | { 0x7a, KEY_9 }, | ||
814 | { 0x0e, KEY_0 }, | ||
815 | |||
816 | { 0x02, KEY_POWER }, | ||
817 | { 0x22, KEY_VIDEO }, | ||
818 | { 0x42, KEY_AUDIO }, | ||
819 | { 0x62, KEY_ZOOM }, | ||
820 | { 0x0a, KEY_TV }, | ||
821 | { 0x12, KEY_CD }, | ||
822 | { 0x1a, KEY_TEXT }, | ||
823 | |||
824 | { 0x16, KEY_SUBTITLE }, | ||
825 | { 0x1e, KEY_REWIND }, | ||
826 | { 0x06, KEY_PRINT }, | ||
827 | |||
828 | { 0x2e, KEY_SEARCH }, | ||
829 | { 0x36, KEY_SLEEP }, | ||
830 | { 0x3e, KEY_SHUFFLE }, | ||
831 | { 0x26, KEY_MUTE }, | ||
832 | |||
833 | { 0x4e, KEY_RECORD }, | ||
834 | { 0x56, KEY_PAUSE }, | ||
835 | { 0x5e, KEY_STOP }, | ||
836 | { 0x46, KEY_PLAY }, | ||
837 | |||
838 | { 0x6e, KEY_RED }, | ||
839 | { 0x0b, KEY_GREEN }, | ||
840 | { 0x66, KEY_YELLOW }, | ||
841 | { 0x03, KEY_BLUE }, | ||
842 | |||
843 | { 0x76, KEY_LEFT }, | ||
844 | { 0x7e, KEY_RIGHT }, | ||
845 | { 0x13, KEY_DOWN }, | ||
846 | { 0x1b, KEY_UP }, | ||
847 | }; | ||
848 | |||
849 | struct ir_scancode_table ir_codes_avertv_303_table = { | ||
850 | .scan = ir_codes_avertv_303, | ||
851 | .size = ARRAY_SIZE(ir_codes_avertv_303), | ||
852 | }; | ||
853 | EXPORT_SYMBOL_GPL(ir_codes_avertv_303_table); | ||
854 | |||
855 | /* ---------------------------------------------------------------------- */ | ||
856 | |||
857 | /* DigitalNow DNTV Live! DVB-T Pro Remote */ | ||
858 | static struct ir_scancode ir_codes_dntv_live_dvbt_pro[] = { | ||
859 | { 0x16, KEY_POWER }, | ||
860 | { 0x5b, KEY_HOME }, | ||
861 | |||
862 | { 0x55, KEY_TV }, /* live tv */ | ||
863 | { 0x58, KEY_TUNER }, /* digital Radio */ | ||
864 | { 0x5a, KEY_RADIO }, /* FM radio */ | ||
865 | { 0x59, KEY_DVD }, /* dvd menu */ | ||
866 | { 0x03, KEY_1 }, | ||
867 | { 0x01, KEY_2 }, | ||
868 | { 0x06, KEY_3 }, | ||
869 | { 0x09, KEY_4 }, | ||
870 | { 0x1d, KEY_5 }, | ||
871 | { 0x1f, KEY_6 }, | ||
872 | { 0x0d, KEY_7 }, | ||
873 | { 0x19, KEY_8 }, | ||
874 | { 0x1b, KEY_9 }, | ||
875 | { 0x0c, KEY_CANCEL }, | ||
876 | { 0x15, KEY_0 }, | ||
877 | { 0x4a, KEY_CLEAR }, | ||
878 | { 0x13, KEY_BACK }, | ||
879 | { 0x00, KEY_TAB }, | ||
880 | { 0x4b, KEY_UP }, | ||
881 | { 0x4e, KEY_LEFT }, | ||
882 | { 0x4f, KEY_OK }, | ||
883 | { 0x52, KEY_RIGHT }, | ||
884 | { 0x51, KEY_DOWN }, | ||
885 | { 0x1e, KEY_VOLUMEUP }, | ||
886 | { 0x0a, KEY_VOLUMEDOWN }, | ||
887 | { 0x02, KEY_CHANNELDOWN }, | ||
888 | { 0x05, KEY_CHANNELUP }, | ||
889 | { 0x11, KEY_RECORD }, | ||
890 | { 0x14, KEY_PLAY }, | ||
891 | { 0x4c, KEY_PAUSE }, | ||
892 | { 0x1a, KEY_STOP }, | ||
893 | { 0x40, KEY_REWIND }, | ||
894 | { 0x12, KEY_FASTFORWARD }, | ||
895 | { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ | ||
896 | { 0x42, KEY_NEXTSONG }, /* skip >| */ | ||
897 | { 0x54, KEY_CAMERA }, /* capture */ | ||
898 | { 0x50, KEY_LANGUAGE }, /* sap */ | ||
899 | { 0x47, KEY_TV2 }, /* pip */ | ||
900 | { 0x4d, KEY_SCREEN }, | ||
901 | { 0x43, KEY_SUBTITLE }, | ||
902 | { 0x10, KEY_MUTE }, | ||
903 | { 0x49, KEY_AUDIO }, /* l/r */ | ||
904 | { 0x07, KEY_SLEEP }, | ||
905 | { 0x08, KEY_VIDEO }, /* a/v */ | ||
906 | { 0x0e, KEY_PREVIOUS }, /* recall */ | ||
907 | { 0x45, KEY_ZOOM }, /* zoom + */ | ||
908 | { 0x46, KEY_ANGLE }, /* zoom - */ | ||
909 | { 0x56, KEY_RED }, | ||
910 | { 0x57, KEY_GREEN }, | ||
911 | { 0x5c, KEY_YELLOW }, | ||
912 | { 0x5d, KEY_BLUE }, | ||
913 | }; | ||
914 | |||
915 | struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table = { | ||
916 | .scan = ir_codes_dntv_live_dvbt_pro, | ||
917 | .size = ARRAY_SIZE(ir_codes_dntv_live_dvbt_pro), | ||
918 | }; | ||
919 | EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro_table); | ||
920 | |||
921 | static struct ir_scancode ir_codes_em_terratec[] = { | ||
922 | { 0x01, KEY_CHANNEL }, | ||
923 | { 0x02, KEY_SELECT }, | ||
924 | { 0x03, KEY_MUTE }, | ||
925 | { 0x04, KEY_POWER }, | ||
926 | { 0x05, KEY_1 }, | ||
927 | { 0x06, KEY_2 }, | ||
928 | { 0x07, KEY_3 }, | ||
929 | { 0x08, KEY_CHANNELUP }, | ||
930 | { 0x09, KEY_4 }, | ||
931 | { 0x0a, KEY_5 }, | ||
932 | { 0x0b, KEY_6 }, | ||
933 | { 0x0c, KEY_CHANNELDOWN }, | ||
934 | { 0x0d, KEY_7 }, | ||
935 | { 0x0e, KEY_8 }, | ||
936 | { 0x0f, KEY_9 }, | ||
937 | { 0x10, KEY_VOLUMEUP }, | ||
938 | { 0x11, KEY_0 }, | ||
939 | { 0x12, KEY_MENU }, | ||
940 | { 0x13, KEY_PRINT }, | ||
941 | { 0x14, KEY_VOLUMEDOWN }, | ||
942 | { 0x16, KEY_PAUSE }, | ||
943 | { 0x18, KEY_RECORD }, | ||
944 | { 0x19, KEY_REWIND }, | ||
945 | { 0x1a, KEY_PLAY }, | ||
946 | { 0x1b, KEY_FORWARD }, | ||
947 | { 0x1c, KEY_BACKSPACE }, | ||
948 | { 0x1e, KEY_STOP }, | ||
949 | { 0x40, KEY_ZOOM }, | ||
950 | }; | ||
951 | |||
952 | struct ir_scancode_table ir_codes_em_terratec_table = { | ||
953 | .scan = ir_codes_em_terratec, | ||
954 | .size = ARRAY_SIZE(ir_codes_em_terratec), | ||
955 | }; | ||
956 | EXPORT_SYMBOL_GPL(ir_codes_em_terratec_table); | ||
957 | |||
958 | static struct ir_scancode ir_codes_pinnacle_grey[] = { | ||
959 | { 0x3a, KEY_0 }, | ||
960 | { 0x31, KEY_1 }, | ||
961 | { 0x32, KEY_2 }, | ||
962 | { 0x33, KEY_3 }, | ||
963 | { 0x34, KEY_4 }, | ||
964 | { 0x35, KEY_5 }, | ||
965 | { 0x36, KEY_6 }, | ||
966 | { 0x37, KEY_7 }, | ||
967 | { 0x38, KEY_8 }, | ||
968 | { 0x39, KEY_9 }, | ||
969 | |||
970 | { 0x2f, KEY_POWER }, | ||
971 | |||
972 | { 0x2e, KEY_P }, | ||
973 | { 0x1f, KEY_L }, | ||
974 | { 0x2b, KEY_I }, | ||
975 | |||
976 | { 0x2d, KEY_SCREEN }, | ||
977 | { 0x1e, KEY_ZOOM }, | ||
978 | { 0x1b, KEY_VOLUMEUP }, | ||
979 | { 0x0f, KEY_VOLUMEDOWN }, | ||
980 | { 0x17, KEY_CHANNELUP }, | ||
981 | { 0x1c, KEY_CHANNELDOWN }, | ||
982 | { 0x25, KEY_INFO }, | ||
983 | |||
984 | { 0x3c, KEY_MUTE }, | ||
985 | |||
986 | { 0x3d, KEY_LEFT }, | ||
987 | { 0x3b, KEY_RIGHT }, | ||
988 | |||
989 | { 0x3f, KEY_UP }, | ||
990 | { 0x3e, KEY_DOWN }, | ||
991 | { 0x1a, KEY_ENTER }, | ||
992 | |||
993 | { 0x1d, KEY_MENU }, | ||
994 | { 0x19, KEY_AGAIN }, | ||
995 | { 0x16, KEY_PREVIOUSSONG }, | ||
996 | { 0x13, KEY_NEXTSONG }, | ||
997 | { 0x15, KEY_PAUSE }, | ||
998 | { 0x0e, KEY_REWIND }, | ||
999 | { 0x0d, KEY_PLAY }, | ||
1000 | { 0x0b, KEY_STOP }, | ||
1001 | { 0x07, KEY_FORWARD }, | ||
1002 | { 0x27, KEY_RECORD }, | ||
1003 | { 0x26, KEY_TUNER }, | ||
1004 | { 0x29, KEY_TEXT }, | ||
1005 | { 0x2a, KEY_MEDIA }, | ||
1006 | { 0x18, KEY_EPG }, | ||
1007 | }; | ||
1008 | |||
1009 | struct ir_scancode_table ir_codes_pinnacle_grey_table = { | ||
1010 | .scan = ir_codes_pinnacle_grey, | ||
1011 | .size = ARRAY_SIZE(ir_codes_pinnacle_grey), | ||
1012 | }; | ||
1013 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey_table); | ||
1014 | |||
1015 | static struct ir_scancode ir_codes_flyvideo[] = { | ||
1016 | { 0x0f, KEY_0 }, | ||
1017 | { 0x03, KEY_1 }, | ||
1018 | { 0x04, KEY_2 }, | ||
1019 | { 0x05, KEY_3 }, | ||
1020 | { 0x07, KEY_4 }, | ||
1021 | { 0x08, KEY_5 }, | ||
1022 | { 0x09, KEY_6 }, | ||
1023 | { 0x0b, KEY_7 }, | ||
1024 | { 0x0c, KEY_8 }, | ||
1025 | { 0x0d, KEY_9 }, | ||
1026 | |||
1027 | { 0x0e, KEY_MODE }, /* Air/Cable */ | ||
1028 | { 0x11, KEY_VIDEO }, /* Video */ | ||
1029 | { 0x15, KEY_AUDIO }, /* Audio */ | ||
1030 | { 0x00, KEY_POWER }, /* Power */ | ||
1031 | { 0x18, KEY_TUNER }, /* AV Source */ | ||
1032 | { 0x02, KEY_ZOOM }, /* Fullscreen */ | ||
1033 | { 0x1a, KEY_LANGUAGE }, /* Stereo */ | ||
1034 | { 0x1b, KEY_MUTE }, /* Mute */ | ||
1035 | { 0x14, KEY_VOLUMEUP }, /* Volume + */ | ||
1036 | { 0x17, KEY_VOLUMEDOWN },/* Volume - */ | ||
1037 | { 0x12, KEY_CHANNELUP },/* Channel + */ | ||
1038 | { 0x13, KEY_CHANNELDOWN },/* Channel - */ | ||
1039 | { 0x06, KEY_AGAIN }, /* Recall */ | ||
1040 | { 0x10, KEY_ENTER }, /* Enter */ | ||
1041 | |||
1042 | { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ | ||
1043 | { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ | ||
1044 | { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ | ||
1045 | }; | ||
1046 | |||
1047 | struct ir_scancode_table ir_codes_flyvideo_table = { | ||
1048 | .scan = ir_codes_flyvideo, | ||
1049 | .size = ARRAY_SIZE(ir_codes_flyvideo), | ||
1050 | }; | ||
1051 | EXPORT_SYMBOL_GPL(ir_codes_flyvideo_table); | ||
1052 | |||
1053 | static struct ir_scancode ir_codes_flydvb[] = { | ||
1054 | { 0x01, KEY_ZOOM }, /* Full Screen */ | ||
1055 | { 0x00, KEY_POWER }, /* Power */ | ||
1056 | |||
1057 | { 0x03, KEY_1 }, | ||
1058 | { 0x04, KEY_2 }, | ||
1059 | { 0x05, KEY_3 }, | ||
1060 | { 0x07, KEY_4 }, | ||
1061 | { 0x08, KEY_5 }, | ||
1062 | { 0x09, KEY_6 }, | ||
1063 | { 0x0b, KEY_7 }, | ||
1064 | { 0x0c, KEY_8 }, | ||
1065 | { 0x0d, KEY_9 }, | ||
1066 | { 0x06, KEY_AGAIN }, /* Recall */ | ||
1067 | { 0x0f, KEY_0 }, | ||
1068 | { 0x10, KEY_MUTE }, /* Mute */ | ||
1069 | { 0x02, KEY_RADIO }, /* TV/Radio */ | ||
1070 | { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ | ||
1071 | |||
1072 | { 0x14, KEY_VOLUMEUP }, /* VOL+ */ | ||
1073 | { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ | ||
1074 | { 0x12, KEY_CHANNELUP }, /* CH+ */ | ||
1075 | { 0x13, KEY_CHANNELDOWN }, /* CH- */ | ||
1076 | { 0x1d, KEY_ENTER }, /* Enter */ | ||
1077 | |||
1078 | { 0x1a, KEY_MODE }, /* PIP */ | ||
1079 | { 0x18, KEY_TUNER }, /* Source */ | ||
1080 | |||
1081 | { 0x1e, KEY_RECORD }, /* Record/Pause */ | ||
1082 | { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ | ||
1083 | { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ | ||
1084 | { 0x19, KEY_BACK }, /* Rewind << */ | ||
1085 | { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ | ||
1086 | { 0x1f, KEY_FORWARD }, /* Forward >> */ | ||
1087 | { 0x16, KEY_PREVIOUS }, /* Back |<< */ | ||
1088 | { 0x11, KEY_STOP }, /* Stop */ | ||
1089 | { 0x0e, KEY_NEXT }, /* End >>| */ | ||
1090 | }; | ||
1091 | |||
1092 | struct ir_scancode_table ir_codes_flydvb_table = { | ||
1093 | .scan = ir_codes_flydvb, | ||
1094 | .size = ARRAY_SIZE(ir_codes_flydvb), | ||
1095 | }; | ||
1096 | EXPORT_SYMBOL_GPL(ir_codes_flydvb_table); | ||
1097 | |||
1098 | static struct ir_scancode ir_codes_cinergy[] = { | ||
1099 | { 0x00, KEY_0 }, | ||
1100 | { 0x01, KEY_1 }, | ||
1101 | { 0x02, KEY_2 }, | ||
1102 | { 0x03, KEY_3 }, | ||
1103 | { 0x04, KEY_4 }, | ||
1104 | { 0x05, KEY_5 }, | ||
1105 | { 0x06, KEY_6 }, | ||
1106 | { 0x07, KEY_7 }, | ||
1107 | { 0x08, KEY_8 }, | ||
1108 | { 0x09, KEY_9 }, | ||
1109 | |||
1110 | { 0x0a, KEY_POWER }, | ||
1111 | { 0x0b, KEY_PROG1 }, /* app */ | ||
1112 | { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ | ||
1113 | { 0x0d, KEY_CHANNELUP }, /* channel */ | ||
1114 | { 0x0e, KEY_CHANNELDOWN }, /* channel- */ | ||
1115 | { 0x0f, KEY_VOLUMEUP }, | ||
1116 | { 0x10, KEY_VOLUMEDOWN }, | ||
1117 | { 0x11, KEY_TUNER }, /* AV */ | ||
1118 | { 0x12, KEY_NUMLOCK }, /* -/-- */ | ||
1119 | { 0x13, KEY_AUDIO }, /* audio */ | ||
1120 | { 0x14, KEY_MUTE }, | ||
1121 | { 0x15, KEY_UP }, | ||
1122 | { 0x16, KEY_DOWN }, | ||
1123 | { 0x17, KEY_LEFT }, | ||
1124 | { 0x18, KEY_RIGHT }, | ||
1125 | { 0x19, BTN_LEFT, }, | ||
1126 | { 0x1a, BTN_RIGHT, }, | ||
1127 | { 0x1b, KEY_WWW }, /* text */ | ||
1128 | { 0x1c, KEY_REWIND }, | ||
1129 | { 0x1d, KEY_FORWARD }, | ||
1130 | { 0x1e, KEY_RECORD }, | ||
1131 | { 0x1f, KEY_PLAY }, | ||
1132 | { 0x20, KEY_PREVIOUSSONG }, | ||
1133 | { 0x21, KEY_NEXTSONG }, | ||
1134 | { 0x22, KEY_PAUSE }, | ||
1135 | { 0x23, KEY_STOP }, | ||
1136 | }; | ||
1137 | |||
1138 | struct ir_scancode_table ir_codes_cinergy_table = { | ||
1139 | .scan = ir_codes_cinergy, | ||
1140 | .size = ARRAY_SIZE(ir_codes_cinergy), | ||
1141 | }; | ||
1142 | EXPORT_SYMBOL_GPL(ir_codes_cinergy_table); | ||
1143 | |||
1144 | /* Alfons Geser <a.geser@cox.net> | ||
1145 | * updates from Job D. R. Borges <jobdrb@ig.com.br> */ | ||
1146 | static struct ir_scancode ir_codes_eztv[] = { | ||
1147 | { 0x12, KEY_POWER }, | ||
1148 | { 0x01, KEY_TV }, /* DVR */ | ||
1149 | { 0x15, KEY_DVD }, /* DVD */ | ||
1150 | { 0x17, KEY_AUDIO }, /* music */ | ||
1151 | /* DVR mode / DVD mode / music mode */ | ||
1152 | |||
1153 | { 0x1b, KEY_MUTE }, /* mute */ | ||
1154 | { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ | ||
1155 | { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ | ||
1156 | { 0x16, KEY_ZOOM }, /* full screen */ | ||
1157 | { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ | ||
1158 | { 0x1d, KEY_RESTART }, /* playback / angle / del */ | ||
1159 | { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ | ||
1160 | { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ | ||
1161 | |||
1162 | { 0x31, KEY_HELP }, /* help */ | ||
1163 | { 0x32, KEY_MODE }, /* num/memo */ | ||
1164 | { 0x33, KEY_ESC }, /* cancel */ | ||
1165 | |||
1166 | { 0x0c, KEY_UP }, /* up */ | ||
1167 | { 0x10, KEY_DOWN }, /* down */ | ||
1168 | { 0x08, KEY_LEFT }, /* left */ | ||
1169 | { 0x04, KEY_RIGHT }, /* right */ | ||
1170 | { 0x03, KEY_SELECT }, /* select */ | ||
1171 | |||
1172 | { 0x1f, KEY_REWIND }, /* rewind */ | ||
1173 | { 0x20, KEY_PLAYPAUSE },/* play/pause */ | ||
1174 | { 0x29, KEY_FORWARD }, /* forward */ | ||
1175 | { 0x14, KEY_AGAIN }, /* repeat */ | ||
1176 | { 0x2b, KEY_RECORD }, /* recording */ | ||
1177 | { 0x2c, KEY_STOP }, /* stop */ | ||
1178 | { 0x2d, KEY_PLAY }, /* play */ | ||
1179 | { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ | ||
1180 | |||
1181 | { 0x00, KEY_0 }, | ||
1182 | { 0x05, KEY_1 }, | ||
1183 | { 0x06, KEY_2 }, | ||
1184 | { 0x07, KEY_3 }, | ||
1185 | { 0x09, KEY_4 }, | ||
1186 | { 0x0a, KEY_5 }, | ||
1187 | { 0x0b, KEY_6 }, | ||
1188 | { 0x0d, KEY_7 }, | ||
1189 | { 0x0e, KEY_8 }, | ||
1190 | { 0x0f, KEY_9 }, | ||
1191 | |||
1192 | { 0x2a, KEY_VOLUMEUP }, | ||
1193 | { 0x11, KEY_VOLUMEDOWN }, | ||
1194 | { 0x18, KEY_CHANNELUP },/* CH.tracking up */ | ||
1195 | { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ | ||
1196 | |||
1197 | { 0x13, KEY_ENTER }, /* enter */ | ||
1198 | { 0x21, KEY_DOT }, /* . (decimal dot) */ | ||
1199 | }; | ||
1200 | |||
1201 | struct ir_scancode_table ir_codes_eztv_table = { | ||
1202 | .scan = ir_codes_eztv, | ||
1203 | .size = ARRAY_SIZE(ir_codes_eztv), | ||
1204 | }; | ||
1205 | EXPORT_SYMBOL_GPL(ir_codes_eztv_table); | ||
1206 | |||
1207 | /* Alex Hermann <gaaf@gmx.net> */ | ||
1208 | static struct ir_scancode ir_codes_avermedia[] = { | ||
1209 | { 0x28, KEY_1 }, | ||
1210 | { 0x18, KEY_2 }, | ||
1211 | { 0x38, KEY_3 }, | ||
1212 | { 0x24, KEY_4 }, | ||
1213 | { 0x14, KEY_5 }, | ||
1214 | { 0x34, KEY_6 }, | ||
1215 | { 0x2c, KEY_7 }, | ||
1216 | { 0x1c, KEY_8 }, | ||
1217 | { 0x3c, KEY_9 }, | ||
1218 | { 0x22, KEY_0 }, | ||
1219 | |||
1220 | { 0x20, KEY_TV }, /* TV/FM */ | ||
1221 | { 0x10, KEY_CD }, /* CD */ | ||
1222 | { 0x30, KEY_TEXT }, /* TELETEXT */ | ||
1223 | { 0x00, KEY_POWER }, /* POWER */ | ||
1224 | |||
1225 | { 0x08, KEY_VIDEO }, /* VIDEO */ | ||
1226 | { 0x04, KEY_AUDIO }, /* AUDIO */ | ||
1227 | { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ | ||
1228 | |||
1229 | { 0x12, KEY_SUBTITLE }, /* DISPLAY */ | ||
1230 | { 0x32, KEY_REWIND }, /* LOOP */ | ||
1231 | { 0x02, KEY_PRINT }, /* PREVIEW */ | ||
1232 | |||
1233 | { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ | ||
1234 | { 0x1a, KEY_SLEEP }, /* FREEZE */ | ||
1235 | { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ | ||
1236 | { 0x0a, KEY_MUTE }, /* MUTE */ | ||
1237 | |||
1238 | { 0x26, KEY_RECORD }, /* RECORD */ | ||
1239 | { 0x16, KEY_PAUSE }, /* PAUSE */ | ||
1240 | { 0x36, KEY_STOP }, /* STOP */ | ||
1241 | { 0x06, KEY_PLAY }, /* PLAY */ | ||
1242 | |||
1243 | { 0x2e, KEY_RED }, /* RED */ | ||
1244 | { 0x21, KEY_GREEN }, /* GREEN */ | ||
1245 | { 0x0e, KEY_YELLOW }, /* YELLOW */ | ||
1246 | { 0x01, KEY_BLUE }, /* BLUE */ | ||
1247 | |||
1248 | { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ | ||
1249 | { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ | ||
1250 | { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ | ||
1251 | { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ | ||
1252 | }; | ||
1253 | |||
1254 | struct ir_scancode_table ir_codes_avermedia_table = { | ||
1255 | .scan = ir_codes_avermedia, | ||
1256 | .size = ARRAY_SIZE(ir_codes_avermedia), | ||
1257 | }; | ||
1258 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_table); | ||
1259 | |||
1260 | static struct ir_scancode ir_codes_videomate_tv_pvr[] = { | ||
1261 | { 0x14, KEY_MUTE }, | ||
1262 | { 0x24, KEY_ZOOM }, | ||
1263 | |||
1264 | { 0x01, KEY_DVD }, | ||
1265 | { 0x23, KEY_RADIO }, | ||
1266 | { 0x00, KEY_TV }, | ||
1267 | |||
1268 | { 0x0a, KEY_REWIND }, | ||
1269 | { 0x08, KEY_PLAYPAUSE }, | ||
1270 | { 0x0f, KEY_FORWARD }, | ||
1271 | |||
1272 | { 0x02, KEY_PREVIOUS }, | ||
1273 | { 0x07, KEY_STOP }, | ||
1274 | { 0x06, KEY_NEXT }, | ||
1275 | |||
1276 | { 0x0c, KEY_UP }, | ||
1277 | { 0x0e, KEY_DOWN }, | ||
1278 | { 0x0b, KEY_LEFT }, | ||
1279 | { 0x0d, KEY_RIGHT }, | ||
1280 | { 0x11, KEY_OK }, | ||
1281 | |||
1282 | { 0x03, KEY_MENU }, | ||
1283 | { 0x09, KEY_SETUP }, | ||
1284 | { 0x05, KEY_VIDEO }, | ||
1285 | { 0x22, KEY_CHANNEL }, | ||
1286 | |||
1287 | { 0x12, KEY_VOLUMEUP }, | ||
1288 | { 0x15, KEY_VOLUMEDOWN }, | ||
1289 | { 0x10, KEY_CHANNELUP }, | ||
1290 | { 0x13, KEY_CHANNELDOWN }, | ||
1291 | |||
1292 | { 0x04, KEY_RECORD }, | ||
1293 | |||
1294 | { 0x16, KEY_1 }, | ||
1295 | { 0x17, KEY_2 }, | ||
1296 | { 0x18, KEY_3 }, | ||
1297 | { 0x19, KEY_4 }, | ||
1298 | { 0x1a, KEY_5 }, | ||
1299 | { 0x1b, KEY_6 }, | ||
1300 | { 0x1c, KEY_7 }, | ||
1301 | { 0x1d, KEY_8 }, | ||
1302 | { 0x1e, KEY_9 }, | ||
1303 | { 0x1f, KEY_0 }, | ||
1304 | |||
1305 | { 0x20, KEY_LANGUAGE }, | ||
1306 | { 0x21, KEY_SLEEP }, | ||
1307 | }; | ||
1308 | |||
1309 | struct ir_scancode_table ir_codes_videomate_tv_pvr_table = { | ||
1310 | .scan = ir_codes_videomate_tv_pvr, | ||
1311 | .size = ARRAY_SIZE(ir_codes_videomate_tv_pvr), | ||
1312 | }; | ||
1313 | EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr_table); | ||
1314 | |||
1315 | /* Michael Tokarev <mjt@tls.msk.ru> | ||
1316 | http://www.corpit.ru/mjt/beholdTV/remote_control.jpg | ||
1317 | keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at | ||
1318 | least, and probably other cards too. | ||
1319 | The "ascii-art picture" below (in comments, first row | ||
1320 | is the keycode in hex, and subsequent row(s) shows | ||
1321 | the button labels (several variants when appropriate) | ||
1322 | helps to descide which keycodes to assign to the buttons. | ||
1323 | */ | ||
1324 | static struct ir_scancode ir_codes_manli[] = { | ||
1325 | |||
1326 | /* 0x1c 0x12 * | ||
1327 | * FUNCTION POWER * | ||
1328 | * FM (|) * | ||
1329 | * */ | ||
1330 | { 0x1c, KEY_RADIO }, /*XXX*/ | ||
1331 | { 0x12, KEY_POWER }, | ||
1332 | |||
1333 | /* 0x01 0x02 0x03 * | ||
1334 | * 1 2 3 * | ||
1335 | * * | ||
1336 | * 0x04 0x05 0x06 * | ||
1337 | * 4 5 6 * | ||
1338 | * * | ||
1339 | * 0x07 0x08 0x09 * | ||
1340 | * 7 8 9 * | ||
1341 | * */ | ||
1342 | { 0x01, KEY_1 }, | ||
1343 | { 0x02, KEY_2 }, | ||
1344 | { 0x03, KEY_3 }, | ||
1345 | { 0x04, KEY_4 }, | ||
1346 | { 0x05, KEY_5 }, | ||
1347 | { 0x06, KEY_6 }, | ||
1348 | { 0x07, KEY_7 }, | ||
1349 | { 0x08, KEY_8 }, | ||
1350 | { 0x09, KEY_9 }, | ||
1351 | |||
1352 | /* 0x0a 0x00 0x17 * | ||
1353 | * RECALL 0 +100 * | ||
1354 | * PLUS * | ||
1355 | * */ | ||
1356 | { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ | ||
1357 | { 0x00, KEY_0 }, | ||
1358 | { 0x17, KEY_DIGITS }, /*XXX*/ | ||
1359 | |||
1360 | /* 0x14 0x10 * | ||
1361 | * MENU INFO * | ||
1362 | * OSD */ | ||
1363 | { 0x14, KEY_MENU }, | ||
1364 | { 0x10, KEY_INFO }, | ||
1365 | |||
1366 | /* 0x0b * | ||
1367 | * Up * | ||
1368 | * * | ||
1369 | * 0x18 0x16 0x0c * | ||
1370 | * Left Ok Right * | ||
1371 | * * | ||
1372 | * 0x015 * | ||
1373 | * Down * | ||
1374 | * */ | ||
1375 | { 0x0b, KEY_UP }, | ||
1376 | { 0x18, KEY_LEFT }, | ||
1377 | { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ | ||
1378 | { 0x0c, KEY_RIGHT }, | ||
1379 | { 0x15, KEY_DOWN }, | ||
1380 | |||
1381 | /* 0x11 0x0d * | ||
1382 | * TV/AV MODE * | ||
1383 | * SOURCE STEREO * | ||
1384 | * */ | ||
1385 | { 0x11, KEY_TV }, /*XXX*/ | ||
1386 | { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ | ||
1387 | |||
1388 | /* 0x0f 0x1b 0x1a * | ||
1389 | * AUDIO Vol+ Chan+ * | ||
1390 | * TIMESHIFT??? * | ||
1391 | * * | ||
1392 | * 0x0e 0x1f 0x1e * | ||
1393 | * SLEEP Vol- Chan- * | ||
1394 | * */ | ||
1395 | { 0x0f, KEY_AUDIO }, | ||
1396 | { 0x1b, KEY_VOLUMEUP }, | ||
1397 | { 0x1a, KEY_CHANNELUP }, | ||
1398 | { 0x0e, KEY_TIME }, | ||
1399 | { 0x1f, KEY_VOLUMEDOWN }, | ||
1400 | { 0x1e, KEY_CHANNELDOWN }, | ||
1401 | |||
1402 | /* 0x13 0x19 * | ||
1403 | * MUTE SNAPSHOT* | ||
1404 | * */ | ||
1405 | { 0x13, KEY_MUTE }, | ||
1406 | { 0x19, KEY_CAMERA }, | ||
1407 | |||
1408 | /* 0x1d unused ? */ | ||
1409 | }; | ||
1410 | |||
1411 | struct ir_scancode_table ir_codes_manli_table = { | ||
1412 | .scan = ir_codes_manli, | ||
1413 | .size = ARRAY_SIZE(ir_codes_manli), | ||
1414 | }; | ||
1415 | EXPORT_SYMBOL_GPL(ir_codes_manli_table); | ||
1416 | |||
1417 | /* Mike Baikov <mike@baikov.com> */ | ||
1418 | static struct ir_scancode ir_codes_gotview7135[] = { | ||
1419 | |||
1420 | { 0x11, KEY_POWER }, | ||
1421 | { 0x35, KEY_TV }, | ||
1422 | { 0x1b, KEY_0 }, | ||
1423 | { 0x29, KEY_1 }, | ||
1424 | { 0x19, KEY_2 }, | ||
1425 | { 0x39, KEY_3 }, | ||
1426 | { 0x1f, KEY_4 }, | ||
1427 | { 0x2c, KEY_5 }, | ||
1428 | { 0x21, KEY_6 }, | ||
1429 | { 0x24, KEY_7 }, | ||
1430 | { 0x18, KEY_8 }, | ||
1431 | { 0x2b, KEY_9 }, | ||
1432 | { 0x3b, KEY_AGAIN }, /* LOOP */ | ||
1433 | { 0x06, KEY_AUDIO }, | ||
1434 | { 0x31, KEY_PRINT }, /* PREVIEW */ | ||
1435 | { 0x3e, KEY_VIDEO }, | ||
1436 | { 0x10, KEY_CHANNELUP }, | ||
1437 | { 0x20, KEY_CHANNELDOWN }, | ||
1438 | { 0x0c, KEY_VOLUMEDOWN }, | ||
1439 | { 0x28, KEY_VOLUMEUP }, | ||
1440 | { 0x08, KEY_MUTE }, | ||
1441 | { 0x26, KEY_SEARCH }, /* SCAN */ | ||
1442 | { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ | ||
1443 | { 0x12, KEY_RECORD }, | ||
1444 | { 0x32, KEY_STOP }, | ||
1445 | { 0x3c, KEY_PLAY }, | ||
1446 | { 0x1d, KEY_REWIND }, | ||
1447 | { 0x2d, KEY_PAUSE }, | ||
1448 | { 0x0d, KEY_FORWARD }, | ||
1449 | { 0x05, KEY_ZOOM }, /*FULL*/ | ||
1450 | |||
1451 | { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ | ||
1452 | { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ | ||
1453 | { 0x1e, KEY_TIME }, /* TIMESHIFT */ | ||
1454 | { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ | ||
1455 | }; | ||
1456 | |||
1457 | struct ir_scancode_table ir_codes_gotview7135_table = { | ||
1458 | .scan = ir_codes_gotview7135, | ||
1459 | .size = ARRAY_SIZE(ir_codes_gotview7135), | ||
1460 | }; | ||
1461 | EXPORT_SYMBOL_GPL(ir_codes_gotview7135_table); | ||
1462 | |||
1463 | static struct ir_scancode ir_codes_purpletv[] = { | ||
1464 | { 0x03, KEY_POWER }, | ||
1465 | { 0x6f, KEY_MUTE }, | ||
1466 | { 0x10, KEY_BACKSPACE }, /* Recall */ | ||
1467 | |||
1468 | { 0x11, KEY_0 }, | ||
1469 | { 0x04, KEY_1 }, | ||
1470 | { 0x05, KEY_2 }, | ||
1471 | { 0x06, KEY_3 }, | ||
1472 | { 0x08, KEY_4 }, | ||
1473 | { 0x09, KEY_5 }, | ||
1474 | { 0x0a, KEY_6 }, | ||
1475 | { 0x0c, KEY_7 }, | ||
1476 | { 0x0d, KEY_8 }, | ||
1477 | { 0x0e, KEY_9 }, | ||
1478 | { 0x12, KEY_DOT }, /* 100+ */ | ||
1479 | |||
1480 | { 0x07, KEY_VOLUMEUP }, | ||
1481 | { 0x0b, KEY_VOLUMEDOWN }, | ||
1482 | { 0x1a, KEY_KPPLUS }, | ||
1483 | { 0x18, KEY_KPMINUS }, | ||
1484 | { 0x15, KEY_UP }, | ||
1485 | { 0x1d, KEY_DOWN }, | ||
1486 | { 0x0f, KEY_CHANNELUP }, | ||
1487 | { 0x13, KEY_CHANNELDOWN }, | ||
1488 | { 0x48, KEY_ZOOM }, | ||
1489 | |||
1490 | { 0x1b, KEY_VIDEO }, /* Video source */ | ||
1491 | { 0x1f, KEY_CAMERA }, /* Snapshot */ | ||
1492 | { 0x49, KEY_LANGUAGE }, /* MTS Select */ | ||
1493 | { 0x19, KEY_SEARCH }, /* Auto Scan */ | ||
1494 | |||
1495 | { 0x4b, KEY_RECORD }, | ||
1496 | { 0x46, KEY_PLAY }, | ||
1497 | { 0x45, KEY_PAUSE }, /* Pause */ | ||
1498 | { 0x44, KEY_STOP }, | ||
1499 | { 0x43, KEY_TIME }, /* Time Shift */ | ||
1500 | { 0x17, KEY_CHANNEL }, /* SURF CH */ | ||
1501 | { 0x40, KEY_FORWARD }, /* Forward ? */ | ||
1502 | { 0x42, KEY_REWIND }, /* Backward ? */ | ||
1503 | |||
1504 | }; | ||
1505 | |||
1506 | struct ir_scancode_table ir_codes_purpletv_table = { | ||
1507 | .scan = ir_codes_purpletv, | ||
1508 | .size = ARRAY_SIZE(ir_codes_purpletv), | ||
1509 | }; | ||
1510 | EXPORT_SYMBOL_GPL(ir_codes_purpletv_table); | ||
1511 | |||
1512 | /* Mapping for the 28 key remote control as seen at | ||
1513 | http://www.sednacomputer.com/photo/cardbus-tv.jpg | ||
1514 | Pavel Mihaylov <bin@bash.info> | ||
1515 | Also for the remote bundled with Kozumi KTV-01C card */ | ||
1516 | static struct ir_scancode ir_codes_pctv_sedna[] = { | ||
1517 | { 0x00, KEY_0 }, | ||
1518 | { 0x01, KEY_1 }, | ||
1519 | { 0x02, KEY_2 }, | ||
1520 | { 0x03, KEY_3 }, | ||
1521 | { 0x04, KEY_4 }, | ||
1522 | { 0x05, KEY_5 }, | ||
1523 | { 0x06, KEY_6 }, | ||
1524 | { 0x07, KEY_7 }, | ||
1525 | { 0x08, KEY_8 }, | ||
1526 | { 0x09, KEY_9 }, | ||
1527 | |||
1528 | { 0x0a, KEY_AGAIN }, /* Recall */ | ||
1529 | { 0x0b, KEY_CHANNELUP }, | ||
1530 | { 0x0c, KEY_VOLUMEUP }, | ||
1531 | { 0x0d, KEY_MODE }, /* Stereo */ | ||
1532 | { 0x0e, KEY_STOP }, | ||
1533 | { 0x0f, KEY_PREVIOUSSONG }, | ||
1534 | { 0x10, KEY_ZOOM }, | ||
1535 | { 0x11, KEY_TUNER }, /* Source */ | ||
1536 | { 0x12, KEY_POWER }, | ||
1537 | { 0x13, KEY_MUTE }, | ||
1538 | { 0x15, KEY_CHANNELDOWN }, | ||
1539 | { 0x18, KEY_VOLUMEDOWN }, | ||
1540 | { 0x19, KEY_CAMERA }, /* Snapshot */ | ||
1541 | { 0x1a, KEY_NEXTSONG }, | ||
1542 | { 0x1b, KEY_TIME }, /* Time Shift */ | ||
1543 | { 0x1c, KEY_RADIO }, /* FM Radio */ | ||
1544 | { 0x1d, KEY_RECORD }, | ||
1545 | { 0x1e, KEY_PAUSE }, | ||
1546 | /* additional codes for Kozumi's remote */ | ||
1547 | { 0x14, KEY_INFO }, /* OSD */ | ||
1548 | { 0x16, KEY_OK }, /* OK */ | ||
1549 | { 0x17, KEY_DIGITS }, /* Plus */ | ||
1550 | { 0x1f, KEY_PLAY }, /* Play */ | ||
1551 | }; | ||
1552 | |||
1553 | struct ir_scancode_table ir_codes_pctv_sedna_table = { | ||
1554 | .scan = ir_codes_pctv_sedna, | ||
1555 | .size = ARRAY_SIZE(ir_codes_pctv_sedna), | ||
1556 | }; | ||
1557 | EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna_table); | ||
1558 | |||
1559 | /* Mark Phalan <phalanm@o2.ie> */ | ||
1560 | static struct ir_scancode ir_codes_pv951[] = { | ||
1561 | { 0x00, KEY_0 }, | ||
1562 | { 0x01, KEY_1 }, | ||
1563 | { 0x02, KEY_2 }, | ||
1564 | { 0x03, KEY_3 }, | ||
1565 | { 0x04, KEY_4 }, | ||
1566 | { 0x05, KEY_5 }, | ||
1567 | { 0x06, KEY_6 }, | ||
1568 | { 0x07, KEY_7 }, | ||
1569 | { 0x08, KEY_8 }, | ||
1570 | { 0x09, KEY_9 }, | ||
1571 | |||
1572 | { 0x12, KEY_POWER }, | ||
1573 | { 0x10, KEY_MUTE }, | ||
1574 | { 0x1f, KEY_VOLUMEDOWN }, | ||
1575 | { 0x1b, KEY_VOLUMEUP }, | ||
1576 | { 0x1a, KEY_CHANNELUP }, | ||
1577 | { 0x1e, KEY_CHANNELDOWN }, | ||
1578 | { 0x0e, KEY_PAGEUP }, | ||
1579 | { 0x1d, KEY_PAGEDOWN }, | ||
1580 | { 0x13, KEY_SOUND }, | ||
1581 | |||
1582 | { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ | ||
1583 | { 0x16, KEY_SUBTITLE }, /* CC */ | ||
1584 | { 0x0d, KEY_TEXT }, /* TTX */ | ||
1585 | { 0x0b, KEY_TV }, /* AIR/CBL */ | ||
1586 | { 0x11, KEY_PC }, /* PC/TV */ | ||
1587 | { 0x17, KEY_OK }, /* CH RTN */ | ||
1588 | { 0x19, KEY_MODE }, /* FUNC */ | ||
1589 | { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ | ||
1590 | |||
1591 | /* Not sure what to do with these ones! */ | ||
1592 | { 0x0f, KEY_SELECT }, /* SOURCE */ | ||
1593 | { 0x0a, KEY_KPPLUS }, /* +100 */ | ||
1594 | { 0x14, KEY_EQUAL }, /* SYNC */ | ||
1595 | { 0x1c, KEY_MEDIA }, /* PC/TV */ | ||
1596 | }; | ||
1597 | |||
1598 | struct ir_scancode_table ir_codes_pv951_table = { | ||
1599 | .scan = ir_codes_pv951, | ||
1600 | .size = ARRAY_SIZE(ir_codes_pv951), | ||
1601 | }; | ||
1602 | EXPORT_SYMBOL_GPL(ir_codes_pv951_table); | ||
1603 | |||
1604 | /* generic RC5 keytable */ | ||
1605 | /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ | ||
1606 | /* used by old (black) Hauppauge remotes */ | ||
1607 | static struct ir_scancode ir_codes_rc5_tv[] = { | ||
1608 | /* Keys 0 to 9 */ | ||
1609 | { 0x00, KEY_0 }, | ||
1610 | { 0x01, KEY_1 }, | ||
1611 | { 0x02, KEY_2 }, | ||
1612 | { 0x03, KEY_3 }, | ||
1613 | { 0x04, KEY_4 }, | ||
1614 | { 0x05, KEY_5 }, | ||
1615 | { 0x06, KEY_6 }, | ||
1616 | { 0x07, KEY_7 }, | ||
1617 | { 0x08, KEY_8 }, | ||
1618 | { 0x09, KEY_9 }, | ||
1619 | |||
1620 | { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ | ||
1621 | { 0x0c, KEY_POWER }, /* standby */ | ||
1622 | { 0x0d, KEY_MUTE }, /* mute / demute */ | ||
1623 | { 0x0f, KEY_TV }, /* display */ | ||
1624 | { 0x10, KEY_VOLUMEUP }, | ||
1625 | { 0x11, KEY_VOLUMEDOWN }, | ||
1626 | { 0x12, KEY_BRIGHTNESSUP }, | ||
1627 | { 0x13, KEY_BRIGHTNESSDOWN }, | ||
1628 | { 0x1e, KEY_SEARCH }, /* search + */ | ||
1629 | { 0x20, KEY_CHANNELUP }, /* channel / program + */ | ||
1630 | { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
1631 | { 0x22, KEY_CHANNEL }, /* alt / channel */ | ||
1632 | { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ | ||
1633 | { 0x26, KEY_SLEEP }, /* sleeptimer */ | ||
1634 | { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ | ||
1635 | { 0x30, KEY_PAUSE }, | ||
1636 | { 0x32, KEY_REWIND }, | ||
1637 | { 0x33, KEY_GOTO }, | ||
1638 | { 0x35, KEY_PLAY }, | ||
1639 | { 0x36, KEY_STOP }, | ||
1640 | { 0x37, KEY_RECORD }, /* recording */ | ||
1641 | { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ | ||
1642 | { 0x3d, KEY_SUSPEND }, /* system standby */ | ||
1643 | |||
1644 | }; | ||
1645 | |||
1646 | struct ir_scancode_table ir_codes_rc5_tv_table = { | ||
1647 | .scan = ir_codes_rc5_tv, | ||
1648 | .size = ARRAY_SIZE(ir_codes_rc5_tv), | ||
1649 | }; | ||
1650 | EXPORT_SYMBOL_GPL(ir_codes_rc5_tv_table); | ||
1651 | |||
1652 | /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ | ||
1653 | static struct ir_scancode ir_codes_winfast[] = { | ||
1654 | /* Keys 0 to 9 */ | ||
1655 | { 0x12, KEY_0 }, | ||
1656 | { 0x05, KEY_1 }, | ||
1657 | { 0x06, KEY_2 }, | ||
1658 | { 0x07, KEY_3 }, | ||
1659 | { 0x09, KEY_4 }, | ||
1660 | { 0x0a, KEY_5 }, | ||
1661 | { 0x0b, KEY_6 }, | ||
1662 | { 0x0d, KEY_7 }, | ||
1663 | { 0x0e, KEY_8 }, | ||
1664 | { 0x0f, KEY_9 }, | ||
1665 | |||
1666 | { 0x00, KEY_POWER }, | ||
1667 | { 0x1b, KEY_AUDIO }, /* Audio Source */ | ||
1668 | { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ | ||
1669 | { 0x1e, KEY_VIDEO }, /* Video Source */ | ||
1670 | { 0x16, KEY_INFO }, /* Display information */ | ||
1671 | { 0x04, KEY_VOLUMEUP }, | ||
1672 | { 0x08, KEY_VOLUMEDOWN }, | ||
1673 | { 0x0c, KEY_CHANNELUP }, | ||
1674 | { 0x10, KEY_CHANNELDOWN }, | ||
1675 | { 0x03, KEY_ZOOM }, /* fullscreen */ | ||
1676 | { 0x1f, KEY_TEXT }, /* closed caption/teletext */ | ||
1677 | { 0x20, KEY_SLEEP }, | ||
1678 | { 0x29, KEY_CLEAR }, /* boss key */ | ||
1679 | { 0x14, KEY_MUTE }, | ||
1680 | { 0x2b, KEY_RED }, | ||
1681 | { 0x2c, KEY_GREEN }, | ||
1682 | { 0x2d, KEY_YELLOW }, | ||
1683 | { 0x2e, KEY_BLUE }, | ||
1684 | { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ | ||
1685 | { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ | ||
1686 | { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ | ||
1687 | { 0x21, KEY_DOT }, | ||
1688 | { 0x13, KEY_ENTER }, | ||
1689 | { 0x11, KEY_LAST }, /* Recall (last channel */ | ||
1690 | { 0x22, KEY_PREVIOUS }, | ||
1691 | { 0x23, KEY_PLAYPAUSE }, | ||
1692 | { 0x24, KEY_NEXT }, | ||
1693 | { 0x25, KEY_TIME }, /* Time Shifting */ | ||
1694 | { 0x26, KEY_STOP }, | ||
1695 | { 0x27, KEY_RECORD }, | ||
1696 | { 0x28, KEY_SAVE }, /* Screenshot */ | ||
1697 | { 0x2f, KEY_MENU }, | ||
1698 | { 0x30, KEY_CANCEL }, | ||
1699 | { 0x31, KEY_CHANNEL }, /* Channel Surf */ | ||
1700 | { 0x32, KEY_SUBTITLE }, | ||
1701 | { 0x33, KEY_LANGUAGE }, | ||
1702 | { 0x34, KEY_REWIND }, | ||
1703 | { 0x35, KEY_FASTFORWARD }, | ||
1704 | { 0x36, KEY_TV }, | ||
1705 | { 0x37, KEY_RADIO }, /* FM */ | ||
1706 | { 0x38, KEY_DVD }, | ||
1707 | |||
1708 | { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ | ||
1709 | { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ | ||
1710 | { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ | ||
1711 | { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ | ||
1712 | { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ | ||
1713 | }; | ||
1714 | |||
1715 | struct ir_scancode_table ir_codes_winfast_table = { | ||
1716 | .scan = ir_codes_winfast, | ||
1717 | .size = ARRAY_SIZE(ir_codes_winfast), | ||
1718 | }; | ||
1719 | EXPORT_SYMBOL_GPL(ir_codes_winfast_table); | ||
1720 | |||
1721 | static struct ir_scancode ir_codes_pinnacle_color[] = { | ||
1722 | { 0x59, KEY_MUTE }, | ||
1723 | { 0x4a, KEY_POWER }, | ||
1724 | |||
1725 | { 0x18, KEY_TEXT }, | ||
1726 | { 0x26, KEY_TV }, | ||
1727 | { 0x3d, KEY_PRINT }, | ||
1728 | |||
1729 | { 0x48, KEY_RED }, | ||
1730 | { 0x04, KEY_GREEN }, | ||
1731 | { 0x11, KEY_YELLOW }, | ||
1732 | { 0x00, KEY_BLUE }, | ||
1733 | |||
1734 | { 0x2d, KEY_VOLUMEUP }, | ||
1735 | { 0x1e, KEY_VOLUMEDOWN }, | ||
1736 | |||
1737 | { 0x49, KEY_MENU }, | ||
1738 | |||
1739 | { 0x16, KEY_CHANNELUP }, | ||
1740 | { 0x17, KEY_CHANNELDOWN }, | ||
1741 | |||
1742 | { 0x20, KEY_UP }, | ||
1743 | { 0x21, KEY_DOWN }, | ||
1744 | { 0x22, KEY_LEFT }, | ||
1745 | { 0x23, KEY_RIGHT }, | ||
1746 | { 0x0d, KEY_SELECT }, | ||
1747 | |||
1748 | { 0x08, KEY_BACK }, | ||
1749 | { 0x07, KEY_REFRESH }, | ||
1750 | |||
1751 | { 0x2f, KEY_ZOOM }, | ||
1752 | { 0x29, KEY_RECORD }, | ||
1753 | |||
1754 | { 0x4b, KEY_PAUSE }, | ||
1755 | { 0x4d, KEY_REWIND }, | ||
1756 | { 0x2e, KEY_PLAY }, | ||
1757 | { 0x4e, KEY_FORWARD }, | ||
1758 | { 0x53, KEY_PREVIOUS }, | ||
1759 | { 0x4c, KEY_STOP }, | ||
1760 | { 0x54, KEY_NEXT }, | ||
1761 | |||
1762 | { 0x69, KEY_0 }, | ||
1763 | { 0x6a, KEY_1 }, | ||
1764 | { 0x6b, KEY_2 }, | ||
1765 | { 0x6c, KEY_3 }, | ||
1766 | { 0x6d, KEY_4 }, | ||
1767 | { 0x6e, KEY_5 }, | ||
1768 | { 0x6f, KEY_6 }, | ||
1769 | { 0x70, KEY_7 }, | ||
1770 | { 0x71, KEY_8 }, | ||
1771 | { 0x72, KEY_9 }, | ||
1772 | |||
1773 | { 0x74, KEY_CHANNEL }, | ||
1774 | { 0x0a, KEY_BACKSPACE }, | ||
1775 | }; | ||
1776 | |||
1777 | struct ir_scancode_table ir_codes_pinnacle_color_table = { | ||
1778 | .scan = ir_codes_pinnacle_color, | ||
1779 | .size = ARRAY_SIZE(ir_codes_pinnacle_color), | ||
1780 | }; | ||
1781 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color_table); | ||
1782 | |||
1783 | /* Hauppauge: the newer, gray remotes (seems there are multiple | ||
1784 | * slightly different versions), shipped with cx88+ivtv cards. | ||
1785 | * almost rc5 coding, but some non-standard keys */ | ||
1786 | static struct ir_scancode ir_codes_hauppauge_new[] = { | ||
1787 | /* Keys 0 to 9 */ | ||
1788 | { 0x00, KEY_0 }, | ||
1789 | { 0x01, KEY_1 }, | ||
1790 | { 0x02, KEY_2 }, | ||
1791 | { 0x03, KEY_3 }, | ||
1792 | { 0x04, KEY_4 }, | ||
1793 | { 0x05, KEY_5 }, | ||
1794 | { 0x06, KEY_6 }, | ||
1795 | { 0x07, KEY_7 }, | ||
1796 | { 0x08, KEY_8 }, | ||
1797 | { 0x09, KEY_9 }, | ||
1798 | |||
1799 | { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
1800 | { 0x0b, KEY_RED }, /* red button */ | ||
1801 | { 0x0c, KEY_RADIO }, | ||
1802 | { 0x0d, KEY_MENU }, | ||
1803 | { 0x0e, KEY_SUBTITLE }, /* also the # key */ | ||
1804 | { 0x0f, KEY_MUTE }, | ||
1805 | { 0x10, KEY_VOLUMEUP }, | ||
1806 | { 0x11, KEY_VOLUMEDOWN }, | ||
1807 | { 0x12, KEY_PREVIOUS }, /* previous channel */ | ||
1808 | { 0x14, KEY_UP }, | ||
1809 | { 0x15, KEY_DOWN }, | ||
1810 | { 0x16, KEY_LEFT }, | ||
1811 | { 0x17, KEY_RIGHT }, | ||
1812 | { 0x18, KEY_VIDEO }, /* Videos */ | ||
1813 | { 0x19, KEY_AUDIO }, /* Music */ | ||
1814 | /* 0x1a: Pictures - presume this means | ||
1815 | "Multimedia Home Platform" - | ||
1816 | no "PICTURES" key in input.h | ||
1817 | */ | ||
1818 | { 0x1a, KEY_MHP }, | ||
1819 | |||
1820 | { 0x1b, KEY_EPG }, /* Guide */ | ||
1821 | { 0x1c, KEY_TV }, | ||
1822 | { 0x1e, KEY_NEXTSONG }, /* skip >| */ | ||
1823 | { 0x1f, KEY_EXIT }, /* back/exit */ | ||
1824 | { 0x20, KEY_CHANNELUP }, /* channel / program + */ | ||
1825 | { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
1826 | { 0x22, KEY_CHANNEL }, /* source (old black remote) */ | ||
1827 | { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
1828 | { 0x25, KEY_ENTER }, /* OK */ | ||
1829 | { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
1830 | { 0x29, KEY_BLUE }, /* blue key */ | ||
1831 | { 0x2e, KEY_GREEN }, /* green button */ | ||
1832 | { 0x30, KEY_PAUSE }, /* pause */ | ||
1833 | { 0x32, KEY_REWIND }, /* backward << */ | ||
1834 | { 0x34, KEY_FASTFORWARD }, /* forward >> */ | ||
1835 | { 0x35, KEY_PLAY }, | ||
1836 | { 0x36, KEY_STOP }, | ||
1837 | { 0x37, KEY_RECORD }, /* recording */ | ||
1838 | { 0x38, KEY_YELLOW }, /* yellow key */ | ||
1839 | { 0x3b, KEY_SELECT }, /* top right button */ | ||
1840 | { 0x3c, KEY_ZOOM }, /* full */ | ||
1841 | { 0x3d, KEY_POWER }, /* system power (green button) */ | ||
1842 | }; | ||
1843 | |||
1844 | struct ir_scancode_table ir_codes_hauppauge_new_table = { | ||
1845 | .scan = ir_codes_hauppauge_new, | ||
1846 | .size = ARRAY_SIZE(ir_codes_hauppauge_new), | ||
1847 | }; | ||
1848 | EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); | ||
1849 | |||
1850 | static struct ir_scancode ir_codes_npgtech[] = { | ||
1851 | { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ | ||
1852 | { 0x2a, KEY_FRONT }, | ||
1853 | |||
1854 | { 0x3e, KEY_1 }, | ||
1855 | { 0x02, KEY_2 }, | ||
1856 | { 0x06, KEY_3 }, | ||
1857 | { 0x0a, KEY_4 }, | ||
1858 | { 0x0e, KEY_5 }, | ||
1859 | { 0x12, KEY_6 }, | ||
1860 | { 0x16, KEY_7 }, | ||
1861 | { 0x1a, KEY_8 }, | ||
1862 | { 0x1e, KEY_9 }, | ||
1863 | { 0x3a, KEY_0 }, | ||
1864 | { 0x22, KEY_NUMLOCK }, /* -/-- */ | ||
1865 | { 0x20, KEY_REFRESH }, | ||
1866 | |||
1867 | { 0x03, KEY_BRIGHTNESSDOWN }, | ||
1868 | { 0x28, KEY_AUDIO }, | ||
1869 | { 0x3c, KEY_CHANNELUP }, | ||
1870 | { 0x3f, KEY_VOLUMEDOWN }, | ||
1871 | { 0x2e, KEY_MUTE }, | ||
1872 | { 0x3b, KEY_VOLUMEUP }, | ||
1873 | { 0x00, KEY_CHANNELDOWN }, | ||
1874 | { 0x07, KEY_BRIGHTNESSUP }, | ||
1875 | { 0x2c, KEY_TEXT }, | ||
1876 | |||
1877 | { 0x37, KEY_RECORD }, | ||
1878 | { 0x17, KEY_PLAY }, | ||
1879 | { 0x13, KEY_PAUSE }, | ||
1880 | { 0x26, KEY_STOP }, | ||
1881 | { 0x18, KEY_FASTFORWARD }, | ||
1882 | { 0x14, KEY_REWIND }, | ||
1883 | { 0x33, KEY_ZOOM }, | ||
1884 | { 0x32, KEY_KEYBOARD }, | ||
1885 | { 0x30, KEY_GOTO }, /* Pointing arrow */ | ||
1886 | { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ | ||
1887 | { 0x0b, KEY_RADIO }, | ||
1888 | { 0x10, KEY_POWER }, | ||
1889 | |||
1890 | }; | ||
1891 | |||
1892 | struct ir_scancode_table ir_codes_npgtech_table = { | ||
1893 | .scan = ir_codes_npgtech, | ||
1894 | .size = ARRAY_SIZE(ir_codes_npgtech), | ||
1895 | }; | ||
1896 | EXPORT_SYMBOL_GPL(ir_codes_npgtech_table); | ||
1897 | |||
1898 | /* Norwood Micro (non-Pro) TV Tuner | ||
1899 | By Peter Naulls <peter@chocky.org> | ||
1900 | Key comments are the functions given in the manual */ | ||
1901 | static struct ir_scancode ir_codes_norwood[] = { | ||
1902 | /* Keys 0 to 9 */ | ||
1903 | { 0x20, KEY_0 }, | ||
1904 | { 0x21, KEY_1 }, | ||
1905 | { 0x22, KEY_2 }, | ||
1906 | { 0x23, KEY_3 }, | ||
1907 | { 0x24, KEY_4 }, | ||
1908 | { 0x25, KEY_5 }, | ||
1909 | { 0x26, KEY_6 }, | ||
1910 | { 0x27, KEY_7 }, | ||
1911 | { 0x28, KEY_8 }, | ||
1912 | { 0x29, KEY_9 }, | ||
1913 | |||
1914 | { 0x78, KEY_TUNER }, /* Video Source */ | ||
1915 | { 0x2c, KEY_EXIT }, /* Open/Close software */ | ||
1916 | { 0x2a, KEY_SELECT }, /* 2 Digit Select */ | ||
1917 | { 0x69, KEY_AGAIN }, /* Recall */ | ||
1918 | |||
1919 | { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ | ||
1920 | { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ | ||
1921 | { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ | ||
1922 | { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ | ||
1923 | |||
1924 | { 0x2d, KEY_MUTE }, /* Mute */ | ||
1925 | { 0x30, KEY_VOLUMEUP }, /* Volume up */ | ||
1926 | { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ | ||
1927 | { 0x60, KEY_CHANNELUP }, /* Channel up */ | ||
1928 | { 0x61, KEY_CHANNELDOWN }, /* Channel down */ | ||
1929 | |||
1930 | { 0x3f, KEY_RECORD }, /* Record */ | ||
1931 | { 0x37, KEY_PLAY }, /* Play */ | ||
1932 | { 0x36, KEY_PAUSE }, /* Pause */ | ||
1933 | { 0x2b, KEY_STOP }, /* Stop */ | ||
1934 | { 0x67, KEY_FASTFORWARD }, /* Foward */ | ||
1935 | { 0x66, KEY_REWIND }, /* Rewind */ | ||
1936 | { 0x3e, KEY_SEARCH }, /* Auto Scan */ | ||
1937 | { 0x2e, KEY_CAMERA }, /* Capture Video */ | ||
1938 | { 0x6d, KEY_MENU }, /* Show/Hide Control */ | ||
1939 | { 0x2f, KEY_ZOOM }, /* Full Screen */ | ||
1940 | { 0x34, KEY_RADIO }, /* FM */ | ||
1941 | { 0x65, KEY_POWER }, /* Computer power */ | ||
1942 | }; | ||
1943 | |||
1944 | struct ir_scancode_table ir_codes_norwood_table = { | ||
1945 | .scan = ir_codes_norwood, | ||
1946 | .size = ARRAY_SIZE(ir_codes_norwood), | ||
1947 | }; | ||
1948 | EXPORT_SYMBOL_GPL(ir_codes_norwood_table); | ||
1949 | |||
1950 | /* From reading the following remotes: | ||
1951 | * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
1952 | * Hauppauge (from NOVA-CI-s box product) | ||
1953 | * This is a "middle of the road" approach, differences are noted | ||
1954 | */ | ||
1955 | static struct ir_scancode ir_codes_budget_ci_old[] = { | ||
1956 | { 0x00, KEY_0 }, | ||
1957 | { 0x01, KEY_1 }, | ||
1958 | { 0x02, KEY_2 }, | ||
1959 | { 0x03, KEY_3 }, | ||
1960 | { 0x04, KEY_4 }, | ||
1961 | { 0x05, KEY_5 }, | ||
1962 | { 0x06, KEY_6 }, | ||
1963 | { 0x07, KEY_7 }, | ||
1964 | { 0x08, KEY_8 }, | ||
1965 | { 0x09, KEY_9 }, | ||
1966 | { 0x0a, KEY_ENTER }, | ||
1967 | { 0x0b, KEY_RED }, | ||
1968 | { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ | ||
1969 | { 0x0d, KEY_MUTE }, | ||
1970 | { 0x0f, KEY_A }, /* TV on Hauppauge */ | ||
1971 | { 0x10, KEY_VOLUMEUP }, | ||
1972 | { 0x11, KEY_VOLUMEDOWN }, | ||
1973 | { 0x14, KEY_B }, | ||
1974 | { 0x1c, KEY_UP }, | ||
1975 | { 0x1d, KEY_DOWN }, | ||
1976 | { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ | ||
1977 | { 0x1f, KEY_BREAK }, | ||
1978 | { 0x20, KEY_CHANNELUP }, | ||
1979 | { 0x21, KEY_CHANNELDOWN }, | ||
1980 | { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ | ||
1981 | { 0x24, KEY_RESTART }, | ||
1982 | { 0x25, KEY_OK }, | ||
1983 | { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ | ||
1984 | { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ | ||
1985 | { 0x29, KEY_PAUSE }, | ||
1986 | { 0x2b, KEY_RIGHT }, | ||
1987 | { 0x2c, KEY_LEFT }, | ||
1988 | { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ | ||
1989 | { 0x30, KEY_SLOW }, | ||
1990 | { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ | ||
1991 | { 0x32, KEY_REWIND }, | ||
1992 | { 0x34, KEY_FASTFORWARD }, | ||
1993 | { 0x35, KEY_PLAY }, | ||
1994 | { 0x36, KEY_STOP }, | ||
1995 | { 0x37, KEY_RECORD }, | ||
1996 | { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ | ||
1997 | { 0x3a, KEY_C }, | ||
1998 | { 0x3c, KEY_EXIT }, | ||
1999 | { 0x3d, KEY_POWER2 }, | ||
2000 | { 0x3e, KEY_TUNER }, | ||
2001 | }; | ||
2002 | |||
2003 | struct ir_scancode_table ir_codes_budget_ci_old_table = { | ||
2004 | .scan = ir_codes_budget_ci_old, | ||
2005 | .size = ARRAY_SIZE(ir_codes_budget_ci_old), | ||
2006 | }; | ||
2007 | EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old_table); | ||
2008 | |||
2009 | /* | ||
2010 | * Marc Fargas <telenieko@telenieko.com> | ||
2011 | * this is the remote control that comes with the asus p7131 | ||
2012 | * which has a label saying is "Model PC-39" | ||
2013 | */ | ||
2014 | static struct ir_scancode ir_codes_asus_pc39[] = { | ||
2015 | /* Keys 0 to 9 */ | ||
2016 | { 0x15, KEY_0 }, | ||
2017 | { 0x29, KEY_1 }, | ||
2018 | { 0x2d, KEY_2 }, | ||
2019 | { 0x2b, KEY_3 }, | ||
2020 | { 0x09, KEY_4 }, | ||
2021 | { 0x0d, KEY_5 }, | ||
2022 | { 0x0b, KEY_6 }, | ||
2023 | { 0x31, KEY_7 }, | ||
2024 | { 0x35, KEY_8 }, | ||
2025 | { 0x33, KEY_9 }, | ||
2026 | |||
2027 | { 0x3e, KEY_RADIO }, /* radio */ | ||
2028 | { 0x03, KEY_MENU }, /* dvd/menu */ | ||
2029 | { 0x2a, KEY_VOLUMEUP }, | ||
2030 | { 0x19, KEY_VOLUMEDOWN }, | ||
2031 | { 0x37, KEY_UP }, | ||
2032 | { 0x3b, KEY_DOWN }, | ||
2033 | { 0x27, KEY_LEFT }, | ||
2034 | { 0x2f, KEY_RIGHT }, | ||
2035 | { 0x25, KEY_VIDEO }, /* video */ | ||
2036 | { 0x39, KEY_AUDIO }, /* music */ | ||
2037 | |||
2038 | { 0x21, KEY_TV }, /* tv */ | ||
2039 | { 0x1d, KEY_EXIT }, /* back */ | ||
2040 | { 0x0a, KEY_CHANNELUP }, /* channel / program + */ | ||
2041 | { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ | ||
2042 | { 0x1a, KEY_ENTER }, /* enter */ | ||
2043 | |||
2044 | { 0x06, KEY_PAUSE }, /* play/pause */ | ||
2045 | { 0x1e, KEY_PREVIOUS }, /* rew */ | ||
2046 | { 0x26, KEY_NEXT }, /* forward */ | ||
2047 | { 0x0e, KEY_REWIND }, /* backward << */ | ||
2048 | { 0x3a, KEY_FASTFORWARD }, /* forward >> */ | ||
2049 | { 0x36, KEY_STOP }, | ||
2050 | { 0x2e, KEY_RECORD }, /* recording */ | ||
2051 | { 0x16, KEY_POWER }, /* the button that reads "close" */ | ||
2052 | |||
2053 | { 0x11, KEY_ZOOM }, /* full screen */ | ||
2054 | { 0x13, KEY_MACRO }, /* recall */ | ||
2055 | { 0x23, KEY_HOME }, /* home */ | ||
2056 | { 0x05, KEY_PVR }, /* picture */ | ||
2057 | { 0x3d, KEY_MUTE }, /* mute */ | ||
2058 | { 0x01, KEY_DVD }, /* dvd */ | ||
2059 | }; | ||
2060 | |||
2061 | struct ir_scancode_table ir_codes_asus_pc39_table = { | ||
2062 | .scan = ir_codes_asus_pc39, | ||
2063 | .size = ARRAY_SIZE(ir_codes_asus_pc39), | ||
2064 | }; | ||
2065 | EXPORT_SYMBOL_GPL(ir_codes_asus_pc39_table); | ||
2066 | |||
2067 | |||
2068 | /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons | ||
2069 | Juan Pablo Sormani <sorman@gmail.com> */ | ||
2070 | static struct ir_scancode ir_codes_encore_enltv[] = { | ||
2071 | |||
2072 | /* Power button does nothing, neither in Windows app, | ||
2073 | although it sends data (used for BIOS wakeup?) */ | ||
2074 | { 0x0d, KEY_MUTE }, | ||
2075 | |||
2076 | { 0x1e, KEY_TV }, | ||
2077 | { 0x00, KEY_VIDEO }, | ||
2078 | { 0x01, KEY_AUDIO }, /* music */ | ||
2079 | { 0x02, KEY_MHP }, /* picture */ | ||
2080 | |||
2081 | { 0x1f, KEY_1 }, | ||
2082 | { 0x03, KEY_2 }, | ||
2083 | { 0x04, KEY_3 }, | ||
2084 | { 0x05, KEY_4 }, | ||
2085 | { 0x1c, KEY_5 }, | ||
2086 | { 0x06, KEY_6 }, | ||
2087 | { 0x07, KEY_7 }, | ||
2088 | { 0x08, KEY_8 }, | ||
2089 | { 0x1d, KEY_9 }, | ||
2090 | { 0x0a, KEY_0 }, | ||
2091 | |||
2092 | { 0x09, KEY_LIST }, /* -/-- */ | ||
2093 | { 0x0b, KEY_LAST }, /* recall */ | ||
2094 | |||
2095 | { 0x14, KEY_HOME }, /* win start menu */ | ||
2096 | { 0x15, KEY_EXIT }, /* exit */ | ||
2097 | { 0x16, KEY_CHANNELUP }, /* UP */ | ||
2098 | { 0x12, KEY_CHANNELDOWN }, /* DOWN */ | ||
2099 | { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ | ||
2100 | { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ | ||
2101 | |||
2102 | { 0x18, KEY_ENTER }, /* OK */ | ||
2103 | |||
2104 | { 0x0e, KEY_ESC }, | ||
2105 | { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ | ||
2106 | { 0x11, KEY_TAB }, | ||
2107 | { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ | ||
2108 | |||
2109 | { 0x1a, KEY_MENU }, | ||
2110 | { 0x1b, KEY_ZOOM }, /* fullscreen */ | ||
2111 | { 0x44, KEY_TIME }, /* time shift */ | ||
2112 | { 0x40, KEY_MODE }, /* source */ | ||
2113 | |||
2114 | { 0x5a, KEY_RECORD }, | ||
2115 | { 0x42, KEY_PLAY }, /* play/pause */ | ||
2116 | { 0x45, KEY_STOP }, | ||
2117 | { 0x43, KEY_CAMERA }, /* camera icon */ | ||
2118 | |||
2119 | { 0x48, KEY_REWIND }, | ||
2120 | { 0x4a, KEY_FASTFORWARD }, | ||
2121 | { 0x49, KEY_PREVIOUS }, | ||
2122 | { 0x4b, KEY_NEXT }, | ||
2123 | |||
2124 | { 0x4c, KEY_FAVORITES }, /* tv wall */ | ||
2125 | { 0x4d, KEY_SOUND }, /* DVD sound */ | ||
2126 | { 0x4e, KEY_LANGUAGE }, /* DVD lang */ | ||
2127 | { 0x4f, KEY_TEXT }, /* DVD text */ | ||
2128 | |||
2129 | { 0x50, KEY_SLEEP }, /* shutdown */ | ||
2130 | { 0x51, KEY_MODE }, /* stereo > main */ | ||
2131 | { 0x52, KEY_SELECT }, /* stereo > sap */ | ||
2132 | { 0x53, KEY_PROG1 }, /* teletext */ | ||
2133 | |||
2134 | |||
2135 | { 0x59, KEY_RED }, /* AP1 */ | ||
2136 | { 0x41, KEY_GREEN }, /* AP2 */ | ||
2137 | { 0x47, KEY_YELLOW }, /* AP3 */ | ||
2138 | { 0x57, KEY_BLUE }, /* AP4 */ | ||
2139 | }; | ||
2140 | |||
2141 | struct ir_scancode_table ir_codes_encore_enltv_table = { | ||
2142 | .scan = ir_codes_encore_enltv, | ||
2143 | .size = ARRAY_SIZE(ir_codes_encore_enltv), | ||
2144 | }; | ||
2145 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_table); | ||
2146 | |||
2147 | /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton | ||
2148 | Mauro Carvalho Chehab <mchehab@infradead.org> */ | ||
2149 | static struct ir_scancode ir_codes_encore_enltv2[] = { | ||
2150 | { 0x4c, KEY_POWER2 }, | ||
2151 | { 0x4a, KEY_TUNER }, | ||
2152 | { 0x40, KEY_1 }, | ||
2153 | { 0x60, KEY_2 }, | ||
2154 | { 0x50, KEY_3 }, | ||
2155 | { 0x70, KEY_4 }, | ||
2156 | { 0x48, KEY_5 }, | ||
2157 | { 0x68, KEY_6 }, | ||
2158 | { 0x58, KEY_7 }, | ||
2159 | { 0x78, KEY_8 }, | ||
2160 | { 0x44, KEY_9 }, | ||
2161 | { 0x54, KEY_0 }, | ||
2162 | |||
2163 | { 0x64, KEY_LAST }, /* +100 */ | ||
2164 | { 0x4e, KEY_AGAIN }, /* Recall */ | ||
2165 | |||
2166 | { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ | ||
2167 | { 0x5e, KEY_MENU }, | ||
2168 | { 0x56, KEY_SCREEN }, | ||
2169 | { 0x7a, KEY_SETUP }, | ||
2170 | |||
2171 | { 0x46, KEY_MUTE }, | ||
2172 | { 0x5c, KEY_MODE }, /* Stereo */ | ||
2173 | { 0x74, KEY_INFO }, | ||
2174 | { 0x7c, KEY_CLEAR }, | ||
2175 | |||
2176 | { 0x55, KEY_UP }, | ||
2177 | { 0x49, KEY_DOWN }, | ||
2178 | { 0x7e, KEY_LEFT }, | ||
2179 | { 0x59, KEY_RIGHT }, | ||
2180 | { 0x6a, KEY_ENTER }, | ||
2181 | |||
2182 | { 0x42, KEY_VOLUMEUP }, | ||
2183 | { 0x62, KEY_VOLUMEDOWN }, | ||
2184 | { 0x52, KEY_CHANNELUP }, | ||
2185 | { 0x72, KEY_CHANNELDOWN }, | ||
2186 | |||
2187 | { 0x41, KEY_RECORD }, | ||
2188 | { 0x51, KEY_CAMERA }, /* Snapshot */ | ||
2189 | { 0x75, KEY_TIME }, /* Timeshift */ | ||
2190 | { 0x71, KEY_TV2 }, /* PIP */ | ||
2191 | |||
2192 | { 0x45, KEY_REWIND }, | ||
2193 | { 0x6f, KEY_PAUSE }, | ||
2194 | { 0x7d, KEY_FORWARD }, | ||
2195 | { 0x79, KEY_STOP }, | ||
2196 | }; | ||
2197 | |||
2198 | struct ir_scancode_table ir_codes_encore_enltv2_table = { | ||
2199 | .scan = ir_codes_encore_enltv2, | ||
2200 | .size = ARRAY_SIZE(ir_codes_encore_enltv2), | ||
2201 | }; | ||
2202 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2_table); | ||
2203 | |||
2204 | /* for the Technotrend 1500 bundled remotes (grey and black): */ | ||
2205 | static struct ir_scancode ir_codes_tt_1500[] = { | ||
2206 | { 0x01, KEY_POWER }, | ||
2207 | { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ | ||
2208 | { 0x03, KEY_1 }, | ||
2209 | { 0x04, KEY_2 }, | ||
2210 | { 0x05, KEY_3 }, | ||
2211 | { 0x06, KEY_4 }, | ||
2212 | { 0x07, KEY_5 }, | ||
2213 | { 0x08, KEY_6 }, | ||
2214 | { 0x09, KEY_7 }, | ||
2215 | { 0x0a, KEY_8 }, | ||
2216 | { 0x0b, KEY_9 }, | ||
2217 | { 0x0c, KEY_0 }, | ||
2218 | { 0x0d, KEY_UP }, | ||
2219 | { 0x0e, KEY_LEFT }, | ||
2220 | { 0x0f, KEY_OK }, | ||
2221 | { 0x10, KEY_RIGHT }, | ||
2222 | { 0x11, KEY_DOWN }, | ||
2223 | { 0x12, KEY_INFO }, | ||
2224 | { 0x13, KEY_EXIT }, | ||
2225 | { 0x14, KEY_RED }, | ||
2226 | { 0x15, KEY_GREEN }, | ||
2227 | { 0x16, KEY_YELLOW }, | ||
2228 | { 0x17, KEY_BLUE }, | ||
2229 | { 0x18, KEY_MUTE }, | ||
2230 | { 0x19, KEY_TEXT }, | ||
2231 | { 0x1a, KEY_MODE }, /* ? TV/Radio */ | ||
2232 | { 0x21, KEY_OPTION }, | ||
2233 | { 0x22, KEY_EPG }, | ||
2234 | { 0x23, KEY_CHANNELUP }, | ||
2235 | { 0x24, KEY_CHANNELDOWN }, | ||
2236 | { 0x25, KEY_VOLUMEUP }, | ||
2237 | { 0x26, KEY_VOLUMEDOWN }, | ||
2238 | { 0x27, KEY_SETUP }, | ||
2239 | { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ | ||
2240 | { 0x3b, KEY_PLAY }, | ||
2241 | { 0x3c, KEY_STOP }, | ||
2242 | { 0x3d, KEY_REWIND }, | ||
2243 | { 0x3e, KEY_PAUSE }, | ||
2244 | { 0x3f, KEY_FORWARD }, | ||
2245 | }; | ||
2246 | |||
2247 | struct ir_scancode_table ir_codes_tt_1500_table = { | ||
2248 | .scan = ir_codes_tt_1500, | ||
2249 | .size = ARRAY_SIZE(ir_codes_tt_1500), | ||
2250 | }; | ||
2251 | EXPORT_SYMBOL_GPL(ir_codes_tt_1500_table); | ||
2252 | |||
2253 | /* DViCO FUSION HDTV MCE remote */ | ||
2254 | static struct ir_scancode ir_codes_fusionhdtv_mce[] = { | ||
2255 | |||
2256 | { 0x0b, KEY_1 }, | ||
2257 | { 0x17, KEY_2 }, | ||
2258 | { 0x1b, KEY_3 }, | ||
2259 | { 0x07, KEY_4 }, | ||
2260 | { 0x50, KEY_5 }, | ||
2261 | { 0x54, KEY_6 }, | ||
2262 | { 0x48, KEY_7 }, | ||
2263 | { 0x4c, KEY_8 }, | ||
2264 | { 0x58, KEY_9 }, | ||
2265 | { 0x03, KEY_0 }, | ||
2266 | |||
2267 | { 0x5e, KEY_OK }, | ||
2268 | { 0x51, KEY_UP }, | ||
2269 | { 0x53, KEY_DOWN }, | ||
2270 | { 0x5b, KEY_LEFT }, | ||
2271 | { 0x5f, KEY_RIGHT }, | ||
2272 | |||
2273 | { 0x02, KEY_TV }, /* Labeled DTV on remote */ | ||
2274 | { 0x0e, KEY_MP3 }, | ||
2275 | { 0x1a, KEY_DVD }, | ||
2276 | { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ | ||
2277 | { 0x16, KEY_SETUP }, | ||
2278 | { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ | ||
2279 | { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ | ||
2280 | |||
2281 | { 0x49, KEY_BACK }, | ||
2282 | { 0x59, KEY_INFO }, /* Labeled MORE on remote */ | ||
2283 | { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ | ||
2284 | { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ | ||
2285 | |||
2286 | { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ | ||
2287 | { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ | ||
2288 | { 0x42, KEY_ENTER }, /* Labeled START with a green | ||
2289 | MS windows logo on remote */ | ||
2290 | |||
2291 | { 0x15, KEY_VOLUMEUP }, | ||
2292 | { 0x05, KEY_VOLUMEDOWN }, | ||
2293 | { 0x11, KEY_CHANNELUP }, | ||
2294 | { 0x09, KEY_CHANNELDOWN }, | ||
2295 | |||
2296 | { 0x52, KEY_CAMERA }, | ||
2297 | { 0x5a, KEY_TUNER }, | ||
2298 | { 0x19, KEY_OPEN }, | ||
2299 | |||
2300 | { 0x13, KEY_MODE }, /* 4:3 16:9 select */ | ||
2301 | { 0x1f, KEY_ZOOM }, | ||
2302 | |||
2303 | { 0x43, KEY_REWIND }, | ||
2304 | { 0x47, KEY_PLAYPAUSE }, | ||
2305 | { 0x4f, KEY_FASTFORWARD }, | ||
2306 | { 0x57, KEY_MUTE }, | ||
2307 | { 0x0d, KEY_STOP }, | ||
2308 | { 0x01, KEY_RECORD }, | ||
2309 | { 0x4e, KEY_POWER }, | ||
2310 | }; | ||
2311 | |||
2312 | struct ir_scancode_table ir_codes_fusionhdtv_mce_table = { | ||
2313 | .scan = ir_codes_fusionhdtv_mce, | ||
2314 | .size = ARRAY_SIZE(ir_codes_fusionhdtv_mce), | ||
2315 | }; | ||
2316 | EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce_table); | ||
2317 | |||
2318 | /* Pinnacle PCTV HD 800i mini remote */ | ||
2319 | static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { | ||
2320 | |||
2321 | { 0x0f, KEY_1 }, | ||
2322 | { 0x15, KEY_2 }, | ||
2323 | { 0x10, KEY_3 }, | ||
2324 | { 0x18, KEY_4 }, | ||
2325 | { 0x1b, KEY_5 }, | ||
2326 | { 0x1e, KEY_6 }, | ||
2327 | { 0x11, KEY_7 }, | ||
2328 | { 0x21, KEY_8 }, | ||
2329 | { 0x12, KEY_9 }, | ||
2330 | { 0x27, KEY_0 }, | ||
2331 | |||
2332 | { 0x24, KEY_ZOOM }, | ||
2333 | { 0x2a, KEY_SUBTITLE }, | ||
2334 | |||
2335 | { 0x00, KEY_MUTE }, | ||
2336 | { 0x01, KEY_ENTER }, /* Pinnacle Logo */ | ||
2337 | { 0x39, KEY_POWER }, | ||
2338 | |||
2339 | { 0x03, KEY_VOLUMEUP }, | ||
2340 | { 0x09, KEY_VOLUMEDOWN }, | ||
2341 | { 0x06, KEY_CHANNELUP }, | ||
2342 | { 0x0c, KEY_CHANNELDOWN }, | ||
2343 | |||
2344 | { 0x2d, KEY_REWIND }, | ||
2345 | { 0x30, KEY_PLAYPAUSE }, | ||
2346 | { 0x33, KEY_FASTFORWARD }, | ||
2347 | { 0x3c, KEY_STOP }, | ||
2348 | { 0x36, KEY_RECORD }, | ||
2349 | { 0x3f, KEY_EPG }, /* Labeled "?" */ | ||
2350 | }; | ||
2351 | |||
2352 | struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table = { | ||
2353 | .scan = ir_codes_pinnacle_pctv_hd, | ||
2354 | .size = ARRAY_SIZE(ir_codes_pinnacle_pctv_hd), | ||
2355 | }; | ||
2356 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd_table); | ||
2357 | |||
2358 | /* | ||
2359 | * Igor Kuznetsov <igk72@ya.ru> | ||
2360 | * Andrey J. Melnikov <temnota@kmv.ru> | ||
2361 | * | ||
2362 | * Keytable is used by BeholdTV 60x series, M6 series at | ||
2363 | * least, and probably other cards too. | ||
2364 | * The "ascii-art picture" below (in comments, first row | ||
2365 | * is the keycode in hex, and subsequent row(s) shows | ||
2366 | * the button labels (several variants when appropriate) | ||
2367 | * helps to descide which keycodes to assign to the buttons. | ||
2368 | */ | ||
2369 | static struct ir_scancode ir_codes_behold[] = { | ||
2370 | |||
2371 | /* 0x1c 0x12 * | ||
2372 | * TV/FM POWER * | ||
2373 | * */ | ||
2374 | { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ | ||
2375 | { 0x12, KEY_POWER }, | ||
2376 | |||
2377 | /* 0x01 0x02 0x03 * | ||
2378 | * 1 2 3 * | ||
2379 | * * | ||
2380 | * 0x04 0x05 0x06 * | ||
2381 | * 4 5 6 * | ||
2382 | * * | ||
2383 | * 0x07 0x08 0x09 * | ||
2384 | * 7 8 9 * | ||
2385 | * */ | ||
2386 | { 0x01, KEY_1 }, | ||
2387 | { 0x02, KEY_2 }, | ||
2388 | { 0x03, KEY_3 }, | ||
2389 | { 0x04, KEY_4 }, | ||
2390 | { 0x05, KEY_5 }, | ||
2391 | { 0x06, KEY_6 }, | ||
2392 | { 0x07, KEY_7 }, | ||
2393 | { 0x08, KEY_8 }, | ||
2394 | { 0x09, KEY_9 }, | ||
2395 | |||
2396 | /* 0x0a 0x00 0x17 * | ||
2397 | * RECALL 0 MODE * | ||
2398 | * */ | ||
2399 | { 0x0a, KEY_AGAIN }, | ||
2400 | { 0x00, KEY_0 }, | ||
2401 | { 0x17, KEY_MODE }, | ||
2402 | |||
2403 | /* 0x14 0x10 * | ||
2404 | * ASPECT FULLSCREEN * | ||
2405 | * */ | ||
2406 | { 0x14, KEY_SCREEN }, | ||
2407 | { 0x10, KEY_ZOOM }, | ||
2408 | |||
2409 | /* 0x0b * | ||
2410 | * Up * | ||
2411 | * * | ||
2412 | * 0x18 0x16 0x0c * | ||
2413 | * Left Ok Right * | ||
2414 | * * | ||
2415 | * 0x015 * | ||
2416 | * Down * | ||
2417 | * */ | ||
2418 | { 0x0b, KEY_CHANNELUP }, | ||
2419 | { 0x18, KEY_VOLUMEDOWN }, | ||
2420 | { 0x16, KEY_OK }, /* XXX KEY_ENTER */ | ||
2421 | { 0x0c, KEY_VOLUMEUP }, | ||
2422 | { 0x15, KEY_CHANNELDOWN }, | ||
2423 | |||
2424 | /* 0x11 0x0d * | ||
2425 | * MUTE INFO * | ||
2426 | * */ | ||
2427 | { 0x11, KEY_MUTE }, | ||
2428 | { 0x0d, KEY_INFO }, | ||
2429 | |||
2430 | /* 0x0f 0x1b 0x1a * | ||
2431 | * RECORD PLAY/PAUSE STOP * | ||
2432 | * * | ||
2433 | * 0x0e 0x1f 0x1e * | ||
2434 | *TELETEXT AUDIO SOURCE * | ||
2435 | * RED YELLOW * | ||
2436 | * */ | ||
2437 | { 0x0f, KEY_RECORD }, | ||
2438 | { 0x1b, KEY_PLAYPAUSE }, | ||
2439 | { 0x1a, KEY_STOP }, | ||
2440 | { 0x0e, KEY_TEXT }, | ||
2441 | { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ | ||
2442 | { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ | ||
2443 | |||
2444 | /* 0x1d 0x13 0x19 * | ||
2445 | * SLEEP PREVIEW DVB * | ||
2446 | * GREEN BLUE * | ||
2447 | * */ | ||
2448 | { 0x1d, KEY_SLEEP }, | ||
2449 | { 0x13, KEY_GREEN }, | ||
2450 | { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ | ||
2451 | |||
2452 | /* 0x58 0x5c * | ||
2453 | * FREEZE SNAPSHOT * | ||
2454 | * */ | ||
2455 | { 0x58, KEY_SLOW }, | ||
2456 | { 0x5c, KEY_CAMERA }, | ||
2457 | |||
2458 | }; | ||
2459 | |||
2460 | struct ir_scancode_table ir_codes_behold_table = { | ||
2461 | .scan = ir_codes_behold, | ||
2462 | .size = ARRAY_SIZE(ir_codes_behold), | ||
2463 | }; | ||
2464 | EXPORT_SYMBOL_GPL(ir_codes_behold_table); | ||
2465 | |||
2466 | /* Beholder Intl. Ltd. 2008 | ||
2467 | * Dmitry Belimov d.belimov@google.com | ||
2468 | * Keytable is used by BeholdTV Columbus | ||
2469 | * The "ascii-art picture" below (in comments, first row | ||
2470 | * is the keycode in hex, and subsequent row(s) shows | ||
2471 | * the button labels (several variants when appropriate) | ||
2472 | * helps to descide which keycodes to assign to the buttons. | ||
2473 | */ | ||
2474 | static struct ir_scancode ir_codes_behold_columbus[] = { | ||
2475 | |||
2476 | /* 0x13 0x11 0x1C 0x12 * | ||
2477 | * Mute Source TV/FM Power * | ||
2478 | * */ | ||
2479 | |||
2480 | { 0x13, KEY_MUTE }, | ||
2481 | { 0x11, KEY_PROPS }, | ||
2482 | { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ | ||
2483 | { 0x12, KEY_POWER }, | ||
2484 | |||
2485 | /* 0x01 0x02 0x03 0x0D * | ||
2486 | * 1 2 3 Stereo * | ||
2487 | * * | ||
2488 | * 0x04 0x05 0x06 0x19 * | ||
2489 | * 4 5 6 Snapshot * | ||
2490 | * * | ||
2491 | * 0x07 0x08 0x09 0x10 * | ||
2492 | * 7 8 9 Zoom * | ||
2493 | * */ | ||
2494 | { 0x01, KEY_1 }, | ||
2495 | { 0x02, KEY_2 }, | ||
2496 | { 0x03, KEY_3 }, | ||
2497 | { 0x0D, KEY_SETUP }, /* Setup key */ | ||
2498 | { 0x04, KEY_4 }, | ||
2499 | { 0x05, KEY_5 }, | ||
2500 | { 0x06, KEY_6 }, | ||
2501 | { 0x19, KEY_CAMERA }, /* Snapshot key */ | ||
2502 | { 0x07, KEY_7 }, | ||
2503 | { 0x08, KEY_8 }, | ||
2504 | { 0x09, KEY_9 }, | ||
2505 | { 0x10, KEY_ZOOM }, | ||
2506 | |||
2507 | /* 0x0A 0x00 0x0B 0x0C * | ||
2508 | * RECALL 0 ChannelUp VolumeUp * | ||
2509 | * */ | ||
2510 | { 0x0A, KEY_AGAIN }, | ||
2511 | { 0x00, KEY_0 }, | ||
2512 | { 0x0B, KEY_CHANNELUP }, | ||
2513 | { 0x0C, KEY_VOLUMEUP }, | ||
2514 | |||
2515 | /* 0x1B 0x1D 0x15 0x18 * | ||
2516 | * Timeshift Record ChannelDown VolumeDown * | ||
2517 | * */ | ||
2518 | |||
2519 | { 0x1B, KEY_TIME }, | ||
2520 | { 0x1D, KEY_RECORD }, | ||
2521 | { 0x15, KEY_CHANNELDOWN }, | ||
2522 | { 0x18, KEY_VOLUMEDOWN }, | ||
2523 | |||
2524 | /* 0x0E 0x1E 0x0F 0x1A * | ||
2525 | * Stop Pause Previouse Next * | ||
2526 | * */ | ||
2527 | |||
2528 | { 0x0E, KEY_STOP }, | ||
2529 | { 0x1E, KEY_PAUSE }, | ||
2530 | { 0x0F, KEY_PREVIOUS }, | ||
2531 | { 0x1A, KEY_NEXT }, | ||
2532 | |||
2533 | }; | ||
2534 | |||
2535 | struct ir_scancode_table ir_codes_behold_columbus_table = { | ||
2536 | .scan = ir_codes_behold_columbus, | ||
2537 | .size = ARRAY_SIZE(ir_codes_behold_columbus), | ||
2538 | }; | ||
2539 | EXPORT_SYMBOL_GPL(ir_codes_behold_columbus_table); | ||
2540 | |||
2541 | /* | ||
2542 | * Remote control for the Genius TVGO A11MCE | ||
2543 | * Adrian Pardini <pardo.bsso@gmail.com> | ||
2544 | */ | ||
2545 | static struct ir_scancode ir_codes_genius_tvgo_a11mce[] = { | ||
2546 | /* Keys 0 to 9 */ | ||
2547 | { 0x48, KEY_0 }, | ||
2548 | { 0x09, KEY_1 }, | ||
2549 | { 0x1d, KEY_2 }, | ||
2550 | { 0x1f, KEY_3 }, | ||
2551 | { 0x19, KEY_4 }, | ||
2552 | { 0x1b, KEY_5 }, | ||
2553 | { 0x11, KEY_6 }, | ||
2554 | { 0x17, KEY_7 }, | ||
2555 | { 0x12, KEY_8 }, | ||
2556 | { 0x16, KEY_9 }, | ||
2557 | |||
2558 | { 0x54, KEY_RECORD }, /* recording */ | ||
2559 | { 0x06, KEY_MUTE }, /* mute */ | ||
2560 | { 0x10, KEY_POWER }, | ||
2561 | { 0x40, KEY_LAST }, /* recall */ | ||
2562 | { 0x4c, KEY_CHANNELUP }, /* channel / program + */ | ||
2563 | { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ | ||
2564 | { 0x0d, KEY_VOLUMEUP }, | ||
2565 | { 0x15, KEY_VOLUMEDOWN }, | ||
2566 | { 0x4d, KEY_OK }, /* also labeled as Pause */ | ||
2567 | { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ | ||
2568 | { 0x02, KEY_MODE }, /* AV Source or Rewind*/ | ||
2569 | { 0x04, KEY_LIST }, /* -/-- */ | ||
2570 | /* small arrows above numbers */ | ||
2571 | { 0x1a, KEY_NEXT }, /* also Fast Forward */ | ||
2572 | { 0x0e, KEY_PREVIOUS }, /* also Rewind */ | ||
2573 | /* these are in a rather non standard layout and have | ||
2574 | an alternate name written */ | ||
2575 | { 0x1e, KEY_UP }, /* Video Setting */ | ||
2576 | { 0x0a, KEY_DOWN }, /* Video Default */ | ||
2577 | { 0x05, KEY_CAMERA }, /* Snapshot */ | ||
2578 | { 0x0c, KEY_RIGHT }, /* Hide Panel */ | ||
2579 | /* Four buttons without label */ | ||
2580 | { 0x49, KEY_RED }, | ||
2581 | { 0x0b, KEY_GREEN }, | ||
2582 | { 0x13, KEY_YELLOW }, | ||
2583 | { 0x50, KEY_BLUE }, | ||
2584 | }; | ||
2585 | |||
2586 | struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table = { | ||
2587 | .scan = ir_codes_genius_tvgo_a11mce, | ||
2588 | .size = ARRAY_SIZE(ir_codes_genius_tvgo_a11mce), | ||
2589 | }; | ||
2590 | EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce_table); | ||
2591 | |||
2592 | /* | ||
2593 | * Remote control for Powercolor Real Angel 330 | ||
2594 | * Daniel Fraga <fragabr@gmail.com> | ||
2595 | */ | ||
2596 | static struct ir_scancode ir_codes_powercolor_real_angel[] = { | ||
2597 | { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ | ||
2598 | { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ | ||
2599 | { 0x00, KEY_0 }, | ||
2600 | { 0x01, KEY_1 }, | ||
2601 | { 0x02, KEY_2 }, | ||
2602 | { 0x03, KEY_3 }, | ||
2603 | { 0x04, KEY_4 }, | ||
2604 | { 0x05, KEY_5 }, | ||
2605 | { 0x06, KEY_6 }, | ||
2606 | { 0x07, KEY_7 }, | ||
2607 | { 0x08, KEY_8 }, | ||
2608 | { 0x09, KEY_9 }, | ||
2609 | { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ | ||
2610 | { 0x29, KEY_PREVIOUS }, /* previous channel */ | ||
2611 | { 0x12, KEY_BRIGHTNESSUP }, | ||
2612 | { 0x13, KEY_BRIGHTNESSDOWN }, | ||
2613 | { 0x2b, KEY_MODE }, /* stereo/mono */ | ||
2614 | { 0x2c, KEY_TEXT }, /* teletext */ | ||
2615 | { 0x20, KEY_CHANNELUP }, /* channel up */ | ||
2616 | { 0x21, KEY_CHANNELDOWN }, /* channel down */ | ||
2617 | { 0x10, KEY_VOLUMEUP }, /* volume up */ | ||
2618 | { 0x11, KEY_VOLUMEDOWN }, /* volume down */ | ||
2619 | { 0x0d, KEY_MUTE }, | ||
2620 | { 0x1f, KEY_RECORD }, | ||
2621 | { 0x17, KEY_PLAY }, | ||
2622 | { 0x16, KEY_PAUSE }, | ||
2623 | { 0x0b, KEY_STOP }, | ||
2624 | { 0x27, KEY_FASTFORWARD }, | ||
2625 | { 0x26, KEY_REWIND }, | ||
2626 | { 0x1e, KEY_SEARCH }, /* autoscan */ | ||
2627 | { 0x0e, KEY_CAMERA }, /* snapshot */ | ||
2628 | { 0x2d, KEY_SETUP }, | ||
2629 | { 0x0f, KEY_SCREEN }, /* full screen */ | ||
2630 | { 0x14, KEY_RADIO }, /* FM radio */ | ||
2631 | { 0x25, KEY_POWER }, /* power */ | ||
2632 | }; | ||
2633 | |||
2634 | struct ir_scancode_table ir_codes_powercolor_real_angel_table = { | ||
2635 | .scan = ir_codes_powercolor_real_angel, | ||
2636 | .size = ARRAY_SIZE(ir_codes_powercolor_real_angel), | ||
2637 | }; | ||
2638 | EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel_table); | ||
2639 | |||
2640 | /* Kworld Plus TV Analog Lite PCI IR | ||
2641 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
2642 | */ | ||
2643 | static struct ir_scancode ir_codes_kworld_plus_tv_analog[] = { | ||
2644 | { 0x0c, KEY_PROG1 }, /* Kworld key */ | ||
2645 | { 0x16, KEY_CLOSECD }, /* -> ) */ | ||
2646 | { 0x1d, KEY_POWER2 }, | ||
2647 | |||
2648 | { 0x00, KEY_1 }, | ||
2649 | { 0x01, KEY_2 }, | ||
2650 | { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ | ||
2651 | { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ | ||
2652 | { 0x04, KEY_5 }, | ||
2653 | { 0x05, KEY_6 }, | ||
2654 | { 0x06, KEY_7 }, | ||
2655 | { 0x07, KEY_8 }, | ||
2656 | { 0x08, KEY_9 }, | ||
2657 | { 0x0a, KEY_0 }, | ||
2658 | |||
2659 | { 0x09, KEY_AGAIN }, | ||
2660 | { 0x14, KEY_MUTE }, | ||
2661 | |||
2662 | { 0x20, KEY_UP }, | ||
2663 | { 0x21, KEY_DOWN }, | ||
2664 | { 0x0b, KEY_ENTER }, | ||
2665 | |||
2666 | { 0x10, KEY_CHANNELUP }, | ||
2667 | { 0x11, KEY_CHANNELDOWN }, | ||
2668 | |||
2669 | /* Couldn't map key left/key right since those | ||
2670 | conflict with '3' and '4' scancodes | ||
2671 | I dunno what the original driver does | ||
2672 | */ | ||
2673 | |||
2674 | { 0x13, KEY_VOLUMEUP }, | ||
2675 | { 0x12, KEY_VOLUMEDOWN }, | ||
2676 | |||
2677 | /* The lower part of the IR | ||
2678 | There are several duplicated keycodes there. | ||
2679 | Most of them conflict with digits. | ||
2680 | Add mappings just to the unused scancodes. | ||
2681 | Somehow, the original driver has a way to know, | ||
2682 | but this doesn't seem to be on some GPIO. | ||
2683 | Also, it is not related to the time between keyup | ||
2684 | and keydown. | ||
2685 | */ | ||
2686 | { 0x19, KEY_TIME}, /* Timeshift */ | ||
2687 | { 0x1a, KEY_STOP}, | ||
2688 | { 0x1b, KEY_RECORD}, | ||
2689 | |||
2690 | { 0x22, KEY_TEXT}, | ||
2691 | |||
2692 | { 0x15, KEY_AUDIO}, /* ((*)) */ | ||
2693 | { 0x0f, KEY_ZOOM}, | ||
2694 | { 0x1c, KEY_CAMERA}, /* snapshot */ | ||
2695 | |||
2696 | { 0x18, KEY_RED}, /* B */ | ||
2697 | { 0x23, KEY_GREEN}, /* C */ | ||
2698 | }; | ||
2699 | struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table = { | ||
2700 | .scan = ir_codes_kworld_plus_tv_analog, | ||
2701 | .size = ARRAY_SIZE(ir_codes_kworld_plus_tv_analog), | ||
2702 | }; | ||
2703 | EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); | ||
2704 | |||
2705 | /* Kaiomy TVnPC U2 | ||
2706 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
2707 | */ | ||
2708 | static struct ir_scancode ir_codes_kaiomy[] = { | ||
2709 | { 0x43, KEY_POWER2}, | ||
2710 | { 0x01, KEY_LIST}, | ||
2711 | { 0x0b, KEY_ZOOM}, | ||
2712 | { 0x03, KEY_POWER}, | ||
2713 | |||
2714 | { 0x04, KEY_1}, | ||
2715 | { 0x08, KEY_2}, | ||
2716 | { 0x02, KEY_3}, | ||
2717 | |||
2718 | { 0x0f, KEY_4}, | ||
2719 | { 0x05, KEY_5}, | ||
2720 | { 0x06, KEY_6}, | ||
2721 | |||
2722 | { 0x0c, KEY_7}, | ||
2723 | { 0x0d, KEY_8}, | ||
2724 | { 0x0a, KEY_9}, | ||
2725 | |||
2726 | { 0x11, KEY_0}, | ||
2727 | |||
2728 | { 0x09, KEY_CHANNELUP}, | ||
2729 | { 0x07, KEY_CHANNELDOWN}, | ||
2730 | |||
2731 | { 0x0e, KEY_VOLUMEUP}, | ||
2732 | { 0x13, KEY_VOLUMEDOWN}, | ||
2733 | |||
2734 | { 0x10, KEY_HOME}, | ||
2735 | { 0x12, KEY_ENTER}, | ||
2736 | |||
2737 | { 0x14, KEY_RECORD}, | ||
2738 | { 0x15, KEY_STOP}, | ||
2739 | { 0x16, KEY_PLAY}, | ||
2740 | { 0x17, KEY_MUTE}, | ||
2741 | |||
2742 | { 0x18, KEY_UP}, | ||
2743 | { 0x19, KEY_DOWN}, | ||
2744 | { 0x1a, KEY_LEFT}, | ||
2745 | { 0x1b, KEY_RIGHT}, | ||
2746 | |||
2747 | { 0x1c, KEY_RED}, | ||
2748 | { 0x1d, KEY_GREEN}, | ||
2749 | { 0x1e, KEY_YELLOW}, | ||
2750 | { 0x1f, KEY_BLUE}, | ||
2751 | }; | ||
2752 | struct ir_scancode_table ir_codes_kaiomy_table = { | ||
2753 | .scan = ir_codes_kaiomy, | ||
2754 | .size = ARRAY_SIZE(ir_codes_kaiomy), | ||
2755 | }; | ||
2756 | EXPORT_SYMBOL_GPL(ir_codes_kaiomy_table); | ||
2757 | |||
2758 | static struct ir_scancode ir_codes_avermedia_a16d[] = { | ||
2759 | { 0x20, KEY_LIST}, | ||
2760 | { 0x00, KEY_POWER}, | ||
2761 | { 0x28, KEY_1}, | ||
2762 | { 0x18, KEY_2}, | ||
2763 | { 0x38, KEY_3}, | ||
2764 | { 0x24, KEY_4}, | ||
2765 | { 0x14, KEY_5}, | ||
2766 | { 0x34, KEY_6}, | ||
2767 | { 0x2c, KEY_7}, | ||
2768 | { 0x1c, KEY_8}, | ||
2769 | { 0x3c, KEY_9}, | ||
2770 | { 0x12, KEY_SUBTITLE}, | ||
2771 | { 0x22, KEY_0}, | ||
2772 | { 0x32, KEY_REWIND}, | ||
2773 | { 0x3a, KEY_SHUFFLE}, | ||
2774 | { 0x02, KEY_PRINT}, | ||
2775 | { 0x11, KEY_CHANNELDOWN}, | ||
2776 | { 0x31, KEY_CHANNELUP}, | ||
2777 | { 0x0c, KEY_ZOOM}, | ||
2778 | { 0x1e, KEY_VOLUMEDOWN}, | ||
2779 | { 0x3e, KEY_VOLUMEUP}, | ||
2780 | { 0x0a, KEY_MUTE}, | ||
2781 | { 0x04, KEY_AUDIO}, | ||
2782 | { 0x26, KEY_RECORD}, | ||
2783 | { 0x06, KEY_PLAY}, | ||
2784 | { 0x36, KEY_STOP}, | ||
2785 | { 0x16, KEY_PAUSE}, | ||
2786 | { 0x2e, KEY_REWIND}, | ||
2787 | { 0x0e, KEY_FASTFORWARD}, | ||
2788 | { 0x30, KEY_TEXT}, | ||
2789 | { 0x21, KEY_GREEN}, | ||
2790 | { 0x01, KEY_BLUE}, | ||
2791 | { 0x08, KEY_EPG}, | ||
2792 | { 0x2a, KEY_MENU}, | ||
2793 | }; | ||
2794 | struct ir_scancode_table ir_codes_avermedia_a16d_table = { | ||
2795 | .scan = ir_codes_avermedia_a16d, | ||
2796 | .size = ARRAY_SIZE(ir_codes_avermedia_a16d), | ||
2797 | }; | ||
2798 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d_table); | ||
2799 | |||
2800 | /* Encore ENLTV-FM v5.3 | ||
2801 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
2802 | */ | ||
2803 | static struct ir_scancode ir_codes_encore_enltv_fm53[] = { | ||
2804 | { 0x10, KEY_POWER2}, | ||
2805 | { 0x06, KEY_MUTE}, | ||
2806 | |||
2807 | { 0x09, KEY_1}, | ||
2808 | { 0x1d, KEY_2}, | ||
2809 | { 0x1f, KEY_3}, | ||
2810 | { 0x19, KEY_4}, | ||
2811 | { 0x1b, KEY_5}, | ||
2812 | { 0x11, KEY_6}, | ||
2813 | { 0x17, KEY_7}, | ||
2814 | { 0x12, KEY_8}, | ||
2815 | { 0x16, KEY_9}, | ||
2816 | { 0x48, KEY_0}, | ||
2817 | |||
2818 | { 0x04, KEY_LIST}, /* -/-- */ | ||
2819 | { 0x40, KEY_LAST}, /* recall */ | ||
2820 | |||
2821 | { 0x02, KEY_MODE}, /* TV/AV */ | ||
2822 | { 0x05, KEY_CAMERA}, /* SNAPSHOT */ | ||
2823 | |||
2824 | { 0x4c, KEY_CHANNELUP}, /* UP */ | ||
2825 | { 0x00, KEY_CHANNELDOWN}, /* DOWN */ | ||
2826 | { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ | ||
2827 | { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ | ||
2828 | { 0x49, KEY_ENTER}, /* OK */ | ||
2829 | |||
2830 | { 0x54, KEY_RECORD}, | ||
2831 | { 0x4d, KEY_PLAY}, /* pause */ | ||
2832 | |||
2833 | { 0x1e, KEY_MENU}, /* video setting */ | ||
2834 | { 0x0e, KEY_RIGHT}, /* <- */ | ||
2835 | { 0x1a, KEY_LEFT}, /* -> */ | ||
2836 | |||
2837 | { 0x0a, KEY_CLEAR}, /* video default */ | ||
2838 | { 0x0c, KEY_ZOOM}, /* hide pannel */ | ||
2839 | { 0x47, KEY_SLEEP}, /* shutdown */ | ||
2840 | }; | ||
2841 | struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { | ||
2842 | .scan = ir_codes_encore_enltv_fm53, | ||
2843 | .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), | ||
2844 | }; | ||
2845 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53_table); | ||
2846 | |||
2847 | /* Zogis Real Audio 220 - 32 keys IR */ | ||
2848 | static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { | ||
2849 | { 0x1c, KEY_RADIO}, | ||
2850 | { 0x12, KEY_POWER2}, | ||
2851 | |||
2852 | { 0x01, KEY_1}, | ||
2853 | { 0x02, KEY_2}, | ||
2854 | { 0x03, KEY_3}, | ||
2855 | { 0x04, KEY_4}, | ||
2856 | { 0x05, KEY_5}, | ||
2857 | { 0x06, KEY_6}, | ||
2858 | { 0x07, KEY_7}, | ||
2859 | { 0x08, KEY_8}, | ||
2860 | { 0x09, KEY_9}, | ||
2861 | { 0x00, KEY_0}, | ||
2862 | |||
2863 | { 0x0c, KEY_VOLUMEUP}, | ||
2864 | { 0x18, KEY_VOLUMEDOWN}, | ||
2865 | { 0x0b, KEY_CHANNELUP}, | ||
2866 | { 0x15, KEY_CHANNELDOWN}, | ||
2867 | { 0x16, KEY_ENTER}, | ||
2868 | |||
2869 | { 0x11, KEY_LIST}, /* Source */ | ||
2870 | { 0x0d, KEY_AUDIO}, /* stereo */ | ||
2871 | |||
2872 | { 0x0f, KEY_PREVIOUS}, /* Prev */ | ||
2873 | { 0x1b, KEY_TIME}, /* Timeshift */ | ||
2874 | { 0x1a, KEY_NEXT}, /* Next */ | ||
2875 | |||
2876 | { 0x0e, KEY_STOP}, | ||
2877 | { 0x1f, KEY_PLAY}, | ||
2878 | { 0x1e, KEY_PLAYPAUSE}, /* Pause */ | ||
2879 | |||
2880 | { 0x1d, KEY_RECORD}, | ||
2881 | { 0x13, KEY_MUTE}, | ||
2882 | { 0x19, KEY_CAMERA}, /* Snapshot */ | ||
2883 | |||
2884 | }; | ||
2885 | struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { | ||
2886 | .scan = ir_codes_real_audio_220_32_keys, | ||
2887 | .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), | ||
2888 | }; | ||
2889 | EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys_table); | ||
2890 | |||
2891 | /* ATI TV Wonder HD 600 USB | ||
2892 | Devin Heitmueller <devin.heitmueller@gmail.com> | ||
2893 | */ | ||
2894 | static struct ir_scancode ir_codes_ati_tv_wonder_hd_600[] = { | ||
2895 | { 0x00, KEY_RECORD}, /* Row 1 */ | ||
2896 | { 0x01, KEY_PLAYPAUSE}, | ||
2897 | { 0x02, KEY_STOP}, | ||
2898 | { 0x03, KEY_POWER}, | ||
2899 | { 0x04, KEY_PREVIOUS}, /* Row 2 */ | ||
2900 | { 0x05, KEY_REWIND}, | ||
2901 | { 0x06, KEY_FORWARD}, | ||
2902 | { 0x07, KEY_NEXT}, | ||
2903 | { 0x08, KEY_EPG}, /* Row 3 */ | ||
2904 | { 0x09, KEY_HOME}, | ||
2905 | { 0x0a, KEY_MENU}, | ||
2906 | { 0x0b, KEY_CHANNELUP}, | ||
2907 | { 0x0c, KEY_BACK}, /* Row 4 */ | ||
2908 | { 0x0d, KEY_UP}, | ||
2909 | { 0x0e, KEY_INFO}, | ||
2910 | { 0x0f, KEY_CHANNELDOWN}, | ||
2911 | { 0x10, KEY_LEFT}, /* Row 5 */ | ||
2912 | { 0x11, KEY_SELECT}, | ||
2913 | { 0x12, KEY_RIGHT}, | ||
2914 | { 0x13, KEY_VOLUMEUP}, | ||
2915 | { 0x14, KEY_LAST}, /* Row 6 */ | ||
2916 | { 0x15, KEY_DOWN}, | ||
2917 | { 0x16, KEY_MUTE}, | ||
2918 | { 0x17, KEY_VOLUMEDOWN}, | ||
2919 | }; | ||
2920 | struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { | ||
2921 | .scan = ir_codes_ati_tv_wonder_hd_600, | ||
2922 | .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), | ||
2923 | }; | ||
2924 | EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600_table); | ||
2925 | |||
2926 | /* DVBWorld remotes | ||
2927 | Igor M. Liplianin <liplianin@me.by> | ||
2928 | */ | ||
2929 | static struct ir_scancode ir_codes_dm1105_nec[] = { | ||
2930 | { 0x0a, KEY_POWER2}, /* power */ | ||
2931 | { 0x0c, KEY_MUTE}, /* mute */ | ||
2932 | { 0x11, KEY_1}, | ||
2933 | { 0x12, KEY_2}, | ||
2934 | { 0x13, KEY_3}, | ||
2935 | { 0x14, KEY_4}, | ||
2936 | { 0x15, KEY_5}, | ||
2937 | { 0x16, KEY_6}, | ||
2938 | { 0x17, KEY_7}, | ||
2939 | { 0x18, KEY_8}, | ||
2940 | { 0x19, KEY_9}, | ||
2941 | { 0x10, KEY_0}, | ||
2942 | { 0x1c, KEY_CHANNELUP}, /* ch+ */ | ||
2943 | { 0x0f, KEY_CHANNELDOWN}, /* ch- */ | ||
2944 | { 0x1a, KEY_VOLUMEUP}, /* vol+ */ | ||
2945 | { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ | ||
2946 | { 0x04, KEY_RECORD}, /* rec */ | ||
2947 | { 0x09, KEY_CHANNEL}, /* fav */ | ||
2948 | { 0x08, KEY_BACKSPACE}, /* rewind */ | ||
2949 | { 0x07, KEY_FASTFORWARD}, /* fast */ | ||
2950 | { 0x0b, KEY_PAUSE}, /* pause */ | ||
2951 | { 0x02, KEY_ESC}, /* cancel */ | ||
2952 | { 0x03, KEY_TAB}, /* tab */ | ||
2953 | { 0x00, KEY_UP}, /* up */ | ||
2954 | { 0x1f, KEY_ENTER}, /* ok */ | ||
2955 | { 0x01, KEY_DOWN}, /* down */ | ||
2956 | { 0x05, KEY_RECORD}, /* cap */ | ||
2957 | { 0x06, KEY_STOP}, /* stop */ | ||
2958 | { 0x40, KEY_ZOOM}, /* full */ | ||
2959 | { 0x1e, KEY_TV}, /* tvmode */ | ||
2960 | { 0x1b, KEY_B}, /* recall */ | ||
2961 | }; | ||
2962 | struct ir_scancode_table ir_codes_dm1105_nec_table = { | ||
2963 | .scan = ir_codes_dm1105_nec, | ||
2964 | .size = ARRAY_SIZE(ir_codes_dm1105_nec), | ||
2965 | }; | ||
2966 | EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); | ||
2967 | |||
2968 | static struct ir_scancode ir_codes_tevii_nec[] = { | ||
2969 | { 0x0a, KEY_POWER2}, | ||
2970 | { 0x0c, KEY_MUTE}, | ||
2971 | { 0x11, KEY_1}, | ||
2972 | { 0x12, KEY_2}, | ||
2973 | { 0x13, KEY_3}, | ||
2974 | { 0x14, KEY_4}, | ||
2975 | { 0x15, KEY_5}, | ||
2976 | { 0x16, KEY_6}, | ||
2977 | { 0x17, KEY_7}, | ||
2978 | { 0x18, KEY_8}, | ||
2979 | { 0x19, KEY_9}, | ||
2980 | { 0x10, KEY_0}, | ||
2981 | { 0x1c, KEY_MENU}, | ||
2982 | { 0x0f, KEY_VOLUMEDOWN}, | ||
2983 | { 0x1a, KEY_LAST}, | ||
2984 | { 0x0e, KEY_OPEN}, | ||
2985 | { 0x04, KEY_RECORD}, | ||
2986 | { 0x09, KEY_VOLUMEUP}, | ||
2987 | { 0x08, KEY_CHANNELUP}, | ||
2988 | { 0x07, KEY_PVR}, | ||
2989 | { 0x0b, KEY_TIME}, | ||
2990 | { 0x02, KEY_RIGHT}, | ||
2991 | { 0x03, KEY_LEFT}, | ||
2992 | { 0x00, KEY_UP}, | ||
2993 | { 0x1f, KEY_OK}, | ||
2994 | { 0x01, KEY_DOWN}, | ||
2995 | { 0x05, KEY_TUNER}, | ||
2996 | { 0x06, KEY_CHANNELDOWN}, | ||
2997 | { 0x40, KEY_PLAYPAUSE}, | ||
2998 | { 0x1e, KEY_REWIND}, | ||
2999 | { 0x1b, KEY_FAVORITES}, | ||
3000 | { 0x1d, KEY_BACK}, | ||
3001 | { 0x4d, KEY_FASTFORWARD}, | ||
3002 | { 0x44, KEY_EPG}, | ||
3003 | { 0x4c, KEY_INFO}, | ||
3004 | { 0x41, KEY_AB}, | ||
3005 | { 0x43, KEY_AUDIO}, | ||
3006 | { 0x45, KEY_SUBTITLE}, | ||
3007 | { 0x4a, KEY_LIST}, | ||
3008 | { 0x46, KEY_F1}, | ||
3009 | { 0x47, KEY_F2}, | ||
3010 | { 0x5e, KEY_F3}, | ||
3011 | { 0x5c, KEY_F4}, | ||
3012 | { 0x52, KEY_F5}, | ||
3013 | { 0x5a, KEY_F6}, | ||
3014 | { 0x56, KEY_MODE}, | ||
3015 | { 0x58, KEY_SWITCHVIDEOMODE}, | ||
3016 | }; | ||
3017 | struct ir_scancode_table ir_codes_tevii_nec_table = { | ||
3018 | .scan = ir_codes_tevii_nec, | ||
3019 | .size = ARRAY_SIZE(ir_codes_tevii_nec), | ||
3020 | }; | ||
3021 | EXPORT_SYMBOL_GPL(ir_codes_tevii_nec_table); | ||
3022 | |||
3023 | static struct ir_scancode ir_codes_tbs_nec[] = { | ||
3024 | { 0x04, KEY_POWER2}, /*power*/ | ||
3025 | { 0x14, KEY_MUTE}, /*mute*/ | ||
3026 | { 0x07, KEY_1}, | ||
3027 | { 0x06, KEY_2}, | ||
3028 | { 0x05, KEY_3}, | ||
3029 | { 0x0b, KEY_4}, | ||
3030 | { 0x0a, KEY_5}, | ||
3031 | { 0x09, KEY_6}, | ||
3032 | { 0x0f, KEY_7}, | ||
3033 | { 0x0e, KEY_8}, | ||
3034 | { 0x0d, KEY_9}, | ||
3035 | { 0x12, KEY_0}, | ||
3036 | { 0x16, KEY_CHANNELUP}, /*ch+*/ | ||
3037 | { 0x11, KEY_CHANNELDOWN},/*ch-*/ | ||
3038 | { 0x13, KEY_VOLUMEUP}, /*vol+*/ | ||
3039 | { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ | ||
3040 | { 0x03, KEY_RECORD}, /*rec*/ | ||
3041 | { 0x18, KEY_PAUSE}, /*pause*/ | ||
3042 | { 0x19, KEY_OK}, /*ok*/ | ||
3043 | { 0x1a, KEY_CAMERA}, /* snapshot */ | ||
3044 | { 0x01, KEY_UP}, | ||
3045 | { 0x10, KEY_LEFT}, | ||
3046 | { 0x02, KEY_RIGHT}, | ||
3047 | { 0x08, KEY_DOWN}, | ||
3048 | { 0x15, KEY_FAVORITES}, | ||
3049 | { 0x17, KEY_SUBTITLE}, | ||
3050 | { 0x1d, KEY_ZOOM}, | ||
3051 | { 0x1f, KEY_EXIT}, | ||
3052 | { 0x1e, KEY_MENU}, | ||
3053 | { 0x1c, KEY_EPG}, | ||
3054 | { 0x00, KEY_PREVIOUS}, | ||
3055 | { 0x1b, KEY_MODE}, | ||
3056 | }; | ||
3057 | struct ir_scancode_table ir_codes_tbs_nec_table = { | ||
3058 | .scan = ir_codes_tbs_nec, | ||
3059 | .size = ARRAY_SIZE(ir_codes_tbs_nec), | ||
3060 | }; | ||
3061 | EXPORT_SYMBOL_GPL(ir_codes_tbs_nec_table); | ||
3062 | |||
3063 | /* Terratec Cinergy Hybrid T USB XS | ||
3064 | Devin Heitmueller <dheitmueller@linuxtv.org> | ||
3065 | */ | ||
3066 | static struct ir_scancode ir_codes_terratec_cinergy_xs[] = { | ||
3067 | { 0x41, KEY_HOME}, | ||
3068 | { 0x01, KEY_POWER}, | ||
3069 | { 0x42, KEY_MENU}, | ||
3070 | { 0x02, KEY_1}, | ||
3071 | { 0x03, KEY_2}, | ||
3072 | { 0x04, KEY_3}, | ||
3073 | { 0x43, KEY_SUBTITLE}, | ||
3074 | { 0x05, KEY_4}, | ||
3075 | { 0x06, KEY_5}, | ||
3076 | { 0x07, KEY_6}, | ||
3077 | { 0x44, KEY_TEXT}, | ||
3078 | { 0x08, KEY_7}, | ||
3079 | { 0x09, KEY_8}, | ||
3080 | { 0x0a, KEY_9}, | ||
3081 | { 0x45, KEY_DELETE}, | ||
3082 | { 0x0b, KEY_TUNER}, | ||
3083 | { 0x0c, KEY_0}, | ||
3084 | { 0x0d, KEY_MODE}, | ||
3085 | { 0x46, KEY_TV}, | ||
3086 | { 0x47, KEY_DVD}, | ||
3087 | { 0x49, KEY_VIDEO}, | ||
3088 | { 0x4b, KEY_AUX}, | ||
3089 | { 0x10, KEY_UP}, | ||
3090 | { 0x11, KEY_LEFT}, | ||
3091 | { 0x12, KEY_OK}, | ||
3092 | { 0x13, KEY_RIGHT}, | ||
3093 | { 0x14, KEY_DOWN}, | ||
3094 | { 0x0f, KEY_EPG}, | ||
3095 | { 0x16, KEY_INFO}, | ||
3096 | { 0x4d, KEY_BACKSPACE}, | ||
3097 | { 0x1c, KEY_VOLUMEUP}, | ||
3098 | { 0x4c, KEY_PLAY}, | ||
3099 | { 0x1b, KEY_CHANNELUP}, | ||
3100 | { 0x1e, KEY_VOLUMEDOWN}, | ||
3101 | { 0x1d, KEY_MUTE}, | ||
3102 | { 0x1f, KEY_CHANNELDOWN}, | ||
3103 | { 0x17, KEY_RED}, | ||
3104 | { 0x18, KEY_GREEN}, | ||
3105 | { 0x19, KEY_YELLOW}, | ||
3106 | { 0x1a, KEY_BLUE}, | ||
3107 | { 0x58, KEY_RECORD}, | ||
3108 | { 0x48, KEY_STOP}, | ||
3109 | { 0x40, KEY_PAUSE}, | ||
3110 | { 0x54, KEY_LAST}, | ||
3111 | { 0x4e, KEY_REWIND}, | ||
3112 | { 0x4f, KEY_FASTFORWARD}, | ||
3113 | { 0x5c, KEY_NEXT}, | ||
3114 | }; | ||
3115 | struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { | ||
3116 | .scan = ir_codes_terratec_cinergy_xs, | ||
3117 | .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), | ||
3118 | }; | ||
3119 | EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs_table); | ||
3120 | |||
3121 | /* EVGA inDtube | ||
3122 | Devin Heitmueller <devin.heitmueller@gmail.com> | ||
3123 | */ | ||
3124 | static struct ir_scancode ir_codes_evga_indtube[] = { | ||
3125 | { 0x12, KEY_POWER}, | ||
3126 | { 0x02, KEY_MODE}, /* TV */ | ||
3127 | { 0x14, KEY_MUTE}, | ||
3128 | { 0x1a, KEY_CHANNELUP}, | ||
3129 | { 0x16, KEY_TV2}, /* PIP */ | ||
3130 | { 0x1d, KEY_VOLUMEUP}, | ||
3131 | { 0x05, KEY_CHANNELDOWN}, | ||
3132 | { 0x0f, KEY_PLAYPAUSE}, | ||
3133 | { 0x19, KEY_VOLUMEDOWN}, | ||
3134 | { 0x1c, KEY_REWIND}, | ||
3135 | { 0x0d, KEY_RECORD}, | ||
3136 | { 0x18, KEY_FORWARD}, | ||
3137 | { 0x1e, KEY_PREVIOUS}, | ||
3138 | { 0x1b, KEY_STOP}, | ||
3139 | { 0x1f, KEY_NEXT}, | ||
3140 | { 0x13, KEY_CAMERA}, | ||
3141 | }; | ||
3142 | struct ir_scancode_table ir_codes_evga_indtube_table = { | ||
3143 | .scan = ir_codes_evga_indtube, | ||
3144 | .size = ARRAY_SIZE(ir_codes_evga_indtube), | ||
3145 | }; | ||
3146 | EXPORT_SYMBOL_GPL(ir_codes_evga_indtube_table); | ||
3147 | |||
3148 | static struct ir_scancode ir_codes_videomate_s350[] = { | ||
3149 | { 0x00, KEY_TV}, | ||
3150 | { 0x01, KEY_DVD}, | ||
3151 | { 0x04, KEY_RECORD}, | ||
3152 | { 0x05, KEY_VIDEO}, /* TV/Video */ | ||
3153 | { 0x07, KEY_STOP}, | ||
3154 | { 0x08, KEY_PLAYPAUSE}, | ||
3155 | { 0x0a, KEY_REWIND}, | ||
3156 | { 0x0f, KEY_FASTFORWARD}, | ||
3157 | { 0x10, KEY_CHANNELUP}, | ||
3158 | { 0x12, KEY_VOLUMEUP}, | ||
3159 | { 0x13, KEY_CHANNELDOWN}, | ||
3160 | { 0x14, KEY_MUTE}, | ||
3161 | { 0x15, KEY_VOLUMEDOWN}, | ||
3162 | { 0x16, KEY_1}, | ||
3163 | { 0x17, KEY_2}, | ||
3164 | { 0x18, KEY_3}, | ||
3165 | { 0x19, KEY_4}, | ||
3166 | { 0x1a, KEY_5}, | ||
3167 | { 0x1b, KEY_6}, | ||
3168 | { 0x1c, KEY_7}, | ||
3169 | { 0x1d, KEY_8}, | ||
3170 | { 0x1e, KEY_9}, | ||
3171 | { 0x1f, KEY_0}, | ||
3172 | { 0x21, KEY_SLEEP}, | ||
3173 | { 0x24, KEY_ZOOM}, | ||
3174 | { 0x25, KEY_LAST}, /* Recall */ | ||
3175 | { 0x26, KEY_SUBTITLE}, /* CC */ | ||
3176 | { 0x27, KEY_LANGUAGE}, /* MTS */ | ||
3177 | { 0x29, KEY_CHANNEL}, /* SURF */ | ||
3178 | { 0x2b, KEY_A}, | ||
3179 | { 0x2c, KEY_B}, | ||
3180 | { 0x2f, KEY_CAMERA}, /* Snapshot */ | ||
3181 | { 0x23, KEY_RADIO}, | ||
3182 | { 0x02, KEY_PREVIOUSSONG}, | ||
3183 | { 0x06, KEY_NEXTSONG}, | ||
3184 | { 0x03, KEY_EPG}, | ||
3185 | { 0x09, KEY_SETUP}, | ||
3186 | { 0x22, KEY_BACKSPACE}, | ||
3187 | { 0x0c, KEY_UP}, | ||
3188 | { 0x0e, KEY_DOWN}, | ||
3189 | { 0x0b, KEY_LEFT}, | ||
3190 | { 0x0d, KEY_RIGHT}, | ||
3191 | { 0x11, KEY_ENTER}, | ||
3192 | { 0x20, KEY_TEXT}, | ||
3193 | }; | ||
3194 | struct ir_scancode_table ir_codes_videomate_s350_table = { | ||
3195 | .scan = ir_codes_videomate_s350, | ||
3196 | .size = ARRAY_SIZE(ir_codes_videomate_s350), | ||
3197 | }; | ||
3198 | EXPORT_SYMBOL_GPL(ir_codes_videomate_s350_table); | ||
3199 | |||
3200 | /* GADMEI UTV330+ RM008Z remote | ||
3201 | Shine Liu <shinel@foxmail.com> | ||
3202 | */ | ||
3203 | static struct ir_scancode ir_codes_gadmei_rm008z[] = { | ||
3204 | { 0x14, KEY_POWER2}, /* POWER OFF */ | ||
3205 | { 0x0c, KEY_MUTE}, /* MUTE */ | ||
3206 | |||
3207 | { 0x18, KEY_TV}, /* TV */ | ||
3208 | { 0x0e, KEY_VIDEO}, /* AV */ | ||
3209 | { 0x0b, KEY_AUDIO}, /* SV */ | ||
3210 | { 0x0f, KEY_RADIO}, /* FM */ | ||
3211 | |||
3212 | { 0x00, KEY_1}, | ||
3213 | { 0x01, KEY_2}, | ||
3214 | { 0x02, KEY_3}, | ||
3215 | { 0x03, KEY_4}, | ||
3216 | { 0x04, KEY_5}, | ||
3217 | { 0x05, KEY_6}, | ||
3218 | { 0x06, KEY_7}, | ||
3219 | { 0x07, KEY_8}, | ||
3220 | { 0x08, KEY_9}, | ||
3221 | { 0x09, KEY_0}, | ||
3222 | { 0x0a, KEY_INFO}, /* OSD */ | ||
3223 | { 0x1c, KEY_BACKSPACE}, /* LAST */ | ||
3224 | |||
3225 | { 0x0d, KEY_PLAY}, /* PLAY */ | ||
3226 | { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ | ||
3227 | { 0x1a, KEY_RECORD}, /* RECORD */ | ||
3228 | { 0x17, KEY_STOP}, /* STOP */ | ||
3229 | |||
3230 | { 0x1f, KEY_UP}, /* UP */ | ||
3231 | { 0x44, KEY_DOWN}, /* DOWN */ | ||
3232 | { 0x46, KEY_TAB}, /* BACK */ | ||
3233 | { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ | ||
3234 | |||
3235 | { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
3236 | { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
3237 | { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ | ||
3238 | { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
3239 | { 0x15, KEY_ENTER}, /* OK */ | ||
3240 | }; | ||
3241 | struct ir_scancode_table ir_codes_gadmei_rm008z_table = { | ||
3242 | .scan = ir_codes_gadmei_rm008z, | ||
3243 | .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), | ||
3244 | }; | ||
3245 | EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); | ||
3246 | |||
3247 | /************************************************************* | ||
3248 | * COMPLETE SCANCODE TABLES | ||
3249 | * Instead of just a partial scancode, the tables bellow | ||
3250 | * contains the complete scancode and the receiver protocol | ||
3251 | *************************************************************/ | ||
3252 | |||
3253 | /* | ||
3254 | * Hauppauge:the newer, gray remotes (seems there are multiple | ||
3255 | * slightly different versions), shipped with cx88+ivtv cards. | ||
3256 | * | ||
3257 | * This table contains the complete RC5 code, instead of just the data part | ||
3258 | */ | ||
3259 | static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { | ||
3260 | /* Keys 0 to 9 */ | ||
3261 | { 0x1e00, KEY_0 }, | ||
3262 | { 0x1e01, KEY_1 }, | ||
3263 | { 0x1e02, KEY_2 }, | ||
3264 | { 0x1e03, KEY_3 }, | ||
3265 | { 0x1e04, KEY_4 }, | ||
3266 | { 0x1e05, KEY_5 }, | ||
3267 | { 0x1e06, KEY_6 }, | ||
3268 | { 0x1e07, KEY_7 }, | ||
3269 | { 0x1e08, KEY_8 }, | ||
3270 | { 0x1e09, KEY_9 }, | ||
3271 | |||
3272 | { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
3273 | { 0x1e0b, KEY_RED }, /* red button */ | ||
3274 | { 0x1e0c, KEY_RADIO }, | ||
3275 | { 0x1e0d, KEY_MENU }, | ||
3276 | { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ | ||
3277 | { 0x1e0f, KEY_MUTE }, | ||
3278 | { 0x1e10, KEY_VOLUMEUP }, | ||
3279 | { 0x1e11, KEY_VOLUMEDOWN }, | ||
3280 | { 0x1e12, KEY_PREVIOUS }, /* previous channel */ | ||
3281 | { 0x1e14, KEY_UP }, | ||
3282 | { 0x1e15, KEY_DOWN }, | ||
3283 | { 0x1e16, KEY_LEFT }, | ||
3284 | { 0x1e17, KEY_RIGHT }, | ||
3285 | { 0x1e18, KEY_VIDEO }, /* Videos */ | ||
3286 | { 0x1e19, KEY_AUDIO }, /* Music */ | ||
3287 | /* 0x1e1a: Pictures - presume this means | ||
3288 | "Multimedia Home Platform" - | ||
3289 | no "PICTURES" key in input.h | ||
3290 | */ | ||
3291 | { 0x1e1a, KEY_MHP }, | ||
3292 | |||
3293 | { 0x1e1b, KEY_EPG }, /* Guide */ | ||
3294 | { 0x1e1c, KEY_TV }, | ||
3295 | { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ | ||
3296 | { 0x1e1f, KEY_EXIT }, /* back/exit */ | ||
3297 | { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ | ||
3298 | { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
3299 | { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ | ||
3300 | { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
3301 | { 0x1e25, KEY_ENTER }, /* OK */ | ||
3302 | { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
3303 | { 0x1e29, KEY_BLUE }, /* blue key */ | ||
3304 | { 0x1e2e, KEY_GREEN }, /* green button */ | ||
3305 | { 0x1e30, KEY_PAUSE }, /* pause */ | ||
3306 | { 0x1e32, KEY_REWIND }, /* backward << */ | ||
3307 | { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ | ||
3308 | { 0x1e35, KEY_PLAY }, | ||
3309 | { 0x1e36, KEY_STOP }, | ||
3310 | { 0x1e37, KEY_RECORD }, /* recording */ | ||
3311 | { 0x1e38, KEY_YELLOW }, /* yellow key */ | ||
3312 | { 0x1e3b, KEY_SELECT }, /* top right button */ | ||
3313 | { 0x1e3c, KEY_ZOOM }, /* full */ | ||
3314 | { 0x1e3d, KEY_POWER }, /* system power (green button) */ | ||
3315 | }; | ||
3316 | |||
3317 | struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { | ||
3318 | .scan = ir_codes_rc5_hauppauge_new, | ||
3319 | .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), | ||
3320 | .ir_type = IR_TYPE_RC5, | ||
3321 | }; | ||
3322 | EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); | ||
3323 | |||
3324 | /* Terratec Cinergy Hybrid T USB XS FM | ||
3325 | Mauro Carvalho Chehab <mchehab@redhat.com> | ||
3326 | */ | ||
3327 | static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = { | ||
3328 | { 0x1441, KEY_HOME}, | ||
3329 | { 0x1401, KEY_POWER2}, | ||
3330 | |||
3331 | { 0x1442, KEY_MENU}, /* DVD menu */ | ||
3332 | { 0x1443, KEY_SUBTITLE}, | ||
3333 | { 0x1444, KEY_TEXT}, /* Teletext */ | ||
3334 | { 0x1445, KEY_DELETE}, | ||
3335 | |||
3336 | { 0x1402, KEY_1}, | ||
3337 | { 0x1403, KEY_2}, | ||
3338 | { 0x1404, KEY_3}, | ||
3339 | { 0x1405, KEY_4}, | ||
3340 | { 0x1406, KEY_5}, | ||
3341 | { 0x1407, KEY_6}, | ||
3342 | { 0x1408, KEY_7}, | ||
3343 | { 0x1409, KEY_8}, | ||
3344 | { 0x140a, KEY_9}, | ||
3345 | { 0x140c, KEY_0}, | ||
3346 | |||
3347 | { 0x140b, KEY_TUNER}, /* AV */ | ||
3348 | { 0x140d, KEY_MODE}, /* A.B */ | ||
3349 | |||
3350 | { 0x1446, KEY_TV}, | ||
3351 | { 0x1447, KEY_DVD}, | ||
3352 | { 0x1449, KEY_VIDEO}, | ||
3353 | { 0x144a, KEY_RADIO}, /* Music */ | ||
3354 | { 0x144b, KEY_CAMERA}, /* PIC */ | ||
3355 | |||
3356 | { 0x1410, KEY_UP}, | ||
3357 | { 0x1411, KEY_LEFT}, | ||
3358 | { 0x1412, KEY_OK}, | ||
3359 | { 0x1413, KEY_RIGHT}, | ||
3360 | { 0x1414, KEY_DOWN}, | ||
3361 | |||
3362 | { 0x140f, KEY_EPG}, | ||
3363 | { 0x1416, KEY_INFO}, | ||
3364 | { 0x144d, KEY_BACKSPACE}, | ||
3365 | |||
3366 | { 0x141c, KEY_VOLUMEUP}, | ||
3367 | { 0x141e, KEY_VOLUMEDOWN}, | ||
3368 | |||
3369 | { 0x144c, KEY_PLAY}, | ||
3370 | { 0x141d, KEY_MUTE}, | ||
3371 | |||
3372 | { 0x141b, KEY_CHANNELUP}, | ||
3373 | { 0x141f, KEY_CHANNELDOWN}, | ||
3374 | |||
3375 | { 0x1417, KEY_RED}, | ||
3376 | { 0x1418, KEY_GREEN}, | ||
3377 | { 0x1419, KEY_YELLOW}, | ||
3378 | { 0x141a, KEY_BLUE}, | ||
3379 | |||
3380 | { 0x1458, KEY_RECORD}, | ||
3381 | { 0x1448, KEY_STOP}, | ||
3382 | { 0x1440, KEY_PAUSE}, | ||
3383 | |||
3384 | { 0x1454, KEY_LAST}, | ||
3385 | { 0x144e, KEY_REWIND}, | ||
3386 | { 0x144f, KEY_FASTFORWARD}, | ||
3387 | { 0x145c, KEY_NEXT}, | ||
3388 | }; | ||
3389 | struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { | ||
3390 | .scan = ir_codes_nec_terratec_cinergy_xs, | ||
3391 | .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), | ||
3392 | .ir_type = IR_TYPE_NEC, | ||
3393 | }; | ||
3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); | ||
3395 | |||
3396 | |||
3397 | /* Leadtek Winfast TV USB II Deluxe remote | ||
3398 | Magnus Alm <magnus.alm@gmail.com> | ||
3399 | */ | ||
3400 | static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { | ||
3401 | { 0x62, KEY_0}, | ||
3402 | { 0x75, KEY_1}, | ||
3403 | { 0x76, KEY_2}, | ||
3404 | { 0x77, KEY_3}, | ||
3405 | { 0x79, KEY_4}, | ||
3406 | { 0x7a, KEY_5}, | ||
3407 | { 0x7b, KEY_6}, | ||
3408 | { 0x7d, KEY_7}, | ||
3409 | { 0x7e, KEY_8}, | ||
3410 | { 0x7f, KEY_9}, | ||
3411 | |||
3412 | { 0x38, KEY_CAMERA}, /* SNAPSHOT */ | ||
3413 | { 0x37, KEY_RECORD}, /* RECORD */ | ||
3414 | { 0x35, KEY_TIME}, /* TIMESHIFT */ | ||
3415 | |||
3416 | { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
3417 | { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
3418 | { 0x64, KEY_MUTE}, /* MUTE */ | ||
3419 | |||
3420 | { 0x21, KEY_CHANNEL}, /* SURF */ | ||
3421 | { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ | ||
3422 | { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
3423 | { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ | ||
3424 | |||
3425 | { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ | ||
3426 | |||
3427 | { 0x70, KEY_POWER2}, /* TV ON/OFF */ | ||
3428 | |||
3429 | { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ | ||
3430 | { 0x3a, KEY_NEW}, /* PIP */ | ||
3431 | { 0x73, KEY_ZOOM}, /* FULLSECREEN */ | ||
3432 | |||
3433 | { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ | ||
3434 | |||
3435 | { 0x31, KEY_DOT}, /* '.' */ | ||
3436 | { 0x63, KEY_ENTER}, /* ENTER */ | ||
3437 | |||
3438 | }; | ||
3439 | struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table = { | ||
3440 | .scan = ir_codes_winfast_usbii_deluxe, | ||
3441 | .size = ARRAY_SIZE(ir_codes_winfast_usbii_deluxe), | ||
3442 | }; | ||
3443 | EXPORT_SYMBOL_GPL(ir_codes_winfast_usbii_deluxe_table); | ||
3444 | |||
3445 | /* Kworld 315U | ||
3446 | */ | ||
3447 | static struct ir_scancode ir_codes_kworld_315u[] = { | ||
3448 | { 0x6143, KEY_POWER }, | ||
3449 | { 0x6101, KEY_TUNER }, /* source */ | ||
3450 | { 0x610b, KEY_ZOOM }, | ||
3451 | { 0x6103, KEY_POWER2 }, /* shutdown */ | ||
3452 | |||
3453 | { 0x6104, KEY_1 }, | ||
3454 | { 0x6108, KEY_2 }, | ||
3455 | { 0x6102, KEY_3 }, | ||
3456 | { 0x6109, KEY_CHANNELUP }, | ||
3457 | |||
3458 | { 0x610f, KEY_4 }, | ||
3459 | { 0x6105, KEY_5 }, | ||
3460 | { 0x6106, KEY_6 }, | ||
3461 | { 0x6107, KEY_CHANNELDOWN }, | ||
3462 | |||
3463 | { 0x610c, KEY_7 }, | ||
3464 | { 0x610d, KEY_8 }, | ||
3465 | { 0x610a, KEY_9 }, | ||
3466 | { 0x610e, KEY_VOLUMEUP }, | ||
3467 | |||
3468 | { 0x6110, KEY_LAST }, | ||
3469 | { 0x6111, KEY_0 }, | ||
3470 | { 0x6112, KEY_ENTER }, | ||
3471 | { 0x6113, KEY_VOLUMEDOWN }, | ||
3472 | |||
3473 | { 0x6114, KEY_RECORD }, | ||
3474 | { 0x6115, KEY_STOP }, | ||
3475 | { 0x6116, KEY_PLAY }, | ||
3476 | { 0x6117, KEY_MUTE }, | ||
3477 | |||
3478 | { 0x6118, KEY_UP }, | ||
3479 | { 0x6119, KEY_DOWN }, | ||
3480 | { 0x611a, KEY_LEFT }, | ||
3481 | { 0x611b, KEY_RIGHT }, | ||
3482 | |||
3483 | { 0x611c, KEY_RED }, | ||
3484 | { 0x611d, KEY_GREEN }, | ||
3485 | { 0x611e, KEY_YELLOW }, | ||
3486 | { 0x611f, KEY_BLUE }, | ||
3487 | }; | ||
3488 | |||
3489 | struct ir_scancode_table ir_codes_kworld_315u_table = { | ||
3490 | .scan = ir_codes_kworld_315u, | ||
3491 | .size = ARRAY_SIZE(ir_codes_kworld_315u), | ||
3492 | .ir_type = IR_TYPE_NEC, | ||
3493 | }; | ||
3494 | EXPORT_SYMBOL_GPL(ir_codes_kworld_315u_table); | ||
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index bfca26d51827..9374a006f43d 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* ir-register.c - handle IR scancode->keycode tables | 1 | /* ir-keytable.c - handle IR scancode->keycode tables |
2 | * | 2 | * |
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | 3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> |
4 | * | 4 | * |
@@ -15,384 +15,408 @@ | |||
15 | 15 | ||
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <media/ir-common.h> | 18 | #include "ir-core-priv.h" |
19 | 19 | ||
20 | #define IR_TAB_MIN_SIZE 32 | 20 | /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ |
21 | #define IR_TAB_MAX_SIZE 1024 | 21 | #define IR_TAB_MIN_SIZE 256 |
22 | #define IR_TAB_MAX_SIZE 8192 | ||
23 | |||
24 | /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ | ||
25 | #define IR_KEYPRESS_TIMEOUT 250 | ||
22 | 26 | ||
23 | /** | 27 | /** |
24 | * ir_seek_table() - returns the element order on the table | 28 | * ir_resize_table() - resizes a scancode table if necessary |
25 | * @rc_tab: the ir_scancode_table with the keymap to be used | 29 | * @rc_tab: the ir_scancode_table to resize |
26 | * @scancode: the scancode that we're seeking | 30 | * @return: zero on success or a negative error code |
27 | * | 31 | * |
28 | * This routine is used by the input routines when a key is pressed at the | 32 | * This routine will shrink the ir_scancode_table if it has lots of |
29 | * IR. The scancode is received and needs to be converted into a keycode. | 33 | * unused entries and grow it if it is full. |
30 | * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the | ||
31 | * corresponding keycode from the table. | ||
32 | */ | 34 | */ |
33 | static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode) | 35 | static int ir_resize_table(struct ir_scancode_table *rc_tab) |
34 | { | 36 | { |
35 | int rc; | 37 | unsigned int oldalloc = rc_tab->alloc; |
36 | unsigned long flags; | 38 | unsigned int newalloc = oldalloc; |
37 | struct ir_scancode *keymap = rc_tab->scan; | 39 | struct ir_scancode *oldscan = rc_tab->scan; |
40 | struct ir_scancode *newscan; | ||
41 | |||
42 | if (rc_tab->size == rc_tab->len) { | ||
43 | /* All entries in use -> grow keytable */ | ||
44 | if (rc_tab->alloc >= IR_TAB_MAX_SIZE) | ||
45 | return -ENOMEM; | ||
38 | 46 | ||
39 | spin_lock_irqsave(&rc_tab->lock, flags); | 47 | newalloc *= 2; |
48 | IR_dprintk(1, "Growing table to %u bytes\n", newalloc); | ||
49 | } | ||
40 | 50 | ||
41 | /* FIXME: replace it by a binary search */ | 51 | if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { |
52 | /* Less than 1/3 of entries in use -> shrink keytable */ | ||
53 | newalloc /= 2; | ||
54 | IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); | ||
55 | } | ||
42 | 56 | ||
43 | for (rc = 0; rc < rc_tab->size; rc++) | 57 | if (newalloc == oldalloc) |
44 | if (keymap[rc].scancode == scancode) | 58 | return 0; |
45 | goto exit; | ||
46 | 59 | ||
47 | /* Not found */ | 60 | newscan = kmalloc(newalloc, GFP_ATOMIC); |
48 | rc = -EINVAL; | 61 | if (!newscan) { |
62 | IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); | ||
63 | return -ENOMEM; | ||
64 | } | ||
49 | 65 | ||
50 | exit: | 66 | memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); |
51 | spin_unlock_irqrestore(&rc_tab->lock, flags); | 67 | rc_tab->scan = newscan; |
52 | return rc; | 68 | rc_tab->alloc = newalloc; |
69 | rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); | ||
70 | kfree(oldscan); | ||
71 | return 0; | ||
53 | } | 72 | } |
54 | 73 | ||
55 | /** | 74 | /** |
56 | * ir_roundup_tablesize() - gets an optimum value for the table size | 75 | * ir_do_setkeycode() - internal function to set a keycode in the |
57 | * @n_elems: minimum number of entries to store keycodes | 76 | * scancode->keycode table |
58 | * | 77 | * @dev: the struct input_dev device descriptor |
59 | * This routine is used to choose the keycode table size. | 78 | * @rc_tab: the struct ir_scancode_table to set the keycode in |
79 | * @scancode: the scancode for the ir command | ||
80 | * @keycode: the keycode for the ir command | ||
81 | * @resize: whether the keytable may be shrunk | ||
82 | * @return: -EINVAL if the keycode could not be inserted, otherwise zero. | ||
60 | * | 83 | * |
61 | * In order to have some empty space for new keycodes, | 84 | * This routine is used internally to manipulate the scancode->keycode table. |
62 | * and knowing in advance that kmalloc allocates only power of two | 85 | * The caller has to hold @rc_tab->lock. |
63 | * segments, it optimizes the allocated space to have some spare space | ||
64 | * for those new keycodes by using the maximum number of entries that | ||
65 | * will be effectively be allocated by kmalloc. | ||
66 | * In order to reduce the quantity of table resizes, it has a minimum | ||
67 | * table size of IR_TAB_MIN_SIZE. | ||
68 | */ | 86 | */ |
69 | static int ir_roundup_tablesize(int n_elems) | 87 | static int ir_do_setkeycode(struct input_dev *dev, |
88 | struct ir_scancode_table *rc_tab, | ||
89 | unsigned scancode, unsigned keycode, | ||
90 | bool resize) | ||
70 | { | 91 | { |
71 | size_t size; | 92 | unsigned int i; |
72 | 93 | int old_keycode = KEY_RESERVED; | |
73 | if (n_elems < IR_TAB_MIN_SIZE) | 94 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
74 | n_elems = IR_TAB_MIN_SIZE; | ||
75 | 95 | ||
76 | /* | 96 | /* |
77 | * As kmalloc only allocates sizes of power of two, get as | 97 | * Unfortunately, some hardware-based IR decoders don't provide |
78 | * much entries as possible for the allocated memory segment | 98 | * all bits for the complete IR code. In general, they provide only |
99 | * the command part of the IR code. Yet, as it is possible to replace | ||
100 | * the provided IR with another one, it is needed to allow loading | ||
101 | * IR tables from other remotes. So, | ||
79 | */ | 102 | */ |
80 | size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode)); | 103 | if (ir_dev->props && ir_dev->props->scanmask) { |
81 | n_elems = size / sizeof(struct ir_scancode); | 104 | scancode &= ir_dev->props->scanmask; |
105 | } | ||
82 | 106 | ||
83 | return n_elems; | 107 | /* First check if we already have a mapping for this ir command */ |
108 | for (i = 0; i < rc_tab->len; i++) { | ||
109 | /* Keytable is sorted from lowest to highest scancode */ | ||
110 | if (rc_tab->scan[i].scancode > scancode) | ||
111 | break; | ||
112 | else if (rc_tab->scan[i].scancode < scancode) | ||
113 | continue; | ||
114 | |||
115 | old_keycode = rc_tab->scan[i].keycode; | ||
116 | rc_tab->scan[i].keycode = keycode; | ||
117 | |||
118 | /* Did the user wish to remove the mapping? */ | ||
119 | if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) { | ||
120 | IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", | ||
121 | i, scancode); | ||
122 | rc_tab->len--; | ||
123 | memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1], | ||
124 | (rc_tab->len - i) * sizeof(struct ir_scancode)); | ||
125 | } | ||
126 | |||
127 | /* Possibly shrink the keytable, failure is not a problem */ | ||
128 | ir_resize_table(rc_tab); | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) { | ||
133 | /* No previous mapping found, we might need to grow the table */ | ||
134 | if (resize && ir_resize_table(rc_tab)) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", | ||
138 | i, scancode, keycode); | ||
139 | |||
140 | /* i is the proper index to insert our new keycode */ | ||
141 | memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], | ||
142 | (rc_tab->len - i) * sizeof(struct ir_scancode)); | ||
143 | rc_tab->scan[i].scancode = scancode; | ||
144 | rc_tab->scan[i].keycode = keycode; | ||
145 | rc_tab->len++; | ||
146 | set_bit(keycode, dev->keybit); | ||
147 | } else { | ||
148 | IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", | ||
149 | i, scancode, keycode); | ||
150 | /* A previous mapping was updated... */ | ||
151 | clear_bit(old_keycode, dev->keybit); | ||
152 | /* ...but another scancode might use the same keycode */ | ||
153 | for (i = 0; i < rc_tab->len; i++) { | ||
154 | if (rc_tab->scan[i].keycode == old_keycode) { | ||
155 | set_bit(old_keycode, dev->keybit); | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | return 0; | ||
84 | } | 162 | } |
85 | 163 | ||
86 | /** | 164 | /** |
87 | * ir_copy_table() - copies a keytable, discarding the unused entries | 165 | * ir_setkeycode() - set a keycode in the scancode->keycode table |
88 | * @destin: destin table | 166 | * @dev: the struct input_dev device descriptor |
89 | * @origin: origin table | 167 | * @scancode: the desired scancode |
168 | * @keycode: result | ||
169 | * @return: -EINVAL if the keycode could not be inserted, otherwise zero. | ||
90 | * | 170 | * |
91 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED | 171 | * This routine is used to handle evdev EVIOCSKEY ioctl. |
92 | * Also copies table size and table protocol. | ||
93 | * NOTE: It shouldn't copy the lock field | ||
94 | */ | 172 | */ |
95 | 173 | static int ir_setkeycode(struct input_dev *dev, | |
96 | static int ir_copy_table(struct ir_scancode_table *destin, | 174 | unsigned int scancode, unsigned int keycode) |
97 | const struct ir_scancode_table *origin) | ||
98 | { | 175 | { |
99 | int i, j = 0; | 176 | int rc; |
100 | 177 | unsigned long flags; | |
101 | for (i = 0; i < origin->size; i++) { | 178 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
102 | if (origin->scan[i].keycode == KEY_UNKNOWN || | 179 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; |
103 | origin->scan[i].keycode == KEY_RESERVED) | ||
104 | continue; | ||
105 | 180 | ||
106 | memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode)); | 181 | spin_lock_irqsave(&rc_tab->lock, flags); |
107 | j++; | 182 | rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true); |
108 | } | 183 | spin_unlock_irqrestore(&rc_tab->lock, flags); |
109 | destin->size = j; | 184 | return rc; |
110 | destin->ir_type = origin->ir_type; | 185 | } |
111 | 186 | ||
112 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); | 187 | /** |
188 | * ir_setkeytable() - sets several entries in the scancode->keycode table | ||
189 | * @dev: the struct input_dev device descriptor | ||
190 | * @to: the struct ir_scancode_table to copy entries to | ||
191 | * @from: the struct ir_scancode_table to copy entries from | ||
192 | * @return: -EINVAL if all keycodes could not be inserted, otherwise zero. | ||
193 | * | ||
194 | * This routine is used to handle table initialization. | ||
195 | */ | ||
196 | static int ir_setkeytable(struct input_dev *dev, | ||
197 | struct ir_scancode_table *to, | ||
198 | const struct ir_scancode_table *from) | ||
199 | { | ||
200 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | ||
201 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
202 | unsigned long flags; | ||
203 | unsigned int i; | ||
204 | int rc = 0; | ||
113 | 205 | ||
114 | return 0; | 206 | spin_lock_irqsave(&rc_tab->lock, flags); |
207 | for (i = 0; i < from->size; i++) { | ||
208 | rc = ir_do_setkeycode(dev, to, from->scan[i].scancode, | ||
209 | from->scan[i].keycode, false); | ||
210 | if (rc) | ||
211 | break; | ||
212 | } | ||
213 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
214 | return rc; | ||
115 | } | 215 | } |
116 | 216 | ||
117 | /** | 217 | /** |
118 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table | 218 | * ir_getkeycode() - get a keycode from the scancode->keycode table |
119 | * @dev: the struct input_dev device descriptor | 219 | * @dev: the struct input_dev device descriptor |
120 | * @scancode: the desired scancode | 220 | * @scancode: the desired scancode |
121 | * @keycode: the keycode to be retorned. | 221 | * @keycode: used to return the keycode, if found, or KEY_RESERVED |
222 | * @return: always returns zero. | ||
122 | * | 223 | * |
123 | * This routine is used to handle evdev EVIOCGKEY ioctl. | 224 | * This routine is used to handle evdev EVIOCGKEY ioctl. |
124 | * If the key is not found, returns -EINVAL, otherwise, returns 0. | ||
125 | */ | 225 | */ |
126 | static int ir_getkeycode(struct input_dev *dev, | 226 | static int ir_getkeycode(struct input_dev *dev, |
127 | unsigned int scancode, unsigned int *keycode) | 227 | unsigned int scancode, unsigned int *keycode) |
128 | { | 228 | { |
129 | int elem; | 229 | int start, end, mid; |
230 | unsigned long flags; | ||
231 | int key = KEY_RESERVED; | ||
130 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 232 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
131 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | 233 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; |
132 | 234 | ||
133 | elem = ir_seek_table(rc_tab, scancode); | 235 | spin_lock_irqsave(&rc_tab->lock, flags); |
134 | if (elem >= 0) { | 236 | start = 0; |
135 | *keycode = rc_tab->scan[elem].keycode; | 237 | end = rc_tab->len - 1; |
136 | return 0; | 238 | while (start <= end) { |
239 | mid = (start + end) / 2; | ||
240 | if (rc_tab->scan[mid].scancode < scancode) | ||
241 | start = mid + 1; | ||
242 | else if (rc_tab->scan[mid].scancode > scancode) | ||
243 | end = mid - 1; | ||
244 | else { | ||
245 | key = rc_tab->scan[mid].keycode; | ||
246 | break; | ||
247 | } | ||
137 | } | 248 | } |
249 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
138 | 250 | ||
139 | /* | 251 | if (key == KEY_RESERVED) |
140 | * Scancode not found and table can't be expanded | 252 | IR_dprintk(1, "unknown key for scancode 0x%04x\n", |
141 | */ | 253 | scancode); |
142 | if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE) | ||
143 | return -EINVAL; | ||
144 | 254 | ||
145 | /* | 255 | *keycode = key; |
146 | * If is there extra space, returns KEY_RESERVED, | ||
147 | * otherwise, input core won't let ir_setkeycode to work | ||
148 | */ | ||
149 | *keycode = KEY_RESERVED; | ||
150 | return 0; | 256 | return 0; |
151 | } | 257 | } |
152 | 258 | ||
153 | /** | 259 | /** |
154 | * ir_is_resize_needed() - Check if the table needs rezise | 260 | * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode |
155 | * @table: keycode table that may need to resize | 261 | * @input_dev: the struct input_dev descriptor of the device |
156 | * @n_elems: minimum number of entries to store keycodes | 262 | * @scancode: the scancode that we're seeking |
157 | * | ||
158 | * Considering that kmalloc uses power of two storage areas, this | ||
159 | * routine detects if the real alloced size will change. If not, it | ||
160 | * just returns without doing nothing. Otherwise, it will extend or | ||
161 | * reduce the table size to meet the new needs. | ||
162 | * | 263 | * |
163 | * It returns 0 if no resize is needed, 1 otherwise. | 264 | * This routine is used by the input routines when a key is pressed at the |
265 | * IR. The scancode is received and needs to be converted into a keycode. | ||
266 | * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the | ||
267 | * corresponding keycode from the table. | ||
164 | */ | 268 | */ |
165 | static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems) | 269 | u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) |
166 | { | 270 | { |
167 | int cur_size = ir_roundup_tablesize(table->size); | 271 | int keycode; |
168 | int new_size = ir_roundup_tablesize(n_elems); | ||
169 | |||
170 | if (cur_size == new_size) | ||
171 | return 0; | ||
172 | 272 | ||
173 | /* Resize is needed */ | 273 | ir_getkeycode(dev, scancode, &keycode); |
174 | return 1; | 274 | if (keycode != KEY_RESERVED) |
275 | IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", | ||
276 | dev->name, scancode, keycode); | ||
277 | return keycode; | ||
175 | } | 278 | } |
279 | EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | ||
176 | 280 | ||
177 | /** | 281 | /** |
178 | * ir_delete_key() - remove a keycode from the table | 282 | * ir_keyup() - generates input event to cleanup a key press |
179 | * @rc_tab: keycode table | 283 | * @ir: the struct ir_input_dev descriptor of the device |
180 | * @elem: element to be removed | ||
181 | * | 284 | * |
285 | * This routine is used to signal that a key has been released on the | ||
286 | * remote control. It reports a keyup input event via input_report_key(). | ||
182 | */ | 287 | */ |
183 | static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) | 288 | static void ir_keyup(struct ir_input_dev *ir) |
184 | { | 289 | { |
185 | unsigned long flags = 0; | 290 | if (!ir->keypressed) |
186 | int newsize = rc_tab->size - 1; | 291 | return; |
187 | int resize = ir_is_resize_needed(rc_tab, newsize); | ||
188 | struct ir_scancode *oldkeymap = rc_tab->scan; | ||
189 | struct ir_scancode *newkeymap = NULL; | ||
190 | |||
191 | if (resize) | ||
192 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * | ||
193 | sizeof(*newkeymap), GFP_ATOMIC); | ||
194 | |||
195 | /* There's no memory for resize. Keep the old table */ | ||
196 | if (!resize || !newkeymap) { | ||
197 | newkeymap = oldkeymap; | ||
198 | |||
199 | /* We'll modify the live table. Lock it */ | ||
200 | spin_lock_irqsave(&rc_tab->lock, flags); | ||
201 | } | ||
202 | 292 | ||
203 | /* | 293 | IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); |
204 | * Copy the elements before the one that will be deleted | 294 | input_report_key(ir->input_dev, ir->last_keycode, 0); |
205 | * if (!resize), both oldkeymap and newkeymap points | 295 | input_sync(ir->input_dev); |
206 | * to the same place, so, there's no need to copy | 296 | ir->keypressed = false; |
207 | */ | 297 | } |
208 | if (resize && elem > 0) | 298 | |
209 | memcpy(newkeymap, oldkeymap, | 299 | /** |
210 | elem * sizeof(*newkeymap)); | 300 | * ir_timer_keyup() - generates a keyup event after a timeout |
301 | * @cookie: a pointer to struct ir_input_dev passed to setup_timer() | ||
302 | * | ||
303 | * This routine will generate a keyup event some time after a keydown event | ||
304 | * is generated when no further activity has been detected. | ||
305 | */ | ||
306 | static void ir_timer_keyup(unsigned long cookie) | ||
307 | { | ||
308 | struct ir_input_dev *ir = (struct ir_input_dev *)cookie; | ||
309 | unsigned long flags; | ||
211 | 310 | ||
212 | /* | 311 | /* |
213 | * Copy the other elements overwriting the element to be removed | 312 | * ir->keyup_jiffies is used to prevent a race condition if a |
214 | * This operation applies to both resize and non-resize case | 313 | * hardware interrupt occurs at this point and the keyup timer |
314 | * event is moved further into the future as a result. | ||
315 | * | ||
316 | * The timer will then be reactivated and this function called | ||
317 | * again in the future. We need to exit gracefully in that case | ||
318 | * to allow the input subsystem to do its auto-repeat magic or | ||
319 | * a keyup event might follow immediately after the keydown. | ||
215 | */ | 320 | */ |
216 | if (elem < newsize) | 321 | spin_lock_irqsave(&ir->keylock, flags); |
217 | memcpy(&newkeymap[elem], &oldkeymap[elem + 1], | 322 | if (time_is_after_eq_jiffies(ir->keyup_jiffies)) |
218 | (newsize - elem) * sizeof(*newkeymap)); | 323 | ir_keyup(ir); |
219 | 324 | spin_unlock_irqrestore(&ir->keylock, flags); | |
220 | if (resize) { | ||
221 | /* | ||
222 | * As the copy happened to a temporary table, only here | ||
223 | * it needs to lock while replacing the table pointers | ||
224 | * to use the new table | ||
225 | */ | ||
226 | spin_lock_irqsave(&rc_tab->lock, flags); | ||
227 | rc_tab->size = newsize; | ||
228 | rc_tab->scan = newkeymap; | ||
229 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
230 | |||
231 | /* Frees the old keytable */ | ||
232 | kfree(oldkeymap); | ||
233 | } else { | ||
234 | rc_tab->size = newsize; | ||
235 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
236 | } | ||
237 | } | 325 | } |
238 | 326 | ||
239 | /** | 327 | /** |
240 | * ir_insert_key() - insert a keycode at the table | 328 | * ir_repeat() - notifies the IR core that a key is still pressed |
241 | * @rc_tab: keycode table | 329 | * @dev: the struct input_dev descriptor of the device |
242 | * @scancode: the desired scancode | ||
243 | * @keycode: the keycode to be retorned. | ||
244 | * | 330 | * |
331 | * This routine is used by IR decoders when a repeat message which does | ||
332 | * not include the necessary bits to reproduce the scancode has been | ||
333 | * received. | ||
245 | */ | 334 | */ |
246 | static int ir_insert_key(struct ir_scancode_table *rc_tab, | 335 | void ir_repeat(struct input_dev *dev) |
247 | int scancode, int keycode) | ||
248 | { | 336 | { |
249 | unsigned long flags; | 337 | unsigned long flags; |
250 | int elem = rc_tab->size; | 338 | struct ir_input_dev *ir = input_get_drvdata(dev); |
251 | int newsize = rc_tab->size + 1; | ||
252 | int resize = ir_is_resize_needed(rc_tab, newsize); | ||
253 | struct ir_scancode *oldkeymap = rc_tab->scan; | ||
254 | struct ir_scancode *newkeymap; | ||
255 | |||
256 | if (resize) { | ||
257 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * | ||
258 | sizeof(*newkeymap), GFP_ATOMIC); | ||
259 | if (!newkeymap) | ||
260 | return -ENOMEM; | ||
261 | 339 | ||
262 | memcpy(newkeymap, oldkeymap, | 340 | spin_lock_irqsave(&ir->keylock, flags); |
263 | rc_tab->size * sizeof(*newkeymap)); | ||
264 | } else | ||
265 | newkeymap = oldkeymap; | ||
266 | 341 | ||
267 | /* Stores the new code at the table */ | 342 | if (!ir->keypressed) |
268 | IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", | 343 | goto out; |
269 | rc_tab->size, scancode, keycode); | ||
270 | 344 | ||
271 | spin_lock_irqsave(&rc_tab->lock, flags); | 345 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); |
272 | rc_tab->size = newsize; | 346 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); |
273 | if (resize) { | ||
274 | rc_tab->scan = newkeymap; | ||
275 | kfree(oldkeymap); | ||
276 | } | ||
277 | newkeymap[elem].scancode = scancode; | ||
278 | newkeymap[elem].keycode = keycode; | ||
279 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
280 | 347 | ||
281 | return 0; | 348 | out: |
349 | spin_unlock_irqrestore(&ir->keylock, flags); | ||
282 | } | 350 | } |
351 | EXPORT_SYMBOL_GPL(ir_repeat); | ||
283 | 352 | ||
284 | /** | 353 | /** |
285 | * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table | 354 | * ir_keydown() - generates input event for a key press |
286 | * @dev: the struct input_dev device descriptor | 355 | * @dev: the struct input_dev descriptor of the device |
287 | * @scancode: the desired scancode | 356 | * @scancode: the scancode that we're seeking |
288 | * @keycode: the keycode to be retorned. | 357 | * @toggle: the toggle value (protocol dependent, if the protocol doesn't |
358 | * support toggle values, this should be set to zero) | ||
289 | * | 359 | * |
290 | * This routine is used to handle evdev EVIOCSKEY ioctl. | 360 | * This routine is used by the input routines when a key is pressed at the |
291 | * There's one caveat here: how can we increase the size of the table? | 361 | * IR. It gets the keycode for a scancode and reports an input event via |
292 | * If the key is not found, returns -EINVAL, otherwise, returns 0. | 362 | * input_report_key(). |
293 | */ | 363 | */ |
294 | static int ir_setkeycode(struct input_dev *dev, | 364 | void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) |
295 | unsigned int scancode, unsigned int keycode) | ||
296 | { | 365 | { |
297 | int rc = 0; | ||
298 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | ||
299 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
300 | struct ir_scancode *keymap = rc_tab->scan; | ||
301 | unsigned long flags; | 366 | unsigned long flags; |
367 | struct ir_input_dev *ir = input_get_drvdata(dev); | ||
302 | 368 | ||
303 | /* | 369 | u32 keycode = ir_g_keycode_from_table(dev, scancode); |
304 | * Handle keycode table deletions | ||
305 | * | ||
306 | * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED, | ||
307 | * deal as a trial to remove an existing scancode attribution | ||
308 | * if table become too big, reduce it to save space | ||
309 | */ | ||
310 | if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) { | ||
311 | rc = ir_seek_table(rc_tab, scancode); | ||
312 | if (rc < 0) | ||
313 | return 0; | ||
314 | |||
315 | IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode); | ||
316 | clear_bit(keymap[rc].keycode, dev->keybit); | ||
317 | ir_delete_key(rc_tab, rc); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | 370 | ||
322 | /* | 371 | spin_lock_irqsave(&ir->keylock, flags); |
323 | * Handle keycode replacements | ||
324 | * | ||
325 | * If the scancode exists, just replace by the new value | ||
326 | */ | ||
327 | rc = ir_seek_table(rc_tab, scancode); | ||
328 | if (rc >= 0) { | ||
329 | IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", | ||
330 | rc, scancode, keycode); | ||
331 | 372 | ||
332 | clear_bit(keymap[rc].keycode, dev->keybit); | 373 | /* Repeat event? */ |
374 | if (ir->keypressed && | ||
375 | ir->last_scancode == scancode && | ||
376 | ir->last_toggle == toggle) | ||
377 | goto set_timer; | ||
333 | 378 | ||
334 | spin_lock_irqsave(&rc_tab->lock, flags); | 379 | /* Release old keypress */ |
335 | keymap[rc].keycode = keycode; | 380 | ir_keyup(ir); |
336 | spin_unlock_irqrestore(&rc_tab->lock, flags); | ||
337 | 381 | ||
338 | set_bit(keycode, dev->keybit); | 382 | ir->last_scancode = scancode; |
383 | ir->last_toggle = toggle; | ||
384 | ir->last_keycode = keycode; | ||
339 | 385 | ||
340 | return 0; | 386 | if (keycode == KEY_RESERVED) |
341 | } | 387 | goto out; |
342 | 388 | ||
343 | /* | 389 | /* Register a keypress */ |
344 | * Handle new scancode inserts | 390 | ir->keypressed = true; |
345 | * | 391 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", |
346 | * reallocate table if needed and insert a new keycode | 392 | dev->name, keycode, scancode); |
347 | */ | 393 | input_report_key(dev, ir->last_keycode, 1); |
394 | input_sync(dev); | ||
348 | 395 | ||
349 | /* Avoid growing the table indefinitely */ | 396 | set_timer: |
350 | if (rc_tab->size + 1 > IR_TAB_MAX_SIZE) | 397 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); |
351 | return -EINVAL; | 398 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); |
352 | 399 | out: | |
353 | rc = ir_insert_key(rc_tab, scancode, keycode); | 400 | spin_unlock_irqrestore(&ir->keylock, flags); |
354 | if (rc < 0) | ||
355 | return rc; | ||
356 | set_bit(keycode, dev->keybit); | ||
357 | |||
358 | return 0; | ||
359 | } | 401 | } |
402 | EXPORT_SYMBOL_GPL(ir_keydown); | ||
360 | 403 | ||
361 | /** | 404 | static int ir_open(struct input_dev *input_dev) |
362 | * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode | ||
363 | * @input_dev: the struct input_dev descriptor of the device | ||
364 | * @scancode: the scancode that we're seeking | ||
365 | * | ||
366 | * This routine is used by the input routines when a key is pressed at the | ||
367 | * IR. The scancode is received and needs to be converted into a keycode. | ||
368 | * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the | ||
369 | * corresponding keycode from the table. | ||
370 | */ | ||
371 | u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) | ||
372 | { | 405 | { |
373 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 406 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
374 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
375 | struct ir_scancode *keymap = rc_tab->scan; | ||
376 | int elem; | ||
377 | 407 | ||
378 | elem = ir_seek_table(rc_tab, scancode); | 408 | return ir_dev->props->open(ir_dev->props->priv); |
379 | if (elem >= 0) { | 409 | } |
380 | IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", | ||
381 | dev->name, scancode, keymap[elem].keycode); | ||
382 | |||
383 | return rc_tab->scan[elem].keycode; | ||
384 | } | ||
385 | 410 | ||
386 | printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", | 411 | static void ir_close(struct input_dev *input_dev) |
387 | dev->name, scancode); | 412 | { |
413 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
388 | 414 | ||
389 | /* Reports userspace that an unknown keycode were got */ | 415 | ir_dev->props->close(ir_dev->props->priv); |
390 | return KEY_RESERVED; | ||
391 | } | 416 | } |
392 | EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | ||
393 | 417 | ||
394 | /** | 418 | /** |
395 | * ir_input_register() - sets the IR keycode table and add the handlers | 419 | * __ir_input_register() - sets the IR keycode table and add the handlers |
396 | * for keymap table get/set | 420 | * for keymap table get/set |
397 | * @input_dev: the struct input_dev descriptor of the device | 421 | * @input_dev: the struct input_dev descriptor of the device |
398 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | 422 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap |
@@ -402,13 +426,13 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | |||
402 | * It will register the input/evdev interface for the device and | 426 | * It will register the input/evdev interface for the device and |
403 | * register the syfs code for IR class | 427 | * register the syfs code for IR class |
404 | */ | 428 | */ |
405 | int ir_input_register(struct input_dev *input_dev, | 429 | int __ir_input_register(struct input_dev *input_dev, |
406 | const struct ir_scancode_table *rc_tab, | 430 | const struct ir_scancode_table *rc_tab, |
407 | const struct ir_dev_props *props) | 431 | const struct ir_dev_props *props, |
432 | const char *driver_name) | ||
408 | { | 433 | { |
409 | struct ir_input_dev *ir_dev; | 434 | struct ir_input_dev *ir_dev; |
410 | struct ir_scancode *keymap = rc_tab->scan; | 435 | int rc; |
411 | int i, rc; | ||
412 | 436 | ||
413 | if (rc_tab->scan == NULL || !rc_tab->size) | 437 | if (rc_tab->scan == NULL || !rc_tab->size) |
414 | return -EINVAL; | 438 | return -EINVAL; |
@@ -417,57 +441,77 @@ int ir_input_register(struct input_dev *input_dev, | |||
417 | if (!ir_dev) | 441 | if (!ir_dev) |
418 | return -ENOMEM; | 442 | return -ENOMEM; |
419 | 443 | ||
420 | spin_lock_init(&ir_dev->rc_tab.lock); | 444 | ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); |
421 | 445 | if (!ir_dev->driver_name) { | |
422 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); | 446 | rc = -ENOMEM; |
423 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * | 447 | goto out_dev; |
424 | sizeof(struct ir_scancode), GFP_KERNEL); | ||
425 | if (!ir_dev->rc_tab.scan) { | ||
426 | kfree(ir_dev); | ||
427 | return -ENOMEM; | ||
428 | } | 448 | } |
429 | 449 | ||
430 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | 450 | input_dev->getkeycode = ir_getkeycode; |
431 | ir_dev->rc_tab.size, | 451 | input_dev->setkeycode = ir_setkeycode; |
432 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); | 452 | input_set_drvdata(input_dev, ir_dev); |
453 | ir_dev->input_dev = input_dev; | ||
433 | 454 | ||
434 | ir_copy_table(&ir_dev->rc_tab, rc_tab); | 455 | spin_lock_init(&ir_dev->rc_tab.lock); |
435 | ir_dev->props = props; | 456 | spin_lock_init(&ir_dev->keylock); |
457 | setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); | ||
458 | |||
459 | ir_dev->rc_tab.name = rc_tab->name; | ||
460 | ir_dev->rc_tab.ir_type = rc_tab->ir_type; | ||
461 | ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * | ||
462 | sizeof(struct ir_scancode)); | ||
463 | ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL); | ||
464 | ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode); | ||
465 | if (props) { | ||
466 | ir_dev->props = props; | ||
467 | if (props->open) | ||
468 | input_dev->open = ir_open; | ||
469 | if (props->close) | ||
470 | input_dev->close = ir_close; | ||
471 | } | ||
436 | 472 | ||
437 | /* set the bits for the keys */ | 473 | if (!ir_dev->rc_tab.scan) { |
438 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); | 474 | rc = -ENOMEM; |
439 | for (i = 0; i < rc_tab->size; i++) { | 475 | goto out_name; |
440 | IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n", | ||
441 | i, keymap[i].keycode); | ||
442 | set_bit(keymap[i].keycode, input_dev->keybit); | ||
443 | } | 476 | } |
444 | clear_bit(0, input_dev->keybit); | 477 | |
478 | IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", | ||
479 | ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); | ||
445 | 480 | ||
446 | set_bit(EV_KEY, input_dev->evbit); | 481 | set_bit(EV_KEY, input_dev->evbit); |
482 | set_bit(EV_REP, input_dev->evbit); | ||
447 | 483 | ||
448 | input_dev->getkeycode = ir_getkeycode; | 484 | if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { |
449 | input_dev->setkeycode = ir_setkeycode; | 485 | rc = -ENOMEM; |
450 | input_set_drvdata(input_dev, ir_dev); | 486 | goto out_table; |
487 | } | ||
451 | 488 | ||
452 | rc = input_register_device(input_dev); | 489 | rc = ir_register_class(input_dev); |
453 | if (rc < 0) | 490 | if (rc < 0) |
454 | goto err; | 491 | goto out_table; |
455 | 492 | ||
456 | rc = ir_register_class(input_dev); | 493 | if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { |
457 | if (rc < 0) { | 494 | rc = ir_raw_event_register(input_dev); |
458 | input_unregister_device(input_dev); | 495 | if (rc < 0) |
459 | goto err; | 496 | goto out_event; |
460 | } | 497 | } |
461 | 498 | ||
499 | IR_dprintk(1, "Registered input device on %s for %s remote.\n", | ||
500 | driver_name, rc_tab->name); | ||
501 | |||
462 | return 0; | 502 | return 0; |
463 | 503 | ||
464 | err: | 504 | out_event: |
465 | kfree(rc_tab->scan); | 505 | ir_unregister_class(input_dev); |
506 | out_table: | ||
507 | kfree(ir_dev->rc_tab.scan); | ||
508 | out_name: | ||
509 | kfree(ir_dev->driver_name); | ||
510 | out_dev: | ||
466 | kfree(ir_dev); | 511 | kfree(ir_dev); |
467 | input_set_drvdata(input_dev, NULL); | ||
468 | return rc; | 512 | return rc; |
469 | } | 513 | } |
470 | EXPORT_SYMBOL_GPL(ir_input_register); | 514 | EXPORT_SYMBOL_GPL(__ir_input_register); |
471 | 515 | ||
472 | /** | 516 | /** |
473 | * ir_input_unregister() - unregisters IR and frees resources | 517 | * ir_input_unregister() - unregisters IR and frees resources |
@@ -475,9 +519,9 @@ EXPORT_SYMBOL_GPL(ir_input_register); | |||
475 | 519 | ||
476 | * This routine is used to free memory and de-register interfaces. | 520 | * This routine is used to free memory and de-register interfaces. |
477 | */ | 521 | */ |
478 | void ir_input_unregister(struct input_dev *dev) | 522 | void ir_input_unregister(struct input_dev *input_dev) |
479 | { | 523 | { |
480 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 524 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
481 | struct ir_scancode_table *rc_tab; | 525 | struct ir_scancode_table *rc_tab; |
482 | 526 | ||
483 | if (!ir_dev) | 527 | if (!ir_dev) |
@@ -485,15 +529,18 @@ void ir_input_unregister(struct input_dev *dev) | |||
485 | 529 | ||
486 | IR_dprintk(1, "Freed keycode table\n"); | 530 | IR_dprintk(1, "Freed keycode table\n"); |
487 | 531 | ||
532 | del_timer_sync(&ir_dev->timer_keyup); | ||
533 | if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) | ||
534 | ir_raw_event_unregister(input_dev); | ||
488 | rc_tab = &ir_dev->rc_tab; | 535 | rc_tab = &ir_dev->rc_tab; |
489 | rc_tab->size = 0; | 536 | rc_tab->size = 0; |
490 | kfree(rc_tab->scan); | 537 | kfree(rc_tab->scan); |
491 | rc_tab->scan = NULL; | 538 | rc_tab->scan = NULL; |
492 | 539 | ||
493 | ir_unregister_class(dev); | 540 | ir_unregister_class(input_dev); |
494 | 541 | ||
542 | kfree(ir_dev->driver_name); | ||
495 | kfree(ir_dev); | 543 | kfree(ir_dev); |
496 | input_unregister_device(dev); | ||
497 | } | 544 | } |
498 | EXPORT_SYMBOL_GPL(ir_input_unregister); | 545 | EXPORT_SYMBOL_GPL(ir_input_unregister); |
499 | 546 | ||
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c new file mode 100644 index 000000000000..ba79233112ef --- /dev/null +++ b/drivers/media/IR/ir-nec-decoder.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/bitrev.h> | ||
16 | #include "ir-core-priv.h" | ||
17 | |||
18 | #define NEC_NBITS 32 | ||
19 | #define NEC_UNIT 562500 /* ns */ | ||
20 | #define NEC_HEADER_PULSE (16 * NEC_UNIT) | ||
21 | #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ | ||
22 | #define NEC_HEADER_SPACE (8 * NEC_UNIT) | ||
23 | #define NEC_REPEAT_SPACE (8 * NEC_UNIT) | ||
24 | #define NEC_BIT_PULSE (1 * NEC_UNIT) | ||
25 | #define NEC_BIT_0_SPACE (1 * NEC_UNIT) | ||
26 | #define NEC_BIT_1_SPACE (3 * NEC_UNIT) | ||
27 | #define NEC_TRAILER_PULSE (1 * NEC_UNIT) | ||
28 | #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ | ||
29 | |||
30 | /* Used to register nec_decoder clients */ | ||
31 | static LIST_HEAD(decoder_list); | ||
32 | static DEFINE_SPINLOCK(decoder_lock); | ||
33 | |||
34 | enum nec_state { | ||
35 | STATE_INACTIVE, | ||
36 | STATE_HEADER_SPACE, | ||
37 | STATE_BIT_PULSE, | ||
38 | STATE_BIT_SPACE, | ||
39 | STATE_TRAILER_PULSE, | ||
40 | STATE_TRAILER_SPACE, | ||
41 | }; | ||
42 | |||
43 | struct decoder_data { | ||
44 | struct list_head list; | ||
45 | struct ir_input_dev *ir_dev; | ||
46 | int enabled:1; | ||
47 | |||
48 | /* State machine control */ | ||
49 | enum nec_state state; | ||
50 | u32 nec_bits; | ||
51 | unsigned count; | ||
52 | }; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * get_decoder_data() - gets decoder data | ||
57 | * @input_dev: input device | ||
58 | * | ||
59 | * Returns the struct decoder_data that corresponds to a device | ||
60 | */ | ||
61 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
62 | { | ||
63 | struct decoder_data *data = NULL; | ||
64 | |||
65 | spin_lock(&decoder_lock); | ||
66 | list_for_each_entry(data, &decoder_list, list) { | ||
67 | if (data->ir_dev == ir_dev) | ||
68 | break; | ||
69 | } | ||
70 | spin_unlock(&decoder_lock); | ||
71 | return data; | ||
72 | } | ||
73 | |||
74 | static ssize_t store_enabled(struct device *d, | ||
75 | struct device_attribute *mattr, | ||
76 | const char *buf, | ||
77 | size_t len) | ||
78 | { | ||
79 | unsigned long value; | ||
80 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
81 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
82 | |||
83 | if (!data) | ||
84 | return -EINVAL; | ||
85 | |||
86 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
87 | return -EINVAL; | ||
88 | |||
89 | data->enabled = value; | ||
90 | |||
91 | return len; | ||
92 | } | ||
93 | |||
94 | static ssize_t show_enabled(struct device *d, | ||
95 | struct device_attribute *mattr, char *buf) | ||
96 | { | ||
97 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
98 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
99 | |||
100 | if (!data) | ||
101 | return -EINVAL; | ||
102 | |||
103 | if (data->enabled) | ||
104 | return sprintf(buf, "1\n"); | ||
105 | else | ||
106 | return sprintf(buf, "0\n"); | ||
107 | } | ||
108 | |||
109 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
110 | |||
111 | static struct attribute *decoder_attributes[] = { | ||
112 | &dev_attr_enabled.attr, | ||
113 | NULL | ||
114 | }; | ||
115 | |||
116 | static struct attribute_group decoder_attribute_group = { | ||
117 | .name = "nec_decoder", | ||
118 | .attrs = decoder_attributes, | ||
119 | }; | ||
120 | |||
121 | /** | ||
122 | * ir_nec_decode() - Decode one NEC pulse or space | ||
123 | * @input_dev: the struct input_dev descriptor of the device | ||
124 | * @duration: the struct ir_raw_event descriptor of the pulse/space | ||
125 | * | ||
126 | * This function returns -EINVAL if the pulse violates the state machine | ||
127 | */ | ||
128 | static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) | ||
129 | { | ||
130 | struct decoder_data *data; | ||
131 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
132 | u32 scancode; | ||
133 | u8 address, not_address, command, not_command; | ||
134 | |||
135 | data = get_decoder_data(ir_dev); | ||
136 | if (!data) | ||
137 | return -EINVAL; | ||
138 | |||
139 | if (!data->enabled) | ||
140 | return 0; | ||
141 | |||
142 | if (IS_RESET(ev)) { | ||
143 | data->state = STATE_INACTIVE; | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n", | ||
148 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
149 | |||
150 | switch (data->state) { | ||
151 | |||
152 | case STATE_INACTIVE: | ||
153 | if (!ev.pulse) | ||
154 | break; | ||
155 | |||
156 | if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) && | ||
157 | !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) | ||
158 | break; | ||
159 | |||
160 | data->count = 0; | ||
161 | data->state = STATE_HEADER_SPACE; | ||
162 | return 0; | ||
163 | |||
164 | case STATE_HEADER_SPACE: | ||
165 | if (ev.pulse) | ||
166 | break; | ||
167 | |||
168 | if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { | ||
169 | data->state = STATE_BIT_PULSE; | ||
170 | return 0; | ||
171 | } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { | ||
172 | ir_repeat(input_dev); | ||
173 | IR_dprintk(1, "Repeat last key\n"); | ||
174 | data->state = STATE_TRAILER_PULSE; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | break; | ||
179 | |||
180 | case STATE_BIT_PULSE: | ||
181 | if (!ev.pulse) | ||
182 | break; | ||
183 | |||
184 | if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) | ||
185 | break; | ||
186 | |||
187 | data->state = STATE_BIT_SPACE; | ||
188 | return 0; | ||
189 | |||
190 | case STATE_BIT_SPACE: | ||
191 | if (ev.pulse) | ||
192 | break; | ||
193 | |||
194 | data->nec_bits <<= 1; | ||
195 | if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) | ||
196 | data->nec_bits |= 1; | ||
197 | else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) | ||
198 | break; | ||
199 | data->count++; | ||
200 | |||
201 | if (data->count == NEC_NBITS) | ||
202 | data->state = STATE_TRAILER_PULSE; | ||
203 | else | ||
204 | data->state = STATE_BIT_PULSE; | ||
205 | |||
206 | return 0; | ||
207 | |||
208 | case STATE_TRAILER_PULSE: | ||
209 | if (!ev.pulse) | ||
210 | break; | ||
211 | |||
212 | if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) | ||
213 | break; | ||
214 | |||
215 | data->state = STATE_TRAILER_SPACE; | ||
216 | return 0; | ||
217 | |||
218 | case STATE_TRAILER_SPACE: | ||
219 | if (ev.pulse) | ||
220 | break; | ||
221 | |||
222 | if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) | ||
223 | break; | ||
224 | |||
225 | address = bitrev8((data->nec_bits >> 24) & 0xff); | ||
226 | not_address = bitrev8((data->nec_bits >> 16) & 0xff); | ||
227 | command = bitrev8((data->nec_bits >> 8) & 0xff); | ||
228 | not_command = bitrev8((data->nec_bits >> 0) & 0xff); | ||
229 | |||
230 | if ((command ^ not_command) != 0xff) { | ||
231 | IR_dprintk(1, "NEC checksum error: received 0x%08x\n", | ||
232 | data->nec_bits); | ||
233 | break; | ||
234 | } | ||
235 | |||
236 | if ((address ^ not_address) != 0xff) { | ||
237 | /* Extended NEC */ | ||
238 | scancode = address << 16 | | ||
239 | not_address << 8 | | ||
240 | command; | ||
241 | IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); | ||
242 | } else { | ||
243 | /* Normal NEC */ | ||
244 | scancode = address << 8 | command; | ||
245 | IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); | ||
246 | } | ||
247 | |||
248 | ir_keydown(input_dev, scancode, 0); | ||
249 | data->state = STATE_INACTIVE; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", | ||
254 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
255 | data->state = STATE_INACTIVE; | ||
256 | return -EINVAL; | ||
257 | } | ||
258 | |||
259 | static int ir_nec_register(struct input_dev *input_dev) | ||
260 | { | ||
261 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
262 | struct decoder_data *data; | ||
263 | int rc; | ||
264 | |||
265 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
266 | if (rc < 0) | ||
267 | return rc; | ||
268 | |||
269 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
270 | if (!data) { | ||
271 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | |||
275 | data->ir_dev = ir_dev; | ||
276 | data->enabled = 1; | ||
277 | |||
278 | spin_lock(&decoder_lock); | ||
279 | list_add_tail(&data->list, &decoder_list); | ||
280 | spin_unlock(&decoder_lock); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int ir_nec_unregister(struct input_dev *input_dev) | ||
286 | { | ||
287 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
288 | static struct decoder_data *data; | ||
289 | |||
290 | data = get_decoder_data(ir_dev); | ||
291 | if (!data) | ||
292 | return 0; | ||
293 | |||
294 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
295 | |||
296 | spin_lock(&decoder_lock); | ||
297 | list_del(&data->list); | ||
298 | spin_unlock(&decoder_lock); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static struct ir_raw_handler nec_handler = { | ||
304 | .decode = ir_nec_decode, | ||
305 | .raw_register = ir_nec_register, | ||
306 | .raw_unregister = ir_nec_unregister, | ||
307 | }; | ||
308 | |||
309 | static int __init ir_nec_decode_init(void) | ||
310 | { | ||
311 | ir_raw_handler_register(&nec_handler); | ||
312 | |||
313 | printk(KERN_INFO "IR NEC protocol handler initialized\n"); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static void __exit ir_nec_decode_exit(void) | ||
318 | { | ||
319 | ir_raw_handler_unregister(&nec_handler); | ||
320 | } | ||
321 | |||
322 | module_init(ir_nec_decode_init); | ||
323 | module_exit(ir_nec_decode_exit); | ||
324 | |||
325 | MODULE_LICENSE("GPL"); | ||
326 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
327 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); | ||
328 | MODULE_DESCRIPTION("NEC IR protocol decoder"); | ||
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c new file mode 100644 index 000000000000..ea68a3f2effa --- /dev/null +++ b/drivers/media/IR/ir-raw-event.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* ir-raw-event.c - handle IR Pulse/Space event | ||
2 | * | ||
3 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include "ir-core-priv.h" | ||
19 | |||
20 | /* Define the max number of pulse/space transitions to buffer */ | ||
21 | #define MAX_IR_EVENT_SIZE 512 | ||
22 | |||
23 | /* Used to handle IR raw handler extensions */ | ||
24 | static LIST_HEAD(ir_raw_handler_list); | ||
25 | static DEFINE_SPINLOCK(ir_raw_handler_lock); | ||
26 | |||
27 | /** | ||
28 | * RUN_DECODER() - runs an operation on all IR decoders | ||
29 | * @ops: IR raw handler operation to be called | ||
30 | * @arg: arguments to be passed to the callback | ||
31 | * | ||
32 | * Calls ir_raw_handler::ops for all registered IR handlers. It prevents | ||
33 | * new decode addition/removal while running, by locking ir_raw_handler_lock | ||
34 | * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum | ||
35 | * of the return codes. | ||
36 | */ | ||
37 | #define RUN_DECODER(ops, ...) ({ \ | ||
38 | struct ir_raw_handler *_ir_raw_handler; \ | ||
39 | int _sumrc = 0, _rc; \ | ||
40 | spin_lock(&ir_raw_handler_lock); \ | ||
41 | list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \ | ||
42 | if (_ir_raw_handler->ops) { \ | ||
43 | _rc = _ir_raw_handler->ops(__VA_ARGS__); \ | ||
44 | if (_rc < 0) \ | ||
45 | break; \ | ||
46 | _sumrc += _rc; \ | ||
47 | } \ | ||
48 | } \ | ||
49 | spin_unlock(&ir_raw_handler_lock); \ | ||
50 | _sumrc; \ | ||
51 | }) | ||
52 | |||
53 | #ifdef MODULE | ||
54 | /* Used to load the decoders */ | ||
55 | static struct work_struct wq_load; | ||
56 | #endif | ||
57 | |||
58 | static void ir_raw_event_work(struct work_struct *work) | ||
59 | { | ||
60 | struct ir_raw_event ev; | ||
61 | struct ir_raw_event_ctrl *raw = | ||
62 | container_of(work, struct ir_raw_event_ctrl, rx_work); | ||
63 | |||
64 | while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) | ||
65 | RUN_DECODER(decode, raw->input_dev, ev); | ||
66 | } | ||
67 | |||
68 | int ir_raw_event_register(struct input_dev *input_dev) | ||
69 | { | ||
70 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
71 | int rc; | ||
72 | |||
73 | ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); | ||
74 | if (!ir->raw) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | ir->raw->input_dev = input_dev; | ||
78 | INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); | ||
79 | |||
80 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, | ||
81 | GFP_KERNEL); | ||
82 | if (rc < 0) { | ||
83 | kfree(ir->raw); | ||
84 | ir->raw = NULL; | ||
85 | return rc; | ||
86 | } | ||
87 | |||
88 | rc = RUN_DECODER(raw_register, input_dev); | ||
89 | if (rc < 0) { | ||
90 | kfifo_free(&ir->raw->kfifo); | ||
91 | kfree(ir->raw); | ||
92 | ir->raw = NULL; | ||
93 | return rc; | ||
94 | } | ||
95 | |||
96 | return rc; | ||
97 | } | ||
98 | |||
99 | void ir_raw_event_unregister(struct input_dev *input_dev) | ||
100 | { | ||
101 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
102 | |||
103 | if (!ir->raw) | ||
104 | return; | ||
105 | |||
106 | cancel_work_sync(&ir->raw->rx_work); | ||
107 | RUN_DECODER(raw_unregister, input_dev); | ||
108 | |||
109 | kfifo_free(&ir->raw->kfifo); | ||
110 | kfree(ir->raw); | ||
111 | ir->raw = NULL; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders | ||
116 | * @input_dev: the struct input_dev device descriptor | ||
117 | * @ev: the struct ir_raw_event descriptor of the pulse/space | ||
118 | * | ||
119 | * This routine (which may be called from an interrupt context) stores a | ||
120 | * pulse/space duration for the raw ir decoding state machines. Pulses are | ||
121 | * signalled as positive values and spaces as negative values. A zero value | ||
122 | * will reset the decoding state machines. | ||
123 | */ | ||
124 | int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) | ||
125 | { | ||
126 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
127 | |||
128 | if (!ir->raw) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | EXPORT_SYMBOL_GPL(ir_raw_event_store); | ||
137 | |||
138 | /** | ||
139 | * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space | ||
140 | * @input_dev: the struct input_dev device descriptor | ||
141 | * @type: the type of the event that has occurred | ||
142 | * | ||
143 | * This routine (which may be called from an interrupt context) is used to | ||
144 | * store the beginning of an ir pulse or space (or the start/end of ir | ||
145 | * reception) for the raw ir decoding state machines. This is used by | ||
146 | * hardware which does not provide durations directly but only interrupts | ||
147 | * (or similar events) on state change. | ||
148 | */ | ||
149 | int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) | ||
150 | { | ||
151 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
152 | ktime_t now; | ||
153 | s64 delta; /* ns */ | ||
154 | struct ir_raw_event ev; | ||
155 | int rc = 0; | ||
156 | |||
157 | if (!ir->raw) | ||
158 | return -EINVAL; | ||
159 | |||
160 | now = ktime_get(); | ||
161 | delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); | ||
162 | |||
163 | /* Check for a long duration since last event or if we're | ||
164 | * being called for the first time, note that delta can't | ||
165 | * possibly be negative. | ||
166 | */ | ||
167 | ev.duration = 0; | ||
168 | if (delta > IR_MAX_DURATION || !ir->raw->last_type) | ||
169 | type |= IR_START_EVENT; | ||
170 | else | ||
171 | ev.duration = delta; | ||
172 | |||
173 | if (type & IR_START_EVENT) | ||
174 | ir_raw_event_reset(input_dev); | ||
175 | else if (ir->raw->last_type & IR_SPACE) { | ||
176 | ev.pulse = false; | ||
177 | rc = ir_raw_event_store(input_dev, &ev); | ||
178 | } else if (ir->raw->last_type & IR_PULSE) { | ||
179 | ev.pulse = true; | ||
180 | rc = ir_raw_event_store(input_dev, &ev); | ||
181 | } else | ||
182 | return 0; | ||
183 | |||
184 | ir->raw->last_event = now; | ||
185 | ir->raw->last_type = type; | ||
186 | return rc; | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); | ||
189 | |||
190 | /** | ||
191 | * ir_raw_event_handle() - schedules the decoding of stored ir data | ||
192 | * @input_dev: the struct input_dev device descriptor | ||
193 | * | ||
194 | * This routine will signal the workqueue to start decoding stored ir data. | ||
195 | */ | ||
196 | void ir_raw_event_handle(struct input_dev *input_dev) | ||
197 | { | ||
198 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
199 | |||
200 | if (!ir->raw) | ||
201 | return; | ||
202 | |||
203 | schedule_work(&ir->raw->rx_work); | ||
204 | } | ||
205 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | ||
206 | |||
207 | /* | ||
208 | * Extension interface - used to register the IR decoders | ||
209 | */ | ||
210 | |||
211 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) | ||
212 | { | ||
213 | spin_lock(&ir_raw_handler_lock); | ||
214 | list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); | ||
215 | spin_unlock(&ir_raw_handler_lock); | ||
216 | return 0; | ||
217 | } | ||
218 | EXPORT_SYMBOL(ir_raw_handler_register); | ||
219 | |||
220 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) | ||
221 | { | ||
222 | spin_lock(&ir_raw_handler_lock); | ||
223 | list_del(&ir_raw_handler->list); | ||
224 | spin_unlock(&ir_raw_handler_lock); | ||
225 | } | ||
226 | EXPORT_SYMBOL(ir_raw_handler_unregister); | ||
227 | |||
228 | #ifdef MODULE | ||
229 | static void init_decoders(struct work_struct *work) | ||
230 | { | ||
231 | /* Load the decoder modules */ | ||
232 | |||
233 | load_nec_decode(); | ||
234 | load_rc5_decode(); | ||
235 | load_rc6_decode(); | ||
236 | load_jvc_decode(); | ||
237 | load_sony_decode(); | ||
238 | |||
239 | /* If needed, we may later add some init code. In this case, | ||
240 | it is needed to change the CONFIG_MODULE test at ir-core.h | ||
241 | */ | ||
242 | } | ||
243 | #endif | ||
244 | |||
245 | void ir_raw_init(void) | ||
246 | { | ||
247 | #ifdef MODULE | ||
248 | INIT_WORK(&wq_load, init_decoders); | ||
249 | schedule_work(&wq_load); | ||
250 | #endif | ||
251 | } | ||
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c new file mode 100644 index 000000000000..23cdb1b1a3bc --- /dev/null +++ b/drivers/media/IR/ir-rc5-decoder.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols. | ||
17 | * There are other variants that use a different number of bits. | ||
18 | * This is currently unsupported. | ||
19 | * It considers a carrier of 36 kHz, with a total of 14/20 bits, where | ||
20 | * the first two bits are start bits, and a third one is a filing bit | ||
21 | */ | ||
22 | |||
23 | #include "ir-core-priv.h" | ||
24 | |||
25 | #define RC5_NBITS 14 | ||
26 | #define RC5X_NBITS 20 | ||
27 | #define CHECK_RC5X_NBITS 8 | ||
28 | #define RC5_UNIT 888888 /* ns */ | ||
29 | #define RC5_BIT_START (1 * RC5_UNIT) | ||
30 | #define RC5_BIT_END (1 * RC5_UNIT) | ||
31 | #define RC5X_SPACE (4 * RC5_UNIT) | ||
32 | |||
33 | /* Used to register rc5_decoder clients */ | ||
34 | static LIST_HEAD(decoder_list); | ||
35 | static DEFINE_SPINLOCK(decoder_lock); | ||
36 | |||
37 | enum rc5_state { | ||
38 | STATE_INACTIVE, | ||
39 | STATE_BIT_START, | ||
40 | STATE_BIT_END, | ||
41 | STATE_CHECK_RC5X, | ||
42 | STATE_FINISHED, | ||
43 | }; | ||
44 | |||
45 | struct decoder_data { | ||
46 | struct list_head list; | ||
47 | struct ir_input_dev *ir_dev; | ||
48 | int enabled:1; | ||
49 | |||
50 | /* State machine control */ | ||
51 | enum rc5_state state; | ||
52 | u32 rc5_bits; | ||
53 | struct ir_raw_event prev_ev; | ||
54 | unsigned count; | ||
55 | unsigned wanted_bits; | ||
56 | }; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * get_decoder_data() - gets decoder data | ||
61 | * @input_dev: input device | ||
62 | * | ||
63 | * Returns the struct decoder_data that corresponds to a device | ||
64 | */ | ||
65 | |||
66 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
67 | { | ||
68 | struct decoder_data *data = NULL; | ||
69 | |||
70 | spin_lock(&decoder_lock); | ||
71 | list_for_each_entry(data, &decoder_list, list) { | ||
72 | if (data->ir_dev == ir_dev) | ||
73 | break; | ||
74 | } | ||
75 | spin_unlock(&decoder_lock); | ||
76 | return data; | ||
77 | } | ||
78 | |||
79 | static ssize_t store_enabled(struct device *d, | ||
80 | struct device_attribute *mattr, | ||
81 | const char *buf, | ||
82 | size_t len) | ||
83 | { | ||
84 | unsigned long value; | ||
85 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
86 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
87 | |||
88 | if (!data) | ||
89 | return -EINVAL; | ||
90 | |||
91 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
92 | return -EINVAL; | ||
93 | |||
94 | data->enabled = value; | ||
95 | |||
96 | return len; | ||
97 | } | ||
98 | |||
99 | static ssize_t show_enabled(struct device *d, | ||
100 | struct device_attribute *mattr, char *buf) | ||
101 | { | ||
102 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
103 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
104 | |||
105 | if (!data) | ||
106 | return -EINVAL; | ||
107 | |||
108 | if (data->enabled) | ||
109 | return sprintf(buf, "1\n"); | ||
110 | else | ||
111 | return sprintf(buf, "0\n"); | ||
112 | } | ||
113 | |||
114 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
115 | |||
116 | static struct attribute *decoder_attributes[] = { | ||
117 | &dev_attr_enabled.attr, | ||
118 | NULL | ||
119 | }; | ||
120 | |||
121 | static struct attribute_group decoder_attribute_group = { | ||
122 | .name = "rc5_decoder", | ||
123 | .attrs = decoder_attributes, | ||
124 | }; | ||
125 | |||
126 | /** | ||
127 | * ir_rc5_decode() - Decode one RC-5 pulse or space | ||
128 | * @input_dev: the struct input_dev descriptor of the device | ||
129 | * @ev: the struct ir_raw_event descriptor of the pulse/space | ||
130 | * | ||
131 | * This function returns -EINVAL if the pulse violates the state machine | ||
132 | */ | ||
133 | static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) | ||
134 | { | ||
135 | struct decoder_data *data; | ||
136 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
137 | u8 toggle; | ||
138 | u32 scancode; | ||
139 | |||
140 | data = get_decoder_data(ir_dev); | ||
141 | if (!data) | ||
142 | return -EINVAL; | ||
143 | |||
144 | if (!data->enabled) | ||
145 | return 0; | ||
146 | |||
147 | if (IS_RESET(ev)) { | ||
148 | data->state = STATE_INACTIVE; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) | ||
153 | goto out; | ||
154 | |||
155 | again: | ||
156 | IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n", | ||
157 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
158 | |||
159 | if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) | ||
160 | return 0; | ||
161 | |||
162 | switch (data->state) { | ||
163 | |||
164 | case STATE_INACTIVE: | ||
165 | if (!ev.pulse) | ||
166 | break; | ||
167 | |||
168 | data->state = STATE_BIT_START; | ||
169 | data->count = 1; | ||
170 | /* We just need enough bits to get to STATE_CHECK_RC5X */ | ||
171 | data->wanted_bits = RC5X_NBITS; | ||
172 | decrease_duration(&ev, RC5_BIT_START); | ||
173 | goto again; | ||
174 | |||
175 | case STATE_BIT_START: | ||
176 | if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) | ||
177 | break; | ||
178 | |||
179 | data->rc5_bits <<= 1; | ||
180 | if (!ev.pulse) | ||
181 | data->rc5_bits |= 1; | ||
182 | data->count++; | ||
183 | data->prev_ev = ev; | ||
184 | data->state = STATE_BIT_END; | ||
185 | return 0; | ||
186 | |||
187 | case STATE_BIT_END: | ||
188 | if (!is_transition(&ev, &data->prev_ev)) | ||
189 | break; | ||
190 | |||
191 | if (data->count == data->wanted_bits) | ||
192 | data->state = STATE_FINISHED; | ||
193 | else if (data->count == CHECK_RC5X_NBITS) | ||
194 | data->state = STATE_CHECK_RC5X; | ||
195 | else | ||
196 | data->state = STATE_BIT_START; | ||
197 | |||
198 | decrease_duration(&ev, RC5_BIT_END); | ||
199 | goto again; | ||
200 | |||
201 | case STATE_CHECK_RC5X: | ||
202 | if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) { | ||
203 | /* RC5X */ | ||
204 | data->wanted_bits = RC5X_NBITS; | ||
205 | decrease_duration(&ev, RC5X_SPACE); | ||
206 | } else { | ||
207 | /* RC5 */ | ||
208 | data->wanted_bits = RC5_NBITS; | ||
209 | } | ||
210 | data->state = STATE_BIT_START; | ||
211 | goto again; | ||
212 | |||
213 | case STATE_FINISHED: | ||
214 | if (ev.pulse) | ||
215 | break; | ||
216 | |||
217 | if (data->wanted_bits == RC5X_NBITS) { | ||
218 | /* RC5X */ | ||
219 | u8 xdata, command, system; | ||
220 | xdata = (data->rc5_bits & 0x0003F) >> 0; | ||
221 | command = (data->rc5_bits & 0x00FC0) >> 6; | ||
222 | system = (data->rc5_bits & 0x1F000) >> 12; | ||
223 | toggle = (data->rc5_bits & 0x20000) ? 1 : 0; | ||
224 | command += (data->rc5_bits & 0x01000) ? 0 : 0x40; | ||
225 | scancode = system << 16 | command << 8 | xdata; | ||
226 | |||
227 | IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", | ||
228 | scancode, toggle); | ||
229 | |||
230 | } else { | ||
231 | /* RC5 */ | ||
232 | u8 command, system; | ||
233 | command = (data->rc5_bits & 0x0003F) >> 0; | ||
234 | system = (data->rc5_bits & 0x007C0) >> 6; | ||
235 | toggle = (data->rc5_bits & 0x00800) ? 1 : 0; | ||
236 | command += (data->rc5_bits & 0x01000) ? 0 : 0x40; | ||
237 | scancode = system << 8 | command; | ||
238 | |||
239 | IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", | ||
240 | scancode, toggle); | ||
241 | } | ||
242 | |||
243 | ir_keydown(input_dev, scancode, toggle); | ||
244 | data->state = STATE_INACTIVE; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | out: | ||
249 | IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n", | ||
250 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
251 | data->state = STATE_INACTIVE; | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | static int ir_rc5_register(struct input_dev *input_dev) | ||
256 | { | ||
257 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
258 | struct decoder_data *data; | ||
259 | int rc; | ||
260 | |||
261 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
262 | if (rc < 0) | ||
263 | return rc; | ||
264 | |||
265 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
266 | if (!data) { | ||
267 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
268 | return -ENOMEM; | ||
269 | } | ||
270 | |||
271 | data->ir_dev = ir_dev; | ||
272 | data->enabled = 1; | ||
273 | |||
274 | spin_lock(&decoder_lock); | ||
275 | list_add_tail(&data->list, &decoder_list); | ||
276 | spin_unlock(&decoder_lock); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int ir_rc5_unregister(struct input_dev *input_dev) | ||
282 | { | ||
283 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
284 | static struct decoder_data *data; | ||
285 | |||
286 | data = get_decoder_data(ir_dev); | ||
287 | if (!data) | ||
288 | return 0; | ||
289 | |||
290 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
291 | |||
292 | spin_lock(&decoder_lock); | ||
293 | list_del(&data->list); | ||
294 | spin_unlock(&decoder_lock); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static struct ir_raw_handler rc5_handler = { | ||
300 | .decode = ir_rc5_decode, | ||
301 | .raw_register = ir_rc5_register, | ||
302 | .raw_unregister = ir_rc5_unregister, | ||
303 | }; | ||
304 | |||
305 | static int __init ir_rc5_decode_init(void) | ||
306 | { | ||
307 | ir_raw_handler_register(&rc5_handler); | ||
308 | |||
309 | printk(KERN_INFO "IR RC5(x) protocol handler initialized\n"); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static void __exit ir_rc5_decode_exit(void) | ||
314 | { | ||
315 | ir_raw_handler_unregister(&rc5_handler); | ||
316 | } | ||
317 | |||
318 | module_init(ir_rc5_decode_init); | ||
319 | module_exit(ir_rc5_decode_exit); | ||
320 | |||
321 | MODULE_LICENSE("GPL"); | ||
322 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
323 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); | ||
324 | MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); | ||
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c new file mode 100644 index 000000000000..2bf479f4f1bc --- /dev/null +++ b/drivers/media/IR/ir-rc6-decoder.c | |||
@@ -0,0 +1,419 @@ | |||
1 | /* ir-rc6-decoder.c - A decoder for the RC6 IR protocol | ||
2 | * | ||
3 | * Copyright (C) 2010 by David Härdeman <david@hardeman.nu> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include "ir-core-priv.h" | ||
16 | |||
17 | /* | ||
18 | * This decoder currently supports: | ||
19 | * RC6-0-16 (standard toggle bit in header) | ||
20 | * RC6-6A-24 (no toggle bit) | ||
21 | * RC6-6A-32 (MCE version with toggle bit in body) | ||
22 | */ | ||
23 | |||
24 | #define RC6_UNIT 444444 /* us */ | ||
25 | #define RC6_HEADER_NBITS 4 /* not including toggle bit */ | ||
26 | #define RC6_0_NBITS 16 | ||
27 | #define RC6_6A_SMALL_NBITS 24 | ||
28 | #define RC6_6A_LARGE_NBITS 32 | ||
29 | #define RC6_PREFIX_PULSE (6 * RC6_UNIT) | ||
30 | #define RC6_PREFIX_SPACE (2 * RC6_UNIT) | ||
31 | #define RC6_BIT_START (1 * RC6_UNIT) | ||
32 | #define RC6_BIT_END (1 * RC6_UNIT) | ||
33 | #define RC6_TOGGLE_START (2 * RC6_UNIT) | ||
34 | #define RC6_TOGGLE_END (2 * RC6_UNIT) | ||
35 | #define RC6_MODE_MASK 0x07 /* for the header bits */ | ||
36 | #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ | ||
37 | #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ | ||
38 | |||
39 | /* Used to register rc6_decoder clients */ | ||
40 | static LIST_HEAD(decoder_list); | ||
41 | static DEFINE_SPINLOCK(decoder_lock); | ||
42 | |||
43 | enum rc6_mode { | ||
44 | RC6_MODE_0, | ||
45 | RC6_MODE_6A, | ||
46 | RC6_MODE_UNKNOWN, | ||
47 | }; | ||
48 | |||
49 | enum rc6_state { | ||
50 | STATE_INACTIVE, | ||
51 | STATE_PREFIX_SPACE, | ||
52 | STATE_HEADER_BIT_START, | ||
53 | STATE_HEADER_BIT_END, | ||
54 | STATE_TOGGLE_START, | ||
55 | STATE_TOGGLE_END, | ||
56 | STATE_BODY_BIT_START, | ||
57 | STATE_BODY_BIT_END, | ||
58 | STATE_FINISHED, | ||
59 | }; | ||
60 | |||
61 | struct decoder_data { | ||
62 | struct list_head list; | ||
63 | struct ir_input_dev *ir_dev; | ||
64 | int enabled:1; | ||
65 | |||
66 | /* State machine control */ | ||
67 | enum rc6_state state; | ||
68 | u8 header; | ||
69 | u32 body; | ||
70 | struct ir_raw_event prev_ev; | ||
71 | bool toggle; | ||
72 | unsigned count; | ||
73 | unsigned wanted_bits; | ||
74 | }; | ||
75 | |||
76 | |||
77 | /** | ||
78 | * get_decoder_data() - gets decoder data | ||
79 | * @input_dev: input device | ||
80 | * | ||
81 | * Returns the struct decoder_data that corresponds to a device | ||
82 | */ | ||
83 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
84 | { | ||
85 | struct decoder_data *data = NULL; | ||
86 | |||
87 | spin_lock(&decoder_lock); | ||
88 | list_for_each_entry(data, &decoder_list, list) { | ||
89 | if (data->ir_dev == ir_dev) | ||
90 | break; | ||
91 | } | ||
92 | spin_unlock(&decoder_lock); | ||
93 | return data; | ||
94 | } | ||
95 | |||
96 | static ssize_t store_enabled(struct device *d, | ||
97 | struct device_attribute *mattr, | ||
98 | const char *buf, | ||
99 | size_t len) | ||
100 | { | ||
101 | unsigned long value; | ||
102 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
103 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
104 | |||
105 | if (!data) | ||
106 | return -EINVAL; | ||
107 | |||
108 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
109 | return -EINVAL; | ||
110 | |||
111 | data->enabled = value; | ||
112 | |||
113 | return len; | ||
114 | } | ||
115 | |||
116 | static ssize_t show_enabled(struct device *d, | ||
117 | struct device_attribute *mattr, char *buf) | ||
118 | { | ||
119 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
120 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
121 | |||
122 | if (!data) | ||
123 | return -EINVAL; | ||
124 | |||
125 | if (data->enabled) | ||
126 | return sprintf(buf, "1\n"); | ||
127 | else | ||
128 | return sprintf(buf, "0\n"); | ||
129 | } | ||
130 | |||
131 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
132 | |||
133 | static struct attribute *decoder_attributes[] = { | ||
134 | &dev_attr_enabled.attr, | ||
135 | NULL | ||
136 | }; | ||
137 | |||
138 | static struct attribute_group decoder_attribute_group = { | ||
139 | .name = "rc6_decoder", | ||
140 | .attrs = decoder_attributes, | ||
141 | }; | ||
142 | |||
143 | static enum rc6_mode rc6_mode(struct decoder_data *data) { | ||
144 | switch (data->header & RC6_MODE_MASK) { | ||
145 | case 0: | ||
146 | return RC6_MODE_0; | ||
147 | case 6: | ||
148 | if (!data->toggle) | ||
149 | return RC6_MODE_6A; | ||
150 | /* fall through */ | ||
151 | default: | ||
152 | return RC6_MODE_UNKNOWN; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * ir_rc6_decode() - Decode one RC6 pulse or space | ||
158 | * @input_dev: the struct input_dev descriptor of the device | ||
159 | * @ev: the struct ir_raw_event descriptor of the pulse/space | ||
160 | * | ||
161 | * This function returns -EINVAL if the pulse violates the state machine | ||
162 | */ | ||
163 | static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) | ||
164 | { | ||
165 | struct decoder_data *data; | ||
166 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
167 | u32 scancode; | ||
168 | u8 toggle; | ||
169 | |||
170 | data = get_decoder_data(ir_dev); | ||
171 | if (!data) | ||
172 | return -EINVAL; | ||
173 | |||
174 | if (!data->enabled) | ||
175 | return 0; | ||
176 | |||
177 | if (IS_RESET(ev)) { | ||
178 | data->state = STATE_INACTIVE; | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) | ||
183 | goto out; | ||
184 | |||
185 | again: | ||
186 | IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", | ||
187 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
188 | |||
189 | if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) | ||
190 | return 0; | ||
191 | |||
192 | switch (data->state) { | ||
193 | |||
194 | case STATE_INACTIVE: | ||
195 | if (!ev.pulse) | ||
196 | break; | ||
197 | |||
198 | /* Note: larger margin on first pulse since each RC6_UNIT | ||
199 | is quite short and some hardware takes some time to | ||
200 | adjust to the signal */ | ||
201 | if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) | ||
202 | break; | ||
203 | |||
204 | data->state = STATE_PREFIX_SPACE; | ||
205 | data->count = 0; | ||
206 | return 0; | ||
207 | |||
208 | case STATE_PREFIX_SPACE: | ||
209 | if (ev.pulse) | ||
210 | break; | ||
211 | |||
212 | if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) | ||
213 | break; | ||
214 | |||
215 | data->state = STATE_HEADER_BIT_START; | ||
216 | return 0; | ||
217 | |||
218 | case STATE_HEADER_BIT_START: | ||
219 | if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) | ||
220 | break; | ||
221 | |||
222 | data->header <<= 1; | ||
223 | if (ev.pulse) | ||
224 | data->header |= 1; | ||
225 | data->count++; | ||
226 | data->prev_ev = ev; | ||
227 | data->state = STATE_HEADER_BIT_END; | ||
228 | return 0; | ||
229 | |||
230 | case STATE_HEADER_BIT_END: | ||
231 | if (!is_transition(&ev, &data->prev_ev)) | ||
232 | break; | ||
233 | |||
234 | if (data->count == RC6_HEADER_NBITS) | ||
235 | data->state = STATE_TOGGLE_START; | ||
236 | else | ||
237 | data->state = STATE_HEADER_BIT_START; | ||
238 | |||
239 | decrease_duration(&ev, RC6_BIT_END); | ||
240 | goto again; | ||
241 | |||
242 | case STATE_TOGGLE_START: | ||
243 | if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) | ||
244 | break; | ||
245 | |||
246 | data->toggle = ev.pulse; | ||
247 | data->prev_ev = ev; | ||
248 | data->state = STATE_TOGGLE_END; | ||
249 | return 0; | ||
250 | |||
251 | case STATE_TOGGLE_END: | ||
252 | if (!is_transition(&ev, &data->prev_ev) || | ||
253 | !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) | ||
254 | break; | ||
255 | |||
256 | if (!(data->header & RC6_STARTBIT_MASK)) { | ||
257 | IR_dprintk(1, "RC6 invalid start bit\n"); | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | data->state = STATE_BODY_BIT_START; | ||
262 | data->prev_ev = ev; | ||
263 | decrease_duration(&ev, RC6_TOGGLE_END); | ||
264 | data->count = 0; | ||
265 | |||
266 | switch (rc6_mode(data)) { | ||
267 | case RC6_MODE_0: | ||
268 | data->wanted_bits = RC6_0_NBITS; | ||
269 | break; | ||
270 | case RC6_MODE_6A: | ||
271 | /* This might look weird, but we basically | ||
272 | check the value of the first body bit to | ||
273 | determine the number of bits in mode 6A */ | ||
274 | if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || | ||
275 | geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) | ||
276 | data->wanted_bits = RC6_6A_LARGE_NBITS; | ||
277 | else | ||
278 | data->wanted_bits = RC6_6A_SMALL_NBITS; | ||
279 | break; | ||
280 | default: | ||
281 | IR_dprintk(1, "RC6 unknown mode\n"); | ||
282 | goto out; | ||
283 | } | ||
284 | goto again; | ||
285 | |||
286 | case STATE_BODY_BIT_START: | ||
287 | if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) | ||
288 | break; | ||
289 | |||
290 | data->body <<= 1; | ||
291 | if (ev.pulse) | ||
292 | data->body |= 1; | ||
293 | data->count++; | ||
294 | data->prev_ev = ev; | ||
295 | |||
296 | data->state = STATE_BODY_BIT_END; | ||
297 | return 0; | ||
298 | |||
299 | case STATE_BODY_BIT_END: | ||
300 | if (!is_transition(&ev, &data->prev_ev)) | ||
301 | break; | ||
302 | |||
303 | if (data->count == data->wanted_bits) | ||
304 | data->state = STATE_FINISHED; | ||
305 | else | ||
306 | data->state = STATE_BODY_BIT_START; | ||
307 | |||
308 | decrease_duration(&ev, RC6_BIT_END); | ||
309 | goto again; | ||
310 | |||
311 | case STATE_FINISHED: | ||
312 | if (ev.pulse) | ||
313 | break; | ||
314 | |||
315 | switch (rc6_mode(data)) { | ||
316 | case RC6_MODE_0: | ||
317 | scancode = data->body & 0xffff; | ||
318 | toggle = data->toggle; | ||
319 | IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", | ||
320 | scancode, toggle); | ||
321 | break; | ||
322 | case RC6_MODE_6A: | ||
323 | if (data->wanted_bits == RC6_6A_LARGE_NBITS) { | ||
324 | toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; | ||
325 | scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; | ||
326 | } else { | ||
327 | toggle = 0; | ||
328 | scancode = data->body & 0xffffff; | ||
329 | } | ||
330 | |||
331 | IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", | ||
332 | scancode, toggle); | ||
333 | break; | ||
334 | default: | ||
335 | IR_dprintk(1, "RC6 unknown mode\n"); | ||
336 | goto out; | ||
337 | } | ||
338 | |||
339 | ir_keydown(input_dev, scancode, toggle); | ||
340 | data->state = STATE_INACTIVE; | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | out: | ||
345 | IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", | ||
346 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
347 | data->state = STATE_INACTIVE; | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | static int ir_rc6_register(struct input_dev *input_dev) | ||
352 | { | ||
353 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
354 | struct decoder_data *data; | ||
355 | int rc; | ||
356 | |||
357 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
358 | if (rc < 0) | ||
359 | return rc; | ||
360 | |||
361 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
362 | if (!data) { | ||
363 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
364 | return -ENOMEM; | ||
365 | } | ||
366 | |||
367 | data->ir_dev = ir_dev; | ||
368 | data->enabled = 1; | ||
369 | |||
370 | spin_lock(&decoder_lock); | ||
371 | list_add_tail(&data->list, &decoder_list); | ||
372 | spin_unlock(&decoder_lock); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int ir_rc6_unregister(struct input_dev *input_dev) | ||
378 | { | ||
379 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
380 | static struct decoder_data *data; | ||
381 | |||
382 | data = get_decoder_data(ir_dev); | ||
383 | if (!data) | ||
384 | return 0; | ||
385 | |||
386 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
387 | |||
388 | spin_lock(&decoder_lock); | ||
389 | list_del(&data->list); | ||
390 | spin_unlock(&decoder_lock); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static struct ir_raw_handler rc6_handler = { | ||
396 | .decode = ir_rc6_decode, | ||
397 | .raw_register = ir_rc6_register, | ||
398 | .raw_unregister = ir_rc6_unregister, | ||
399 | }; | ||
400 | |||
401 | static int __init ir_rc6_decode_init(void) | ||
402 | { | ||
403 | ir_raw_handler_register(&rc6_handler); | ||
404 | |||
405 | printk(KERN_INFO "IR RC6 protocol handler initialized\n"); | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static void __exit ir_rc6_decode_exit(void) | ||
410 | { | ||
411 | ir_raw_handler_unregister(&rc6_handler); | ||
412 | } | ||
413 | |||
414 | module_init(ir_rc6_decode_init); | ||
415 | module_exit(ir_rc6_decode_exit); | ||
416 | |||
417 | MODULE_LICENSE("GPL"); | ||
418 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); | ||
419 | MODULE_DESCRIPTION("RC6 IR protocol decoder"); | ||
diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c new file mode 100644 index 000000000000..9f440c5c060d --- /dev/null +++ b/drivers/media/IR/ir-sony-decoder.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2010 by David Härdeman <david@hardeman.nu> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/bitrev.h> | ||
16 | #include "ir-core-priv.h" | ||
17 | |||
18 | #define SONY_UNIT 600000 /* ns */ | ||
19 | #define SONY_HEADER_PULSE (4 * SONY_UNIT) | ||
20 | #define SONY_HEADER_SPACE (1 * SONY_UNIT) | ||
21 | #define SONY_BIT_0_PULSE (1 * SONY_UNIT) | ||
22 | #define SONY_BIT_1_PULSE (2 * SONY_UNIT) | ||
23 | #define SONY_BIT_SPACE (1 * SONY_UNIT) | ||
24 | #define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ | ||
25 | |||
26 | /* Used to register sony_decoder clients */ | ||
27 | static LIST_HEAD(decoder_list); | ||
28 | static DEFINE_SPINLOCK(decoder_lock); | ||
29 | |||
30 | enum sony_state { | ||
31 | STATE_INACTIVE, | ||
32 | STATE_HEADER_SPACE, | ||
33 | STATE_BIT_PULSE, | ||
34 | STATE_BIT_SPACE, | ||
35 | STATE_FINISHED, | ||
36 | }; | ||
37 | |||
38 | struct decoder_data { | ||
39 | struct list_head list; | ||
40 | struct ir_input_dev *ir_dev; | ||
41 | int enabled:1; | ||
42 | |||
43 | /* State machine control */ | ||
44 | enum sony_state state; | ||
45 | u32 sony_bits; | ||
46 | unsigned count; | ||
47 | }; | ||
48 | |||
49 | |||
50 | /** | ||
51 | * get_decoder_data() - gets decoder data | ||
52 | * @input_dev: input device | ||
53 | * | ||
54 | * Returns the struct decoder_data that corresponds to a device | ||
55 | */ | ||
56 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
57 | { | ||
58 | struct decoder_data *data = NULL; | ||
59 | |||
60 | spin_lock(&decoder_lock); | ||
61 | list_for_each_entry(data, &decoder_list, list) { | ||
62 | if (data->ir_dev == ir_dev) | ||
63 | break; | ||
64 | } | ||
65 | spin_unlock(&decoder_lock); | ||
66 | return data; | ||
67 | } | ||
68 | |||
69 | static ssize_t store_enabled(struct device *d, | ||
70 | struct device_attribute *mattr, | ||
71 | const char *buf, | ||
72 | size_t len) | ||
73 | { | ||
74 | unsigned long value; | ||
75 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
76 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
77 | |||
78 | if (!data) | ||
79 | return -EINVAL; | ||
80 | |||
81 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
82 | return -EINVAL; | ||
83 | |||
84 | data->enabled = value; | ||
85 | |||
86 | return len; | ||
87 | } | ||
88 | |||
89 | static ssize_t show_enabled(struct device *d, | ||
90 | struct device_attribute *mattr, char *buf) | ||
91 | { | ||
92 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
93 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
94 | |||
95 | if (!data) | ||
96 | return -EINVAL; | ||
97 | |||
98 | if (data->enabled) | ||
99 | return sprintf(buf, "1\n"); | ||
100 | else | ||
101 | return sprintf(buf, "0\n"); | ||
102 | } | ||
103 | |||
104 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
105 | |||
106 | static struct attribute *decoder_attributes[] = { | ||
107 | &dev_attr_enabled.attr, | ||
108 | NULL | ||
109 | }; | ||
110 | |||
111 | static struct attribute_group decoder_attribute_group = { | ||
112 | .name = "sony_decoder", | ||
113 | .attrs = decoder_attributes, | ||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * ir_sony_decode() - Decode one Sony pulse or space | ||
118 | * @input_dev: the struct input_dev descriptor of the device | ||
119 | * @ev: the struct ir_raw_event descriptor of the pulse/space | ||
120 | * | ||
121 | * This function returns -EINVAL if the pulse violates the state machine | ||
122 | */ | ||
123 | static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) | ||
124 | { | ||
125 | struct decoder_data *data; | ||
126 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
127 | u32 scancode; | ||
128 | u8 device, subdevice, function; | ||
129 | |||
130 | data = get_decoder_data(ir_dev); | ||
131 | if (!data) | ||
132 | return -EINVAL; | ||
133 | |||
134 | if (!data->enabled) | ||
135 | return 0; | ||
136 | |||
137 | if (IS_RESET(ev)) { | ||
138 | data->state = STATE_INACTIVE; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) | ||
143 | goto out; | ||
144 | |||
145 | IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n", | ||
146 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
147 | |||
148 | switch (data->state) { | ||
149 | |||
150 | case STATE_INACTIVE: | ||
151 | if (!ev.pulse) | ||
152 | break; | ||
153 | |||
154 | if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2)) | ||
155 | break; | ||
156 | |||
157 | data->count = 0; | ||
158 | data->state = STATE_HEADER_SPACE; | ||
159 | return 0; | ||
160 | |||
161 | case STATE_HEADER_SPACE: | ||
162 | if (ev.pulse) | ||
163 | break; | ||
164 | |||
165 | if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2)) | ||
166 | break; | ||
167 | |||
168 | data->state = STATE_BIT_PULSE; | ||
169 | return 0; | ||
170 | |||
171 | case STATE_BIT_PULSE: | ||
172 | if (!ev.pulse) | ||
173 | break; | ||
174 | |||
175 | data->sony_bits <<= 1; | ||
176 | if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) | ||
177 | data->sony_bits |= 1; | ||
178 | else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) | ||
179 | break; | ||
180 | |||
181 | data->count++; | ||
182 | data->state = STATE_BIT_SPACE; | ||
183 | return 0; | ||
184 | |||
185 | case STATE_BIT_SPACE: | ||
186 | if (ev.pulse) | ||
187 | break; | ||
188 | |||
189 | if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2)) | ||
190 | break; | ||
191 | |||
192 | decrease_duration(&ev, SONY_BIT_SPACE); | ||
193 | |||
194 | if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) { | ||
195 | data->state = STATE_BIT_PULSE; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | data->state = STATE_FINISHED; | ||
200 | /* Fall through */ | ||
201 | |||
202 | case STATE_FINISHED: | ||
203 | if (ev.pulse) | ||
204 | break; | ||
205 | |||
206 | if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2)) | ||
207 | break; | ||
208 | |||
209 | switch (data->count) { | ||
210 | case 12: | ||
211 | device = bitrev8((data->sony_bits << 3) & 0xF8); | ||
212 | subdevice = 0; | ||
213 | function = bitrev8((data->sony_bits >> 4) & 0xFE); | ||
214 | break; | ||
215 | case 15: | ||
216 | device = bitrev8((data->sony_bits >> 0) & 0xFF); | ||
217 | subdevice = 0; | ||
218 | function = bitrev8((data->sony_bits >> 7) & 0xFD); | ||
219 | break; | ||
220 | case 20: | ||
221 | device = bitrev8((data->sony_bits >> 5) & 0xF8); | ||
222 | subdevice = bitrev8((data->sony_bits >> 0) & 0xFF); | ||
223 | function = bitrev8((data->sony_bits >> 12) & 0xFE); | ||
224 | break; | ||
225 | default: | ||
226 | IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | scancode = device << 16 | subdevice << 8 | function; | ||
231 | IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); | ||
232 | ir_keydown(input_dev, scancode, 0); | ||
233 | data->state = STATE_INACTIVE; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | out: | ||
238 | IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n", | ||
239 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
240 | data->state = STATE_INACTIVE; | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | |||
244 | static int ir_sony_register(struct input_dev *input_dev) | ||
245 | { | ||
246 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
247 | struct decoder_data *data; | ||
248 | int rc; | ||
249 | |||
250 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
251 | if (rc < 0) | ||
252 | return rc; | ||
253 | |||
254 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
255 | if (!data) { | ||
256 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
257 | return -ENOMEM; | ||
258 | } | ||
259 | |||
260 | data->ir_dev = ir_dev; | ||
261 | data->enabled = 1; | ||
262 | |||
263 | spin_lock(&decoder_lock); | ||
264 | list_add_tail(&data->list, &decoder_list); | ||
265 | spin_unlock(&decoder_lock); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int ir_sony_unregister(struct input_dev *input_dev) | ||
271 | { | ||
272 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
273 | static struct decoder_data *data; | ||
274 | |||
275 | data = get_decoder_data(ir_dev); | ||
276 | if (!data) | ||
277 | return 0; | ||
278 | |||
279 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
280 | |||
281 | spin_lock(&decoder_lock); | ||
282 | list_del(&data->list); | ||
283 | spin_unlock(&decoder_lock); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct ir_raw_handler sony_handler = { | ||
289 | .decode = ir_sony_decode, | ||
290 | .raw_register = ir_sony_register, | ||
291 | .raw_unregister = ir_sony_unregister, | ||
292 | }; | ||
293 | |||
294 | static int __init ir_sony_decode_init(void) | ||
295 | { | ||
296 | ir_raw_handler_register(&sony_handler); | ||
297 | |||
298 | printk(KERN_INFO "IR Sony protocol handler initialized\n"); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static void __exit ir_sony_decode_exit(void) | ||
303 | { | ||
304 | ir_raw_handler_unregister(&sony_handler); | ||
305 | } | ||
306 | |||
307 | module_init(ir_sony_decode_init); | ||
308 | module_exit(ir_sony_decode_exit); | ||
309 | |||
310 | MODULE_LICENSE("GPL"); | ||
311 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); | ||
312 | MODULE_DESCRIPTION("Sony IR protocol decoder"); | ||
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index e14e6c486b52..d7da63e16c92 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* ir-register.c - handle IR scancode->keycode tables | 1 | /* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) |
2 | * | 2 | * |
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | 3 | * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -15,15 +15,23 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <media/ir-core.h> | 18 | #include "ir-core-priv.h" |
19 | 19 | ||
20 | #define IRRCV_NUM_DEVICES 256 | 20 | #define IRRCV_NUM_DEVICES 256 |
21 | 21 | ||
22 | /* bit array to represent IR sysfs device number */ | 22 | /* bit array to represent IR sysfs device number */ |
23 | static unsigned long ir_core_dev_number; | 23 | static unsigned long ir_core_dev_number; |
24 | 24 | ||
25 | /* class for /sys/class/irrcv */ | 25 | /* class for /sys/class/rc */ |
26 | static struct class *ir_input_class; | 26 | static char *ir_devnode(struct device *dev, mode_t *mode) |
27 | { | ||
28 | return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); | ||
29 | } | ||
30 | |||
31 | static struct class ir_input_class = { | ||
32 | .name = "rc", | ||
33 | .devnode = ir_devnode, | ||
34 | }; | ||
27 | 35 | ||
28 | /** | 36 | /** |
29 | * show_protocol() - shows the current IR protocol | 37 | * show_protocol() - shows the current IR protocol |
@@ -32,7 +40,7 @@ static struct class *ir_input_class; | |||
32 | * @buf: a pointer to the output buffer | 40 | * @buf: a pointer to the output buffer |
33 | * | 41 | * |
34 | * This routine is a callback routine for input read the IR protocol type. | 42 | * This routine is a callback routine for input read the IR protocol type. |
35 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | 43 | * it is trigged by reading /sys/class/rc/rc?/current_protocol. |
36 | * It returns the protocol name, as understood by the driver. | 44 | * It returns the protocol name, as understood by the driver. |
37 | */ | 45 | */ |
38 | static ssize_t show_protocol(struct device *d, | 46 | static ssize_t show_protocol(struct device *d, |
@@ -48,13 +56,17 @@ static ssize_t show_protocol(struct device *d, | |||
48 | if (ir_type == IR_TYPE_UNKNOWN) | 56 | if (ir_type == IR_TYPE_UNKNOWN) |
49 | s = "Unknown"; | 57 | s = "Unknown"; |
50 | else if (ir_type == IR_TYPE_RC5) | 58 | else if (ir_type == IR_TYPE_RC5) |
51 | s = "RC-5"; | 59 | s = "rc-5"; |
52 | else if (ir_type == IR_TYPE_PD) | ||
53 | s = "Pulse/distance"; | ||
54 | else if (ir_type == IR_TYPE_NEC) | 60 | else if (ir_type == IR_TYPE_NEC) |
55 | s = "NEC"; | 61 | s = "nec"; |
62 | else if (ir_type == IR_TYPE_RC6) | ||
63 | s = "rc6"; | ||
64 | else if (ir_type == IR_TYPE_JVC) | ||
65 | s = "jvc"; | ||
66 | else if (ir_type == IR_TYPE_SONY) | ||
67 | s = "sony"; | ||
56 | else | 68 | else |
57 | s = "Other"; | 69 | s = "other"; |
58 | 70 | ||
59 | return sprintf(buf, "%s\n", s); | 71 | return sprintf(buf, "%s\n", s); |
60 | } | 72 | } |
@@ -67,7 +79,7 @@ static ssize_t show_protocol(struct device *d, | |||
67 | * @len: length of the input buffer | 79 | * @len: length of the input buffer |
68 | * | 80 | * |
69 | * This routine is a callback routine for changing the IR protocol type. | 81 | * This routine is a callback routine for changing the IR protocol type. |
70 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | 82 | * it is trigged by reading /sys/class/rc/rc?/current_protocol. |
71 | * It changes the IR the protocol name, if the IR type is recognized | 83 | * It changes the IR the protocol name, if the IR type is recognized |
72 | * by the driver. | 84 | * by the driver. |
73 | * If an unknown protocol name is used, returns -EINVAL. | 85 | * If an unknown protocol name is used, returns -EINVAL. |
@@ -78,23 +90,24 @@ static ssize_t store_protocol(struct device *d, | |||
78 | size_t len) | 90 | size_t len) |
79 | { | 91 | { |
80 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | 92 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); |
81 | u64 ir_type = IR_TYPE_UNKNOWN; | 93 | u64 ir_type = 0; |
82 | int rc = -EINVAL; | 94 | int rc = -EINVAL; |
83 | unsigned long flags; | 95 | unsigned long flags; |
84 | char *buf; | 96 | char *buf; |
85 | 97 | ||
86 | buf = strsep((char **) &data, "\n"); | 98 | while ((buf = strsep((char **) &data, " \n")) != NULL) { |
87 | 99 | if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) | |
88 | if (!strcasecmp(buf, "rc-5")) | 100 | ir_type |= IR_TYPE_RC5; |
89 | ir_type = IR_TYPE_RC5; | 101 | if (!strcasecmp(buf, "nec")) |
90 | else if (!strcasecmp(buf, "pd")) | 102 | ir_type |= IR_TYPE_NEC; |
91 | ir_type = IR_TYPE_PD; | 103 | if (!strcasecmp(buf, "jvc")) |
92 | else if (!strcasecmp(buf, "nec")) | 104 | ir_type |= IR_TYPE_JVC; |
93 | ir_type = IR_TYPE_NEC; | 105 | if (!strcasecmp(buf, "sony")) |
106 | ir_type |= IR_TYPE_SONY; | ||
107 | } | ||
94 | 108 | ||
95 | if (ir_type == IR_TYPE_UNKNOWN) { | 109 | if (!ir_type) { |
96 | IR_dprintk(1, "Error setting protocol to %lld\n", | 110 | IR_dprintk(1, "Unknown protocol\n"); |
97 | (long long)ir_type); | ||
98 | return -EINVAL; | 111 | return -EINVAL; |
99 | } | 112 | } |
100 | 113 | ||
@@ -112,25 +125,87 @@ static ssize_t store_protocol(struct device *d, | |||
112 | ir_dev->rc_tab.ir_type = ir_type; | 125 | ir_dev->rc_tab.ir_type = ir_type; |
113 | spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); | 126 | spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); |
114 | 127 | ||
115 | IR_dprintk(1, "Current protocol is %lld\n", | 128 | IR_dprintk(1, "Current protocol(s) is(are) %lld\n", |
116 | (long long)ir_type); | 129 | (long long)ir_type); |
117 | 130 | ||
118 | return len; | 131 | return len; |
119 | } | 132 | } |
120 | 133 | ||
134 | static ssize_t show_supported_protocols(struct device *d, | ||
135 | struct device_attribute *mattr, char *buf) | ||
136 | { | ||
137 | char *orgbuf = buf; | ||
138 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
139 | |||
140 | /* FIXME: doesn't support multiple protocols at the same time */ | ||
141 | if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN) | ||
142 | buf += sprintf(buf, "unknown "); | ||
143 | if (ir_dev->props->allowed_protos & IR_TYPE_RC5) | ||
144 | buf += sprintf(buf, "rc-5 "); | ||
145 | if (ir_dev->props->allowed_protos & IR_TYPE_NEC) | ||
146 | buf += sprintf(buf, "nec "); | ||
147 | if (buf == orgbuf) | ||
148 | buf += sprintf(buf, "other "); | ||
149 | |||
150 | buf += sprintf(buf - 1, "\n"); | ||
151 | |||
152 | return buf - orgbuf; | ||
153 | } | ||
154 | |||
155 | #define ADD_HOTPLUG_VAR(fmt, val...) \ | ||
156 | do { \ | ||
157 | int err = add_uevent_var(env, fmt, val); \ | ||
158 | if (err) \ | ||
159 | return err; \ | ||
160 | } while (0) | ||
161 | |||
162 | static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) | ||
163 | { | ||
164 | struct ir_input_dev *ir_dev = dev_get_drvdata(device); | ||
165 | |||
166 | if (ir_dev->rc_tab.name) | ||
167 | ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); | ||
168 | if (ir_dev->driver_name) | ||
169 | ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
121 | /* | 174 | /* |
122 | * Static device attribute struct with the sysfs attributes for IR's | 175 | * Static device attribute struct with the sysfs attributes for IR's |
123 | */ | 176 | */ |
124 | static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, | 177 | static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, |
125 | show_protocol, store_protocol); | 178 | show_protocol, store_protocol); |
126 | 179 | ||
127 | static struct attribute *ir_dev_attrs[] = { | 180 | static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR, |
128 | &dev_attr_current_protocol.attr, | 181 | show_supported_protocols, NULL); |
182 | |||
183 | static struct attribute *ir_hw_dev_attrs[] = { | ||
184 | &dev_attr_protocol.attr, | ||
185 | &dev_attr_supported_protocols.attr, | ||
129 | NULL, | 186 | NULL, |
130 | }; | 187 | }; |
131 | 188 | ||
189 | static struct attribute_group ir_hw_dev_attr_grp = { | ||
190 | .attrs = ir_hw_dev_attrs, | ||
191 | }; | ||
192 | |||
193 | static const struct attribute_group *ir_hw_dev_attr_groups[] = { | ||
194 | &ir_hw_dev_attr_grp, | ||
195 | NULL | ||
196 | }; | ||
197 | |||
198 | static struct device_type rc_dev_type = { | ||
199 | .groups = ir_hw_dev_attr_groups, | ||
200 | .uevent = ir_dev_uevent, | ||
201 | }; | ||
202 | |||
203 | static struct device_type ir_raw_dev_type = { | ||
204 | .uevent = ir_dev_uevent, | ||
205 | }; | ||
206 | |||
132 | /** | 207 | /** |
133 | * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? | 208 | * ir_register_class() - creates the sysfs for /sys/class/rc/rc? |
134 | * @input_dev: the struct input_dev descriptor of the device | 209 | * @input_dev: the struct input_dev descriptor of the device |
135 | * | 210 | * |
136 | * This routine is used to register the syfs code for IR class | 211 | * This routine is used to register the syfs code for IR class |
@@ -138,8 +213,7 @@ static struct attribute *ir_dev_attrs[] = { | |||
138 | int ir_register_class(struct input_dev *input_dev) | 213 | int ir_register_class(struct input_dev *input_dev) |
139 | { | 214 | { |
140 | int rc; | 215 | int rc; |
141 | struct kobject *kobj; | 216 | const char *path; |
142 | |||
143 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 217 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
144 | int devno = find_first_zero_bit(&ir_core_dev_number, | 218 | int devno = find_first_zero_bit(&ir_core_dev_number, |
145 | IRRCV_NUM_DEVICES); | 219 | IRRCV_NUM_DEVICES); |
@@ -147,19 +221,36 @@ int ir_register_class(struct input_dev *input_dev) | |||
147 | if (unlikely(devno < 0)) | 221 | if (unlikely(devno < 0)) |
148 | return devno; | 222 | return devno; |
149 | 223 | ||
150 | ir_dev->attr.attrs = ir_dev_attrs; | 224 | if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) |
151 | ir_dev->class_dev = device_create(ir_input_class, NULL, | 225 | ir_dev->dev.type = &rc_dev_type; |
152 | input_dev->dev.devt, ir_dev, | 226 | else |
153 | "irrcv%d", devno); | 227 | ir_dev->dev.type = &ir_raw_dev_type; |
154 | kobj = &ir_dev->class_dev->kobj; | 228 | |
155 | 229 | ir_dev->dev.class = &ir_input_class; | |
156 | printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj)); | 230 | ir_dev->dev.parent = input_dev->dev.parent; |
157 | rc = sysfs_create_group(kobj, &ir_dev->attr); | 231 | dev_set_name(&ir_dev->dev, "rc%d", devno); |
158 | if (unlikely(rc < 0)) { | 232 | dev_set_drvdata(&ir_dev->dev, ir_dev); |
159 | device_destroy(ir_input_class, input_dev->dev.devt); | 233 | rc = device_register(&ir_dev->dev); |
160 | return -ENOMEM; | 234 | if (rc) |
235 | return rc; | ||
236 | |||
237 | |||
238 | input_dev->dev.parent = &ir_dev->dev; | ||
239 | rc = input_register_device(input_dev); | ||
240 | if (rc < 0) { | ||
241 | device_del(&ir_dev->dev); | ||
242 | return rc; | ||
161 | } | 243 | } |
162 | 244 | ||
245 | __module_get(THIS_MODULE); | ||
246 | |||
247 | path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); | ||
248 | printk(KERN_INFO "%s: %s as %s\n", | ||
249 | dev_name(&ir_dev->dev), | ||
250 | input_dev->name ? input_dev->name : "Unspecified device", | ||
251 | path ? path : "N/A"); | ||
252 | kfree(path); | ||
253 | |||
163 | ir_dev->devno = devno; | 254 | ir_dev->devno = devno; |
164 | set_bit(devno, &ir_core_dev_number); | 255 | set_bit(devno, &ir_core_dev_number); |
165 | 256 | ||
@@ -168,7 +259,7 @@ int ir_register_class(struct input_dev *input_dev) | |||
168 | 259 | ||
169 | /** | 260 | /** |
170 | * ir_unregister_class() - removes the sysfs for sysfs for | 261 | * ir_unregister_class() - removes the sysfs for sysfs for |
171 | * /sys/class/irrcv/irrcv? | 262 | * /sys/class/rc/rc? |
172 | * @input_dev: the struct input_dev descriptor of the device | 263 | * @input_dev: the struct input_dev descriptor of the device |
173 | * | 264 | * |
174 | * This routine is used to unregister the syfs code for IR class | 265 | * This routine is used to unregister the syfs code for IR class |
@@ -176,36 +267,35 @@ int ir_register_class(struct input_dev *input_dev) | |||
176 | void ir_unregister_class(struct input_dev *input_dev) | 267 | void ir_unregister_class(struct input_dev *input_dev) |
177 | { | 268 | { |
178 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 269 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
179 | struct kobject *kobj; | ||
180 | 270 | ||
181 | clear_bit(ir_dev->devno, &ir_core_dev_number); | 271 | clear_bit(ir_dev->devno, &ir_core_dev_number); |
272 | input_unregister_device(input_dev); | ||
273 | device_del(&ir_dev->dev); | ||
182 | 274 | ||
183 | kobj = &ir_dev->class_dev->kobj; | 275 | module_put(THIS_MODULE); |
184 | |||
185 | sysfs_remove_group(kobj, &ir_dev->attr); | ||
186 | device_destroy(ir_input_class, input_dev->dev.devt); | ||
187 | |||
188 | kfree(ir_dev->attr.name); | ||
189 | } | 276 | } |
190 | 277 | ||
191 | /* | 278 | /* |
192 | * Init/exit code for the module. Basically, creates/removes /sys/class/irrcv | 279 | * Init/exit code for the module. Basically, creates/removes /sys/class/rc |
193 | */ | 280 | */ |
194 | 281 | ||
195 | static int __init ir_core_init(void) | 282 | static int __init ir_core_init(void) |
196 | { | 283 | { |
197 | ir_input_class = class_create(THIS_MODULE, "irrcv"); | 284 | int rc = class_register(&ir_input_class); |
198 | if (IS_ERR(ir_input_class)) { | 285 | if (rc) { |
199 | printk(KERN_ERR "ir_core: unable to register irrcv class\n"); | 286 | printk(KERN_ERR "ir_core: unable to register rc class\n"); |
200 | return PTR_ERR(ir_input_class); | 287 | return rc; |
201 | } | 288 | } |
202 | 289 | ||
290 | /* Initialize/load the decoders/keymap code that will be used */ | ||
291 | ir_raw_init(); | ||
292 | |||
203 | return 0; | 293 | return 0; |
204 | } | 294 | } |
205 | 295 | ||
206 | static void __exit ir_core_exit(void) | 296 | static void __exit ir_core_exit(void) |
207 | { | 297 | { |
208 | class_destroy(ir_input_class); | 298 | class_unregister(&ir_input_class); |
209 | } | 299 | } |
210 | 300 | ||
211 | module_init(ir_core_init); | 301 | module_init(ir_core_init); |
diff --git a/drivers/media/IR/keymaps/Kconfig b/drivers/media/IR/keymaps/Kconfig new file mode 100644 index 000000000000..14b22f58f823 --- /dev/null +++ b/drivers/media/IR/keymaps/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | config RC_MAP | ||
2 | tristate "Compile Remote Controller keymap modules" | ||
3 | depends on IR_CORE | ||
4 | default y | ||
5 | |||
6 | ---help--- | ||
7 | This option enables the compilation of lots of Remote | ||
8 | Controller tables. They are short tables, but if you | ||
9 | don't use a remote controller, or prefer to load the | ||
10 | tables on userspace, you should disable it. | ||
11 | |||
12 | The ir-keytable program, available at v4l-utils package | ||
13 | provide the tool and the same RC maps for load from | ||
14 | userspace. Its available at | ||
15 | http://git.linuxtv.org/v4l-utils | ||
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile new file mode 100644 index 000000000000..ec25258a955f --- /dev/null +++ b/drivers/media/IR/keymaps/Makefile | |||
@@ -0,0 +1,67 @@ | |||
1 | obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | ||
2 | rc-apac-viewcomp.o \ | ||
3 | rc-asus-pc39.o \ | ||
4 | rc-ati-tv-wonder-hd-600.o \ | ||
5 | rc-avermedia-a16d.o \ | ||
6 | rc-avermedia.o \ | ||
7 | rc-avermedia-cardbus.o \ | ||
8 | rc-avermedia-dvbt.o \ | ||
9 | rc-avermedia-m135a-rm-jx.o \ | ||
10 | rc-avertv-303.o \ | ||
11 | rc-behold.o \ | ||
12 | rc-behold-columbus.o \ | ||
13 | rc-budget-ci-old.o \ | ||
14 | rc-cinergy-1400.o \ | ||
15 | rc-cinergy.o \ | ||
16 | rc-dm1105-nec.o \ | ||
17 | rc-dntv-live-dvb-t.o \ | ||
18 | rc-dntv-live-dvbt-pro.o \ | ||
19 | rc-empty.o \ | ||
20 | rc-em-terratec.o \ | ||
21 | rc-encore-enltv2.o \ | ||
22 | rc-encore-enltv.o \ | ||
23 | rc-encore-enltv-fm53.o \ | ||
24 | rc-evga-indtube.o \ | ||
25 | rc-eztv.o \ | ||
26 | rc-flydvb.o \ | ||
27 | rc-flyvideo.o \ | ||
28 | rc-fusionhdtv-mce.o \ | ||
29 | rc-gadmei-rm008z.o \ | ||
30 | rc-genius-tvgo-a11mce.o \ | ||
31 | rc-gotview7135.o \ | ||
32 | rc-hauppauge-new.o \ | ||
33 | rc-imon-mce.o \ | ||
34 | rc-imon-pad.o \ | ||
35 | rc-iodata-bctv7e.o \ | ||
36 | rc-kaiomy.o \ | ||
37 | rc-kworld-315u.o \ | ||
38 | rc-kworld-plus-tv-analog.o \ | ||
39 | rc-manli.o \ | ||
40 | rc-msi-tvanywhere.o \ | ||
41 | rc-msi-tvanywhere-plus.o \ | ||
42 | rc-nebula.o \ | ||
43 | rc-nec-terratec-cinergy-xs.o \ | ||
44 | rc-norwood.o \ | ||
45 | rc-npgtech.o \ | ||
46 | rc-pctv-sedna.o \ | ||
47 | rc-pinnacle-color.o \ | ||
48 | rc-pinnacle-grey.o \ | ||
49 | rc-pinnacle-pctv-hd.o \ | ||
50 | rc-pixelview.o \ | ||
51 | rc-pixelview-mk12.o \ | ||
52 | rc-pixelview-new.o \ | ||
53 | rc-powercolor-real-angel.o \ | ||
54 | rc-proteus-2309.o \ | ||
55 | rc-purpletv.o \ | ||
56 | rc-pv951.o \ | ||
57 | rc-rc5-hauppauge-new.o \ | ||
58 | rc-rc5-tv.o \ | ||
59 | rc-real-audio-220-32-keys.o \ | ||
60 | rc-tbs-nec.o \ | ||
61 | rc-terratec-cinergy-xs.o \ | ||
62 | rc-tevii-nec.o \ | ||
63 | rc-tt-1500.o \ | ||
64 | rc-videomate-s350.o \ | ||
65 | rc-videomate-tv-pvr.o \ | ||
66 | rc-winfast.o \ | ||
67 | rc-winfast-usbii-deluxe.o | ||
diff --git a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c new file mode 100644 index 000000000000..b17283176ecd --- /dev/null +++ b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* ADS Tech Instant TV DVB-T PCI Remote */ | ||
16 | |||
17 | static struct ir_scancode adstech_dvb_t_pci[] = { | ||
18 | /* Keys 0 to 9 */ | ||
19 | { 0x4d, KEY_0 }, | ||
20 | { 0x57, KEY_1 }, | ||
21 | { 0x4f, KEY_2 }, | ||
22 | { 0x53, KEY_3 }, | ||
23 | { 0x56, KEY_4 }, | ||
24 | { 0x4e, KEY_5 }, | ||
25 | { 0x5e, KEY_6 }, | ||
26 | { 0x54, KEY_7 }, | ||
27 | { 0x4c, KEY_8 }, | ||
28 | { 0x5c, KEY_9 }, | ||
29 | |||
30 | { 0x5b, KEY_POWER }, | ||
31 | { 0x5f, KEY_MUTE }, | ||
32 | { 0x55, KEY_GOTO }, | ||
33 | { 0x5d, KEY_SEARCH }, | ||
34 | { 0x17, KEY_EPG }, /* Guide */ | ||
35 | { 0x1f, KEY_MENU }, | ||
36 | { 0x0f, KEY_UP }, | ||
37 | { 0x46, KEY_DOWN }, | ||
38 | { 0x16, KEY_LEFT }, | ||
39 | { 0x1e, KEY_RIGHT }, | ||
40 | { 0x0e, KEY_SELECT }, /* Enter */ | ||
41 | { 0x5a, KEY_INFO }, | ||
42 | { 0x52, KEY_EXIT }, | ||
43 | { 0x59, KEY_PREVIOUS }, | ||
44 | { 0x51, KEY_NEXT }, | ||
45 | { 0x58, KEY_REWIND }, | ||
46 | { 0x50, KEY_FORWARD }, | ||
47 | { 0x44, KEY_PLAYPAUSE }, | ||
48 | { 0x07, KEY_STOP }, | ||
49 | { 0x1b, KEY_RECORD }, | ||
50 | { 0x13, KEY_TUNER }, /* Live */ | ||
51 | { 0x0a, KEY_A }, | ||
52 | { 0x12, KEY_B }, | ||
53 | { 0x03, KEY_PROG1 }, /* 1 */ | ||
54 | { 0x01, KEY_PROG2 }, /* 2 */ | ||
55 | { 0x00, KEY_PROG3 }, /* 3 */ | ||
56 | { 0x06, KEY_DVD }, | ||
57 | { 0x48, KEY_AUX }, /* Photo */ | ||
58 | { 0x40, KEY_VIDEO }, | ||
59 | { 0x19, KEY_AUDIO }, /* Music */ | ||
60 | { 0x0b, KEY_CHANNELUP }, | ||
61 | { 0x08, KEY_CHANNELDOWN }, | ||
62 | { 0x15, KEY_VOLUMEUP }, | ||
63 | { 0x1c, KEY_VOLUMEDOWN }, | ||
64 | }; | ||
65 | |||
66 | static struct rc_keymap adstech_dvb_t_pci_map = { | ||
67 | .map = { | ||
68 | .scan = adstech_dvb_t_pci, | ||
69 | .size = ARRAY_SIZE(adstech_dvb_t_pci), | ||
70 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
71 | .name = RC_MAP_ADSTECH_DVB_T_PCI, | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | static int __init init_rc_map_adstech_dvb_t_pci(void) | ||
76 | { | ||
77 | return ir_register_map(&adstech_dvb_t_pci_map); | ||
78 | } | ||
79 | |||
80 | static void __exit exit_rc_map_adstech_dvb_t_pci(void) | ||
81 | { | ||
82 | ir_unregister_map(&adstech_dvb_t_pci_map); | ||
83 | } | ||
84 | |||
85 | module_init(init_rc_map_adstech_dvb_t_pci) | ||
86 | module_exit(exit_rc_map_adstech_dvb_t_pci) | ||
87 | |||
88 | MODULE_LICENSE("GPL"); | ||
89 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-apac-viewcomp.c b/drivers/media/IR/keymaps/rc-apac-viewcomp.c new file mode 100644 index 000000000000..0ef2b562baf0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-apac-viewcomp.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Attila Kondoros <attila.kondoros@chello.hu> */ | ||
16 | |||
17 | static struct ir_scancode apac_viewcomp[] = { | ||
18 | |||
19 | { 0x01, KEY_1 }, | ||
20 | { 0x02, KEY_2 }, | ||
21 | { 0x03, KEY_3 }, | ||
22 | { 0x04, KEY_4 }, | ||
23 | { 0x05, KEY_5 }, | ||
24 | { 0x06, KEY_6 }, | ||
25 | { 0x07, KEY_7 }, | ||
26 | { 0x08, KEY_8 }, | ||
27 | { 0x09, KEY_9 }, | ||
28 | { 0x00, KEY_0 }, | ||
29 | { 0x17, KEY_LAST }, /* +100 */ | ||
30 | { 0x0a, KEY_LIST }, /* recall */ | ||
31 | |||
32 | |||
33 | { 0x1c, KEY_TUNER }, /* TV/FM */ | ||
34 | { 0x15, KEY_SEARCH }, /* scan */ | ||
35 | { 0x12, KEY_POWER }, /* power */ | ||
36 | { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ | ||
37 | { 0x1b, KEY_VOLUMEUP }, /* vol down */ | ||
38 | { 0x1e, KEY_CHANNELDOWN }, /* chn up */ | ||
39 | { 0x1a, KEY_CHANNELUP }, /* chn down */ | ||
40 | |||
41 | { 0x11, KEY_VIDEO }, /* video */ | ||
42 | { 0x0f, KEY_ZOOM }, /* full screen */ | ||
43 | { 0x13, KEY_MUTE }, /* mute/unmute */ | ||
44 | { 0x10, KEY_TEXT }, /* min */ | ||
45 | |||
46 | { 0x0d, KEY_STOP }, /* freeze */ | ||
47 | { 0x0e, KEY_RECORD }, /* record */ | ||
48 | { 0x1d, KEY_PLAYPAUSE }, /* stop */ | ||
49 | { 0x19, KEY_PLAY }, /* play */ | ||
50 | |||
51 | { 0x16, KEY_GOTO }, /* osd */ | ||
52 | { 0x14, KEY_REFRESH }, /* default */ | ||
53 | { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ | ||
54 | { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ | ||
55 | }; | ||
56 | |||
57 | static struct rc_keymap apac_viewcomp_map = { | ||
58 | .map = { | ||
59 | .scan = apac_viewcomp, | ||
60 | .size = ARRAY_SIZE(apac_viewcomp), | ||
61 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
62 | .name = RC_MAP_APAC_VIEWCOMP, | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | static int __init init_rc_map_apac_viewcomp(void) | ||
67 | { | ||
68 | return ir_register_map(&apac_viewcomp_map); | ||
69 | } | ||
70 | |||
71 | static void __exit exit_rc_map_apac_viewcomp(void) | ||
72 | { | ||
73 | ir_unregister_map(&apac_viewcomp_map); | ||
74 | } | ||
75 | |||
76 | module_init(init_rc_map_apac_viewcomp) | ||
77 | module_exit(exit_rc_map_apac_viewcomp) | ||
78 | |||
79 | MODULE_LICENSE("GPL"); | ||
80 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-asus-pc39.c b/drivers/media/IR/keymaps/rc-asus-pc39.c new file mode 100644 index 000000000000..2aa068cd6c75 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-asus-pc39.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* asus-pc39.h - Keytable for asus_pc39 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Marc Fargas <telenieko@telenieko.com> | ||
17 | * this is the remote control that comes with the asus p7131 | ||
18 | * which has a label saying is "Model PC-39" | ||
19 | */ | ||
20 | |||
21 | static struct ir_scancode asus_pc39[] = { | ||
22 | /* Keys 0 to 9 */ | ||
23 | { 0x15, KEY_0 }, | ||
24 | { 0x29, KEY_1 }, | ||
25 | { 0x2d, KEY_2 }, | ||
26 | { 0x2b, KEY_3 }, | ||
27 | { 0x09, KEY_4 }, | ||
28 | { 0x0d, KEY_5 }, | ||
29 | { 0x0b, KEY_6 }, | ||
30 | { 0x31, KEY_7 }, | ||
31 | { 0x35, KEY_8 }, | ||
32 | { 0x33, KEY_9 }, | ||
33 | |||
34 | { 0x3e, KEY_RADIO }, /* radio */ | ||
35 | { 0x03, KEY_MENU }, /* dvd/menu */ | ||
36 | { 0x2a, KEY_VOLUMEUP }, | ||
37 | { 0x19, KEY_VOLUMEDOWN }, | ||
38 | { 0x37, KEY_UP }, | ||
39 | { 0x3b, KEY_DOWN }, | ||
40 | { 0x27, KEY_LEFT }, | ||
41 | { 0x2f, KEY_RIGHT }, | ||
42 | { 0x25, KEY_VIDEO }, /* video */ | ||
43 | { 0x39, KEY_AUDIO }, /* music */ | ||
44 | |||
45 | { 0x21, KEY_TV }, /* tv */ | ||
46 | { 0x1d, KEY_EXIT }, /* back */ | ||
47 | { 0x0a, KEY_CHANNELUP }, /* channel / program + */ | ||
48 | { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ | ||
49 | { 0x1a, KEY_ENTER }, /* enter */ | ||
50 | |||
51 | { 0x06, KEY_PAUSE }, /* play/pause */ | ||
52 | { 0x1e, KEY_PREVIOUS }, /* rew */ | ||
53 | { 0x26, KEY_NEXT }, /* forward */ | ||
54 | { 0x0e, KEY_REWIND }, /* backward << */ | ||
55 | { 0x3a, KEY_FASTFORWARD }, /* forward >> */ | ||
56 | { 0x36, KEY_STOP }, | ||
57 | { 0x2e, KEY_RECORD }, /* recording */ | ||
58 | { 0x16, KEY_POWER }, /* the button that reads "close" */ | ||
59 | |||
60 | { 0x11, KEY_ZOOM }, /* full screen */ | ||
61 | { 0x13, KEY_MACRO }, /* recall */ | ||
62 | { 0x23, KEY_HOME }, /* home */ | ||
63 | { 0x05, KEY_PVR }, /* picture */ | ||
64 | { 0x3d, KEY_MUTE }, /* mute */ | ||
65 | { 0x01, KEY_DVD }, /* dvd */ | ||
66 | }; | ||
67 | |||
68 | static struct rc_keymap asus_pc39_map = { | ||
69 | .map = { | ||
70 | .scan = asus_pc39, | ||
71 | .size = ARRAY_SIZE(asus_pc39), | ||
72 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
73 | .name = RC_MAP_ASUS_PC39, | ||
74 | } | ||
75 | }; | ||
76 | |||
77 | static int __init init_rc_map_asus_pc39(void) | ||
78 | { | ||
79 | return ir_register_map(&asus_pc39_map); | ||
80 | } | ||
81 | |||
82 | static void __exit exit_rc_map_asus_pc39(void) | ||
83 | { | ||
84 | ir_unregister_map(&asus_pc39_map); | ||
85 | } | ||
86 | |||
87 | module_init(init_rc_map_asus_pc39) | ||
88 | module_exit(exit_rc_map_asus_pc39) | ||
89 | |||
90 | MODULE_LICENSE("GPL"); | ||
91 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c new file mode 100644 index 000000000000..8edfd293d010 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* ATI TV Wonder HD 600 USB | ||
16 | Devin Heitmueller <devin.heitmueller@gmail.com> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode ati_tv_wonder_hd_600[] = { | ||
20 | { 0x00, KEY_RECORD}, /* Row 1 */ | ||
21 | { 0x01, KEY_PLAYPAUSE}, | ||
22 | { 0x02, KEY_STOP}, | ||
23 | { 0x03, KEY_POWER}, | ||
24 | { 0x04, KEY_PREVIOUS}, /* Row 2 */ | ||
25 | { 0x05, KEY_REWIND}, | ||
26 | { 0x06, KEY_FORWARD}, | ||
27 | { 0x07, KEY_NEXT}, | ||
28 | { 0x08, KEY_EPG}, /* Row 3 */ | ||
29 | { 0x09, KEY_HOME}, | ||
30 | { 0x0a, KEY_MENU}, | ||
31 | { 0x0b, KEY_CHANNELUP}, | ||
32 | { 0x0c, KEY_BACK}, /* Row 4 */ | ||
33 | { 0x0d, KEY_UP}, | ||
34 | { 0x0e, KEY_INFO}, | ||
35 | { 0x0f, KEY_CHANNELDOWN}, | ||
36 | { 0x10, KEY_LEFT}, /* Row 5 */ | ||
37 | { 0x11, KEY_SELECT}, | ||
38 | { 0x12, KEY_RIGHT}, | ||
39 | { 0x13, KEY_VOLUMEUP}, | ||
40 | { 0x14, KEY_LAST}, /* Row 6 */ | ||
41 | { 0x15, KEY_DOWN}, | ||
42 | { 0x16, KEY_MUTE}, | ||
43 | { 0x17, KEY_VOLUMEDOWN}, | ||
44 | }; | ||
45 | |||
46 | static struct rc_keymap ati_tv_wonder_hd_600_map = { | ||
47 | .map = { | ||
48 | .scan = ati_tv_wonder_hd_600, | ||
49 | .size = ARRAY_SIZE(ati_tv_wonder_hd_600), | ||
50 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
51 | .name = RC_MAP_ATI_TV_WONDER_HD_600, | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | static int __init init_rc_map_ati_tv_wonder_hd_600(void) | ||
56 | { | ||
57 | return ir_register_map(&ati_tv_wonder_hd_600_map); | ||
58 | } | ||
59 | |||
60 | static void __exit exit_rc_map_ati_tv_wonder_hd_600(void) | ||
61 | { | ||
62 | ir_unregister_map(&ati_tv_wonder_hd_600_map); | ||
63 | } | ||
64 | |||
65 | module_init(init_rc_map_ati_tv_wonder_hd_600) | ||
66 | module_exit(exit_rc_map_ati_tv_wonder_hd_600) | ||
67 | |||
68 | MODULE_LICENSE("GPL"); | ||
69 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avermedia-a16d.c b/drivers/media/IR/keymaps/rc-avermedia-a16d.c new file mode 100644 index 000000000000..12f043587f2e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-a16d.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode avermedia_a16d[] = { | ||
16 | { 0x20, KEY_LIST}, | ||
17 | { 0x00, KEY_POWER}, | ||
18 | { 0x28, KEY_1}, | ||
19 | { 0x18, KEY_2}, | ||
20 | { 0x38, KEY_3}, | ||
21 | { 0x24, KEY_4}, | ||
22 | { 0x14, KEY_5}, | ||
23 | { 0x34, KEY_6}, | ||
24 | { 0x2c, KEY_7}, | ||
25 | { 0x1c, KEY_8}, | ||
26 | { 0x3c, KEY_9}, | ||
27 | { 0x12, KEY_SUBTITLE}, | ||
28 | { 0x22, KEY_0}, | ||
29 | { 0x32, KEY_REWIND}, | ||
30 | { 0x3a, KEY_SHUFFLE}, | ||
31 | { 0x02, KEY_PRINT}, | ||
32 | { 0x11, KEY_CHANNELDOWN}, | ||
33 | { 0x31, KEY_CHANNELUP}, | ||
34 | { 0x0c, KEY_ZOOM}, | ||
35 | { 0x1e, KEY_VOLUMEDOWN}, | ||
36 | { 0x3e, KEY_VOLUMEUP}, | ||
37 | { 0x0a, KEY_MUTE}, | ||
38 | { 0x04, KEY_AUDIO}, | ||
39 | { 0x26, KEY_RECORD}, | ||
40 | { 0x06, KEY_PLAY}, | ||
41 | { 0x36, KEY_STOP}, | ||
42 | { 0x16, KEY_PAUSE}, | ||
43 | { 0x2e, KEY_REWIND}, | ||
44 | { 0x0e, KEY_FASTFORWARD}, | ||
45 | { 0x30, KEY_TEXT}, | ||
46 | { 0x21, KEY_GREEN}, | ||
47 | { 0x01, KEY_BLUE}, | ||
48 | { 0x08, KEY_EPG}, | ||
49 | { 0x2a, KEY_MENU}, | ||
50 | }; | ||
51 | |||
52 | static struct rc_keymap avermedia_a16d_map = { | ||
53 | .map = { | ||
54 | .scan = avermedia_a16d, | ||
55 | .size = ARRAY_SIZE(avermedia_a16d), | ||
56 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
57 | .name = RC_MAP_AVERMEDIA_A16D, | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | static int __init init_rc_map_avermedia_a16d(void) | ||
62 | { | ||
63 | return ir_register_map(&avermedia_a16d_map); | ||
64 | } | ||
65 | |||
66 | static void __exit exit_rc_map_avermedia_a16d(void) | ||
67 | { | ||
68 | ir_unregister_map(&avermedia_a16d_map); | ||
69 | } | ||
70 | |||
71 | module_init(init_rc_map_avermedia_a16d) | ||
72 | module_exit(exit_rc_map_avermedia_a16d) | ||
73 | |||
74 | MODULE_LICENSE("GPL"); | ||
75 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c new file mode 100644 index 000000000000..2a945b02e8ca --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Oldrich Jedlicka <oldium.pro@seznam.cz> */ | ||
16 | |||
17 | static struct ir_scancode avermedia_cardbus[] = { | ||
18 | { 0x00, KEY_POWER }, | ||
19 | { 0x01, KEY_TUNER }, /* TV/FM */ | ||
20 | { 0x03, KEY_TEXT }, /* Teletext */ | ||
21 | { 0x04, KEY_EPG }, | ||
22 | { 0x05, KEY_1 }, | ||
23 | { 0x06, KEY_2 }, | ||
24 | { 0x07, KEY_3 }, | ||
25 | { 0x08, KEY_AUDIO }, | ||
26 | { 0x09, KEY_4 }, | ||
27 | { 0x0a, KEY_5 }, | ||
28 | { 0x0b, KEY_6 }, | ||
29 | { 0x0c, KEY_ZOOM }, /* Full screen */ | ||
30 | { 0x0d, KEY_7 }, | ||
31 | { 0x0e, KEY_8 }, | ||
32 | { 0x0f, KEY_9 }, | ||
33 | { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ | ||
34 | { 0x11, KEY_0 }, | ||
35 | { 0x12, KEY_INFO }, | ||
36 | { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ | ||
37 | { 0x14, KEY_MUTE }, | ||
38 | { 0x15, KEY_EDIT }, /* Autoscan */ | ||
39 | { 0x17, KEY_SAVE }, /* Screenshot */ | ||
40 | { 0x18, KEY_PLAYPAUSE }, | ||
41 | { 0x19, KEY_RECORD }, | ||
42 | { 0x1a, KEY_PLAY }, | ||
43 | { 0x1b, KEY_STOP }, | ||
44 | { 0x1c, KEY_FASTFORWARD }, | ||
45 | { 0x1d, KEY_REWIND }, | ||
46 | { 0x1e, KEY_VOLUMEDOWN }, | ||
47 | { 0x1f, KEY_VOLUMEUP }, | ||
48 | { 0x22, KEY_SLEEP }, /* Sleep */ | ||
49 | { 0x23, KEY_ZOOM }, /* Aspect */ | ||
50 | { 0x26, KEY_SCREEN }, /* Pos */ | ||
51 | { 0x27, KEY_ANGLE }, /* Size */ | ||
52 | { 0x28, KEY_SELECT }, /* Select */ | ||
53 | { 0x29, KEY_BLUE }, /* Blue/Picture */ | ||
54 | { 0x2a, KEY_BACKSPACE }, /* Back */ | ||
55 | { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ | ||
56 | { 0x2c, KEY_DOWN }, | ||
57 | { 0x2e, KEY_DOT }, | ||
58 | { 0x2f, KEY_TV }, /* Live TV */ | ||
59 | { 0x32, KEY_LEFT }, | ||
60 | { 0x33, KEY_CLEAR }, /* Clear */ | ||
61 | { 0x35, KEY_RED }, /* Red/TV */ | ||
62 | { 0x36, KEY_UP }, | ||
63 | { 0x37, KEY_HOME }, /* Home */ | ||
64 | { 0x39, KEY_GREEN }, /* Green/Video */ | ||
65 | { 0x3d, KEY_YELLOW }, /* Yellow/Music */ | ||
66 | { 0x3e, KEY_OK }, /* Ok */ | ||
67 | { 0x3f, KEY_RIGHT }, | ||
68 | { 0x40, KEY_NEXT }, /* Next */ | ||
69 | { 0x41, KEY_PREVIOUS }, /* Previous */ | ||
70 | { 0x42, KEY_CHANNELDOWN }, /* Channel down */ | ||
71 | { 0x43, KEY_CHANNELUP }, /* Channel up */ | ||
72 | }; | ||
73 | |||
74 | static struct rc_keymap avermedia_cardbus_map = { | ||
75 | .map = { | ||
76 | .scan = avermedia_cardbus, | ||
77 | .size = ARRAY_SIZE(avermedia_cardbus), | ||
78 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
79 | .name = RC_MAP_AVERMEDIA_CARDBUS, | ||
80 | } | ||
81 | }; | ||
82 | |||
83 | static int __init init_rc_map_avermedia_cardbus(void) | ||
84 | { | ||
85 | return ir_register_map(&avermedia_cardbus_map); | ||
86 | } | ||
87 | |||
88 | static void __exit exit_rc_map_avermedia_cardbus(void) | ||
89 | { | ||
90 | ir_unregister_map(&avermedia_cardbus_map); | ||
91 | } | ||
92 | |||
93 | module_init(init_rc_map_avermedia_cardbus) | ||
94 | module_exit(exit_rc_map_avermedia_cardbus) | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||
97 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c new file mode 100644 index 000000000000..39dde6222875 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Matt Jesson <dvb@jesson.eclipse.co.uk */ | ||
16 | |||
17 | static struct ir_scancode avermedia_dvbt[] = { | ||
18 | { 0x28, KEY_0 }, /* '0' / 'enter' */ | ||
19 | { 0x22, KEY_1 }, /* '1' */ | ||
20 | { 0x12, KEY_2 }, /* '2' / 'up arrow' */ | ||
21 | { 0x32, KEY_3 }, /* '3' */ | ||
22 | { 0x24, KEY_4 }, /* '4' / 'left arrow' */ | ||
23 | { 0x14, KEY_5 }, /* '5' */ | ||
24 | { 0x34, KEY_6 }, /* '6' / 'right arrow' */ | ||
25 | { 0x26, KEY_7 }, /* '7' */ | ||
26 | { 0x16, KEY_8 }, /* '8' / 'down arrow' */ | ||
27 | { 0x36, KEY_9 }, /* '9' */ | ||
28 | |||
29 | { 0x20, KEY_LIST }, /* 'source' */ | ||
30 | { 0x10, KEY_TEXT }, /* 'teletext' */ | ||
31 | { 0x00, KEY_POWER }, /* 'power' */ | ||
32 | { 0x04, KEY_AUDIO }, /* 'audio' */ | ||
33 | { 0x06, KEY_ZOOM }, /* 'full screen' */ | ||
34 | { 0x18, KEY_VIDEO }, /* 'display' */ | ||
35 | { 0x38, KEY_SEARCH }, /* 'loop' */ | ||
36 | { 0x08, KEY_INFO }, /* 'preview' */ | ||
37 | { 0x2a, KEY_REWIND }, /* 'backward <<' */ | ||
38 | { 0x1a, KEY_FASTFORWARD }, /* 'forward >>' */ | ||
39 | { 0x3a, KEY_RECORD }, /* 'capture' */ | ||
40 | { 0x0a, KEY_MUTE }, /* 'mute' */ | ||
41 | { 0x2c, KEY_RECORD }, /* 'record' */ | ||
42 | { 0x1c, KEY_PAUSE }, /* 'pause' */ | ||
43 | { 0x3c, KEY_STOP }, /* 'stop' */ | ||
44 | { 0x0c, KEY_PLAY }, /* 'play' */ | ||
45 | { 0x2e, KEY_RED }, /* 'red' */ | ||
46 | { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ | ||
47 | { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ | ||
48 | { 0x21, KEY_GREEN }, /* 'green' */ | ||
49 | { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ | ||
50 | { 0x31, KEY_CHANNELUP }, /* 'channel +' */ | ||
51 | { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ | ||
52 | { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ | ||
53 | }; | ||
54 | |||
55 | static struct rc_keymap avermedia_dvbt_map = { | ||
56 | .map = { | ||
57 | .scan = avermedia_dvbt, | ||
58 | .size = ARRAY_SIZE(avermedia_dvbt), | ||
59 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
60 | .name = RC_MAP_AVERMEDIA_DVBT, | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | static int __init init_rc_map_avermedia_dvbt(void) | ||
65 | { | ||
66 | return ir_register_map(&avermedia_dvbt_map); | ||
67 | } | ||
68 | |||
69 | static void __exit exit_rc_map_avermedia_dvbt(void) | ||
70 | { | ||
71 | ir_unregister_map(&avermedia_dvbt_map); | ||
72 | } | ||
73 | |||
74 | module_init(init_rc_map_avermedia_dvbt) | ||
75 | module_exit(exit_rc_map_avermedia_dvbt) | ||
76 | |||
77 | MODULE_LICENSE("GPL"); | ||
78 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c new file mode 100644 index 000000000000..101e7ea85941 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Avermedia M135A with IR model RM-JX | ||
17 | * The same codes exist on both Positivo (BR) and original IR | ||
18 | * Mauro Carvalho Chehab <mchehab@infradead.org> | ||
19 | */ | ||
20 | |||
21 | static struct ir_scancode avermedia_m135a_rm_jx[] = { | ||
22 | { 0x0200, KEY_POWER2 }, | ||
23 | { 0x022e, KEY_DOT }, /* '.' */ | ||
24 | { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ | ||
25 | |||
26 | { 0x0205, KEY_1 }, | ||
27 | { 0x0206, KEY_2 }, | ||
28 | { 0x0207, KEY_3 }, | ||
29 | { 0x0209, KEY_4 }, | ||
30 | { 0x020a, KEY_5 }, | ||
31 | { 0x020b, KEY_6 }, | ||
32 | { 0x020d, KEY_7 }, | ||
33 | { 0x020e, KEY_8 }, | ||
34 | { 0x020f, KEY_9 }, | ||
35 | { 0x0211, KEY_0 }, | ||
36 | |||
37 | { 0x0213, KEY_RIGHT }, /* -> or L */ | ||
38 | { 0x0212, KEY_LEFT }, /* <- or R */ | ||
39 | |||
40 | { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ | ||
41 | { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ | ||
42 | |||
43 | { 0x0303, KEY_CHANNELUP }, | ||
44 | { 0x0302, KEY_CHANNELDOWN }, | ||
45 | { 0x021f, KEY_VOLUMEUP }, | ||
46 | { 0x021e, KEY_VOLUMEDOWN }, | ||
47 | { 0x020c, KEY_ENTER }, /* Full Screen */ | ||
48 | |||
49 | { 0x0214, KEY_MUTE }, | ||
50 | { 0x0208, KEY_AUDIO }, | ||
51 | |||
52 | { 0x0203, KEY_TEXT }, /* Teletext */ | ||
53 | { 0x0204, KEY_EPG }, | ||
54 | { 0x022b, KEY_TV2 }, /* TV2 or PIP */ | ||
55 | |||
56 | { 0x021d, KEY_RED }, | ||
57 | { 0x021c, KEY_YELLOW }, | ||
58 | { 0x0301, KEY_GREEN }, | ||
59 | { 0x0300, KEY_BLUE }, | ||
60 | |||
61 | { 0x021a, KEY_PLAYPAUSE }, | ||
62 | { 0x0219, KEY_RECORD }, | ||
63 | { 0x0218, KEY_PLAY }, | ||
64 | { 0x021b, KEY_STOP }, | ||
65 | }; | ||
66 | |||
67 | static struct rc_keymap avermedia_m135a_rm_jx_map = { | ||
68 | .map = { | ||
69 | .scan = avermedia_m135a_rm_jx, | ||
70 | .size = ARRAY_SIZE(avermedia_m135a_rm_jx), | ||
71 | .ir_type = IR_TYPE_NEC, | ||
72 | .name = RC_MAP_AVERMEDIA_M135A_RM_JX, | ||
73 | } | ||
74 | }; | ||
75 | |||
76 | static int __init init_rc_map_avermedia_m135a_rm_jx(void) | ||
77 | { | ||
78 | return ir_register_map(&avermedia_m135a_rm_jx_map); | ||
79 | } | ||
80 | |||
81 | static void __exit exit_rc_map_avermedia_m135a_rm_jx(void) | ||
82 | { | ||
83 | ir_unregister_map(&avermedia_m135a_rm_jx_map); | ||
84 | } | ||
85 | |||
86 | module_init(init_rc_map_avermedia_m135a_rm_jx) | ||
87 | module_exit(exit_rc_map_avermedia_m135a_rm_jx) | ||
88 | |||
89 | MODULE_LICENSE("GPL"); | ||
90 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avermedia.c b/drivers/media/IR/keymaps/rc-avermedia.c new file mode 100644 index 000000000000..21effd5bfb0d --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* avermedia.h - Keytable for avermedia Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Alex Hermann <gaaf@gmx.net> */ | ||
16 | |||
17 | static struct ir_scancode avermedia[] = { | ||
18 | { 0x28, KEY_1 }, | ||
19 | { 0x18, KEY_2 }, | ||
20 | { 0x38, KEY_3 }, | ||
21 | { 0x24, KEY_4 }, | ||
22 | { 0x14, KEY_5 }, | ||
23 | { 0x34, KEY_6 }, | ||
24 | { 0x2c, KEY_7 }, | ||
25 | { 0x1c, KEY_8 }, | ||
26 | { 0x3c, KEY_9 }, | ||
27 | { 0x22, KEY_0 }, | ||
28 | |||
29 | { 0x20, KEY_TV }, /* TV/FM */ | ||
30 | { 0x10, KEY_CD }, /* CD */ | ||
31 | { 0x30, KEY_TEXT }, /* TELETEXT */ | ||
32 | { 0x00, KEY_POWER }, /* POWER */ | ||
33 | |||
34 | { 0x08, KEY_VIDEO }, /* VIDEO */ | ||
35 | { 0x04, KEY_AUDIO }, /* AUDIO */ | ||
36 | { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ | ||
37 | |||
38 | { 0x12, KEY_SUBTITLE }, /* DISPLAY */ | ||
39 | { 0x32, KEY_REWIND }, /* LOOP */ | ||
40 | { 0x02, KEY_PRINT }, /* PREVIEW */ | ||
41 | |||
42 | { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ | ||
43 | { 0x1a, KEY_SLEEP }, /* FREEZE */ | ||
44 | { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ | ||
45 | { 0x0a, KEY_MUTE }, /* MUTE */ | ||
46 | |||
47 | { 0x26, KEY_RECORD }, /* RECORD */ | ||
48 | { 0x16, KEY_PAUSE }, /* PAUSE */ | ||
49 | { 0x36, KEY_STOP }, /* STOP */ | ||
50 | { 0x06, KEY_PLAY }, /* PLAY */ | ||
51 | |||
52 | { 0x2e, KEY_RED }, /* RED */ | ||
53 | { 0x21, KEY_GREEN }, /* GREEN */ | ||
54 | { 0x0e, KEY_YELLOW }, /* YELLOW */ | ||
55 | { 0x01, KEY_BLUE }, /* BLUE */ | ||
56 | |||
57 | { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ | ||
58 | { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ | ||
59 | { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ | ||
60 | { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ | ||
61 | }; | ||
62 | |||
63 | static struct rc_keymap avermedia_map = { | ||
64 | .map = { | ||
65 | .scan = avermedia, | ||
66 | .size = ARRAY_SIZE(avermedia), | ||
67 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
68 | .name = RC_MAP_AVERMEDIA, | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | static int __init init_rc_map_avermedia(void) | ||
73 | { | ||
74 | return ir_register_map(&avermedia_map); | ||
75 | } | ||
76 | |||
77 | static void __exit exit_rc_map_avermedia(void) | ||
78 | { | ||
79 | ir_unregister_map(&avermedia_map); | ||
80 | } | ||
81 | |||
82 | module_init(init_rc_map_avermedia) | ||
83 | module_exit(exit_rc_map_avermedia) | ||
84 | |||
85 | MODULE_LICENSE("GPL"); | ||
86 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-avertv-303.c b/drivers/media/IR/keymaps/rc-avertv-303.c new file mode 100644 index 000000000000..971c59d6f9d6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avertv-303.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* avertv-303.h - Keytable for avertv_303 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* AVERTV STUDIO 303 Remote */ | ||
16 | |||
17 | static struct ir_scancode avertv_303[] = { | ||
18 | { 0x2a, KEY_1 }, | ||
19 | { 0x32, KEY_2 }, | ||
20 | { 0x3a, KEY_3 }, | ||
21 | { 0x4a, KEY_4 }, | ||
22 | { 0x52, KEY_5 }, | ||
23 | { 0x5a, KEY_6 }, | ||
24 | { 0x6a, KEY_7 }, | ||
25 | { 0x72, KEY_8 }, | ||
26 | { 0x7a, KEY_9 }, | ||
27 | { 0x0e, KEY_0 }, | ||
28 | |||
29 | { 0x02, KEY_POWER }, | ||
30 | { 0x22, KEY_VIDEO }, | ||
31 | { 0x42, KEY_AUDIO }, | ||
32 | { 0x62, KEY_ZOOM }, | ||
33 | { 0x0a, KEY_TV }, | ||
34 | { 0x12, KEY_CD }, | ||
35 | { 0x1a, KEY_TEXT }, | ||
36 | |||
37 | { 0x16, KEY_SUBTITLE }, | ||
38 | { 0x1e, KEY_REWIND }, | ||
39 | { 0x06, KEY_PRINT }, | ||
40 | |||
41 | { 0x2e, KEY_SEARCH }, | ||
42 | { 0x36, KEY_SLEEP }, | ||
43 | { 0x3e, KEY_SHUFFLE }, | ||
44 | { 0x26, KEY_MUTE }, | ||
45 | |||
46 | { 0x4e, KEY_RECORD }, | ||
47 | { 0x56, KEY_PAUSE }, | ||
48 | { 0x5e, KEY_STOP }, | ||
49 | { 0x46, KEY_PLAY }, | ||
50 | |||
51 | { 0x6e, KEY_RED }, | ||
52 | { 0x0b, KEY_GREEN }, | ||
53 | { 0x66, KEY_YELLOW }, | ||
54 | { 0x03, KEY_BLUE }, | ||
55 | |||
56 | { 0x76, KEY_LEFT }, | ||
57 | { 0x7e, KEY_RIGHT }, | ||
58 | { 0x13, KEY_DOWN }, | ||
59 | { 0x1b, KEY_UP }, | ||
60 | }; | ||
61 | |||
62 | static struct rc_keymap avertv_303_map = { | ||
63 | .map = { | ||
64 | .scan = avertv_303, | ||
65 | .size = ARRAY_SIZE(avertv_303), | ||
66 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
67 | .name = RC_MAP_AVERTV_303, | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | static int __init init_rc_map_avertv_303(void) | ||
72 | { | ||
73 | return ir_register_map(&avertv_303_map); | ||
74 | } | ||
75 | |||
76 | static void __exit exit_rc_map_avertv_303(void) | ||
77 | { | ||
78 | ir_unregister_map(&avertv_303_map); | ||
79 | } | ||
80 | |||
81 | module_init(init_rc_map_avertv_303) | ||
82 | module_exit(exit_rc_map_avertv_303) | ||
83 | |||
84 | MODULE_LICENSE("GPL"); | ||
85 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-behold-columbus.c b/drivers/media/IR/keymaps/rc-behold-columbus.c new file mode 100644 index 000000000000..9f56c98fef5b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-behold-columbus.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* behold-columbus.h - Keytable for behold_columbus Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Beholder Intl. Ltd. 2008 | ||
16 | * Dmitry Belimov d.belimov@google.com | ||
17 | * Keytable is used by BeholdTV Columbus | ||
18 | * The "ascii-art picture" below (in comments, first row | ||
19 | * is the keycode in hex, and subsequent row(s) shows | ||
20 | * the button labels (several variants when appropriate) | ||
21 | * helps to descide which keycodes to assign to the buttons. | ||
22 | */ | ||
23 | |||
24 | static struct ir_scancode behold_columbus[] = { | ||
25 | |||
26 | /* 0x13 0x11 0x1C 0x12 * | ||
27 | * Mute Source TV/FM Power * | ||
28 | * */ | ||
29 | |||
30 | { 0x13, KEY_MUTE }, | ||
31 | { 0x11, KEY_PROPS }, | ||
32 | { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ | ||
33 | { 0x12, KEY_POWER }, | ||
34 | |||
35 | /* 0x01 0x02 0x03 0x0D * | ||
36 | * 1 2 3 Stereo * | ||
37 | * * | ||
38 | * 0x04 0x05 0x06 0x19 * | ||
39 | * 4 5 6 Snapshot * | ||
40 | * * | ||
41 | * 0x07 0x08 0x09 0x10 * | ||
42 | * 7 8 9 Zoom * | ||
43 | * */ | ||
44 | { 0x01, KEY_1 }, | ||
45 | { 0x02, KEY_2 }, | ||
46 | { 0x03, KEY_3 }, | ||
47 | { 0x0D, KEY_SETUP }, /* Setup key */ | ||
48 | { 0x04, KEY_4 }, | ||
49 | { 0x05, KEY_5 }, | ||
50 | { 0x06, KEY_6 }, | ||
51 | { 0x19, KEY_CAMERA }, /* Snapshot key */ | ||
52 | { 0x07, KEY_7 }, | ||
53 | { 0x08, KEY_8 }, | ||
54 | { 0x09, KEY_9 }, | ||
55 | { 0x10, KEY_ZOOM }, | ||
56 | |||
57 | /* 0x0A 0x00 0x0B 0x0C * | ||
58 | * RECALL 0 ChannelUp VolumeUp * | ||
59 | * */ | ||
60 | { 0x0A, KEY_AGAIN }, | ||
61 | { 0x00, KEY_0 }, | ||
62 | { 0x0B, KEY_CHANNELUP }, | ||
63 | { 0x0C, KEY_VOLUMEUP }, | ||
64 | |||
65 | /* 0x1B 0x1D 0x15 0x18 * | ||
66 | * Timeshift Record ChannelDown VolumeDown * | ||
67 | * */ | ||
68 | |||
69 | { 0x1B, KEY_TIME }, | ||
70 | { 0x1D, KEY_RECORD }, | ||
71 | { 0x15, KEY_CHANNELDOWN }, | ||
72 | { 0x18, KEY_VOLUMEDOWN }, | ||
73 | |||
74 | /* 0x0E 0x1E 0x0F 0x1A * | ||
75 | * Stop Pause Previouse Next * | ||
76 | * */ | ||
77 | |||
78 | { 0x0E, KEY_STOP }, | ||
79 | { 0x1E, KEY_PAUSE }, | ||
80 | { 0x0F, KEY_PREVIOUS }, | ||
81 | { 0x1A, KEY_NEXT }, | ||
82 | |||
83 | }; | ||
84 | |||
85 | static struct rc_keymap behold_columbus_map = { | ||
86 | .map = { | ||
87 | .scan = behold_columbus, | ||
88 | .size = ARRAY_SIZE(behold_columbus), | ||
89 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
90 | .name = RC_MAP_BEHOLD_COLUMBUS, | ||
91 | } | ||
92 | }; | ||
93 | |||
94 | static int __init init_rc_map_behold_columbus(void) | ||
95 | { | ||
96 | return ir_register_map(&behold_columbus_map); | ||
97 | } | ||
98 | |||
99 | static void __exit exit_rc_map_behold_columbus(void) | ||
100 | { | ||
101 | ir_unregister_map(&behold_columbus_map); | ||
102 | } | ||
103 | |||
104 | module_init(init_rc_map_behold_columbus) | ||
105 | module_exit(exit_rc_map_behold_columbus) | ||
106 | |||
107 | MODULE_LICENSE("GPL"); | ||
108 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-behold.c b/drivers/media/IR/keymaps/rc-behold.c new file mode 100644 index 000000000000..abc140b2098b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-behold.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /* behold.h - Keytable for behold Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Igor Kuznetsov <igk72@ya.ru> | ||
17 | * Andrey J. Melnikov <temnota@kmv.ru> | ||
18 | * | ||
19 | * Keytable is used by BeholdTV 60x series, M6 series at | ||
20 | * least, and probably other cards too. | ||
21 | * The "ascii-art picture" below (in comments, first row | ||
22 | * is the keycode in hex, and subsequent row(s) shows | ||
23 | * the button labels (several variants when appropriate) | ||
24 | * helps to descide which keycodes to assign to the buttons. | ||
25 | */ | ||
26 | |||
27 | static struct ir_scancode behold[] = { | ||
28 | |||
29 | /* 0x1c 0x12 * | ||
30 | * TV/FM POWER * | ||
31 | * */ | ||
32 | { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ | ||
33 | { 0x12, KEY_POWER }, | ||
34 | |||
35 | /* 0x01 0x02 0x03 * | ||
36 | * 1 2 3 * | ||
37 | * * | ||
38 | * 0x04 0x05 0x06 * | ||
39 | * 4 5 6 * | ||
40 | * * | ||
41 | * 0x07 0x08 0x09 * | ||
42 | * 7 8 9 * | ||
43 | * */ | ||
44 | { 0x01, KEY_1 }, | ||
45 | { 0x02, KEY_2 }, | ||
46 | { 0x03, KEY_3 }, | ||
47 | { 0x04, KEY_4 }, | ||
48 | { 0x05, KEY_5 }, | ||
49 | { 0x06, KEY_6 }, | ||
50 | { 0x07, KEY_7 }, | ||
51 | { 0x08, KEY_8 }, | ||
52 | { 0x09, KEY_9 }, | ||
53 | |||
54 | /* 0x0a 0x00 0x17 * | ||
55 | * RECALL 0 MODE * | ||
56 | * */ | ||
57 | { 0x0a, KEY_AGAIN }, | ||
58 | { 0x00, KEY_0 }, | ||
59 | { 0x17, KEY_MODE }, | ||
60 | |||
61 | /* 0x14 0x10 * | ||
62 | * ASPECT FULLSCREEN * | ||
63 | * */ | ||
64 | { 0x14, KEY_SCREEN }, | ||
65 | { 0x10, KEY_ZOOM }, | ||
66 | |||
67 | /* 0x0b * | ||
68 | * Up * | ||
69 | * * | ||
70 | * 0x18 0x16 0x0c * | ||
71 | * Left Ok Right * | ||
72 | * * | ||
73 | * 0x015 * | ||
74 | * Down * | ||
75 | * */ | ||
76 | { 0x0b, KEY_CHANNELUP }, | ||
77 | { 0x18, KEY_VOLUMEDOWN }, | ||
78 | { 0x16, KEY_OK }, /* XXX KEY_ENTER */ | ||
79 | { 0x0c, KEY_VOLUMEUP }, | ||
80 | { 0x15, KEY_CHANNELDOWN }, | ||
81 | |||
82 | /* 0x11 0x0d * | ||
83 | * MUTE INFO * | ||
84 | * */ | ||
85 | { 0x11, KEY_MUTE }, | ||
86 | { 0x0d, KEY_INFO }, | ||
87 | |||
88 | /* 0x0f 0x1b 0x1a * | ||
89 | * RECORD PLAY/PAUSE STOP * | ||
90 | * * | ||
91 | * 0x0e 0x1f 0x1e * | ||
92 | *TELETEXT AUDIO SOURCE * | ||
93 | * RED YELLOW * | ||
94 | * */ | ||
95 | { 0x0f, KEY_RECORD }, | ||
96 | { 0x1b, KEY_PLAYPAUSE }, | ||
97 | { 0x1a, KEY_STOP }, | ||
98 | { 0x0e, KEY_TEXT }, | ||
99 | { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ | ||
100 | { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ | ||
101 | |||
102 | /* 0x1d 0x13 0x19 * | ||
103 | * SLEEP PREVIEW DVB * | ||
104 | * GREEN BLUE * | ||
105 | * */ | ||
106 | { 0x1d, KEY_SLEEP }, | ||
107 | { 0x13, KEY_GREEN }, | ||
108 | { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ | ||
109 | |||
110 | /* 0x58 0x5c * | ||
111 | * FREEZE SNAPSHOT * | ||
112 | * */ | ||
113 | { 0x58, KEY_SLOW }, | ||
114 | { 0x5c, KEY_CAMERA }, | ||
115 | |||
116 | }; | ||
117 | |||
118 | static struct rc_keymap behold_map = { | ||
119 | .map = { | ||
120 | .scan = behold, | ||
121 | .size = ARRAY_SIZE(behold), | ||
122 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
123 | .name = RC_MAP_BEHOLD, | ||
124 | } | ||
125 | }; | ||
126 | |||
127 | static int __init init_rc_map_behold(void) | ||
128 | { | ||
129 | return ir_register_map(&behold_map); | ||
130 | } | ||
131 | |||
132 | static void __exit exit_rc_map_behold(void) | ||
133 | { | ||
134 | ir_unregister_map(&behold_map); | ||
135 | } | ||
136 | |||
137 | module_init(init_rc_map_behold) | ||
138 | module_exit(exit_rc_map_behold) | ||
139 | |||
140 | MODULE_LICENSE("GPL"); | ||
141 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-budget-ci-old.c b/drivers/media/IR/keymaps/rc-budget-ci-old.c new file mode 100644 index 000000000000..64c2ac913338 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-budget-ci-old.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* budget-ci-old.h - Keytable for budget_ci_old Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* From reading the following remotes: | ||
16 | * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 | ||
17 | * Hauppauge (from NOVA-CI-s box product) | ||
18 | * This is a "middle of the road" approach, differences are noted | ||
19 | */ | ||
20 | |||
21 | static struct ir_scancode budget_ci_old[] = { | ||
22 | { 0x00, KEY_0 }, | ||
23 | { 0x01, KEY_1 }, | ||
24 | { 0x02, KEY_2 }, | ||
25 | { 0x03, KEY_3 }, | ||
26 | { 0x04, KEY_4 }, | ||
27 | { 0x05, KEY_5 }, | ||
28 | { 0x06, KEY_6 }, | ||
29 | { 0x07, KEY_7 }, | ||
30 | { 0x08, KEY_8 }, | ||
31 | { 0x09, KEY_9 }, | ||
32 | { 0x0a, KEY_ENTER }, | ||
33 | { 0x0b, KEY_RED }, | ||
34 | { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ | ||
35 | { 0x0d, KEY_MUTE }, | ||
36 | { 0x0f, KEY_A }, /* TV on Hauppauge */ | ||
37 | { 0x10, KEY_VOLUMEUP }, | ||
38 | { 0x11, KEY_VOLUMEDOWN }, | ||
39 | { 0x14, KEY_B }, | ||
40 | { 0x1c, KEY_UP }, | ||
41 | { 0x1d, KEY_DOWN }, | ||
42 | { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ | ||
43 | { 0x1f, KEY_BREAK }, | ||
44 | { 0x20, KEY_CHANNELUP }, | ||
45 | { 0x21, KEY_CHANNELDOWN }, | ||
46 | { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ | ||
47 | { 0x24, KEY_RESTART }, | ||
48 | { 0x25, KEY_OK }, | ||
49 | { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ | ||
50 | { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ | ||
51 | { 0x29, KEY_PAUSE }, | ||
52 | { 0x2b, KEY_RIGHT }, | ||
53 | { 0x2c, KEY_LEFT }, | ||
54 | { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ | ||
55 | { 0x30, KEY_SLOW }, | ||
56 | { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ | ||
57 | { 0x32, KEY_REWIND }, | ||
58 | { 0x34, KEY_FASTFORWARD }, | ||
59 | { 0x35, KEY_PLAY }, | ||
60 | { 0x36, KEY_STOP }, | ||
61 | { 0x37, KEY_RECORD }, | ||
62 | { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ | ||
63 | { 0x3a, KEY_C }, | ||
64 | { 0x3c, KEY_EXIT }, | ||
65 | { 0x3d, KEY_POWER2 }, | ||
66 | { 0x3e, KEY_TUNER }, | ||
67 | }; | ||
68 | |||
69 | static struct rc_keymap budget_ci_old_map = { | ||
70 | .map = { | ||
71 | .scan = budget_ci_old, | ||
72 | .size = ARRAY_SIZE(budget_ci_old), | ||
73 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
74 | .name = RC_MAP_BUDGET_CI_OLD, | ||
75 | } | ||
76 | }; | ||
77 | |||
78 | static int __init init_rc_map_budget_ci_old(void) | ||
79 | { | ||
80 | return ir_register_map(&budget_ci_old_map); | ||
81 | } | ||
82 | |||
83 | static void __exit exit_rc_map_budget_ci_old(void) | ||
84 | { | ||
85 | ir_unregister_map(&budget_ci_old_map); | ||
86 | } | ||
87 | |||
88 | module_init(init_rc_map_budget_ci_old) | ||
89 | module_exit(exit_rc_map_budget_ci_old) | ||
90 | |||
91 | MODULE_LICENSE("GPL"); | ||
92 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-cinergy-1400.c b/drivers/media/IR/keymaps/rc-cinergy-1400.c new file mode 100644 index 000000000000..074f2c2c2c61 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-cinergy-1400.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Cinergy 1400 DVB-T */ | ||
16 | |||
17 | static struct ir_scancode cinergy_1400[] = { | ||
18 | { 0x01, KEY_POWER }, | ||
19 | { 0x02, KEY_1 }, | ||
20 | { 0x03, KEY_2 }, | ||
21 | { 0x04, KEY_3 }, | ||
22 | { 0x05, KEY_4 }, | ||
23 | { 0x06, KEY_5 }, | ||
24 | { 0x07, KEY_6 }, | ||
25 | { 0x08, KEY_7 }, | ||
26 | { 0x09, KEY_8 }, | ||
27 | { 0x0a, KEY_9 }, | ||
28 | { 0x0c, KEY_0 }, | ||
29 | |||
30 | { 0x0b, KEY_VIDEO }, | ||
31 | { 0x0d, KEY_REFRESH }, | ||
32 | { 0x0e, KEY_SELECT }, | ||
33 | { 0x0f, KEY_EPG }, | ||
34 | { 0x10, KEY_UP }, | ||
35 | { 0x11, KEY_LEFT }, | ||
36 | { 0x12, KEY_OK }, | ||
37 | { 0x13, KEY_RIGHT }, | ||
38 | { 0x14, KEY_DOWN }, | ||
39 | { 0x15, KEY_TEXT }, | ||
40 | { 0x16, KEY_INFO }, | ||
41 | |||
42 | { 0x17, KEY_RED }, | ||
43 | { 0x18, KEY_GREEN }, | ||
44 | { 0x19, KEY_YELLOW }, | ||
45 | { 0x1a, KEY_BLUE }, | ||
46 | |||
47 | { 0x1b, KEY_CHANNELUP }, | ||
48 | { 0x1c, KEY_VOLUMEUP }, | ||
49 | { 0x1d, KEY_MUTE }, | ||
50 | { 0x1e, KEY_VOLUMEDOWN }, | ||
51 | { 0x1f, KEY_CHANNELDOWN }, | ||
52 | |||
53 | { 0x40, KEY_PAUSE }, | ||
54 | { 0x4c, KEY_PLAY }, | ||
55 | { 0x58, KEY_RECORD }, | ||
56 | { 0x54, KEY_PREVIOUS }, | ||
57 | { 0x48, KEY_STOP }, | ||
58 | { 0x5c, KEY_NEXT }, | ||
59 | }; | ||
60 | |||
61 | static struct rc_keymap cinergy_1400_map = { | ||
62 | .map = { | ||
63 | .scan = cinergy_1400, | ||
64 | .size = ARRAY_SIZE(cinergy_1400), | ||
65 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
66 | .name = RC_MAP_CINERGY_1400, | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | static int __init init_rc_map_cinergy_1400(void) | ||
71 | { | ||
72 | return ir_register_map(&cinergy_1400_map); | ||
73 | } | ||
74 | |||
75 | static void __exit exit_rc_map_cinergy_1400(void) | ||
76 | { | ||
77 | ir_unregister_map(&cinergy_1400_map); | ||
78 | } | ||
79 | |||
80 | module_init(init_rc_map_cinergy_1400) | ||
81 | module_exit(exit_rc_map_cinergy_1400) | ||
82 | |||
83 | MODULE_LICENSE("GPL"); | ||
84 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-cinergy.c b/drivers/media/IR/keymaps/rc-cinergy.c new file mode 100644 index 000000000000..cf84c3dba742 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-cinergy.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* cinergy.h - Keytable for cinergy Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode cinergy[] = { | ||
16 | { 0x00, KEY_0 }, | ||
17 | { 0x01, KEY_1 }, | ||
18 | { 0x02, KEY_2 }, | ||
19 | { 0x03, KEY_3 }, | ||
20 | { 0x04, KEY_4 }, | ||
21 | { 0x05, KEY_5 }, | ||
22 | { 0x06, KEY_6 }, | ||
23 | { 0x07, KEY_7 }, | ||
24 | { 0x08, KEY_8 }, | ||
25 | { 0x09, KEY_9 }, | ||
26 | |||
27 | { 0x0a, KEY_POWER }, | ||
28 | { 0x0b, KEY_PROG1 }, /* app */ | ||
29 | { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ | ||
30 | { 0x0d, KEY_CHANNELUP }, /* channel */ | ||
31 | { 0x0e, KEY_CHANNELDOWN }, /* channel- */ | ||
32 | { 0x0f, KEY_VOLUMEUP }, | ||
33 | { 0x10, KEY_VOLUMEDOWN }, | ||
34 | { 0x11, KEY_TUNER }, /* AV */ | ||
35 | { 0x12, KEY_NUMLOCK }, /* -/-- */ | ||
36 | { 0x13, KEY_AUDIO }, /* audio */ | ||
37 | { 0x14, KEY_MUTE }, | ||
38 | { 0x15, KEY_UP }, | ||
39 | { 0x16, KEY_DOWN }, | ||
40 | { 0x17, KEY_LEFT }, | ||
41 | { 0x18, KEY_RIGHT }, | ||
42 | { 0x19, BTN_LEFT, }, | ||
43 | { 0x1a, BTN_RIGHT, }, | ||
44 | { 0x1b, KEY_WWW }, /* text */ | ||
45 | { 0x1c, KEY_REWIND }, | ||
46 | { 0x1d, KEY_FORWARD }, | ||
47 | { 0x1e, KEY_RECORD }, | ||
48 | { 0x1f, KEY_PLAY }, | ||
49 | { 0x20, KEY_PREVIOUSSONG }, | ||
50 | { 0x21, KEY_NEXTSONG }, | ||
51 | { 0x22, KEY_PAUSE }, | ||
52 | { 0x23, KEY_STOP }, | ||
53 | }; | ||
54 | |||
55 | static struct rc_keymap cinergy_map = { | ||
56 | .map = { | ||
57 | .scan = cinergy, | ||
58 | .size = ARRAY_SIZE(cinergy), | ||
59 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
60 | .name = RC_MAP_CINERGY, | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | static int __init init_rc_map_cinergy(void) | ||
65 | { | ||
66 | return ir_register_map(&cinergy_map); | ||
67 | } | ||
68 | |||
69 | static void __exit exit_rc_map_cinergy(void) | ||
70 | { | ||
71 | ir_unregister_map(&cinergy_map); | ||
72 | } | ||
73 | |||
74 | module_init(init_rc_map_cinergy) | ||
75 | module_exit(exit_rc_map_cinergy) | ||
76 | |||
77 | MODULE_LICENSE("GPL"); | ||
78 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-dm1105-nec.c b/drivers/media/IR/keymaps/rc-dm1105-nec.c new file mode 100644 index 000000000000..90684d0efea3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dm1105-nec.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* dm1105-nec.h - Keytable for dm1105_nec Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* DVBWorld remotes | ||
16 | Igor M. Liplianin <liplianin@me.by> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode dm1105_nec[] = { | ||
20 | { 0x0a, KEY_POWER2}, /* power */ | ||
21 | { 0x0c, KEY_MUTE}, /* mute */ | ||
22 | { 0x11, KEY_1}, | ||
23 | { 0x12, KEY_2}, | ||
24 | { 0x13, KEY_3}, | ||
25 | { 0x14, KEY_4}, | ||
26 | { 0x15, KEY_5}, | ||
27 | { 0x16, KEY_6}, | ||
28 | { 0x17, KEY_7}, | ||
29 | { 0x18, KEY_8}, | ||
30 | { 0x19, KEY_9}, | ||
31 | { 0x10, KEY_0}, | ||
32 | { 0x1c, KEY_CHANNELUP}, /* ch+ */ | ||
33 | { 0x0f, KEY_CHANNELDOWN}, /* ch- */ | ||
34 | { 0x1a, KEY_VOLUMEUP}, /* vol+ */ | ||
35 | { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ | ||
36 | { 0x04, KEY_RECORD}, /* rec */ | ||
37 | { 0x09, KEY_CHANNEL}, /* fav */ | ||
38 | { 0x08, KEY_BACKSPACE}, /* rewind */ | ||
39 | { 0x07, KEY_FASTFORWARD}, /* fast */ | ||
40 | { 0x0b, KEY_PAUSE}, /* pause */ | ||
41 | { 0x02, KEY_ESC}, /* cancel */ | ||
42 | { 0x03, KEY_TAB}, /* tab */ | ||
43 | { 0x00, KEY_UP}, /* up */ | ||
44 | { 0x1f, KEY_ENTER}, /* ok */ | ||
45 | { 0x01, KEY_DOWN}, /* down */ | ||
46 | { 0x05, KEY_RECORD}, /* cap */ | ||
47 | { 0x06, KEY_STOP}, /* stop */ | ||
48 | { 0x40, KEY_ZOOM}, /* full */ | ||
49 | { 0x1e, KEY_TV}, /* tvmode */ | ||
50 | { 0x1b, KEY_B}, /* recall */ | ||
51 | }; | ||
52 | |||
53 | static struct rc_keymap dm1105_nec_map = { | ||
54 | .map = { | ||
55 | .scan = dm1105_nec, | ||
56 | .size = ARRAY_SIZE(dm1105_nec), | ||
57 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
58 | .name = RC_MAP_DM1105_NEC, | ||
59 | } | ||
60 | }; | ||
61 | |||
62 | static int __init init_rc_map_dm1105_nec(void) | ||
63 | { | ||
64 | return ir_register_map(&dm1105_nec_map); | ||
65 | } | ||
66 | |||
67 | static void __exit exit_rc_map_dm1105_nec(void) | ||
68 | { | ||
69 | ir_unregister_map(&dm1105_nec_map); | ||
70 | } | ||
71 | |||
72 | module_init(init_rc_map_dm1105_nec) | ||
73 | module_exit(exit_rc_map_dm1105_nec) | ||
74 | |||
75 | MODULE_LICENSE("GPL"); | ||
76 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c new file mode 100644 index 000000000000..8a4027af964a --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* DigitalNow DNTV Live DVB-T Remote */ | ||
16 | |||
17 | static struct ir_scancode dntv_live_dvb_t[] = { | ||
18 | { 0x00, KEY_ESC }, /* 'go up a level?' */ | ||
19 | /* Keys 0 to 9 */ | ||
20 | { 0x0a, KEY_0 }, | ||
21 | { 0x01, KEY_1 }, | ||
22 | { 0x02, KEY_2 }, | ||
23 | { 0x03, KEY_3 }, | ||
24 | { 0x04, KEY_4 }, | ||
25 | { 0x05, KEY_5 }, | ||
26 | { 0x06, KEY_6 }, | ||
27 | { 0x07, KEY_7 }, | ||
28 | { 0x08, KEY_8 }, | ||
29 | { 0x09, KEY_9 }, | ||
30 | |||
31 | { 0x0b, KEY_TUNER }, /* tv/fm */ | ||
32 | { 0x0c, KEY_SEARCH }, /* scan */ | ||
33 | { 0x0d, KEY_STOP }, | ||
34 | { 0x0e, KEY_PAUSE }, | ||
35 | { 0x0f, KEY_LIST }, /* source */ | ||
36 | |||
37 | { 0x10, KEY_MUTE }, | ||
38 | { 0x11, KEY_REWIND }, /* backward << */ | ||
39 | { 0x12, KEY_POWER }, | ||
40 | { 0x13, KEY_CAMERA }, /* snap */ | ||
41 | { 0x14, KEY_AUDIO }, /* stereo */ | ||
42 | { 0x15, KEY_CLEAR }, /* reset */ | ||
43 | { 0x16, KEY_PLAY }, | ||
44 | { 0x17, KEY_ENTER }, | ||
45 | { 0x18, KEY_ZOOM }, /* full screen */ | ||
46 | { 0x19, KEY_FASTFORWARD }, /* forward >> */ | ||
47 | { 0x1a, KEY_CHANNELUP }, | ||
48 | { 0x1b, KEY_VOLUMEUP }, | ||
49 | { 0x1c, KEY_INFO }, /* preview */ | ||
50 | { 0x1d, KEY_RECORD }, /* record */ | ||
51 | { 0x1e, KEY_CHANNELDOWN }, | ||
52 | { 0x1f, KEY_VOLUMEDOWN }, | ||
53 | }; | ||
54 | |||
55 | static struct rc_keymap dntv_live_dvb_t_map = { | ||
56 | .map = { | ||
57 | .scan = dntv_live_dvb_t, | ||
58 | .size = ARRAY_SIZE(dntv_live_dvb_t), | ||
59 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
60 | .name = RC_MAP_DNTV_LIVE_DVB_T, | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | static int __init init_rc_map_dntv_live_dvb_t(void) | ||
65 | { | ||
66 | return ir_register_map(&dntv_live_dvb_t_map); | ||
67 | } | ||
68 | |||
69 | static void __exit exit_rc_map_dntv_live_dvb_t(void) | ||
70 | { | ||
71 | ir_unregister_map(&dntv_live_dvb_t_map); | ||
72 | } | ||
73 | |||
74 | module_init(init_rc_map_dntv_live_dvb_t) | ||
75 | module_exit(exit_rc_map_dntv_live_dvb_t) | ||
76 | |||
77 | MODULE_LICENSE("GPL"); | ||
78 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c new file mode 100644 index 000000000000..6f4d60764d59 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* DigitalNow DNTV Live! DVB-T Pro Remote */ | ||
16 | |||
17 | static struct ir_scancode dntv_live_dvbt_pro[] = { | ||
18 | { 0x16, KEY_POWER }, | ||
19 | { 0x5b, KEY_HOME }, | ||
20 | |||
21 | { 0x55, KEY_TV }, /* live tv */ | ||
22 | { 0x58, KEY_TUNER }, /* digital Radio */ | ||
23 | { 0x5a, KEY_RADIO }, /* FM radio */ | ||
24 | { 0x59, KEY_DVD }, /* dvd menu */ | ||
25 | { 0x03, KEY_1 }, | ||
26 | { 0x01, KEY_2 }, | ||
27 | { 0x06, KEY_3 }, | ||
28 | { 0x09, KEY_4 }, | ||
29 | { 0x1d, KEY_5 }, | ||
30 | { 0x1f, KEY_6 }, | ||
31 | { 0x0d, KEY_7 }, | ||
32 | { 0x19, KEY_8 }, | ||
33 | { 0x1b, KEY_9 }, | ||
34 | { 0x0c, KEY_CANCEL }, | ||
35 | { 0x15, KEY_0 }, | ||
36 | { 0x4a, KEY_CLEAR }, | ||
37 | { 0x13, KEY_BACK }, | ||
38 | { 0x00, KEY_TAB }, | ||
39 | { 0x4b, KEY_UP }, | ||
40 | { 0x4e, KEY_LEFT }, | ||
41 | { 0x4f, KEY_OK }, | ||
42 | { 0x52, KEY_RIGHT }, | ||
43 | { 0x51, KEY_DOWN }, | ||
44 | { 0x1e, KEY_VOLUMEUP }, | ||
45 | { 0x0a, KEY_VOLUMEDOWN }, | ||
46 | { 0x02, KEY_CHANNELDOWN }, | ||
47 | { 0x05, KEY_CHANNELUP }, | ||
48 | { 0x11, KEY_RECORD }, | ||
49 | { 0x14, KEY_PLAY }, | ||
50 | { 0x4c, KEY_PAUSE }, | ||
51 | { 0x1a, KEY_STOP }, | ||
52 | { 0x40, KEY_REWIND }, | ||
53 | { 0x12, KEY_FASTFORWARD }, | ||
54 | { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ | ||
55 | { 0x42, KEY_NEXTSONG }, /* skip >| */ | ||
56 | { 0x54, KEY_CAMERA }, /* capture */ | ||
57 | { 0x50, KEY_LANGUAGE }, /* sap */ | ||
58 | { 0x47, KEY_TV2 }, /* pip */ | ||
59 | { 0x4d, KEY_SCREEN }, | ||
60 | { 0x43, KEY_SUBTITLE }, | ||
61 | { 0x10, KEY_MUTE }, | ||
62 | { 0x49, KEY_AUDIO }, /* l/r */ | ||
63 | { 0x07, KEY_SLEEP }, | ||
64 | { 0x08, KEY_VIDEO }, /* a/v */ | ||
65 | { 0x0e, KEY_PREVIOUS }, /* recall */ | ||
66 | { 0x45, KEY_ZOOM }, /* zoom + */ | ||
67 | { 0x46, KEY_ANGLE }, /* zoom - */ | ||
68 | { 0x56, KEY_RED }, | ||
69 | { 0x57, KEY_GREEN }, | ||
70 | { 0x5c, KEY_YELLOW }, | ||
71 | { 0x5d, KEY_BLUE }, | ||
72 | }; | ||
73 | |||
74 | static struct rc_keymap dntv_live_dvbt_pro_map = { | ||
75 | .map = { | ||
76 | .scan = dntv_live_dvbt_pro, | ||
77 | .size = ARRAY_SIZE(dntv_live_dvbt_pro), | ||
78 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
79 | .name = RC_MAP_DNTV_LIVE_DVBT_PRO, | ||
80 | } | ||
81 | }; | ||
82 | |||
83 | static int __init init_rc_map_dntv_live_dvbt_pro(void) | ||
84 | { | ||
85 | return ir_register_map(&dntv_live_dvbt_pro_map); | ||
86 | } | ||
87 | |||
88 | static void __exit exit_rc_map_dntv_live_dvbt_pro(void) | ||
89 | { | ||
90 | ir_unregister_map(&dntv_live_dvbt_pro_map); | ||
91 | } | ||
92 | |||
93 | module_init(init_rc_map_dntv_live_dvbt_pro) | ||
94 | module_exit(exit_rc_map_dntv_live_dvbt_pro) | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||
97 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-em-terratec.c b/drivers/media/IR/keymaps/rc-em-terratec.c new file mode 100644 index 000000000000..3130c9c29e6b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-em-terratec.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* em-terratec.h - Keytable for em_terratec Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode em_terratec[] = { | ||
16 | { 0x01, KEY_CHANNEL }, | ||
17 | { 0x02, KEY_SELECT }, | ||
18 | { 0x03, KEY_MUTE }, | ||
19 | { 0x04, KEY_POWER }, | ||
20 | { 0x05, KEY_1 }, | ||
21 | { 0x06, KEY_2 }, | ||
22 | { 0x07, KEY_3 }, | ||
23 | { 0x08, KEY_CHANNELUP }, | ||
24 | { 0x09, KEY_4 }, | ||
25 | { 0x0a, KEY_5 }, | ||
26 | { 0x0b, KEY_6 }, | ||
27 | { 0x0c, KEY_CHANNELDOWN }, | ||
28 | { 0x0d, KEY_7 }, | ||
29 | { 0x0e, KEY_8 }, | ||
30 | { 0x0f, KEY_9 }, | ||
31 | { 0x10, KEY_VOLUMEUP }, | ||
32 | { 0x11, KEY_0 }, | ||
33 | { 0x12, KEY_MENU }, | ||
34 | { 0x13, KEY_PRINT }, | ||
35 | { 0x14, KEY_VOLUMEDOWN }, | ||
36 | { 0x16, KEY_PAUSE }, | ||
37 | { 0x18, KEY_RECORD }, | ||
38 | { 0x19, KEY_REWIND }, | ||
39 | { 0x1a, KEY_PLAY }, | ||
40 | { 0x1b, KEY_FORWARD }, | ||
41 | { 0x1c, KEY_BACKSPACE }, | ||
42 | { 0x1e, KEY_STOP }, | ||
43 | { 0x40, KEY_ZOOM }, | ||
44 | }; | ||
45 | |||
46 | static struct rc_keymap em_terratec_map = { | ||
47 | .map = { | ||
48 | .scan = em_terratec, | ||
49 | .size = ARRAY_SIZE(em_terratec), | ||
50 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
51 | .name = RC_MAP_EM_TERRATEC, | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | static int __init init_rc_map_em_terratec(void) | ||
56 | { | ||
57 | return ir_register_map(&em_terratec_map); | ||
58 | } | ||
59 | |||
60 | static void __exit exit_rc_map_em_terratec(void) | ||
61 | { | ||
62 | ir_unregister_map(&em_terratec_map); | ||
63 | } | ||
64 | |||
65 | module_init(init_rc_map_em_terratec) | ||
66 | module_exit(exit_rc_map_em_terratec) | ||
67 | |||
68 | MODULE_LICENSE("GPL"); | ||
69 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-empty.c b/drivers/media/IR/keymaps/rc-empty.c new file mode 100644 index 000000000000..3b338d84b476 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-empty.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* empty.h - Keytable for empty Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | ||
16 | |||
17 | static struct ir_scancode empty[] = { | ||
18 | { 0x2a, KEY_COFFEE }, | ||
19 | }; | ||
20 | |||
21 | static struct rc_keymap empty_map = { | ||
22 | .map = { | ||
23 | .scan = empty, | ||
24 | .size = ARRAY_SIZE(empty), | ||
25 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
26 | .name = RC_MAP_EMPTY, | ||
27 | } | ||
28 | }; | ||
29 | |||
30 | static int __init init_rc_map_empty(void) | ||
31 | { | ||
32 | return ir_register_map(&empty_map); | ||
33 | } | ||
34 | |||
35 | static void __exit exit_rc_map_empty(void) | ||
36 | { | ||
37 | ir_unregister_map(&empty_map); | ||
38 | } | ||
39 | |||
40 | module_init(init_rc_map_empty) | ||
41 | module_exit(exit_rc_map_empty) | ||
42 | |||
43 | MODULE_LICENSE("GPL"); | ||
44 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c new file mode 100644 index 000000000000..4b816967877e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Encore ENLTV-FM v5.3 | ||
16 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode encore_enltv_fm53[] = { | ||
20 | { 0x10, KEY_POWER2}, | ||
21 | { 0x06, KEY_MUTE}, | ||
22 | |||
23 | { 0x09, KEY_1}, | ||
24 | { 0x1d, KEY_2}, | ||
25 | { 0x1f, KEY_3}, | ||
26 | { 0x19, KEY_4}, | ||
27 | { 0x1b, KEY_5}, | ||
28 | { 0x11, KEY_6}, | ||
29 | { 0x17, KEY_7}, | ||
30 | { 0x12, KEY_8}, | ||
31 | { 0x16, KEY_9}, | ||
32 | { 0x48, KEY_0}, | ||
33 | |||
34 | { 0x04, KEY_LIST}, /* -/-- */ | ||
35 | { 0x40, KEY_LAST}, /* recall */ | ||
36 | |||
37 | { 0x02, KEY_MODE}, /* TV/AV */ | ||
38 | { 0x05, KEY_CAMERA}, /* SNAPSHOT */ | ||
39 | |||
40 | { 0x4c, KEY_CHANNELUP}, /* UP */ | ||
41 | { 0x00, KEY_CHANNELDOWN}, /* DOWN */ | ||
42 | { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ | ||
43 | { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ | ||
44 | { 0x49, KEY_ENTER}, /* OK */ | ||
45 | |||
46 | { 0x54, KEY_RECORD}, | ||
47 | { 0x4d, KEY_PLAY}, /* pause */ | ||
48 | |||
49 | { 0x1e, KEY_MENU}, /* video setting */ | ||
50 | { 0x0e, KEY_RIGHT}, /* <- */ | ||
51 | { 0x1a, KEY_LEFT}, /* -> */ | ||
52 | |||
53 | { 0x0a, KEY_CLEAR}, /* video default */ | ||
54 | { 0x0c, KEY_ZOOM}, /* hide pannel */ | ||
55 | { 0x47, KEY_SLEEP}, /* shutdown */ | ||
56 | }; | ||
57 | |||
58 | static struct rc_keymap encore_enltv_fm53_map = { | ||
59 | .map = { | ||
60 | .scan = encore_enltv_fm53, | ||
61 | .size = ARRAY_SIZE(encore_enltv_fm53), | ||
62 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
63 | .name = RC_MAP_ENCORE_ENLTV_FM53, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_encore_enltv_fm53(void) | ||
68 | { | ||
69 | return ir_register_map(&encore_enltv_fm53_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_encore_enltv_fm53(void) | ||
73 | { | ||
74 | ir_unregister_map(&encore_enltv_fm53_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_encore_enltv_fm53) | ||
78 | module_exit(exit_rc_map_encore_enltv_fm53) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-encore-enltv.c b/drivers/media/IR/keymaps/rc-encore-enltv.c new file mode 100644 index 000000000000..9fabffd28cc9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* encore-enltv.h - Keytable for encore_enltv Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons | ||
16 | Juan Pablo Sormani <sorman@gmail.com> */ | ||
17 | |||
18 | static struct ir_scancode encore_enltv[] = { | ||
19 | |||
20 | /* Power button does nothing, neither in Windows app, | ||
21 | although it sends data (used for BIOS wakeup?) */ | ||
22 | { 0x0d, KEY_MUTE }, | ||
23 | |||
24 | { 0x1e, KEY_TV }, | ||
25 | { 0x00, KEY_VIDEO }, | ||
26 | { 0x01, KEY_AUDIO }, /* music */ | ||
27 | { 0x02, KEY_MHP }, /* picture */ | ||
28 | |||
29 | { 0x1f, KEY_1 }, | ||
30 | { 0x03, KEY_2 }, | ||
31 | { 0x04, KEY_3 }, | ||
32 | { 0x05, KEY_4 }, | ||
33 | { 0x1c, KEY_5 }, | ||
34 | { 0x06, KEY_6 }, | ||
35 | { 0x07, KEY_7 }, | ||
36 | { 0x08, KEY_8 }, | ||
37 | { 0x1d, KEY_9 }, | ||
38 | { 0x0a, KEY_0 }, | ||
39 | |||
40 | { 0x09, KEY_LIST }, /* -/-- */ | ||
41 | { 0x0b, KEY_LAST }, /* recall */ | ||
42 | |||
43 | { 0x14, KEY_HOME }, /* win start menu */ | ||
44 | { 0x15, KEY_EXIT }, /* exit */ | ||
45 | { 0x16, KEY_CHANNELUP }, /* UP */ | ||
46 | { 0x12, KEY_CHANNELDOWN }, /* DOWN */ | ||
47 | { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ | ||
48 | { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ | ||
49 | |||
50 | { 0x18, KEY_ENTER }, /* OK */ | ||
51 | |||
52 | { 0x0e, KEY_ESC }, | ||
53 | { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ | ||
54 | { 0x11, KEY_TAB }, | ||
55 | { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ | ||
56 | |||
57 | { 0x1a, KEY_MENU }, | ||
58 | { 0x1b, KEY_ZOOM }, /* fullscreen */ | ||
59 | { 0x44, KEY_TIME }, /* time shift */ | ||
60 | { 0x40, KEY_MODE }, /* source */ | ||
61 | |||
62 | { 0x5a, KEY_RECORD }, | ||
63 | { 0x42, KEY_PLAY }, /* play/pause */ | ||
64 | { 0x45, KEY_STOP }, | ||
65 | { 0x43, KEY_CAMERA }, /* camera icon */ | ||
66 | |||
67 | { 0x48, KEY_REWIND }, | ||
68 | { 0x4a, KEY_FASTFORWARD }, | ||
69 | { 0x49, KEY_PREVIOUS }, | ||
70 | { 0x4b, KEY_NEXT }, | ||
71 | |||
72 | { 0x4c, KEY_FAVORITES }, /* tv wall */ | ||
73 | { 0x4d, KEY_SOUND }, /* DVD sound */ | ||
74 | { 0x4e, KEY_LANGUAGE }, /* DVD lang */ | ||
75 | { 0x4f, KEY_TEXT }, /* DVD text */ | ||
76 | |||
77 | { 0x50, KEY_SLEEP }, /* shutdown */ | ||
78 | { 0x51, KEY_MODE }, /* stereo > main */ | ||
79 | { 0x52, KEY_SELECT }, /* stereo > sap */ | ||
80 | { 0x53, KEY_PROG1 }, /* teletext */ | ||
81 | |||
82 | |||
83 | { 0x59, KEY_RED }, /* AP1 */ | ||
84 | { 0x41, KEY_GREEN }, /* AP2 */ | ||
85 | { 0x47, KEY_YELLOW }, /* AP3 */ | ||
86 | { 0x57, KEY_BLUE }, /* AP4 */ | ||
87 | }; | ||
88 | |||
89 | static struct rc_keymap encore_enltv_map = { | ||
90 | .map = { | ||
91 | .scan = encore_enltv, | ||
92 | .size = ARRAY_SIZE(encore_enltv), | ||
93 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
94 | .name = RC_MAP_ENCORE_ENLTV, | ||
95 | } | ||
96 | }; | ||
97 | |||
98 | static int __init init_rc_map_encore_enltv(void) | ||
99 | { | ||
100 | return ir_register_map(&encore_enltv_map); | ||
101 | } | ||
102 | |||
103 | static void __exit exit_rc_map_encore_enltv(void) | ||
104 | { | ||
105 | ir_unregister_map(&encore_enltv_map); | ||
106 | } | ||
107 | |||
108 | module_init(init_rc_map_encore_enltv) | ||
109 | module_exit(exit_rc_map_encore_enltv) | ||
110 | |||
111 | MODULE_LICENSE("GPL"); | ||
112 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-encore-enltv2.c b/drivers/media/IR/keymaps/rc-encore-enltv2.c new file mode 100644 index 000000000000..efefd5166618 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv2.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton | ||
16 | Mauro Carvalho Chehab <mchehab@infradead.org> */ | ||
17 | |||
18 | static struct ir_scancode encore_enltv2[] = { | ||
19 | { 0x4c, KEY_POWER2 }, | ||
20 | { 0x4a, KEY_TUNER }, | ||
21 | { 0x40, KEY_1 }, | ||
22 | { 0x60, KEY_2 }, | ||
23 | { 0x50, KEY_3 }, | ||
24 | { 0x70, KEY_4 }, | ||
25 | { 0x48, KEY_5 }, | ||
26 | { 0x68, KEY_6 }, | ||
27 | { 0x58, KEY_7 }, | ||
28 | { 0x78, KEY_8 }, | ||
29 | { 0x44, KEY_9 }, | ||
30 | { 0x54, KEY_0 }, | ||
31 | |||
32 | { 0x64, KEY_LAST }, /* +100 */ | ||
33 | { 0x4e, KEY_AGAIN }, /* Recall */ | ||
34 | |||
35 | { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ | ||
36 | { 0x5e, KEY_MENU }, | ||
37 | { 0x56, KEY_SCREEN }, | ||
38 | { 0x7a, KEY_SETUP }, | ||
39 | |||
40 | { 0x46, KEY_MUTE }, | ||
41 | { 0x5c, KEY_MODE }, /* Stereo */ | ||
42 | { 0x74, KEY_INFO }, | ||
43 | { 0x7c, KEY_CLEAR }, | ||
44 | |||
45 | { 0x55, KEY_UP }, | ||
46 | { 0x49, KEY_DOWN }, | ||
47 | { 0x7e, KEY_LEFT }, | ||
48 | { 0x59, KEY_RIGHT }, | ||
49 | { 0x6a, KEY_ENTER }, | ||
50 | |||
51 | { 0x42, KEY_VOLUMEUP }, | ||
52 | { 0x62, KEY_VOLUMEDOWN }, | ||
53 | { 0x52, KEY_CHANNELUP }, | ||
54 | { 0x72, KEY_CHANNELDOWN }, | ||
55 | |||
56 | { 0x41, KEY_RECORD }, | ||
57 | { 0x51, KEY_CAMERA }, /* Snapshot */ | ||
58 | { 0x75, KEY_TIME }, /* Timeshift */ | ||
59 | { 0x71, KEY_TV2 }, /* PIP */ | ||
60 | |||
61 | { 0x45, KEY_REWIND }, | ||
62 | { 0x6f, KEY_PAUSE }, | ||
63 | { 0x7d, KEY_FORWARD }, | ||
64 | { 0x79, KEY_STOP }, | ||
65 | }; | ||
66 | |||
67 | static struct rc_keymap encore_enltv2_map = { | ||
68 | .map = { | ||
69 | .scan = encore_enltv2, | ||
70 | .size = ARRAY_SIZE(encore_enltv2), | ||
71 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
72 | .name = RC_MAP_ENCORE_ENLTV2, | ||
73 | } | ||
74 | }; | ||
75 | |||
76 | static int __init init_rc_map_encore_enltv2(void) | ||
77 | { | ||
78 | return ir_register_map(&encore_enltv2_map); | ||
79 | } | ||
80 | |||
81 | static void __exit exit_rc_map_encore_enltv2(void) | ||
82 | { | ||
83 | ir_unregister_map(&encore_enltv2_map); | ||
84 | } | ||
85 | |||
86 | module_init(init_rc_map_encore_enltv2) | ||
87 | module_exit(exit_rc_map_encore_enltv2) | ||
88 | |||
89 | MODULE_LICENSE("GPL"); | ||
90 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-evga-indtube.c b/drivers/media/IR/keymaps/rc-evga-indtube.c new file mode 100644 index 000000000000..3f3fb13813b3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-evga-indtube.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* evga-indtube.h - Keytable for evga_indtube Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* EVGA inDtube | ||
16 | Devin Heitmueller <devin.heitmueller@gmail.com> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode evga_indtube[] = { | ||
20 | { 0x12, KEY_POWER}, | ||
21 | { 0x02, KEY_MODE}, /* TV */ | ||
22 | { 0x14, KEY_MUTE}, | ||
23 | { 0x1a, KEY_CHANNELUP}, | ||
24 | { 0x16, KEY_TV2}, /* PIP */ | ||
25 | { 0x1d, KEY_VOLUMEUP}, | ||
26 | { 0x05, KEY_CHANNELDOWN}, | ||
27 | { 0x0f, KEY_PLAYPAUSE}, | ||
28 | { 0x19, KEY_VOLUMEDOWN}, | ||
29 | { 0x1c, KEY_REWIND}, | ||
30 | { 0x0d, KEY_RECORD}, | ||
31 | { 0x18, KEY_FORWARD}, | ||
32 | { 0x1e, KEY_PREVIOUS}, | ||
33 | { 0x1b, KEY_STOP}, | ||
34 | { 0x1f, KEY_NEXT}, | ||
35 | { 0x13, KEY_CAMERA}, | ||
36 | }; | ||
37 | |||
38 | static struct rc_keymap evga_indtube_map = { | ||
39 | .map = { | ||
40 | .scan = evga_indtube, | ||
41 | .size = ARRAY_SIZE(evga_indtube), | ||
42 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
43 | .name = RC_MAP_EVGA_INDTUBE, | ||
44 | } | ||
45 | }; | ||
46 | |||
47 | static int __init init_rc_map_evga_indtube(void) | ||
48 | { | ||
49 | return ir_register_map(&evga_indtube_map); | ||
50 | } | ||
51 | |||
52 | static void __exit exit_rc_map_evga_indtube(void) | ||
53 | { | ||
54 | ir_unregister_map(&evga_indtube_map); | ||
55 | } | ||
56 | |||
57 | module_init(init_rc_map_evga_indtube) | ||
58 | module_exit(exit_rc_map_evga_indtube) | ||
59 | |||
60 | MODULE_LICENSE("GPL"); | ||
61 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-eztv.c b/drivers/media/IR/keymaps/rc-eztv.c new file mode 100644 index 000000000000..660907a78db9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-eztv.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* eztv.h - Keytable for eztv Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Alfons Geser <a.geser@cox.net> | ||
16 | * updates from Job D. R. Borges <jobdrb@ig.com.br> */ | ||
17 | |||
18 | static struct ir_scancode eztv[] = { | ||
19 | { 0x12, KEY_POWER }, | ||
20 | { 0x01, KEY_TV }, /* DVR */ | ||
21 | { 0x15, KEY_DVD }, /* DVD */ | ||
22 | { 0x17, KEY_AUDIO }, /* music */ | ||
23 | /* DVR mode / DVD mode / music mode */ | ||
24 | |||
25 | { 0x1b, KEY_MUTE }, /* mute */ | ||
26 | { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ | ||
27 | { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ | ||
28 | { 0x16, KEY_ZOOM }, /* full screen */ | ||
29 | { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ | ||
30 | { 0x1d, KEY_RESTART }, /* playback / angle / del */ | ||
31 | { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ | ||
32 | { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ | ||
33 | |||
34 | { 0x31, KEY_HELP }, /* help */ | ||
35 | { 0x32, KEY_MODE }, /* num/memo */ | ||
36 | { 0x33, KEY_ESC }, /* cancel */ | ||
37 | |||
38 | { 0x0c, KEY_UP }, /* up */ | ||
39 | { 0x10, KEY_DOWN }, /* down */ | ||
40 | { 0x08, KEY_LEFT }, /* left */ | ||
41 | { 0x04, KEY_RIGHT }, /* right */ | ||
42 | { 0x03, KEY_SELECT }, /* select */ | ||
43 | |||
44 | { 0x1f, KEY_REWIND }, /* rewind */ | ||
45 | { 0x20, KEY_PLAYPAUSE },/* play/pause */ | ||
46 | { 0x29, KEY_FORWARD }, /* forward */ | ||
47 | { 0x14, KEY_AGAIN }, /* repeat */ | ||
48 | { 0x2b, KEY_RECORD }, /* recording */ | ||
49 | { 0x2c, KEY_STOP }, /* stop */ | ||
50 | { 0x2d, KEY_PLAY }, /* play */ | ||
51 | { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ | ||
52 | |||
53 | { 0x00, KEY_0 }, | ||
54 | { 0x05, KEY_1 }, | ||
55 | { 0x06, KEY_2 }, | ||
56 | { 0x07, KEY_3 }, | ||
57 | { 0x09, KEY_4 }, | ||
58 | { 0x0a, KEY_5 }, | ||
59 | { 0x0b, KEY_6 }, | ||
60 | { 0x0d, KEY_7 }, | ||
61 | { 0x0e, KEY_8 }, | ||
62 | { 0x0f, KEY_9 }, | ||
63 | |||
64 | { 0x2a, KEY_VOLUMEUP }, | ||
65 | { 0x11, KEY_VOLUMEDOWN }, | ||
66 | { 0x18, KEY_CHANNELUP },/* CH.tracking up */ | ||
67 | { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ | ||
68 | |||
69 | { 0x13, KEY_ENTER }, /* enter */ | ||
70 | { 0x21, KEY_DOT }, /* . (decimal dot) */ | ||
71 | }; | ||
72 | |||
73 | static struct rc_keymap eztv_map = { | ||
74 | .map = { | ||
75 | .scan = eztv, | ||
76 | .size = ARRAY_SIZE(eztv), | ||
77 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
78 | .name = RC_MAP_EZTV, | ||
79 | } | ||
80 | }; | ||
81 | |||
82 | static int __init init_rc_map_eztv(void) | ||
83 | { | ||
84 | return ir_register_map(&eztv_map); | ||
85 | } | ||
86 | |||
87 | static void __exit exit_rc_map_eztv(void) | ||
88 | { | ||
89 | ir_unregister_map(&eztv_map); | ||
90 | } | ||
91 | |||
92 | module_init(init_rc_map_eztv) | ||
93 | module_exit(exit_rc_map_eztv) | ||
94 | |||
95 | MODULE_LICENSE("GPL"); | ||
96 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-flydvb.c b/drivers/media/IR/keymaps/rc-flydvb.c new file mode 100644 index 000000000000..a173c81035f4 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-flydvb.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* flydvb.h - Keytable for flydvb Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode flydvb[] = { | ||
16 | { 0x01, KEY_ZOOM }, /* Full Screen */ | ||
17 | { 0x00, KEY_POWER }, /* Power */ | ||
18 | |||
19 | { 0x03, KEY_1 }, | ||
20 | { 0x04, KEY_2 }, | ||
21 | { 0x05, KEY_3 }, | ||
22 | { 0x07, KEY_4 }, | ||
23 | { 0x08, KEY_5 }, | ||
24 | { 0x09, KEY_6 }, | ||
25 | { 0x0b, KEY_7 }, | ||
26 | { 0x0c, KEY_8 }, | ||
27 | { 0x0d, KEY_9 }, | ||
28 | { 0x06, KEY_AGAIN }, /* Recall */ | ||
29 | { 0x0f, KEY_0 }, | ||
30 | { 0x10, KEY_MUTE }, /* Mute */ | ||
31 | { 0x02, KEY_RADIO }, /* TV/Radio */ | ||
32 | { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ | ||
33 | |||
34 | { 0x14, KEY_VOLUMEUP }, /* VOL+ */ | ||
35 | { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ | ||
36 | { 0x12, KEY_CHANNELUP }, /* CH+ */ | ||
37 | { 0x13, KEY_CHANNELDOWN }, /* CH- */ | ||
38 | { 0x1d, KEY_ENTER }, /* Enter */ | ||
39 | |||
40 | { 0x1a, KEY_MODE }, /* PIP */ | ||
41 | { 0x18, KEY_TUNER }, /* Source */ | ||
42 | |||
43 | { 0x1e, KEY_RECORD }, /* Record/Pause */ | ||
44 | { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ | ||
45 | { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ | ||
46 | { 0x19, KEY_BACK }, /* Rewind << */ | ||
47 | { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ | ||
48 | { 0x1f, KEY_FORWARD }, /* Forward >> */ | ||
49 | { 0x16, KEY_PREVIOUS }, /* Back |<< */ | ||
50 | { 0x11, KEY_STOP }, /* Stop */ | ||
51 | { 0x0e, KEY_NEXT }, /* End >>| */ | ||
52 | }; | ||
53 | |||
54 | static struct rc_keymap flydvb_map = { | ||
55 | .map = { | ||
56 | .scan = flydvb, | ||
57 | .size = ARRAY_SIZE(flydvb), | ||
58 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
59 | .name = RC_MAP_FLYDVB, | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | static int __init init_rc_map_flydvb(void) | ||
64 | { | ||
65 | return ir_register_map(&flydvb_map); | ||
66 | } | ||
67 | |||
68 | static void __exit exit_rc_map_flydvb(void) | ||
69 | { | ||
70 | ir_unregister_map(&flydvb_map); | ||
71 | } | ||
72 | |||
73 | module_init(init_rc_map_flydvb) | ||
74 | module_exit(exit_rc_map_flydvb) | ||
75 | |||
76 | MODULE_LICENSE("GPL"); | ||
77 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-flyvideo.c b/drivers/media/IR/keymaps/rc-flyvideo.c new file mode 100644 index 000000000000..9c73043cbdba --- /dev/null +++ b/drivers/media/IR/keymaps/rc-flyvideo.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* flyvideo.h - Keytable for flyvideo Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode flyvideo[] = { | ||
16 | { 0x0f, KEY_0 }, | ||
17 | { 0x03, KEY_1 }, | ||
18 | { 0x04, KEY_2 }, | ||
19 | { 0x05, KEY_3 }, | ||
20 | { 0x07, KEY_4 }, | ||
21 | { 0x08, KEY_5 }, | ||
22 | { 0x09, KEY_6 }, | ||
23 | { 0x0b, KEY_7 }, | ||
24 | { 0x0c, KEY_8 }, | ||
25 | { 0x0d, KEY_9 }, | ||
26 | |||
27 | { 0x0e, KEY_MODE }, /* Air/Cable */ | ||
28 | { 0x11, KEY_VIDEO }, /* Video */ | ||
29 | { 0x15, KEY_AUDIO }, /* Audio */ | ||
30 | { 0x00, KEY_POWER }, /* Power */ | ||
31 | { 0x18, KEY_TUNER }, /* AV Source */ | ||
32 | { 0x02, KEY_ZOOM }, /* Fullscreen */ | ||
33 | { 0x1a, KEY_LANGUAGE }, /* Stereo */ | ||
34 | { 0x1b, KEY_MUTE }, /* Mute */ | ||
35 | { 0x14, KEY_VOLUMEUP }, /* Volume + */ | ||
36 | { 0x17, KEY_VOLUMEDOWN },/* Volume - */ | ||
37 | { 0x12, KEY_CHANNELUP },/* Channel + */ | ||
38 | { 0x13, KEY_CHANNELDOWN },/* Channel - */ | ||
39 | { 0x06, KEY_AGAIN }, /* Recall */ | ||
40 | { 0x10, KEY_ENTER }, /* Enter */ | ||
41 | |||
42 | { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ | ||
43 | { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ | ||
44 | { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ | ||
45 | }; | ||
46 | |||
47 | static struct rc_keymap flyvideo_map = { | ||
48 | .map = { | ||
49 | .scan = flyvideo, | ||
50 | .size = ARRAY_SIZE(flyvideo), | ||
51 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
52 | .name = RC_MAP_FLYVIDEO, | ||
53 | } | ||
54 | }; | ||
55 | |||
56 | static int __init init_rc_map_flyvideo(void) | ||
57 | { | ||
58 | return ir_register_map(&flyvideo_map); | ||
59 | } | ||
60 | |||
61 | static void __exit exit_rc_map_flyvideo(void) | ||
62 | { | ||
63 | ir_unregister_map(&flyvideo_map); | ||
64 | } | ||
65 | |||
66 | module_init(init_rc_map_flyvideo) | ||
67 | module_exit(exit_rc_map_flyvideo) | ||
68 | |||
69 | MODULE_LICENSE("GPL"); | ||
70 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c new file mode 100644 index 000000000000..cdb10389b10e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* DViCO FUSION HDTV MCE remote */ | ||
16 | |||
17 | static struct ir_scancode fusionhdtv_mce[] = { | ||
18 | |||
19 | { 0x0b, KEY_1 }, | ||
20 | { 0x17, KEY_2 }, | ||
21 | { 0x1b, KEY_3 }, | ||
22 | { 0x07, KEY_4 }, | ||
23 | { 0x50, KEY_5 }, | ||
24 | { 0x54, KEY_6 }, | ||
25 | { 0x48, KEY_7 }, | ||
26 | { 0x4c, KEY_8 }, | ||
27 | { 0x58, KEY_9 }, | ||
28 | { 0x03, KEY_0 }, | ||
29 | |||
30 | { 0x5e, KEY_OK }, | ||
31 | { 0x51, KEY_UP }, | ||
32 | { 0x53, KEY_DOWN }, | ||
33 | { 0x5b, KEY_LEFT }, | ||
34 | { 0x5f, KEY_RIGHT }, | ||
35 | |||
36 | { 0x02, KEY_TV }, /* Labeled DTV on remote */ | ||
37 | { 0x0e, KEY_MP3 }, | ||
38 | { 0x1a, KEY_DVD }, | ||
39 | { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ | ||
40 | { 0x16, KEY_SETUP }, | ||
41 | { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ | ||
42 | { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ | ||
43 | |||
44 | { 0x49, KEY_BACK }, | ||
45 | { 0x59, KEY_INFO }, /* Labeled MORE on remote */ | ||
46 | { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ | ||
47 | { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ | ||
48 | |||
49 | { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ | ||
50 | { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ | ||
51 | { 0x42, KEY_ENTER }, /* Labeled START with a green | ||
52 | MS windows logo on remote */ | ||
53 | |||
54 | { 0x15, KEY_VOLUMEUP }, | ||
55 | { 0x05, KEY_VOLUMEDOWN }, | ||
56 | { 0x11, KEY_CHANNELUP }, | ||
57 | { 0x09, KEY_CHANNELDOWN }, | ||
58 | |||
59 | { 0x52, KEY_CAMERA }, | ||
60 | { 0x5a, KEY_TUNER }, | ||
61 | { 0x19, KEY_OPEN }, | ||
62 | |||
63 | { 0x13, KEY_MODE }, /* 4:3 16:9 select */ | ||
64 | { 0x1f, KEY_ZOOM }, | ||
65 | |||
66 | { 0x43, KEY_REWIND }, | ||
67 | { 0x47, KEY_PLAYPAUSE }, | ||
68 | { 0x4f, KEY_FASTFORWARD }, | ||
69 | { 0x57, KEY_MUTE }, | ||
70 | { 0x0d, KEY_STOP }, | ||
71 | { 0x01, KEY_RECORD }, | ||
72 | { 0x4e, KEY_POWER }, | ||
73 | }; | ||
74 | |||
75 | static struct rc_keymap fusionhdtv_mce_map = { | ||
76 | .map = { | ||
77 | .scan = fusionhdtv_mce, | ||
78 | .size = ARRAY_SIZE(fusionhdtv_mce), | ||
79 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
80 | .name = RC_MAP_FUSIONHDTV_MCE, | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static int __init init_rc_map_fusionhdtv_mce(void) | ||
85 | { | ||
86 | return ir_register_map(&fusionhdtv_mce_map); | ||
87 | } | ||
88 | |||
89 | static void __exit exit_rc_map_fusionhdtv_mce(void) | ||
90 | { | ||
91 | ir_unregister_map(&fusionhdtv_mce_map); | ||
92 | } | ||
93 | |||
94 | module_init(init_rc_map_fusionhdtv_mce) | ||
95 | module_exit(exit_rc_map_fusionhdtv_mce) | ||
96 | |||
97 | MODULE_LICENSE("GPL"); | ||
98 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c new file mode 100644 index 000000000000..c16c0d1263ac --- /dev/null +++ b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* GADMEI UTV330+ RM008Z remote | ||
16 | Shine Liu <shinel@foxmail.com> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode gadmei_rm008z[] = { | ||
20 | { 0x14, KEY_POWER2}, /* POWER OFF */ | ||
21 | { 0x0c, KEY_MUTE}, /* MUTE */ | ||
22 | |||
23 | { 0x18, KEY_TV}, /* TV */ | ||
24 | { 0x0e, KEY_VIDEO}, /* AV */ | ||
25 | { 0x0b, KEY_AUDIO}, /* SV */ | ||
26 | { 0x0f, KEY_RADIO}, /* FM */ | ||
27 | |||
28 | { 0x00, KEY_1}, | ||
29 | { 0x01, KEY_2}, | ||
30 | { 0x02, KEY_3}, | ||
31 | { 0x03, KEY_4}, | ||
32 | { 0x04, KEY_5}, | ||
33 | { 0x05, KEY_6}, | ||
34 | { 0x06, KEY_7}, | ||
35 | { 0x07, KEY_8}, | ||
36 | { 0x08, KEY_9}, | ||
37 | { 0x09, KEY_0}, | ||
38 | { 0x0a, KEY_INFO}, /* OSD */ | ||
39 | { 0x1c, KEY_BACKSPACE}, /* LAST */ | ||
40 | |||
41 | { 0x0d, KEY_PLAY}, /* PLAY */ | ||
42 | { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ | ||
43 | { 0x1a, KEY_RECORD}, /* RECORD */ | ||
44 | { 0x17, KEY_STOP}, /* STOP */ | ||
45 | |||
46 | { 0x1f, KEY_UP}, /* UP */ | ||
47 | { 0x44, KEY_DOWN}, /* DOWN */ | ||
48 | { 0x46, KEY_TAB}, /* BACK */ | ||
49 | { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ | ||
50 | |||
51 | { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
52 | { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
53 | { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ | ||
54 | { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
55 | { 0x15, KEY_ENTER}, /* OK */ | ||
56 | }; | ||
57 | |||
58 | static struct rc_keymap gadmei_rm008z_map = { | ||
59 | .map = { | ||
60 | .scan = gadmei_rm008z, | ||
61 | .size = ARRAY_SIZE(gadmei_rm008z), | ||
62 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
63 | .name = RC_MAP_GADMEI_RM008Z, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_gadmei_rm008z(void) | ||
68 | { | ||
69 | return ir_register_map(&gadmei_rm008z_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_gadmei_rm008z(void) | ||
73 | { | ||
74 | ir_unregister_map(&gadmei_rm008z_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_gadmei_rm008z) | ||
78 | module_exit(exit_rc_map_gadmei_rm008z) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c new file mode 100644 index 000000000000..89f8e384e52a --- /dev/null +++ b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Remote control for the Genius TVGO A11MCE | ||
17 | * Adrian Pardini <pardo.bsso@gmail.com> | ||
18 | */ | ||
19 | |||
20 | static struct ir_scancode genius_tvgo_a11mce[] = { | ||
21 | /* Keys 0 to 9 */ | ||
22 | { 0x48, KEY_0 }, | ||
23 | { 0x09, KEY_1 }, | ||
24 | { 0x1d, KEY_2 }, | ||
25 | { 0x1f, KEY_3 }, | ||
26 | { 0x19, KEY_4 }, | ||
27 | { 0x1b, KEY_5 }, | ||
28 | { 0x11, KEY_6 }, | ||
29 | { 0x17, KEY_7 }, | ||
30 | { 0x12, KEY_8 }, | ||
31 | { 0x16, KEY_9 }, | ||
32 | |||
33 | { 0x54, KEY_RECORD }, /* recording */ | ||
34 | { 0x06, KEY_MUTE }, /* mute */ | ||
35 | { 0x10, KEY_POWER }, | ||
36 | { 0x40, KEY_LAST }, /* recall */ | ||
37 | { 0x4c, KEY_CHANNELUP }, /* channel / program + */ | ||
38 | { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ | ||
39 | { 0x0d, KEY_VOLUMEUP }, | ||
40 | { 0x15, KEY_VOLUMEDOWN }, | ||
41 | { 0x4d, KEY_OK }, /* also labeled as Pause */ | ||
42 | { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ | ||
43 | { 0x02, KEY_MODE }, /* AV Source or Rewind*/ | ||
44 | { 0x04, KEY_LIST }, /* -/-- */ | ||
45 | /* small arrows above numbers */ | ||
46 | { 0x1a, KEY_NEXT }, /* also Fast Forward */ | ||
47 | { 0x0e, KEY_PREVIOUS }, /* also Rewind */ | ||
48 | /* these are in a rather non standard layout and have | ||
49 | an alternate name written */ | ||
50 | { 0x1e, KEY_UP }, /* Video Setting */ | ||
51 | { 0x0a, KEY_DOWN }, /* Video Default */ | ||
52 | { 0x05, KEY_CAMERA }, /* Snapshot */ | ||
53 | { 0x0c, KEY_RIGHT }, /* Hide Panel */ | ||
54 | /* Four buttons without label */ | ||
55 | { 0x49, KEY_RED }, | ||
56 | { 0x0b, KEY_GREEN }, | ||
57 | { 0x13, KEY_YELLOW }, | ||
58 | { 0x50, KEY_BLUE }, | ||
59 | }; | ||
60 | |||
61 | static struct rc_keymap genius_tvgo_a11mce_map = { | ||
62 | .map = { | ||
63 | .scan = genius_tvgo_a11mce, | ||
64 | .size = ARRAY_SIZE(genius_tvgo_a11mce), | ||
65 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
66 | .name = RC_MAP_GENIUS_TVGO_A11MCE, | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | static int __init init_rc_map_genius_tvgo_a11mce(void) | ||
71 | { | ||
72 | return ir_register_map(&genius_tvgo_a11mce_map); | ||
73 | } | ||
74 | |||
75 | static void __exit exit_rc_map_genius_tvgo_a11mce(void) | ||
76 | { | ||
77 | ir_unregister_map(&genius_tvgo_a11mce_map); | ||
78 | } | ||
79 | |||
80 | module_init(init_rc_map_genius_tvgo_a11mce) | ||
81 | module_exit(exit_rc_map_genius_tvgo_a11mce) | ||
82 | |||
83 | MODULE_LICENSE("GPL"); | ||
84 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-gotview7135.c b/drivers/media/IR/keymaps/rc-gotview7135.c new file mode 100644 index 000000000000..52f025bb35f6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-gotview7135.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* gotview7135.h - Keytable for gotview7135 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Mike Baikov <mike@baikov.com> */ | ||
16 | |||
17 | static struct ir_scancode gotview7135[] = { | ||
18 | |||
19 | { 0x11, KEY_POWER }, | ||
20 | { 0x35, KEY_TV }, | ||
21 | { 0x1b, KEY_0 }, | ||
22 | { 0x29, KEY_1 }, | ||
23 | { 0x19, KEY_2 }, | ||
24 | { 0x39, KEY_3 }, | ||
25 | { 0x1f, KEY_4 }, | ||
26 | { 0x2c, KEY_5 }, | ||
27 | { 0x21, KEY_6 }, | ||
28 | { 0x24, KEY_7 }, | ||
29 | { 0x18, KEY_8 }, | ||
30 | { 0x2b, KEY_9 }, | ||
31 | { 0x3b, KEY_AGAIN }, /* LOOP */ | ||
32 | { 0x06, KEY_AUDIO }, | ||
33 | { 0x31, KEY_PRINT }, /* PREVIEW */ | ||
34 | { 0x3e, KEY_VIDEO }, | ||
35 | { 0x10, KEY_CHANNELUP }, | ||
36 | { 0x20, KEY_CHANNELDOWN }, | ||
37 | { 0x0c, KEY_VOLUMEDOWN }, | ||
38 | { 0x28, KEY_VOLUMEUP }, | ||
39 | { 0x08, KEY_MUTE }, | ||
40 | { 0x26, KEY_SEARCH }, /* SCAN */ | ||
41 | { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ | ||
42 | { 0x12, KEY_RECORD }, | ||
43 | { 0x32, KEY_STOP }, | ||
44 | { 0x3c, KEY_PLAY }, | ||
45 | { 0x1d, KEY_REWIND }, | ||
46 | { 0x2d, KEY_PAUSE }, | ||
47 | { 0x0d, KEY_FORWARD }, | ||
48 | { 0x05, KEY_ZOOM }, /*FULL*/ | ||
49 | |||
50 | { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ | ||
51 | { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ | ||
52 | { 0x1e, KEY_TIME }, /* TIMESHIFT */ | ||
53 | { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ | ||
54 | }; | ||
55 | |||
56 | static struct rc_keymap gotview7135_map = { | ||
57 | .map = { | ||
58 | .scan = gotview7135, | ||
59 | .size = ARRAY_SIZE(gotview7135), | ||
60 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
61 | .name = RC_MAP_GOTVIEW7135, | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | static int __init init_rc_map_gotview7135(void) | ||
66 | { | ||
67 | return ir_register_map(&gotview7135_map); | ||
68 | } | ||
69 | |||
70 | static void __exit exit_rc_map_gotview7135(void) | ||
71 | { | ||
72 | ir_unregister_map(&gotview7135_map); | ||
73 | } | ||
74 | |||
75 | module_init(init_rc_map_gotview7135) | ||
76 | module_exit(exit_rc_map_gotview7135) | ||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
79 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-hauppauge-new.c b/drivers/media/IR/keymaps/rc-hauppauge-new.c new file mode 100644 index 000000000000..c6f8cd7c5186 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-hauppauge-new.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* hauppauge-new.h - Keytable for hauppauge_new Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Hauppauge: the newer, gray remotes (seems there are multiple | ||
16 | * slightly different versions), shipped with cx88+ivtv cards. | ||
17 | * almost rc5 coding, but some non-standard keys */ | ||
18 | |||
19 | static struct ir_scancode hauppauge_new[] = { | ||
20 | /* Keys 0 to 9 */ | ||
21 | { 0x00, KEY_0 }, | ||
22 | { 0x01, KEY_1 }, | ||
23 | { 0x02, KEY_2 }, | ||
24 | { 0x03, KEY_3 }, | ||
25 | { 0x04, KEY_4 }, | ||
26 | { 0x05, KEY_5 }, | ||
27 | { 0x06, KEY_6 }, | ||
28 | { 0x07, KEY_7 }, | ||
29 | { 0x08, KEY_8 }, | ||
30 | { 0x09, KEY_9 }, | ||
31 | |||
32 | { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
33 | { 0x0b, KEY_RED }, /* red button */ | ||
34 | { 0x0c, KEY_RADIO }, | ||
35 | { 0x0d, KEY_MENU }, | ||
36 | { 0x0e, KEY_SUBTITLE }, /* also the # key */ | ||
37 | { 0x0f, KEY_MUTE }, | ||
38 | { 0x10, KEY_VOLUMEUP }, | ||
39 | { 0x11, KEY_VOLUMEDOWN }, | ||
40 | { 0x12, KEY_PREVIOUS }, /* previous channel */ | ||
41 | { 0x14, KEY_UP }, | ||
42 | { 0x15, KEY_DOWN }, | ||
43 | { 0x16, KEY_LEFT }, | ||
44 | { 0x17, KEY_RIGHT }, | ||
45 | { 0x18, KEY_VIDEO }, /* Videos */ | ||
46 | { 0x19, KEY_AUDIO }, /* Music */ | ||
47 | /* 0x1a: Pictures - presume this means | ||
48 | "Multimedia Home Platform" - | ||
49 | no "PICTURES" key in input.h | ||
50 | */ | ||
51 | { 0x1a, KEY_MHP }, | ||
52 | |||
53 | { 0x1b, KEY_EPG }, /* Guide */ | ||
54 | { 0x1c, KEY_TV }, | ||
55 | { 0x1e, KEY_NEXTSONG }, /* skip >| */ | ||
56 | { 0x1f, KEY_EXIT }, /* back/exit */ | ||
57 | { 0x20, KEY_CHANNELUP }, /* channel / program + */ | ||
58 | { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
59 | { 0x22, KEY_CHANNEL }, /* source (old black remote) */ | ||
60 | { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
61 | { 0x25, KEY_ENTER }, /* OK */ | ||
62 | { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
63 | { 0x29, KEY_BLUE }, /* blue key */ | ||
64 | { 0x2e, KEY_GREEN }, /* green button */ | ||
65 | { 0x30, KEY_PAUSE }, /* pause */ | ||
66 | { 0x32, KEY_REWIND }, /* backward << */ | ||
67 | { 0x34, KEY_FASTFORWARD }, /* forward >> */ | ||
68 | { 0x35, KEY_PLAY }, | ||
69 | { 0x36, KEY_STOP }, | ||
70 | { 0x37, KEY_RECORD }, /* recording */ | ||
71 | { 0x38, KEY_YELLOW }, /* yellow key */ | ||
72 | { 0x3b, KEY_SELECT }, /* top right button */ | ||
73 | { 0x3c, KEY_ZOOM }, /* full */ | ||
74 | { 0x3d, KEY_POWER }, /* system power (green button) */ | ||
75 | }; | ||
76 | |||
77 | static struct rc_keymap hauppauge_new_map = { | ||
78 | .map = { | ||
79 | .scan = hauppauge_new, | ||
80 | .size = ARRAY_SIZE(hauppauge_new), | ||
81 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
82 | .name = RC_MAP_HAUPPAUGE_NEW, | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | static int __init init_rc_map_hauppauge_new(void) | ||
87 | { | ||
88 | return ir_register_map(&hauppauge_new_map); | ||
89 | } | ||
90 | |||
91 | static void __exit exit_rc_map_hauppauge_new(void) | ||
92 | { | ||
93 | ir_unregister_map(&hauppauge_new_map); | ||
94 | } | ||
95 | |||
96 | module_init(init_rc_map_hauppauge_new) | ||
97 | module_exit(exit_rc_map_hauppauge_new) | ||
98 | |||
99 | MODULE_LICENSE("GPL"); | ||
100 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c new file mode 100644 index 000000000000..e49f350e3a0d --- /dev/null +++ b/drivers/media/IR/keymaps/rc-imon-mce.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use | ||
2 | * with the SoundGraph iMON/Antec Veris hardware IR decoder | ||
3 | * | ||
4 | * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <media/rc-map.h> | ||
13 | |||
14 | /* mce-mode imon mce remote key table */ | ||
15 | static struct ir_scancode imon_mce[] = { | ||
16 | /* keys sorted mostly by frequency of use to optimize lookups */ | ||
17 | { 0x800ff415, KEY_REWIND }, | ||
18 | { 0x800ff414, KEY_FASTFORWARD }, | ||
19 | { 0x800ff41b, KEY_PREVIOUS }, | ||
20 | { 0x800ff41a, KEY_NEXT }, | ||
21 | |||
22 | { 0x800ff416, KEY_PLAY }, | ||
23 | { 0x800ff418, KEY_PAUSE }, | ||
24 | { 0x800ff419, KEY_STOP }, | ||
25 | { 0x800ff417, KEY_RECORD }, | ||
26 | |||
27 | { 0x02000052, KEY_UP }, | ||
28 | { 0x02000051, KEY_DOWN }, | ||
29 | { 0x02000050, KEY_LEFT }, | ||
30 | { 0x0200004f, KEY_RIGHT }, | ||
31 | |||
32 | { 0x800ff41e, KEY_UP }, | ||
33 | { 0x800ff41f, KEY_DOWN }, | ||
34 | { 0x800ff420, KEY_LEFT }, | ||
35 | { 0x800ff421, KEY_RIGHT }, | ||
36 | |||
37 | /* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */ | ||
38 | { 0x800ff40b, KEY_ENTER }, | ||
39 | { 0x02000028, KEY_ENTER }, | ||
40 | /* the OK and Enter buttons decode to the same value on some remotes | ||
41 | { 0x02000028, KEY_OK }, */ | ||
42 | { 0x800ff422, KEY_OK }, | ||
43 | { 0x0200002a, KEY_EXIT }, | ||
44 | { 0x800ff423, KEY_EXIT }, | ||
45 | { 0x02000029, KEY_DELETE }, | ||
46 | /* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */ | ||
47 | { 0x800ff40a, KEY_DELETE }, | ||
48 | |||
49 | { 0x800ff40e, KEY_MUTE }, | ||
50 | { 0x800ff410, KEY_VOLUMEUP }, | ||
51 | { 0x800ff411, KEY_VOLUMEDOWN }, | ||
52 | { 0x800ff412, KEY_CHANNELUP }, | ||
53 | { 0x800ff413, KEY_CHANNELDOWN }, | ||
54 | |||
55 | { 0x0200001e, KEY_NUMERIC_1 }, | ||
56 | { 0x0200001f, KEY_NUMERIC_2 }, | ||
57 | { 0x02000020, KEY_NUMERIC_3 }, | ||
58 | { 0x02000021, KEY_NUMERIC_4 }, | ||
59 | { 0x02000022, KEY_NUMERIC_5 }, | ||
60 | { 0x02000023, KEY_NUMERIC_6 }, | ||
61 | { 0x02000024, KEY_NUMERIC_7 }, | ||
62 | { 0x02000025, KEY_NUMERIC_8 }, | ||
63 | { 0x02000026, KEY_NUMERIC_9 }, | ||
64 | { 0x02000027, KEY_NUMERIC_0 }, | ||
65 | |||
66 | { 0x800ff401, KEY_NUMERIC_1 }, | ||
67 | { 0x800ff402, KEY_NUMERIC_2 }, | ||
68 | { 0x800ff403, KEY_NUMERIC_3 }, | ||
69 | { 0x800ff404, KEY_NUMERIC_4 }, | ||
70 | { 0x800ff405, KEY_NUMERIC_5 }, | ||
71 | { 0x800ff406, KEY_NUMERIC_6 }, | ||
72 | { 0x800ff407, KEY_NUMERIC_7 }, | ||
73 | { 0x800ff408, KEY_NUMERIC_8 }, | ||
74 | { 0x800ff409, KEY_NUMERIC_9 }, | ||
75 | { 0x800ff400, KEY_NUMERIC_0 }, | ||
76 | |||
77 | { 0x02200025, KEY_NUMERIC_STAR }, | ||
78 | { 0x02200020, KEY_NUMERIC_POUND }, | ||
79 | /* 0x800ff41d also KEY_BLUE on some receivers */ | ||
80 | { 0x800ff41d, KEY_NUMERIC_STAR }, | ||
81 | /* 0x800ff41c also KEY_PREVIOUS on some receivers */ | ||
82 | { 0x800ff41c, KEY_NUMERIC_POUND }, | ||
83 | |||
84 | { 0x800ff446, KEY_TV }, | ||
85 | { 0x800ff447, KEY_AUDIO }, /* My Music */ | ||
86 | { 0x800ff448, KEY_PVR }, /* RecordedTV */ | ||
87 | { 0x800ff449, KEY_CAMERA }, | ||
88 | { 0x800ff44a, KEY_VIDEO }, | ||
89 | /* 0x800ff424 also KEY_MENU on some receivers */ | ||
90 | { 0x800ff424, KEY_DVD }, | ||
91 | /* 0x800ff425 also KEY_GREEN on some receivers */ | ||
92 | { 0x800ff425, KEY_TUNER }, /* LiveTV */ | ||
93 | { 0x800ff450, KEY_RADIO }, | ||
94 | |||
95 | { 0x800ff44c, KEY_LANGUAGE }, | ||
96 | { 0x800ff427, KEY_ZOOM }, /* Aspect */ | ||
97 | |||
98 | { 0x800ff45b, KEY_RED }, | ||
99 | { 0x800ff45c, KEY_GREEN }, | ||
100 | { 0x800ff45d, KEY_YELLOW }, | ||
101 | { 0x800ff45e, KEY_BLUE }, | ||
102 | |||
103 | { 0x800ff466, KEY_RED }, | ||
104 | /* { 0x800ff425, KEY_GREEN }, */ | ||
105 | { 0x800ff468, KEY_YELLOW }, | ||
106 | /* { 0x800ff41d, KEY_BLUE }, */ | ||
107 | |||
108 | { 0x800ff40f, KEY_INFO }, | ||
109 | { 0x800ff426, KEY_EPG }, /* Guide */ | ||
110 | { 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */ | ||
111 | { 0x800ff44d, KEY_TITLE }, | ||
112 | |||
113 | { 0x800ff40c, KEY_POWER }, | ||
114 | { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ | ||
115 | |||
116 | }; | ||
117 | |||
118 | static struct rc_keymap imon_mce_map = { | ||
119 | .map = { | ||
120 | .scan = imon_mce, | ||
121 | .size = ARRAY_SIZE(imon_mce), | ||
122 | /* its RC6, but w/a hardware decoder */ | ||
123 | .ir_type = IR_TYPE_RC6, | ||
124 | .name = RC_MAP_IMON_MCE, | ||
125 | } | ||
126 | }; | ||
127 | |||
128 | static int __init init_rc_map_imon_mce(void) | ||
129 | { | ||
130 | return ir_register_map(&imon_mce_map); | ||
131 | } | ||
132 | |||
133 | static void __exit exit_rc_map_imon_mce(void) | ||
134 | { | ||
135 | ir_unregister_map(&imon_mce_map); | ||
136 | } | ||
137 | |||
138 | module_init(init_rc_map_imon_mce) | ||
139 | module_exit(exit_rc_map_imon_mce) | ||
140 | |||
141 | MODULE_LICENSE("GPL"); | ||
142 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c new file mode 100644 index 000000000000..bc4db72f02e6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-imon-pad.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris | ||
2 | * RM-200 Remote Control | ||
3 | * | ||
4 | * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.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 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <media/rc-map.h> | ||
13 | |||
14 | /* | ||
15 | * standard imon remote key table, which isn't really entirely | ||
16 | * "standard", as different receivers decode the same key on the | ||
17 | * same remote to different hex codes, and the silkscreened names | ||
18 | * vary a bit between the SoundGraph and Antec remotes... ugh. | ||
19 | */ | ||
20 | static struct ir_scancode imon_pad[] = { | ||
21 | /* keys sorted mostly by frequency of use to optimize lookups */ | ||
22 | { 0x2a8195b7, KEY_REWIND }, | ||
23 | { 0x298315b7, KEY_REWIND }, | ||
24 | { 0x2b8115b7, KEY_FASTFORWARD }, | ||
25 | { 0x2b8315b7, KEY_FASTFORWARD }, | ||
26 | { 0x2b9115b7, KEY_PREVIOUS }, | ||
27 | { 0x298195b7, KEY_NEXT }, | ||
28 | |||
29 | { 0x2a8115b7, KEY_PLAY }, | ||
30 | { 0x2a8315b7, KEY_PLAY }, | ||
31 | { 0x2a9115b7, KEY_PAUSE }, | ||
32 | { 0x2b9715b7, KEY_STOP }, | ||
33 | { 0x298115b7, KEY_RECORD }, | ||
34 | |||
35 | { 0x01008000, KEY_UP }, | ||
36 | { 0x01007f00, KEY_DOWN }, | ||
37 | { 0x01000080, KEY_LEFT }, | ||
38 | { 0x0100007f, KEY_RIGHT }, | ||
39 | |||
40 | { 0x2aa515b7, KEY_UP }, | ||
41 | { 0x289515b7, KEY_DOWN }, | ||
42 | { 0x29a515b7, KEY_LEFT }, | ||
43 | { 0x2ba515b7, KEY_RIGHT }, | ||
44 | |||
45 | { 0x0200002c, KEY_SPACE }, /* Select/Space */ | ||
46 | { 0x2a9315b7, KEY_SPACE }, /* Select/Space */ | ||
47 | { 0x02000028, KEY_ENTER }, | ||
48 | { 0x28a195b7, KEY_ENTER }, | ||
49 | { 0x288195b7, KEY_EXIT }, | ||
50 | { 0x02000029, KEY_ESC }, | ||
51 | { 0x2bb715b7, KEY_ESC }, | ||
52 | { 0x0200002a, KEY_BACKSPACE }, | ||
53 | { 0x28a115b7, KEY_BACKSPACE }, | ||
54 | |||
55 | { 0x2b9595b7, KEY_MUTE }, | ||
56 | { 0x28a395b7, KEY_VOLUMEUP }, | ||
57 | { 0x28a595b7, KEY_VOLUMEDOWN }, | ||
58 | { 0x289395b7, KEY_CHANNELUP }, | ||
59 | { 0x288795b7, KEY_CHANNELDOWN }, | ||
60 | |||
61 | { 0x0200001e, KEY_NUMERIC_1 }, | ||
62 | { 0x0200001f, KEY_NUMERIC_2 }, | ||
63 | { 0x02000020, KEY_NUMERIC_3 }, | ||
64 | { 0x02000021, KEY_NUMERIC_4 }, | ||
65 | { 0x02000022, KEY_NUMERIC_5 }, | ||
66 | { 0x02000023, KEY_NUMERIC_6 }, | ||
67 | { 0x02000024, KEY_NUMERIC_7 }, | ||
68 | { 0x02000025, KEY_NUMERIC_8 }, | ||
69 | { 0x02000026, KEY_NUMERIC_9 }, | ||
70 | { 0x02000027, KEY_NUMERIC_0 }, | ||
71 | |||
72 | { 0x28b595b7, KEY_NUMERIC_1 }, | ||
73 | { 0x2bb195b7, KEY_NUMERIC_2 }, | ||
74 | { 0x28b195b7, KEY_NUMERIC_3 }, | ||
75 | { 0x2a8595b7, KEY_NUMERIC_4 }, | ||
76 | { 0x299595b7, KEY_NUMERIC_5 }, | ||
77 | { 0x2aa595b7, KEY_NUMERIC_6 }, | ||
78 | { 0x2b9395b7, KEY_NUMERIC_7 }, | ||
79 | { 0x2a8515b7, KEY_NUMERIC_8 }, | ||
80 | { 0x2aa115b7, KEY_NUMERIC_9 }, | ||
81 | { 0x2ba595b7, KEY_NUMERIC_0 }, | ||
82 | |||
83 | { 0x02200025, KEY_NUMERIC_STAR }, | ||
84 | { 0x28b515b7, KEY_NUMERIC_STAR }, | ||
85 | { 0x02200020, KEY_NUMERIC_POUND }, | ||
86 | { 0x29a115b7, KEY_NUMERIC_POUND }, | ||
87 | |||
88 | { 0x2b8515b7, KEY_VIDEO }, | ||
89 | { 0x299195b7, KEY_AUDIO }, | ||
90 | { 0x2ba115b7, KEY_CAMERA }, | ||
91 | { 0x28a515b7, KEY_TV }, | ||
92 | { 0x29a395b7, KEY_DVD }, | ||
93 | { 0x29a295b7, KEY_DVD }, | ||
94 | |||
95 | /* the Menu key between DVD and Subtitle on the RM-200... */ | ||
96 | { 0x2ba385b7, KEY_MENU }, | ||
97 | { 0x2ba395b7, KEY_MENU }, | ||
98 | |||
99 | { 0x288515b7, KEY_BOOKMARKS }, | ||
100 | { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ | ||
101 | { 0x298595b7, KEY_SUBTITLE }, | ||
102 | { 0x2b8595b7, KEY_LANGUAGE }, | ||
103 | |||
104 | { 0x29a595b7, KEY_ZOOM }, | ||
105 | { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */ | ||
106 | |||
107 | { 0x299115b7, KEY_KEYBOARD }, | ||
108 | { 0x299135b7, KEY_KEYBOARD }, | ||
109 | |||
110 | { 0x01010000, BTN_LEFT }, | ||
111 | { 0x01020000, BTN_RIGHT }, | ||
112 | { 0x01010080, BTN_LEFT }, | ||
113 | { 0x01020080, BTN_RIGHT }, | ||
114 | { 0x688301b7, BTN_LEFT }, | ||
115 | { 0x688481b7, BTN_RIGHT }, | ||
116 | |||
117 | { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */ | ||
118 | { 0x2b8395b7, KEY_TIME }, /* Timer */ | ||
119 | |||
120 | { 0x289115b7, KEY_POWER }, | ||
121 | { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */ | ||
122 | { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */ | ||
123 | |||
124 | { 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */ | ||
125 | { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ | ||
126 | { 0x02000065, KEY_COMPOSE }, /* RightMenu */ | ||
127 | { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ | ||
128 | { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ | ||
129 | { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ | ||
130 | }; | ||
131 | |||
132 | static struct rc_keymap imon_pad_map = { | ||
133 | .map = { | ||
134 | .scan = imon_pad, | ||
135 | .size = ARRAY_SIZE(imon_pad), | ||
136 | /* actual protocol details unknown, hardware decoder */ | ||
137 | .ir_type = IR_TYPE_OTHER, | ||
138 | .name = RC_MAP_IMON_PAD, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | static int __init init_rc_map_imon_pad(void) | ||
143 | { | ||
144 | return ir_register_map(&imon_pad_map); | ||
145 | } | ||
146 | |||
147 | static void __exit exit_rc_map_imon_pad(void) | ||
148 | { | ||
149 | ir_unregister_map(&imon_pad_map); | ||
150 | } | ||
151 | |||
152 | module_init(init_rc_map_imon_pad) | ||
153 | module_exit(exit_rc_map_imon_pad) | ||
154 | |||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c new file mode 100644 index 000000000000..ef6600259fc0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* IO-DATA BCTV7E Remote */ | ||
16 | |||
17 | static struct ir_scancode iodata_bctv7e[] = { | ||
18 | { 0x40, KEY_TV }, | ||
19 | { 0x20, KEY_RADIO }, /* FM */ | ||
20 | { 0x60, KEY_EPG }, | ||
21 | { 0x00, KEY_POWER }, | ||
22 | |||
23 | /* Keys 0 to 9 */ | ||
24 | { 0x44, KEY_0 }, /* 10 */ | ||
25 | { 0x50, KEY_1 }, | ||
26 | { 0x30, KEY_2 }, | ||
27 | { 0x70, KEY_3 }, | ||
28 | { 0x48, KEY_4 }, | ||
29 | { 0x28, KEY_5 }, | ||
30 | { 0x68, KEY_6 }, | ||
31 | { 0x58, KEY_7 }, | ||
32 | { 0x38, KEY_8 }, | ||
33 | { 0x78, KEY_9 }, | ||
34 | |||
35 | { 0x10, KEY_L }, /* Live */ | ||
36 | { 0x08, KEY_TIME }, /* Time Shift */ | ||
37 | |||
38 | { 0x18, KEY_PLAYPAUSE }, /* Play */ | ||
39 | |||
40 | { 0x24, KEY_ENTER }, /* 11 */ | ||
41 | { 0x64, KEY_ESC }, /* 12 */ | ||
42 | { 0x04, KEY_M }, /* Multi */ | ||
43 | |||
44 | { 0x54, KEY_VIDEO }, | ||
45 | { 0x34, KEY_CHANNELUP }, | ||
46 | { 0x74, KEY_VOLUMEUP }, | ||
47 | { 0x14, KEY_MUTE }, | ||
48 | |||
49 | { 0x4c, KEY_VCR }, /* SVIDEO */ | ||
50 | { 0x2c, KEY_CHANNELDOWN }, | ||
51 | { 0x6c, KEY_VOLUMEDOWN }, | ||
52 | { 0x0c, KEY_ZOOM }, | ||
53 | |||
54 | { 0x5c, KEY_PAUSE }, | ||
55 | { 0x3c, KEY_RED }, /* || (red) */ | ||
56 | { 0x7c, KEY_RECORD }, /* recording */ | ||
57 | { 0x1c, KEY_STOP }, | ||
58 | |||
59 | { 0x41, KEY_REWIND }, /* backward << */ | ||
60 | { 0x21, KEY_PLAY }, | ||
61 | { 0x61, KEY_FASTFORWARD }, /* forward >> */ | ||
62 | { 0x01, KEY_NEXT }, /* skip >| */ | ||
63 | }; | ||
64 | |||
65 | static struct rc_keymap iodata_bctv7e_map = { | ||
66 | .map = { | ||
67 | .scan = iodata_bctv7e, | ||
68 | .size = ARRAY_SIZE(iodata_bctv7e), | ||
69 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
70 | .name = RC_MAP_IODATA_BCTV7E, | ||
71 | } | ||
72 | }; | ||
73 | |||
74 | static int __init init_rc_map_iodata_bctv7e(void) | ||
75 | { | ||
76 | return ir_register_map(&iodata_bctv7e_map); | ||
77 | } | ||
78 | |||
79 | static void __exit exit_rc_map_iodata_bctv7e(void) | ||
80 | { | ||
81 | ir_unregister_map(&iodata_bctv7e_map); | ||
82 | } | ||
83 | |||
84 | module_init(init_rc_map_iodata_bctv7e) | ||
85 | module_exit(exit_rc_map_iodata_bctv7e) | ||
86 | |||
87 | MODULE_LICENSE("GPL"); | ||
88 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-kaiomy.c b/drivers/media/IR/keymaps/rc-kaiomy.c new file mode 100644 index 000000000000..4c7883ba0f15 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kaiomy.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* kaiomy.h - Keytable for kaiomy Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Kaiomy TVnPC U2 | ||
16 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode kaiomy[] = { | ||
20 | { 0x43, KEY_POWER2}, | ||
21 | { 0x01, KEY_LIST}, | ||
22 | { 0x0b, KEY_ZOOM}, | ||
23 | { 0x03, KEY_POWER}, | ||
24 | |||
25 | { 0x04, KEY_1}, | ||
26 | { 0x08, KEY_2}, | ||
27 | { 0x02, KEY_3}, | ||
28 | |||
29 | { 0x0f, KEY_4}, | ||
30 | { 0x05, KEY_5}, | ||
31 | { 0x06, KEY_6}, | ||
32 | |||
33 | { 0x0c, KEY_7}, | ||
34 | { 0x0d, KEY_8}, | ||
35 | { 0x0a, KEY_9}, | ||
36 | |||
37 | { 0x11, KEY_0}, | ||
38 | |||
39 | { 0x09, KEY_CHANNELUP}, | ||
40 | { 0x07, KEY_CHANNELDOWN}, | ||
41 | |||
42 | { 0x0e, KEY_VOLUMEUP}, | ||
43 | { 0x13, KEY_VOLUMEDOWN}, | ||
44 | |||
45 | { 0x10, KEY_HOME}, | ||
46 | { 0x12, KEY_ENTER}, | ||
47 | |||
48 | { 0x14, KEY_RECORD}, | ||
49 | { 0x15, KEY_STOP}, | ||
50 | { 0x16, KEY_PLAY}, | ||
51 | { 0x17, KEY_MUTE}, | ||
52 | |||
53 | { 0x18, KEY_UP}, | ||
54 | { 0x19, KEY_DOWN}, | ||
55 | { 0x1a, KEY_LEFT}, | ||
56 | { 0x1b, KEY_RIGHT}, | ||
57 | |||
58 | { 0x1c, KEY_RED}, | ||
59 | { 0x1d, KEY_GREEN}, | ||
60 | { 0x1e, KEY_YELLOW}, | ||
61 | { 0x1f, KEY_BLUE}, | ||
62 | }; | ||
63 | |||
64 | static struct rc_keymap kaiomy_map = { | ||
65 | .map = { | ||
66 | .scan = kaiomy, | ||
67 | .size = ARRAY_SIZE(kaiomy), | ||
68 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
69 | .name = RC_MAP_KAIOMY, | ||
70 | } | ||
71 | }; | ||
72 | |||
73 | static int __init init_rc_map_kaiomy(void) | ||
74 | { | ||
75 | return ir_register_map(&kaiomy_map); | ||
76 | } | ||
77 | |||
78 | static void __exit exit_rc_map_kaiomy(void) | ||
79 | { | ||
80 | ir_unregister_map(&kaiomy_map); | ||
81 | } | ||
82 | |||
83 | module_init(init_rc_map_kaiomy) | ||
84 | module_exit(exit_rc_map_kaiomy) | ||
85 | |||
86 | MODULE_LICENSE("GPL"); | ||
87 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-kworld-315u.c b/drivers/media/IR/keymaps/rc-kworld-315u.c new file mode 100644 index 000000000000..618c817374e6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kworld-315u.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* kworld-315u.h - Keytable for kworld_315u Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Kworld 315U | ||
16 | */ | ||
17 | |||
18 | static struct ir_scancode kworld_315u[] = { | ||
19 | { 0x6143, KEY_POWER }, | ||
20 | { 0x6101, KEY_TUNER }, /* source */ | ||
21 | { 0x610b, KEY_ZOOM }, | ||
22 | { 0x6103, KEY_POWER2 }, /* shutdown */ | ||
23 | |||
24 | { 0x6104, KEY_1 }, | ||
25 | { 0x6108, KEY_2 }, | ||
26 | { 0x6102, KEY_3 }, | ||
27 | { 0x6109, KEY_CHANNELUP }, | ||
28 | |||
29 | { 0x610f, KEY_4 }, | ||
30 | { 0x6105, KEY_5 }, | ||
31 | { 0x6106, KEY_6 }, | ||
32 | { 0x6107, KEY_CHANNELDOWN }, | ||
33 | |||
34 | { 0x610c, KEY_7 }, | ||
35 | { 0x610d, KEY_8 }, | ||
36 | { 0x610a, KEY_9 }, | ||
37 | { 0x610e, KEY_VOLUMEUP }, | ||
38 | |||
39 | { 0x6110, KEY_LAST }, | ||
40 | { 0x6111, KEY_0 }, | ||
41 | { 0x6112, KEY_ENTER }, | ||
42 | { 0x6113, KEY_VOLUMEDOWN }, | ||
43 | |||
44 | { 0x6114, KEY_RECORD }, | ||
45 | { 0x6115, KEY_STOP }, | ||
46 | { 0x6116, KEY_PLAY }, | ||
47 | { 0x6117, KEY_MUTE }, | ||
48 | |||
49 | { 0x6118, KEY_UP }, | ||
50 | { 0x6119, KEY_DOWN }, | ||
51 | { 0x611a, KEY_LEFT }, | ||
52 | { 0x611b, KEY_RIGHT }, | ||
53 | |||
54 | { 0x611c, KEY_RED }, | ||
55 | { 0x611d, KEY_GREEN }, | ||
56 | { 0x611e, KEY_YELLOW }, | ||
57 | { 0x611f, KEY_BLUE }, | ||
58 | }; | ||
59 | |||
60 | static struct rc_keymap kworld_315u_map = { | ||
61 | .map = { | ||
62 | .scan = kworld_315u, | ||
63 | .size = ARRAY_SIZE(kworld_315u), | ||
64 | .ir_type = IR_TYPE_NEC, | ||
65 | .name = RC_MAP_KWORLD_315U, | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | static int __init init_rc_map_kworld_315u(void) | ||
70 | { | ||
71 | return ir_register_map(&kworld_315u_map); | ||
72 | } | ||
73 | |||
74 | static void __exit exit_rc_map_kworld_315u(void) | ||
75 | { | ||
76 | ir_unregister_map(&kworld_315u_map); | ||
77 | } | ||
78 | |||
79 | module_init(init_rc_map_kworld_315u) | ||
80 | module_exit(exit_rc_map_kworld_315u) | ||
81 | |||
82 | MODULE_LICENSE("GPL"); | ||
83 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c new file mode 100644 index 000000000000..366732f1f7b7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Kworld Plus TV Analog Lite PCI IR | ||
16 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode kworld_plus_tv_analog[] = { | ||
20 | { 0x0c, KEY_PROG1 }, /* Kworld key */ | ||
21 | { 0x16, KEY_CLOSECD }, /* -> ) */ | ||
22 | { 0x1d, KEY_POWER2 }, | ||
23 | |||
24 | { 0x00, KEY_1 }, | ||
25 | { 0x01, KEY_2 }, | ||
26 | { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ | ||
27 | { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ | ||
28 | { 0x04, KEY_5 }, | ||
29 | { 0x05, KEY_6 }, | ||
30 | { 0x06, KEY_7 }, | ||
31 | { 0x07, KEY_8 }, | ||
32 | { 0x08, KEY_9 }, | ||
33 | { 0x0a, KEY_0 }, | ||
34 | |||
35 | { 0x09, KEY_AGAIN }, | ||
36 | { 0x14, KEY_MUTE }, | ||
37 | |||
38 | { 0x20, KEY_UP }, | ||
39 | { 0x21, KEY_DOWN }, | ||
40 | { 0x0b, KEY_ENTER }, | ||
41 | |||
42 | { 0x10, KEY_CHANNELUP }, | ||
43 | { 0x11, KEY_CHANNELDOWN }, | ||
44 | |||
45 | /* Couldn't map key left/key right since those | ||
46 | conflict with '3' and '4' scancodes | ||
47 | I dunno what the original driver does | ||
48 | */ | ||
49 | |||
50 | { 0x13, KEY_VOLUMEUP }, | ||
51 | { 0x12, KEY_VOLUMEDOWN }, | ||
52 | |||
53 | /* The lower part of the IR | ||
54 | There are several duplicated keycodes there. | ||
55 | Most of them conflict with digits. | ||
56 | Add mappings just to the unused scancodes. | ||
57 | Somehow, the original driver has a way to know, | ||
58 | but this doesn't seem to be on some GPIO. | ||
59 | Also, it is not related to the time between keyup | ||
60 | and keydown. | ||
61 | */ | ||
62 | { 0x19, KEY_TIME}, /* Timeshift */ | ||
63 | { 0x1a, KEY_STOP}, | ||
64 | { 0x1b, KEY_RECORD}, | ||
65 | |||
66 | { 0x22, KEY_TEXT}, | ||
67 | |||
68 | { 0x15, KEY_AUDIO}, /* ((*)) */ | ||
69 | { 0x0f, KEY_ZOOM}, | ||
70 | { 0x1c, KEY_CAMERA}, /* snapshot */ | ||
71 | |||
72 | { 0x18, KEY_RED}, /* B */ | ||
73 | { 0x23, KEY_GREEN}, /* C */ | ||
74 | }; | ||
75 | |||
76 | static struct rc_keymap kworld_plus_tv_analog_map = { | ||
77 | .map = { | ||
78 | .scan = kworld_plus_tv_analog, | ||
79 | .size = ARRAY_SIZE(kworld_plus_tv_analog), | ||
80 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
81 | .name = RC_MAP_KWORLD_PLUS_TV_ANALOG, | ||
82 | } | ||
83 | }; | ||
84 | |||
85 | static int __init init_rc_map_kworld_plus_tv_analog(void) | ||
86 | { | ||
87 | return ir_register_map(&kworld_plus_tv_analog_map); | ||
88 | } | ||
89 | |||
90 | static void __exit exit_rc_map_kworld_plus_tv_analog(void) | ||
91 | { | ||
92 | ir_unregister_map(&kworld_plus_tv_analog_map); | ||
93 | } | ||
94 | |||
95 | module_init(init_rc_map_kworld_plus_tv_analog) | ||
96 | module_exit(exit_rc_map_kworld_plus_tv_analog) | ||
97 | |||
98 | MODULE_LICENSE("GPL"); | ||
99 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-manli.c b/drivers/media/IR/keymaps/rc-manli.c new file mode 100644 index 000000000000..1e9fbfa90a1e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-manli.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* manli.h - Keytable for manli Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Michael Tokarev <mjt@tls.msk.ru> | ||
16 | http://www.corpit.ru/mjt/beholdTV/remote_control.jpg | ||
17 | keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at | ||
18 | least, and probably other cards too. | ||
19 | The "ascii-art picture" below (in comments, first row | ||
20 | is the keycode in hex, and subsequent row(s) shows | ||
21 | the button labels (several variants when appropriate) | ||
22 | helps to descide which keycodes to assign to the buttons. | ||
23 | */ | ||
24 | |||
25 | static struct ir_scancode manli[] = { | ||
26 | |||
27 | /* 0x1c 0x12 * | ||
28 | * FUNCTION POWER * | ||
29 | * FM (|) * | ||
30 | * */ | ||
31 | { 0x1c, KEY_RADIO }, /*XXX*/ | ||
32 | { 0x12, KEY_POWER }, | ||
33 | |||
34 | /* 0x01 0x02 0x03 * | ||
35 | * 1 2 3 * | ||
36 | * * | ||
37 | * 0x04 0x05 0x06 * | ||
38 | * 4 5 6 * | ||
39 | * * | ||
40 | * 0x07 0x08 0x09 * | ||
41 | * 7 8 9 * | ||
42 | * */ | ||
43 | { 0x01, KEY_1 }, | ||
44 | { 0x02, KEY_2 }, | ||
45 | { 0x03, KEY_3 }, | ||
46 | { 0x04, KEY_4 }, | ||
47 | { 0x05, KEY_5 }, | ||
48 | { 0x06, KEY_6 }, | ||
49 | { 0x07, KEY_7 }, | ||
50 | { 0x08, KEY_8 }, | ||
51 | { 0x09, KEY_9 }, | ||
52 | |||
53 | /* 0x0a 0x00 0x17 * | ||
54 | * RECALL 0 +100 * | ||
55 | * PLUS * | ||
56 | * */ | ||
57 | { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ | ||
58 | { 0x00, KEY_0 }, | ||
59 | { 0x17, KEY_DIGITS }, /*XXX*/ | ||
60 | |||
61 | /* 0x14 0x10 * | ||
62 | * MENU INFO * | ||
63 | * OSD */ | ||
64 | { 0x14, KEY_MENU }, | ||
65 | { 0x10, KEY_INFO }, | ||
66 | |||
67 | /* 0x0b * | ||
68 | * Up * | ||
69 | * * | ||
70 | * 0x18 0x16 0x0c * | ||
71 | * Left Ok Right * | ||
72 | * * | ||
73 | * 0x015 * | ||
74 | * Down * | ||
75 | * */ | ||
76 | { 0x0b, KEY_UP }, | ||
77 | { 0x18, KEY_LEFT }, | ||
78 | { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ | ||
79 | { 0x0c, KEY_RIGHT }, | ||
80 | { 0x15, KEY_DOWN }, | ||
81 | |||
82 | /* 0x11 0x0d * | ||
83 | * TV/AV MODE * | ||
84 | * SOURCE STEREO * | ||
85 | * */ | ||
86 | { 0x11, KEY_TV }, /*XXX*/ | ||
87 | { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ | ||
88 | |||
89 | /* 0x0f 0x1b 0x1a * | ||
90 | * AUDIO Vol+ Chan+ * | ||
91 | * TIMESHIFT??? * | ||
92 | * * | ||
93 | * 0x0e 0x1f 0x1e * | ||
94 | * SLEEP Vol- Chan- * | ||
95 | * */ | ||
96 | { 0x0f, KEY_AUDIO }, | ||
97 | { 0x1b, KEY_VOLUMEUP }, | ||
98 | { 0x1a, KEY_CHANNELUP }, | ||
99 | { 0x0e, KEY_TIME }, | ||
100 | { 0x1f, KEY_VOLUMEDOWN }, | ||
101 | { 0x1e, KEY_CHANNELDOWN }, | ||
102 | |||
103 | /* 0x13 0x19 * | ||
104 | * MUTE SNAPSHOT* | ||
105 | * */ | ||
106 | { 0x13, KEY_MUTE }, | ||
107 | { 0x19, KEY_CAMERA }, | ||
108 | |||
109 | /* 0x1d unused ? */ | ||
110 | }; | ||
111 | |||
112 | static struct rc_keymap manli_map = { | ||
113 | .map = { | ||
114 | .scan = manli, | ||
115 | .size = ARRAY_SIZE(manli), | ||
116 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
117 | .name = RC_MAP_MANLI, | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | static int __init init_rc_map_manli(void) | ||
122 | { | ||
123 | return ir_register_map(&manli_map); | ||
124 | } | ||
125 | |||
126 | static void __exit exit_rc_map_manli(void) | ||
127 | { | ||
128 | ir_unregister_map(&manli_map); | ||
129 | } | ||
130 | |||
131 | module_init(init_rc_map_manli) | ||
132 | module_exit(exit_rc_map_manli) | ||
133 | |||
134 | MODULE_LICENSE("GPL"); | ||
135 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c new file mode 100644 index 000000000000..eb8e42c18ff9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card | ||
17 | is marked "KS003". The controller is I2C at address 0x30, but does not seem | ||
18 | to respond to probes until a read is performed from a valid device. | ||
19 | I don't know why... | ||
20 | |||
21 | Note: This remote may be of similar or identical design to the | ||
22 | Pixelview remote (?). The raw codes and duplicate button codes | ||
23 | appear to be the same. | ||
24 | |||
25 | Henry Wong <henry@stuffedcow.net> | ||
26 | Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com> | ||
27 | */ | ||
28 | |||
29 | static struct ir_scancode msi_tvanywhere_plus[] = { | ||
30 | |||
31 | /* ---- Remote Button Layout ---- | ||
32 | |||
33 | POWER SOURCE SCAN MUTE | ||
34 | TV/FM 1 2 3 | ||
35 | |> 4 5 6 | ||
36 | <| 7 8 9 | ||
37 | ^^UP 0 + RECALL | ||
38 | vvDN RECORD STOP PLAY | ||
39 | |||
40 | MINIMIZE ZOOM | ||
41 | |||
42 | CH+ | ||
43 | VOL- VOL+ | ||
44 | CH- | ||
45 | |||
46 | SNAPSHOT MTS | ||
47 | |||
48 | << FUNC >> RESET | ||
49 | */ | ||
50 | |||
51 | { 0x01, KEY_1 }, /* 1 */ | ||
52 | { 0x0b, KEY_2 }, /* 2 */ | ||
53 | { 0x1b, KEY_3 }, /* 3 */ | ||
54 | { 0x05, KEY_4 }, /* 4 */ | ||
55 | { 0x09, KEY_5 }, /* 5 */ | ||
56 | { 0x15, KEY_6 }, /* 6 */ | ||
57 | { 0x06, KEY_7 }, /* 7 */ | ||
58 | { 0x0a, KEY_8 }, /* 8 */ | ||
59 | { 0x12, KEY_9 }, /* 9 */ | ||
60 | { 0x02, KEY_0 }, /* 0 */ | ||
61 | { 0x10, KEY_KPPLUS }, /* + */ | ||
62 | { 0x13, KEY_AGAIN }, /* Recall */ | ||
63 | |||
64 | { 0x1e, KEY_POWER }, /* Power */ | ||
65 | { 0x07, KEY_TUNER }, /* Source */ | ||
66 | { 0x1c, KEY_SEARCH }, /* Scan */ | ||
67 | { 0x18, KEY_MUTE }, /* Mute */ | ||
68 | |||
69 | { 0x03, KEY_RADIO }, /* TV/FM */ | ||
70 | /* The next four keys are duplicates that appear to send the | ||
71 | same IR code as Ch+, Ch-, >>, and << . The raw code assigned | ||
72 | to them is the actual code + 0x20 - they will never be | ||
73 | detected as such unless some way is discovered to distinguish | ||
74 | these buttons from those that have the same code. */ | ||
75 | { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ | ||
76 | { 0x37, KEY_LEFT }, /* <| and Ch- */ | ||
77 | { 0x2c, KEY_UP }, /* ^^Up and >> */ | ||
78 | { 0x24, KEY_DOWN }, /* vvDn and << */ | ||
79 | |||
80 | { 0x00, KEY_RECORD }, /* Record */ | ||
81 | { 0x08, KEY_STOP }, /* Stop */ | ||
82 | { 0x11, KEY_PLAY }, /* Play */ | ||
83 | |||
84 | { 0x0f, KEY_CLOSE }, /* Minimize */ | ||
85 | { 0x19, KEY_ZOOM }, /* Zoom */ | ||
86 | { 0x1a, KEY_CAMERA }, /* Snapshot */ | ||
87 | { 0x0d, KEY_LANGUAGE }, /* MTS */ | ||
88 | |||
89 | { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ | ||
90 | { 0x16, KEY_VOLUMEUP }, /* Vol+ */ | ||
91 | { 0x17, KEY_CHANNELDOWN }, /* Ch- */ | ||
92 | { 0x1f, KEY_CHANNELUP }, /* Ch+ */ | ||
93 | |||
94 | { 0x04, KEY_REWIND }, /* << */ | ||
95 | { 0x0e, KEY_MENU }, /* Function */ | ||
96 | { 0x0c, KEY_FASTFORWARD }, /* >> */ | ||
97 | { 0x1d, KEY_RESTART }, /* Reset */ | ||
98 | }; | ||
99 | |||
100 | static struct rc_keymap msi_tvanywhere_plus_map = { | ||
101 | .map = { | ||
102 | .scan = msi_tvanywhere_plus, | ||
103 | .size = ARRAY_SIZE(msi_tvanywhere_plus), | ||
104 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
105 | .name = RC_MAP_MSI_TVANYWHERE_PLUS, | ||
106 | } | ||
107 | }; | ||
108 | |||
109 | static int __init init_rc_map_msi_tvanywhere_plus(void) | ||
110 | { | ||
111 | return ir_register_map(&msi_tvanywhere_plus_map); | ||
112 | } | ||
113 | |||
114 | static void __exit exit_rc_map_msi_tvanywhere_plus(void) | ||
115 | { | ||
116 | ir_unregister_map(&msi_tvanywhere_plus_map); | ||
117 | } | ||
118 | |||
119 | module_init(init_rc_map_msi_tvanywhere_plus) | ||
120 | module_exit(exit_rc_map_msi_tvanywhere_plus) | ||
121 | |||
122 | MODULE_LICENSE("GPL"); | ||
123 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c new file mode 100644 index 000000000000..ef411854f067 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* MSI TV@nywhere MASTER remote */ | ||
16 | |||
17 | static struct ir_scancode msi_tvanywhere[] = { | ||
18 | /* Keys 0 to 9 */ | ||
19 | { 0x00, KEY_0 }, | ||
20 | { 0x01, KEY_1 }, | ||
21 | { 0x02, KEY_2 }, | ||
22 | { 0x03, KEY_3 }, | ||
23 | { 0x04, KEY_4 }, | ||
24 | { 0x05, KEY_5 }, | ||
25 | { 0x06, KEY_6 }, | ||
26 | { 0x07, KEY_7 }, | ||
27 | { 0x08, KEY_8 }, | ||
28 | { 0x09, KEY_9 }, | ||
29 | |||
30 | { 0x0c, KEY_MUTE }, | ||
31 | { 0x0f, KEY_SCREEN }, /* Full Screen */ | ||
32 | { 0x10, KEY_FN }, /* Funtion */ | ||
33 | { 0x11, KEY_TIME }, /* Time shift */ | ||
34 | { 0x12, KEY_POWER }, | ||
35 | { 0x13, KEY_MEDIA }, /* MTS */ | ||
36 | { 0x14, KEY_SLOW }, | ||
37 | { 0x16, KEY_REWIND }, /* backward << */ | ||
38 | { 0x17, KEY_ENTER }, /* Return */ | ||
39 | { 0x18, KEY_FASTFORWARD }, /* forward >> */ | ||
40 | { 0x1a, KEY_CHANNELUP }, | ||
41 | { 0x1b, KEY_VOLUMEUP }, | ||
42 | { 0x1e, KEY_CHANNELDOWN }, | ||
43 | { 0x1f, KEY_VOLUMEDOWN }, | ||
44 | }; | ||
45 | |||
46 | static struct rc_keymap msi_tvanywhere_map = { | ||
47 | .map = { | ||
48 | .scan = msi_tvanywhere, | ||
49 | .size = ARRAY_SIZE(msi_tvanywhere), | ||
50 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
51 | .name = RC_MAP_MSI_TVANYWHERE, | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | static int __init init_rc_map_msi_tvanywhere(void) | ||
56 | { | ||
57 | return ir_register_map(&msi_tvanywhere_map); | ||
58 | } | ||
59 | |||
60 | static void __exit exit_rc_map_msi_tvanywhere(void) | ||
61 | { | ||
62 | ir_unregister_map(&msi_tvanywhere_map); | ||
63 | } | ||
64 | |||
65 | module_init(init_rc_map_msi_tvanywhere) | ||
66 | module_exit(exit_rc_map_msi_tvanywhere) | ||
67 | |||
68 | MODULE_LICENSE("GPL"); | ||
69 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-nebula.c b/drivers/media/IR/keymaps/rc-nebula.c new file mode 100644 index 000000000000..ccc50eb402ec --- /dev/null +++ b/drivers/media/IR/keymaps/rc-nebula.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* nebula.h - Keytable for nebula Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode nebula[] = { | ||
16 | { 0x00, KEY_0 }, | ||
17 | { 0x01, KEY_1 }, | ||
18 | { 0x02, KEY_2 }, | ||
19 | { 0x03, KEY_3 }, | ||
20 | { 0x04, KEY_4 }, | ||
21 | { 0x05, KEY_5 }, | ||
22 | { 0x06, KEY_6 }, | ||
23 | { 0x07, KEY_7 }, | ||
24 | { 0x08, KEY_8 }, | ||
25 | { 0x09, KEY_9 }, | ||
26 | { 0x0a, KEY_TV }, | ||
27 | { 0x0b, KEY_AUX }, | ||
28 | { 0x0c, KEY_DVD }, | ||
29 | { 0x0d, KEY_POWER }, | ||
30 | { 0x0e, KEY_MHP }, /* labelled 'Picture' */ | ||
31 | { 0x0f, KEY_AUDIO }, | ||
32 | { 0x10, KEY_INFO }, | ||
33 | { 0x11, KEY_F13 }, /* 16:9 */ | ||
34 | { 0x12, KEY_F14 }, /* 14:9 */ | ||
35 | { 0x13, KEY_EPG }, | ||
36 | { 0x14, KEY_EXIT }, | ||
37 | { 0x15, KEY_MENU }, | ||
38 | { 0x16, KEY_UP }, | ||
39 | { 0x17, KEY_DOWN }, | ||
40 | { 0x18, KEY_LEFT }, | ||
41 | { 0x19, KEY_RIGHT }, | ||
42 | { 0x1a, KEY_ENTER }, | ||
43 | { 0x1b, KEY_CHANNELUP }, | ||
44 | { 0x1c, KEY_CHANNELDOWN }, | ||
45 | { 0x1d, KEY_VOLUMEUP }, | ||
46 | { 0x1e, KEY_VOLUMEDOWN }, | ||
47 | { 0x1f, KEY_RED }, | ||
48 | { 0x20, KEY_GREEN }, | ||
49 | { 0x21, KEY_YELLOW }, | ||
50 | { 0x22, KEY_BLUE }, | ||
51 | { 0x23, KEY_SUBTITLE }, | ||
52 | { 0x24, KEY_F15 }, /* AD */ | ||
53 | { 0x25, KEY_TEXT }, | ||
54 | { 0x26, KEY_MUTE }, | ||
55 | { 0x27, KEY_REWIND }, | ||
56 | { 0x28, KEY_STOP }, | ||
57 | { 0x29, KEY_PLAY }, | ||
58 | { 0x2a, KEY_FASTFORWARD }, | ||
59 | { 0x2b, KEY_F16 }, /* chapter */ | ||
60 | { 0x2c, KEY_PAUSE }, | ||
61 | { 0x2d, KEY_PLAY }, | ||
62 | { 0x2e, KEY_RECORD }, | ||
63 | { 0x2f, KEY_F17 }, /* picture in picture */ | ||
64 | { 0x30, KEY_KPPLUS }, /* zoom in */ | ||
65 | { 0x31, KEY_KPMINUS }, /* zoom out */ | ||
66 | { 0x32, KEY_F18 }, /* capture */ | ||
67 | { 0x33, KEY_F19 }, /* web */ | ||
68 | { 0x34, KEY_EMAIL }, | ||
69 | { 0x35, KEY_PHONE }, | ||
70 | { 0x36, KEY_PC }, | ||
71 | }; | ||
72 | |||
73 | static struct rc_keymap nebula_map = { | ||
74 | .map = { | ||
75 | .scan = nebula, | ||
76 | .size = ARRAY_SIZE(nebula), | ||
77 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
78 | .name = RC_MAP_NEBULA, | ||
79 | } | ||
80 | }; | ||
81 | |||
82 | static int __init init_rc_map_nebula(void) | ||
83 | { | ||
84 | return ir_register_map(&nebula_map); | ||
85 | } | ||
86 | |||
87 | static void __exit exit_rc_map_nebula(void) | ||
88 | { | ||
89 | ir_unregister_map(&nebula_map); | ||
90 | } | ||
91 | |||
92 | module_init(init_rc_map_nebula) | ||
93 | module_exit(exit_rc_map_nebula) | ||
94 | |||
95 | MODULE_LICENSE("GPL"); | ||
96 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c new file mode 100644 index 000000000000..e1b54d20db60 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Terratec Cinergy Hybrid T USB XS FM | ||
16 | Mauro Carvalho Chehab <mchehab@redhat.com> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode nec_terratec_cinergy_xs[] = { | ||
20 | { 0x1441, KEY_HOME}, | ||
21 | { 0x1401, KEY_POWER2}, | ||
22 | |||
23 | { 0x1442, KEY_MENU}, /* DVD menu */ | ||
24 | { 0x1443, KEY_SUBTITLE}, | ||
25 | { 0x1444, KEY_TEXT}, /* Teletext */ | ||
26 | { 0x1445, KEY_DELETE}, | ||
27 | |||
28 | { 0x1402, KEY_1}, | ||
29 | { 0x1403, KEY_2}, | ||
30 | { 0x1404, KEY_3}, | ||
31 | { 0x1405, KEY_4}, | ||
32 | { 0x1406, KEY_5}, | ||
33 | { 0x1407, KEY_6}, | ||
34 | { 0x1408, KEY_7}, | ||
35 | { 0x1409, KEY_8}, | ||
36 | { 0x140a, KEY_9}, | ||
37 | { 0x140c, KEY_0}, | ||
38 | |||
39 | { 0x140b, KEY_TUNER}, /* AV */ | ||
40 | { 0x140d, KEY_MODE}, /* A.B */ | ||
41 | |||
42 | { 0x1446, KEY_TV}, | ||
43 | { 0x1447, KEY_DVD}, | ||
44 | { 0x1449, KEY_VIDEO}, | ||
45 | { 0x144a, KEY_RADIO}, /* Music */ | ||
46 | { 0x144b, KEY_CAMERA}, /* PIC */ | ||
47 | |||
48 | { 0x1410, KEY_UP}, | ||
49 | { 0x1411, KEY_LEFT}, | ||
50 | { 0x1412, KEY_OK}, | ||
51 | { 0x1413, KEY_RIGHT}, | ||
52 | { 0x1414, KEY_DOWN}, | ||
53 | |||
54 | { 0x140f, KEY_EPG}, | ||
55 | { 0x1416, KEY_INFO}, | ||
56 | { 0x144d, KEY_BACKSPACE}, | ||
57 | |||
58 | { 0x141c, KEY_VOLUMEUP}, | ||
59 | { 0x141e, KEY_VOLUMEDOWN}, | ||
60 | |||
61 | { 0x144c, KEY_PLAY}, | ||
62 | { 0x141d, KEY_MUTE}, | ||
63 | |||
64 | { 0x141b, KEY_CHANNELUP}, | ||
65 | { 0x141f, KEY_CHANNELDOWN}, | ||
66 | |||
67 | { 0x1417, KEY_RED}, | ||
68 | { 0x1418, KEY_GREEN}, | ||
69 | { 0x1419, KEY_YELLOW}, | ||
70 | { 0x141a, KEY_BLUE}, | ||
71 | |||
72 | { 0x1458, KEY_RECORD}, | ||
73 | { 0x1448, KEY_STOP}, | ||
74 | { 0x1440, KEY_PAUSE}, | ||
75 | |||
76 | { 0x1454, KEY_LAST}, | ||
77 | { 0x144e, KEY_REWIND}, | ||
78 | { 0x144f, KEY_FASTFORWARD}, | ||
79 | { 0x145c, KEY_NEXT}, | ||
80 | }; | ||
81 | |||
82 | static struct rc_keymap nec_terratec_cinergy_xs_map = { | ||
83 | .map = { | ||
84 | .scan = nec_terratec_cinergy_xs, | ||
85 | .size = ARRAY_SIZE(nec_terratec_cinergy_xs), | ||
86 | .ir_type = IR_TYPE_NEC, | ||
87 | .name = RC_MAP_NEC_TERRATEC_CINERGY_XS, | ||
88 | } | ||
89 | }; | ||
90 | |||
91 | static int __init init_rc_map_nec_terratec_cinergy_xs(void) | ||
92 | { | ||
93 | return ir_register_map(&nec_terratec_cinergy_xs_map); | ||
94 | } | ||
95 | |||
96 | static void __exit exit_rc_map_nec_terratec_cinergy_xs(void) | ||
97 | { | ||
98 | ir_unregister_map(&nec_terratec_cinergy_xs_map); | ||
99 | } | ||
100 | |||
101 | module_init(init_rc_map_nec_terratec_cinergy_xs) | ||
102 | module_exit(exit_rc_map_nec_terratec_cinergy_xs) | ||
103 | |||
104 | MODULE_LICENSE("GPL"); | ||
105 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-norwood.c b/drivers/media/IR/keymaps/rc-norwood.c new file mode 100644 index 000000000000..e5849a6b3f05 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-norwood.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* norwood.h - Keytable for norwood Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Norwood Micro (non-Pro) TV Tuner | ||
16 | By Peter Naulls <peter@chocky.org> | ||
17 | Key comments are the functions given in the manual */ | ||
18 | |||
19 | static struct ir_scancode norwood[] = { | ||
20 | /* Keys 0 to 9 */ | ||
21 | { 0x20, KEY_0 }, | ||
22 | { 0x21, KEY_1 }, | ||
23 | { 0x22, KEY_2 }, | ||
24 | { 0x23, KEY_3 }, | ||
25 | { 0x24, KEY_4 }, | ||
26 | { 0x25, KEY_5 }, | ||
27 | { 0x26, KEY_6 }, | ||
28 | { 0x27, KEY_7 }, | ||
29 | { 0x28, KEY_8 }, | ||
30 | { 0x29, KEY_9 }, | ||
31 | |||
32 | { 0x78, KEY_TUNER }, /* Video Source */ | ||
33 | { 0x2c, KEY_EXIT }, /* Open/Close software */ | ||
34 | { 0x2a, KEY_SELECT }, /* 2 Digit Select */ | ||
35 | { 0x69, KEY_AGAIN }, /* Recall */ | ||
36 | |||
37 | { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ | ||
38 | { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ | ||
39 | { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ | ||
40 | { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ | ||
41 | |||
42 | { 0x2d, KEY_MUTE }, /* Mute */ | ||
43 | { 0x30, KEY_VOLUMEUP }, /* Volume up */ | ||
44 | { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ | ||
45 | { 0x60, KEY_CHANNELUP }, /* Channel up */ | ||
46 | { 0x61, KEY_CHANNELDOWN }, /* Channel down */ | ||
47 | |||
48 | { 0x3f, KEY_RECORD }, /* Record */ | ||
49 | { 0x37, KEY_PLAY }, /* Play */ | ||
50 | { 0x36, KEY_PAUSE }, /* Pause */ | ||
51 | { 0x2b, KEY_STOP }, /* Stop */ | ||
52 | { 0x67, KEY_FASTFORWARD }, /* Foward */ | ||
53 | { 0x66, KEY_REWIND }, /* Rewind */ | ||
54 | { 0x3e, KEY_SEARCH }, /* Auto Scan */ | ||
55 | { 0x2e, KEY_CAMERA }, /* Capture Video */ | ||
56 | { 0x6d, KEY_MENU }, /* Show/Hide Control */ | ||
57 | { 0x2f, KEY_ZOOM }, /* Full Screen */ | ||
58 | { 0x34, KEY_RADIO }, /* FM */ | ||
59 | { 0x65, KEY_POWER }, /* Computer power */ | ||
60 | }; | ||
61 | |||
62 | static struct rc_keymap norwood_map = { | ||
63 | .map = { | ||
64 | .scan = norwood, | ||
65 | .size = ARRAY_SIZE(norwood), | ||
66 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
67 | .name = RC_MAP_NORWOOD, | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | static int __init init_rc_map_norwood(void) | ||
72 | { | ||
73 | return ir_register_map(&norwood_map); | ||
74 | } | ||
75 | |||
76 | static void __exit exit_rc_map_norwood(void) | ||
77 | { | ||
78 | ir_unregister_map(&norwood_map); | ||
79 | } | ||
80 | |||
81 | module_init(init_rc_map_norwood) | ||
82 | module_exit(exit_rc_map_norwood) | ||
83 | |||
84 | MODULE_LICENSE("GPL"); | ||
85 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-npgtech.c b/drivers/media/IR/keymaps/rc-npgtech.c new file mode 100644 index 000000000000..b9ece1e90296 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-npgtech.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* npgtech.h - Keytable for npgtech Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode npgtech[] = { | ||
16 | { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ | ||
17 | { 0x2a, KEY_FRONT }, | ||
18 | |||
19 | { 0x3e, KEY_1 }, | ||
20 | { 0x02, KEY_2 }, | ||
21 | { 0x06, KEY_3 }, | ||
22 | { 0x0a, KEY_4 }, | ||
23 | { 0x0e, KEY_5 }, | ||
24 | { 0x12, KEY_6 }, | ||
25 | { 0x16, KEY_7 }, | ||
26 | { 0x1a, KEY_8 }, | ||
27 | { 0x1e, KEY_9 }, | ||
28 | { 0x3a, KEY_0 }, | ||
29 | { 0x22, KEY_NUMLOCK }, /* -/-- */ | ||
30 | { 0x20, KEY_REFRESH }, | ||
31 | |||
32 | { 0x03, KEY_BRIGHTNESSDOWN }, | ||
33 | { 0x28, KEY_AUDIO }, | ||
34 | { 0x3c, KEY_CHANNELUP }, | ||
35 | { 0x3f, KEY_VOLUMEDOWN }, | ||
36 | { 0x2e, KEY_MUTE }, | ||
37 | { 0x3b, KEY_VOLUMEUP }, | ||
38 | { 0x00, KEY_CHANNELDOWN }, | ||
39 | { 0x07, KEY_BRIGHTNESSUP }, | ||
40 | { 0x2c, KEY_TEXT }, | ||
41 | |||
42 | { 0x37, KEY_RECORD }, | ||
43 | { 0x17, KEY_PLAY }, | ||
44 | { 0x13, KEY_PAUSE }, | ||
45 | { 0x26, KEY_STOP }, | ||
46 | { 0x18, KEY_FASTFORWARD }, | ||
47 | { 0x14, KEY_REWIND }, | ||
48 | { 0x33, KEY_ZOOM }, | ||
49 | { 0x32, KEY_KEYBOARD }, | ||
50 | { 0x30, KEY_GOTO }, /* Pointing arrow */ | ||
51 | { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ | ||
52 | { 0x0b, KEY_RADIO }, | ||
53 | { 0x10, KEY_POWER }, | ||
54 | |||
55 | }; | ||
56 | |||
57 | static struct rc_keymap npgtech_map = { | ||
58 | .map = { | ||
59 | .scan = npgtech, | ||
60 | .size = ARRAY_SIZE(npgtech), | ||
61 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
62 | .name = RC_MAP_NPGTECH, | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | static int __init init_rc_map_npgtech(void) | ||
67 | { | ||
68 | return ir_register_map(&npgtech_map); | ||
69 | } | ||
70 | |||
71 | static void __exit exit_rc_map_npgtech(void) | ||
72 | { | ||
73 | ir_unregister_map(&npgtech_map); | ||
74 | } | ||
75 | |||
76 | module_init(init_rc_map_npgtech) | ||
77 | module_exit(exit_rc_map_npgtech) | ||
78 | |||
79 | MODULE_LICENSE("GPL"); | ||
80 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pctv-sedna.c b/drivers/media/IR/keymaps/rc-pctv-sedna.c new file mode 100644 index 000000000000..4129bb44a25b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pctv-sedna.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* pctv-sedna.h - Keytable for pctv_sedna Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Mapping for the 28 key remote control as seen at | ||
16 | http://www.sednacomputer.com/photo/cardbus-tv.jpg | ||
17 | Pavel Mihaylov <bin@bash.info> | ||
18 | Also for the remote bundled with Kozumi KTV-01C card */ | ||
19 | |||
20 | static struct ir_scancode pctv_sedna[] = { | ||
21 | { 0x00, KEY_0 }, | ||
22 | { 0x01, KEY_1 }, | ||
23 | { 0x02, KEY_2 }, | ||
24 | { 0x03, KEY_3 }, | ||
25 | { 0x04, KEY_4 }, | ||
26 | { 0x05, KEY_5 }, | ||
27 | { 0x06, KEY_6 }, | ||
28 | { 0x07, KEY_7 }, | ||
29 | { 0x08, KEY_8 }, | ||
30 | { 0x09, KEY_9 }, | ||
31 | |||
32 | { 0x0a, KEY_AGAIN }, /* Recall */ | ||
33 | { 0x0b, KEY_CHANNELUP }, | ||
34 | { 0x0c, KEY_VOLUMEUP }, | ||
35 | { 0x0d, KEY_MODE }, /* Stereo */ | ||
36 | { 0x0e, KEY_STOP }, | ||
37 | { 0x0f, KEY_PREVIOUSSONG }, | ||
38 | { 0x10, KEY_ZOOM }, | ||
39 | { 0x11, KEY_TUNER }, /* Source */ | ||
40 | { 0x12, KEY_POWER }, | ||
41 | { 0x13, KEY_MUTE }, | ||
42 | { 0x15, KEY_CHANNELDOWN }, | ||
43 | { 0x18, KEY_VOLUMEDOWN }, | ||
44 | { 0x19, KEY_CAMERA }, /* Snapshot */ | ||
45 | { 0x1a, KEY_NEXTSONG }, | ||
46 | { 0x1b, KEY_TIME }, /* Time Shift */ | ||
47 | { 0x1c, KEY_RADIO }, /* FM Radio */ | ||
48 | { 0x1d, KEY_RECORD }, | ||
49 | { 0x1e, KEY_PAUSE }, | ||
50 | /* additional codes for Kozumi's remote */ | ||
51 | { 0x14, KEY_INFO }, /* OSD */ | ||
52 | { 0x16, KEY_OK }, /* OK */ | ||
53 | { 0x17, KEY_DIGITS }, /* Plus */ | ||
54 | { 0x1f, KEY_PLAY }, /* Play */ | ||
55 | }; | ||
56 | |||
57 | static struct rc_keymap pctv_sedna_map = { | ||
58 | .map = { | ||
59 | .scan = pctv_sedna, | ||
60 | .size = ARRAY_SIZE(pctv_sedna), | ||
61 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
62 | .name = RC_MAP_PCTV_SEDNA, | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | static int __init init_rc_map_pctv_sedna(void) | ||
67 | { | ||
68 | return ir_register_map(&pctv_sedna_map); | ||
69 | } | ||
70 | |||
71 | static void __exit exit_rc_map_pctv_sedna(void) | ||
72 | { | ||
73 | ir_unregister_map(&pctv_sedna_map); | ||
74 | } | ||
75 | |||
76 | module_init(init_rc_map_pctv_sedna) | ||
77 | module_exit(exit_rc_map_pctv_sedna) | ||
78 | |||
79 | MODULE_LICENSE("GPL"); | ||
80 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pinnacle-color.c b/drivers/media/IR/keymaps/rc-pinnacle-color.c new file mode 100644 index 000000000000..326e023ce126 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-color.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* pinnacle-color.h - Keytable for pinnacle_color Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode pinnacle_color[] = { | ||
16 | { 0x59, KEY_MUTE }, | ||
17 | { 0x4a, KEY_POWER }, | ||
18 | |||
19 | { 0x18, KEY_TEXT }, | ||
20 | { 0x26, KEY_TV }, | ||
21 | { 0x3d, KEY_PRINT }, | ||
22 | |||
23 | { 0x48, KEY_RED }, | ||
24 | { 0x04, KEY_GREEN }, | ||
25 | { 0x11, KEY_YELLOW }, | ||
26 | { 0x00, KEY_BLUE }, | ||
27 | |||
28 | { 0x2d, KEY_VOLUMEUP }, | ||
29 | { 0x1e, KEY_VOLUMEDOWN }, | ||
30 | |||
31 | { 0x49, KEY_MENU }, | ||
32 | |||
33 | { 0x16, KEY_CHANNELUP }, | ||
34 | { 0x17, KEY_CHANNELDOWN }, | ||
35 | |||
36 | { 0x20, KEY_UP }, | ||
37 | { 0x21, KEY_DOWN }, | ||
38 | { 0x22, KEY_LEFT }, | ||
39 | { 0x23, KEY_RIGHT }, | ||
40 | { 0x0d, KEY_SELECT }, | ||
41 | |||
42 | { 0x08, KEY_BACK }, | ||
43 | { 0x07, KEY_REFRESH }, | ||
44 | |||
45 | { 0x2f, KEY_ZOOM }, | ||
46 | { 0x29, KEY_RECORD }, | ||
47 | |||
48 | { 0x4b, KEY_PAUSE }, | ||
49 | { 0x4d, KEY_REWIND }, | ||
50 | { 0x2e, KEY_PLAY }, | ||
51 | { 0x4e, KEY_FORWARD }, | ||
52 | { 0x53, KEY_PREVIOUS }, | ||
53 | { 0x4c, KEY_STOP }, | ||
54 | { 0x54, KEY_NEXT }, | ||
55 | |||
56 | { 0x69, KEY_0 }, | ||
57 | { 0x6a, KEY_1 }, | ||
58 | { 0x6b, KEY_2 }, | ||
59 | { 0x6c, KEY_3 }, | ||
60 | { 0x6d, KEY_4 }, | ||
61 | { 0x6e, KEY_5 }, | ||
62 | { 0x6f, KEY_6 }, | ||
63 | { 0x70, KEY_7 }, | ||
64 | { 0x71, KEY_8 }, | ||
65 | { 0x72, KEY_9 }, | ||
66 | |||
67 | { 0x74, KEY_CHANNEL }, | ||
68 | { 0x0a, KEY_BACKSPACE }, | ||
69 | }; | ||
70 | |||
71 | static struct rc_keymap pinnacle_color_map = { | ||
72 | .map = { | ||
73 | .scan = pinnacle_color, | ||
74 | .size = ARRAY_SIZE(pinnacle_color), | ||
75 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
76 | .name = RC_MAP_PINNACLE_COLOR, | ||
77 | } | ||
78 | }; | ||
79 | |||
80 | static int __init init_rc_map_pinnacle_color(void) | ||
81 | { | ||
82 | return ir_register_map(&pinnacle_color_map); | ||
83 | } | ||
84 | |||
85 | static void __exit exit_rc_map_pinnacle_color(void) | ||
86 | { | ||
87 | ir_unregister_map(&pinnacle_color_map); | ||
88 | } | ||
89 | |||
90 | module_init(init_rc_map_pinnacle_color) | ||
91 | module_exit(exit_rc_map_pinnacle_color) | ||
92 | |||
93 | MODULE_LICENSE("GPL"); | ||
94 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pinnacle-grey.c b/drivers/media/IR/keymaps/rc-pinnacle-grey.c new file mode 100644 index 000000000000..14cb772515c6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-grey.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode pinnacle_grey[] = { | ||
16 | { 0x3a, KEY_0 }, | ||
17 | { 0x31, KEY_1 }, | ||
18 | { 0x32, KEY_2 }, | ||
19 | { 0x33, KEY_3 }, | ||
20 | { 0x34, KEY_4 }, | ||
21 | { 0x35, KEY_5 }, | ||
22 | { 0x36, KEY_6 }, | ||
23 | { 0x37, KEY_7 }, | ||
24 | { 0x38, KEY_8 }, | ||
25 | { 0x39, KEY_9 }, | ||
26 | |||
27 | { 0x2f, KEY_POWER }, | ||
28 | |||
29 | { 0x2e, KEY_P }, | ||
30 | { 0x1f, KEY_L }, | ||
31 | { 0x2b, KEY_I }, | ||
32 | |||
33 | { 0x2d, KEY_SCREEN }, | ||
34 | { 0x1e, KEY_ZOOM }, | ||
35 | { 0x1b, KEY_VOLUMEUP }, | ||
36 | { 0x0f, KEY_VOLUMEDOWN }, | ||
37 | { 0x17, KEY_CHANNELUP }, | ||
38 | { 0x1c, KEY_CHANNELDOWN }, | ||
39 | { 0x25, KEY_INFO }, | ||
40 | |||
41 | { 0x3c, KEY_MUTE }, | ||
42 | |||
43 | { 0x3d, KEY_LEFT }, | ||
44 | { 0x3b, KEY_RIGHT }, | ||
45 | |||
46 | { 0x3f, KEY_UP }, | ||
47 | { 0x3e, KEY_DOWN }, | ||
48 | { 0x1a, KEY_ENTER }, | ||
49 | |||
50 | { 0x1d, KEY_MENU }, | ||
51 | { 0x19, KEY_AGAIN }, | ||
52 | { 0x16, KEY_PREVIOUSSONG }, | ||
53 | { 0x13, KEY_NEXTSONG }, | ||
54 | { 0x15, KEY_PAUSE }, | ||
55 | { 0x0e, KEY_REWIND }, | ||
56 | { 0x0d, KEY_PLAY }, | ||
57 | { 0x0b, KEY_STOP }, | ||
58 | { 0x07, KEY_FORWARD }, | ||
59 | { 0x27, KEY_RECORD }, | ||
60 | { 0x26, KEY_TUNER }, | ||
61 | { 0x29, KEY_TEXT }, | ||
62 | { 0x2a, KEY_MEDIA }, | ||
63 | { 0x18, KEY_EPG }, | ||
64 | }; | ||
65 | |||
66 | static struct rc_keymap pinnacle_grey_map = { | ||
67 | .map = { | ||
68 | .scan = pinnacle_grey, | ||
69 | .size = ARRAY_SIZE(pinnacle_grey), | ||
70 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
71 | .name = RC_MAP_PINNACLE_GREY, | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | static int __init init_rc_map_pinnacle_grey(void) | ||
76 | { | ||
77 | return ir_register_map(&pinnacle_grey_map); | ||
78 | } | ||
79 | |||
80 | static void __exit exit_rc_map_pinnacle_grey(void) | ||
81 | { | ||
82 | ir_unregister_map(&pinnacle_grey_map); | ||
83 | } | ||
84 | |||
85 | module_init(init_rc_map_pinnacle_grey) | ||
86 | module_exit(exit_rc_map_pinnacle_grey) | ||
87 | |||
88 | MODULE_LICENSE("GPL"); | ||
89 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c new file mode 100644 index 000000000000..835bf4ef8de7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Pinnacle PCTV HD 800i mini remote */ | ||
16 | |||
17 | static struct ir_scancode pinnacle_pctv_hd[] = { | ||
18 | |||
19 | { 0x0f, KEY_1 }, | ||
20 | { 0x15, KEY_2 }, | ||
21 | { 0x10, KEY_3 }, | ||
22 | { 0x18, KEY_4 }, | ||
23 | { 0x1b, KEY_5 }, | ||
24 | { 0x1e, KEY_6 }, | ||
25 | { 0x11, KEY_7 }, | ||
26 | { 0x21, KEY_8 }, | ||
27 | { 0x12, KEY_9 }, | ||
28 | { 0x27, KEY_0 }, | ||
29 | |||
30 | { 0x24, KEY_ZOOM }, | ||
31 | { 0x2a, KEY_SUBTITLE }, | ||
32 | |||
33 | { 0x00, KEY_MUTE }, | ||
34 | { 0x01, KEY_ENTER }, /* Pinnacle Logo */ | ||
35 | { 0x39, KEY_POWER }, | ||
36 | |||
37 | { 0x03, KEY_VOLUMEUP }, | ||
38 | { 0x09, KEY_VOLUMEDOWN }, | ||
39 | { 0x06, KEY_CHANNELUP }, | ||
40 | { 0x0c, KEY_CHANNELDOWN }, | ||
41 | |||
42 | { 0x2d, KEY_REWIND }, | ||
43 | { 0x30, KEY_PLAYPAUSE }, | ||
44 | { 0x33, KEY_FASTFORWARD }, | ||
45 | { 0x3c, KEY_STOP }, | ||
46 | { 0x36, KEY_RECORD }, | ||
47 | { 0x3f, KEY_EPG }, /* Labeled "?" */ | ||
48 | }; | ||
49 | |||
50 | static struct rc_keymap pinnacle_pctv_hd_map = { | ||
51 | .map = { | ||
52 | .scan = pinnacle_pctv_hd, | ||
53 | .size = ARRAY_SIZE(pinnacle_pctv_hd), | ||
54 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
55 | .name = RC_MAP_PINNACLE_PCTV_HD, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | static int __init init_rc_map_pinnacle_pctv_hd(void) | ||
60 | { | ||
61 | return ir_register_map(&pinnacle_pctv_hd_map); | ||
62 | } | ||
63 | |||
64 | static void __exit exit_rc_map_pinnacle_pctv_hd(void) | ||
65 | { | ||
66 | ir_unregister_map(&pinnacle_pctv_hd_map); | ||
67 | } | ||
68 | |||
69 | module_init(init_rc_map_pinnacle_pctv_hd) | ||
70 | module_exit(exit_rc_map_pinnacle_pctv_hd) | ||
71 | |||
72 | MODULE_LICENSE("GPL"); | ||
73 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c new file mode 100644 index 000000000000..5a735d569a8b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview-mk12.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Keytable for MK-F12 IR remote provided together with Pixelview | ||
17 | * Ultra Pro Remote Controller. Uses NEC extended format. | ||
18 | */ | ||
19 | static struct ir_scancode pixelview_mk12[] = { | ||
20 | { 0x866b03, KEY_TUNER }, /* Timeshift */ | ||
21 | { 0x866b1e, KEY_POWER2 }, /* power */ | ||
22 | |||
23 | { 0x866b01, KEY_1 }, | ||
24 | { 0x866b0b, KEY_2 }, | ||
25 | { 0x866b1b, KEY_3 }, | ||
26 | { 0x866b05, KEY_4 }, | ||
27 | { 0x866b09, KEY_5 }, | ||
28 | { 0x866b15, KEY_6 }, | ||
29 | { 0x866b06, KEY_7 }, | ||
30 | { 0x866b0a, KEY_8 }, | ||
31 | { 0x866b12, KEY_9 }, | ||
32 | { 0x866b02, KEY_0 }, | ||
33 | |||
34 | { 0x866b13, KEY_AGAIN }, /* loop */ | ||
35 | { 0x866b10, KEY_DIGITS }, /* +100 */ | ||
36 | |||
37 | { 0x866b00, KEY_MEDIA }, /* source */ | ||
38 | { 0x866b18, KEY_MUTE }, /* mute */ | ||
39 | { 0x866b19, KEY_CAMERA }, /* snapshot */ | ||
40 | { 0x866b1a, KEY_SEARCH }, /* scan */ | ||
41 | |||
42 | { 0x866b16, KEY_CHANNELUP }, /* chn + */ | ||
43 | { 0x866b14, KEY_CHANNELDOWN }, /* chn - */ | ||
44 | { 0x866b1f, KEY_VOLUMEUP }, /* vol + */ | ||
45 | { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */ | ||
46 | { 0x866b1c, KEY_ZOOM }, /* zoom */ | ||
47 | |||
48 | { 0x866b04, KEY_REWIND }, | ||
49 | { 0x866b0e, KEY_RECORD }, | ||
50 | { 0x866b0c, KEY_FORWARD }, | ||
51 | |||
52 | { 0x866b1d, KEY_STOP }, | ||
53 | { 0x866b08, KEY_PLAY }, | ||
54 | { 0x866b0f, KEY_PAUSE }, | ||
55 | |||
56 | { 0x866b0d, KEY_TV }, | ||
57 | { 0x866b07, KEY_RADIO }, /* FM */ | ||
58 | }; | ||
59 | |||
60 | static struct rc_keymap pixelview_map = { | ||
61 | .map = { | ||
62 | .scan = pixelview_mk12, | ||
63 | .size = ARRAY_SIZE(pixelview_mk12), | ||
64 | .ir_type = IR_TYPE_NEC, | ||
65 | .name = RC_MAP_PIXELVIEW_MK12, | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | static int __init init_rc_map_pixelview(void) | ||
70 | { | ||
71 | return ir_register_map(&pixelview_map); | ||
72 | } | ||
73 | |||
74 | static void __exit exit_rc_map_pixelview(void) | ||
75 | { | ||
76 | ir_unregister_map(&pixelview_map); | ||
77 | } | ||
78 | |||
79 | module_init(init_rc_map_pixelview) | ||
80 | module_exit(exit_rc_map_pixelview) | ||
81 | |||
82 | MODULE_LICENSE("GPL"); | ||
83 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pixelview-new.c b/drivers/media/IR/keymaps/rc-pixelview-new.c new file mode 100644 index 000000000000..7bbbbf5735e6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview-new.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* pixelview-new.h - Keytable for pixelview_new Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | present on PV MPEG 8000GT | ||
18 | */ | ||
19 | |||
20 | static struct ir_scancode pixelview_new[] = { | ||
21 | { 0x3c, KEY_TIME }, /* Timeshift */ | ||
22 | { 0x12, KEY_POWER }, | ||
23 | |||
24 | { 0x3d, KEY_1 }, | ||
25 | { 0x38, KEY_2 }, | ||
26 | { 0x18, KEY_3 }, | ||
27 | { 0x35, KEY_4 }, | ||
28 | { 0x39, KEY_5 }, | ||
29 | { 0x15, KEY_6 }, | ||
30 | { 0x36, KEY_7 }, | ||
31 | { 0x3a, KEY_8 }, | ||
32 | { 0x1e, KEY_9 }, | ||
33 | { 0x3e, KEY_0 }, | ||
34 | |||
35 | { 0x1c, KEY_AGAIN }, /* LOOP */ | ||
36 | { 0x3f, KEY_MEDIA }, /* Source */ | ||
37 | { 0x1f, KEY_LAST }, /* +100 */ | ||
38 | { 0x1b, KEY_MUTE }, | ||
39 | |||
40 | { 0x17, KEY_CHANNELDOWN }, | ||
41 | { 0x16, KEY_CHANNELUP }, | ||
42 | { 0x10, KEY_VOLUMEUP }, | ||
43 | { 0x14, KEY_VOLUMEDOWN }, | ||
44 | { 0x13, KEY_ZOOM }, | ||
45 | |||
46 | { 0x19, KEY_CAMERA }, /* SNAPSHOT */ | ||
47 | { 0x1a, KEY_SEARCH }, /* scan */ | ||
48 | |||
49 | { 0x37, KEY_REWIND }, /* << */ | ||
50 | { 0x32, KEY_RECORD }, /* o (red) */ | ||
51 | { 0x33, KEY_FORWARD }, /* >> */ | ||
52 | { 0x11, KEY_STOP }, /* square */ | ||
53 | { 0x3b, KEY_PLAY }, /* > */ | ||
54 | { 0x30, KEY_PLAYPAUSE }, /* || */ | ||
55 | |||
56 | { 0x31, KEY_TV }, | ||
57 | { 0x34, KEY_RADIO }, | ||
58 | }; | ||
59 | |||
60 | static struct rc_keymap pixelview_new_map = { | ||
61 | .map = { | ||
62 | .scan = pixelview_new, | ||
63 | .size = ARRAY_SIZE(pixelview_new), | ||
64 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
65 | .name = RC_MAP_PIXELVIEW_NEW, | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | static int __init init_rc_map_pixelview_new(void) | ||
70 | { | ||
71 | return ir_register_map(&pixelview_new_map); | ||
72 | } | ||
73 | |||
74 | static void __exit exit_rc_map_pixelview_new(void) | ||
75 | { | ||
76 | ir_unregister_map(&pixelview_new_map); | ||
77 | } | ||
78 | |||
79 | module_init(init_rc_map_pixelview_new) | ||
80 | module_exit(exit_rc_map_pixelview_new) | ||
81 | |||
82 | MODULE_LICENSE("GPL"); | ||
83 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pixelview.c b/drivers/media/IR/keymaps/rc-pixelview.c new file mode 100644 index 000000000000..82ff12e182a0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* pixelview.h - Keytable for pixelview Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode pixelview[] = { | ||
16 | |||
17 | { 0x1e, KEY_POWER }, /* power */ | ||
18 | { 0x07, KEY_MEDIA }, /* source */ | ||
19 | { 0x1c, KEY_SEARCH }, /* scan */ | ||
20 | |||
21 | |||
22 | { 0x03, KEY_TUNER }, /* TV/FM */ | ||
23 | |||
24 | { 0x00, KEY_RECORD }, | ||
25 | { 0x08, KEY_STOP }, | ||
26 | { 0x11, KEY_PLAY }, | ||
27 | |||
28 | { 0x1a, KEY_PLAYPAUSE }, /* freeze */ | ||
29 | { 0x19, KEY_ZOOM }, /* zoom */ | ||
30 | { 0x0f, KEY_TEXT }, /* min */ | ||
31 | |||
32 | { 0x01, KEY_1 }, | ||
33 | { 0x0b, KEY_2 }, | ||
34 | { 0x1b, KEY_3 }, | ||
35 | { 0x05, KEY_4 }, | ||
36 | { 0x09, KEY_5 }, | ||
37 | { 0x15, KEY_6 }, | ||
38 | { 0x06, KEY_7 }, | ||
39 | { 0x0a, KEY_8 }, | ||
40 | { 0x12, KEY_9 }, | ||
41 | { 0x02, KEY_0 }, | ||
42 | { 0x10, KEY_LAST }, /* +100 */ | ||
43 | { 0x13, KEY_LIST }, /* recall */ | ||
44 | |||
45 | { 0x1f, KEY_CHANNELUP }, /* chn down */ | ||
46 | { 0x17, KEY_CHANNELDOWN }, /* chn up */ | ||
47 | { 0x16, KEY_VOLUMEUP }, /* vol down */ | ||
48 | { 0x14, KEY_VOLUMEDOWN }, /* vol up */ | ||
49 | |||
50 | { 0x04, KEY_KPMINUS }, /* <<< */ | ||
51 | { 0x0e, KEY_SETUP }, /* function */ | ||
52 | { 0x0c, KEY_KPPLUS }, /* >>> */ | ||
53 | |||
54 | { 0x0d, KEY_GOTO }, /* mts */ | ||
55 | { 0x1d, KEY_REFRESH }, /* reset */ | ||
56 | { 0x18, KEY_MUTE }, /* mute/unmute */ | ||
57 | }; | ||
58 | |||
59 | static struct rc_keymap pixelview_map = { | ||
60 | .map = { | ||
61 | .scan = pixelview, | ||
62 | .size = ARRAY_SIZE(pixelview), | ||
63 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
64 | .name = RC_MAP_PIXELVIEW, | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static int __init init_rc_map_pixelview(void) | ||
69 | { | ||
70 | return ir_register_map(&pixelview_map); | ||
71 | } | ||
72 | |||
73 | static void __exit exit_rc_map_pixelview(void) | ||
74 | { | ||
75 | ir_unregister_map(&pixelview_map); | ||
76 | } | ||
77 | |||
78 | module_init(init_rc_map_pixelview) | ||
79 | module_exit(exit_rc_map_pixelview) | ||
80 | |||
81 | MODULE_LICENSE("GPL"); | ||
82 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c new file mode 100644 index 000000000000..7cef8190a224 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Remote control for Powercolor Real Angel 330 | ||
17 | * Daniel Fraga <fragabr@gmail.com> | ||
18 | */ | ||
19 | |||
20 | static struct ir_scancode powercolor_real_angel[] = { | ||
21 | { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ | ||
22 | { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ | ||
23 | { 0x00, KEY_0 }, | ||
24 | { 0x01, KEY_1 }, | ||
25 | { 0x02, KEY_2 }, | ||
26 | { 0x03, KEY_3 }, | ||
27 | { 0x04, KEY_4 }, | ||
28 | { 0x05, KEY_5 }, | ||
29 | { 0x06, KEY_6 }, | ||
30 | { 0x07, KEY_7 }, | ||
31 | { 0x08, KEY_8 }, | ||
32 | { 0x09, KEY_9 }, | ||
33 | { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ | ||
34 | { 0x29, KEY_PREVIOUS }, /* previous channel */ | ||
35 | { 0x12, KEY_BRIGHTNESSUP }, | ||
36 | { 0x13, KEY_BRIGHTNESSDOWN }, | ||
37 | { 0x2b, KEY_MODE }, /* stereo/mono */ | ||
38 | { 0x2c, KEY_TEXT }, /* teletext */ | ||
39 | { 0x20, KEY_CHANNELUP }, /* channel up */ | ||
40 | { 0x21, KEY_CHANNELDOWN }, /* channel down */ | ||
41 | { 0x10, KEY_VOLUMEUP }, /* volume up */ | ||
42 | { 0x11, KEY_VOLUMEDOWN }, /* volume down */ | ||
43 | { 0x0d, KEY_MUTE }, | ||
44 | { 0x1f, KEY_RECORD }, | ||
45 | { 0x17, KEY_PLAY }, | ||
46 | { 0x16, KEY_PAUSE }, | ||
47 | { 0x0b, KEY_STOP }, | ||
48 | { 0x27, KEY_FASTFORWARD }, | ||
49 | { 0x26, KEY_REWIND }, | ||
50 | { 0x1e, KEY_SEARCH }, /* autoscan */ | ||
51 | { 0x0e, KEY_CAMERA }, /* snapshot */ | ||
52 | { 0x2d, KEY_SETUP }, | ||
53 | { 0x0f, KEY_SCREEN }, /* full screen */ | ||
54 | { 0x14, KEY_RADIO }, /* FM radio */ | ||
55 | { 0x25, KEY_POWER }, /* power */ | ||
56 | }; | ||
57 | |||
58 | static struct rc_keymap powercolor_real_angel_map = { | ||
59 | .map = { | ||
60 | .scan = powercolor_real_angel, | ||
61 | .size = ARRAY_SIZE(powercolor_real_angel), | ||
62 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
63 | .name = RC_MAP_POWERCOLOR_REAL_ANGEL, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_powercolor_real_angel(void) | ||
68 | { | ||
69 | return ir_register_map(&powercolor_real_angel_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_powercolor_real_angel(void) | ||
73 | { | ||
74 | ir_unregister_map(&powercolor_real_angel_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_powercolor_real_angel) | ||
78 | module_exit(exit_rc_map_powercolor_real_angel) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-proteus-2309.c b/drivers/media/IR/keymaps/rc-proteus-2309.c new file mode 100644 index 000000000000..22e92d39dee5 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-proteus-2309.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* proteus-2309.h - Keytable for proteus_2309 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Michal Majchrowicz <mmajchrowicz@gmail.com> */ | ||
16 | |||
17 | static struct ir_scancode proteus_2309[] = { | ||
18 | /* numeric */ | ||
19 | { 0x00, KEY_0 }, | ||
20 | { 0x01, KEY_1 }, | ||
21 | { 0x02, KEY_2 }, | ||
22 | { 0x03, KEY_3 }, | ||
23 | { 0x04, KEY_4 }, | ||
24 | { 0x05, KEY_5 }, | ||
25 | { 0x06, KEY_6 }, | ||
26 | { 0x07, KEY_7 }, | ||
27 | { 0x08, KEY_8 }, | ||
28 | { 0x09, KEY_9 }, | ||
29 | |||
30 | { 0x5c, KEY_POWER }, /* power */ | ||
31 | { 0x20, KEY_ZOOM }, /* full screen */ | ||
32 | { 0x0f, KEY_BACKSPACE }, /* recall */ | ||
33 | { 0x1b, KEY_ENTER }, /* mute */ | ||
34 | { 0x41, KEY_RECORD }, /* record */ | ||
35 | { 0x43, KEY_STOP }, /* stop */ | ||
36 | { 0x16, KEY_S }, | ||
37 | { 0x1a, KEY_POWER2 }, /* off */ | ||
38 | { 0x2e, KEY_RED }, | ||
39 | { 0x1f, KEY_CHANNELDOWN }, /* channel - */ | ||
40 | { 0x1c, KEY_CHANNELUP }, /* channel + */ | ||
41 | { 0x10, KEY_VOLUMEDOWN }, /* volume - */ | ||
42 | { 0x1e, KEY_VOLUMEUP }, /* volume + */ | ||
43 | { 0x14, KEY_F1 }, | ||
44 | }; | ||
45 | |||
46 | static struct rc_keymap proteus_2309_map = { | ||
47 | .map = { | ||
48 | .scan = proteus_2309, | ||
49 | .size = ARRAY_SIZE(proteus_2309), | ||
50 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
51 | .name = RC_MAP_PROTEUS_2309, | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | static int __init init_rc_map_proteus_2309(void) | ||
56 | { | ||
57 | return ir_register_map(&proteus_2309_map); | ||
58 | } | ||
59 | |||
60 | static void __exit exit_rc_map_proteus_2309(void) | ||
61 | { | ||
62 | ir_unregister_map(&proteus_2309_map); | ||
63 | } | ||
64 | |||
65 | module_init(init_rc_map_proteus_2309) | ||
66 | module_exit(exit_rc_map_proteus_2309) | ||
67 | |||
68 | MODULE_LICENSE("GPL"); | ||
69 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-purpletv.c b/drivers/media/IR/keymaps/rc-purpletv.c new file mode 100644 index 000000000000..4e20fc2269f7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-purpletv.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* purpletv.h - Keytable for purpletv Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode purpletv[] = { | ||
16 | { 0x03, KEY_POWER }, | ||
17 | { 0x6f, KEY_MUTE }, | ||
18 | { 0x10, KEY_BACKSPACE }, /* Recall */ | ||
19 | |||
20 | { 0x11, KEY_0 }, | ||
21 | { 0x04, KEY_1 }, | ||
22 | { 0x05, KEY_2 }, | ||
23 | { 0x06, KEY_3 }, | ||
24 | { 0x08, KEY_4 }, | ||
25 | { 0x09, KEY_5 }, | ||
26 | { 0x0a, KEY_6 }, | ||
27 | { 0x0c, KEY_7 }, | ||
28 | { 0x0d, KEY_8 }, | ||
29 | { 0x0e, KEY_9 }, | ||
30 | { 0x12, KEY_DOT }, /* 100+ */ | ||
31 | |||
32 | { 0x07, KEY_VOLUMEUP }, | ||
33 | { 0x0b, KEY_VOLUMEDOWN }, | ||
34 | { 0x1a, KEY_KPPLUS }, | ||
35 | { 0x18, KEY_KPMINUS }, | ||
36 | { 0x15, KEY_UP }, | ||
37 | { 0x1d, KEY_DOWN }, | ||
38 | { 0x0f, KEY_CHANNELUP }, | ||
39 | { 0x13, KEY_CHANNELDOWN }, | ||
40 | { 0x48, KEY_ZOOM }, | ||
41 | |||
42 | { 0x1b, KEY_VIDEO }, /* Video source */ | ||
43 | { 0x1f, KEY_CAMERA }, /* Snapshot */ | ||
44 | { 0x49, KEY_LANGUAGE }, /* MTS Select */ | ||
45 | { 0x19, KEY_SEARCH }, /* Auto Scan */ | ||
46 | |||
47 | { 0x4b, KEY_RECORD }, | ||
48 | { 0x46, KEY_PLAY }, | ||
49 | { 0x45, KEY_PAUSE }, /* Pause */ | ||
50 | { 0x44, KEY_STOP }, | ||
51 | { 0x43, KEY_TIME }, /* Time Shift */ | ||
52 | { 0x17, KEY_CHANNEL }, /* SURF CH */ | ||
53 | { 0x40, KEY_FORWARD }, /* Forward ? */ | ||
54 | { 0x42, KEY_REWIND }, /* Backward ? */ | ||
55 | |||
56 | }; | ||
57 | |||
58 | static struct rc_keymap purpletv_map = { | ||
59 | .map = { | ||
60 | .scan = purpletv, | ||
61 | .size = ARRAY_SIZE(purpletv), | ||
62 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
63 | .name = RC_MAP_PURPLETV, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_purpletv(void) | ||
68 | { | ||
69 | return ir_register_map(&purpletv_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_purpletv(void) | ||
73 | { | ||
74 | ir_unregister_map(&purpletv_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_purpletv) | ||
78 | module_exit(exit_rc_map_purpletv) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-pv951.c b/drivers/media/IR/keymaps/rc-pv951.c new file mode 100644 index 000000000000..36679e706cf3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pv951.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* pv951.h - Keytable for pv951 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Mark Phalan <phalanm@o2.ie> */ | ||
16 | |||
17 | static struct ir_scancode pv951[] = { | ||
18 | { 0x00, KEY_0 }, | ||
19 | { 0x01, KEY_1 }, | ||
20 | { 0x02, KEY_2 }, | ||
21 | { 0x03, KEY_3 }, | ||
22 | { 0x04, KEY_4 }, | ||
23 | { 0x05, KEY_5 }, | ||
24 | { 0x06, KEY_6 }, | ||
25 | { 0x07, KEY_7 }, | ||
26 | { 0x08, KEY_8 }, | ||
27 | { 0x09, KEY_9 }, | ||
28 | |||
29 | { 0x12, KEY_POWER }, | ||
30 | { 0x10, KEY_MUTE }, | ||
31 | { 0x1f, KEY_VOLUMEDOWN }, | ||
32 | { 0x1b, KEY_VOLUMEUP }, | ||
33 | { 0x1a, KEY_CHANNELUP }, | ||
34 | { 0x1e, KEY_CHANNELDOWN }, | ||
35 | { 0x0e, KEY_PAGEUP }, | ||
36 | { 0x1d, KEY_PAGEDOWN }, | ||
37 | { 0x13, KEY_SOUND }, | ||
38 | |||
39 | { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ | ||
40 | { 0x16, KEY_SUBTITLE }, /* CC */ | ||
41 | { 0x0d, KEY_TEXT }, /* TTX */ | ||
42 | { 0x0b, KEY_TV }, /* AIR/CBL */ | ||
43 | { 0x11, KEY_PC }, /* PC/TV */ | ||
44 | { 0x17, KEY_OK }, /* CH RTN */ | ||
45 | { 0x19, KEY_MODE }, /* FUNC */ | ||
46 | { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ | ||
47 | |||
48 | /* Not sure what to do with these ones! */ | ||
49 | { 0x0f, KEY_SELECT }, /* SOURCE */ | ||
50 | { 0x0a, KEY_KPPLUS }, /* +100 */ | ||
51 | { 0x14, KEY_EQUAL }, /* SYNC */ | ||
52 | { 0x1c, KEY_MEDIA }, /* PC/TV */ | ||
53 | }; | ||
54 | |||
55 | static struct rc_keymap pv951_map = { | ||
56 | .map = { | ||
57 | .scan = pv951, | ||
58 | .size = ARRAY_SIZE(pv951), | ||
59 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
60 | .name = RC_MAP_PV951, | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | static int __init init_rc_map_pv951(void) | ||
65 | { | ||
66 | return ir_register_map(&pv951_map); | ||
67 | } | ||
68 | |||
69 | static void __exit exit_rc_map_pv951(void) | ||
70 | { | ||
71 | ir_unregister_map(&pv951_map); | ||
72 | } | ||
73 | |||
74 | module_init(init_rc_map_pv951) | ||
75 | module_exit(exit_rc_map_pv951) | ||
76 | |||
77 | MODULE_LICENSE("GPL"); | ||
78 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c new file mode 100644 index 000000000000..cc6b8f548747 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* | ||
16 | * Hauppauge:the newer, gray remotes (seems there are multiple | ||
17 | * slightly different versions), shipped with cx88+ivtv cards. | ||
18 | * | ||
19 | * This table contains the complete RC5 code, instead of just the data part | ||
20 | */ | ||
21 | |||
22 | static struct ir_scancode rc5_hauppauge_new[] = { | ||
23 | /* Keys 0 to 9 */ | ||
24 | { 0x1e00, KEY_0 }, | ||
25 | { 0x1e01, KEY_1 }, | ||
26 | { 0x1e02, KEY_2 }, | ||
27 | { 0x1e03, KEY_3 }, | ||
28 | { 0x1e04, KEY_4 }, | ||
29 | { 0x1e05, KEY_5 }, | ||
30 | { 0x1e06, KEY_6 }, | ||
31 | { 0x1e07, KEY_7 }, | ||
32 | { 0x1e08, KEY_8 }, | ||
33 | { 0x1e09, KEY_9 }, | ||
34 | |||
35 | { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
36 | { 0x1e0b, KEY_RED }, /* red button */ | ||
37 | { 0x1e0c, KEY_RADIO }, | ||
38 | { 0x1e0d, KEY_MENU }, | ||
39 | { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ | ||
40 | { 0x1e0f, KEY_MUTE }, | ||
41 | { 0x1e10, KEY_VOLUMEUP }, | ||
42 | { 0x1e11, KEY_VOLUMEDOWN }, | ||
43 | { 0x1e12, KEY_PREVIOUS }, /* previous channel */ | ||
44 | { 0x1e14, KEY_UP }, | ||
45 | { 0x1e15, KEY_DOWN }, | ||
46 | { 0x1e16, KEY_LEFT }, | ||
47 | { 0x1e17, KEY_RIGHT }, | ||
48 | { 0x1e18, KEY_VIDEO }, /* Videos */ | ||
49 | { 0x1e19, KEY_AUDIO }, /* Music */ | ||
50 | /* 0x1e1a: Pictures - presume this means | ||
51 | "Multimedia Home Platform" - | ||
52 | no "PICTURES" key in input.h | ||
53 | */ | ||
54 | { 0x1e1a, KEY_MHP }, | ||
55 | |||
56 | { 0x1e1b, KEY_EPG }, /* Guide */ | ||
57 | { 0x1e1c, KEY_TV }, | ||
58 | { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ | ||
59 | { 0x1e1f, KEY_EXIT }, /* back/exit */ | ||
60 | { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ | ||
61 | { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
62 | { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ | ||
63 | { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
64 | { 0x1e25, KEY_ENTER }, /* OK */ | ||
65 | { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
66 | { 0x1e29, KEY_BLUE }, /* blue key */ | ||
67 | { 0x1e2e, KEY_GREEN }, /* green button */ | ||
68 | { 0x1e30, KEY_PAUSE }, /* pause */ | ||
69 | { 0x1e32, KEY_REWIND }, /* backward << */ | ||
70 | { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ | ||
71 | { 0x1e35, KEY_PLAY }, | ||
72 | { 0x1e36, KEY_STOP }, | ||
73 | { 0x1e37, KEY_RECORD }, /* recording */ | ||
74 | { 0x1e38, KEY_YELLOW }, /* yellow key */ | ||
75 | { 0x1e3b, KEY_SELECT }, /* top right button */ | ||
76 | { 0x1e3c, KEY_ZOOM }, /* full */ | ||
77 | { 0x1e3d, KEY_POWER }, /* system power (green button) */ | ||
78 | }; | ||
79 | |||
80 | static struct rc_keymap rc5_hauppauge_new_map = { | ||
81 | .map = { | ||
82 | .scan = rc5_hauppauge_new, | ||
83 | .size = ARRAY_SIZE(rc5_hauppauge_new), | ||
84 | .ir_type = IR_TYPE_RC5, | ||
85 | .name = RC_MAP_RC5_HAUPPAUGE_NEW, | ||
86 | } | ||
87 | }; | ||
88 | |||
89 | static int __init init_rc_map_rc5_hauppauge_new(void) | ||
90 | { | ||
91 | return ir_register_map(&rc5_hauppauge_new_map); | ||
92 | } | ||
93 | |||
94 | static void __exit exit_rc_map_rc5_hauppauge_new(void) | ||
95 | { | ||
96 | ir_unregister_map(&rc5_hauppauge_new_map); | ||
97 | } | ||
98 | |||
99 | module_init(init_rc_map_rc5_hauppauge_new) | ||
100 | module_exit(exit_rc_map_rc5_hauppauge_new) | ||
101 | |||
102 | MODULE_LICENSE("GPL"); | ||
103 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-rc5-tv.c b/drivers/media/IR/keymaps/rc-rc5-tv.c new file mode 100644 index 000000000000..73cce2f8ddfb --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-tv.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* rc5-tv.h - Keytable for rc5_tv Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* generic RC5 keytable */ | ||
16 | /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ | ||
17 | /* used by old (black) Hauppauge remotes */ | ||
18 | |||
19 | static struct ir_scancode rc5_tv[] = { | ||
20 | /* Keys 0 to 9 */ | ||
21 | { 0x00, KEY_0 }, | ||
22 | { 0x01, KEY_1 }, | ||
23 | { 0x02, KEY_2 }, | ||
24 | { 0x03, KEY_3 }, | ||
25 | { 0x04, KEY_4 }, | ||
26 | { 0x05, KEY_5 }, | ||
27 | { 0x06, KEY_6 }, | ||
28 | { 0x07, KEY_7 }, | ||
29 | { 0x08, KEY_8 }, | ||
30 | { 0x09, KEY_9 }, | ||
31 | |||
32 | { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ | ||
33 | { 0x0c, KEY_POWER }, /* standby */ | ||
34 | { 0x0d, KEY_MUTE }, /* mute / demute */ | ||
35 | { 0x0f, KEY_TV }, /* display */ | ||
36 | { 0x10, KEY_VOLUMEUP }, | ||
37 | { 0x11, KEY_VOLUMEDOWN }, | ||
38 | { 0x12, KEY_BRIGHTNESSUP }, | ||
39 | { 0x13, KEY_BRIGHTNESSDOWN }, | ||
40 | { 0x1e, KEY_SEARCH }, /* search + */ | ||
41 | { 0x20, KEY_CHANNELUP }, /* channel / program + */ | ||
42 | { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
43 | { 0x22, KEY_CHANNEL }, /* alt / channel */ | ||
44 | { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ | ||
45 | { 0x26, KEY_SLEEP }, /* sleeptimer */ | ||
46 | { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ | ||
47 | { 0x30, KEY_PAUSE }, | ||
48 | { 0x32, KEY_REWIND }, | ||
49 | { 0x33, KEY_GOTO }, | ||
50 | { 0x35, KEY_PLAY }, | ||
51 | { 0x36, KEY_STOP }, | ||
52 | { 0x37, KEY_RECORD }, /* recording */ | ||
53 | { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ | ||
54 | { 0x3d, KEY_SUSPEND }, /* system standby */ | ||
55 | |||
56 | }; | ||
57 | |||
58 | static struct rc_keymap rc5_tv_map = { | ||
59 | .map = { | ||
60 | .scan = rc5_tv, | ||
61 | .size = ARRAY_SIZE(rc5_tv), | ||
62 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
63 | .name = RC_MAP_RC5_TV, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_rc5_tv(void) | ||
68 | { | ||
69 | return ir_register_map(&rc5_tv_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_rc5_tv(void) | ||
73 | { | ||
74 | ir_unregister_map(&rc5_tv_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_rc5_tv) | ||
78 | module_exit(exit_rc_map_rc5_tv) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c new file mode 100644 index 000000000000..ab1a6d2baf72 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Zogis Real Audio 220 - 32 keys IR */ | ||
16 | |||
17 | static struct ir_scancode real_audio_220_32_keys[] = { | ||
18 | { 0x1c, KEY_RADIO}, | ||
19 | { 0x12, KEY_POWER2}, | ||
20 | |||
21 | { 0x01, KEY_1}, | ||
22 | { 0x02, KEY_2}, | ||
23 | { 0x03, KEY_3}, | ||
24 | { 0x04, KEY_4}, | ||
25 | { 0x05, KEY_5}, | ||
26 | { 0x06, KEY_6}, | ||
27 | { 0x07, KEY_7}, | ||
28 | { 0x08, KEY_8}, | ||
29 | { 0x09, KEY_9}, | ||
30 | { 0x00, KEY_0}, | ||
31 | |||
32 | { 0x0c, KEY_VOLUMEUP}, | ||
33 | { 0x18, KEY_VOLUMEDOWN}, | ||
34 | { 0x0b, KEY_CHANNELUP}, | ||
35 | { 0x15, KEY_CHANNELDOWN}, | ||
36 | { 0x16, KEY_ENTER}, | ||
37 | |||
38 | { 0x11, KEY_LIST}, /* Source */ | ||
39 | { 0x0d, KEY_AUDIO}, /* stereo */ | ||
40 | |||
41 | { 0x0f, KEY_PREVIOUS}, /* Prev */ | ||
42 | { 0x1b, KEY_TIME}, /* Timeshift */ | ||
43 | { 0x1a, KEY_NEXT}, /* Next */ | ||
44 | |||
45 | { 0x0e, KEY_STOP}, | ||
46 | { 0x1f, KEY_PLAY}, | ||
47 | { 0x1e, KEY_PLAYPAUSE}, /* Pause */ | ||
48 | |||
49 | { 0x1d, KEY_RECORD}, | ||
50 | { 0x13, KEY_MUTE}, | ||
51 | { 0x19, KEY_CAMERA}, /* Snapshot */ | ||
52 | |||
53 | }; | ||
54 | |||
55 | static struct rc_keymap real_audio_220_32_keys_map = { | ||
56 | .map = { | ||
57 | .scan = real_audio_220_32_keys, | ||
58 | .size = ARRAY_SIZE(real_audio_220_32_keys), | ||
59 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
60 | .name = RC_MAP_REAL_AUDIO_220_32_KEYS, | ||
61 | } | ||
62 | }; | ||
63 | |||
64 | static int __init init_rc_map_real_audio_220_32_keys(void) | ||
65 | { | ||
66 | return ir_register_map(&real_audio_220_32_keys_map); | ||
67 | } | ||
68 | |||
69 | static void __exit exit_rc_map_real_audio_220_32_keys(void) | ||
70 | { | ||
71 | ir_unregister_map(&real_audio_220_32_keys_map); | ||
72 | } | ||
73 | |||
74 | module_init(init_rc_map_real_audio_220_32_keys) | ||
75 | module_exit(exit_rc_map_real_audio_220_32_keys) | ||
76 | |||
77 | MODULE_LICENSE("GPL"); | ||
78 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-tbs-nec.c b/drivers/media/IR/keymaps/rc-tbs-nec.c new file mode 100644 index 000000000000..3309631e6f80 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tbs-nec.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* tbs-nec.h - Keytable for tbs_nec Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode tbs_nec[] = { | ||
16 | { 0x04, KEY_POWER2}, /*power*/ | ||
17 | { 0x14, KEY_MUTE}, /*mute*/ | ||
18 | { 0x07, KEY_1}, | ||
19 | { 0x06, KEY_2}, | ||
20 | { 0x05, KEY_3}, | ||
21 | { 0x0b, KEY_4}, | ||
22 | { 0x0a, KEY_5}, | ||
23 | { 0x09, KEY_6}, | ||
24 | { 0x0f, KEY_7}, | ||
25 | { 0x0e, KEY_8}, | ||
26 | { 0x0d, KEY_9}, | ||
27 | { 0x12, KEY_0}, | ||
28 | { 0x16, KEY_CHANNELUP}, /*ch+*/ | ||
29 | { 0x11, KEY_CHANNELDOWN},/*ch-*/ | ||
30 | { 0x13, KEY_VOLUMEUP}, /*vol+*/ | ||
31 | { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ | ||
32 | { 0x03, KEY_RECORD}, /*rec*/ | ||
33 | { 0x18, KEY_PAUSE}, /*pause*/ | ||
34 | { 0x19, KEY_OK}, /*ok*/ | ||
35 | { 0x1a, KEY_CAMERA}, /* snapshot */ | ||
36 | { 0x01, KEY_UP}, | ||
37 | { 0x10, KEY_LEFT}, | ||
38 | { 0x02, KEY_RIGHT}, | ||
39 | { 0x08, KEY_DOWN}, | ||
40 | { 0x15, KEY_FAVORITES}, | ||
41 | { 0x17, KEY_SUBTITLE}, | ||
42 | { 0x1d, KEY_ZOOM}, | ||
43 | { 0x1f, KEY_EXIT}, | ||
44 | { 0x1e, KEY_MENU}, | ||
45 | { 0x1c, KEY_EPG}, | ||
46 | { 0x00, KEY_PREVIOUS}, | ||
47 | { 0x1b, KEY_MODE}, | ||
48 | }; | ||
49 | |||
50 | static struct rc_keymap tbs_nec_map = { | ||
51 | .map = { | ||
52 | .scan = tbs_nec, | ||
53 | .size = ARRAY_SIZE(tbs_nec), | ||
54 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
55 | .name = RC_MAP_TBS_NEC, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | static int __init init_rc_map_tbs_nec(void) | ||
60 | { | ||
61 | return ir_register_map(&tbs_nec_map); | ||
62 | } | ||
63 | |||
64 | static void __exit exit_rc_map_tbs_nec(void) | ||
65 | { | ||
66 | ir_unregister_map(&tbs_nec_map); | ||
67 | } | ||
68 | |||
69 | module_init(init_rc_map_tbs_nec) | ||
70 | module_exit(exit_rc_map_tbs_nec) | ||
71 | |||
72 | MODULE_LICENSE("GPL"); | ||
73 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c new file mode 100644 index 000000000000..5326a0b444c1 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Terratec Cinergy Hybrid T USB XS | ||
16 | Devin Heitmueller <dheitmueller@linuxtv.org> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode terratec_cinergy_xs[] = { | ||
20 | { 0x41, KEY_HOME}, | ||
21 | { 0x01, KEY_POWER}, | ||
22 | { 0x42, KEY_MENU}, | ||
23 | { 0x02, KEY_1}, | ||
24 | { 0x03, KEY_2}, | ||
25 | { 0x04, KEY_3}, | ||
26 | { 0x43, KEY_SUBTITLE}, | ||
27 | { 0x05, KEY_4}, | ||
28 | { 0x06, KEY_5}, | ||
29 | { 0x07, KEY_6}, | ||
30 | { 0x44, KEY_TEXT}, | ||
31 | { 0x08, KEY_7}, | ||
32 | { 0x09, KEY_8}, | ||
33 | { 0x0a, KEY_9}, | ||
34 | { 0x45, KEY_DELETE}, | ||
35 | { 0x0b, KEY_TUNER}, | ||
36 | { 0x0c, KEY_0}, | ||
37 | { 0x0d, KEY_MODE}, | ||
38 | { 0x46, KEY_TV}, | ||
39 | { 0x47, KEY_DVD}, | ||
40 | { 0x49, KEY_VIDEO}, | ||
41 | { 0x4b, KEY_AUX}, | ||
42 | { 0x10, KEY_UP}, | ||
43 | { 0x11, KEY_LEFT}, | ||
44 | { 0x12, KEY_OK}, | ||
45 | { 0x13, KEY_RIGHT}, | ||
46 | { 0x14, KEY_DOWN}, | ||
47 | { 0x0f, KEY_EPG}, | ||
48 | { 0x16, KEY_INFO}, | ||
49 | { 0x4d, KEY_BACKSPACE}, | ||
50 | { 0x1c, KEY_VOLUMEUP}, | ||
51 | { 0x4c, KEY_PLAY}, | ||
52 | { 0x1b, KEY_CHANNELUP}, | ||
53 | { 0x1e, KEY_VOLUMEDOWN}, | ||
54 | { 0x1d, KEY_MUTE}, | ||
55 | { 0x1f, KEY_CHANNELDOWN}, | ||
56 | { 0x17, KEY_RED}, | ||
57 | { 0x18, KEY_GREEN}, | ||
58 | { 0x19, KEY_YELLOW}, | ||
59 | { 0x1a, KEY_BLUE}, | ||
60 | { 0x58, KEY_RECORD}, | ||
61 | { 0x48, KEY_STOP}, | ||
62 | { 0x40, KEY_PAUSE}, | ||
63 | { 0x54, KEY_LAST}, | ||
64 | { 0x4e, KEY_REWIND}, | ||
65 | { 0x4f, KEY_FASTFORWARD}, | ||
66 | { 0x5c, KEY_NEXT}, | ||
67 | }; | ||
68 | |||
69 | static struct rc_keymap terratec_cinergy_xs_map = { | ||
70 | .map = { | ||
71 | .scan = terratec_cinergy_xs, | ||
72 | .size = ARRAY_SIZE(terratec_cinergy_xs), | ||
73 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
74 | .name = RC_MAP_TERRATEC_CINERGY_XS, | ||
75 | } | ||
76 | }; | ||
77 | |||
78 | static int __init init_rc_map_terratec_cinergy_xs(void) | ||
79 | { | ||
80 | return ir_register_map(&terratec_cinergy_xs_map); | ||
81 | } | ||
82 | |||
83 | static void __exit exit_rc_map_terratec_cinergy_xs(void) | ||
84 | { | ||
85 | ir_unregister_map(&terratec_cinergy_xs_map); | ||
86 | } | ||
87 | |||
88 | module_init(init_rc_map_terratec_cinergy_xs) | ||
89 | module_exit(exit_rc_map_terratec_cinergy_xs) | ||
90 | |||
91 | MODULE_LICENSE("GPL"); | ||
92 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-tevii-nec.c b/drivers/media/IR/keymaps/rc-tevii-nec.c new file mode 100644 index 000000000000..e30d411c07bb --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tevii-nec.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* tevii-nec.h - Keytable for tevii_nec Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode tevii_nec[] = { | ||
16 | { 0x0a, KEY_POWER2}, | ||
17 | { 0x0c, KEY_MUTE}, | ||
18 | { 0x11, KEY_1}, | ||
19 | { 0x12, KEY_2}, | ||
20 | { 0x13, KEY_3}, | ||
21 | { 0x14, KEY_4}, | ||
22 | { 0x15, KEY_5}, | ||
23 | { 0x16, KEY_6}, | ||
24 | { 0x17, KEY_7}, | ||
25 | { 0x18, KEY_8}, | ||
26 | { 0x19, KEY_9}, | ||
27 | { 0x10, KEY_0}, | ||
28 | { 0x1c, KEY_MENU}, | ||
29 | { 0x0f, KEY_VOLUMEDOWN}, | ||
30 | { 0x1a, KEY_LAST}, | ||
31 | { 0x0e, KEY_OPEN}, | ||
32 | { 0x04, KEY_RECORD}, | ||
33 | { 0x09, KEY_VOLUMEUP}, | ||
34 | { 0x08, KEY_CHANNELUP}, | ||
35 | { 0x07, KEY_PVR}, | ||
36 | { 0x0b, KEY_TIME}, | ||
37 | { 0x02, KEY_RIGHT}, | ||
38 | { 0x03, KEY_LEFT}, | ||
39 | { 0x00, KEY_UP}, | ||
40 | { 0x1f, KEY_OK}, | ||
41 | { 0x01, KEY_DOWN}, | ||
42 | { 0x05, KEY_TUNER}, | ||
43 | { 0x06, KEY_CHANNELDOWN}, | ||
44 | { 0x40, KEY_PLAYPAUSE}, | ||
45 | { 0x1e, KEY_REWIND}, | ||
46 | { 0x1b, KEY_FAVORITES}, | ||
47 | { 0x1d, KEY_BACK}, | ||
48 | { 0x4d, KEY_FASTFORWARD}, | ||
49 | { 0x44, KEY_EPG}, | ||
50 | { 0x4c, KEY_INFO}, | ||
51 | { 0x41, KEY_AB}, | ||
52 | { 0x43, KEY_AUDIO}, | ||
53 | { 0x45, KEY_SUBTITLE}, | ||
54 | { 0x4a, KEY_LIST}, | ||
55 | { 0x46, KEY_F1}, | ||
56 | { 0x47, KEY_F2}, | ||
57 | { 0x5e, KEY_F3}, | ||
58 | { 0x5c, KEY_F4}, | ||
59 | { 0x52, KEY_F5}, | ||
60 | { 0x5a, KEY_F6}, | ||
61 | { 0x56, KEY_MODE}, | ||
62 | { 0x58, KEY_SWITCHVIDEOMODE}, | ||
63 | }; | ||
64 | |||
65 | static struct rc_keymap tevii_nec_map = { | ||
66 | .map = { | ||
67 | .scan = tevii_nec, | ||
68 | .size = ARRAY_SIZE(tevii_nec), | ||
69 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
70 | .name = RC_MAP_TEVII_NEC, | ||
71 | } | ||
72 | }; | ||
73 | |||
74 | static int __init init_rc_map_tevii_nec(void) | ||
75 | { | ||
76 | return ir_register_map(&tevii_nec_map); | ||
77 | } | ||
78 | |||
79 | static void __exit exit_rc_map_tevii_nec(void) | ||
80 | { | ||
81 | ir_unregister_map(&tevii_nec_map); | ||
82 | } | ||
83 | |||
84 | module_init(init_rc_map_tevii_nec) | ||
85 | module_exit(exit_rc_map_tevii_nec) | ||
86 | |||
87 | MODULE_LICENSE("GPL"); | ||
88 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-tt-1500.c b/drivers/media/IR/keymaps/rc-tt-1500.c new file mode 100644 index 000000000000..bc88de011d5d --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tt-1500.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* tt-1500.h - Keytable for tt_1500 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* for the Technotrend 1500 bundled remotes (grey and black): */ | ||
16 | |||
17 | static struct ir_scancode tt_1500[] = { | ||
18 | { 0x01, KEY_POWER }, | ||
19 | { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ | ||
20 | { 0x03, KEY_1 }, | ||
21 | { 0x04, KEY_2 }, | ||
22 | { 0x05, KEY_3 }, | ||
23 | { 0x06, KEY_4 }, | ||
24 | { 0x07, KEY_5 }, | ||
25 | { 0x08, KEY_6 }, | ||
26 | { 0x09, KEY_7 }, | ||
27 | { 0x0a, KEY_8 }, | ||
28 | { 0x0b, KEY_9 }, | ||
29 | { 0x0c, KEY_0 }, | ||
30 | { 0x0d, KEY_UP }, | ||
31 | { 0x0e, KEY_LEFT }, | ||
32 | { 0x0f, KEY_OK }, | ||
33 | { 0x10, KEY_RIGHT }, | ||
34 | { 0x11, KEY_DOWN }, | ||
35 | { 0x12, KEY_INFO }, | ||
36 | { 0x13, KEY_EXIT }, | ||
37 | { 0x14, KEY_RED }, | ||
38 | { 0x15, KEY_GREEN }, | ||
39 | { 0x16, KEY_YELLOW }, | ||
40 | { 0x17, KEY_BLUE }, | ||
41 | { 0x18, KEY_MUTE }, | ||
42 | { 0x19, KEY_TEXT }, | ||
43 | { 0x1a, KEY_MODE }, /* ? TV/Radio */ | ||
44 | { 0x21, KEY_OPTION }, | ||
45 | { 0x22, KEY_EPG }, | ||
46 | { 0x23, KEY_CHANNELUP }, | ||
47 | { 0x24, KEY_CHANNELDOWN }, | ||
48 | { 0x25, KEY_VOLUMEUP }, | ||
49 | { 0x26, KEY_VOLUMEDOWN }, | ||
50 | { 0x27, KEY_SETUP }, | ||
51 | { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ | ||
52 | { 0x3b, KEY_PLAY }, | ||
53 | { 0x3c, KEY_STOP }, | ||
54 | { 0x3d, KEY_REWIND }, | ||
55 | { 0x3e, KEY_PAUSE }, | ||
56 | { 0x3f, KEY_FORWARD }, | ||
57 | }; | ||
58 | |||
59 | static struct rc_keymap tt_1500_map = { | ||
60 | .map = { | ||
61 | .scan = tt_1500, | ||
62 | .size = ARRAY_SIZE(tt_1500), | ||
63 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
64 | .name = RC_MAP_TT_1500, | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static int __init init_rc_map_tt_1500(void) | ||
69 | { | ||
70 | return ir_register_map(&tt_1500_map); | ||
71 | } | ||
72 | |||
73 | static void __exit exit_rc_map_tt_1500(void) | ||
74 | { | ||
75 | ir_unregister_map(&tt_1500_map); | ||
76 | } | ||
77 | |||
78 | module_init(init_rc_map_tt_1500) | ||
79 | module_exit(exit_rc_map_tt_1500) | ||
80 | |||
81 | MODULE_LICENSE("GPL"); | ||
82 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-videomate-s350.c b/drivers/media/IR/keymaps/rc-videomate-s350.c new file mode 100644 index 000000000000..4df7fcd1d2fc --- /dev/null +++ b/drivers/media/IR/keymaps/rc-videomate-s350.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* videomate-s350.h - Keytable for videomate_s350 Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode videomate_s350[] = { | ||
16 | { 0x00, KEY_TV}, | ||
17 | { 0x01, KEY_DVD}, | ||
18 | { 0x04, KEY_RECORD}, | ||
19 | { 0x05, KEY_VIDEO}, /* TV/Video */ | ||
20 | { 0x07, KEY_STOP}, | ||
21 | { 0x08, KEY_PLAYPAUSE}, | ||
22 | { 0x0a, KEY_REWIND}, | ||
23 | { 0x0f, KEY_FASTFORWARD}, | ||
24 | { 0x10, KEY_CHANNELUP}, | ||
25 | { 0x12, KEY_VOLUMEUP}, | ||
26 | { 0x13, KEY_CHANNELDOWN}, | ||
27 | { 0x14, KEY_MUTE}, | ||
28 | { 0x15, KEY_VOLUMEDOWN}, | ||
29 | { 0x16, KEY_1}, | ||
30 | { 0x17, KEY_2}, | ||
31 | { 0x18, KEY_3}, | ||
32 | { 0x19, KEY_4}, | ||
33 | { 0x1a, KEY_5}, | ||
34 | { 0x1b, KEY_6}, | ||
35 | { 0x1c, KEY_7}, | ||
36 | { 0x1d, KEY_8}, | ||
37 | { 0x1e, KEY_9}, | ||
38 | { 0x1f, KEY_0}, | ||
39 | { 0x21, KEY_SLEEP}, | ||
40 | { 0x24, KEY_ZOOM}, | ||
41 | { 0x25, KEY_LAST}, /* Recall */ | ||
42 | { 0x26, KEY_SUBTITLE}, /* CC */ | ||
43 | { 0x27, KEY_LANGUAGE}, /* MTS */ | ||
44 | { 0x29, KEY_CHANNEL}, /* SURF */ | ||
45 | { 0x2b, KEY_A}, | ||
46 | { 0x2c, KEY_B}, | ||
47 | { 0x2f, KEY_CAMERA}, /* Snapshot */ | ||
48 | { 0x23, KEY_RADIO}, | ||
49 | { 0x02, KEY_PREVIOUSSONG}, | ||
50 | { 0x06, KEY_NEXTSONG}, | ||
51 | { 0x03, KEY_EPG}, | ||
52 | { 0x09, KEY_SETUP}, | ||
53 | { 0x22, KEY_BACKSPACE}, | ||
54 | { 0x0c, KEY_UP}, | ||
55 | { 0x0e, KEY_DOWN}, | ||
56 | { 0x0b, KEY_LEFT}, | ||
57 | { 0x0d, KEY_RIGHT}, | ||
58 | { 0x11, KEY_ENTER}, | ||
59 | { 0x20, KEY_TEXT}, | ||
60 | }; | ||
61 | |||
62 | static struct rc_keymap videomate_s350_map = { | ||
63 | .map = { | ||
64 | .scan = videomate_s350, | ||
65 | .size = ARRAY_SIZE(videomate_s350), | ||
66 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
67 | .name = RC_MAP_VIDEOMATE_S350, | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | static int __init init_rc_map_videomate_s350(void) | ||
72 | { | ||
73 | return ir_register_map(&videomate_s350_map); | ||
74 | } | ||
75 | |||
76 | static void __exit exit_rc_map_videomate_s350(void) | ||
77 | { | ||
78 | ir_unregister_map(&videomate_s350_map); | ||
79 | } | ||
80 | |||
81 | module_init(init_rc_map_videomate_s350) | ||
82 | module_exit(exit_rc_map_videomate_s350) | ||
83 | |||
84 | MODULE_LICENSE("GPL"); | ||
85 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c new file mode 100644 index 000000000000..776b0a638d87 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | static struct ir_scancode videomate_tv_pvr[] = { | ||
16 | { 0x14, KEY_MUTE }, | ||
17 | { 0x24, KEY_ZOOM }, | ||
18 | |||
19 | { 0x01, KEY_DVD }, | ||
20 | { 0x23, KEY_RADIO }, | ||
21 | { 0x00, KEY_TV }, | ||
22 | |||
23 | { 0x0a, KEY_REWIND }, | ||
24 | { 0x08, KEY_PLAYPAUSE }, | ||
25 | { 0x0f, KEY_FORWARD }, | ||
26 | |||
27 | { 0x02, KEY_PREVIOUS }, | ||
28 | { 0x07, KEY_STOP }, | ||
29 | { 0x06, KEY_NEXT }, | ||
30 | |||
31 | { 0x0c, KEY_UP }, | ||
32 | { 0x0e, KEY_DOWN }, | ||
33 | { 0x0b, KEY_LEFT }, | ||
34 | { 0x0d, KEY_RIGHT }, | ||
35 | { 0x11, KEY_OK }, | ||
36 | |||
37 | { 0x03, KEY_MENU }, | ||
38 | { 0x09, KEY_SETUP }, | ||
39 | { 0x05, KEY_VIDEO }, | ||
40 | { 0x22, KEY_CHANNEL }, | ||
41 | |||
42 | { 0x12, KEY_VOLUMEUP }, | ||
43 | { 0x15, KEY_VOLUMEDOWN }, | ||
44 | { 0x10, KEY_CHANNELUP }, | ||
45 | { 0x13, KEY_CHANNELDOWN }, | ||
46 | |||
47 | { 0x04, KEY_RECORD }, | ||
48 | |||
49 | { 0x16, KEY_1 }, | ||
50 | { 0x17, KEY_2 }, | ||
51 | { 0x18, KEY_3 }, | ||
52 | { 0x19, KEY_4 }, | ||
53 | { 0x1a, KEY_5 }, | ||
54 | { 0x1b, KEY_6 }, | ||
55 | { 0x1c, KEY_7 }, | ||
56 | { 0x1d, KEY_8 }, | ||
57 | { 0x1e, KEY_9 }, | ||
58 | { 0x1f, KEY_0 }, | ||
59 | |||
60 | { 0x20, KEY_LANGUAGE }, | ||
61 | { 0x21, KEY_SLEEP }, | ||
62 | }; | ||
63 | |||
64 | static struct rc_keymap videomate_tv_pvr_map = { | ||
65 | .map = { | ||
66 | .scan = videomate_tv_pvr, | ||
67 | .size = ARRAY_SIZE(videomate_tv_pvr), | ||
68 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
69 | .name = RC_MAP_VIDEOMATE_TV_PVR, | ||
70 | } | ||
71 | }; | ||
72 | |||
73 | static int __init init_rc_map_videomate_tv_pvr(void) | ||
74 | { | ||
75 | return ir_register_map(&videomate_tv_pvr_map); | ||
76 | } | ||
77 | |||
78 | static void __exit exit_rc_map_videomate_tv_pvr(void) | ||
79 | { | ||
80 | ir_unregister_map(&videomate_tv_pvr_map); | ||
81 | } | ||
82 | |||
83 | module_init(init_rc_map_videomate_tv_pvr) | ||
84 | module_exit(exit_rc_map_videomate_tv_pvr) | ||
85 | |||
86 | MODULE_LICENSE("GPL"); | ||
87 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c new file mode 100644 index 000000000000..9d2d550aaa90 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Leadtek Winfast TV USB II Deluxe remote | ||
16 | Magnus Alm <magnus.alm@gmail.com> | ||
17 | */ | ||
18 | |||
19 | static struct ir_scancode winfast_usbii_deluxe[] = { | ||
20 | { 0x62, KEY_0}, | ||
21 | { 0x75, KEY_1}, | ||
22 | { 0x76, KEY_2}, | ||
23 | { 0x77, KEY_3}, | ||
24 | { 0x79, KEY_4}, | ||
25 | { 0x7a, KEY_5}, | ||
26 | { 0x7b, KEY_6}, | ||
27 | { 0x7d, KEY_7}, | ||
28 | { 0x7e, KEY_8}, | ||
29 | { 0x7f, KEY_9}, | ||
30 | |||
31 | { 0x38, KEY_CAMERA}, /* SNAPSHOT */ | ||
32 | { 0x37, KEY_RECORD}, /* RECORD */ | ||
33 | { 0x35, KEY_TIME}, /* TIMESHIFT */ | ||
34 | |||
35 | { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
36 | { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
37 | { 0x64, KEY_MUTE}, /* MUTE */ | ||
38 | |||
39 | { 0x21, KEY_CHANNEL}, /* SURF */ | ||
40 | { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ | ||
41 | { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
42 | { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ | ||
43 | |||
44 | { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ | ||
45 | |||
46 | { 0x70, KEY_POWER2}, /* TV ON/OFF */ | ||
47 | |||
48 | { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ | ||
49 | { 0x3a, KEY_NEW}, /* PIP */ | ||
50 | { 0x73, KEY_ZOOM}, /* FULLSECREEN */ | ||
51 | |||
52 | { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ | ||
53 | |||
54 | { 0x31, KEY_DOT}, /* '.' */ | ||
55 | { 0x63, KEY_ENTER}, /* ENTER */ | ||
56 | |||
57 | }; | ||
58 | |||
59 | static struct rc_keymap winfast_usbii_deluxe_map = { | ||
60 | .map = { | ||
61 | .scan = winfast_usbii_deluxe, | ||
62 | .size = ARRAY_SIZE(winfast_usbii_deluxe), | ||
63 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
64 | .name = RC_MAP_WINFAST_USBII_DELUXE, | ||
65 | } | ||
66 | }; | ||
67 | |||
68 | static int __init init_rc_map_winfast_usbii_deluxe(void) | ||
69 | { | ||
70 | return ir_register_map(&winfast_usbii_deluxe_map); | ||
71 | } | ||
72 | |||
73 | static void __exit exit_rc_map_winfast_usbii_deluxe(void) | ||
74 | { | ||
75 | ir_unregister_map(&winfast_usbii_deluxe_map); | ||
76 | } | ||
77 | |||
78 | module_init(init_rc_map_winfast_usbii_deluxe) | ||
79 | module_exit(exit_rc_map_winfast_usbii_deluxe) | ||
80 | |||
81 | MODULE_LICENSE("GPL"); | ||
82 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-winfast.c b/drivers/media/IR/keymaps/rc-winfast.c new file mode 100644 index 000000000000..0e90a3bd9499 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-winfast.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* winfast.h - Keytable for winfast Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ | ||
16 | |||
17 | static struct ir_scancode winfast[] = { | ||
18 | /* Keys 0 to 9 */ | ||
19 | { 0x12, KEY_0 }, | ||
20 | { 0x05, KEY_1 }, | ||
21 | { 0x06, KEY_2 }, | ||
22 | { 0x07, KEY_3 }, | ||
23 | { 0x09, KEY_4 }, | ||
24 | { 0x0a, KEY_5 }, | ||
25 | { 0x0b, KEY_6 }, | ||
26 | { 0x0d, KEY_7 }, | ||
27 | { 0x0e, KEY_8 }, | ||
28 | { 0x0f, KEY_9 }, | ||
29 | |||
30 | { 0x00, KEY_POWER }, | ||
31 | { 0x1b, KEY_AUDIO }, /* Audio Source */ | ||
32 | { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ | ||
33 | { 0x1e, KEY_VIDEO }, /* Video Source */ | ||
34 | { 0x16, KEY_INFO }, /* Display information */ | ||
35 | { 0x04, KEY_VOLUMEUP }, | ||
36 | { 0x08, KEY_VOLUMEDOWN }, | ||
37 | { 0x0c, KEY_CHANNELUP }, | ||
38 | { 0x10, KEY_CHANNELDOWN }, | ||
39 | { 0x03, KEY_ZOOM }, /* fullscreen */ | ||
40 | { 0x1f, KEY_TEXT }, /* closed caption/teletext */ | ||
41 | { 0x20, KEY_SLEEP }, | ||
42 | { 0x29, KEY_CLEAR }, /* boss key */ | ||
43 | { 0x14, KEY_MUTE }, | ||
44 | { 0x2b, KEY_RED }, | ||
45 | { 0x2c, KEY_GREEN }, | ||
46 | { 0x2d, KEY_YELLOW }, | ||
47 | { 0x2e, KEY_BLUE }, | ||
48 | { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ | ||
49 | { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ | ||
50 | { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ | ||
51 | { 0x21, KEY_DOT }, | ||
52 | { 0x13, KEY_ENTER }, | ||
53 | { 0x11, KEY_LAST }, /* Recall (last channel */ | ||
54 | { 0x22, KEY_PREVIOUS }, | ||
55 | { 0x23, KEY_PLAYPAUSE }, | ||
56 | { 0x24, KEY_NEXT }, | ||
57 | { 0x25, KEY_TIME }, /* Time Shifting */ | ||
58 | { 0x26, KEY_STOP }, | ||
59 | { 0x27, KEY_RECORD }, | ||
60 | { 0x28, KEY_SAVE }, /* Screenshot */ | ||
61 | { 0x2f, KEY_MENU }, | ||
62 | { 0x30, KEY_CANCEL }, | ||
63 | { 0x31, KEY_CHANNEL }, /* Channel Surf */ | ||
64 | { 0x32, KEY_SUBTITLE }, | ||
65 | { 0x33, KEY_LANGUAGE }, | ||
66 | { 0x34, KEY_REWIND }, | ||
67 | { 0x35, KEY_FASTFORWARD }, | ||
68 | { 0x36, KEY_TV }, | ||
69 | { 0x37, KEY_RADIO }, /* FM */ | ||
70 | { 0x38, KEY_DVD }, | ||
71 | |||
72 | { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ | ||
73 | { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ | ||
74 | { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ | ||
75 | { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ | ||
76 | { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ | ||
77 | }; | ||
78 | |||
79 | static struct rc_keymap winfast_map = { | ||
80 | .map = { | ||
81 | .scan = winfast, | ||
82 | .size = ARRAY_SIZE(winfast), | ||
83 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
84 | .name = RC_MAP_WINFAST, | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | static int __init init_rc_map_winfast(void) | ||
89 | { | ||
90 | return ir_register_map(&winfast_map); | ||
91 | } | ||
92 | |||
93 | static void __exit exit_rc_map_winfast(void) | ||
94 | { | ||
95 | ir_unregister_map(&winfast_map); | ||
96 | } | ||
97 | |||
98 | module_init(init_rc_map_winfast) | ||
99 | module_exit(exit_rc_map_winfast) | ||
100 | |||
101 | MODULE_LICENSE("GPL"); | ||
102 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c new file mode 100644 index 000000000000..46a8f1524b5b --- /dev/null +++ b/drivers/media/IR/rc-map.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* ir-raw-event.c - handle IR Pulse/Space event | ||
2 | * | ||
3 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <media/ir-core.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/delay.h> | ||
18 | |||
19 | /* Used to handle IR raw handler extensions */ | ||
20 | static LIST_HEAD(rc_map_list); | ||
21 | static DEFINE_SPINLOCK(rc_map_lock); | ||
22 | |||
23 | static struct rc_keymap *seek_rc_map(const char *name) | ||
24 | { | ||
25 | struct rc_keymap *map = NULL; | ||
26 | |||
27 | spin_lock(&rc_map_lock); | ||
28 | list_for_each_entry(map, &rc_map_list, list) { | ||
29 | if (!strcmp(name, map->map.name)) { | ||
30 | spin_unlock(&rc_map_lock); | ||
31 | return map; | ||
32 | } | ||
33 | } | ||
34 | spin_unlock(&rc_map_lock); | ||
35 | |||
36 | return NULL; | ||
37 | } | ||
38 | |||
39 | struct ir_scancode_table *get_rc_map(const char *name) | ||
40 | { | ||
41 | |||
42 | struct rc_keymap *map; | ||
43 | |||
44 | map = seek_rc_map(name); | ||
45 | #ifdef MODULE | ||
46 | if (!map) { | ||
47 | int rc = request_module(name); | ||
48 | if (rc < 0) { | ||
49 | printk(KERN_ERR "Couldn't load IR keymap %s\n", name); | ||
50 | return NULL; | ||
51 | } | ||
52 | msleep(20); /* Give some time for IR to register */ | ||
53 | |||
54 | map = seek_rc_map(name); | ||
55 | } | ||
56 | #endif | ||
57 | if (!map) { | ||
58 | printk(KERN_ERR "IR keymap %s not found\n", name); | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); | ||
63 | |||
64 | return &map->map; | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(get_rc_map); | ||
67 | |||
68 | int ir_register_map(struct rc_keymap *map) | ||
69 | { | ||
70 | spin_lock(&rc_map_lock); | ||
71 | list_add_tail(&map->list, &rc_map_list); | ||
72 | spin_unlock(&rc_map_lock); | ||
73 | return 0; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(ir_register_map); | ||
76 | |||
77 | void ir_unregister_map(struct rc_keymap *map) | ||
78 | { | ||
79 | spin_lock(&rc_map_lock); | ||
80 | list_del(&map->list); | ||
81 | spin_unlock(&rc_map_lock); | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(ir_unregister_map); | ||
84 | |||
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 96d61707f501..b6ce528e1889 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -100,6 +100,8 @@ struct xc2028_data { | |||
100 | if (size != _rc) \ | 100 | if (size != _rc) \ |
101 | tuner_info("i2c output error: rc = %d (should be %d)\n",\ | 101 | tuner_info("i2c output error: rc = %d (should be %d)\n",\ |
102 | _rc, (int)size); \ | 102 | _rc, (int)size); \ |
103 | if (priv->ctrl.msleep) \ | ||
104 | msleep(priv->ctrl.msleep); \ | ||
103 | _rc; \ | 105 | _rc; \ |
104 | }) | 106 | }) |
105 | 107 | ||
@@ -119,6 +121,8 @@ struct xc2028_data { | |||
119 | if (isize != _rc) \ | 121 | if (isize != _rc) \ |
120 | tuner_err("i2c input error: rc = %d (should be %d)\n", \ | 122 | tuner_err("i2c input error: rc = %d (should be %d)\n", \ |
121 | _rc, (int)isize); \ | 123 | _rc, (int)isize); \ |
124 | if (priv->ctrl.msleep) \ | ||
125 | msleep(priv->ctrl.msleep); \ | ||
122 | _rc; \ | 126 | _rc; \ |
123 | }) | 127 | }) |
124 | 128 | ||
@@ -129,8 +133,8 @@ struct xc2028_data { | |||
129 | (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \ | 133 | (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \ |
130 | _val, sizeof(_val)))) { \ | 134 | _val, sizeof(_val)))) { \ |
131 | tuner_err("Error on line %d: %d\n", __LINE__, _rc); \ | 135 | tuner_err("Error on line %d: %d\n", __LINE__, _rc); \ |
132 | } else \ | 136 | } else if (priv->ctrl.msleep) \ |
133 | msleep(10); \ | 137 | msleep(priv->ctrl.msleep); \ |
134 | _rc; \ | 138 | _rc; \ |
135 | }) | 139 | }) |
136 | 140 | ||
@@ -809,10 +813,20 @@ check_device: | |||
809 | hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, | 813 | hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, |
810 | (version & 0xf0) >> 4, version & 0xf); | 814 | (version & 0xf0) >> 4, version & 0xf); |
811 | 815 | ||
816 | |||
817 | if (priv->ctrl.read_not_reliable) | ||
818 | goto read_not_reliable; | ||
819 | |||
812 | /* Check firmware version against what we downloaded. */ | 820 | /* Check firmware version against what we downloaded. */ |
813 | if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { | 821 | if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { |
814 | tuner_err("Incorrect readback of firmware version.\n"); | 822 | if (!priv->ctrl.read_not_reliable) { |
815 | goto fail; | 823 | tuner_err("Incorrect readback of firmware version.\n"); |
824 | goto fail; | ||
825 | } else { | ||
826 | tuner_err("Returned an incorrect version. However, " | ||
827 | "read is not reliable enough. Ignoring it.\n"); | ||
828 | hwmodel = 3028; | ||
829 | } | ||
816 | } | 830 | } |
817 | 831 | ||
818 | /* Check that the tuner hardware model remains consistent over time. */ | 832 | /* Check that the tuner hardware model remains consistent over time. */ |
@@ -826,6 +840,7 @@ check_device: | |||
826 | goto fail; | 840 | goto fail; |
827 | } | 841 | } |
828 | 842 | ||
843 | read_not_reliable: | ||
829 | memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw)); | 844 | memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw)); |
830 | 845 | ||
831 | /* | 846 | /* |
@@ -996,6 +1011,8 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
996 | The reset CLK is needed only with tm6000. | 1011 | The reset CLK is needed only with tm6000. |
997 | Driver should work fine even if this fails. | 1012 | Driver should work fine even if this fails. |
998 | */ | 1013 | */ |
1014 | if (priv->ctrl.msleep) | ||
1015 | msleep(priv->ctrl.msleep); | ||
999 | do_tuner_callback(fe, XC2028_RESET_CLK, 1); | 1016 | do_tuner_callback(fe, XC2028_RESET_CLK, 1); |
1000 | 1017 | ||
1001 | msleep(10); | 1018 | msleep(10); |
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h index a90c35d50add..9778c96a5006 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/common/tuners/tuner-xc2028.h | |||
@@ -33,12 +33,14 @@ enum firmware_type { | |||
33 | struct xc2028_ctrl { | 33 | struct xc2028_ctrl { |
34 | char *fname; | 34 | char *fname; |
35 | int max_len; | 35 | int max_len; |
36 | int msleep; | ||
36 | unsigned int scode_table; | 37 | unsigned int scode_table; |
37 | unsigned int mts :1; | 38 | unsigned int mts :1; |
38 | unsigned int input1:1; | 39 | unsigned int input1:1; |
39 | unsigned int vhfbw7:1; | 40 | unsigned int vhfbw7:1; |
40 | unsigned int uhfbw8:1; | 41 | unsigned int uhfbw8:1; |
41 | unsigned int disable_power_mgmt:1; | 42 | unsigned int disable_power_mgmt:1; |
43 | unsigned int read_not_reliable:1; | ||
42 | unsigned int demod; | 44 | unsigned int demod; |
43 | enum firmware_type type:2; | 45 | enum firmware_type type:2; |
44 | }; | 46 | }; |
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 8b0cde38984d..248a2a9d8416 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c | |||
@@ -930,7 +930,6 @@ static int dst_fw_ver(struct dst_state *state) | |||
930 | dprintk(verbose, DST_INFO, 1, "Unsupported Command"); | 930 | dprintk(verbose, DST_INFO, 1, "Unsupported Command"); |
931 | return -1; | 931 | return -1; |
932 | } | 932 | } |
933 | memset(&state->fw_version, '\0', 8); | ||
934 | memcpy(&state->fw_version, &state->rxbuffer, 8); | 933 | memcpy(&state->fw_version, &state->rxbuffer, 8); |
935 | dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x", | 934 | dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x", |
936 | state->fw_version[0] >> 4, state->fw_version[0] & 0x0f, | 935 | state->fw_version[0] >> 4, state->fw_version[0] & 0x0f, |
@@ -1053,7 +1052,6 @@ static int dst_get_tuner_info(struct dst_state *state) | |||
1053 | goto force; | 1052 | goto force; |
1054 | } | 1053 | } |
1055 | } | 1054 | } |
1056 | memset(&state->board_info, '\0', 8); | ||
1057 | memcpy(&state->board_info, &state->rxbuffer, 8); | 1055 | memcpy(&state->board_info, &state->rxbuffer, 8); |
1058 | if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { | 1056 | if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { |
1059 | dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); | 1057 | dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); |
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index b6d46961a99e..b762e561a6d5 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/input.h> | 29 | #include <linux/input.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <media/ir-common.h> | 31 | #include <media/ir-core.h> |
32 | 32 | ||
33 | #include "demux.h" | 33 | #include "demux.h" |
34 | #include "dmxdev.h" | 34 | #include "dmxdev.h" |
@@ -46,6 +46,8 @@ | |||
46 | #include "z0194a.h" | 46 | #include "z0194a.h" |
47 | #include "ds3000.h" | 47 | #include "ds3000.h" |
48 | 48 | ||
49 | #define MODULE_NAME "dm1105" | ||
50 | |||
49 | #define UNSET (-1U) | 51 | #define UNSET (-1U) |
50 | 52 | ||
51 | #define DM1105_BOARD_NOAUTO UNSET | 53 | #define DM1105_BOARD_NOAUTO UNSET |
@@ -265,7 +267,6 @@ static void dm1105_card_list(struct pci_dev *pci) | |||
265 | /* infrared remote control */ | 267 | /* infrared remote control */ |
266 | struct infrared { | 268 | struct infrared { |
267 | struct input_dev *input_dev; | 269 | struct input_dev *input_dev; |
268 | struct ir_input_state ir; | ||
269 | char input_phys[32]; | 270 | char input_phys[32]; |
270 | struct work_struct work; | 271 | struct work_struct work; |
271 | u32 ir_command; | 272 | u32 ir_command; |
@@ -531,8 +532,7 @@ static void dm1105_emit_key(struct work_struct *work) | |||
531 | 532 | ||
532 | data = (ircom >> 8) & 0x7f; | 533 | data = (ircom >> 8) & 0x7f; |
533 | 534 | ||
534 | ir_input_keydown(ir->input_dev, &ir->ir, data); | 535 | ir_keydown(ir->input_dev, data, 0); |
535 | ir_input_nokey(ir->input_dev, &ir->ir); | ||
536 | } | 536 | } |
537 | 537 | ||
538 | /* work handler */ | 538 | /* work handler */ |
@@ -594,8 +594,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id) | |||
594 | int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) | 594 | int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) |
595 | { | 595 | { |
596 | struct input_dev *input_dev; | 596 | struct input_dev *input_dev; |
597 | struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; | 597 | char *ir_codes = NULL; |
598 | u64 ir_type = IR_TYPE_OTHER; | ||
599 | int err = -ENOMEM; | 598 | int err = -ENOMEM; |
600 | 599 | ||
601 | input_dev = input_allocate_device(); | 600 | input_dev = input_allocate_device(); |
@@ -606,12 +605,6 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) | |||
606 | snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), | 605 | snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), |
607 | "pci-%s/ir0", pci_name(dm1105->pdev)); | 606 | "pci-%s/ir0", pci_name(dm1105->pdev)); |
608 | 607 | ||
609 | err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type); | ||
610 | if (err < 0) { | ||
611 | input_free_device(input_dev); | ||
612 | return err; | ||
613 | } | ||
614 | |||
615 | input_dev->name = "DVB on-card IR receiver"; | 608 | input_dev->name = "DVB on-card IR receiver"; |
616 | input_dev->phys = dm1105->ir.input_phys; | 609 | input_dev->phys = dm1105->ir.input_phys; |
617 | input_dev->id.bustype = BUS_PCI; | 610 | input_dev->id.bustype = BUS_PCI; |
@@ -628,9 +621,13 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) | |||
628 | 621 | ||
629 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); | 622 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); |
630 | 623 | ||
631 | err = ir_input_register(input_dev, ir_codes, NULL); | 624 | err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); |
625 | if (err < 0) { | ||
626 | input_free_device(input_dev); | ||
627 | return err; | ||
628 | } | ||
632 | 629 | ||
633 | return err; | 630 | return 0; |
634 | } | 631 | } |
635 | 632 | ||
636 | void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105) | 633 | void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105) |
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 67f189b7aa1f..977ddba3e235 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c | |||
@@ -426,7 +426,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | |||
426 | }; | 426 | }; |
427 | }; | 427 | }; |
428 | 428 | ||
429 | if (demux->cnt_storage) { | 429 | if (demux->cnt_storage && dvb_demux_tscheck) { |
430 | /* check pkt counter */ | 430 | /* check pkt counter */ |
431 | if (pid < MAX_PID) { | 431 | if (pid < MAX_PID) { |
432 | if (buf[1] & 0x80) | 432 | if (buf[1] & 0x80) |
@@ -1248,12 +1248,9 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) | |||
1248 | dvbdemux->feed[i].index = i; | 1248 | dvbdemux->feed[i].index = i; |
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | if (dvb_demux_tscheck) { | 1251 | dvbdemux->cnt_storage = vmalloc(MAX_PID + 1); |
1252 | dvbdemux->cnt_storage = vmalloc(MAX_PID + 1); | 1252 | if (!dvbdemux->cnt_storage) |
1253 | 1253 | printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); | |
1254 | if (!dvbdemux->cnt_storage) | ||
1255 | printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); | ||
1256 | } | ||
1257 | 1254 | ||
1258 | INIT_LIST_HEAD(&dvbdemux->frontend_list); | 1255 | INIT_LIST_HEAD(&dvbdemux->frontend_list); |
1259 | 1256 | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 55ea260572bf..6932def4d266 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -95,6 +95,10 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open( | |||
95 | * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. | 95 | * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. |
96 | */ | 96 | */ |
97 | 97 | ||
98 | #define DVB_FE_NO_EXIT 0 | ||
99 | #define DVB_FE_NORMAL_EXIT 1 | ||
100 | #define DVB_FE_DEVICE_REMOVED 2 | ||
101 | |||
98 | static DEFINE_MUTEX(frontend_mutex); | 102 | static DEFINE_MUTEX(frontend_mutex); |
99 | 103 | ||
100 | struct dvb_frontend_private { | 104 | struct dvb_frontend_private { |
@@ -497,7 +501,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | |||
497 | { | 501 | { |
498 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 502 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
499 | 503 | ||
500 | if (fepriv->exit) | 504 | if (fepriv->exit != DVB_FE_NO_EXIT) |
501 | return 1; | 505 | return 1; |
502 | 506 | ||
503 | if (fepriv->dvbdev->writers == 1) | 507 | if (fepriv->dvbdev->writers == 1) |
@@ -559,7 +563,7 @@ restart: | |||
559 | 563 | ||
560 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { | 564 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { |
561 | /* got signal or quitting */ | 565 | /* got signal or quitting */ |
562 | fepriv->exit = 1; | 566 | fepriv->exit = DVB_FE_NORMAL_EXIT; |
563 | break; | 567 | break; |
564 | } | 568 | } |
565 | 569 | ||
@@ -673,7 +677,10 @@ restart: | |||
673 | } | 677 | } |
674 | 678 | ||
675 | fepriv->thread = NULL; | 679 | fepriv->thread = NULL; |
676 | fepriv->exit = 0; | 680 | if (kthread_should_stop()) |
681 | fepriv->exit = DVB_FE_DEVICE_REMOVED; | ||
682 | else | ||
683 | fepriv->exit = DVB_FE_NO_EXIT; | ||
677 | mb(); | 684 | mb(); |
678 | 685 | ||
679 | dvb_frontend_wakeup(fe); | 686 | dvb_frontend_wakeup(fe); |
@@ -686,7 +693,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) | |||
686 | 693 | ||
687 | dprintk ("%s\n", __func__); | 694 | dprintk ("%s\n", __func__); |
688 | 695 | ||
689 | fepriv->exit = 1; | 696 | fepriv->exit = DVB_FE_NORMAL_EXIT; |
690 | mb(); | 697 | mb(); |
691 | 698 | ||
692 | if (!fepriv->thread) | 699 | if (!fepriv->thread) |
@@ -755,7 +762,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) | |||
755 | dprintk ("%s\n", __func__); | 762 | dprintk ("%s\n", __func__); |
756 | 763 | ||
757 | if (fepriv->thread) { | 764 | if (fepriv->thread) { |
758 | if (!fepriv->exit) | 765 | if (fepriv->exit == DVB_FE_NO_EXIT) |
759 | return 0; | 766 | return 0; |
760 | else | 767 | else |
761 | dvb_frontend_stop (fe); | 768 | dvb_frontend_stop (fe); |
@@ -767,7 +774,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) | |||
767 | return -EINTR; | 774 | return -EINTR; |
768 | 775 | ||
769 | fepriv->state = FESTATE_IDLE; | 776 | fepriv->state = FESTATE_IDLE; |
770 | fepriv->exit = 0; | 777 | fepriv->exit = DVB_FE_NO_EXIT; |
771 | fepriv->thread = NULL; | 778 | fepriv->thread = NULL; |
772 | mb(); | 779 | mb(); |
773 | 780 | ||
@@ -1490,7 +1497,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
1490 | 1497 | ||
1491 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); | 1498 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); |
1492 | 1499 | ||
1493 | if (fepriv->exit) | 1500 | if (fepriv->exit != DVB_FE_NO_EXIT) |
1494 | return -ENODEV; | 1501 | return -ENODEV; |
1495 | 1502 | ||
1496 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && | 1503 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && |
@@ -1916,6 +1923,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) | |||
1916 | int ret; | 1923 | int ret; |
1917 | 1924 | ||
1918 | dprintk ("%s\n", __func__); | 1925 | dprintk ("%s\n", __func__); |
1926 | if (fepriv->exit == DVB_FE_DEVICE_REMOVED) | ||
1927 | return -ENODEV; | ||
1919 | 1928 | ||
1920 | if (adapter->mfe_shared) { | 1929 | if (adapter->mfe_shared) { |
1921 | mutex_lock (&adapter->mfe_lock); | 1930 | mutex_lock (&adapter->mfe_lock); |
@@ -2008,7 +2017,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) | |||
2008 | ret = dvb_generic_release (inode, file); | 2017 | ret = dvb_generic_release (inode, file); |
2009 | 2018 | ||
2010 | if (dvbdev->users == -1) { | 2019 | if (dvbdev->users == -1) { |
2011 | if (fepriv->exit == 1) { | 2020 | if (fepriv->exit != DVB_FE_NO_EXIT) { |
2012 | fops_put(file->f_op); | 2021 | fops_put(file->f_op); |
2013 | file->f_op = NULL; | 2022 | file->f_op = NULL; |
2014 | wake_up(&dvbdev->wait_queue); | 2023 | wake_up(&dvbdev->wait_queue); |
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index 6247239982e9..b6cbb1dfc5f1 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
@@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr | |||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct dvb_usb_rc_key a800_rc_keys[] = { | 40 | static struct dvb_usb_rc_key ir_codes_a800_table[] = { |
41 | { 0x0201, KEY_PROG1 }, /* SOURCE */ | 41 | { 0x0201, KEY_PROG1 }, /* SOURCE */ |
42 | { 0x0200, KEY_POWER }, /* POWER */ | 42 | { 0x0200, KEY_POWER }, /* POWER */ |
43 | { 0x0205, KEY_1 }, /* 1 */ | 43 | { 0x0205, KEY_1 }, /* 1 */ |
@@ -147,8 +147,8 @@ static struct dvb_usb_device_properties a800_properties = { | |||
147 | .identify_state = a800_identify_state, | 147 | .identify_state = a800_identify_state, |
148 | 148 | ||
149 | .rc_interval = DEFAULT_RC_INTERVAL, | 149 | .rc_interval = DEFAULT_RC_INTERVAL, |
150 | .rc_key_map = a800_rc_keys, | 150 | .rc_key_map = ir_codes_a800_table, |
151 | .rc_key_map_size = ARRAY_SIZE(a800_rc_keys), | 151 | .rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table), |
152 | .rc_query = a800_rc_query, | 152 | .rc_query = a800_rc_query, |
153 | 153 | ||
154 | .i2c_algo = &dibusb_i2c_algo, | 154 | .i2c_algo = &dibusb_i2c_algo, |
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c index f4379c650a19..b41fa873b04d 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c | |||
@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, | |||
33 | 33 | ||
34 | #define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args) | 34 | #define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args) |
35 | 35 | ||
36 | struct dvb_usb_rc_key af9005_rc_keys[] = { | 36 | struct dvb_usb_rc_key ir_codes_af9005_table[] = { |
37 | 37 | ||
38 | {0x01b7, KEY_POWER}, | 38 | {0x01b7, KEY_POWER}, |
39 | {0x01a7, KEY_VOLUMEUP}, | 39 | {0x01a7, KEY_VOLUMEUP}, |
@@ -74,7 +74,7 @@ struct dvb_usb_rc_key af9005_rc_keys[] = { | |||
74 | {0x00d5, KEY_GOTO}, /* marked jump on the remote */ | 74 | {0x00d5, KEY_GOTO}, /* marked jump on the remote */ |
75 | }; | 75 | }; |
76 | 76 | ||
77 | int af9005_rc_keys_size = ARRAY_SIZE(af9005_rc_keys); | 77 | int ir_codes_af9005_table_size = ARRAY_SIZE(ir_codes_af9005_table); |
78 | 78 | ||
79 | static int repeatable_keys[] = { | 79 | static int repeatable_keys[] = { |
80 | KEY_VOLUMEUP, | 80 | KEY_VOLUMEUP, |
@@ -130,10 +130,10 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, | |||
130 | deb_decode("code != inverted code\n"); | 130 | deb_decode("code != inverted code\n"); |
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | for (i = 0; i < af9005_rc_keys_size; i++) { | 133 | for (i = 0; i < ir_codes_af9005_table_size; i++) { |
134 | if (rc5_custom(&af9005_rc_keys[i]) == cust | 134 | if (rc5_custom(&ir_codes_af9005_table[i]) == cust |
135 | && rc5_data(&af9005_rc_keys[i]) == dat) { | 135 | && rc5_data(&ir_codes_af9005_table[i]) == dat) { |
136 | *event = af9005_rc_keys[i].event; | 136 | *event = ir_codes_af9005_table[i].event; |
137 | *state = REMOTE_KEY_PRESSED; | 137 | *state = REMOTE_KEY_PRESSED; |
138 | deb_decode | 138 | deb_decode |
139 | ("key pressed, event %x\n", *event); | 139 | ("key pressed, event %x\n", *event); |
@@ -146,8 +146,8 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, | |||
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | EXPORT_SYMBOL(af9005_rc_keys); | 149 | EXPORT_SYMBOL(ir_codes_af9005_table); |
150 | EXPORT_SYMBOL(af9005_rc_keys_size); | 150 | EXPORT_SYMBOL(ir_codes_af9005_table_size); |
151 | EXPORT_SYMBOL(af9005_rc_decode); | 151 | EXPORT_SYMBOL(af9005_rc_decode); |
152 | 152 | ||
153 | MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>"); | 153 | MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>"); |
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index ca5a0a4d2a47..cfd6107d5349 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c | |||
@@ -1109,8 +1109,8 @@ static int __init af9005_usb_module_init(void) | |||
1109 | return result; | 1109 | return result; |
1110 | } | 1110 | } |
1111 | rc_decode = symbol_request(af9005_rc_decode); | 1111 | rc_decode = symbol_request(af9005_rc_decode); |
1112 | rc_keys = symbol_request(af9005_rc_keys); | 1112 | rc_keys = symbol_request(ir_codes_af9005_table); |
1113 | rc_keys_size = symbol_request(af9005_rc_keys_size); | 1113 | rc_keys_size = symbol_request(ir_codes_af9005_table_size); |
1114 | if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { | 1114 | if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { |
1115 | err("af9005_rc_decode function not found, disabling remote"); | 1115 | err("af9005_rc_decode function not found, disabling remote"); |
1116 | af9005_properties.rc_query = NULL; | 1116 | af9005_properties.rc_query = NULL; |
@@ -1128,9 +1128,9 @@ static void __exit af9005_usb_module_exit(void) | |||
1128 | if (rc_decode != NULL) | 1128 | if (rc_decode != NULL) |
1129 | symbol_put(af9005_rc_decode); | 1129 | symbol_put(af9005_rc_decode); |
1130 | if (rc_keys != NULL) | 1130 | if (rc_keys != NULL) |
1131 | symbol_put(af9005_rc_keys); | 1131 | symbol_put(ir_codes_af9005_table); |
1132 | if (rc_keys_size != NULL) | 1132 | if (rc_keys_size != NULL) |
1133 | symbol_put(af9005_rc_keys_size); | 1133 | symbol_put(ir_codes_af9005_table_size); |
1134 | /* deregister this driver from the USB subsystem */ | 1134 | /* deregister this driver from the USB subsystem */ |
1135 | usb_deregister(&af9005_usb_driver); | 1135 | usb_deregister(&af9005_usb_driver); |
1136 | } | 1136 | } |
diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h index 0bc48a012187..088e7083a39b 100644 --- a/drivers/media/dvb/dvb-usb/af9005.h +++ b/drivers/media/dvb/dvb-usb/af9005.h | |||
@@ -3490,7 +3490,7 @@ extern u8 regmask[8]; | |||
3490 | /* remote control decoder */ | 3490 | /* remote control decoder */ |
3491 | extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, | 3491 | extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, |
3492 | u32 * event, int *state); | 3492 | u32 * event, int *state); |
3493 | extern struct dvb_usb_rc_key af9005_rc_keys[]; | 3493 | extern struct dvb_usb_rc_key ir_codes_af9005_table[]; |
3494 | extern int af9005_rc_keys_size; | 3494 | extern int ir_codes_af9005_table_size; |
3495 | 3495 | ||
3496 | #endif | 3496 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 74d94e45324d..66c7c3ea7990 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
@@ -752,19 +752,19 @@ static const struct af9015_setup *af9015_setup_match(unsigned int id, | |||
752 | 752 | ||
753 | static const struct af9015_setup af9015_setup_modparam[] = { | 753 | static const struct af9015_setup af9015_setup_modparam[] = { |
754 | { AF9015_REMOTE_A_LINK_DTU_M, | 754 | { AF9015_REMOTE_A_LINK_DTU_M, |
755 | af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), | 755 | ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), |
756 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, | 756 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, |
757 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | 757 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, |
758 | af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), | 758 | ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), |
759 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, | 759 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, |
760 | { AF9015_REMOTE_MYGICTV_U718, | 760 | { AF9015_REMOTE_MYGICTV_U718, |
761 | af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), | 761 | ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), |
762 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, | 762 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, |
763 | { AF9015_REMOTE_DIGITTRADE_DVB_T, | 763 | { AF9015_REMOTE_DIGITTRADE_DVB_T, |
764 | af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade), | 764 | ir_codes_af9015_table_digittrade, ARRAY_SIZE(ir_codes_af9015_table_digittrade), |
765 | af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, | 765 | af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, |
766 | { AF9015_REMOTE_AVERMEDIA_KS, | 766 | { AF9015_REMOTE_AVERMEDIA_KS, |
767 | af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), | 767 | ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), |
768 | af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) }, | 768 | af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) }, |
769 | { } | 769 | { } |
770 | }; | 770 | }; |
@@ -772,32 +772,32 @@ static const struct af9015_setup af9015_setup_modparam[] = { | |||
772 | /* don't add new entries here anymore, use hashes instead */ | 772 | /* don't add new entries here anymore, use hashes instead */ |
773 | static const struct af9015_setup af9015_setup_usbids[] = { | 773 | static const struct af9015_setup af9015_setup_usbids[] = { |
774 | { USB_VID_LEADTEK, | 774 | { USB_VID_LEADTEK, |
775 | af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek), | 775 | ir_codes_af9015_table_leadtek, ARRAY_SIZE(ir_codes_af9015_table_leadtek), |
776 | af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, | 776 | af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, |
777 | { USB_VID_VISIONPLUS, | 777 | { USB_VID_VISIONPLUS, |
778 | af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), | 778 | ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), |
779 | af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, | 779 | af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, |
780 | { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ | 780 | { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ |
781 | af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), | 781 | ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), |
782 | af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, | 782 | af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, |
783 | { USB_VID_AVERMEDIA, | 783 | { USB_VID_AVERMEDIA, |
784 | af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), | 784 | ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), |
785 | af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, | 785 | af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, |
786 | { USB_VID_MSI_2, | 786 | { USB_VID_MSI_2, |
787 | af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii), | 787 | ir_codes_af9015_table_msi_digivox_iii, ARRAY_SIZE(ir_codes_af9015_table_msi_digivox_iii), |
788 | af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) }, | 788 | af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) }, |
789 | { } | 789 | { } |
790 | }; | 790 | }; |
791 | 791 | ||
792 | static const struct af9015_setup af9015_setup_hashes[] = { | 792 | static const struct af9015_setup af9015_setup_hashes[] = { |
793 | { 0xb8feb708, | 793 | { 0xb8feb708, |
794 | af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), | 794 | ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), |
795 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, | 795 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, |
796 | { 0xa3703d00, | 796 | { 0xa3703d00, |
797 | af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), | 797 | ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), |
798 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, | 798 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, |
799 | { 0x9b7dc64e, | 799 | { 0x9b7dc64e, |
800 | af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), | 800 | ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), |
801 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, | 801 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, |
802 | { } | 802 | { } |
803 | }; | 803 | }; |
@@ -836,8 +836,8 @@ static void af9015_set_remote_config(struct usb_device *udev, | |||
836 | } else if (udev->descriptor.idProduct == | 836 | } else if (udev->descriptor.idProduct == |
837 | cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { | 837 | cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { |
838 | table = &(const struct af9015_setup){ 0, | 838 | table = &(const struct af9015_setup){ 0, |
839 | af9015_rc_keys_trekstor, | 839 | ir_codes_af9015_table_trekstor, |
840 | ARRAY_SIZE(af9015_rc_keys_trekstor), | 840 | ARRAY_SIZE(ir_codes_af9015_table_trekstor), |
841 | af9015_ir_table_trekstor, | 841 | af9015_ir_table_trekstor, |
842 | ARRAY_SIZE(af9015_ir_table_trekstor) | 842 | ARRAY_SIZE(af9015_ir_table_trekstor) |
843 | }; | 843 | }; |
@@ -1297,6 +1297,8 @@ static struct usb_device_id af9015_usb_table[] = { | |||
1297 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, | 1297 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, |
1298 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, | 1298 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, |
1299 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, | 1299 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, |
1300 | /* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)}, | ||
1301 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)}, | ||
1300 | {0}, | 1302 | {0}, |
1301 | }; | 1303 | }; |
1302 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); | 1304 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); |
@@ -1500,7 +1502,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1500 | "(VS-DVB-T 395U)", | 1502 | "(VS-DVB-T 395U)", |
1501 | .cold_ids = {&af9015_usb_table[16], | 1503 | .cold_ids = {&af9015_usb_table[16], |
1502 | &af9015_usb_table[17], | 1504 | &af9015_usb_table[17], |
1503 | &af9015_usb_table[18], NULL}, | 1505 | &af9015_usb_table[18], |
1506 | &af9015_usb_table[31], NULL}, | ||
1504 | .warm_ids = {NULL}, | 1507 | .warm_ids = {NULL}, |
1505 | }, | 1508 | }, |
1506 | { | 1509 | { |
@@ -1569,7 +1572,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1569 | 1572 | ||
1570 | .i2c_algo = &af9015_i2c_algo, | 1573 | .i2c_algo = &af9015_i2c_algo, |
1571 | 1574 | ||
1572 | .num_device_descs = 7, /* max 9 */ | 1575 | .num_device_descs = 8, /* max 9 */ |
1573 | .devices = { | 1576 | .devices = { |
1574 | { | 1577 | { |
1575 | .name = "AverMedia AVerTV Volar GPS 805 (A805)", | 1578 | .name = "AverMedia AVerTV Volar GPS 805 (A805)", |
@@ -1608,6 +1611,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1608 | .cold_ids = {&af9015_usb_table[29], NULL}, | 1611 | .cold_ids = {&af9015_usb_table[29], NULL}, |
1609 | .warm_ids = {NULL}, | 1612 | .warm_ids = {NULL}, |
1610 | }, | 1613 | }, |
1614 | { | ||
1615 | .name = "KWorld USB DVB-T Stick Mobile " \ | ||
1616 | "(UB383-T)", | ||
1617 | .cold_ids = {&af9015_usb_table[30], NULL}, | ||
1618 | .warm_ids = {NULL}, | ||
1619 | }, | ||
1611 | } | 1620 | } |
1612 | }, | 1621 | }, |
1613 | }; | 1622 | }; |
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index ef36b1831490..63b2a4907b7e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
@@ -123,7 +123,7 @@ enum af9015_remote { | |||
123 | 123 | ||
124 | /* LeadTek - Y04G0051 */ | 124 | /* LeadTek - Y04G0051 */ |
125 | /* Leadtek WinFast DTV Dongle Gold */ | 125 | /* Leadtek WinFast DTV Dongle Gold */ |
126 | static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { | 126 | static struct dvb_usb_rc_key ir_codes_af9015_table_leadtek[] = { |
127 | { 0x001e, KEY_1 }, | 127 | { 0x001e, KEY_1 }, |
128 | { 0x001f, KEY_2 }, | 128 | { 0x001f, KEY_2 }, |
129 | { 0x0020, KEY_3 }, | 129 | { 0x0020, KEY_3 }, |
@@ -227,7 +227,7 @@ static u8 af9015_ir_table_leadtek[] = { | |||
227 | }; | 227 | }; |
228 | 228 | ||
229 | /* TwinHan AzureWave AD-TU700(704J) */ | 229 | /* TwinHan AzureWave AD-TU700(704J) */ |
230 | static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { | 230 | static struct dvb_usb_rc_key ir_codes_af9015_table_twinhan[] = { |
231 | { 0x053f, KEY_POWER }, | 231 | { 0x053f, KEY_POWER }, |
232 | { 0x0019, KEY_FAVORITES }, /* Favorite List */ | 232 | { 0x0019, KEY_FAVORITES }, /* Favorite List */ |
233 | { 0x0004, KEY_TEXT }, /* Teletext */ | 233 | { 0x0004, KEY_TEXT }, /* Teletext */ |
@@ -338,7 +338,7 @@ static u8 af9015_ir_table_twinhan[] = { | |||
338 | }; | 338 | }; |
339 | 339 | ||
340 | /* A-Link DTU(m) */ | 340 | /* A-Link DTU(m) */ |
341 | static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { | 341 | static struct dvb_usb_rc_key ir_codes_af9015_table_a_link[] = { |
342 | { 0x001e, KEY_1 }, | 342 | { 0x001e, KEY_1 }, |
343 | { 0x001f, KEY_2 }, | 343 | { 0x001f, KEY_2 }, |
344 | { 0x0020, KEY_3 }, | 344 | { 0x0020, KEY_3 }, |
@@ -381,7 +381,7 @@ static u8 af9015_ir_table_a_link[] = { | |||
381 | }; | 381 | }; |
382 | 382 | ||
383 | /* MSI DIGIVOX mini II V3.0 */ | 383 | /* MSI DIGIVOX mini II V3.0 */ |
384 | static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { | 384 | static struct dvb_usb_rc_key ir_codes_af9015_table_msi[] = { |
385 | { 0x001e, KEY_1 }, | 385 | { 0x001e, KEY_1 }, |
386 | { 0x001f, KEY_2 }, | 386 | { 0x001f, KEY_2 }, |
387 | { 0x0020, KEY_3 }, | 387 | { 0x0020, KEY_3 }, |
@@ -424,7 +424,7 @@ static u8 af9015_ir_table_msi[] = { | |||
424 | }; | 424 | }; |
425 | 425 | ||
426 | /* MYGICTV U718 */ | 426 | /* MYGICTV U718 */ |
427 | static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { | 427 | static struct dvb_usb_rc_key ir_codes_af9015_table_mygictv[] = { |
428 | { 0x003d, KEY_SWITCHVIDEOMODE }, | 428 | { 0x003d, KEY_SWITCHVIDEOMODE }, |
429 | /* TV / AV */ | 429 | /* TV / AV */ |
430 | { 0x0545, KEY_POWER }, | 430 | { 0x0545, KEY_POWER }, |
@@ -550,7 +550,7 @@ static u8 af9015_ir_table_kworld[] = { | |||
550 | }; | 550 | }; |
551 | 551 | ||
552 | /* AverMedia Volar X */ | 552 | /* AverMedia Volar X */ |
553 | static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = { | 553 | static struct dvb_usb_rc_key ir_codes_af9015_table_avermedia[] = { |
554 | { 0x053d, KEY_PROG1 }, /* SOURCE */ | 554 | { 0x053d, KEY_PROG1 }, /* SOURCE */ |
555 | { 0x0512, KEY_POWER }, /* POWER */ | 555 | { 0x0512, KEY_POWER }, /* POWER */ |
556 | { 0x051e, KEY_1 }, /* 1 */ | 556 | { 0x051e, KEY_1 }, /* 1 */ |
@@ -656,7 +656,7 @@ static u8 af9015_ir_table_avermedia_ks[] = { | |||
656 | }; | 656 | }; |
657 | 657 | ||
658 | /* Digittrade DVB-T USB Stick */ | 658 | /* Digittrade DVB-T USB Stick */ |
659 | static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = { | 659 | static struct dvb_usb_rc_key ir_codes_af9015_table_digittrade[] = { |
660 | { 0x010f, KEY_LAST }, /* RETURN */ | 660 | { 0x010f, KEY_LAST }, /* RETURN */ |
661 | { 0x0517, KEY_TEXT }, /* TELETEXT */ | 661 | { 0x0517, KEY_TEXT }, /* TELETEXT */ |
662 | { 0x0108, KEY_EPG }, /* EPG */ | 662 | { 0x0108, KEY_EPG }, /* EPG */ |
@@ -719,7 +719,7 @@ static u8 af9015_ir_table_digittrade[] = { | |||
719 | }; | 719 | }; |
720 | 720 | ||
721 | /* TREKSTOR DVB-T USB Stick */ | 721 | /* TREKSTOR DVB-T USB Stick */ |
722 | static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = { | 722 | static struct dvb_usb_rc_key ir_codes_af9015_table_trekstor[] = { |
723 | { 0x0704, KEY_AGAIN }, /* Home */ | 723 | { 0x0704, KEY_AGAIN }, /* Home */ |
724 | { 0x0705, KEY_MUTE }, /* Mute */ | 724 | { 0x0705, KEY_MUTE }, /* Mute */ |
725 | { 0x0706, KEY_UP }, /* Up */ | 725 | { 0x0706, KEY_UP }, /* Up */ |
@@ -782,7 +782,7 @@ static u8 af9015_ir_table_trekstor[] = { | |||
782 | }; | 782 | }; |
783 | 783 | ||
784 | /* MSI DIGIVOX mini III */ | 784 | /* MSI DIGIVOX mini III */ |
785 | static struct dvb_usb_rc_key af9015_rc_keys_msi_digivox_iii[] = { | 785 | static struct dvb_usb_rc_key ir_codes_af9015_table_msi_digivox_iii[] = { |
786 | { 0x0713, KEY_POWER }, /* [red power button] */ | 786 | { 0x0713, KEY_POWER }, /* [red power button] */ |
787 | { 0x073b, KEY_VIDEO }, /* Source */ | 787 | { 0x073b, KEY_VIDEO }, /* Source */ |
788 | { 0x073e, KEY_ZOOM }, /* Zoom */ | 788 | { 0x073e, KEY_ZOOM }, /* Zoom */ |
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index bb69f3719f9a..faca1ad88a67 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
@@ -399,7 +399,7 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static struct dvb_usb_rc_key anysee_rc_keys[] = { | 402 | static struct dvb_usb_rc_key ir_codes_anysee_table[] = { |
403 | { 0x0100, KEY_0 }, | 403 | { 0x0100, KEY_0 }, |
404 | { 0x0101, KEY_1 }, | 404 | { 0x0101, KEY_1 }, |
405 | { 0x0102, KEY_2 }, | 405 | { 0x0102, KEY_2 }, |
@@ -518,8 +518,8 @@ static struct dvb_usb_device_properties anysee_properties = { | |||
518 | } | 518 | } |
519 | }, | 519 | }, |
520 | 520 | ||
521 | .rc_key_map = anysee_rc_keys, | 521 | .rc_key_map = ir_codes_anysee_table, |
522 | .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys), | 522 | .rc_key_map_size = ARRAY_SIZE(ir_codes_anysee_table), |
523 | .rc_query = anysee_rc_query, | 523 | .rc_query = anysee_rc_query, |
524 | .rc_interval = 200, /* windows driver uses 500ms */ | 524 | .rc_interval = 200, /* windows driver uses 500ms */ |
525 | 525 | ||
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index d7290b2c0913..6681ac1c56e3 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c | |||
@@ -125,12 +125,12 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { | |||
125 | { STB0899_RCOMPC , 0xc9 }, | 125 | { STB0899_RCOMPC , 0xc9 }, |
126 | { STB0899_AGC1CN , 0x01 }, | 126 | { STB0899_AGC1CN , 0x01 }, |
127 | { STB0899_AGC1REF , 0x10 }, | 127 | { STB0899_AGC1REF , 0x10 }, |
128 | { STB0899_RTC , 0x23 }, | 128 | { STB0899_RTC , 0x23 }, |
129 | { STB0899_TMGCFG , 0x4e }, | 129 | { STB0899_TMGCFG , 0x4e }, |
130 | { STB0899_AGC2REF , 0x34 }, | 130 | { STB0899_AGC2REF , 0x34 }, |
131 | { STB0899_TLSR , 0x84 }, | 131 | { STB0899_TLSR , 0x84 }, |
132 | { STB0899_CFD , 0xf7 }, | 132 | { STB0899_CFD , 0xf7 }, |
133 | { STB0899_ACLC , 0x87 }, | 133 | { STB0899_ACLC , 0x87 }, |
134 | { STB0899_BCLC , 0x94 }, | 134 | { STB0899_BCLC , 0x94 }, |
135 | { STB0899_EQON , 0x41 }, | 135 | { STB0899_EQON , 0x41 }, |
136 | { STB0899_LDT , 0xf1 }, | 136 | { STB0899_LDT , 0xf1 }, |
@@ -183,10 +183,10 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { | |||
183 | { STB0899_ECNT3M , 0x0a }, | 183 | { STB0899_ECNT3M , 0x0a }, |
184 | { STB0899_ECNT3L , 0xad }, | 184 | { STB0899_ECNT3L , 0xad }, |
185 | { STB0899_FECAUTO1 , 0x06 }, | 185 | { STB0899_FECAUTO1 , 0x06 }, |
186 | { STB0899_FECM , 0x01 }, | 186 | { STB0899_FECM , 0x01 }, |
187 | { STB0899_VTH12 , 0xb0 }, | 187 | { STB0899_VTH12 , 0xb0 }, |
188 | { STB0899_VTH23 , 0x7a }, | 188 | { STB0899_VTH23 , 0x7a }, |
189 | { STB0899_VTH34 , 0x58 }, | 189 | { STB0899_VTH34 , 0x58 }, |
190 | { STB0899_VTH56 , 0x38 }, | 190 | { STB0899_VTH56 , 0x38 }, |
191 | { STB0899_VTH67 , 0x34 }, | 191 | { STB0899_VTH67 , 0x34 }, |
192 | { STB0899_VTH78 , 0x24 }, | 192 | { STB0899_VTH78 , 0x24 }, |
@@ -195,7 +195,7 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { | |||
195 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ | 195 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ |
196 | { STB0899_TSULC , 0x42 }, | 196 | { STB0899_TSULC , 0x42 }, |
197 | { STB0899_RSLLC , 0x41 }, | 197 | { STB0899_RSLLC , 0x41 }, |
198 | { STB0899_TSLPL , 0x12 }, | 198 | { STB0899_TSLPL , 0x12 }, |
199 | { STB0899_TSCFGH , 0x0c }, | 199 | { STB0899_TSCFGH , 0x0c }, |
200 | { STB0899_TSCFGM , 0x00 }, | 200 | { STB0899_TSCFGM , 0x00 }, |
201 | { STB0899_TSCFGL , 0x00 }, | 201 | { STB0899_TSCFGL , 0x00 }, |
@@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
386 | } | 386 | } |
387 | 387 | ||
388 | /* keys for the enclosed remote control */ | 388 | /* keys for the enclosed remote control */ |
389 | static struct dvb_usb_rc_key az6027_rc_keys[] = { | 389 | static struct dvb_usb_rc_key ir_codes_az6027_table[] = { |
390 | { 0x01, KEY_1 }, | 390 | { 0x01, KEY_1 }, |
391 | { 0x02, KEY_2 }, | 391 | { 0x02, KEY_2 }, |
392 | }; | 392 | }; |
@@ -417,11 +417,15 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, | |||
417 | u16 value; | 417 | u16 value; |
418 | u16 index; | 418 | u16 index; |
419 | int blen; | 419 | int blen; |
420 | u8 b[12]; | 420 | u8 *b; |
421 | 421 | ||
422 | if (slot != 0) | 422 | if (slot != 0) |
423 | return -EINVAL; | 423 | return -EINVAL; |
424 | 424 | ||
425 | b = kmalloc(12, GFP_KERNEL); | ||
426 | if (!b) | ||
427 | return -ENOMEM; | ||
428 | |||
425 | mutex_lock(&state->ca_mutex); | 429 | mutex_lock(&state->ca_mutex); |
426 | 430 | ||
427 | req = 0xC1; | 431 | req = 0xC1; |
@@ -438,6 +442,7 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, | |||
438 | } | 442 | } |
439 | 443 | ||
440 | mutex_unlock(&state->ca_mutex); | 444 | mutex_unlock(&state->ca_mutex); |
445 | kfree(b); | ||
441 | return ret; | 446 | return ret; |
442 | } | 447 | } |
443 | 448 | ||
@@ -485,11 +490,15 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, | |||
485 | u16 value; | 490 | u16 value; |
486 | u16 index; | 491 | u16 index; |
487 | int blen; | 492 | int blen; |
488 | u8 b[12]; | 493 | u8 *b; |
489 | 494 | ||
490 | if (slot != 0) | 495 | if (slot != 0) |
491 | return -EINVAL; | 496 | return -EINVAL; |
492 | 497 | ||
498 | b = kmalloc(12, GFP_KERNEL); | ||
499 | if (!b) | ||
500 | return -ENOMEM; | ||
501 | |||
493 | mutex_lock(&state->ca_mutex); | 502 | mutex_lock(&state->ca_mutex); |
494 | 503 | ||
495 | req = 0xC3; | 504 | req = 0xC3; |
@@ -510,6 +519,7 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, | |||
510 | } | 519 | } |
511 | 520 | ||
512 | mutex_unlock(&state->ca_mutex); | 521 | mutex_unlock(&state->ca_mutex); |
522 | kfree(b); | ||
513 | return ret; | 523 | return ret; |
514 | } | 524 | } |
515 | 525 | ||
@@ -556,7 +566,11 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) | |||
556 | u16 value; | 566 | u16 value; |
557 | u16 index; | 567 | u16 index; |
558 | int blen; | 568 | int blen; |
559 | u8 b[12]; | 569 | u8 *b; |
570 | |||
571 | b = kmalloc(12, GFP_KERNEL); | ||
572 | if (!b) | ||
573 | return -ENOMEM; | ||
560 | 574 | ||
561 | req = 0xC8; | 575 | req = 0xC8; |
562 | value = 0; | 576 | value = 0; |
@@ -570,6 +584,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) | |||
570 | } else{ | 584 | } else{ |
571 | ret = b[0]; | 585 | ret = b[0]; |
572 | } | 586 | } |
587 | kfree(b); | ||
573 | return ret; | 588 | return ret; |
574 | } | 589 | } |
575 | 590 | ||
@@ -667,8 +682,11 @@ static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int o | |||
667 | u16 value; | 682 | u16 value; |
668 | u16 index; | 683 | u16 index; |
669 | int blen; | 684 | int blen; |
670 | u8 b[12]; | 685 | u8 *b; |
671 | 686 | ||
687 | b = kmalloc(12, GFP_KERNEL); | ||
688 | if (!b) | ||
689 | return -ENOMEM; | ||
672 | mutex_lock(&state->ca_mutex); | 690 | mutex_lock(&state->ca_mutex); |
673 | 691 | ||
674 | req = 0xC5; | 692 | req = 0xC5; |
@@ -683,15 +701,13 @@ static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int o | |||
683 | } else | 701 | } else |
684 | ret = 0; | 702 | ret = 0; |
685 | 703 | ||
686 | if (b[0] == 0) { | 704 | if (!ret && b[0] == 1) { |
687 | ret = 0; | ||
688 | |||
689 | } else if (b[0] == 1) { | ||
690 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT | | 705 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT | |
691 | DVB_CA_EN50221_POLL_CAM_READY; | 706 | DVB_CA_EN50221_POLL_CAM_READY; |
692 | } | 707 | } |
693 | 708 | ||
694 | mutex_unlock(&state->ca_mutex); | 709 | mutex_unlock(&state->ca_mutex); |
710 | kfree(b); | ||
695 | return ret; | 711 | return ret; |
696 | } | 712 | } |
697 | 713 | ||
@@ -943,10 +959,16 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n | |||
943 | u16 value; | 959 | u16 value; |
944 | int length; | 960 | int length; |
945 | u8 req; | 961 | u8 req; |
946 | u8 data[256]; | 962 | u8 *data; |
947 | 963 | ||
948 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 964 | data = kmalloc(256, GFP_KERNEL); |
965 | if (!data) | ||
966 | return -ENOMEM; | ||
967 | |||
968 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) { | ||
969 | kfree(data); | ||
949 | return -EAGAIN; | 970 | return -EAGAIN; |
971 | } | ||
950 | 972 | ||
951 | if (num > 2) | 973 | if (num > 2) |
952 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | 974 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); |
@@ -976,17 +998,14 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n | |||
976 | i++; | 998 | i++; |
977 | } else { | 999 | } else { |
978 | 1000 | ||
979 | if (msg[i].addr == 0xd0) { | 1001 | /* demod 16bit addr */ |
980 | /* demod 16bit addr */ | 1002 | req = 0xBD; |
981 | req = 0xBD; | 1003 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); |
982 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); | 1004 | value = msg[i].addr + (2 << 8); |
983 | value = msg[i].addr + (2 << 8); | 1005 | length = msg[i].len - 2; |
984 | length = msg[i].len - 2; | 1006 | len = msg[i].len - 2; |
985 | len = msg[i].len - 2; | 1007 | for (j = 0; j < len; j++) |
986 | for (j = 0; j < len; j++) | 1008 | data[j] = msg[i].buf[j + 2]; |
987 | data[j] = msg[i].buf[j + 2]; | ||
988 | |||
989 | } | ||
990 | az6027_usb_out_op(d, req, value, index, data, length); | 1009 | az6027_usb_out_op(d, req, value, index, data, length); |
991 | } | 1010 | } |
992 | } | 1011 | } |
@@ -1019,6 +1038,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n | |||
1019 | } | 1038 | } |
1020 | } | 1039 | } |
1021 | mutex_unlock(&d->i2c_mutex); | 1040 | mutex_unlock(&d->i2c_mutex); |
1041 | kfree(data); | ||
1022 | 1042 | ||
1023 | return i; | 1043 | return i; |
1024 | } | 1044 | } |
@@ -1039,8 +1059,14 @@ int az6027_identify_state(struct usb_device *udev, | |||
1039 | struct dvb_usb_device_description **desc, | 1059 | struct dvb_usb_device_description **desc, |
1040 | int *cold) | 1060 | int *cold) |
1041 | { | 1061 | { |
1042 | u8 b[16]; | 1062 | u8 *b; |
1043 | s16 ret = usb_control_msg(udev, | 1063 | s16 ret; |
1064 | |||
1065 | b = kmalloc(16, GFP_KERNEL); | ||
1066 | if (!b) | ||
1067 | return -ENOMEM; | ||
1068 | |||
1069 | ret = usb_control_msg(udev, | ||
1044 | usb_rcvctrlpipe(udev, 0), | 1070 | usb_rcvctrlpipe(udev, 0), |
1045 | 0xb7, | 1071 | 0xb7, |
1046 | USB_TYPE_VENDOR | USB_DIR_IN, | 1072 | USB_TYPE_VENDOR | USB_DIR_IN, |
@@ -1051,7 +1077,7 @@ int az6027_identify_state(struct usb_device *udev, | |||
1051 | USB_CTRL_GET_TIMEOUT); | 1077 | USB_CTRL_GET_TIMEOUT); |
1052 | 1078 | ||
1053 | *cold = ret <= 0; | 1079 | *cold = ret <= 0; |
1054 | 1080 | kfree(b); | |
1055 | deb_info("cold: %d\n", *cold); | 1081 | deb_info("cold: %d\n", *cold); |
1056 | return 0; | 1082 | return 0; |
1057 | } | 1083 | } |
@@ -1059,8 +1085,10 @@ int az6027_identify_state(struct usb_device *udev, | |||
1059 | 1085 | ||
1060 | static struct usb_device_id az6027_usb_table[] = { | 1086 | static struct usb_device_id az6027_usb_table[] = { |
1061 | { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, | 1087 | { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, |
1062 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI) }, | 1088 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V1) }, |
1063 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI) }, | 1089 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V2) }, |
1090 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) }, | ||
1091 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) }, | ||
1064 | { }, | 1092 | { }, |
1065 | }; | 1093 | }; |
1066 | 1094 | ||
@@ -1097,18 +1125,34 @@ static struct dvb_usb_device_properties az6027_properties = { | |||
1097 | .power_ctrl = az6027_power_ctrl, | 1125 | .power_ctrl = az6027_power_ctrl, |
1098 | .read_mac_address = az6027_read_mac_addr, | 1126 | .read_mac_address = az6027_read_mac_addr, |
1099 | */ | 1127 | */ |
1100 | .rc_key_map = az6027_rc_keys, | 1128 | .rc_key_map = ir_codes_az6027_table, |
1101 | .rc_key_map_size = ARRAY_SIZE(az6027_rc_keys), | 1129 | .rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table), |
1102 | .rc_interval = 400, | 1130 | .rc_interval = 400, |
1103 | .rc_query = az6027_rc_query, | 1131 | .rc_query = az6027_rc_query, |
1104 | .i2c_algo = &az6027_i2c_algo, | 1132 | .i2c_algo = &az6027_i2c_algo, |
1105 | 1133 | ||
1106 | .num_device_descs = 1, | 1134 | .num_device_descs = 5, |
1107 | .devices = { | 1135 | .devices = { |
1108 | { | 1136 | { |
1109 | .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", | 1137 | .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", |
1110 | .cold_ids = { &az6027_usb_table[0], NULL }, | 1138 | .cold_ids = { &az6027_usb_table[0], NULL }, |
1111 | .warm_ids = { NULL }, | 1139 | .warm_ids = { NULL }, |
1140 | }, { | ||
1141 | .name = "TERRATEC S7", | ||
1142 | .cold_ids = { &az6027_usb_table[1], NULL }, | ||
1143 | .warm_ids = { NULL }, | ||
1144 | }, { | ||
1145 | .name = "TERRATEC S7 MKII", | ||
1146 | .cold_ids = { &az6027_usb_table[2], NULL }, | ||
1147 | .warm_ids = { NULL }, | ||
1148 | }, { | ||
1149 | .name = "Technisat SkyStar USB 2 HD CI", | ||
1150 | .cold_ids = { &az6027_usb_table[3], NULL }, | ||
1151 | .warm_ids = { NULL }, | ||
1152 | }, { | ||
1153 | .name = "Technisat SkyStar USB 2 HD CI", | ||
1154 | .cold_ids = { &az6027_usb_table[4], NULL }, | ||
1155 | .warm_ids = { NULL }, | ||
1112 | }, | 1156 | }, |
1113 | { NULL }, | 1157 | { NULL }, |
1114 | } | 1158 | } |
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c index e37ac4d48602..5a9c14bdc980 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c | |||
@@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) | |||
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { | 87 | static struct dvb_usb_rc_key ir_codes_cinergyt2_table[] = { |
88 | { 0x0401, KEY_POWER }, | 88 | { 0x0401, KEY_POWER }, |
89 | { 0x0402, KEY_1 }, | 89 | { 0x0402, KEY_1 }, |
90 | { 0x0403, KEY_2 }, | 90 | { 0x0403, KEY_2 }, |
@@ -218,8 +218,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = { | |||
218 | .power_ctrl = cinergyt2_power_ctrl, | 218 | .power_ctrl = cinergyt2_power_ctrl, |
219 | 219 | ||
220 | .rc_interval = 50, | 220 | .rc_interval = 50, |
221 | .rc_key_map = cinergyt2_rc_keys, | 221 | .rc_key_map = ir_codes_cinergyt2_table, |
222 | .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys), | 222 | .rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table), |
223 | .rc_query = cinergyt2_rc_query, | 223 | .rc_query = cinergyt2_rc_query, |
224 | 224 | ||
225 | .generic_bulk_ctrl_endpoint = 1, | 225 | .generic_bulk_ctrl_endpoint = 1, |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 960376da7d59..0eb490889162 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | |||
461 | return 0; | 461 | return 0; |
462 | } | 462 | } |
463 | 463 | ||
464 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | 464 | static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = { |
465 | { 0xfe02, KEY_TV }, | 465 | { 0xfe02, KEY_TV }, |
466 | { 0xfe0e, KEY_MP3 }, | 466 | { 0xfe0e, KEY_MP3 }, |
467 | { 0xfe1a, KEY_DVD }, | 467 | { 0xfe1a, KEY_DVD }, |
@@ -509,7 +509,7 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | |||
509 | { 0xfe4e, KEY_POWER }, | 509 | { 0xfe4e, KEY_POWER }, |
510 | }; | 510 | }; |
511 | 511 | ||
512 | static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { | 512 | static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = { |
513 | { 0xfc02, KEY_SETUP }, /* Profile */ | 513 | { 0xfc02, KEY_SETUP }, /* Profile */ |
514 | { 0xfc43, KEY_POWER2 }, | 514 | { 0xfc43, KEY_POWER2 }, |
515 | { 0xfc06, KEY_EPG }, | 515 | { 0xfc06, KEY_EPG }, |
@@ -548,7 +548,7 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { | |||
548 | { 0xfc00, KEY_UNKNOWN }, /* HD */ | 548 | { 0xfc00, KEY_UNKNOWN }, /* HD */ |
549 | }; | 549 | }; |
550 | 550 | ||
551 | static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { | 551 | static struct dvb_usb_rc_key ir_codes_d680_dmb_table[] = { |
552 | { 0x0038, KEY_UNKNOWN }, /* TV/AV */ | 552 | { 0x0038, KEY_UNKNOWN }, /* TV/AV */ |
553 | { 0x080c, KEY_ZOOM }, | 553 | { 0x080c, KEY_ZOOM }, |
554 | { 0x0800, KEY_0 }, | 554 | { 0x0800, KEY_0 }, |
@@ -1025,8 +1025,9 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | |||
1025 | 1025 | ||
1026 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | 1026 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); |
1027 | 1027 | ||
1028 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 1028 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
1029 | &cxusb_dualdig4_rev2_config); | 1029 | &cxusb_dualdig4_rev2_config) < 0) |
1030 | return -ENODEV; | ||
1030 | 1031 | ||
1031 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | 1032 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, |
1032 | &cxusb_dualdig4_rev2_config); | 1033 | &cxusb_dualdig4_rev2_config); |
@@ -1449,8 +1450,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { | |||
1449 | .i2c_algo = &cxusb_i2c_algo, | 1450 | .i2c_algo = &cxusb_i2c_algo, |
1450 | 1451 | ||
1451 | .rc_interval = 100, | 1452 | .rc_interval = 100, |
1452 | .rc_key_map = dvico_portable_rc_keys, | 1453 | .rc_key_map = ir_codes_dvico_portable_table, |
1453 | .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys), | 1454 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), |
1454 | .rc_query = cxusb_rc_query, | 1455 | .rc_query = cxusb_rc_query, |
1455 | 1456 | ||
1456 | .generic_bulk_ctrl_endpoint = 0x01, | 1457 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -1500,8 +1501,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { | |||
1500 | .i2c_algo = &cxusb_i2c_algo, | 1501 | .i2c_algo = &cxusb_i2c_algo, |
1501 | 1502 | ||
1502 | .rc_interval = 150, | 1503 | .rc_interval = 150, |
1503 | .rc_key_map = dvico_mce_rc_keys, | 1504 | .rc_key_map = ir_codes_dvico_mce_table, |
1504 | .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), | 1505 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), |
1505 | .rc_query = cxusb_rc_query, | 1506 | .rc_query = cxusb_rc_query, |
1506 | 1507 | ||
1507 | .generic_bulk_ctrl_endpoint = 0x01, | 1508 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -1559,8 +1560,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { | |||
1559 | .i2c_algo = &cxusb_i2c_algo, | 1560 | .i2c_algo = &cxusb_i2c_algo, |
1560 | 1561 | ||
1561 | .rc_interval = 100, | 1562 | .rc_interval = 100, |
1562 | .rc_key_map = dvico_portable_rc_keys, | 1563 | .rc_key_map = ir_codes_dvico_portable_table, |
1563 | .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys), | 1564 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), |
1564 | .rc_query = cxusb_rc_query, | 1565 | .rc_query = cxusb_rc_query, |
1565 | 1566 | ||
1566 | .generic_bulk_ctrl_endpoint = 0x01, | 1567 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -1609,8 +1610,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | |||
1609 | .i2c_algo = &cxusb_i2c_algo, | 1610 | .i2c_algo = &cxusb_i2c_algo, |
1610 | 1611 | ||
1611 | .rc_interval = 100, | 1612 | .rc_interval = 100, |
1612 | .rc_key_map = dvico_portable_rc_keys, | 1613 | .rc_key_map = ir_codes_dvico_portable_table, |
1613 | .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys), | 1614 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), |
1614 | .rc_query = cxusb_rc_query, | 1615 | .rc_query = cxusb_rc_query, |
1615 | 1616 | ||
1616 | .generic_bulk_ctrl_endpoint = 0x01, | 1617 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -1658,8 +1659,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { | |||
1658 | .generic_bulk_ctrl_endpoint = 0x01, | 1659 | .generic_bulk_ctrl_endpoint = 0x01, |
1659 | 1660 | ||
1660 | .rc_interval = 100, | 1661 | .rc_interval = 100, |
1661 | .rc_key_map = dvico_mce_rc_keys, | 1662 | .rc_key_map = ir_codes_dvico_mce_table, |
1662 | .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), | 1663 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), |
1663 | .rc_query = cxusb_bluebird2_rc_query, | 1664 | .rc_query = cxusb_bluebird2_rc_query, |
1664 | 1665 | ||
1665 | .num_device_descs = 1, | 1666 | .num_device_descs = 1, |
@@ -1706,8 +1707,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = { | |||
1706 | .generic_bulk_ctrl_endpoint = 0x01, | 1707 | .generic_bulk_ctrl_endpoint = 0x01, |
1707 | 1708 | ||
1708 | .rc_interval = 100, | 1709 | .rc_interval = 100, |
1709 | .rc_key_map = dvico_portable_rc_keys, | 1710 | .rc_key_map = ir_codes_dvico_portable_table, |
1710 | .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys), | 1711 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), |
1711 | .rc_query = cxusb_bluebird2_rc_query, | 1712 | .rc_query = cxusb_bluebird2_rc_query, |
1712 | 1713 | ||
1713 | .num_device_descs = 1, | 1714 | .num_device_descs = 1, |
@@ -1756,8 +1757,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope | |||
1756 | .generic_bulk_ctrl_endpoint = 0x01, | 1757 | .generic_bulk_ctrl_endpoint = 0x01, |
1757 | 1758 | ||
1758 | .rc_interval = 100, | 1759 | .rc_interval = 100, |
1759 | .rc_key_map = dvico_portable_rc_keys, | 1760 | .rc_key_map = ir_codes_dvico_portable_table, |
1760 | .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys), | 1761 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), |
1761 | .rc_query = cxusb_rc_query, | 1762 | .rc_query = cxusb_rc_query, |
1762 | 1763 | ||
1763 | .num_device_descs = 1, | 1764 | .num_device_descs = 1, |
@@ -1847,8 +1848,8 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { | |||
1847 | .generic_bulk_ctrl_endpoint = 0x01, | 1848 | .generic_bulk_ctrl_endpoint = 0x01, |
1848 | 1849 | ||
1849 | .rc_interval = 100, | 1850 | .rc_interval = 100, |
1850 | .rc_key_map = dvico_mce_rc_keys, | 1851 | .rc_key_map = ir_codes_dvico_mce_table, |
1851 | .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), | 1852 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), |
1852 | .rc_query = cxusb_rc_query, | 1853 | .rc_query = cxusb_rc_query, |
1853 | 1854 | ||
1854 | .num_device_descs = 1, | 1855 | .num_device_descs = 1, |
@@ -1895,8 +1896,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { | |||
1895 | .generic_bulk_ctrl_endpoint = 0x01, | 1896 | .generic_bulk_ctrl_endpoint = 0x01, |
1896 | 1897 | ||
1897 | .rc_interval = 100, | 1898 | .rc_interval = 100, |
1898 | .rc_key_map = d680_dmb_rc_keys, | 1899 | .rc_key_map = ir_codes_d680_dmb_table, |
1899 | .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), | 1900 | .rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table), |
1900 | .rc_query = cxusb_d680_dmb_rc_query, | 1901 | .rc_query = cxusb_d680_dmb_rc_query, |
1901 | 1902 | ||
1902 | .num_device_descs = 1, | 1903 | .num_device_descs = 1, |
@@ -1944,8 +1945,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { | |||
1944 | .generic_bulk_ctrl_endpoint = 0x01, | 1945 | .generic_bulk_ctrl_endpoint = 0x01, |
1945 | 1946 | ||
1946 | .rc_interval = 100, | 1947 | .rc_interval = 100, |
1947 | .rc_key_map = d680_dmb_rc_keys, | 1948 | .rc_key_map = ir_codes_d680_dmb_table, |
1948 | .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), | 1949 | .rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table), |
1949 | .rc_query = cxusb_d680_dmb_rc_query, | 1950 | .rc_query = cxusb_d680_dmb_rc_query, |
1950 | 1951 | ||
1951 | .num_device_descs = 1, | 1952 | .num_device_descs = 1, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 34eab05afc6c..800800a9649e 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -562,7 +562,7 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
562 | return 0; | 562 | return 0; |
563 | } | 563 | } |
564 | 564 | ||
565 | static struct dvb_usb_rc_key dib0700_rc_keys[] = { | 565 | static struct dvb_usb_rc_key ir_codes_dib0700_table[] = { |
566 | /* Key codes for the tiny Pinnacle remote*/ | 566 | /* Key codes for the tiny Pinnacle remote*/ |
567 | { 0x0700, KEY_MUTE }, | 567 | { 0x0700, KEY_MUTE }, |
568 | { 0x0701, KEY_MENU }, /* Pinnacle logo */ | 568 | { 0x0701, KEY_MENU }, /* Pinnacle logo */ |
@@ -794,6 +794,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { | |||
794 | { 0x7a13, KEY_VOLUMEDOWN }, | 794 | { 0x7a13, KEY_VOLUMEDOWN }, |
795 | { 0x7a40, KEY_POWER }, | 795 | { 0x7a40, KEY_POWER }, |
796 | { 0x7a41, KEY_MUTE }, | 796 | { 0x7a41, KEY_MUTE }, |
797 | |||
798 | /* Key codes for the Elgato EyeTV Diversity silver remote, | ||
799 | set dvb_usb_dib0700_ir_proto=0 */ | ||
800 | { 0x4501, KEY_POWER }, | ||
801 | { 0x4502, KEY_MUTE }, | ||
802 | { 0x4503, KEY_1 }, | ||
803 | { 0x4504, KEY_2 }, | ||
804 | { 0x4505, KEY_3 }, | ||
805 | { 0x4506, KEY_4 }, | ||
806 | { 0x4507, KEY_5 }, | ||
807 | { 0x4508, KEY_6 }, | ||
808 | { 0x4509, KEY_7 }, | ||
809 | { 0x450a, KEY_8 }, | ||
810 | { 0x450b, KEY_9 }, | ||
811 | { 0x450c, KEY_LAST }, | ||
812 | { 0x450d, KEY_0 }, | ||
813 | { 0x450e, KEY_ENTER }, | ||
814 | { 0x450f, KEY_RED }, | ||
815 | { 0x4510, KEY_CHANNELUP }, | ||
816 | { 0x4511, KEY_GREEN }, | ||
817 | { 0x4512, KEY_VOLUMEDOWN }, | ||
818 | { 0x4513, KEY_OK }, | ||
819 | { 0x4514, KEY_VOLUMEUP }, | ||
820 | { 0x4515, KEY_YELLOW }, | ||
821 | { 0x4516, KEY_CHANNELDOWN }, | ||
822 | { 0x4517, KEY_BLUE }, | ||
823 | { 0x4518, KEY_LEFT }, /* Skip backwards */ | ||
824 | { 0x4519, KEY_PLAYPAUSE }, | ||
825 | { 0x451a, KEY_RIGHT }, /* Skip forward */ | ||
826 | { 0x451b, KEY_REWIND }, | ||
827 | { 0x451c, KEY_L }, /* Live */ | ||
828 | { 0x451d, KEY_FASTFORWARD }, | ||
829 | { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */ | ||
830 | { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */ | ||
831 | { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */ | ||
832 | { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */ | ||
833 | { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */ | ||
797 | }; | 834 | }; |
798 | 835 | ||
799 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 836 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
@@ -2049,6 +2086,7 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
2049 | /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, | 2086 | /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, |
2050 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, | 2087 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, |
2051 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, | 2088 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, |
2089 | { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DIVERSITY) }, | ||
2052 | { 0 } /* Terminating entry */ | 2090 | { 0 } /* Terminating entry */ |
2053 | }; | 2091 | }; |
2054 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 2092 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -2131,8 +2169,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2131 | }, | 2169 | }, |
2132 | 2170 | ||
2133 | .rc_interval = DEFAULT_RC_INTERVAL, | 2171 | .rc_interval = DEFAULT_RC_INTERVAL, |
2134 | .rc_key_map = dib0700_rc_keys, | 2172 | .rc_key_map = ir_codes_dib0700_table, |
2135 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2173 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2136 | .rc_query = dib0700_rc_query | 2174 | .rc_query = dib0700_rc_query |
2137 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2175 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2138 | 2176 | ||
@@ -2160,8 +2198,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2160 | }, | 2198 | }, |
2161 | 2199 | ||
2162 | .rc_interval = DEFAULT_RC_INTERVAL, | 2200 | .rc_interval = DEFAULT_RC_INTERVAL, |
2163 | .rc_key_map = dib0700_rc_keys, | 2201 | .rc_key_map = ir_codes_dib0700_table, |
2164 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2202 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2165 | .rc_query = dib0700_rc_query | 2203 | .rc_query = dib0700_rc_query |
2166 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2204 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2167 | 2205 | ||
@@ -2214,8 +2252,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2214 | }, | 2252 | }, |
2215 | 2253 | ||
2216 | .rc_interval = DEFAULT_RC_INTERVAL, | 2254 | .rc_interval = DEFAULT_RC_INTERVAL, |
2217 | .rc_key_map = dib0700_rc_keys, | 2255 | .rc_key_map = ir_codes_dib0700_table, |
2218 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2256 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2219 | .rc_query = dib0700_rc_query | 2257 | .rc_query = dib0700_rc_query |
2220 | 2258 | ||
2221 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2259 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
@@ -2251,8 +2289,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2251 | }, | 2289 | }, |
2252 | 2290 | ||
2253 | .rc_interval = DEFAULT_RC_INTERVAL, | 2291 | .rc_interval = DEFAULT_RC_INTERVAL, |
2254 | .rc_key_map = dib0700_rc_keys, | 2292 | .rc_key_map = ir_codes_dib0700_table, |
2255 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2293 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2256 | .rc_query = dib0700_rc_query | 2294 | .rc_query = dib0700_rc_query |
2257 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2295 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2258 | 2296 | ||
@@ -2321,8 +2359,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2321 | }, | 2359 | }, |
2322 | 2360 | ||
2323 | .rc_interval = DEFAULT_RC_INTERVAL, | 2361 | .rc_interval = DEFAULT_RC_INTERVAL, |
2324 | .rc_key_map = dib0700_rc_keys, | 2362 | .rc_key_map = ir_codes_dib0700_table, |
2325 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2363 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2326 | .rc_query = dib0700_rc_query | 2364 | .rc_query = dib0700_rc_query |
2327 | 2365 | ||
2328 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2366 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
@@ -2360,8 +2398,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2360 | }, | 2398 | }, |
2361 | 2399 | ||
2362 | .rc_interval = DEFAULT_RC_INTERVAL, | 2400 | .rc_interval = DEFAULT_RC_INTERVAL, |
2363 | .rc_key_map = dib0700_rc_keys, | 2401 | .rc_key_map = ir_codes_dib0700_table, |
2364 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2402 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2365 | .rc_query = dib0700_rc_query | 2403 | .rc_query = dib0700_rc_query |
2366 | 2404 | ||
2367 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2405 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
@@ -2393,7 +2431,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2393 | } | 2431 | } |
2394 | }, | 2432 | }, |
2395 | 2433 | ||
2396 | .num_device_descs = 6, | 2434 | .num_device_descs = 7, |
2397 | .devices = { | 2435 | .devices = { |
2398 | { "DiBcom STK7070PD reference design", | 2436 | { "DiBcom STK7070PD reference design", |
2399 | { &dib0700_usb_id_table[17], NULL }, | 2437 | { &dib0700_usb_id_table[17], NULL }, |
@@ -2419,11 +2457,15 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2419 | { "Sony PlayTV", | 2457 | { "Sony PlayTV", |
2420 | { &dib0700_usb_id_table[44], NULL }, | 2458 | { &dib0700_usb_id_table[44], NULL }, |
2421 | { NULL }, | 2459 | { NULL }, |
2422 | } | 2460 | }, |
2461 | { "Elgato EyeTV Diversity", | ||
2462 | { &dib0700_usb_id_table[68], NULL }, | ||
2463 | { NULL }, | ||
2464 | }, | ||
2423 | }, | 2465 | }, |
2424 | .rc_interval = DEFAULT_RC_INTERVAL, | 2466 | .rc_interval = DEFAULT_RC_INTERVAL, |
2425 | .rc_key_map = dib0700_rc_keys, | 2467 | .rc_key_map = ir_codes_dib0700_table, |
2426 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2468 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2427 | .rc_query = dib0700_rc_query | 2469 | .rc_query = dib0700_rc_query |
2428 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2470 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2429 | 2471 | ||
@@ -2484,8 +2526,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2484 | }, | 2526 | }, |
2485 | }, | 2527 | }, |
2486 | .rc_interval = DEFAULT_RC_INTERVAL, | 2528 | .rc_interval = DEFAULT_RC_INTERVAL, |
2487 | .rc_key_map = dib0700_rc_keys, | 2529 | .rc_key_map = ir_codes_dib0700_table, |
2488 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2530 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2489 | .rc_query = dib0700_rc_query | 2531 | .rc_query = dib0700_rc_query |
2490 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2532 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2491 | .num_adapters = 1, | 2533 | .num_adapters = 1, |
@@ -2513,8 +2555,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2513 | }, | 2555 | }, |
2514 | }, | 2556 | }, |
2515 | .rc_interval = DEFAULT_RC_INTERVAL, | 2557 | .rc_interval = DEFAULT_RC_INTERVAL, |
2516 | .rc_key_map = dib0700_rc_keys, | 2558 | .rc_key_map = ir_codes_dib0700_table, |
2517 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2559 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2518 | .rc_query = dib0700_rc_query | 2560 | .rc_query = dib0700_rc_query |
2519 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2561 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2520 | .num_adapters = 1, | 2562 | .num_adapters = 1, |
@@ -2574,8 +2616,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2574 | }, | 2616 | }, |
2575 | }, | 2617 | }, |
2576 | .rc_interval = DEFAULT_RC_INTERVAL, | 2618 | .rc_interval = DEFAULT_RC_INTERVAL, |
2577 | .rc_key_map = dib0700_rc_keys, | 2619 | .rc_key_map = ir_codes_dib0700_table, |
2578 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2620 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2579 | .rc_query = dib0700_rc_query | 2621 | .rc_query = dib0700_rc_query |
2580 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2622 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2581 | .num_adapters = 1, | 2623 | .num_adapters = 1, |
@@ -2612,8 +2654,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2612 | }, | 2654 | }, |
2613 | 2655 | ||
2614 | .rc_interval = DEFAULT_RC_INTERVAL, | 2656 | .rc_interval = DEFAULT_RC_INTERVAL, |
2615 | .rc_key_map = dib0700_rc_keys, | 2657 | .rc_key_map = ir_codes_dib0700_table, |
2616 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2658 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2617 | .rc_query = dib0700_rc_query | 2659 | .rc_query = dib0700_rc_query |
2618 | 2660 | ||
2619 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2661 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
@@ -2656,8 +2698,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2656 | }, | 2698 | }, |
2657 | 2699 | ||
2658 | .rc_interval = DEFAULT_RC_INTERVAL, | 2700 | .rc_interval = DEFAULT_RC_INTERVAL, |
2659 | .rc_key_map = dib0700_rc_keys, | 2701 | .rc_key_map = ir_codes_dib0700_table, |
2660 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2702 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2661 | .rc_query = dib0700_rc_query | 2703 | .rc_query = dib0700_rc_query |
2662 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 2704 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
2663 | .num_adapters = 1, | 2705 | .num_adapters = 1, |
@@ -2687,8 +2729,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2687 | }, | 2729 | }, |
2688 | 2730 | ||
2689 | .rc_interval = DEFAULT_RC_INTERVAL, | 2731 | .rc_interval = DEFAULT_RC_INTERVAL, |
2690 | .rc_key_map = dib0700_rc_keys, | 2732 | .rc_key_map = ir_codes_dib0700_table, |
2691 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2733 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table), |
2692 | .rc_query = dib0700_rc_query | 2734 | .rc_query = dib0700_rc_query |
2693 | }, | 2735 | }, |
2694 | }; | 2736 | }; |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 9143b5631e88..bc08bc0b723c 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
@@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); | |||
327 | /* | 327 | /* |
328 | * common remote control stuff | 328 | * common remote control stuff |
329 | */ | 329 | */ |
330 | struct dvb_usb_rc_key dibusb_rc_keys[] = { | 330 | struct dvb_usb_rc_key ir_codes_dibusb_table[] = { |
331 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ | 331 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ |
332 | { 0x0016, KEY_POWER }, | 332 | { 0x0016, KEY_POWER }, |
333 | { 0x0010, KEY_MUTE }, | 333 | { 0x0010, KEY_MUTE }, |
@@ -456,7 +456,7 @@ struct dvb_usb_rc_key dibusb_rc_keys[] = { | |||
456 | { 0x804e, KEY_ENTER }, | 456 | { 0x804e, KEY_ENTER }, |
457 | { 0x804f, KEY_VOLUMEDOWN }, | 457 | { 0x804f, KEY_VOLUMEDOWN }, |
458 | }; | 458 | }; |
459 | EXPORT_SYMBOL(dibusb_rc_keys); | 459 | EXPORT_SYMBOL(ir_codes_dibusb_table); |
460 | 460 | ||
461 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 461 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
462 | { | 462 | { |
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 5c0126dc1ff9..eb2e6f050fbe 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
@@ -212,7 +212,7 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { | |||
212 | .power_ctrl = dibusb_power_ctrl, | 212 | .power_ctrl = dibusb_power_ctrl, |
213 | 213 | ||
214 | .rc_interval = DEFAULT_RC_INTERVAL, | 214 | .rc_interval = DEFAULT_RC_INTERVAL, |
215 | .rc_key_map = dibusb_rc_keys, | 215 | .rc_key_map = ir_codes_dibusb_table, |
216 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | 216 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
217 | .rc_query = dibusb_rc_query, | 217 | .rc_query = dibusb_rc_query, |
218 | 218 | ||
@@ -296,7 +296,7 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { | |||
296 | .power_ctrl = dibusb_power_ctrl, | 296 | .power_ctrl = dibusb_power_ctrl, |
297 | 297 | ||
298 | .rc_interval = DEFAULT_RC_INTERVAL, | 298 | .rc_interval = DEFAULT_RC_INTERVAL, |
299 | .rc_key_map = dibusb_rc_keys, | 299 | .rc_key_map = ir_codes_dibusb_table, |
300 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | 300 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
301 | .rc_query = dibusb_rc_query, | 301 | .rc_query = dibusb_rc_query, |
302 | 302 | ||
@@ -360,7 +360,7 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { | |||
360 | .power_ctrl = dibusb2_0_power_ctrl, | 360 | .power_ctrl = dibusb2_0_power_ctrl, |
361 | 361 | ||
362 | .rc_interval = DEFAULT_RC_INTERVAL, | 362 | .rc_interval = DEFAULT_RC_INTERVAL, |
363 | .rc_key_map = dibusb_rc_keys, | 363 | .rc_key_map = ir_codes_dibusb_table, |
364 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | 364 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
365 | .rc_query = dibusb_rc_query, | 365 | .rc_query = dibusb_rc_query, |
366 | 366 | ||
@@ -417,7 +417,7 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { | |||
417 | .power_ctrl = dibusb2_0_power_ctrl, | 417 | .power_ctrl = dibusb2_0_power_ctrl, |
418 | 418 | ||
419 | .rc_interval = DEFAULT_RC_INTERVAL, | 419 | .rc_interval = DEFAULT_RC_INTERVAL, |
420 | .rc_key_map = dibusb_rc_keys, | 420 | .rc_key_map = ir_codes_dibusb_table, |
421 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | 421 | .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ |
422 | .rc_query = dibusb_rc_query, | 422 | .rc_query = dibusb_rc_query, |
423 | 423 | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index a05b9f875663..588308eb6638 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
@@ -82,7 +82,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { | |||
82 | .power_ctrl = dibusb2_0_power_ctrl, | 82 | .power_ctrl = dibusb2_0_power_ctrl, |
83 | 83 | ||
84 | .rc_interval = DEFAULT_RC_INTERVAL, | 84 | .rc_interval = DEFAULT_RC_INTERVAL, |
85 | .rc_key_map = dibusb_rc_keys, | 85 | .rc_key_map = ir_codes_dibusb_table, |
86 | .rc_key_map_size = 111, /* FIXME */ | 86 | .rc_key_map_size = 111, /* FIXME */ |
87 | .rc_query = dibusb_rc_query, | 87 | .rc_query = dibusb_rc_query, |
88 | 88 | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h index 8e847aa73ba1..3d50ac59088f 100644 --- a/drivers/media/dvb/dvb-usb/dibusb.h +++ b/drivers/media/dvb/dvb-usb/dibusb.h | |||
@@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int); | |||
124 | #define DEFAULT_RC_INTERVAL 150 | 124 | #define DEFAULT_RC_INTERVAL 150 |
125 | //#define DEFAULT_RC_INTERVAL 100000 | 125 | //#define DEFAULT_RC_INTERVAL 100000 |
126 | 126 | ||
127 | extern struct dvb_usb_rc_key dibusb_rc_keys[]; | 127 | extern struct dvb_usb_rc_key ir_codes_dibusb_table[]; |
128 | extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); | 128 | extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); |
129 | extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); | 129 | extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); |
130 | 130 | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 955147d00756..e826077094fa 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | static struct dvb_usb_rc_key digitv_rc_keys[] = { | 164 | static struct dvb_usb_rc_key ir_codes_digitv_table[] = { |
165 | { 0x5f55, KEY_0 }, | 165 | { 0x5f55, KEY_0 }, |
166 | { 0x6f55, KEY_1 }, | 166 | { 0x6f55, KEY_1 }, |
167 | { 0x9f55, KEY_2 }, | 167 | { 0x9f55, KEY_2 }, |
@@ -311,8 +311,8 @@ static struct dvb_usb_device_properties digitv_properties = { | |||
311 | .identify_state = digitv_identify_state, | 311 | .identify_state = digitv_identify_state, |
312 | 312 | ||
313 | .rc_interval = 1000, | 313 | .rc_interval = 1000, |
314 | .rc_key_map = digitv_rc_keys, | 314 | .rc_key_map = ir_codes_digitv_table, |
315 | .rc_key_map_size = ARRAY_SIZE(digitv_rc_keys), | 315 | .rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table), |
316 | .rc_query = digitv_rc_query, | 316 | .rc_query = digitv_rc_query, |
317 | 317 | ||
318 | .i2c_algo = &digitv_i2c_algo, | 318 | .i2c_algo = &digitv_i2c_algo, |
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index a1b12b01cbe4..f57e59044d4d 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | |||
57 | 57 | ||
58 | /* remote control */ | 58 | /* remote control */ |
59 | /* key list for the tiny remote control (Yakumo, don't know about the others) */ | 59 | /* key list for the tiny remote control (Yakumo, don't know about the others) */ |
60 | static struct dvb_usb_rc_key dtt200u_rc_keys[] = { | 60 | static struct dvb_usb_rc_key ir_codes_dtt200u_table[] = { |
61 | { 0x8001, KEY_MUTE }, | 61 | { 0x8001, KEY_MUTE }, |
62 | { 0x8002, KEY_CHANNELDOWN }, | 62 | { 0x8002, KEY_CHANNELDOWN }, |
63 | { 0x8003, KEY_VOLUMEDOWN }, | 63 | { 0x8003, KEY_VOLUMEDOWN }, |
@@ -162,8 +162,8 @@ static struct dvb_usb_device_properties dtt200u_properties = { | |||
162 | .power_ctrl = dtt200u_power_ctrl, | 162 | .power_ctrl = dtt200u_power_ctrl, |
163 | 163 | ||
164 | .rc_interval = 300, | 164 | .rc_interval = 300, |
165 | .rc_key_map = dtt200u_rc_keys, | 165 | .rc_key_map = ir_codes_dtt200u_table, |
166 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | 166 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), |
167 | .rc_query = dtt200u_rc_query, | 167 | .rc_query = dtt200u_rc_query, |
168 | 168 | ||
169 | .generic_bulk_ctrl_endpoint = 0x01, | 169 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -207,8 +207,8 @@ static struct dvb_usb_device_properties wt220u_properties = { | |||
207 | .power_ctrl = dtt200u_power_ctrl, | 207 | .power_ctrl = dtt200u_power_ctrl, |
208 | 208 | ||
209 | .rc_interval = 300, | 209 | .rc_interval = 300, |
210 | .rc_key_map = dtt200u_rc_keys, | 210 | .rc_key_map = ir_codes_dtt200u_table, |
211 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | 211 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), |
212 | .rc_query = dtt200u_rc_query, | 212 | .rc_query = dtt200u_rc_query, |
213 | 213 | ||
214 | .generic_bulk_ctrl_endpoint = 0x01, | 214 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -252,8 +252,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = { | |||
252 | .power_ctrl = dtt200u_power_ctrl, | 252 | .power_ctrl = dtt200u_power_ctrl, |
253 | 253 | ||
254 | .rc_interval = 300, | 254 | .rc_interval = 300, |
255 | .rc_key_map = dtt200u_rc_keys, | 255 | .rc_key_map = ir_codes_dtt200u_table, |
256 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | 256 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), |
257 | .rc_query = dtt200u_rc_query, | 257 | .rc_query = dtt200u_rc_query, |
258 | 258 | ||
259 | .generic_bulk_ctrl_endpoint = 0x01, | 259 | .generic_bulk_ctrl_endpoint = 0x01, |
@@ -297,8 +297,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { | |||
297 | .power_ctrl = dtt200u_power_ctrl, | 297 | .power_ctrl = dtt200u_power_ctrl, |
298 | 298 | ||
299 | .rc_interval = 300, | 299 | .rc_interval = 300, |
300 | .rc_key_map = dtt200u_rc_keys, | 300 | .rc_key_map = ir_codes_dtt200u_table, |
301 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | 301 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), |
302 | .rc_query = dtt200u_rc_query, | 302 | .rc_query = dtt200u_rc_query, |
303 | 303 | ||
304 | .generic_bulk_ctrl_endpoint = 0x01, | 304 | .generic_bulk_ctrl_endpoint = 0x01, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index ae8b57acfe05..085c4e457e0e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -124,9 +124,11 @@ | |||
124 | #define USB_PID_KWORLD_395U 0xe396 | 124 | #define USB_PID_KWORLD_395U 0xe396 |
125 | #define USB_PID_KWORLD_395U_2 0xe39b | 125 | #define USB_PID_KWORLD_395U_2 0xe39b |
126 | #define USB_PID_KWORLD_395U_3 0xe395 | 126 | #define USB_PID_KWORLD_395U_3 0xe395 |
127 | #define USB_PID_KWORLD_395U_4 0xe39a | ||
127 | #define USB_PID_KWORLD_MC810 0xc810 | 128 | #define USB_PID_KWORLD_MC810 0xc810 |
128 | #define USB_PID_KWORLD_PC160_2T 0xc160 | 129 | #define USB_PID_KWORLD_PC160_2T 0xc160 |
129 | #define USB_PID_KWORLD_PC160_T 0xc161 | 130 | #define USB_PID_KWORLD_PC160_T 0xc161 |
131 | #define USB_PID_KWORLD_UB383_T 0xe383 | ||
130 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 132 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
131 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | 133 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df |
132 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 | 134 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 |
@@ -288,6 +290,7 @@ | |||
288 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 | 290 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 |
289 | #define USB_PID_SONY_PLAYTV 0x0003 | 291 | #define USB_PID_SONY_PLAYTV 0x0003 |
290 | #define USB_PID_MYGICA_D689 0xd811 | 292 | #define USB_PID_MYGICA_D689 0xd811 |
293 | #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 | ||
291 | #define USB_PID_ELGATO_EYETV_DTT 0x0021 | 294 | #define USB_PID_ELGATO_EYETV_DTT 0x0021 |
292 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 | 295 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 |
293 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 | 296 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 |
@@ -296,6 +299,8 @@ | |||
296 | #define USB_PID_TVWAY_PLUS 0x0002 | 299 | #define USB_PID_TVWAY_PLUS 0x0002 |
297 | #define USB_PID_SVEON_STV20 0xe39d | 300 | #define USB_PID_SVEON_STV20 0xe39d |
298 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 | 301 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 |
299 | #define USB_PID_TERRATEC_DVBS2CI 0x3275 | 302 | #define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4 |
300 | #define USB_PID_TECHNISAT_USB2_HDCI 0x0002 | 303 | #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac |
304 | #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 | ||
305 | #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 | ||
301 | #endif | 306 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index 6fe71c6745eb..bb46ba6a3573 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c | |||
@@ -42,6 +42,8 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | |||
42 | msleep(delay_ms); | 42 | msleep(delay_ms); |
43 | 43 | ||
44 | ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, | 44 | ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, |
45 | d->props.generic_bulk_ctrl_endpoint_response ? | ||
46 | d->props.generic_bulk_ctrl_endpoint_response : | ||
45 | d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, | 47 | d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, |
46 | 2000); | 48 | 2000); |
47 | 49 | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 0143aef19ecd..4a9f676087bf 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
@@ -198,6 +198,12 @@ struct dvb_usb_adapter_properties { | |||
198 | * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write- | 198 | * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write- |
199 | * helper functions. | 199 | * helper functions. |
200 | * | 200 | * |
201 | * @generic_bulk_ctrl_endpoint_response: some DVB USB devices use a separate | ||
202 | * endpoint for responses to control messages sent with bulk transfers via | ||
203 | * the generic_bulk_ctrl_endpoint. When this is non-zero, this will be used | ||
204 | * instead of the generic_bulk_ctrl_endpoint when reading usb responses in | ||
205 | * the dvb_usb_generic_rw helper function. | ||
206 | * | ||
201 | * @num_device_descs: number of struct dvb_usb_device_description in @devices | 207 | * @num_device_descs: number of struct dvb_usb_device_description in @devices |
202 | * @devices: array of struct dvb_usb_device_description compatibles with these | 208 | * @devices: array of struct dvb_usb_device_description compatibles with these |
203 | * properties. | 209 | * properties. |
@@ -239,6 +245,7 @@ struct dvb_usb_device_properties { | |||
239 | struct i2c_algorithm *i2c_algo; | 245 | struct i2c_algorithm *i2c_algo; |
240 | 246 | ||
241 | int generic_bulk_ctrl_endpoint; | 247 | int generic_bulk_ctrl_endpoint; |
248 | int generic_bulk_ctrl_endpoint_response; | ||
242 | 249 | ||
243 | int num_device_descs; | 250 | int num_device_descs; |
244 | struct dvb_usb_device_description devices[12]; | 251 | struct dvb_usb_device_description devices[12]; |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index accc65509b07..e8fb85380672 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -73,7 +73,7 @@ | |||
73 | "Please see linux/Documentation/dvb/ for more details " \ | 73 | "Please see linux/Documentation/dvb/ for more details " \ |
74 | "on firmware-problems." | 74 | "on firmware-problems." |
75 | 75 | ||
76 | struct dvb_usb_rc_keys_table { | 76 | struct ir_codes_dvb_usb_table_table { |
77 | struct dvb_usb_rc_key *rc_keys; | 77 | struct dvb_usb_rc_key *rc_keys; |
78 | int rc_keys_size; | 78 | int rc_keys_size; |
79 | }; | 79 | }; |
@@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) | |||
948 | return 0; | 948 | return 0; |
949 | } | 949 | } |
950 | 950 | ||
951 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { | 951 | static struct dvb_usb_rc_key ir_codes_dw210x_table[] = { |
952 | { 0xf80a, KEY_Q }, /*power*/ | 952 | { 0xf80a, KEY_Q }, /*power*/ |
953 | { 0xf80c, KEY_M }, /*mute*/ | 953 | { 0xf80c, KEY_M }, /*mute*/ |
954 | { 0xf811, KEY_1 }, | 954 | { 0xf811, KEY_1 }, |
@@ -982,7 +982,7 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = { | |||
982 | { 0xf81b, KEY_B }, /*recall*/ | 982 | { 0xf81b, KEY_B }, /*recall*/ |
983 | }; | 983 | }; |
984 | 984 | ||
985 | static struct dvb_usb_rc_key tevii_rc_keys[] = { | 985 | static struct dvb_usb_rc_key ir_codes_tevii_table[] = { |
986 | { 0xf80a, KEY_POWER }, | 986 | { 0xf80a, KEY_POWER }, |
987 | { 0xf80c, KEY_MUTE }, | 987 | { 0xf80c, KEY_MUTE }, |
988 | { 0xf811, KEY_1 }, | 988 | { 0xf811, KEY_1 }, |
@@ -1032,7 +1032,7 @@ static struct dvb_usb_rc_key tevii_rc_keys[] = { | |||
1032 | { 0xf858, KEY_SWITCHVIDEOMODE }, | 1032 | { 0xf858, KEY_SWITCHVIDEOMODE }, |
1033 | }; | 1033 | }; |
1034 | 1034 | ||
1035 | static struct dvb_usb_rc_key tbs_rc_keys[] = { | 1035 | static struct dvb_usb_rc_key ir_codes_tbs_table[] = { |
1036 | { 0xf884, KEY_POWER }, | 1036 | { 0xf884, KEY_POWER }, |
1037 | { 0xf894, KEY_MUTE }, | 1037 | { 0xf894, KEY_MUTE }, |
1038 | { 0xf887, KEY_1 }, | 1038 | { 0xf887, KEY_1 }, |
@@ -1067,10 +1067,10 @@ static struct dvb_usb_rc_key tbs_rc_keys[] = { | |||
1067 | { 0xf89b, KEY_MODE } | 1067 | { 0xf89b, KEY_MODE } |
1068 | }; | 1068 | }; |
1069 | 1069 | ||
1070 | static struct dvb_usb_rc_keys_table keys_tables[] = { | 1070 | static struct ir_codes_dvb_usb_table_table keys_tables[] = { |
1071 | { dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) }, | 1071 | { ir_codes_dw210x_table, ARRAY_SIZE(ir_codes_dw210x_table) }, |
1072 | { tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) }, | 1072 | { ir_codes_tevii_table, ARRAY_SIZE(ir_codes_tevii_table) }, |
1073 | { tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) }, | 1073 | { ir_codes_tbs_table, ARRAY_SIZE(ir_codes_tbs_table) }, |
1074 | }; | 1074 | }; |
1075 | 1075 | ||
1076 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 1076 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
@@ -1185,14 +1185,14 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
1185 | /* init registers */ | 1185 | /* init registers */ |
1186 | switch (dev->descriptor.idProduct) { | 1186 | switch (dev->descriptor.idProduct) { |
1187 | case USB_PID_PROF_1100: | 1187 | case USB_PID_PROF_1100: |
1188 | s6x0_properties.rc_key_map = tbs_rc_keys; | 1188 | s6x0_properties.rc_key_map = ir_codes_tbs_table; |
1189 | s6x0_properties.rc_key_map_size = | 1189 | s6x0_properties.rc_key_map_size = |
1190 | ARRAY_SIZE(tbs_rc_keys); | 1190 | ARRAY_SIZE(ir_codes_tbs_table); |
1191 | break; | 1191 | break; |
1192 | case USB_PID_TEVII_S650: | 1192 | case USB_PID_TEVII_S650: |
1193 | dw2104_properties.rc_key_map = tevii_rc_keys; | 1193 | dw2104_properties.rc_key_map = ir_codes_tevii_table; |
1194 | dw2104_properties.rc_key_map_size = | 1194 | dw2104_properties.rc_key_map_size = |
1195 | ARRAY_SIZE(tevii_rc_keys); | 1195 | ARRAY_SIZE(ir_codes_tevii_table); |
1196 | case USB_PID_DW2104: | 1196 | case USB_PID_DW2104: |
1197 | reset = 1; | 1197 | reset = 1; |
1198 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, | 1198 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, |
@@ -1255,8 +1255,8 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
1255 | .no_reconnect = 1, | 1255 | .no_reconnect = 1, |
1256 | 1256 | ||
1257 | .i2c_algo = &dw2102_serit_i2c_algo, | 1257 | .i2c_algo = &dw2102_serit_i2c_algo, |
1258 | .rc_key_map = dw210x_rc_keys, | 1258 | .rc_key_map = ir_codes_dw210x_table, |
1259 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | 1259 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), |
1260 | .rc_interval = 150, | 1260 | .rc_interval = 150, |
1261 | .rc_query = dw2102_rc_query, | 1261 | .rc_query = dw2102_rc_query, |
1262 | 1262 | ||
@@ -1306,8 +1306,8 @@ static struct dvb_usb_device_properties dw2104_properties = { | |||
1306 | .no_reconnect = 1, | 1306 | .no_reconnect = 1, |
1307 | 1307 | ||
1308 | .i2c_algo = &dw2104_i2c_algo, | 1308 | .i2c_algo = &dw2104_i2c_algo, |
1309 | .rc_key_map = dw210x_rc_keys, | 1309 | .rc_key_map = ir_codes_dw210x_table, |
1310 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | 1310 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), |
1311 | .rc_interval = 150, | 1311 | .rc_interval = 150, |
1312 | .rc_query = dw2102_rc_query, | 1312 | .rc_query = dw2102_rc_query, |
1313 | 1313 | ||
@@ -1353,8 +1353,8 @@ static struct dvb_usb_device_properties dw3101_properties = { | |||
1353 | .no_reconnect = 1, | 1353 | .no_reconnect = 1, |
1354 | 1354 | ||
1355 | .i2c_algo = &dw3101_i2c_algo, | 1355 | .i2c_algo = &dw3101_i2c_algo, |
1356 | .rc_key_map = dw210x_rc_keys, | 1356 | .rc_key_map = ir_codes_dw210x_table, |
1357 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | 1357 | .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), |
1358 | .rc_interval = 150, | 1358 | .rc_interval = 150, |
1359 | .rc_query = dw2102_rc_query, | 1359 | .rc_query = dw2102_rc_query, |
1360 | 1360 | ||
@@ -1396,8 +1396,8 @@ static struct dvb_usb_device_properties s6x0_properties = { | |||
1396 | .no_reconnect = 1, | 1396 | .no_reconnect = 1, |
1397 | 1397 | ||
1398 | .i2c_algo = &s6x0_i2c_algo, | 1398 | .i2c_algo = &s6x0_i2c_algo, |
1399 | .rc_key_map = tevii_rc_keys, | 1399 | .rc_key_map = ir_codes_tevii_table, |
1400 | .rc_key_map_size = ARRAY_SIZE(tevii_rc_keys), | 1400 | .rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table), |
1401 | .rc_interval = 150, | 1401 | .rc_interval = 150, |
1402 | .rc_query = dw2102_rc_query, | 1402 | .rc_query = dw2102_rc_query, |
1403 | 1403 | ||
@@ -1459,8 +1459,8 @@ static int dw2102_probe(struct usb_interface *intf, | |||
1459 | /* fill only different fields */ | 1459 | /* fill only different fields */ |
1460 | p7500->firmware = "dvb-usb-p7500.fw"; | 1460 | p7500->firmware = "dvb-usb-p7500.fw"; |
1461 | p7500->devices[0] = d7500; | 1461 | p7500->devices[0] = d7500; |
1462 | p7500->rc_key_map = tbs_rc_keys; | 1462 | p7500->rc_key_map = ir_codes_tbs_table; |
1463 | p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys); | 1463 | p7500->rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table); |
1464 | p7500->adapter->frontend_attach = prof_7500_frontend_attach; | 1464 | p7500->adapter->frontend_attach = prof_7500_frontend_attach; |
1465 | 1465 | ||
1466 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, | 1466 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index afb444db43ad..45106ac49674 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c | |||
@@ -105,6 +105,10 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) | |||
105 | 105 | ||
106 | ptr = fw->data; | 106 | ptr = fw->data; |
107 | buf = kmalloc(64, GFP_KERNEL | GFP_DMA); | 107 | buf = kmalloc(64, GFP_KERNEL | GFP_DMA); |
108 | if (!buf) { | ||
109 | ret = -ENOMEM; | ||
110 | goto out_rel_fw; | ||
111 | } | ||
108 | 112 | ||
109 | while (ptr[0] != 0xff) { | 113 | while (ptr[0] != 0xff) { |
110 | u16 buflen = ptr[0] + 4; | 114 | u16 buflen = ptr[0] + 4; |
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 737ffa36ac9c..c211fef45fc3 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = { | |||
589 | }; | 589 | }; |
590 | 590 | ||
591 | /* ir keymaps */ | 591 | /* ir keymaps */ |
592 | static struct dvb_usb_rc_key megasky_rc_keys [] = { | 592 | static struct dvb_usb_rc_key ir_codes_megasky_table [] = { |
593 | { 0x0012, KEY_POWER }, | 593 | { 0x0012, KEY_POWER }, |
594 | { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */ | 594 | { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */ |
595 | { 0x0002, KEY_CHANNELUP }, | 595 | { 0x0002, KEY_CHANNELUP }, |
@@ -608,7 +608,7 @@ static struct dvb_usb_rc_key megasky_rc_keys [] = { | |||
608 | { 0x000e, KEY_COFFEE }, /* "MTS" */ | 608 | { 0x000e, KEY_COFFEE }, /* "MTS" */ |
609 | }; | 609 | }; |
610 | 610 | ||
611 | static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { | 611 | static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = { |
612 | { 0x0001, KEY_ZOOM }, /* Full Screen */ | 612 | { 0x0001, KEY_ZOOM }, /* Full Screen */ |
613 | { 0x0002, KEY_CAMERA }, /* snapshot */ | 613 | { 0x0002, KEY_CAMERA }, /* snapshot */ |
614 | { 0x0003, KEY_MUTE }, | 614 | { 0x0003, KEY_MUTE }, |
@@ -628,7 +628,7 @@ static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { | |||
628 | { 0x001e, KEY_VOLUMEUP }, | 628 | { 0x001e, KEY_VOLUMEUP }, |
629 | }; | 629 | }; |
630 | 630 | ||
631 | static struct dvb_usb_rc_key pinnacle310e_rc_keys[] = { | 631 | static struct dvb_usb_rc_key ir_codes_pinnacle310e_table[] = { |
632 | { 0x16, KEY_POWER }, | 632 | { 0x16, KEY_POWER }, |
633 | { 0x17, KEY_FAVORITES }, | 633 | { 0x17, KEY_FAVORITES }, |
634 | { 0x0f, KEY_TEXT }, | 634 | { 0x0f, KEY_TEXT }, |
@@ -785,8 +785,8 @@ static struct dvb_usb_device_properties megasky_properties = { | |||
785 | .download_firmware = m920x_firmware_download, | 785 | .download_firmware = m920x_firmware_download, |
786 | 786 | ||
787 | .rc_interval = 100, | 787 | .rc_interval = 100, |
788 | .rc_key_map = megasky_rc_keys, | 788 | .rc_key_map = ir_codes_megasky_table, |
789 | .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), | 789 | .rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table), |
790 | .rc_query = m920x_rc_query, | 790 | .rc_query = m920x_rc_query, |
791 | 791 | ||
792 | .size_of_priv = sizeof(struct m920x_state), | 792 | .size_of_priv = sizeof(struct m920x_state), |
@@ -886,8 +886,8 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = { | |||
886 | .download_firmware = m920x_firmware_download, | 886 | .download_firmware = m920x_firmware_download, |
887 | 887 | ||
888 | .rc_interval = 100, | 888 | .rc_interval = 100, |
889 | .rc_key_map = tvwalkertwin_rc_keys, | 889 | .rc_key_map = ir_codes_tvwalkertwin_table, |
890 | .rc_key_map_size = ARRAY_SIZE(tvwalkertwin_rc_keys), | 890 | .rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table), |
891 | .rc_query = m920x_rc_query, | 891 | .rc_query = m920x_rc_query, |
892 | 892 | ||
893 | .size_of_priv = sizeof(struct m920x_state), | 893 | .size_of_priv = sizeof(struct m920x_state), |
@@ -993,8 +993,8 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { | |||
993 | .download_firmware = NULL, | 993 | .download_firmware = NULL, |
994 | 994 | ||
995 | .rc_interval = 100, | 995 | .rc_interval = 100, |
996 | .rc_key_map = pinnacle310e_rc_keys, | 996 | .rc_key_map = ir_codes_pinnacle310e_table, |
997 | .rc_key_map_size = ARRAY_SIZE(pinnacle310e_rc_keys), | 997 | .rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table), |
998 | .rc_query = m920x_rc_query, | 998 | .rc_query = m920x_rc_query, |
999 | 999 | ||
1000 | .size_of_priv = sizeof(struct m920x_state), | 1000 | .size_of_priv = sizeof(struct m920x_state), |
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index b41d66ef8325..d195a587cc65 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
@@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
21 | #define deb_ee(args...) dprintk(debug,0x02,args) | 21 | #define deb_ee(args...) dprintk(debug,0x02,args) |
22 | 22 | ||
23 | /* Hauppauge NOVA-T USB2 keys */ | 23 | /* Hauppauge NOVA-T USB2 keys */ |
24 | static struct dvb_usb_rc_key haupp_rc_keys [] = { | 24 | static struct dvb_usb_rc_key ir_codes_haupp_table [] = { |
25 | { 0x1e00, KEY_0 }, | 25 | { 0x1e00, KEY_0 }, |
26 | { 0x1e01, KEY_1 }, | 26 | { 0x1e01, KEY_1 }, |
27 | { 0x1e02, KEY_2 }, | 27 | { 0x1e02, KEY_2 }, |
@@ -91,14 +91,14 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
91 | 91 | ||
92 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); | 92 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); |
93 | 93 | ||
94 | for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) { | 94 | for (i = 0; i < ARRAY_SIZE(ir_codes_haupp_table); i++) { |
95 | if (rc5_data(&haupp_rc_keys[i]) == data && | 95 | if (rc5_data(&ir_codes_haupp_table[i]) == data && |
96 | rc5_custom(&haupp_rc_keys[i]) == custom) { | 96 | rc5_custom(&ir_codes_haupp_table[i]) == custom) { |
97 | 97 | ||
98 | deb_rc("c: %x, d: %x\n", rc5_data(&haupp_rc_keys[i]), | 98 | deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]), |
99 | rc5_custom(&haupp_rc_keys[i])); | 99 | rc5_custom(&ir_codes_haupp_table[i])); |
100 | 100 | ||
101 | *event = haupp_rc_keys[i].event; | 101 | *event = ir_codes_haupp_table[i].event; |
102 | *state = REMOTE_KEY_PRESSED; | 102 | *state = REMOTE_KEY_PRESSED; |
103 | if (st->old_toggle == toggle) { | 103 | if (st->old_toggle == toggle) { |
104 | if (st->last_repeat_count++ < 2) | 104 | if (st->last_repeat_count++ < 2) |
@@ -196,8 +196,8 @@ static struct dvb_usb_device_properties nova_t_properties = { | |||
196 | .read_mac_address = nova_t_read_mac_address, | 196 | .read_mac_address = nova_t_read_mac_address, |
197 | 197 | ||
198 | .rc_interval = 100, | 198 | .rc_interval = 100, |
199 | .rc_key_map = haupp_rc_keys, | 199 | .rc_key_map = ir_codes_haupp_table, |
200 | .rc_key_map_size = ARRAY_SIZE(haupp_rc_keys), | 200 | .rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table), |
201 | .rc_query = nova_t_rc_query, | 201 | .rc_query = nova_t_rc_query, |
202 | 202 | ||
203 | .i2c_algo = &dibusb_i2c_algo, | 203 | .i2c_algo = &dibusb_i2c_algo, |
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 830557696ae6..dfb81ff1d9a7 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c | |||
@@ -35,7 +35,7 @@ | |||
35 | struct opera1_state { | 35 | struct opera1_state { |
36 | u32 last_key_pressed; | 36 | u32 last_key_pressed; |
37 | }; | 37 | }; |
38 | struct opera_rc_keys { | 38 | struct ir_codes_opera_table { |
39 | u32 keycode; | 39 | u32 keycode; |
40 | u32 event; | 40 | u32 event; |
41 | }; | 41 | }; |
@@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) | |||
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | 333 | ||
334 | static struct dvb_usb_rc_key opera1_rc_keys[] = { | 334 | static struct dvb_usb_rc_key ir_codes_opera1_table[] = { |
335 | {0x5fa0, KEY_1}, | 335 | {0x5fa0, KEY_1}, |
336 | {0x51af, KEY_2}, | 336 | {0x51af, KEY_2}, |
337 | {0x5da2, KEY_3}, | 337 | {0x5da2, KEY_3}, |
@@ -404,12 +404,12 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) | |||
404 | 404 | ||
405 | send_key = (send_key & 0xffff) | 0x0100; | 405 | send_key = (send_key & 0xffff) | 0x0100; |
406 | 406 | ||
407 | for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) { | 407 | for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) { |
408 | if (rc5_scan(&opera1_rc_keys[i]) == (send_key & 0xffff)) { | 408 | if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) { |
409 | *state = REMOTE_KEY_PRESSED; | 409 | *state = REMOTE_KEY_PRESSED; |
410 | *event = opera1_rc_keys[i].event; | 410 | *event = ir_codes_opera1_table[i].event; |
411 | opst->last_key_pressed = | 411 | opst->last_key_pressed = |
412 | opera1_rc_keys[i].event; | 412 | ir_codes_opera1_table[i].event; |
413 | break; | 413 | break; |
414 | } | 414 | } |
415 | opst->last_key_pressed = 0; | 415 | opst->last_key_pressed = 0; |
@@ -498,8 +498,8 @@ static struct dvb_usb_device_properties opera1_properties = { | |||
498 | .power_ctrl = opera1_power_ctrl, | 498 | .power_ctrl = opera1_power_ctrl, |
499 | .i2c_algo = &opera1_i2c_algo, | 499 | .i2c_algo = &opera1_i2c_algo, |
500 | 500 | ||
501 | .rc_key_map = opera1_rc_keys, | 501 | .rc_key_map = ir_codes_opera1_table, |
502 | .rc_key_map_size = ARRAY_SIZE(opera1_rc_keys), | 502 | .rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table), |
503 | .rc_interval = 200, | 503 | .rc_interval = 200, |
504 | .rc_query = opera1_rc_query, | 504 | .rc_query = opera1_rc_query, |
505 | .read_mac_address = opera1_read_mac_address, | 505 | .read_mac_address = opera1_read_mac_address, |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index ef4e37d9c5ff..4d332451653b 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
@@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
174 | } | 174 | } |
175 | 175 | ||
176 | /* keys for the enclosed remote control */ | 176 | /* keys for the enclosed remote control */ |
177 | static struct dvb_usb_rc_key vp702x_rc_keys[] = { | 177 | static struct dvb_usb_rc_key ir_codes_vp702x_table[] = { |
178 | { 0x0001, KEY_1 }, | 178 | { 0x0001, KEY_1 }, |
179 | { 0x0002, KEY_2 }, | 179 | { 0x0002, KEY_2 }, |
180 | }; | 180 | }; |
@@ -197,10 +197,10 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++) | 200 | for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++) |
201 | if (rc5_custom(&vp702x_rc_keys[i]) == key[1]) { | 201 | if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) { |
202 | *state = REMOTE_KEY_PRESSED; | 202 | *state = REMOTE_KEY_PRESSED; |
203 | *event = vp702x_rc_keys[i].event; | 203 | *event = ir_codes_vp702x_table[i].event; |
204 | break; | 204 | break; |
205 | } | 205 | } |
206 | return 0; | 206 | return 0; |
@@ -283,8 +283,8 @@ static struct dvb_usb_device_properties vp702x_properties = { | |||
283 | }, | 283 | }, |
284 | .read_mac_address = vp702x_read_mac_addr, | 284 | .read_mac_address = vp702x_read_mac_addr, |
285 | 285 | ||
286 | .rc_key_map = vp702x_rc_keys, | 286 | .rc_key_map = ir_codes_vp702x_table, |
287 | .rc_key_map_size = ARRAY_SIZE(vp702x_rc_keys), | 287 | .rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table), |
288 | .rc_interval = 400, | 288 | .rc_interval = 400, |
289 | .rc_query = vp702x_rc_query, | 289 | .rc_query = vp702x_rc_query, |
290 | 290 | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index a59faa27912a..036893fa4480 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
99 | 99 | ||
100 | /* The keymapping struct. Somehow this should be loaded to the driver, but | 100 | /* The keymapping struct. Somehow this should be loaded to the driver, but |
101 | * currently it is hardcoded. */ | 101 | * currently it is hardcoded. */ |
102 | static struct dvb_usb_rc_key vp7045_rc_keys[] = { | 102 | static struct dvb_usb_rc_key ir_codes_vp7045_table[] = { |
103 | { 0x0016, KEY_POWER }, | 103 | { 0x0016, KEY_POWER }, |
104 | { 0x0010, KEY_MUTE }, | 104 | { 0x0010, KEY_MUTE }, |
105 | { 0x0003, KEY_1 }, | 105 | { 0x0003, KEY_1 }, |
@@ -165,10 +165,10 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
165 | return 0; | 165 | return 0; |
166 | } | 166 | } |
167 | 167 | ||
168 | for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++) | 168 | for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++) |
169 | if (rc5_data(&vp7045_rc_keys[i]) == key) { | 169 | if (rc5_data(&ir_codes_vp7045_table[i]) == key) { |
170 | *state = REMOTE_KEY_PRESSED; | 170 | *state = REMOTE_KEY_PRESSED; |
171 | *event = vp7045_rc_keys[i].event; | 171 | *event = ir_codes_vp7045_table[i].event; |
172 | break; | 172 | break; |
173 | } | 173 | } |
174 | return 0; | 174 | return 0; |
@@ -260,8 +260,8 @@ static struct dvb_usb_device_properties vp7045_properties = { | |||
260 | .read_mac_address = vp7045_read_mac_addr, | 260 | .read_mac_address = vp7045_read_mac_addr, |
261 | 261 | ||
262 | .rc_interval = 400, | 262 | .rc_interval = 400, |
263 | .rc_key_map = vp7045_rc_keys, | 263 | .rc_key_map = ir_codes_vp7045_table, |
264 | .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys), | 264 | .rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table), |
265 | .rc_query = vp7045_rc_query, | 265 | .rc_query = vp7045_rc_query, |
266 | 266 | ||
267 | .num_device_descs = 2, | 267 | .num_device_descs = 2, |
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 1b31bebc27d6..28294af752db 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c | |||
@@ -1096,7 +1096,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | |||
1096 | 1096 | ||
1097 | c->operand[15] = msg[1]; /* Program number */ | 1097 | c->operand[15] = msg[1]; /* Program number */ |
1098 | c->operand[16] = msg[2]; | 1098 | c->operand[16] = msg[2]; |
1099 | c->operand[17] = 0x01; /* Version number=0 + current/next=1 */ | 1099 | c->operand[17] = msg[3]; /* Version number and current/next */ |
1100 | c->operand[18] = 0x00; /* Section number=0 */ | 1100 | c->operand[18] = 0x00; /* Section number=0 */ |
1101 | c->operand[19] = 0x00; /* Last section number=0 */ | 1101 | c->operand[19] = 0x00; /* Last section number=0 */ |
1102 | c->operand[20] = 0x1f; /* PCR_PID=1FFF */ | 1102 | c->operand[20] = 0x1f; /* PCR_PID=1FFF */ |
diff --git a/drivers/media/dvb/frontends/atbm8830_priv.h b/drivers/media/dvb/frontends/atbm8830_priv.h index ce960f76092a..d460058d497e 100644 --- a/drivers/media/dvb/frontends/atbm8830_priv.h +++ b/drivers/media/dvb/frontends/atbm8830_priv.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef __ATBM8830_PRIV_H | 22 | #ifndef __ATBM8830_PRIV_H |
23 | #define __ATBM8830_PRIV_H | 23 | #define __ATBM8830_PRIV_H |
24 | 24 | ||
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 24268ef2753d..68dba3a4b4da 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c | |||
@@ -664,6 +664,13 @@ static int au8522_reset(struct v4l2_subdev *sd, u32 val) | |||
664 | { | 664 | { |
665 | struct au8522_state *state = to_state(sd); | 665 | struct au8522_state *state = to_state(sd); |
666 | 666 | ||
667 | state->operational_mode = AU8522_ANALOG_MODE; | ||
668 | |||
669 | /* Clear out any state associated with the digital side of the | ||
670 | chip, so that when it gets powered back up it won't think | ||
671 | that it is already tuned */ | ||
672 | state->current_frequency = 0; | ||
673 | |||
667 | au8522_writereg(state, 0xa4, 1 << 5); | 674 | au8522_writereg(state, 0xa4, 1 << 5); |
668 | 675 | ||
669 | return 0; | 676 | return 0; |
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index a1fed0fa8ed4..65f6a36dfb21 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c | |||
@@ -84,6 +84,14 @@ static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
84 | 84 | ||
85 | dprintk("%s(%d)\n", __func__, enable); | 85 | dprintk("%s(%d)\n", __func__, enable); |
86 | 86 | ||
87 | if (state->operational_mode == AU8522_ANALOG_MODE) { | ||
88 | /* We're being asked to manage the gate even though we're | ||
89 | not in digital mode. This can occur if we get switched | ||
90 | over to analog mode before the dvb_frontend kernel thread | ||
91 | has completely shutdown */ | ||
92 | return 0; | ||
93 | } | ||
94 | |||
87 | if (enable) | 95 | if (enable) |
88 | return au8522_writereg(state, 0x106, 1); | 96 | return au8522_writereg(state, 0x106, 1); |
89 | else | 97 | else |
@@ -608,6 +616,13 @@ int au8522_init(struct dvb_frontend *fe) | |||
608 | struct au8522_state *state = fe->demodulator_priv; | 616 | struct au8522_state *state = fe->demodulator_priv; |
609 | dprintk("%s()\n", __func__); | 617 | dprintk("%s()\n", __func__); |
610 | 618 | ||
619 | state->operational_mode = AU8522_DIGITAL_MODE; | ||
620 | |||
621 | /* Clear out any state associated with the digital side of the | ||
622 | chip, so that when it gets powered back up it won't think | ||
623 | that it is already tuned */ | ||
624 | state->current_frequency = 0; | ||
625 | |||
611 | au8522_writereg(state, 0xa4, 1 << 5); | 626 | au8522_writereg(state, 0xa4, 1 << 5); |
612 | 627 | ||
613 | au8522_i2c_gate_ctrl(fe, 1); | 628 | au8522_i2c_gate_ctrl(fe, 1); |
@@ -704,6 +719,15 @@ int au8522_sleep(struct dvb_frontend *fe) | |||
704 | struct au8522_state *state = fe->demodulator_priv; | 719 | struct au8522_state *state = fe->demodulator_priv; |
705 | dprintk("%s()\n", __func__); | 720 | dprintk("%s()\n", __func__); |
706 | 721 | ||
722 | /* Only power down if the digital side is currently using the chip */ | ||
723 | if (state->operational_mode == AU8522_ANALOG_MODE) { | ||
724 | /* We're not in one of the expected power modes, which means | ||
725 | that the DVB thread is probably telling us to go to sleep | ||
726 | even though the analog frontend has already started using | ||
727 | the chip. So ignore the request */ | ||
728 | return 0; | ||
729 | } | ||
730 | |||
707 | /* turn off led */ | 731 | /* turn off led */ |
708 | au8522_led_ctrl(state, 0); | 732 | au8522_led_ctrl(state, 0); |
709 | 733 | ||
@@ -932,6 +956,8 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, | |||
932 | /* setup the state */ | 956 | /* setup the state */ |
933 | state->config = config; | 957 | state->config = config; |
934 | state->i2c = i2c; | 958 | state->i2c = i2c; |
959 | state->operational_mode = AU8522_DIGITAL_MODE; | ||
960 | |||
935 | /* create dvb_frontend */ | 961 | /* create dvb_frontend */ |
936 | memcpy(&state->frontend.ops, &au8522_ops, | 962 | memcpy(&state->frontend.ops, &au8522_ops, |
937 | sizeof(struct dvb_frontend_ops)); | 963 | sizeof(struct dvb_frontend_ops)); |
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h index c74c4e72fe91..609cf04bc312 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb/frontends/au8522_priv.h | |||
@@ -34,10 +34,15 @@ | |||
34 | #include "au8522.h" | 34 | #include "au8522.h" |
35 | #include "tuner-i2c.h" | 35 | #include "tuner-i2c.h" |
36 | 36 | ||
37 | #define AU8522_ANALOG_MODE 0 | ||
38 | #define AU8522_DIGITAL_MODE 1 | ||
39 | |||
37 | struct au8522_state { | 40 | struct au8522_state { |
38 | struct i2c_client *c; | 41 | struct i2c_client *c; |
39 | struct i2c_adapter *i2c; | 42 | struct i2c_adapter *i2c; |
40 | 43 | ||
44 | u8 operational_mode; | ||
45 | |||
41 | /* Used for sharing of the state between analog and digital mode */ | 46 | /* Used for sharing of the state between analog and digital mode */ |
42 | struct tuner_i2c_props i2c_props; | 47 | struct tuner_i2c_props i2c_props; |
43 | struct list_head hybrid_tuner_instance_list; | 48 | struct list_head hybrid_tuner_instance_list; |
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 40a099810279..afad252abf41 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c | |||
@@ -814,42 +814,51 @@ EXPORT_SYMBOL(dib3000mc_set_config); | |||
814 | 814 | ||
815 | int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]) | 815 | int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]) |
816 | { | 816 | { |
817 | struct dib3000mc_state st = { .i2c_adap = i2c }; | 817 | struct dib3000mc_state *dmcst; |
818 | int k; | 818 | int k; |
819 | u8 new_addr; | 819 | u8 new_addr; |
820 | 820 | ||
821 | static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26}; | 821 | static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26}; |
822 | 822 | ||
823 | dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL); | ||
824 | if (dmcst == NULL) | ||
825 | return -ENODEV; | ||
826 | |||
827 | dmcst->i2c_adap = i2c; | ||
828 | |||
823 | for (k = no_of_demods-1; k >= 0; k--) { | 829 | for (k = no_of_demods-1; k >= 0; k--) { |
824 | st.cfg = &cfg[k]; | 830 | dmcst->cfg = &cfg[k]; |
825 | 831 | ||
826 | /* designated i2c address */ | 832 | /* designated i2c address */ |
827 | new_addr = DIB3000MC_I2C_ADDRESS[k]; | 833 | new_addr = DIB3000MC_I2C_ADDRESS[k]; |
828 | st.i2c_addr = new_addr; | 834 | dmcst->i2c_addr = new_addr; |
829 | if (dib3000mc_identify(&st) != 0) { | 835 | if (dib3000mc_identify(dmcst) != 0) { |
830 | st.i2c_addr = default_addr; | 836 | dmcst->i2c_addr = default_addr; |
831 | if (dib3000mc_identify(&st) != 0) { | 837 | if (dib3000mc_identify(dmcst) != 0) { |
832 | dprintk("-E- DiB3000P/MC #%d: not identified\n", k); | 838 | dprintk("-E- DiB3000P/MC #%d: not identified\n", k); |
839 | kfree(dmcst); | ||
833 | return -ENODEV; | 840 | return -ENODEV; |
834 | } | 841 | } |
835 | } | 842 | } |
836 | 843 | ||
837 | dib3000mc_set_output_mode(&st, OUTMODE_MPEG2_PAR_CONT_CLK); | 844 | dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK); |
838 | 845 | ||
839 | // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0) | 846 | // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0) |
840 | dib3000mc_write_word(&st, 1024, (new_addr << 3) | 0x1); | 847 | dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1); |
841 | st.i2c_addr = new_addr; | 848 | dmcst->i2c_addr = new_addr; |
842 | } | 849 | } |
843 | 850 | ||
844 | for (k = 0; k < no_of_demods; k++) { | 851 | for (k = 0; k < no_of_demods; k++) { |
845 | st.cfg = &cfg[k]; | 852 | dmcst->cfg = &cfg[k]; |
846 | st.i2c_addr = DIB3000MC_I2C_ADDRESS[k]; | 853 | dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k]; |
847 | 854 | ||
848 | dib3000mc_write_word(&st, 1024, st.i2c_addr << 3); | 855 | dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3); |
849 | 856 | ||
850 | /* turn off data output */ | 857 | /* turn off data output */ |
851 | dib3000mc_set_output_mode(&st, OUTMODE_HIGH_Z); | 858 | dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z); |
852 | } | 859 | } |
860 | |||
861 | kfree(dmcst); | ||
853 | return 0; | 862 | return 0; |
854 | } | 863 | } |
855 | EXPORT_SYMBOL(dib3000mc_i2c_enumeration); | 864 | EXPORT_SYMBOL(dib3000mc_i2c_enumeration); |
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 85468a45c344..2e28b973dfd3 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
@@ -1324,46 +1324,54 @@ EXPORT_SYMBOL(dib7000p_pid_filter); | |||
1324 | 1324 | ||
1325 | int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) | 1325 | int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) |
1326 | { | 1326 | { |
1327 | struct dib7000p_state st = { .i2c_adap = i2c }; | 1327 | struct dib7000p_state *dpst; |
1328 | int k = 0; | 1328 | int k = 0; |
1329 | u8 new_addr = 0; | 1329 | u8 new_addr = 0; |
1330 | 1330 | ||
1331 | dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); | ||
1332 | if (!dpst) | ||
1333 | return -ENOMEM; | ||
1334 | |||
1335 | dpst->i2c_adap = i2c; | ||
1336 | |||
1331 | for (k = no_of_demods-1; k >= 0; k--) { | 1337 | for (k = no_of_demods-1; k >= 0; k--) { |
1332 | st.cfg = cfg[k]; | 1338 | dpst->cfg = cfg[k]; |
1333 | 1339 | ||
1334 | /* designated i2c address */ | 1340 | /* designated i2c address */ |
1335 | new_addr = (0x40 + k) << 1; | 1341 | new_addr = (0x40 + k) << 1; |
1336 | st.i2c_addr = new_addr; | 1342 | dpst->i2c_addr = new_addr; |
1337 | dib7000p_write_word(&st, 1287, 0x0003); /* sram lead in, rdy */ | 1343 | dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */ |
1338 | if (dib7000p_identify(&st) != 0) { | 1344 | if (dib7000p_identify(dpst) != 0) { |
1339 | st.i2c_addr = default_addr; | 1345 | dpst->i2c_addr = default_addr; |
1340 | dib7000p_write_word(&st, 1287, 0x0003); /* sram lead in, rdy */ | 1346 | dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */ |
1341 | if (dib7000p_identify(&st) != 0) { | 1347 | if (dib7000p_identify(dpst) != 0) { |
1342 | dprintk("DiB7000P #%d: not identified\n", k); | 1348 | dprintk("DiB7000P #%d: not identified\n", k); |
1349 | kfree(dpst); | ||
1343 | return -EIO; | 1350 | return -EIO; |
1344 | } | 1351 | } |
1345 | } | 1352 | } |
1346 | 1353 | ||
1347 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | 1354 | /* start diversity to pull_down div_str - just for i2c-enumeration */ |
1348 | dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); | 1355 | dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY); |
1349 | 1356 | ||
1350 | /* set new i2c address and force divstart */ | 1357 | /* set new i2c address and force divstart */ |
1351 | dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); | 1358 | dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2); |
1352 | 1359 | ||
1353 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); | 1360 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); |
1354 | } | 1361 | } |
1355 | 1362 | ||
1356 | for (k = 0; k < no_of_demods; k++) { | 1363 | for (k = 0; k < no_of_demods; k++) { |
1357 | st.cfg = cfg[k]; | 1364 | dpst->cfg = cfg[k]; |
1358 | st.i2c_addr = (0x40 + k) << 1; | 1365 | dpst->i2c_addr = (0x40 + k) << 1; |
1359 | 1366 | ||
1360 | // unforce divstr | 1367 | // unforce divstr |
1361 | dib7000p_write_word(&st, 1285, st.i2c_addr << 2); | 1368 | dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2); |
1362 | 1369 | ||
1363 | /* deactivate div - it was just for i2c-enumeration */ | 1370 | /* deactivate div - it was just for i2c-enumeration */ |
1364 | dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); | 1371 | dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z); |
1365 | } | 1372 | } |
1366 | 1373 | ||
1374 | kfree(dpst); | ||
1367 | return 0; | 1375 | return 0; |
1368 | } | 1376 | } |
1369 | EXPORT_SYMBOL(dib7000p_i2c_enumeration); | 1377 | EXPORT_SYMBOL(dib7000p_i2c_enumeration); |
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index b1ee20799639..e0a9ded11df4 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h | |||
@@ -109,6 +109,7 @@ static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | |||
109 | static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) | 109 | static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) |
110 | { | 110 | { |
111 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 111 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
112 | return 0; | ||
112 | } | 113 | } |
113 | #endif | 114 | #endif |
114 | 115 | ||
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c index cff3535566fe..78001e8bcdb7 100644 --- a/drivers/media/dvb/frontends/ds3000.c +++ b/drivers/media/dvb/frontends/ds3000.c | |||
@@ -719,7 +719,7 @@ static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
719 | (ds3000_readreg(state, 0x8d) << 4); | 719 | (ds3000_readreg(state, 0x8d) << 4); |
720 | dvbs2_signal_reading = ds3000_readreg(state, 0x8e); | 720 | dvbs2_signal_reading = ds3000_readreg(state, 0x8e); |
721 | tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1; | 721 | tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1; |
722 | if (dvbs2_signal_reading == 0) { | 722 | if (tmp == 0) { |
723 | *snr = 0x0000; | 723 | *snr = 0x0000; |
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 01f8f1f802fd..4f5e7d3a0e61 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c | |||
@@ -1583,7 +1583,7 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, | |||
1583 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1583 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1584 | 1584 | ||
1585 | struct stv0900_search_params p_search; | 1585 | struct stv0900_search_params p_search; |
1586 | struct stv0900_signal_info p_result; | 1586 | struct stv0900_signal_info p_result = intp->result[demod]; |
1587 | 1587 | ||
1588 | enum fe_stv0900_error error = STV0900_NO_ERROR; | 1588 | enum fe_stv0900_error error = STV0900_NO_ERROR; |
1589 | 1589 | ||
@@ -1842,6 +1842,19 @@ static void stv0900_release(struct dvb_frontend *fe) | |||
1842 | kfree(state); | 1842 | kfree(state); |
1843 | } | 1843 | } |
1844 | 1844 | ||
1845 | static int stv0900_get_frontend(struct dvb_frontend *fe, | ||
1846 | struct dvb_frontend_parameters *p) | ||
1847 | { | ||
1848 | struct stv0900_state *state = fe->demodulator_priv; | ||
1849 | struct stv0900_internal *intp = state->internal; | ||
1850 | enum fe_stv0900_demod_num demod = state->demod; | ||
1851 | struct stv0900_signal_info p_result = intp->result[demod]; | ||
1852 | |||
1853 | p->frequency = p_result.locked ? p_result.frequency : 0; | ||
1854 | p->u.qpsk.symbol_rate = p_result.locked ? p_result.symbol_rate : 0; | ||
1855 | return 0; | ||
1856 | } | ||
1857 | |||
1845 | static struct dvb_frontend_ops stv0900_ops = { | 1858 | static struct dvb_frontend_ops stv0900_ops = { |
1846 | 1859 | ||
1847 | .info = { | 1860 | .info = { |
@@ -1862,6 +1875,7 @@ static struct dvb_frontend_ops stv0900_ops = { | |||
1862 | }, | 1875 | }, |
1863 | .release = stv0900_release, | 1876 | .release = stv0900_release, |
1864 | .init = stv0900_init, | 1877 | .init = stv0900_init, |
1878 | .get_frontend = stv0900_get_frontend, | ||
1865 | .get_frontend_algo = stv0900_frontend_algo, | 1879 | .get_frontend_algo = stv0900_frontend_algo, |
1866 | .i2c_gate_ctrl = stv0900_i2c_gate_ctrl, | 1880 | .i2c_gate_ctrl = stv0900_i2c_gate_ctrl, |
1867 | .diseqc_send_master_cmd = stv0900_send_master_cmd, | 1881 | .diseqc_send_master_cmd = stv0900_send_master_cmd, |
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 96972804f4ad..425e7a43ae19 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c | |||
@@ -754,11 +754,19 @@ static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 d | |||
754 | return stv090x_write_regs(state, reg, &data, 1); | 754 | return stv090x_write_regs(state, reg, &data, 1); |
755 | } | 755 | } |
756 | 756 | ||
757 | static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | 757 | static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) |
758 | { | 758 | { |
759 | struct stv090x_state *state = fe->demodulator_priv; | ||
760 | u32 reg; | 759 | u32 reg; |
761 | 760 | ||
761 | /* | ||
762 | * NOTE! A lock is used as a FSM to control the state in which | ||
763 | * access is serialized between two tuners on the same demod. | ||
764 | * This has nothing to do with a lock to protect a critical section | ||
765 | * which may in some other cases be confused with protecting I/O | ||
766 | * access to the demodulator gate. | ||
767 | * In case of any error, the lock is unlocked and exit within the | ||
768 | * relevant operations themselves. | ||
769 | */ | ||
762 | if (enable) | 770 | if (enable) |
763 | mutex_lock(&state->internal->tuner_lock); | 771 | mutex_lock(&state->internal->tuner_lock); |
764 | 772 | ||
@@ -1778,7 +1786,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1778 | freq -= cur_step * car_step; | 1786 | freq -= cur_step * car_step; |
1779 | 1787 | ||
1780 | /* Setup tuner */ | 1788 | /* Setup tuner */ |
1781 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 1789 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
1782 | goto err; | 1790 | goto err; |
1783 | 1791 | ||
1784 | if (state->config->tuner_set_frequency) { | 1792 | if (state->config->tuner_set_frequency) { |
@@ -1791,12 +1799,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1791 | goto err_gateoff; | 1799 | goto err_gateoff; |
1792 | } | 1800 | } |
1793 | 1801 | ||
1794 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 1802 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
1795 | goto err; | 1803 | goto err; |
1796 | 1804 | ||
1797 | msleep(50); | 1805 | msleep(50); |
1798 | 1806 | ||
1799 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 1807 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
1800 | goto err; | 1808 | goto err; |
1801 | 1809 | ||
1802 | if (state->config->tuner_get_status) { | 1810 | if (state->config->tuner_get_status) { |
@@ -1809,7 +1817,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1809 | else | 1817 | else |
1810 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); | 1818 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); |
1811 | 1819 | ||
1812 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 1820 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
1813 | goto err; | 1821 | goto err; |
1814 | 1822 | ||
1815 | } | 1823 | } |
@@ -1822,7 +1830,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1822 | return srate_coarse; | 1830 | return srate_coarse; |
1823 | 1831 | ||
1824 | err_gateoff: | 1832 | err_gateoff: |
1825 | stv090x_i2c_gate_ctrl(fe, 0); | 1833 | stv090x_i2c_gate_ctrl(state, 0); |
1826 | err: | 1834 | err: |
1827 | dprintk(FE_ERROR, 1, "I/O error"); | 1835 | dprintk(FE_ERROR, 1, "I/O error"); |
1828 | return -1; | 1836 | return -1; |
@@ -2167,7 +2175,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2167 | freq -= cur_step * car_step; | 2175 | freq -= cur_step * car_step; |
2168 | 2176 | ||
2169 | /* Setup tuner */ | 2177 | /* Setup tuner */ |
2170 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 2178 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
2171 | goto err; | 2179 | goto err; |
2172 | 2180 | ||
2173 | if (state->config->tuner_set_frequency) { | 2181 | if (state->config->tuner_set_frequency) { |
@@ -2180,12 +2188,12 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2180 | goto err_gateoff; | 2188 | goto err_gateoff; |
2181 | } | 2189 | } |
2182 | 2190 | ||
2183 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2191 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
2184 | goto err; | 2192 | goto err; |
2185 | 2193 | ||
2186 | msleep(50); | 2194 | msleep(50); |
2187 | 2195 | ||
2188 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 2196 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
2189 | goto err; | 2197 | goto err; |
2190 | 2198 | ||
2191 | if (state->config->tuner_get_status) { | 2199 | if (state->config->tuner_get_status) { |
@@ -2198,7 +2206,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2198 | else | 2206 | else |
2199 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); | 2207 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); |
2200 | 2208 | ||
2201 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2209 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
2202 | goto err; | 2210 | goto err; |
2203 | 2211 | ||
2204 | STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); | 2212 | STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); |
@@ -2222,7 +2230,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2222 | return lock; | 2230 | return lock; |
2223 | 2231 | ||
2224 | err_gateoff: | 2232 | err_gateoff: |
2225 | stv090x_i2c_gate_ctrl(fe, 0); | 2233 | stv090x_i2c_gate_ctrl(state, 0); |
2226 | err: | 2234 | err: |
2227 | dprintk(FE_ERROR, 1, "I/O error"); | 2235 | dprintk(FE_ERROR, 1, "I/O error"); |
2228 | return -1; | 2236 | return -1; |
@@ -2591,7 +2599,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2591 | } | 2599 | } |
2592 | state->delsys = stv090x_get_std(state); | 2600 | state->delsys = stv090x_get_std(state); |
2593 | 2601 | ||
2594 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 2602 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
2595 | goto err; | 2603 | goto err; |
2596 | 2604 | ||
2597 | if (state->config->tuner_get_frequency) { | 2605 | if (state->config->tuner_get_frequency) { |
@@ -2599,7 +2607,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2599 | goto err_gateoff; | 2607 | goto err_gateoff; |
2600 | } | 2608 | } |
2601 | 2609 | ||
2602 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2610 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
2603 | goto err; | 2611 | goto err; |
2604 | 2612 | ||
2605 | offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000; | 2613 | offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000; |
@@ -2619,7 +2627,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2619 | 2627 | ||
2620 | if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { | 2628 | if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { |
2621 | 2629 | ||
2622 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 2630 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
2623 | goto err; | 2631 | goto err; |
2624 | 2632 | ||
2625 | if (state->config->tuner_get_frequency) { | 2633 | if (state->config->tuner_get_frequency) { |
@@ -2627,7 +2635,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2627 | goto err_gateoff; | 2635 | goto err_gateoff; |
2628 | } | 2636 | } |
2629 | 2637 | ||
2630 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2638 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
2631 | goto err; | 2639 | goto err; |
2632 | 2640 | ||
2633 | if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) | 2641 | if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) |
@@ -2646,7 +2654,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2646 | return STV090x_OUTOFRANGE; | 2654 | return STV090x_OUTOFRANGE; |
2647 | 2655 | ||
2648 | err_gateoff: | 2656 | err_gateoff: |
2649 | stv090x_i2c_gate_ctrl(fe, 0); | 2657 | stv090x_i2c_gate_ctrl(state, 0); |
2650 | err: | 2658 | err: |
2651 | dprintk(FE_ERROR, 1, "I/O error"); | 2659 | dprintk(FE_ERROR, 1, "I/O error"); |
2652 | return -1; | 2660 | return -1; |
@@ -3000,7 +3008,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
3000 | 3008 | ||
3001 | if (state->algo != STV090x_WARM_SEARCH) { | 3009 | if (state->algo != STV090x_WARM_SEARCH) { |
3002 | 3010 | ||
3003 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 3011 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
3004 | goto err; | 3012 | goto err; |
3005 | 3013 | ||
3006 | if (state->config->tuner_set_bandwidth) { | 3014 | if (state->config->tuner_set_bandwidth) { |
@@ -3008,7 +3016,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
3008 | goto err_gateoff; | 3016 | goto err_gateoff; |
3009 | } | 3017 | } |
3010 | 3018 | ||
3011 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3019 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
3012 | goto err; | 3020 | goto err; |
3013 | 3021 | ||
3014 | } | 3022 | } |
@@ -3059,7 +3067,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
3059 | return 0; | 3067 | return 0; |
3060 | 3068 | ||
3061 | err_gateoff: | 3069 | err_gateoff: |
3062 | stv090x_i2c_gate_ctrl(fe, 0); | 3070 | stv090x_i2c_gate_ctrl(state, 0); |
3063 | err: | 3071 | err: |
3064 | dprintk(FE_ERROR, 1, "I/O error"); | 3072 | dprintk(FE_ERROR, 1, "I/O error"); |
3065 | return -1; | 3073 | return -1; |
@@ -3235,7 +3243,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3235 | } | 3243 | } |
3236 | 3244 | ||
3237 | /* Setup tuner */ | 3245 | /* Setup tuner */ |
3238 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 3246 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
3239 | goto err; | 3247 | goto err; |
3240 | 3248 | ||
3241 | if (state->config->tuner_set_bbgain) { | 3249 | if (state->config->tuner_set_bbgain) { |
@@ -3256,17 +3264,17 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3256 | goto err_gateoff; | 3264 | goto err_gateoff; |
3257 | } | 3265 | } |
3258 | 3266 | ||
3259 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3267 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
3260 | goto err; | 3268 | goto err; |
3261 | 3269 | ||
3262 | msleep(50); | 3270 | msleep(50); |
3263 | 3271 | ||
3264 | if (state->config->tuner_get_status) { | 3272 | if (state->config->tuner_get_status) { |
3265 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 3273 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
3266 | goto err; | 3274 | goto err; |
3267 | if (state->config->tuner_get_status(fe, ®) < 0) | 3275 | if (state->config->tuner_get_status(fe, ®) < 0) |
3268 | goto err_gateoff; | 3276 | goto err_gateoff; |
3269 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3277 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
3270 | goto err; | 3278 | goto err; |
3271 | 3279 | ||
3272 | if (reg) | 3280 | if (reg) |
@@ -3400,7 +3408,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3400 | return signal_state; | 3408 | return signal_state; |
3401 | 3409 | ||
3402 | err_gateoff: | 3410 | err_gateoff: |
3403 | stv090x_i2c_gate_ctrl(fe, 0); | 3411 | stv090x_i2c_gate_ctrl(state, 0); |
3404 | err: | 3412 | err: |
3405 | dprintk(FE_ERROR, 1, "I/O error"); | 3413 | dprintk(FE_ERROR, 1, "I/O error"); |
3406 | return -1; | 3414 | return -1; |
@@ -3839,6 +3847,17 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3839 | struct stv090x_state *state = fe->demodulator_priv; | 3847 | struct stv090x_state *state = fe->demodulator_priv; |
3840 | u32 reg; | 3848 | u32 reg; |
3841 | 3849 | ||
3850 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) | ||
3851 | goto err; | ||
3852 | |||
3853 | if (state->config->tuner_sleep) { | ||
3854 | if (state->config->tuner_sleep(fe) < 0) | ||
3855 | goto err_gateoff; | ||
3856 | } | ||
3857 | |||
3858 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) | ||
3859 | goto err; | ||
3860 | |||
3842 | dprintk(FE_DEBUG, 1, "Set %s to sleep", | 3861 | dprintk(FE_DEBUG, 1, "Set %s to sleep", |
3843 | state->device == STV0900 ? "STV0900" : "STV0903"); | 3862 | state->device == STV0900 ? "STV0900" : "STV0903"); |
3844 | 3863 | ||
@@ -3853,6 +3872,9 @@ static int stv090x_sleep(struct dvb_frontend *fe) | |||
3853 | goto err; | 3872 | goto err; |
3854 | 3873 | ||
3855 | return 0; | 3874 | return 0; |
3875 | |||
3876 | err_gateoff: | ||
3877 | stv090x_i2c_gate_ctrl(state, 0); | ||
3856 | err: | 3878 | err: |
3857 | dprintk(FE_ERROR, 1, "I/O error"); | 3879 | dprintk(FE_ERROR, 1, "I/O error"); |
3858 | return -1; | 3880 | return -1; |
@@ -4311,6 +4333,20 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4311 | u32 reg; | 4333 | u32 reg; |
4312 | 4334 | ||
4313 | if (state->internal->mclk == 0) { | 4335 | if (state->internal->mclk == 0) { |
4336 | /* call tuner init to configure the tuner's clock output | ||
4337 | divider directly before setting up the master clock of | ||
4338 | the stv090x. */ | ||
4339 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) | ||
4340 | goto err; | ||
4341 | |||
4342 | if (config->tuner_init) { | ||
4343 | if (config->tuner_init(fe) < 0) | ||
4344 | goto err_gateoff; | ||
4345 | } | ||
4346 | |||
4347 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) | ||
4348 | goto err; | ||
4349 | |||
4314 | stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ | 4350 | stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ |
4315 | msleep(5); | 4351 | msleep(5); |
4316 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, | 4352 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, |
@@ -4336,7 +4372,7 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4336 | if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) | 4372 | if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) |
4337 | goto err; | 4373 | goto err; |
4338 | 4374 | ||
4339 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | 4375 | if (stv090x_i2c_gate_ctrl(state, 1) < 0) |
4340 | goto err; | 4376 | goto err; |
4341 | 4377 | ||
4342 | if (config->tuner_set_mode) { | 4378 | if (config->tuner_set_mode) { |
@@ -4349,7 +4385,7 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4349 | goto err_gateoff; | 4385 | goto err_gateoff; |
4350 | } | 4386 | } |
4351 | 4387 | ||
4352 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 4388 | if (stv090x_i2c_gate_ctrl(state, 0) < 0) |
4353 | goto err; | 4389 | goto err; |
4354 | 4390 | ||
4355 | if (stv090x_set_tspath(state) < 0) | 4391 | if (stv090x_set_tspath(state) < 0) |
@@ -4358,7 +4394,7 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4358 | return 0; | 4394 | return 0; |
4359 | 4395 | ||
4360 | err_gateoff: | 4396 | err_gateoff: |
4361 | stv090x_i2c_gate_ctrl(fe, 0); | 4397 | stv090x_i2c_gate_ctrl(state, 0); |
4362 | err: | 4398 | err: |
4363 | dprintk(FE_ERROR, 1, "I/O error"); | 4399 | dprintk(FE_ERROR, 1, "I/O error"); |
4364 | return -1; | 4400 | return -1; |
@@ -4503,8 +4539,6 @@ static struct dvb_frontend_ops stv090x_ops = { | |||
4503 | .sleep = stv090x_sleep, | 4539 | .sleep = stv090x_sleep, |
4504 | .get_frontend_algo = stv090x_frontend_algo, | 4540 | .get_frontend_algo = stv090x_frontend_algo, |
4505 | 4541 | ||
4506 | .i2c_gate_ctrl = stv090x_i2c_gate_ctrl, | ||
4507 | |||
4508 | .diseqc_send_master_cmd = stv090x_send_diseqc_msg, | 4542 | .diseqc_send_master_cmd = stv090x_send_diseqc_msg, |
4509 | .diseqc_send_burst = stv090x_send_diseqc_burst, | 4543 | .diseqc_send_burst = stv090x_send_diseqc_burst, |
4510 | .diseqc_recv_slave_reply = stv090x_recv_slave_reply, | 4544 | .diseqc_recv_slave_reply = stv090x_recv_slave_reply, |
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index 30f01a6902ac..dd1b93ae4e9d 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h | |||
@@ -87,6 +87,7 @@ struct stv090x_config { | |||
87 | bool diseqc_envelope_mode; | 87 | bool diseqc_envelope_mode; |
88 | 88 | ||
89 | int (*tuner_init) (struct dvb_frontend *fe); | 89 | int (*tuner_init) (struct dvb_frontend *fe); |
90 | int (*tuner_sleep) (struct dvb_frontend *fe); | ||
90 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); | 91 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); |
91 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); | 92 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); |
92 | int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); | 93 | int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); |
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index dea4245f077c..42591ce1aaad 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c | |||
@@ -338,14 +338,12 @@ static struct dvb_tuner_ops stv6110x_ops = { | |||
338 | .frequency_max = 2150000, | 338 | .frequency_max = 2150000, |
339 | .frequency_step = 0, | 339 | .frequency_step = 0, |
340 | }, | 340 | }, |
341 | |||
342 | .init = stv6110x_init, | ||
343 | .sleep = stv6110x_sleep, | ||
344 | .release = stv6110x_release | 341 | .release = stv6110x_release |
345 | }; | 342 | }; |
346 | 343 | ||
347 | static struct stv6110x_devctl stv6110x_ctl = { | 344 | static struct stv6110x_devctl stv6110x_ctl = { |
348 | .tuner_init = stv6110x_init, | 345 | .tuner_init = stv6110x_init, |
346 | .tuner_sleep = stv6110x_sleep, | ||
349 | .tuner_set_mode = stv6110x_set_mode, | 347 | .tuner_set_mode = stv6110x_set_mode, |
350 | .tuner_set_frequency = stv6110x_set_frequency, | 348 | .tuner_set_frequency = stv6110x_set_frequency, |
351 | .tuner_get_frequency = stv6110x_get_frequency, | 349 | .tuner_get_frequency = stv6110x_get_frequency, |
@@ -363,11 +361,10 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, | |||
363 | { | 361 | { |
364 | struct stv6110x_state *stv6110x; | 362 | struct stv6110x_state *stv6110x; |
365 | u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; | 363 | u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; |
366 | int ret; | ||
367 | 364 | ||
368 | stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); | 365 | stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); |
369 | if (stv6110x == NULL) | 366 | if (!stv6110x) |
370 | goto error; | 367 | return NULL; |
371 | 368 | ||
372 | stv6110x->i2c = i2c; | 369 | stv6110x->i2c = i2c; |
373 | stv6110x->config = config; | 370 | stv6110x->config = config; |
@@ -392,34 +389,11 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, | |||
392 | break; | 389 | break; |
393 | } | 390 | } |
394 | 391 | ||
395 | if (fe->ops.i2c_gate_ctrl) { | ||
396 | ret = fe->ops.i2c_gate_ctrl(fe, 1); | ||
397 | if (ret < 0) | ||
398 | goto error; | ||
399 | } | ||
400 | |||
401 | ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, | ||
402 | ARRAY_SIZE(stv6110x->regs)); | ||
403 | if (ret < 0) { | ||
404 | dprintk(FE_ERROR, 1, "Initialization failed"); | ||
405 | goto error; | ||
406 | } | ||
407 | |||
408 | if (fe->ops.i2c_gate_ctrl) { | ||
409 | ret = fe->ops.i2c_gate_ctrl(fe, 0); | ||
410 | if (ret < 0) | ||
411 | goto error; | ||
412 | } | ||
413 | |||
414 | fe->tuner_priv = stv6110x; | 392 | fe->tuner_priv = stv6110x; |
415 | fe->ops.tuner_ops = stv6110x_ops; | 393 | fe->ops.tuner_ops = stv6110x_ops; |
416 | 394 | ||
417 | printk("%s: Attaching STV6110x \n", __func__); | 395 | printk(KERN_INFO "%s: Attaching STV6110x\n", __func__); |
418 | return stv6110x->devctl; | 396 | return stv6110x->devctl; |
419 | |||
420 | error: | ||
421 | kfree(stv6110x); | ||
422 | return NULL; | ||
423 | } | 397 | } |
424 | EXPORT_SYMBOL(stv6110x_attach); | 398 | EXPORT_SYMBOL(stv6110x_attach); |
425 | 399 | ||
diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h index 2429ae6d7847..47516753929a 100644 --- a/drivers/media/dvb/frontends/stv6110x.h +++ b/drivers/media/dvb/frontends/stv6110x.h | |||
@@ -40,6 +40,7 @@ enum tuner_status { | |||
40 | 40 | ||
41 | struct stv6110x_devctl { | 41 | struct stv6110x_devctl { |
42 | int (*tuner_init) (struct dvb_frontend *fe); | 42 | int (*tuner_init) (struct dvb_frontend *fe); |
43 | int (*tuner_sleep) (struct dvb_frontend *fe); | ||
43 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); | 44 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); |
44 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); | 45 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); |
45 | int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); | 46 | int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); |
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 4675a3b53c7d..3d4e4663220c 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "mantis_reg.h" | 32 | #include "mantis_reg.h" |
33 | #include "mantis_uart.h" | 33 | #include "mantis_uart.h" |
34 | 34 | ||
35 | #define MODULE_NAME "mantis_core" | ||
36 | |||
35 | static struct ir_scancode mantis_ir_table[] = { | 37 | static struct ir_scancode mantis_ir_table[] = { |
36 | { 0x29, KEY_POWER }, | 38 | { 0x29, KEY_POWER }, |
37 | { 0x28, KEY_FAVORITES }, | 39 | { 0x28, KEY_FAVORITES }, |
@@ -126,7 +128,7 @@ int mantis_input_init(struct mantis_pci *mantis) | |||
126 | rc->id.version = 1; | 128 | rc->id.version = 1; |
127 | rc->dev = mantis->pdev->dev; | 129 | rc->dev = mantis->pdev->dev; |
128 | 130 | ||
129 | err = ir_input_register(rc, &ir_mantis, NULL); | 131 | err = __ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME); |
130 | if (err) { | 132 | if (err) { |
131 | dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); | 133 | dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); |
132 | input_free_device(rc); | 134 | input_free_device(rc); |
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 515346dd31d0..d1aa2bc0c155 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c | |||
@@ -136,12 +136,12 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { | |||
136 | { STB0899_RCOMPC , 0xc9 }, | 136 | { STB0899_RCOMPC , 0xc9 }, |
137 | { STB0899_AGC1CN , 0x01 }, | 137 | { STB0899_AGC1CN , 0x01 }, |
138 | { STB0899_AGC1REF , 0x10 }, | 138 | { STB0899_AGC1REF , 0x10 }, |
139 | { STB0899_RTC , 0x23 }, | 139 | { STB0899_RTC , 0x23 }, |
140 | { STB0899_TMGCFG , 0x4e }, | 140 | { STB0899_TMGCFG , 0x4e }, |
141 | { STB0899_AGC2REF , 0x34 }, | 141 | { STB0899_AGC2REF , 0x34 }, |
142 | { STB0899_TLSR , 0x84 }, | 142 | { STB0899_TLSR , 0x84 }, |
143 | { STB0899_CFD , 0xf7 }, | 143 | { STB0899_CFD , 0xf7 }, |
144 | { STB0899_ACLC , 0x87 }, | 144 | { STB0899_ACLC , 0x87 }, |
145 | { STB0899_BCLC , 0x94 }, | 145 | { STB0899_BCLC , 0x94 }, |
146 | { STB0899_EQON , 0x41 }, | 146 | { STB0899_EQON , 0x41 }, |
147 | { STB0899_LDT , 0xf1 }, | 147 | { STB0899_LDT , 0xf1 }, |
@@ -194,10 +194,10 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { | |||
194 | { STB0899_ECNT3M , 0x0a }, | 194 | { STB0899_ECNT3M , 0x0a }, |
195 | { STB0899_ECNT3L , 0xad }, | 195 | { STB0899_ECNT3L , 0xad }, |
196 | { STB0899_FECAUTO1 , 0x06 }, | 196 | { STB0899_FECAUTO1 , 0x06 }, |
197 | { STB0899_FECM , 0x01 }, | 197 | { STB0899_FECM , 0x01 }, |
198 | { STB0899_VTH12 , 0xb0 }, | 198 | { STB0899_VTH12 , 0xb0 }, |
199 | { STB0899_VTH23 , 0x7a }, | 199 | { STB0899_VTH23 , 0x7a }, |
200 | { STB0899_VTH34 , 0x58 }, | 200 | { STB0899_VTH34 , 0x58 }, |
201 | { STB0899_VTH56 , 0x38 }, | 201 | { STB0899_VTH56 , 0x38 }, |
202 | { STB0899_VTH67 , 0x34 }, | 202 | { STB0899_VTH67 , 0x34 }, |
203 | { STB0899_VTH78 , 0x24 }, | 203 | { STB0899_VTH78 , 0x24 }, |
@@ -206,7 +206,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { | |||
206 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ | 206 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ |
207 | { STB0899_TSULC , 0x42 }, | 207 | { STB0899_TSULC , 0x42 }, |
208 | { STB0899_RSLLC , 0x41 }, | 208 | { STB0899_RSLLC , 0x41 }, |
209 | { STB0899_TSLPL , 0x12 }, | 209 | { STB0899_TSLPL , 0x12 }, |
210 | { STB0899_TSCFGH , 0x0c }, | 210 | { STB0899_TSCFGH , 0x0c }, |
211 | { STB0899_TSCFGM , 0x00 }, | 211 | { STB0899_TSCFGM , 0x00 }, |
212 | { STB0899_TSCFGL , 0x00 }, | 212 | { STB0899_TSCFGL , 0x00 }, |
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig index 3ec8e6fcbb1d..cec242b7c00d 100644 --- a/drivers/media/dvb/ngene/Kconfig +++ b/drivers/media/dvb/ngene/Kconfig | |||
@@ -4,6 +4,8 @@ config DVB_NGENE | |||
4 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 4 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
5 | select DVB_STV6110x if !DVB_FE_CUSTOMISE | 5 | select DVB_STV6110x if !DVB_FE_CUSTOMISE |
6 | select DVB_STV090x if !DVB_FE_CUSTOMISE | 6 | select DVB_STV090x if !DVB_FE_CUSTOMISE |
7 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | ||
8 | select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE | ||
7 | ---help--- | 9 | ---help--- |
8 | Support for Micronas PCI express cards with nGene bridge. | 10 | Support for Micronas PCI express cards with nGene bridge. |
9 | 11 | ||
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile index 40435cad4819..0608aabb14ee 100644 --- a/drivers/media/dvb/ngene/Makefile +++ b/drivers/media/dvb/ngene/Makefile | |||
@@ -2,10 +2,10 @@ | |||
2 | # Makefile for the nGene device driver | 2 | # Makefile for the nGene device driver |
3 | # | 3 | # |
4 | 4 | ||
5 | ngene-objs := ngene-core.o | 5 | ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o |
6 | 6 | ||
7 | obj-$(CONFIG_DVB_NGENE) += ngene.o | 7 | obj-$(CONFIG_DVB_NGENE) += ngene.o |
8 | 8 | ||
9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ | 9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ |
10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ | 10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ |
11 | 11 | EXTRA_CFLAGS += -Idrivers/media/common/tuners/ | |
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c new file mode 100644 index 000000000000..692c3e226e83 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-cards.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * ngene-cards.c: nGene PCIe bridge driver - card specific info | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * Modifications for new nGene firmware, | ||
8 | * support for EEPROM-copying, | ||
9 | * support for new dual DVB-S2 card prototype | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 only, as published by the Free Software Foundation. | ||
15 | * | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
26 | * 02110-1301, USA | ||
27 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/pci_ids.h> | ||
34 | |||
35 | #include "ngene.h" | ||
36 | |||
37 | /* demods/tuners */ | ||
38 | #include "stv6110x.h" | ||
39 | #include "stv090x.h" | ||
40 | #include "lnbh24.h" | ||
41 | #include "lgdt330x.h" | ||
42 | #include "mt2131.h" | ||
43 | |||
44 | |||
45 | /****************************************************************************/ | ||
46 | /* Demod/tuner attachment ***************************************************/ | ||
47 | /****************************************************************************/ | ||
48 | |||
49 | static int tuner_attach_stv6110(struct ngene_channel *chan) | ||
50 | { | ||
51 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
52 | chan->dev->card_info->fe_config[chan->number]; | ||
53 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) | ||
54 | chan->dev->card_info->tuner_config[chan->number]; | ||
55 | struct stv6110x_devctl *ctl; | ||
56 | |||
57 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, | ||
58 | &chan->i2c_adapter); | ||
59 | if (ctl == NULL) { | ||
60 | printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); | ||
61 | return -ENODEV; | ||
62 | } | ||
63 | |||
64 | feconf->tuner_init = ctl->tuner_init; | ||
65 | feconf->tuner_set_mode = ctl->tuner_set_mode; | ||
66 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; | ||
67 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; | ||
68 | feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; | ||
69 | feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; | ||
70 | feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; | ||
71 | feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; | ||
72 | feconf->tuner_set_refclk = ctl->tuner_set_refclk; | ||
73 | feconf->tuner_get_status = ctl->tuner_get_status; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | |||
79 | static int demod_attach_stv0900(struct ngene_channel *chan) | ||
80 | { | ||
81 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
82 | chan->dev->card_info->fe_config[chan->number]; | ||
83 | |||
84 | chan->fe = dvb_attach(stv090x_attach, | ||
85 | feconf, | ||
86 | &chan->i2c_adapter, | ||
87 | chan->number == 0 ? STV090x_DEMODULATOR_0 : | ||
88 | STV090x_DEMODULATOR_1); | ||
89 | if (chan->fe == NULL) { | ||
90 | printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); | ||
91 | return -ENODEV; | ||
92 | } | ||
93 | |||
94 | if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0, | ||
95 | 0, chan->dev->card_info->lnb[chan->number])) { | ||
96 | printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); | ||
97 | dvb_frontend_detach(chan->fe); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static struct lgdt330x_config aver_m780 = { | ||
105 | .demod_address = 0xb2 >> 1, | ||
106 | .demod_chip = LGDT3303, | ||
107 | .serial_mpeg = 0x00, /* PARALLEL */ | ||
108 | .clock_polarity_flip = 1, | ||
109 | }; | ||
110 | |||
111 | static struct mt2131_config m780_tunerconfig = { | ||
112 | 0xc0 >> 1 | ||
113 | }; | ||
114 | |||
115 | /* A single func to attach the demo and tuner, rather than | ||
116 | * use two sep funcs like the current design mandates. | ||
117 | */ | ||
118 | static int demod_attach_lg330x(struct ngene_channel *chan) | ||
119 | { | ||
120 | chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter); | ||
121 | if (chan->fe == NULL) { | ||
122 | printk(KERN_ERR DEVICE_NAME ": No LGDT330x found!\n"); | ||
123 | return -ENODEV; | ||
124 | } | ||
125 | |||
126 | dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter, | ||
127 | &m780_tunerconfig, 0); | ||
128 | |||
129 | return (chan->fe) ? 0 : -ENODEV; | ||
130 | } | ||
131 | |||
132 | /****************************************************************************/ | ||
133 | /* Switch control (I2C gates, etc.) *****************************************/ | ||
134 | /****************************************************************************/ | ||
135 | |||
136 | |||
137 | static struct stv090x_config fe_cineS2 = { | ||
138 | .device = STV0900, | ||
139 | .demod_mode = STV090x_DUAL, | ||
140 | .clk_mode = STV090x_CLK_EXT, | ||
141 | |||
142 | .xtal = 27000000, | ||
143 | .address = 0x68, | ||
144 | |||
145 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
146 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
147 | |||
148 | .repeater_level = STV090x_RPTLEVEL_16, | ||
149 | |||
150 | .adc1_range = STV090x_ADC_1Vpp, | ||
151 | .adc2_range = STV090x_ADC_1Vpp, | ||
152 | |||
153 | .diseqc_envelope_mode = true, | ||
154 | }; | ||
155 | |||
156 | static struct stv6110x_config tuner_cineS2_0 = { | ||
157 | .addr = 0x60, | ||
158 | .refclk = 27000000, | ||
159 | .clk_div = 1, | ||
160 | }; | ||
161 | |||
162 | static struct stv6110x_config tuner_cineS2_1 = { | ||
163 | .addr = 0x63, | ||
164 | .refclk = 27000000, | ||
165 | .clk_div = 1, | ||
166 | }; | ||
167 | |||
168 | static struct ngene_info ngene_info_cineS2 = { | ||
169 | .type = NGENE_SIDEWINDER, | ||
170 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner", | ||
171 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
172 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
173 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
174 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
175 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
176 | .lnb = {0x0b, 0x08}, | ||
177 | .tsf = {3, 3}, | ||
178 | .fw_version = 15, | ||
179 | }; | ||
180 | |||
181 | static struct ngene_info ngene_info_satixS2 = { | ||
182 | .type = NGENE_SIDEWINDER, | ||
183 | .name = "Mystique SaTiX-S2 Dual", | ||
184 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
185 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
186 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
187 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
188 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
189 | .lnb = {0x0b, 0x08}, | ||
190 | .tsf = {3, 3}, | ||
191 | .fw_version = 15, | ||
192 | }; | ||
193 | |||
194 | static struct ngene_info ngene_info_satixS2v2 = { | ||
195 | .type = NGENE_SIDEWINDER, | ||
196 | .name = "Mystique SaTiX-S2 Dual (v2)", | ||
197 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
198 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
199 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
200 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
201 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
202 | .lnb = {0x0a, 0x08}, | ||
203 | .tsf = {3, 3}, | ||
204 | .fw_version = 15, | ||
205 | }; | ||
206 | |||
207 | static struct ngene_info ngene_info_cineS2v5 = { | ||
208 | .type = NGENE_SIDEWINDER, | ||
209 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)", | ||
210 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
211 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
212 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
213 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
214 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
215 | .lnb = {0x0a, 0x08}, | ||
216 | .tsf = {3, 3}, | ||
217 | .fw_version = 15, | ||
218 | }; | ||
219 | |||
220 | static struct ngene_info ngene_info_m780 = { | ||
221 | .type = NGENE_APP, | ||
222 | .name = "Aver M780 ATSC/QAM-B", | ||
223 | |||
224 | /* Channel 0 is analog, which is currently unsupported */ | ||
225 | .io_type = { NGENE_IO_NONE, NGENE_IO_TSIN }, | ||
226 | .demod_attach = { NULL, demod_attach_lg330x }, | ||
227 | |||
228 | /* Ensure these are NULL else the frame will call them (as funcs) */ | ||
229 | .tuner_attach = { 0, 0, 0, 0 }, | ||
230 | .fe_config = { NULL, &aver_m780 }, | ||
231 | .avf = { 0 }, | ||
232 | |||
233 | /* A custom electrical interface config for the demod to bridge */ | ||
234 | .tsf = { 4, 4 }, | ||
235 | .fw_version = 15, | ||
236 | }; | ||
237 | |||
238 | /****************************************************************************/ | ||
239 | |||
240 | |||
241 | |||
242 | /****************************************************************************/ | ||
243 | /* PCI Subsystem ID *********************************************************/ | ||
244 | /****************************************************************************/ | ||
245 | |||
246 | #define NGENE_ID(_subvend, _subdev, _driverdata) { \ | ||
247 | .vendor = NGENE_VID, .device = NGENE_PID, \ | ||
248 | .subvendor = _subvend, .subdevice = _subdev, \ | ||
249 | .driver_data = (unsigned long) &_driverdata } | ||
250 | |||
251 | /****************************************************************************/ | ||
252 | |||
253 | static const struct pci_device_id ngene_id_tbl[] __devinitdata = { | ||
254 | NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), | ||
255 | NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), | ||
256 | NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), | ||
257 | NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2), | ||
258 | NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5), | ||
259 | NGENE_ID(0x1461, 0x062e, ngene_info_m780), | ||
260 | {0} | ||
261 | }; | ||
262 | MODULE_DEVICE_TABLE(pci, ngene_id_tbl); | ||
263 | |||
264 | /****************************************************************************/ | ||
265 | /* Init/Exit ****************************************************************/ | ||
266 | /****************************************************************************/ | ||
267 | |||
268 | static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, | ||
269 | enum pci_channel_state state) | ||
270 | { | ||
271 | printk(KERN_ERR DEVICE_NAME ": PCI error\n"); | ||
272 | if (state == pci_channel_io_perm_failure) | ||
273 | return PCI_ERS_RESULT_DISCONNECT; | ||
274 | if (state == pci_channel_io_frozen) | ||
275 | return PCI_ERS_RESULT_NEED_RESET; | ||
276 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
277 | } | ||
278 | |||
279 | static pci_ers_result_t ngene_link_reset(struct pci_dev *dev) | ||
280 | { | ||
281 | printk(KERN_INFO DEVICE_NAME ": link reset\n"); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) | ||
286 | { | ||
287 | printk(KERN_INFO DEVICE_NAME ": slot reset\n"); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void ngene_resume(struct pci_dev *dev) | ||
292 | { | ||
293 | printk(KERN_INFO DEVICE_NAME ": resume\n"); | ||
294 | } | ||
295 | |||
296 | static struct pci_error_handlers ngene_errors = { | ||
297 | .error_detected = ngene_error_detected, | ||
298 | .link_reset = ngene_link_reset, | ||
299 | .slot_reset = ngene_slot_reset, | ||
300 | .resume = ngene_resume, | ||
301 | }; | ||
302 | |||
303 | static struct pci_driver ngene_pci_driver = { | ||
304 | .name = "ngene", | ||
305 | .id_table = ngene_id_tbl, | ||
306 | .probe = ngene_probe, | ||
307 | .remove = __devexit_p(ngene_remove), | ||
308 | .err_handler = &ngene_errors, | ||
309 | }; | ||
310 | |||
311 | static __init int module_init_ngene(void) | ||
312 | { | ||
313 | printk(KERN_INFO | ||
314 | "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); | ||
315 | return pci_register_driver(&ngene_pci_driver); | ||
316 | } | ||
317 | |||
318 | static __exit void module_exit_ngene(void) | ||
319 | { | ||
320 | pci_unregister_driver(&ngene_pci_driver); | ||
321 | } | ||
322 | |||
323 | module_init(module_init_ngene); | ||
324 | module_exit(module_exit_ngene); | ||
325 | |||
326 | MODULE_DESCRIPTION("nGene"); | ||
327 | MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); | ||
328 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 645e8b8a7137..c8b4dfa0ab5f 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c | |||
@@ -34,20 +34,14 @@ | |||
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <asm/div64.h> | 35 | #include <asm/div64.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/pci_ids.h> | ||
38 | #include <linux/smp_lock.h> | 37 | #include <linux/smp_lock.h> |
39 | #include <linux/timer.h> | 38 | #include <linux/timer.h> |
40 | #include <linux/version.h> | ||
41 | #include <linux/byteorder/generic.h> | 39 | #include <linux/byteorder/generic.h> |
42 | #include <linux/firmware.h> | 40 | #include <linux/firmware.h> |
43 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
44 | 42 | ||
45 | #include "ngene.h" | 43 | #include "ngene.h" |
46 | 44 | ||
47 | #include "stv6110x.h" | ||
48 | #include "stv090x.h" | ||
49 | #include "lnbh24.h" | ||
50 | |||
51 | static int one_adapter = 1; | 45 | static int one_adapter = 1; |
52 | module_param(one_adapter, int, 0444); | 46 | module_param(one_adapter, int, 0444); |
53 | MODULE_PARM_DESC(one_adapter, "Use only one adapter."); | 47 | MODULE_PARM_DESC(one_adapter, "Use only one adapter."); |
@@ -63,8 +57,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
63 | 57 | ||
64 | #define dprintk if (debug) printk | 58 | #define dprintk if (debug) printk |
65 | 59 | ||
66 | #define DEVICE_NAME "ngene" | ||
67 | |||
68 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | 60 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) |
69 | #define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) | 61 | #define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) |
70 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | 62 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) |
@@ -352,7 +344,7 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) | |||
352 | return 0; | 344 | return 0; |
353 | } | 345 | } |
354 | 346 | ||
355 | static int ngene_command(struct ngene *dev, struct ngene_command *com) | 347 | int ngene_command(struct ngene *dev, struct ngene_command *com) |
356 | { | 348 | { |
357 | int result; | 349 | int result; |
358 | 350 | ||
@@ -363,55 +355,6 @@ static int ngene_command(struct ngene *dev, struct ngene_command *com) | |||
363 | } | 355 | } |
364 | 356 | ||
365 | 357 | ||
366 | static int ngene_command_i2c_read(struct ngene *dev, u8 adr, | ||
367 | u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) | ||
368 | { | ||
369 | struct ngene_command com; | ||
370 | |||
371 | com.cmd.hdr.Opcode = CMD_I2C_READ; | ||
372 | com.cmd.hdr.Length = outlen + 3; | ||
373 | com.cmd.I2CRead.Device = adr << 1; | ||
374 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
375 | com.cmd.I2CRead.Data[outlen] = inlen; | ||
376 | com.cmd.I2CRead.Data[outlen + 1] = 0; | ||
377 | com.in_len = outlen + 3; | ||
378 | com.out_len = inlen + 1; | ||
379 | |||
380 | if (ngene_command(dev, &com) < 0) | ||
381 | return -EIO; | ||
382 | |||
383 | if ((com.cmd.raw8[0] >> 1) != adr) | ||
384 | return -EIO; | ||
385 | |||
386 | if (flag) | ||
387 | memcpy(in, com.cmd.raw8, inlen + 1); | ||
388 | else | ||
389 | memcpy(in, com.cmd.raw8 + 1, inlen); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static int ngene_command_i2c_write(struct ngene *dev, u8 adr, | ||
394 | u8 *out, u8 outlen) | ||
395 | { | ||
396 | struct ngene_command com; | ||
397 | |||
398 | |||
399 | com.cmd.hdr.Opcode = CMD_I2C_WRITE; | ||
400 | com.cmd.hdr.Length = outlen + 1; | ||
401 | com.cmd.I2CRead.Device = adr << 1; | ||
402 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
403 | com.in_len = outlen + 1; | ||
404 | com.out_len = 1; | ||
405 | |||
406 | if (ngene_command(dev, &com) < 0) | ||
407 | return -EIO; | ||
408 | |||
409 | if (com.cmd.raw8[0] == 1) | ||
410 | return -EIO; | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int ngene_command_load_firmware(struct ngene *dev, | 358 | static int ngene_command_load_firmware(struct ngene *dev, |
416 | u8 *ngene_fw, u32 size) | 359 | u8 *ngene_fw, u32 size) |
417 | { | 360 | { |
@@ -477,7 +420,7 @@ static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) | |||
477 | return 0; | 420 | return 0; |
478 | } | 421 | } |
479 | 422 | ||
480 | static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) | 423 | int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) |
481 | { | 424 | { |
482 | struct ngene_command com; | 425 | struct ngene_command com; |
483 | 426 | ||
@@ -514,11 +457,12 @@ static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) | |||
514 | 457 | ||
515 | /****************************************************************************/ | 458 | /****************************************************************************/ |
516 | 459 | ||
517 | static u8 TSFeatureDecoderSetup[8 * 4] = { | 460 | static u8 TSFeatureDecoderSetup[8 * 5] = { |
518 | 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, | 461 | 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, |
519 | 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ | 462 | 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ |
520 | 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ | 463 | 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ |
521 | 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ | 464 | 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ |
465 | 0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */ | ||
522 | }; | 466 | }; |
523 | 467 | ||
524 | /* Set NGENE I2S Config to 16 bit packed */ | 468 | /* Set NGENE I2S Config to 16 bit packed */ |
@@ -559,7 +503,7 @@ static u8 ITUFeatureDecoderSetup[8] = { | |||
559 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 | 503 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 |
560 | }; | 504 | }; |
561 | 505 | ||
562 | static void FillTSBuffer(void *Buffer, int Length, u32 Flags) | 506 | void FillTSBuffer(void *Buffer, int Length, u32 Flags) |
563 | { | 507 | { |
564 | u32 *ptr = Buffer; | 508 | u32 *ptr = Buffer; |
565 | 509 | ||
@@ -772,144 +716,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream, | |||
772 | return 0; | 716 | return 0; |
773 | } | 717 | } |
774 | 718 | ||
775 | 719 | void set_transfer(struct ngene_channel *chan, int state) | |
776 | /****************************************************************************/ | ||
777 | /* I2C **********************************************************************/ | ||
778 | /****************************************************************************/ | ||
779 | |||
780 | static void ngene_i2c_set_bus(struct ngene *dev, int bus) | ||
781 | { | ||
782 | if (!(dev->card_info->i2c_access & 2)) | ||
783 | return; | ||
784 | if (dev->i2c_current_bus == bus) | ||
785 | return; | ||
786 | |||
787 | switch (bus) { | ||
788 | case 0: | ||
789 | ngene_command_gpio_set(dev, 3, 0); | ||
790 | ngene_command_gpio_set(dev, 2, 1); | ||
791 | break; | ||
792 | |||
793 | case 1: | ||
794 | ngene_command_gpio_set(dev, 2, 0); | ||
795 | ngene_command_gpio_set(dev, 3, 1); | ||
796 | break; | ||
797 | } | ||
798 | dev->i2c_current_bus = bus; | ||
799 | } | ||
800 | |||
801 | static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, | ||
802 | struct i2c_msg msg[], int num) | ||
803 | { | ||
804 | struct ngene_channel *chan = | ||
805 | (struct ngene_channel *)i2c_get_adapdata(adapter); | ||
806 | struct ngene *dev = chan->dev; | ||
807 | |||
808 | down(&dev->i2c_switch_mutex); | ||
809 | ngene_i2c_set_bus(dev, chan->number); | ||
810 | |||
811 | if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) | ||
812 | if (!ngene_command_i2c_read(dev, msg[0].addr, | ||
813 | msg[0].buf, msg[0].len, | ||
814 | msg[1].buf, msg[1].len, 0)) | ||
815 | goto done; | ||
816 | |||
817 | if (num == 1 && !(msg[0].flags & I2C_M_RD)) | ||
818 | if (!ngene_command_i2c_write(dev, msg[0].addr, | ||
819 | msg[0].buf, msg[0].len)) | ||
820 | goto done; | ||
821 | if (num == 1 && (msg[0].flags & I2C_M_RD)) | ||
822 | if (!ngene_command_i2c_read(dev, msg[0].addr, 0, 0, | ||
823 | msg[0].buf, msg[0].len, 0)) | ||
824 | goto done; | ||
825 | |||
826 | up(&dev->i2c_switch_mutex); | ||
827 | return -EIO; | ||
828 | |||
829 | done: | ||
830 | up(&dev->i2c_switch_mutex); | ||
831 | return num; | ||
832 | } | ||
833 | |||
834 | |||
835 | static u32 ngene_i2c_functionality(struct i2c_adapter *adap) | ||
836 | { | ||
837 | return I2C_FUNC_SMBUS_EMUL; | ||
838 | } | ||
839 | |||
840 | static struct i2c_algorithm ngene_i2c_algo = { | ||
841 | .master_xfer = ngene_i2c_master_xfer, | ||
842 | .functionality = ngene_i2c_functionality, | ||
843 | }; | ||
844 | |||
845 | static int ngene_i2c_init(struct ngene *dev, int dev_nr) | ||
846 | { | ||
847 | struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); | ||
848 | |||
849 | i2c_set_adapdata(adap, &(dev->channel[dev_nr])); | ||
850 | adap->class = I2C_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; | ||
851 | |||
852 | strcpy(adap->name, "nGene"); | ||
853 | |||
854 | adap->algo = &ngene_i2c_algo; | ||
855 | adap->algo_data = (void *)&(dev->channel[dev_nr]); | ||
856 | adap->dev.parent = &dev->pci_dev->dev; | ||
857 | |||
858 | return i2c_add_adapter(adap); | ||
859 | } | ||
860 | |||
861 | |||
862 | /****************************************************************************/ | ||
863 | /* DVB functions and API interface ******************************************/ | ||
864 | /****************************************************************************/ | ||
865 | |||
866 | static void swap_buffer(u32 *p, u32 len) | ||
867 | { | ||
868 | while (len) { | ||
869 | *p = swab32(*p); | ||
870 | p++; | ||
871 | len -= 4; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | |||
876 | static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
877 | { | ||
878 | struct ngene_channel *chan = priv; | ||
879 | |||
880 | |||
881 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
882 | if (chan->users > 0) | ||
883 | #endif | ||
884 | dvb_dmx_swfilter(&chan->demux, buf, len); | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; | ||
889 | |||
890 | static void *tsout_exchange(void *priv, void *buf, u32 len, | ||
891 | u32 clock, u32 flags) | ||
892 | { | ||
893 | struct ngene_channel *chan = priv; | ||
894 | struct ngene *dev = chan->dev; | ||
895 | u32 alen; | ||
896 | |||
897 | alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); | ||
898 | alen -= alen % 188; | ||
899 | |||
900 | if (alen < len) | ||
901 | FillTSBuffer(buf + alen, len - alen, flags); | ||
902 | else | ||
903 | alen = len; | ||
904 | dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); | ||
905 | if (flags & DF_SWAP32) | ||
906 | swap_buffer((u32 *)buf, alen); | ||
907 | wake_up_interruptible(&dev->tsout_rbuf.queue); | ||
908 | return buf; | ||
909 | } | ||
910 | |||
911 | |||
912 | static void set_transfer(struct ngene_channel *chan, int state) | ||
913 | { | 720 | { |
914 | u8 control = 0, mode = 0, flags = 0; | 721 | u8 control = 0, mode = 0, flags = 0; |
915 | struct ngene *dev = chan->dev; | 722 | struct ngene *dev = chan->dev; |
@@ -970,85 +777,12 @@ static void set_transfer(struct ngene_channel *chan, int state) | |||
970 | state); | 777 | state); |
971 | if (!state) { | 778 | if (!state) { |
972 | spin_lock_irq(&chan->state_lock); | 779 | spin_lock_irq(&chan->state_lock); |
973 | chan->pBufferExchange = 0; | 780 | chan->pBufferExchange = NULL; |
974 | dvb_ringbuffer_flush(&dev->tsout_rbuf); | 781 | dvb_ringbuffer_flush(&dev->tsout_rbuf); |
975 | spin_unlock_irq(&chan->state_lock); | 782 | spin_unlock_irq(&chan->state_lock); |
976 | } | 783 | } |
977 | } | 784 | } |
978 | 785 | ||
979 | static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
980 | { | ||
981 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
982 | struct ngene_channel *chan = dvbdmx->priv; | ||
983 | |||
984 | if (chan->users == 0) { | ||
985 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
986 | if (!chan->running) | ||
987 | #endif | ||
988 | set_transfer(chan, 1); | ||
989 | /* msleep(10); */ | ||
990 | } | ||
991 | |||
992 | return ++chan->users; | ||
993 | } | ||
994 | |||
995 | static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
996 | { | ||
997 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
998 | struct ngene_channel *chan = dvbdmx->priv; | ||
999 | |||
1000 | if (--chan->users) | ||
1001 | return chan->users; | ||
1002 | |||
1003 | #ifndef COMMAND_TIMEOUT_WORKAROUND | ||
1004 | set_transfer(chan, 0); | ||
1005 | #endif | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | |||
1012 | static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, | ||
1013 | int (*start_feed)(struct dvb_demux_feed *), | ||
1014 | int (*stop_feed)(struct dvb_demux_feed *), | ||
1015 | void *priv) | ||
1016 | { | ||
1017 | dvbdemux->priv = priv; | ||
1018 | |||
1019 | dvbdemux->filternum = 256; | ||
1020 | dvbdemux->feednum = 256; | ||
1021 | dvbdemux->start_feed = start_feed; | ||
1022 | dvbdemux->stop_feed = stop_feed; | ||
1023 | dvbdemux->write_to_decoder = 0; | ||
1024 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | ||
1025 | DMX_SECTION_FILTERING | | ||
1026 | DMX_MEMORY_BASED_FILTERING); | ||
1027 | return dvb_dmx_init(dvbdemux); | ||
1028 | } | ||
1029 | |||
1030 | static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, | ||
1031 | struct dvb_demux *dvbdemux, | ||
1032 | struct dmx_frontend *hw_frontend, | ||
1033 | struct dmx_frontend *mem_frontend, | ||
1034 | struct dvb_adapter *dvb_adapter) | ||
1035 | { | ||
1036 | int ret; | ||
1037 | |||
1038 | dmxdev->filternum = 256; | ||
1039 | dmxdev->demux = &dvbdemux->dmx; | ||
1040 | dmxdev->capabilities = 0; | ||
1041 | ret = dvb_dmxdev_init(dmxdev, dvb_adapter); | ||
1042 | if (ret < 0) | ||
1043 | return ret; | ||
1044 | |||
1045 | hw_frontend->source = DMX_FRONTEND_0; | ||
1046 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); | ||
1047 | mem_frontend->source = DMX_MEMORY_FE; | ||
1048 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); | ||
1049 | return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); | ||
1050 | } | ||
1051 | |||
1052 | 786 | ||
1053 | /****************************************************************************/ | 787 | /****************************************************************************/ |
1054 | /* nGene hardware init and release functions ********************************/ | 788 | /* nGene hardware init and release functions ********************************/ |
@@ -1094,8 +828,8 @@ static void free_idlebuffer(struct ngene *dev, | |||
1094 | return; | 828 | return; |
1095 | free_ringbuffer(dev, rb); | 829 | free_ringbuffer(dev, rb); |
1096 | for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { | 830 | for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { |
1097 | Cur->Buffer2 = 0; | 831 | Cur->Buffer2 = NULL; |
1098 | Cur->scList2 = 0; | 832 | Cur->scList2 = NULL; |
1099 | Cur->ngeneBuffer.Address_of_first_entry_2 = 0; | 833 | Cur->ngeneBuffer.Address_of_first_entry_2 = 0; |
1100 | Cur->ngeneBuffer.Number_of_entries_2 = 0; | 834 | Cur->ngeneBuffer.Number_of_entries_2 = 0; |
1101 | } | 835 | } |
@@ -1141,7 +875,7 @@ static int create_ring_buffer(struct pci_dev *pci_dev, | |||
1141 | u64 PARingBufferNext; | 875 | u64 PARingBufferNext; |
1142 | struct SBufferHeader *Cur, *Next; | 876 | struct SBufferHeader *Cur, *Next; |
1143 | 877 | ||
1144 | descr->Head = 0; | 878 | descr->Head = NULL; |
1145 | descr->MemSize = 0; | 879 | descr->MemSize = 0; |
1146 | descr->PAHead = 0; | 880 | descr->PAHead = 0; |
1147 | descr->NumBuffers = 0; | 881 | descr->NumBuffers = 0; |
@@ -1633,69 +1367,6 @@ fail: | |||
1633 | 1367 | ||
1634 | 1368 | ||
1635 | 1369 | ||
1636 | /****************************************************************************/ | ||
1637 | /* Switch control (I2C gates, etc.) *****************************************/ | ||
1638 | /****************************************************************************/ | ||
1639 | |||
1640 | |||
1641 | /****************************************************************************/ | ||
1642 | /* Demod/tuner attachment ***************************************************/ | ||
1643 | /****************************************************************************/ | ||
1644 | |||
1645 | static int tuner_attach_stv6110(struct ngene_channel *chan) | ||
1646 | { | ||
1647 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
1648 | chan->dev->card_info->fe_config[chan->number]; | ||
1649 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) | ||
1650 | chan->dev->card_info->tuner_config[chan->number]; | ||
1651 | struct stv6110x_devctl *ctl; | ||
1652 | |||
1653 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, | ||
1654 | &chan->i2c_adapter); | ||
1655 | if (ctl == NULL) { | ||
1656 | printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); | ||
1657 | return -ENODEV; | ||
1658 | } | ||
1659 | |||
1660 | feconf->tuner_init = ctl->tuner_init; | ||
1661 | feconf->tuner_set_mode = ctl->tuner_set_mode; | ||
1662 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; | ||
1663 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; | ||
1664 | feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; | ||
1665 | feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; | ||
1666 | feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; | ||
1667 | feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; | ||
1668 | feconf->tuner_set_refclk = ctl->tuner_set_refclk; | ||
1669 | feconf->tuner_get_status = ctl->tuner_get_status; | ||
1670 | |||
1671 | return 0; | ||
1672 | } | ||
1673 | |||
1674 | |||
1675 | static int demod_attach_stv0900(struct ngene_channel *chan) | ||
1676 | { | ||
1677 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
1678 | chan->dev->card_info->fe_config[chan->number]; | ||
1679 | |||
1680 | chan->fe = dvb_attach(stv090x_attach, | ||
1681 | feconf, | ||
1682 | &chan->i2c_adapter, | ||
1683 | chan->number == 0 ? STV090x_DEMODULATOR_0 : | ||
1684 | STV090x_DEMODULATOR_1); | ||
1685 | if (chan->fe == NULL) { | ||
1686 | printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); | ||
1687 | return -ENODEV; | ||
1688 | } | ||
1689 | |||
1690 | if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0, | ||
1691 | 0, chan->dev->card_info->lnb[chan->number])) { | ||
1692 | printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); | ||
1693 | dvb_frontend_detach(chan->fe); | ||
1694 | return -ENODEV; | ||
1695 | } | ||
1696 | |||
1697 | return 0; | ||
1698 | } | ||
1699 | 1370 | ||
1700 | /****************************************************************************/ | 1371 | /****************************************************************************/ |
1701 | /****************************************************************************/ | 1372 | /****************************************************************************/ |
@@ -1719,7 +1390,7 @@ static void release_channel(struct ngene_channel *chan) | |||
1719 | if (chan->fe) { | 1390 | if (chan->fe) { |
1720 | dvb_unregister_frontend(chan->fe); | 1391 | dvb_unregister_frontend(chan->fe); |
1721 | dvb_frontend_detach(chan->fe); | 1392 | dvb_frontend_detach(chan->fe); |
1722 | chan->fe = 0; | 1393 | chan->fe = NULL; |
1723 | } | 1394 | } |
1724 | dvbdemux->dmx.close(&dvbdemux->dmx); | 1395 | dvbdemux->dmx.close(&dvbdemux->dmx); |
1725 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, | 1396 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, |
@@ -1751,7 +1422,7 @@ static int init_channel(struct ngene_channel *chan) | |||
1751 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | 1422 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { |
1752 | if (nr >= STREAM_AUDIOIN1) | 1423 | if (nr >= STREAM_AUDIOIN1) |
1753 | chan->DataFormatFlags = DF_SWAP32; | 1424 | chan->DataFormatFlags = DF_SWAP32; |
1754 | if (nr == 0 || !one_adapter) { | 1425 | if (nr == 0 || !one_adapter || dev->first_adapter == NULL) { |
1755 | adapter = &dev->adapter[nr]; | 1426 | adapter = &dev->adapter[nr]; |
1756 | ret = dvb_register_adapter(adapter, "nGene", | 1427 | ret = dvb_register_adapter(adapter, "nGene", |
1757 | THIS_MODULE, | 1428 | THIS_MODULE, |
@@ -1759,8 +1430,10 @@ static int init_channel(struct ngene_channel *chan) | |||
1759 | adapter_nr); | 1430 | adapter_nr); |
1760 | if (ret < 0) | 1431 | if (ret < 0) |
1761 | return ret; | 1432 | return ret; |
1433 | if (dev->first_adapter == NULL) | ||
1434 | dev->first_adapter = adapter; | ||
1762 | } else { | 1435 | } else { |
1763 | adapter = &dev->adapter[0]; | 1436 | adapter = dev->first_adapter; |
1764 | } | 1437 | } |
1765 | 1438 | ||
1766 | ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", | 1439 | ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", |
@@ -1797,6 +1470,7 @@ static int init_channels(struct ngene *dev) | |||
1797 | int i, j; | 1470 | int i, j; |
1798 | 1471 | ||
1799 | for (i = 0; i < MAX_STREAM; i++) { | 1472 | for (i = 0; i < MAX_STREAM; i++) { |
1473 | dev->channel[i].number = i; | ||
1800 | if (init_channel(&dev->channel[i]) < 0) { | 1474 | if (init_channel(&dev->channel[i]) < 0) { |
1801 | for (j = i - 1; j >= 0; j--) | 1475 | for (j = i - 1; j >= 0; j--) |
1802 | release_channel(&dev->channel[j]); | 1476 | release_channel(&dev->channel[j]); |
@@ -1810,7 +1484,7 @@ static int init_channels(struct ngene *dev) | |||
1810 | /* device probe/remove calls ************************************************/ | 1484 | /* device probe/remove calls ************************************************/ |
1811 | /****************************************************************************/ | 1485 | /****************************************************************************/ |
1812 | 1486 | ||
1813 | static void __devexit ngene_remove(struct pci_dev *pdev) | 1487 | void __devexit ngene_remove(struct pci_dev *pdev) |
1814 | { | 1488 | { |
1815 | struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); | 1489 | struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); |
1816 | int i; | 1490 | int i; |
@@ -1820,12 +1494,12 @@ static void __devexit ngene_remove(struct pci_dev *pdev) | |||
1820 | release_channel(&dev->channel[i]); | 1494 | release_channel(&dev->channel[i]); |
1821 | ngene_stop(dev); | 1495 | ngene_stop(dev); |
1822 | ngene_release_buffers(dev); | 1496 | ngene_release_buffers(dev); |
1823 | pci_set_drvdata(pdev, 0); | 1497 | pci_set_drvdata(pdev, NULL); |
1824 | pci_disable_device(pdev); | 1498 | pci_disable_device(pdev); |
1825 | } | 1499 | } |
1826 | 1500 | ||
1827 | static int __devinit ngene_probe(struct pci_dev *pci_dev, | 1501 | int __devinit ngene_probe(struct pci_dev *pci_dev, |
1828 | const struct pci_device_id *id) | 1502 | const struct pci_device_id *id) |
1829 | { | 1503 | { |
1830 | struct ngene *dev; | 1504 | struct ngene *dev; |
1831 | int stat = 0; | 1505 | int stat = 0; |
@@ -1868,156 +1542,6 @@ fail1: | |||
1868 | ngene_release_buffers(dev); | 1542 | ngene_release_buffers(dev); |
1869 | fail0: | 1543 | fail0: |
1870 | pci_disable_device(pci_dev); | 1544 | pci_disable_device(pci_dev); |
1871 | pci_set_drvdata(pci_dev, 0); | 1545 | pci_set_drvdata(pci_dev, NULL); |
1872 | return stat; | 1546 | return stat; |
1873 | } | 1547 | } |
1874 | |||
1875 | /****************************************************************************/ | ||
1876 | /* Card configs *************************************************************/ | ||
1877 | /****************************************************************************/ | ||
1878 | |||
1879 | static struct stv090x_config fe_cineS2 = { | ||
1880 | .device = STV0900, | ||
1881 | .demod_mode = STV090x_DUAL, | ||
1882 | .clk_mode = STV090x_CLK_EXT, | ||
1883 | |||
1884 | .xtal = 27000000, | ||
1885 | .address = 0x68, | ||
1886 | |||
1887 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
1888 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
1889 | |||
1890 | .repeater_level = STV090x_RPTLEVEL_16, | ||
1891 | |||
1892 | .adc1_range = STV090x_ADC_1Vpp, | ||
1893 | .adc2_range = STV090x_ADC_1Vpp, | ||
1894 | |||
1895 | .diseqc_envelope_mode = true, | ||
1896 | }; | ||
1897 | |||
1898 | static struct stv6110x_config tuner_cineS2_0 = { | ||
1899 | .addr = 0x60, | ||
1900 | .refclk = 27000000, | ||
1901 | .clk_div = 1, | ||
1902 | }; | ||
1903 | |||
1904 | static struct stv6110x_config tuner_cineS2_1 = { | ||
1905 | .addr = 0x63, | ||
1906 | .refclk = 27000000, | ||
1907 | .clk_div = 1, | ||
1908 | }; | ||
1909 | |||
1910 | static struct ngene_info ngene_info_cineS2 = { | ||
1911 | .type = NGENE_SIDEWINDER, | ||
1912 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner", | ||
1913 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
1914 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
1915 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
1916 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
1917 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
1918 | .lnb = {0x0b, 0x08}, | ||
1919 | .tsf = {3, 3}, | ||
1920 | .fw_version = 15, | ||
1921 | }; | ||
1922 | |||
1923 | static struct ngene_info ngene_info_satixs2 = { | ||
1924 | .type = NGENE_SIDEWINDER, | ||
1925 | .name = "Mystique SaTiX-S2 Dual", | ||
1926 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
1927 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
1928 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
1929 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
1930 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
1931 | .lnb = {0x0b, 0x08}, | ||
1932 | .tsf = {3, 3}, | ||
1933 | .fw_version = 15, | ||
1934 | }; | ||
1935 | |||
1936 | /****************************************************************************/ | ||
1937 | |||
1938 | |||
1939 | |||
1940 | /****************************************************************************/ | ||
1941 | /* PCI Subsystem ID *********************************************************/ | ||
1942 | /****************************************************************************/ | ||
1943 | |||
1944 | #define NGENE_ID(_subvend, _subdev, _driverdata) { \ | ||
1945 | .vendor = NGENE_VID, .device = NGENE_PID, \ | ||
1946 | .subvendor = _subvend, .subdevice = _subdev, \ | ||
1947 | .driver_data = (unsigned long) &_driverdata } | ||
1948 | |||
1949 | /****************************************************************************/ | ||
1950 | |||
1951 | static const struct pci_device_id ngene_id_tbl[] __devinitdata = { | ||
1952 | NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), | ||
1953 | NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), | ||
1954 | NGENE_ID(0x18c3, 0xdb01, ngene_info_satixs2), | ||
1955 | {0} | ||
1956 | }; | ||
1957 | MODULE_DEVICE_TABLE(pci, ngene_id_tbl); | ||
1958 | |||
1959 | /****************************************************************************/ | ||
1960 | /* Init/Exit ****************************************************************/ | ||
1961 | /****************************************************************************/ | ||
1962 | |||
1963 | static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, | ||
1964 | enum pci_channel_state state) | ||
1965 | { | ||
1966 | printk(KERN_ERR DEVICE_NAME ": PCI error\n"); | ||
1967 | if (state == pci_channel_io_perm_failure) | ||
1968 | return PCI_ERS_RESULT_DISCONNECT; | ||
1969 | if (state == pci_channel_io_frozen) | ||
1970 | return PCI_ERS_RESULT_NEED_RESET; | ||
1971 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
1972 | } | ||
1973 | |||
1974 | static pci_ers_result_t ngene_link_reset(struct pci_dev *dev) | ||
1975 | { | ||
1976 | printk(KERN_INFO DEVICE_NAME ": link reset\n"); | ||
1977 | return 0; | ||
1978 | } | ||
1979 | |||
1980 | static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) | ||
1981 | { | ||
1982 | printk(KERN_INFO DEVICE_NAME ": slot reset\n"); | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1986 | static void ngene_resume(struct pci_dev *dev) | ||
1987 | { | ||
1988 | printk(KERN_INFO DEVICE_NAME ": resume\n"); | ||
1989 | } | ||
1990 | |||
1991 | static struct pci_error_handlers ngene_errors = { | ||
1992 | .error_detected = ngene_error_detected, | ||
1993 | .link_reset = ngene_link_reset, | ||
1994 | .slot_reset = ngene_slot_reset, | ||
1995 | .resume = ngene_resume, | ||
1996 | }; | ||
1997 | |||
1998 | static struct pci_driver ngene_pci_driver = { | ||
1999 | .name = "ngene", | ||
2000 | .id_table = ngene_id_tbl, | ||
2001 | .probe = ngene_probe, | ||
2002 | .remove = __devexit_p(ngene_remove), | ||
2003 | .err_handler = &ngene_errors, | ||
2004 | }; | ||
2005 | |||
2006 | static __init int module_init_ngene(void) | ||
2007 | { | ||
2008 | printk(KERN_INFO | ||
2009 | "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); | ||
2010 | return pci_register_driver(&ngene_pci_driver); | ||
2011 | } | ||
2012 | |||
2013 | static __exit void module_exit_ngene(void) | ||
2014 | { | ||
2015 | pci_unregister_driver(&ngene_pci_driver); | ||
2016 | } | ||
2017 | |||
2018 | module_init(module_init_ngene); | ||
2019 | module_exit(module_exit_ngene); | ||
2020 | |||
2021 | MODULE_DESCRIPTION("nGene"); | ||
2022 | MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); | ||
2023 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/dvb/ngene/ngene-dvb.c new file mode 100644 index 000000000000..96013eb353cd --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-dvb.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * ngene-dvb.c: nGene PCIe bridge driver - DVB functions | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * Modifications for new nGene firmware, | ||
8 | * support for EEPROM-copying, | ||
9 | * support for new dual DVB-S2 card prototype | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 only, as published by the Free Software Foundation. | ||
15 | * | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
26 | * 02110-1301, USA | ||
27 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/io.h> | ||
36 | #include <asm/div64.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/smp_lock.h> | ||
39 | #include <linux/timer.h> | ||
40 | #include <linux/version.h> | ||
41 | #include <linux/byteorder/generic.h> | ||
42 | #include <linux/firmware.h> | ||
43 | #include <linux/vmalloc.h> | ||
44 | |||
45 | #include "ngene.h" | ||
46 | |||
47 | #define COMMAND_TIMEOUT_WORKAROUND | ||
48 | |||
49 | |||
50 | /****************************************************************************/ | ||
51 | /* COMMAND API interface ****************************************************/ | ||
52 | /****************************************************************************/ | ||
53 | |||
54 | /****************************************************************************/ | ||
55 | /* DVB functions and API interface ******************************************/ | ||
56 | /****************************************************************************/ | ||
57 | |||
58 | static void swap_buffer(u32 *p, u32 len) | ||
59 | { | ||
60 | while (len) { | ||
61 | *p = swab32(*p); | ||
62 | p++; | ||
63 | len -= 4; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
68 | { | ||
69 | struct ngene_channel *chan = priv; | ||
70 | |||
71 | |||
72 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
73 | if (chan->users > 0) | ||
74 | #endif | ||
75 | dvb_dmx_swfilter(&chan->demux, buf, len); | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; | ||
80 | |||
81 | void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
82 | { | ||
83 | struct ngene_channel *chan = priv; | ||
84 | struct ngene *dev = chan->dev; | ||
85 | u32 alen; | ||
86 | |||
87 | alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); | ||
88 | alen -= alen % 188; | ||
89 | |||
90 | if (alen < len) | ||
91 | FillTSBuffer(buf + alen, len - alen, flags); | ||
92 | else | ||
93 | alen = len; | ||
94 | dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); | ||
95 | if (flags & DF_SWAP32) | ||
96 | swap_buffer((u32 *)buf, alen); | ||
97 | wake_up_interruptible(&dev->tsout_rbuf.queue); | ||
98 | return buf; | ||
99 | } | ||
100 | |||
101 | |||
102 | |||
103 | int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
104 | { | ||
105 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
106 | struct ngene_channel *chan = dvbdmx->priv; | ||
107 | |||
108 | if (chan->users == 0) { | ||
109 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
110 | if (!chan->running) | ||
111 | #endif | ||
112 | set_transfer(chan, 1); | ||
113 | /* msleep(10); */ | ||
114 | } | ||
115 | |||
116 | return ++chan->users; | ||
117 | } | ||
118 | |||
119 | int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
120 | { | ||
121 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
122 | struct ngene_channel *chan = dvbdmx->priv; | ||
123 | |||
124 | if (--chan->users) | ||
125 | return chan->users; | ||
126 | |||
127 | #ifndef COMMAND_TIMEOUT_WORKAROUND | ||
128 | set_transfer(chan, 0); | ||
129 | #endif | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, | ||
135 | int (*start_feed)(struct dvb_demux_feed *), | ||
136 | int (*stop_feed)(struct dvb_demux_feed *), | ||
137 | void *priv) | ||
138 | { | ||
139 | dvbdemux->priv = priv; | ||
140 | |||
141 | dvbdemux->filternum = 256; | ||
142 | dvbdemux->feednum = 256; | ||
143 | dvbdemux->start_feed = start_feed; | ||
144 | dvbdemux->stop_feed = stop_feed; | ||
145 | dvbdemux->write_to_decoder = NULL; | ||
146 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | ||
147 | DMX_SECTION_FILTERING | | ||
148 | DMX_MEMORY_BASED_FILTERING); | ||
149 | return dvb_dmx_init(dvbdemux); | ||
150 | } | ||
151 | |||
152 | int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, | ||
153 | struct dvb_demux *dvbdemux, | ||
154 | struct dmx_frontend *hw_frontend, | ||
155 | struct dmx_frontend *mem_frontend, | ||
156 | struct dvb_adapter *dvb_adapter) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | dmxdev->filternum = 256; | ||
161 | dmxdev->demux = &dvbdemux->dmx; | ||
162 | dmxdev->capabilities = 0; | ||
163 | ret = dvb_dmxdev_init(dmxdev, dvb_adapter); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | hw_frontend->source = DMX_FRONTEND_0; | ||
168 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); | ||
169 | mem_frontend->source = DMX_MEMORY_FE; | ||
170 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); | ||
171 | return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); | ||
172 | } | ||
diff --git a/drivers/media/dvb/ngene/ngene-i2c.c b/drivers/media/dvb/ngene/ngene-i2c.c new file mode 100644 index 000000000000..2ef54ca6badd --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-i2c.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * ngene-i2c.c: nGene PCIe bridge driver i2c functions | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * Modifications for new nGene firmware, | ||
8 | * support for EEPROM-copying, | ||
9 | * support for new dual DVB-S2 card prototype | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 only, as published by the Free Software Foundation. | ||
15 | * | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
26 | * 02110-1301, USA | ||
27 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
28 | */ | ||
29 | |||
30 | /* FIXME - some of these can probably be removed */ | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/poll.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <asm/div64.h> | ||
38 | #include <linux/pci.h> | ||
39 | #include <linux/pci_ids.h> | ||
40 | #include <linux/smp_lock.h> | ||
41 | #include <linux/timer.h> | ||
42 | #include <linux/version.h> | ||
43 | #include <linux/byteorder/generic.h> | ||
44 | #include <linux/firmware.h> | ||
45 | #include <linux/vmalloc.h> | ||
46 | |||
47 | #include "ngene.h" | ||
48 | |||
49 | /* Firmware command for i2c operations */ | ||
50 | static int ngene_command_i2c_read(struct ngene *dev, u8 adr, | ||
51 | u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) | ||
52 | { | ||
53 | struct ngene_command com; | ||
54 | |||
55 | com.cmd.hdr.Opcode = CMD_I2C_READ; | ||
56 | com.cmd.hdr.Length = outlen + 3; | ||
57 | com.cmd.I2CRead.Device = adr << 1; | ||
58 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
59 | com.cmd.I2CRead.Data[outlen] = inlen; | ||
60 | com.cmd.I2CRead.Data[outlen + 1] = 0; | ||
61 | com.in_len = outlen + 3; | ||
62 | com.out_len = inlen + 1; | ||
63 | |||
64 | if (ngene_command(dev, &com) < 0) | ||
65 | return -EIO; | ||
66 | |||
67 | if ((com.cmd.raw8[0] >> 1) != adr) | ||
68 | return -EIO; | ||
69 | |||
70 | if (flag) | ||
71 | memcpy(in, com.cmd.raw8, inlen + 1); | ||
72 | else | ||
73 | memcpy(in, com.cmd.raw8 + 1, inlen); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int ngene_command_i2c_write(struct ngene *dev, u8 adr, | ||
78 | u8 *out, u8 outlen) | ||
79 | { | ||
80 | struct ngene_command com; | ||
81 | |||
82 | |||
83 | com.cmd.hdr.Opcode = CMD_I2C_WRITE; | ||
84 | com.cmd.hdr.Length = outlen + 1; | ||
85 | com.cmd.I2CRead.Device = adr << 1; | ||
86 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
87 | com.in_len = outlen + 1; | ||
88 | com.out_len = 1; | ||
89 | |||
90 | if (ngene_command(dev, &com) < 0) | ||
91 | return -EIO; | ||
92 | |||
93 | if (com.cmd.raw8[0] == 1) | ||
94 | return -EIO; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static void ngene_i2c_set_bus(struct ngene *dev, int bus) | ||
100 | { | ||
101 | if (!(dev->card_info->i2c_access & 2)) | ||
102 | return; | ||
103 | if (dev->i2c_current_bus == bus) | ||
104 | return; | ||
105 | |||
106 | switch (bus) { | ||
107 | case 0: | ||
108 | ngene_command_gpio_set(dev, 3, 0); | ||
109 | ngene_command_gpio_set(dev, 2, 1); | ||
110 | break; | ||
111 | |||
112 | case 1: | ||
113 | ngene_command_gpio_set(dev, 2, 0); | ||
114 | ngene_command_gpio_set(dev, 3, 1); | ||
115 | break; | ||
116 | } | ||
117 | dev->i2c_current_bus = bus; | ||
118 | } | ||
119 | |||
120 | static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, | ||
121 | struct i2c_msg msg[], int num) | ||
122 | { | ||
123 | struct ngene_channel *chan = | ||
124 | (struct ngene_channel *)i2c_get_adapdata(adapter); | ||
125 | struct ngene *dev = chan->dev; | ||
126 | |||
127 | down(&dev->i2c_switch_mutex); | ||
128 | ngene_i2c_set_bus(dev, chan->number); | ||
129 | |||
130 | if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) | ||
131 | if (!ngene_command_i2c_read(dev, msg[0].addr, | ||
132 | msg[0].buf, msg[0].len, | ||
133 | msg[1].buf, msg[1].len, 0)) | ||
134 | goto done; | ||
135 | |||
136 | if (num == 1 && !(msg[0].flags & I2C_M_RD)) | ||
137 | if (!ngene_command_i2c_write(dev, msg[0].addr, | ||
138 | msg[0].buf, msg[0].len)) | ||
139 | goto done; | ||
140 | if (num == 1 && (msg[0].flags & I2C_M_RD)) | ||
141 | if (!ngene_command_i2c_read(dev, msg[0].addr, NULL, 0, | ||
142 | msg[0].buf, msg[0].len, 0)) | ||
143 | goto done; | ||
144 | |||
145 | up(&dev->i2c_switch_mutex); | ||
146 | return -EIO; | ||
147 | |||
148 | done: | ||
149 | up(&dev->i2c_switch_mutex); | ||
150 | return num; | ||
151 | } | ||
152 | |||
153 | |||
154 | static u32 ngene_i2c_functionality(struct i2c_adapter *adap) | ||
155 | { | ||
156 | return I2C_FUNC_SMBUS_EMUL; | ||
157 | } | ||
158 | |||
159 | static struct i2c_algorithm ngene_i2c_algo = { | ||
160 | .master_xfer = ngene_i2c_master_xfer, | ||
161 | .functionality = ngene_i2c_functionality, | ||
162 | }; | ||
163 | |||
164 | int ngene_i2c_init(struct ngene *dev, int dev_nr) | ||
165 | { | ||
166 | struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); | ||
167 | |||
168 | i2c_set_adapdata(adap, &(dev->channel[dev_nr])); | ||
169 | adap->class = I2C_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; | ||
170 | |||
171 | strcpy(adap->name, "nGene"); | ||
172 | |||
173 | adap->algo = &ngene_i2c_algo; | ||
174 | adap->algo_data = (void *)&(dev->channel[dev_nr]); | ||
175 | adap->dev.parent = &dev->pci_dev->dev; | ||
176 | |||
177 | return i2c_add_adapter(adap); | ||
178 | } | ||
179 | |||
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index a7eb29846310..676fcbb79026 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h | |||
@@ -39,6 +39,8 @@ | |||
39 | #include "dvb_frontend.h" | 39 | #include "dvb_frontend.h" |
40 | #include "dvb_ringbuffer.h" | 40 | #include "dvb_ringbuffer.h" |
41 | 41 | ||
42 | #define DEVICE_NAME "ngene" | ||
43 | |||
42 | #define NGENE_VID 0x18c3 | 44 | #define NGENE_VID 0x18c3 |
43 | #define NGENE_PID 0x0720 | 45 | #define NGENE_PID 0x0720 |
44 | 46 | ||
@@ -752,6 +754,7 @@ struct ngene { | |||
752 | spinlock_t cmd_lock; | 754 | spinlock_t cmd_lock; |
753 | 755 | ||
754 | struct dvb_adapter adapter[MAX_STREAM]; | 756 | struct dvb_adapter adapter[MAX_STREAM]; |
757 | struct dvb_adapter *first_adapter; /* "one_adapter" modprobe opt */ | ||
755 | struct ngene_channel channel[MAX_STREAM]; | 758 | struct ngene_channel channel[MAX_STREAM]; |
756 | 759 | ||
757 | struct ngene_info *card_info; | 760 | struct ngene_info *card_info; |
@@ -853,6 +856,33 @@ struct ngene_buffer { | |||
853 | #endif | 856 | #endif |
854 | 857 | ||
855 | 858 | ||
859 | /* Provided by ngene-core.c */ | ||
860 | int __devinit ngene_probe(struct pci_dev *pci_dev, | ||
861 | const struct pci_device_id *id); | ||
862 | void __devexit ngene_remove(struct pci_dev *pdev); | ||
863 | int ngene_command(struct ngene *dev, struct ngene_command *com); | ||
864 | int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level); | ||
865 | void set_transfer(struct ngene_channel *chan, int state); | ||
866 | void FillTSBuffer(void *Buffer, int Length, u32 Flags); | ||
867 | |||
868 | /* Provided by ngene-i2c.c */ | ||
869 | int ngene_i2c_init(struct ngene *dev, int dev_nr); | ||
870 | |||
871 | /* Provided by ngene-dvb.c */ | ||
872 | void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags); | ||
873 | void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags); | ||
874 | int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
875 | int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
876 | int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, | ||
877 | int (*start_feed)(struct dvb_demux_feed *), | ||
878 | int (*stop_feed)(struct dvb_demux_feed *), | ||
879 | void *priv); | ||
880 | int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, | ||
881 | struct dvb_demux *dvbdemux, | ||
882 | struct dmx_frontend *hw_frontend, | ||
883 | struct dmx_frontend *mem_frontend, | ||
884 | struct dvb_adapter *dvb_adapter); | ||
885 | |||
856 | #endif | 886 | #endif |
857 | 887 | ||
858 | /* LocalWords: Endif | 888 | /* LocalWords: Endif |
diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index 6aded234aa61..69ad94934ec2 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * driver for Earthsoft PT1 | 2 | * driver for Earthsoft PT1/PT2 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | 4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> |
5 | * | 5 | * |
@@ -77,6 +77,10 @@ struct pt1 { | |||
77 | struct pt1_adapter *adaps[PT1_NR_ADAPS]; | 77 | struct pt1_adapter *adaps[PT1_NR_ADAPS]; |
78 | struct pt1_table *tables; | 78 | struct pt1_table *tables; |
79 | struct task_struct *kthread; | 79 | struct task_struct *kthread; |
80 | |||
81 | struct mutex lock; | ||
82 | int power; | ||
83 | int reset; | ||
80 | }; | 84 | }; |
81 | 85 | ||
82 | struct pt1_adapter { | 86 | struct pt1_adapter { |
@@ -95,6 +99,11 @@ struct pt1_adapter { | |||
95 | struct dvb_frontend *fe; | 99 | struct dvb_frontend *fe; |
96 | int (*orig_set_voltage)(struct dvb_frontend *fe, | 100 | int (*orig_set_voltage)(struct dvb_frontend *fe, |
97 | fe_sec_voltage_t voltage); | 101 | fe_sec_voltage_t voltage); |
102 | int (*orig_sleep)(struct dvb_frontend *fe); | ||
103 | int (*orig_init)(struct dvb_frontend *fe); | ||
104 | |||
105 | fe_sec_voltage_t voltage; | ||
106 | int sleep; | ||
98 | }; | 107 | }; |
99 | 108 | ||
100 | #define pt1_printk(level, pt1, format, arg...) \ | 109 | #define pt1_printk(level, pt1, format, arg...) \ |
@@ -219,8 +228,10 @@ static int pt1_do_enable_ram(struct pt1 *pt1) | |||
219 | static int pt1_enable_ram(struct pt1 *pt1) | 228 | static int pt1_enable_ram(struct pt1 *pt1) |
220 | { | 229 | { |
221 | int i, ret; | 230 | int i, ret; |
231 | int phase; | ||
222 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | 232 | schedule_timeout_uninterruptible((HZ + 999) / 1000); |
223 | for (i = 0; i < 10; i++) { | 233 | phase = pt1->pdev->device == 0x211a ? 128 : 166; |
234 | for (i = 0; i < phase; i++) { | ||
224 | ret = pt1_do_enable_ram(pt1); | 235 | ret = pt1_do_enable_ram(pt1); |
225 | if (ret < 0) | 236 | if (ret < 0) |
226 | return ret; | 237 | return ret; |
@@ -485,33 +496,47 @@ static int pt1_stop_feed(struct dvb_demux_feed *feed) | |||
485 | } | 496 | } |
486 | 497 | ||
487 | static void | 498 | static void |
488 | pt1_set_power(struct pt1 *pt1, int power, int lnb, int reset) | 499 | pt1_update_power(struct pt1 *pt1) |
489 | { | 500 | { |
490 | pt1_write_reg(pt1, 1, power | lnb << 1 | !reset << 3); | 501 | int bits; |
502 | int i; | ||
503 | struct pt1_adapter *adap; | ||
504 | static const int sleep_bits[] = { | ||
505 | 1 << 4, | ||
506 | 1 << 6 | 1 << 7, | ||
507 | 1 << 5, | ||
508 | 1 << 6 | 1 << 8, | ||
509 | }; | ||
510 | |||
511 | bits = pt1->power | !pt1->reset << 3; | ||
512 | mutex_lock(&pt1->lock); | ||
513 | for (i = 0; i < PT1_NR_ADAPS; i++) { | ||
514 | adap = pt1->adaps[i]; | ||
515 | switch (adap->voltage) { | ||
516 | case SEC_VOLTAGE_13: /* actually 11V */ | ||
517 | bits |= 1 << 1; | ||
518 | break; | ||
519 | case SEC_VOLTAGE_18: /* actually 15V */ | ||
520 | bits |= 1 << 1 | 1 << 2; | ||
521 | break; | ||
522 | default: | ||
523 | break; | ||
524 | } | ||
525 | |||
526 | /* XXX: The bits should be changed depending on adap->sleep. */ | ||
527 | bits |= sleep_bits[i]; | ||
528 | } | ||
529 | pt1_write_reg(pt1, 1, bits); | ||
530 | mutex_unlock(&pt1->lock); | ||
491 | } | 531 | } |
492 | 532 | ||
493 | static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 533 | static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
494 | { | 534 | { |
495 | struct pt1_adapter *adap; | 535 | struct pt1_adapter *adap; |
496 | int lnb; | ||
497 | 536 | ||
498 | adap = container_of(fe->dvb, struct pt1_adapter, adap); | 537 | adap = container_of(fe->dvb, struct pt1_adapter, adap); |
499 | 538 | adap->voltage = voltage; | |
500 | switch (voltage) { | 539 | pt1_update_power(adap->pt1); |
501 | case SEC_VOLTAGE_13: /* actually 11V */ | ||
502 | lnb = 2; | ||
503 | break; | ||
504 | case SEC_VOLTAGE_18: /* actually 15V */ | ||
505 | lnb = 3; | ||
506 | break; | ||
507 | case SEC_VOLTAGE_OFF: | ||
508 | lnb = 0; | ||
509 | break; | ||
510 | default: | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | |||
514 | pt1_set_power(adap->pt1, 1, lnb, 0); | ||
515 | 540 | ||
516 | if (adap->orig_set_voltage) | 541 | if (adap->orig_set_voltage) |
517 | return adap->orig_set_voltage(fe, voltage); | 542 | return adap->orig_set_voltage(fe, voltage); |
@@ -519,9 +544,37 @@ static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | |||
519 | return 0; | 544 | return 0; |
520 | } | 545 | } |
521 | 546 | ||
547 | static int pt1_sleep(struct dvb_frontend *fe) | ||
548 | { | ||
549 | struct pt1_adapter *adap; | ||
550 | |||
551 | adap = container_of(fe->dvb, struct pt1_adapter, adap); | ||
552 | adap->sleep = 1; | ||
553 | pt1_update_power(adap->pt1); | ||
554 | |||
555 | if (adap->orig_sleep) | ||
556 | return adap->orig_sleep(fe); | ||
557 | else | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int pt1_wakeup(struct dvb_frontend *fe) | ||
562 | { | ||
563 | struct pt1_adapter *adap; | ||
564 | |||
565 | adap = container_of(fe->dvb, struct pt1_adapter, adap); | ||
566 | adap->sleep = 0; | ||
567 | pt1_update_power(adap->pt1); | ||
568 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | ||
569 | |||
570 | if (adap->orig_init) | ||
571 | return adap->orig_init(fe); | ||
572 | else | ||
573 | return 0; | ||
574 | } | ||
575 | |||
522 | static void pt1_free_adapter(struct pt1_adapter *adap) | 576 | static void pt1_free_adapter(struct pt1_adapter *adap) |
523 | { | 577 | { |
524 | dvb_unregister_frontend(adap->fe); | ||
525 | dvb_net_release(&adap->net); | 578 | dvb_net_release(&adap->net); |
526 | adap->demux.dmx.close(&adap->demux.dmx); | 579 | adap->demux.dmx.close(&adap->demux.dmx); |
527 | dvb_dmxdev_release(&adap->dmxdev); | 580 | dvb_dmxdev_release(&adap->dmxdev); |
@@ -534,7 +587,7 @@ static void pt1_free_adapter(struct pt1_adapter *adap) | |||
534 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 587 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
535 | 588 | ||
536 | static struct pt1_adapter * | 589 | static struct pt1_adapter * |
537 | pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) | 590 | pt1_alloc_adapter(struct pt1 *pt1) |
538 | { | 591 | { |
539 | struct pt1_adapter *adap; | 592 | struct pt1_adapter *adap; |
540 | void *buf; | 593 | void *buf; |
@@ -551,8 +604,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) | |||
551 | 604 | ||
552 | adap->pt1 = pt1; | 605 | adap->pt1 = pt1; |
553 | 606 | ||
554 | adap->orig_set_voltage = fe->ops.set_voltage; | 607 | adap->voltage = SEC_VOLTAGE_OFF; |
555 | fe->ops.set_voltage = pt1_set_voltage; | 608 | adap->sleep = 1; |
556 | 609 | ||
557 | buf = (u8 *)__get_free_page(GFP_KERNEL); | 610 | buf = (u8 *)__get_free_page(GFP_KERNEL); |
558 | if (!buf) { | 611 | if (!buf) { |
@@ -593,17 +646,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) | |||
593 | 646 | ||
594 | dvb_net_init(dvb_adap, &adap->net, &demux->dmx); | 647 | dvb_net_init(dvb_adap, &adap->net, &demux->dmx); |
595 | 648 | ||
596 | ret = dvb_register_frontend(dvb_adap, fe); | ||
597 | if (ret < 0) | ||
598 | goto err_net_release; | ||
599 | adap->fe = fe; | ||
600 | |||
601 | return adap; | 649 | return adap; |
602 | 650 | ||
603 | err_net_release: | ||
604 | dvb_net_release(&adap->net); | ||
605 | adap->demux.dmx.close(&adap->demux.dmx); | ||
606 | dvb_dmxdev_release(&adap->dmxdev); | ||
607 | err_dmx_release: | 651 | err_dmx_release: |
608 | dvb_dmx_release(demux); | 652 | dvb_dmx_release(demux); |
609 | err_unregister_adapter: | 653 | err_unregister_adapter: |
@@ -623,6 +667,62 @@ static void pt1_cleanup_adapters(struct pt1 *pt1) | |||
623 | pt1_free_adapter(pt1->adaps[i]); | 667 | pt1_free_adapter(pt1->adaps[i]); |
624 | } | 668 | } |
625 | 669 | ||
670 | static int pt1_init_adapters(struct pt1 *pt1) | ||
671 | { | ||
672 | int i; | ||
673 | struct pt1_adapter *adap; | ||
674 | int ret; | ||
675 | |||
676 | for (i = 0; i < PT1_NR_ADAPS; i++) { | ||
677 | adap = pt1_alloc_adapter(pt1); | ||
678 | if (IS_ERR(adap)) { | ||
679 | ret = PTR_ERR(adap); | ||
680 | goto err; | ||
681 | } | ||
682 | |||
683 | adap->index = i; | ||
684 | pt1->adaps[i] = adap; | ||
685 | } | ||
686 | return 0; | ||
687 | |||
688 | err: | ||
689 | while (i--) | ||
690 | pt1_free_adapter(pt1->adaps[i]); | ||
691 | |||
692 | return ret; | ||
693 | } | ||
694 | |||
695 | static void pt1_cleanup_frontend(struct pt1_adapter *adap) | ||
696 | { | ||
697 | dvb_unregister_frontend(adap->fe); | ||
698 | } | ||
699 | |||
700 | static int pt1_init_frontend(struct pt1_adapter *adap, struct dvb_frontend *fe) | ||
701 | { | ||
702 | int ret; | ||
703 | |||
704 | adap->orig_set_voltage = fe->ops.set_voltage; | ||
705 | adap->orig_sleep = fe->ops.sleep; | ||
706 | adap->orig_init = fe->ops.init; | ||
707 | fe->ops.set_voltage = pt1_set_voltage; | ||
708 | fe->ops.sleep = pt1_sleep; | ||
709 | fe->ops.init = pt1_wakeup; | ||
710 | |||
711 | ret = dvb_register_frontend(&adap->adap, fe); | ||
712 | if (ret < 0) | ||
713 | return ret; | ||
714 | |||
715 | adap->fe = fe; | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | static void pt1_cleanup_frontends(struct pt1 *pt1) | ||
720 | { | ||
721 | int i; | ||
722 | for (i = 0; i < PT1_NR_ADAPS; i++) | ||
723 | pt1_cleanup_frontend(pt1->adaps[i]); | ||
724 | } | ||
725 | |||
626 | struct pt1_config { | 726 | struct pt1_config { |
627 | struct va1j5jf8007s_config va1j5jf8007s_config; | 727 | struct va1j5jf8007s_config va1j5jf8007s_config; |
628 | struct va1j5jf8007t_config va1j5jf8007t_config; | 728 | struct va1j5jf8007t_config va1j5jf8007t_config; |
@@ -630,29 +730,63 @@ struct pt1_config { | |||
630 | 730 | ||
631 | static const struct pt1_config pt1_configs[2] = { | 731 | static const struct pt1_config pt1_configs[2] = { |
632 | { | 732 | { |
633 | { .demod_address = 0x1b }, | 733 | { |
634 | { .demod_address = 0x1a }, | 734 | .demod_address = 0x1b, |
735 | .frequency = VA1J5JF8007S_20MHZ, | ||
736 | }, | ||
737 | { | ||
738 | .demod_address = 0x1a, | ||
739 | .frequency = VA1J5JF8007T_20MHZ, | ||
740 | }, | ||
635 | }, { | 741 | }, { |
636 | { .demod_address = 0x19 }, | 742 | { |
637 | { .demod_address = 0x18 }, | 743 | .demod_address = 0x19, |
744 | .frequency = VA1J5JF8007S_20MHZ, | ||
745 | }, | ||
746 | { | ||
747 | .demod_address = 0x18, | ||
748 | .frequency = VA1J5JF8007T_20MHZ, | ||
749 | }, | ||
638 | }, | 750 | }, |
639 | }; | 751 | }; |
640 | 752 | ||
641 | static int pt1_init_adapters(struct pt1 *pt1) | 753 | static const struct pt1_config pt2_configs[2] = { |
754 | { | ||
755 | { | ||
756 | .demod_address = 0x1b, | ||
757 | .frequency = VA1J5JF8007S_25MHZ, | ||
758 | }, | ||
759 | { | ||
760 | .demod_address = 0x1a, | ||
761 | .frequency = VA1J5JF8007T_25MHZ, | ||
762 | }, | ||
763 | }, { | ||
764 | { | ||
765 | .demod_address = 0x19, | ||
766 | .frequency = VA1J5JF8007S_25MHZ, | ||
767 | }, | ||
768 | { | ||
769 | .demod_address = 0x18, | ||
770 | .frequency = VA1J5JF8007T_25MHZ, | ||
771 | }, | ||
772 | }, | ||
773 | }; | ||
774 | |||
775 | static int pt1_init_frontends(struct pt1 *pt1) | ||
642 | { | 776 | { |
643 | int i, j; | 777 | int i, j; |
644 | struct i2c_adapter *i2c_adap; | 778 | struct i2c_adapter *i2c_adap; |
645 | const struct pt1_config *config; | 779 | const struct pt1_config *configs, *config; |
646 | struct dvb_frontend *fe[4]; | 780 | struct dvb_frontend *fe[4]; |
647 | struct pt1_adapter *adap; | ||
648 | int ret; | 781 | int ret; |
649 | 782 | ||
650 | i = 0; | 783 | i = 0; |
651 | j = 0; | 784 | j = 0; |
652 | 785 | ||
653 | i2c_adap = &pt1->i2c_adap; | 786 | i2c_adap = &pt1->i2c_adap; |
787 | configs = pt1->pdev->device == 0x211a ? pt1_configs : pt2_configs; | ||
654 | do { | 788 | do { |
655 | config = &pt1_configs[i / 2]; | 789 | config = &configs[i / 2]; |
656 | 790 | ||
657 | fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config, | 791 | fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config, |
658 | i2c_adap); | 792 | i2c_adap); |
@@ -681,11 +815,9 @@ static int pt1_init_adapters(struct pt1 *pt1) | |||
681 | } while (i < 4); | 815 | } while (i < 4); |
682 | 816 | ||
683 | do { | 817 | do { |
684 | adap = pt1_alloc_adapter(pt1, fe[j]); | 818 | ret = pt1_init_frontend(pt1->adaps[j], fe[j]); |
685 | if (IS_ERR(adap)) | 819 | if (ret < 0) |
686 | goto err; | 820 | goto err; |
687 | adap->index = j; | ||
688 | pt1->adaps[j] = adap; | ||
689 | } while (++j < 4); | 821 | } while (++j < 4); |
690 | 822 | ||
691 | return 0; | 823 | return 0; |
@@ -695,7 +827,7 @@ err: | |||
695 | fe[i]->ops.release(fe[i]); | 827 | fe[i]->ops.release(fe[i]); |
696 | 828 | ||
697 | while (j--) | 829 | while (j--) |
698 | pt1_free_adapter(pt1->adaps[j]); | 830 | dvb_unregister_frontend(fe[j]); |
699 | 831 | ||
700 | return ret; | 832 | return ret; |
701 | } | 833 | } |
@@ -890,9 +1022,12 @@ static void __devexit pt1_remove(struct pci_dev *pdev) | |||
890 | 1022 | ||
891 | kthread_stop(pt1->kthread); | 1023 | kthread_stop(pt1->kthread); |
892 | pt1_cleanup_tables(pt1); | 1024 | pt1_cleanup_tables(pt1); |
893 | pt1_cleanup_adapters(pt1); | 1025 | pt1_cleanup_frontends(pt1); |
894 | pt1_disable_ram(pt1); | 1026 | pt1_disable_ram(pt1); |
895 | pt1_set_power(pt1, 0, 0, 1); | 1027 | pt1->power = 0; |
1028 | pt1->reset = 1; | ||
1029 | pt1_update_power(pt1); | ||
1030 | pt1_cleanup_adapters(pt1); | ||
896 | i2c_del_adapter(&pt1->i2c_adap); | 1031 | i2c_del_adapter(&pt1->i2c_adap); |
897 | pci_set_drvdata(pdev, NULL); | 1032 | pci_set_drvdata(pdev, NULL); |
898 | kfree(pt1); | 1033 | kfree(pt1); |
@@ -936,10 +1071,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
936 | goto err_pci_iounmap; | 1071 | goto err_pci_iounmap; |
937 | } | 1072 | } |
938 | 1073 | ||
1074 | mutex_init(&pt1->lock); | ||
939 | pt1->pdev = pdev; | 1075 | pt1->pdev = pdev; |
940 | pt1->regs = regs; | 1076 | pt1->regs = regs; |
941 | pci_set_drvdata(pdev, pt1); | 1077 | pci_set_drvdata(pdev, pt1); |
942 | 1078 | ||
1079 | ret = pt1_init_adapters(pt1); | ||
1080 | if (ret < 0) | ||
1081 | goto err_kfree; | ||
1082 | |||
1083 | mutex_init(&pt1->lock); | ||
1084 | |||
1085 | pt1->power = 0; | ||
1086 | pt1->reset = 1; | ||
1087 | pt1_update_power(pt1); | ||
1088 | |||
943 | i2c_adap = &pt1->i2c_adap; | 1089 | i2c_adap = &pt1->i2c_adap; |
944 | i2c_adap->class = I2C_CLASS_TV_DIGITAL; | 1090 | i2c_adap->class = I2C_CLASS_TV_DIGITAL; |
945 | i2c_adap->algo = &pt1_i2c_algo; | 1091 | i2c_adap->algo = &pt1_i2c_algo; |
@@ -948,9 +1094,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
948 | i2c_set_adapdata(i2c_adap, pt1); | 1094 | i2c_set_adapdata(i2c_adap, pt1); |
949 | ret = i2c_add_adapter(i2c_adap); | 1095 | ret = i2c_add_adapter(i2c_adap); |
950 | if (ret < 0) | 1096 | if (ret < 0) |
951 | goto err_kfree; | 1097 | goto err_pt1_cleanup_adapters; |
952 | |||
953 | pt1_set_power(pt1, 0, 0, 1); | ||
954 | 1098 | ||
955 | pt1_i2c_init(pt1); | 1099 | pt1_i2c_init(pt1); |
956 | pt1_i2c_wait(pt1); | 1100 | pt1_i2c_wait(pt1); |
@@ -979,19 +1123,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
979 | 1123 | ||
980 | pt1_init_streams(pt1); | 1124 | pt1_init_streams(pt1); |
981 | 1125 | ||
982 | pt1_set_power(pt1, 1, 0, 1); | 1126 | pt1->power = 1; |
1127 | pt1_update_power(pt1); | ||
983 | schedule_timeout_uninterruptible((HZ + 49) / 50); | 1128 | schedule_timeout_uninterruptible((HZ + 49) / 50); |
984 | 1129 | ||
985 | pt1_set_power(pt1, 1, 0, 0); | 1130 | pt1->reset = 0; |
1131 | pt1_update_power(pt1); | ||
986 | schedule_timeout_uninterruptible((HZ + 999) / 1000); | 1132 | schedule_timeout_uninterruptible((HZ + 999) / 1000); |
987 | 1133 | ||
988 | ret = pt1_init_adapters(pt1); | 1134 | ret = pt1_init_frontends(pt1); |
989 | if (ret < 0) | 1135 | if (ret < 0) |
990 | goto err_pt1_disable_ram; | 1136 | goto err_pt1_disable_ram; |
991 | 1137 | ||
992 | ret = pt1_init_tables(pt1); | 1138 | ret = pt1_init_tables(pt1); |
993 | if (ret < 0) | 1139 | if (ret < 0) |
994 | goto err_pt1_cleanup_adapters; | 1140 | goto err_pt1_cleanup_frontends; |
995 | 1141 | ||
996 | kthread = kthread_run(pt1_thread, pt1, "pt1"); | 1142 | kthread = kthread_run(pt1_thread, pt1, "pt1"); |
997 | if (IS_ERR(kthread)) { | 1143 | if (IS_ERR(kthread)) { |
@@ -1004,11 +1150,15 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1004 | 1150 | ||
1005 | err_pt1_cleanup_tables: | 1151 | err_pt1_cleanup_tables: |
1006 | pt1_cleanup_tables(pt1); | 1152 | pt1_cleanup_tables(pt1); |
1007 | err_pt1_cleanup_adapters: | 1153 | err_pt1_cleanup_frontends: |
1008 | pt1_cleanup_adapters(pt1); | 1154 | pt1_cleanup_frontends(pt1); |
1009 | err_pt1_disable_ram: | 1155 | err_pt1_disable_ram: |
1010 | pt1_disable_ram(pt1); | 1156 | pt1_disable_ram(pt1); |
1011 | pt1_set_power(pt1, 0, 0, 1); | 1157 | pt1->power = 0; |
1158 | pt1->reset = 1; | ||
1159 | pt1_update_power(pt1); | ||
1160 | err_pt1_cleanup_adapters: | ||
1161 | pt1_cleanup_adapters(pt1); | ||
1012 | err_i2c_del_adapter: | 1162 | err_i2c_del_adapter: |
1013 | i2c_del_adapter(i2c_adap); | 1163 | i2c_del_adapter(i2c_adap); |
1014 | err_kfree: | 1164 | err_kfree: |
@@ -1027,6 +1177,7 @@ err: | |||
1027 | 1177 | ||
1028 | static struct pci_device_id pt1_id_table[] = { | 1178 | static struct pci_device_id pt1_id_table[] = { |
1029 | { PCI_DEVICE(0x10ee, 0x211a) }, | 1179 | { PCI_DEVICE(0x10ee, 0x211a) }, |
1180 | { PCI_DEVICE(0x10ee, 0x222a) }, | ||
1030 | { }, | 1181 | { }, |
1031 | }; | 1182 | }; |
1032 | MODULE_DEVICE_TABLE(pci, pt1_id_table); | 1183 | MODULE_DEVICE_TABLE(pci, pt1_id_table); |
@@ -1054,5 +1205,5 @@ module_init(pt1_init); | |||
1054 | module_exit(pt1_cleanup); | 1205 | module_exit(pt1_cleanup); |
1055 | 1206 | ||
1056 | MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>"); | 1207 | MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>"); |
1057 | MODULE_DESCRIPTION("Earthsoft PT1 Driver"); | 1208 | MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver"); |
1058 | MODULE_LICENSE("GPL"); | 1209 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c index fc6594996e79..451641c0c1d2 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.c +++ b/drivers/media/dvb/pt1/va1j5jf8007s.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ISDB-S driver for VA1J5JF8007 | 2 | * ISDB-S driver for VA1J5JF8007/VA1J5JF8011 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | 4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> |
5 | * | 5 | * |
@@ -580,7 +580,7 @@ static void va1j5jf8007s_release(struct dvb_frontend *fe) | |||
580 | 580 | ||
581 | static struct dvb_frontend_ops va1j5jf8007s_ops = { | 581 | static struct dvb_frontend_ops va1j5jf8007s_ops = { |
582 | .info = { | 582 | .info = { |
583 | .name = "VA1J5JF8007 ISDB-S", | 583 | .name = "VA1J5JF8007/VA1J5JF8011 ISDB-S", |
584 | .type = FE_QPSK, | 584 | .type = FE_QPSK, |
585 | .frequency_min = 950000, | 585 | .frequency_min = 950000, |
586 | .frequency_max = 2150000, | 586 | .frequency_max = 2150000, |
@@ -628,28 +628,50 @@ static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state) | |||
628 | return 0; | 628 | return 0; |
629 | } | 629 | } |
630 | 630 | ||
631 | static const u8 va1j5jf8007s_prepare_bufs[][2] = { | 631 | static const u8 va1j5jf8007s_20mhz_prepare_bufs[][2] = { |
632 | {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, | 632 | {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, |
633 | {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, | 633 | {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, |
634 | {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, | 634 | {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, |
635 | {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0}, | 635 | {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0}, |
636 | }; | 636 | }; |
637 | 637 | ||
638 | static const u8 va1j5jf8007s_25mhz_prepare_bufs[][2] = { | ||
639 | {0x04, 0x02}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, {0x1c, 0x0a}, | ||
640 | {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, {0x52, 0x89}, | ||
641 | {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, {0x87, 0x04}, | ||
642 | {0x8e, 0x26}, {0xa3, 0xf7}, {0xa5, 0xc0}, | ||
643 | }; | ||
644 | |||
638 | static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state) | 645 | static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state) |
639 | { | 646 | { |
647 | const u8 (*bufs)[2]; | ||
648 | int size; | ||
640 | u8 addr; | 649 | u8 addr; |
641 | u8 buf[2]; | 650 | u8 buf[2]; |
642 | struct i2c_msg msg; | 651 | struct i2c_msg msg; |
643 | int i; | 652 | int i; |
644 | 653 | ||
654 | switch (state->config->frequency) { | ||
655 | case VA1J5JF8007S_20MHZ: | ||
656 | bufs = va1j5jf8007s_20mhz_prepare_bufs; | ||
657 | size = ARRAY_SIZE(va1j5jf8007s_20mhz_prepare_bufs); | ||
658 | break; | ||
659 | case VA1J5JF8007S_25MHZ: | ||
660 | bufs = va1j5jf8007s_25mhz_prepare_bufs; | ||
661 | size = ARRAY_SIZE(va1j5jf8007s_25mhz_prepare_bufs); | ||
662 | break; | ||
663 | default: | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
645 | addr = state->config->demod_address; | 667 | addr = state->config->demod_address; |
646 | 668 | ||
647 | msg.addr = addr; | 669 | msg.addr = addr; |
648 | msg.flags = 0; | 670 | msg.flags = 0; |
649 | msg.len = 2; | 671 | msg.len = 2; |
650 | msg.buf = buf; | 672 | msg.buf = buf; |
651 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_prepare_bufs); i++) { | 673 | for (i = 0; i < size; i++) { |
652 | memcpy(buf, va1j5jf8007s_prepare_bufs[i], sizeof(buf)); | 674 | memcpy(buf, bufs[i], sizeof(buf)); |
653 | if (i2c_transfer(state->adap, &msg, 1) != 1) | 675 | if (i2c_transfer(state->adap, &msg, 1) != 1) |
654 | return -EREMOTEIO; | 676 | return -EREMOTEIO; |
655 | } | 677 | } |
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.h b/drivers/media/dvb/pt1/va1j5jf8007s.h index aa228a816353..b7d6f05a0e02 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.h +++ b/drivers/media/dvb/pt1/va1j5jf8007s.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ISDB-S driver for VA1J5JF8007 | 2 | * ISDB-S driver for VA1J5JF8007/VA1J5JF8011 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | 4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> |
5 | * | 5 | * |
@@ -24,8 +24,14 @@ | |||
24 | #ifndef VA1J5JF8007S_H | 24 | #ifndef VA1J5JF8007S_H |
25 | #define VA1J5JF8007S_H | 25 | #define VA1J5JF8007S_H |
26 | 26 | ||
27 | enum va1j5jf8007s_frequency { | ||
28 | VA1J5JF8007S_20MHZ, | ||
29 | VA1J5JF8007S_25MHZ, | ||
30 | }; | ||
31 | |||
27 | struct va1j5jf8007s_config { | 32 | struct va1j5jf8007s_config { |
28 | u8 demod_address; | 33 | u8 demod_address; |
34 | enum va1j5jf8007s_frequency frequency; | ||
29 | }; | 35 | }; |
30 | 36 | ||
31 | struct i2c_adapter; | 37 | struct i2c_adapter; |
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c index 3db4f3e34e8f..0f085c3e571b 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.c +++ b/drivers/media/dvb/pt1/va1j5jf8007t.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ISDB-T driver for VA1J5JF8007 | 2 | * ISDB-T driver for VA1J5JF8007/VA1J5JF8011 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | 4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> |
5 | * | 5 | * |
@@ -429,7 +429,7 @@ static void va1j5jf8007t_release(struct dvb_frontend *fe) | |||
429 | 429 | ||
430 | static struct dvb_frontend_ops va1j5jf8007t_ops = { | 430 | static struct dvb_frontend_ops va1j5jf8007t_ops = { |
431 | .info = { | 431 | .info = { |
432 | .name = "VA1J5JF8007 ISDB-T", | 432 | .name = "VA1J5JF8007/VA1J5JF8011 ISDB-T", |
433 | .type = FE_OFDM, | 433 | .type = FE_OFDM, |
434 | .frequency_min = 90000000, | 434 | .frequency_min = 90000000, |
435 | .frequency_max = 770000000, | 435 | .frequency_max = 770000000, |
@@ -448,29 +448,50 @@ static struct dvb_frontend_ops va1j5jf8007t_ops = { | |||
448 | .release = va1j5jf8007t_release, | 448 | .release = va1j5jf8007t_release, |
449 | }; | 449 | }; |
450 | 450 | ||
451 | static const u8 va1j5jf8007t_prepare_bufs[][2] = { | 451 | static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = { |
452 | {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, | 452 | {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, |
453 | {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00}, | 453 | {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00}, |
454 | {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03}, | 454 | {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03}, |
455 | {0xef, 0x01} | 455 | {0xef, 0x01} |
456 | }; | 456 | }; |
457 | 457 | ||
458 | static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = { | ||
459 | {0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83}, | ||
460 | {0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c}, | ||
461 | {0x77, 0x03}, {0xef, 0x01} | ||
462 | }; | ||
463 | |||
458 | int va1j5jf8007t_prepare(struct dvb_frontend *fe) | 464 | int va1j5jf8007t_prepare(struct dvb_frontend *fe) |
459 | { | 465 | { |
460 | struct va1j5jf8007t_state *state; | 466 | struct va1j5jf8007t_state *state; |
467 | const u8 (*bufs)[2]; | ||
468 | int size; | ||
461 | u8 buf[2]; | 469 | u8 buf[2]; |
462 | struct i2c_msg msg; | 470 | struct i2c_msg msg; |
463 | int i; | 471 | int i; |
464 | 472 | ||
465 | state = fe->demodulator_priv; | 473 | state = fe->demodulator_priv; |
466 | 474 | ||
475 | switch (state->config->frequency) { | ||
476 | case VA1J5JF8007T_20MHZ: | ||
477 | bufs = va1j5jf8007t_20mhz_prepare_bufs; | ||
478 | size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs); | ||
479 | break; | ||
480 | case VA1J5JF8007T_25MHZ: | ||
481 | bufs = va1j5jf8007t_25mhz_prepare_bufs; | ||
482 | size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs); | ||
483 | break; | ||
484 | default: | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
467 | msg.addr = state->config->demod_address; | 488 | msg.addr = state->config->demod_address; |
468 | msg.flags = 0; | 489 | msg.flags = 0; |
469 | msg.len = sizeof(buf); | 490 | msg.len = sizeof(buf); |
470 | msg.buf = buf; | 491 | msg.buf = buf; |
471 | 492 | ||
472 | for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_prepare_bufs); i++) { | 493 | for (i = 0; i < size; i++) { |
473 | memcpy(buf, va1j5jf8007t_prepare_bufs[i], sizeof(buf)); | 494 | memcpy(buf, bufs[i], sizeof(buf)); |
474 | if (i2c_transfer(state->adap, &msg, 1) != 1) | 495 | if (i2c_transfer(state->adap, &msg, 1) != 1) |
475 | return -EREMOTEIO; | 496 | return -EREMOTEIO; |
476 | } | 497 | } |
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.h b/drivers/media/dvb/pt1/va1j5jf8007t.h index ed49906f7769..2903be519ef5 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.h +++ b/drivers/media/dvb/pt1/va1j5jf8007t.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ISDB-T driver for VA1J5JF8007 | 2 | * ISDB-T driver for VA1J5JF8007/VA1J5JF8011 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> | 4 | * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> |
5 | * | 5 | * |
@@ -24,8 +24,14 @@ | |||
24 | #ifndef VA1J5JF8007T_H | 24 | #ifndef VA1J5JF8007T_H |
25 | #define VA1J5JF8007T_H | 25 | #define VA1J5JF8007T_H |
26 | 26 | ||
27 | enum va1j5jf8007t_frequency { | ||
28 | VA1J5JF8007T_20MHZ, | ||
29 | VA1J5JF8007T_25MHZ, | ||
30 | }; | ||
31 | |||
27 | struct va1j5jf8007t_config { | 32 | struct va1j5jf8007t_config { |
28 | u8 demod_address; | 33 | u8 demod_address; |
34 | enum va1j5jf8007t_frequency frequency; | ||
29 | }; | 35 | }; |
30 | 36 | ||
31 | struct i2c_adapter; | 37 | struct i2c_adapter; |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 49c2a817a06f..461714396331 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
36 | #include <linux/input.h> | 36 | #include <linux/input.h> |
37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
38 | #include <media/ir-common.h> | 38 | #include <media/ir-core.h> |
39 | 39 | ||
40 | #include "budget.h" | 40 | #include "budget.h" |
41 | 41 | ||
@@ -54,6 +54,8 @@ | |||
54 | #include "tda1002x.h" | 54 | #include "tda1002x.h" |
55 | #include "tda827x.h" | 55 | #include "tda827x.h" |
56 | 56 | ||
57 | #define MODULE_NAME "budget_ci" | ||
58 | |||
57 | /* | 59 | /* |
58 | * Regarding DEBIADDR_IR: | 60 | * Regarding DEBIADDR_IR: |
59 | * Some CI modules hang if random addresses are read. | 61 | * Some CI modules hang if random addresses are read. |
@@ -80,12 +82,6 @@ | |||
80 | #define SLOTSTATUS_READY 8 | 82 | #define SLOTSTATUS_READY 8 |
81 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) | 83 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
82 | 84 | ||
83 | /* | ||
84 | * Milliseconds during which a key is regarded as pressed. | ||
85 | * If an identical command arrives within this time, the timer will start over. | ||
86 | */ | ||
87 | #define IR_KEYPRESS_TIMEOUT 250 | ||
88 | |||
89 | /* RC5 device wildcard */ | 85 | /* RC5 device wildcard */ |
90 | #define IR_DEVICE_ANY 255 | 86 | #define IR_DEVICE_ANY 255 |
91 | 87 | ||
@@ -102,12 +98,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
102 | struct budget_ci_ir { | 98 | struct budget_ci_ir { |
103 | struct input_dev *dev; | 99 | struct input_dev *dev; |
104 | struct tasklet_struct msp430_irq_tasklet; | 100 | struct tasklet_struct msp430_irq_tasklet; |
105 | struct timer_list timer_keyup; | ||
106 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ | 101 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ |
107 | char phys[32]; | 102 | char phys[32]; |
108 | struct ir_input_state state; | ||
109 | int rc5_device; | 103 | int rc5_device; |
110 | u32 last_raw; | ||
111 | u32 ir_key; | 104 | u32 ir_key; |
112 | bool have_command; | 105 | bool have_command; |
113 | }; | 106 | }; |
@@ -122,18 +115,11 @@ struct budget_ci { | |||
122 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ | 115 | u8 tuner_pll_address; /* used for philips_tdm1316l configs */ |
123 | }; | 116 | }; |
124 | 117 | ||
125 | static void msp430_ir_keyup(unsigned long data) | ||
126 | { | ||
127 | struct budget_ci_ir *ir = (struct budget_ci_ir *) data; | ||
128 | ir_input_nokey(ir->dev, &ir->state); | ||
129 | } | ||
130 | |||
131 | static void msp430_ir_interrupt(unsigned long data) | 118 | static void msp430_ir_interrupt(unsigned long data) |
132 | { | 119 | { |
133 | struct budget_ci *budget_ci = (struct budget_ci *) data; | 120 | struct budget_ci *budget_ci = (struct budget_ci *) data; |
134 | struct input_dev *dev = budget_ci->ir.dev; | 121 | struct input_dev *dev = budget_ci->ir.dev; |
135 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | 122 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; |
136 | u32 raw; | ||
137 | 123 | ||
138 | /* | 124 | /* |
139 | * The msp430 chip can generate two different bytes, command and device | 125 | * The msp430 chip can generate two different bytes, command and device |
@@ -169,20 +155,12 @@ static void msp430_ir_interrupt(unsigned long data) | |||
169 | return; | 155 | return; |
170 | budget_ci->ir.have_command = false; | 156 | budget_ci->ir.have_command = false; |
171 | 157 | ||
158 | /* FIXME: We should generate complete scancodes with device info */ | ||
172 | if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && | 159 | if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && |
173 | budget_ci->ir.rc5_device != (command & 0x1f)) | 160 | budget_ci->ir.rc5_device != (command & 0x1f)) |
174 | return; | 161 | return; |
175 | 162 | ||
176 | /* Is this a repeated key sequence? (same device, command, toggle) */ | 163 | ir_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0); |
177 | raw = budget_ci->ir.ir_key | (command << 8); | ||
178 | if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) { | ||
179 | ir_input_nokey(dev, &budget_ci->ir.state); | ||
180 | ir_input_keydown(dev, &budget_ci->ir.state, | ||
181 | budget_ci->ir.ir_key); | ||
182 | budget_ci->ir.last_raw = raw; | ||
183 | } | ||
184 | |||
185 | mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT)); | ||
186 | } | 164 | } |
187 | 165 | ||
188 | static int msp430_ir_init(struct budget_ci *budget_ci) | 166 | static int msp430_ir_init(struct budget_ci *budget_ci) |
@@ -190,7 +168,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
190 | struct saa7146_dev *saa = budget_ci->budget.dev; | 168 | struct saa7146_dev *saa = budget_ci->budget.dev; |
191 | struct input_dev *input_dev = budget_ci->ir.dev; | 169 | struct input_dev *input_dev = budget_ci->ir.dev; |
192 | int error; | 170 | int error; |
193 | struct ir_scancode_table *ir_codes; | 171 | char *ir_codes = NULL; |
194 | 172 | ||
195 | 173 | ||
196 | budget_ci->ir.dev = input_dev = input_allocate_device(); | 174 | budget_ci->ir.dev = input_dev = input_allocate_device(); |
@@ -230,7 +208,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
230 | case 0x1011: | 208 | case 0x1011: |
231 | case 0x1012: | 209 | case 0x1012: |
232 | /* The hauppauge keymap is a superset of these remotes */ | 210 | /* The hauppauge keymap is a superset of these remotes */ |
233 | ir_codes = &ir_codes_hauppauge_new_table; | 211 | ir_codes = RC_MAP_HAUPPAUGE_NEW; |
234 | 212 | ||
235 | if (rc5_device < 0) | 213 | if (rc5_device < 0) |
236 | budget_ci->ir.rc5_device = 0x1f; | 214 | budget_ci->ir.rc5_device = 0x1f; |
@@ -239,22 +217,15 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
239 | case 0x1017: | 217 | case 0x1017: |
240 | case 0x101a: | 218 | case 0x101a: |
241 | /* for the Technotrend 1500 bundled remote */ | 219 | /* for the Technotrend 1500 bundled remote */ |
242 | ir_codes = &ir_codes_tt_1500_table; | 220 | ir_codes = RC_MAP_TT_1500; |
243 | break; | 221 | break; |
244 | default: | 222 | default: |
245 | /* unknown remote */ | 223 | /* unknown remote */ |
246 | ir_codes = &ir_codes_budget_ci_old_table; | 224 | ir_codes = RC_MAP_BUDGET_CI_OLD; |
247 | break; | 225 | break; |
248 | } | 226 | } |
249 | 227 | ||
250 | ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5); | 228 | error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); |
251 | |||
252 | /* initialise the key-up timeout handler */ | ||
253 | init_timer(&budget_ci->ir.timer_keyup); | ||
254 | budget_ci->ir.timer_keyup.function = msp430_ir_keyup; | ||
255 | budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; | ||
256 | budget_ci->ir.last_raw = 0xffff; /* An impossible value */ | ||
257 | error = ir_input_register(input_dev, ir_codes, NULL); | ||
258 | if (error) { | 229 | if (error) { |
259 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); | 230 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); |
260 | return error; | 231 | return error; |
@@ -282,9 +253,6 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) | |||
282 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); | 253 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); |
283 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); | 254 | tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); |
284 | 255 | ||
285 | del_timer_sync(&dev->timer); | ||
286 | ir_input_nokey(dev, &budget_ci->ir.state); | ||
287 | |||
288 | ir_input_unregister(dev); | 256 | ir_input_unregister(dev); |
289 | } | 257 | } |
290 | 258 | ||
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 1500210c06cf..874a10a9d493 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -442,6 +442,7 @@ static struct stv090x_config tt1600_stv090x_config = { | |||
442 | .repeater_level = STV090x_RPTLEVEL_16, | 442 | .repeater_level = STV090x_RPTLEVEL_16, |
443 | 443 | ||
444 | .tuner_init = NULL, | 444 | .tuner_init = NULL, |
445 | .tuner_sleep = NULL, | ||
445 | .tuner_set_mode = NULL, | 446 | .tuner_set_mode = NULL, |
446 | .tuner_set_frequency = NULL, | 447 | .tuner_set_frequency = NULL, |
447 | .tuner_get_frequency = NULL, | 448 | .tuner_get_frequency = NULL, |
@@ -627,22 +628,36 @@ static void frontend_init(struct budget *budget) | |||
627 | &tt1600_stv6110x_config, | 628 | &tt1600_stv6110x_config, |
628 | &budget->i2c_adap); | 629 | &budget->i2c_adap); |
629 | 630 | ||
630 | tt1600_stv090x_config.tuner_init = ctl->tuner_init; | 631 | if (ctl) { |
631 | tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; | 632 | tt1600_stv090x_config.tuner_init = ctl->tuner_init; |
632 | tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; | 633 | tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep; |
633 | tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; | 634 | tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; |
634 | tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; | 635 | tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; |
635 | tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; | 636 | tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; |
636 | tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; | 637 | tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; |
637 | tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; | 638 | tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; |
638 | tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; | 639 | tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; |
639 | tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; | 640 | tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; |
640 | 641 | tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; | |
641 | dvb_attach(isl6423_attach, | 642 | tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; |
642 | budget->dvb_frontend, | 643 | |
643 | &budget->i2c_adap, | 644 | /* call the init function once to initialize |
644 | &tt1600_isl6423_config); | 645 | tuner's clock output divider and demod's |
645 | 646 | master clock */ | |
647 | if (budget->dvb_frontend->ops.init) | ||
648 | budget->dvb_frontend->ops.init(budget->dvb_frontend); | ||
649 | |||
650 | if (dvb_attach(isl6423_attach, | ||
651 | budget->dvb_frontend, | ||
652 | &budget->i2c_adap, | ||
653 | &tt1600_isl6423_config) == NULL) { | ||
654 | printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__); | ||
655 | goto error_out; | ||
656 | } | ||
657 | } else { | ||
658 | printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__); | ||
659 | goto error_out; | ||
660 | } | ||
646 | } | 661 | } |
647 | } | 662 | } |
648 | break; | 663 | break; |
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 02a9cefc9a00..353b82855949 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -144,7 +144,10 @@ struct amradio_device { | |||
144 | int initialized; | 144 | int initialized; |
145 | }; | 145 | }; |
146 | 146 | ||
147 | #define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev) | 147 | static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev) |
148 | { | ||
149 | return container_of(v4l2_dev, struct amradio_device, v4l2_dev); | ||
150 | } | ||
148 | 151 | ||
149 | /* USB Device ID List */ | 152 | /* USB Device ID List */ |
150 | static struct usb_device_id usb_amradio_device_table[] = { | 153 | static struct usb_device_id usb_amradio_device_table[] = { |
@@ -284,13 +287,12 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) | |||
284 | */ | 287 | */ |
285 | static void usb_amradio_disconnect(struct usb_interface *intf) | 288 | static void usb_amradio_disconnect(struct usb_interface *intf) |
286 | { | 289 | { |
287 | struct amradio_device *radio = usb_get_intfdata(intf); | 290 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); |
288 | 291 | ||
289 | mutex_lock(&radio->lock); | 292 | mutex_lock(&radio->lock); |
290 | radio->usbdev = NULL; | 293 | radio->usbdev = NULL; |
291 | mutex_unlock(&radio->lock); | 294 | mutex_unlock(&radio->lock); |
292 | 295 | ||
293 | usb_set_intfdata(intf, NULL); | ||
294 | v4l2_device_disconnect(&radio->v4l2_dev); | 296 | v4l2_device_disconnect(&radio->v4l2_dev); |
295 | video_unregister_device(&radio->videodev); | 297 | video_unregister_device(&radio->videodev); |
296 | } | 298 | } |
@@ -500,7 +502,7 @@ out: | |||
500 | /* open device - amradio_start() and amradio_setfreq() */ | 502 | /* open device - amradio_start() and amradio_setfreq() */ |
501 | static int usb_amradio_open(struct file *file) | 503 | static int usb_amradio_open(struct file *file) |
502 | { | 504 | { |
503 | struct amradio_device *radio = vdev_to_amradio(video_devdata(file)); | 505 | struct amradio_device *radio = video_drvdata(file); |
504 | int retval = 0; | 506 | int retval = 0; |
505 | 507 | ||
506 | mutex_lock(&radio->lock); | 508 | mutex_lock(&radio->lock); |
@@ -566,7 +568,7 @@ unlock: | |||
566 | /* Suspend device - stop device. Need to be checked and fixed */ | 568 | /* Suspend device - stop device. Need to be checked and fixed */ |
567 | static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) | 569 | static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) |
568 | { | 570 | { |
569 | struct amradio_device *radio = usb_get_intfdata(intf); | 571 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); |
570 | 572 | ||
571 | mutex_lock(&radio->lock); | 573 | mutex_lock(&radio->lock); |
572 | 574 | ||
@@ -584,7 +586,7 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) | |||
584 | /* Resume device - start device. Need to be checked and fixed */ | 586 | /* Resume device - start device. Need to be checked and fixed */ |
585 | static int usb_amradio_resume(struct usb_interface *intf) | 587 | static int usb_amradio_resume(struct usb_interface *intf) |
586 | { | 588 | { |
587 | struct amradio_device *radio = usb_get_intfdata(intf); | 589 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); |
588 | 590 | ||
589 | mutex_lock(&radio->lock); | 591 | mutex_lock(&radio->lock); |
590 | 592 | ||
@@ -633,9 +635,7 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { | |||
633 | 635 | ||
634 | static void usb_amradio_video_device_release(struct video_device *videodev) | 636 | static void usb_amradio_video_device_release(struct video_device *videodev) |
635 | { | 637 | { |
636 | struct amradio_device *radio = vdev_to_amradio(videodev); | 638 | struct amradio_device *radio = video_get_drvdata(videodev); |
637 | |||
638 | v4l2_device_unregister(&radio->v4l2_dev); | ||
639 | 639 | ||
640 | /* free rest memory */ | 640 | /* free rest memory */ |
641 | kfree(radio->buffer); | 641 | kfree(radio->buffer); |
@@ -693,7 +693,6 @@ static int usb_amradio_probe(struct usb_interface *intf, | |||
693 | goto err_vdev; | 693 | goto err_vdev; |
694 | } | 694 | } |
695 | 695 | ||
696 | usb_set_intfdata(intf, radio); | ||
697 | return 0; | 696 | return 0; |
698 | 697 | ||
699 | err_vdev: | 698 | err_vdev: |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9644cf760aaa..ad9e6f9c22e9 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -45,6 +45,10 @@ config VIDEO_TUNER | |||
45 | tristate | 45 | tristate |
46 | depends on MEDIA_TUNER | 46 | depends on MEDIA_TUNER |
47 | 47 | ||
48 | config V4L2_MEM2MEM_DEV | ||
49 | tristate | ||
50 | depends on VIDEOBUF_GEN | ||
51 | |||
48 | # | 52 | # |
49 | # Multimedia Video device configuration | 53 | # Multimedia Video device configuration |
50 | # | 54 | # |
@@ -480,6 +484,12 @@ config VIDEO_ADV7343 | |||
480 | To compile this driver as a module, choose M here: the | 484 | To compile this driver as a module, choose M here: the |
481 | module will be called adv7343. | 485 | module will be called adv7343. |
482 | 486 | ||
487 | config VIDEO_AK881X | ||
488 | tristate "AK8813/AK8814 video encoders" | ||
489 | depends on I2C | ||
490 | help | ||
491 | Video output driver for AKM AK8813 and AK8814 TV encoders | ||
492 | |||
483 | comment "Video improvement chips" | 493 | comment "Video improvement chips" |
484 | 494 | ||
485 | config VIDEO_UPD64031A | 495 | config VIDEO_UPD64031A |
@@ -520,6 +530,13 @@ config DISPLAY_DAVINCI_DM646X_EVM | |||
520 | To compile this driver as a module, choose M here: the | 530 | To compile this driver as a module, choose M here: the |
521 | module will be called vpif_display. | 531 | module will be called vpif_display. |
522 | 532 | ||
533 | config VIDEO_SH_VOU | ||
534 | tristate "SuperH VOU video output driver" | ||
535 | depends on VIDEO_DEV && ARCH_SHMOBILE | ||
536 | select VIDEOBUF_DMA_CONTIG | ||
537 | help | ||
538 | Support for the Video Output Unit (VOU) on SuperH SoCs. | ||
539 | |||
523 | config CAPTURE_DAVINCI_DM646X_EVM | 540 | config CAPTURE_DAVINCI_DM646X_EVM |
524 | tristate "DM646x EVM Video Capture" | 541 | tristate "DM646x EVM Video Capture" |
525 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM | 542 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM |
@@ -542,7 +559,8 @@ config VIDEO_DAVINCI_VPIF | |||
542 | 559 | ||
543 | config VIDEO_VIVI | 560 | config VIDEO_VIVI |
544 | tristate "Virtual Video Driver" | 561 | tristate "Virtual Video Driver" |
545 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 | 562 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS |
563 | select FONT_8x16 | ||
546 | select VIDEOBUF_VMALLOC | 564 | select VIDEOBUF_VMALLOC |
547 | default n | 565 | default n |
548 | ---help--- | 566 | ---help--- |
@@ -613,6 +631,8 @@ config VIDEO_ISIF | |||
613 | To compile this driver as a module, choose M here: the | 631 | To compile this driver as a module, choose M here: the |
614 | module will be called vpfe. | 632 | module will be called vpfe. |
615 | 633 | ||
634 | source "drivers/media/video/omap/Kconfig" | ||
635 | |||
616 | source "drivers/media/video/bt8xx/Kconfig" | 636 | source "drivers/media/video/bt8xx/Kconfig" |
617 | 637 | ||
618 | config VIDEO_PMS | 638 | config VIDEO_PMS |
@@ -647,7 +667,7 @@ config VIDEO_CQCAM | |||
647 | 667 | ||
648 | config VIDEO_W9966 | 668 | config VIDEO_W9966 |
649 | tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" | 669 | tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" |
650 | depends on PARPORT_1284 && PARPORT && VIDEO_V4L1 | 670 | depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 |
651 | help | 671 | help |
652 | Video4linux driver for Winbond's w9966 based Webcams. | 672 | Video4linux driver for Winbond's w9966 based Webcams. |
653 | Currently tested with the LifeView FlyCam Supra. | 673 | Currently tested with the LifeView FlyCam Supra. |
@@ -740,7 +760,7 @@ source "drivers/media/video/zoran/Kconfig" | |||
740 | 760 | ||
741 | config VIDEO_MEYE | 761 | config VIDEO_MEYE |
742 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 762 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
743 | depends on PCI && SONY_LAPTOP && VIDEO_V4L1 | 763 | depends on PCI && SONY_LAPTOP && VIDEO_V4L2 |
744 | ---help--- | 764 | ---help--- |
745 | This is the video4linux driver for the Motion Eye camera found | 765 | This is the video4linux driver for the Motion Eye camera found |
746 | in the Vaio Picturebook laptops. Please read the material in | 766 | in the Vaio Picturebook laptops. Please read the material in |
@@ -807,7 +827,7 @@ source "drivers/media/video/saa7164/Kconfig" | |||
807 | 827 | ||
808 | config VIDEO_M32R_AR | 828 | config VIDEO_M32R_AR |
809 | tristate "AR devices" | 829 | tristate "AR devices" |
810 | depends on M32R && VIDEO_V4L1 | 830 | depends on M32R && VIDEO_V4L2 |
811 | ---help--- | 831 | ---help--- |
812 | This is a video4linux driver for the Renesas AR (Artificial Retina) | 832 | This is a video4linux driver for the Renesas AR (Artificial Retina) |
813 | camera module. | 833 | camera module. |
@@ -1107,3 +1127,27 @@ config USB_S2255 | |||
1107 | 1127 | ||
1108 | endif # V4L_USB_DRIVERS | 1128 | endif # V4L_USB_DRIVERS |
1109 | endif # VIDEO_CAPTURE_DRIVERS | 1129 | endif # VIDEO_CAPTURE_DRIVERS |
1130 | |||
1131 | menuconfig V4L_MEM2MEM_DRIVERS | ||
1132 | bool "Memory-to-memory multimedia devices" | ||
1133 | depends on VIDEO_V4L2 | ||
1134 | default n | ||
1135 | ---help--- | ||
1136 | Say Y here to enable selecting drivers for V4L devices that | ||
1137 | use system memory for both source and destination buffers, as opposed | ||
1138 | to capture and output drivers, which use memory buffers for just | ||
1139 | one of those. | ||
1140 | |||
1141 | if V4L_MEM2MEM_DRIVERS | ||
1142 | |||
1143 | config VIDEO_MEM2MEM_TESTDEV | ||
1144 | tristate "Virtual test device for mem2mem framework" | ||
1145 | depends on VIDEO_DEV && VIDEO_V4L2 | ||
1146 | select VIDEOBUF_VMALLOC | ||
1147 | select V4L2_MEM2MEM_DEV | ||
1148 | default n | ||
1149 | ---help--- | ||
1150 | This is a virtual test device for the memory-to-memory driver | ||
1151 | framework. | ||
1152 | |||
1153 | endif # V4L_MEM2MEM_DRIVERS | ||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index c51c386559f2..cc93859d3164 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -10,7 +10,8 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o | |||
10 | 10 | ||
11 | omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o | 11 | omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o |
12 | 12 | ||
13 | videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o | 13 | videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ |
14 | v4l2-event.o | ||
14 | 15 | ||
15 | # V4L2 core modules | 16 | # V4L2 core modules |
16 | 17 | ||
@@ -117,6 +118,8 @@ obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o | |||
117 | obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o | 118 | obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o |
118 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o | 119 | obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o |
119 | 120 | ||
121 | obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o | ||
122 | |||
120 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o | 123 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o |
121 | 124 | ||
122 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | 125 | obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o |
@@ -149,8 +152,11 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | |||
149 | obj-$(CONFIG_VIDEO_CX18) += cx18/ | 152 | obj-$(CONFIG_VIDEO_CX18) += cx18/ |
150 | 153 | ||
151 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o | 154 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o |
155 | obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o | ||
152 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ | 156 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ |
153 | 157 | ||
158 | obj-$(CONFIG_VIDEO_AK881X) += ak881x.o | ||
159 | |||
154 | obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o | 160 | obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o |
155 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o | 161 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o |
156 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o | 162 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o |
@@ -160,6 +166,10 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o | |||
160 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | 166 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o |
161 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 167 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
162 | 168 | ||
169 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | ||
170 | |||
171 | obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o | ||
172 | |||
163 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ | 173 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ |
164 | 174 | ||
165 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ | 175 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ |
@@ -169,6 +179,8 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o | |||
169 | 179 | ||
170 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 180 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
171 | 181 | ||
182 | obj-$(CONFIG_ARCH_OMAP) += omap/ | ||
183 | |||
172 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 184 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
173 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 185 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
174 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 186 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c new file mode 100644 index 000000000000..35390d4717b9 --- /dev/null +++ b/drivers/media/video/ak881x.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * Driver for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM) | ||
3 | * | ||
4 | * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/videodev2.h> | ||
15 | |||
16 | #include <media/ak881x.h> | ||
17 | #include <media/v4l2-chip-ident.h> | ||
18 | #include <media/v4l2-common.h> | ||
19 | #include <media/v4l2-device.h> | ||
20 | |||
21 | #define AK881X_INTERFACE_MODE 0 | ||
22 | #define AK881X_VIDEO_PROCESS1 1 | ||
23 | #define AK881X_VIDEO_PROCESS2 2 | ||
24 | #define AK881X_VIDEO_PROCESS3 3 | ||
25 | #define AK881X_DAC_MODE 5 | ||
26 | #define AK881X_STATUS 0x24 | ||
27 | #define AK881X_DEVICE_ID 0x25 | ||
28 | #define AK881X_DEVICE_REVISION 0x26 | ||
29 | |||
30 | struct ak881x { | ||
31 | struct v4l2_subdev subdev; | ||
32 | struct ak881x_pdata *pdata; | ||
33 | unsigned int lines; | ||
34 | int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */ | ||
35 | char revision; /* DEVICE_REVISION content */ | ||
36 | }; | ||
37 | |||
38 | static int reg_read(struct i2c_client *client, const u8 reg) | ||
39 | { | ||
40 | return i2c_smbus_read_byte_data(client, reg); | ||
41 | } | ||
42 | |||
43 | static int reg_write(struct i2c_client *client, const u8 reg, | ||
44 | const u8 data) | ||
45 | { | ||
46 | return i2c_smbus_write_byte_data(client, reg, data); | ||
47 | } | ||
48 | |||
49 | static int reg_set(struct i2c_client *client, const u8 reg, | ||
50 | const u8 data, u8 mask) | ||
51 | { | ||
52 | int ret = reg_read(client, reg); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | return reg_write(client, reg, (ret & ~mask) | (data & mask)); | ||
56 | } | ||
57 | |||
58 | static struct ak881x *to_ak881x(const struct i2c_client *client) | ||
59 | { | ||
60 | return container_of(i2c_get_clientdata(client), struct ak881x, subdev); | ||
61 | } | ||
62 | |||
63 | static int ak881x_g_chip_ident(struct v4l2_subdev *sd, | ||
64 | struct v4l2_dbg_chip_ident *id) | ||
65 | { | ||
66 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
67 | struct ak881x *ak881x = to_ak881x(client); | ||
68 | |||
69 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
70 | return -EINVAL; | ||
71 | |||
72 | if (id->match.addr != client->addr) | ||
73 | return -ENODEV; | ||
74 | |||
75 | id->ident = ak881x->id; | ||
76 | id->revision = ak881x->revision; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
82 | static int ak881x_g_register(struct v4l2_subdev *sd, | ||
83 | struct v4l2_dbg_register *reg) | ||
84 | { | ||
85 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
86 | |||
87 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) | ||
88 | return -EINVAL; | ||
89 | |||
90 | if (reg->match.addr != client->addr) | ||
91 | return -ENODEV; | ||
92 | |||
93 | reg->val = reg_read(client, reg->reg); | ||
94 | |||
95 | if (reg->val > 0xffff) | ||
96 | return -EIO; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int ak881x_s_register(struct v4l2_subdev *sd, | ||
102 | struct v4l2_dbg_register *reg) | ||
103 | { | ||
104 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
105 | |||
106 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) | ||
107 | return -EINVAL; | ||
108 | |||
109 | if (reg->match.addr != client->addr) | ||
110 | return -ENODEV; | ||
111 | |||
112 | if (reg_write(client, reg->reg, reg->val) < 0) | ||
113 | return -EIO; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd, | ||
120 | struct v4l2_mbus_framefmt *mf) | ||
121 | { | ||
122 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
123 | struct ak881x *ak881x = to_ak881x(client); | ||
124 | |||
125 | v4l_bound_align_image(&mf->width, 0, 720, 2, | ||
126 | &mf->height, 0, ak881x->lines, 1, 0); | ||
127 | mf->field = V4L2_FIELD_INTERLACED; | ||
128 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_LE; | ||
129 | mf->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd, | ||
135 | struct v4l2_mbus_framefmt *mf) | ||
136 | { | ||
137 | if (mf->field != V4L2_FIELD_INTERLACED || | ||
138 | mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | ||
139 | return -EINVAL; | ||
140 | |||
141 | return ak881x_try_g_mbus_fmt(sd, mf); | ||
142 | } | ||
143 | |||
144 | static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index, | ||
145 | enum v4l2_mbus_pixelcode *code) | ||
146 | { | ||
147 | if (index) | ||
148 | return -EINVAL; | ||
149 | |||
150 | *code = V4L2_MBUS_FMT_YUYV8_2X8_LE; | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
155 | { | ||
156 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
157 | struct ak881x *ak881x = to_ak881x(client); | ||
158 | |||
159 | a->bounds.left = 0; | ||
160 | a->bounds.top = 0; | ||
161 | a->bounds.width = 720; | ||
162 | a->bounds.height = ak881x->lines; | ||
163 | a->defrect = a->bounds; | ||
164 | a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
165 | a->pixelaspect.numerator = 1; | ||
166 | a->pixelaspect.denominator = 1; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) | ||
172 | { | ||
173 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
174 | struct ak881x *ak881x = to_ak881x(client); | ||
175 | u8 vp1; | ||
176 | |||
177 | if (std == V4L2_STD_NTSC_443) { | ||
178 | vp1 = 3; | ||
179 | ak881x->lines = 480; | ||
180 | } else if (std == V4L2_STD_PAL_M) { | ||
181 | vp1 = 5; | ||
182 | ak881x->lines = 480; | ||
183 | } else if (std == V4L2_STD_PAL_60) { | ||
184 | vp1 = 7; | ||
185 | ak881x->lines = 480; | ||
186 | } else if (std && !(std & ~V4L2_STD_PAL)) { | ||
187 | vp1 = 0xf; | ||
188 | ak881x->lines = 576; | ||
189 | } else if (std && !(std & ~V4L2_STD_NTSC)) { | ||
190 | vp1 = 0; | ||
191 | ak881x->lines = 480; | ||
192 | } else { | ||
193 | /* No SECAM or PAL_N/Nc supported */ | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | reg_set(client, AK881X_VIDEO_PROCESS1, vp1, 0xf); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int ak881x_s_stream(struct v4l2_subdev *sd, int enable) | ||
203 | { | ||
204 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
205 | struct ak881x *ak881x = to_ak881x(client); | ||
206 | |||
207 | if (enable) { | ||
208 | u8 dac; | ||
209 | /* For colour-bar testing set bit 6 of AK881X_VIDEO_PROCESS1 */ | ||
210 | /* Default: composite output */ | ||
211 | if (ak881x->pdata->flags & AK881X_COMPONENT) | ||
212 | dac = 3; | ||
213 | else | ||
214 | dac = 4; | ||
215 | /* Turn on the DAC(s) */ | ||
216 | reg_write(client, AK881X_DAC_MODE, dac); | ||
217 | dev_dbg(&client->dev, "chip status 0x%x\n", | ||
218 | reg_read(client, AK881X_STATUS)); | ||
219 | } else { | ||
220 | /* ...and clear bit 6 of AK881X_VIDEO_PROCESS1 here */ | ||
221 | reg_write(client, AK881X_DAC_MODE, 0); | ||
222 | dev_dbg(&client->dev, "chip status 0x%x\n", | ||
223 | reg_read(client, AK881X_STATUS)); | ||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = { | ||
230 | .g_chip_ident = ak881x_g_chip_ident, | ||
231 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
232 | .g_register = ak881x_g_register, | ||
233 | .s_register = ak881x_s_register, | ||
234 | #endif | ||
235 | }; | ||
236 | |||
237 | static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = { | ||
238 | .s_mbus_fmt = ak881x_s_mbus_fmt, | ||
239 | .g_mbus_fmt = ak881x_try_g_mbus_fmt, | ||
240 | .try_mbus_fmt = ak881x_try_g_mbus_fmt, | ||
241 | .cropcap = ak881x_cropcap, | ||
242 | .enum_mbus_fmt = ak881x_enum_mbus_fmt, | ||
243 | .s_std_output = ak881x_s_std_output, | ||
244 | .s_stream = ak881x_s_stream, | ||
245 | }; | ||
246 | |||
247 | static struct v4l2_subdev_ops ak881x_subdev_ops = { | ||
248 | .core = &ak881x_subdev_core_ops, | ||
249 | .video = &ak881x_subdev_video_ops, | ||
250 | }; | ||
251 | |||
252 | static int ak881x_probe(struct i2c_client *client, | ||
253 | const struct i2c_device_id *did) | ||
254 | { | ||
255 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
256 | struct ak881x *ak881x; | ||
257 | u8 ifmode, data; | ||
258 | |||
259 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
260 | dev_warn(&adapter->dev, | ||
261 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
262 | return -EIO; | ||
263 | } | ||
264 | |||
265 | ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); | ||
266 | if (!ak881x) | ||
267 | return -ENOMEM; | ||
268 | |||
269 | v4l2_i2c_subdev_init(&ak881x->subdev, client, &ak881x_subdev_ops); | ||
270 | |||
271 | data = reg_read(client, AK881X_DEVICE_ID); | ||
272 | |||
273 | switch (data) { | ||
274 | case 0x13: | ||
275 | ak881x->id = V4L2_IDENT_AK8813; | ||
276 | break; | ||
277 | case 0x14: | ||
278 | ak881x->id = V4L2_IDENT_AK8814; | ||
279 | break; | ||
280 | default: | ||
281 | dev_err(&client->dev, | ||
282 | "No ak881x chip detected, register read %x\n", data); | ||
283 | kfree(ak881x); | ||
284 | return -ENODEV; | ||
285 | } | ||
286 | |||
287 | ak881x->revision = reg_read(client, AK881X_DEVICE_REVISION); | ||
288 | ak881x->pdata = client->dev.platform_data; | ||
289 | |||
290 | if (ak881x->pdata) { | ||
291 | if (ak881x->pdata->flags & AK881X_FIELD) | ||
292 | ifmode = 4; | ||
293 | else | ||
294 | ifmode = 0; | ||
295 | |||
296 | switch (ak881x->pdata->flags & AK881X_IF_MODE_MASK) { | ||
297 | case AK881X_IF_MODE_BT656: | ||
298 | ifmode |= 1; | ||
299 | break; | ||
300 | case AK881X_IF_MODE_MASTER: | ||
301 | ifmode |= 2; | ||
302 | break; | ||
303 | case AK881X_IF_MODE_SLAVE: | ||
304 | default: | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | dev_dbg(&client->dev, "IF mode %x\n", ifmode); | ||
309 | |||
310 | /* | ||
311 | * "Line Blanking No." seems to be the same as the number of | ||
312 | * "black" lines on, e.g., SuperH VOU, whose default value of 20 | ||
313 | * "incidentally" matches ak881x' default | ||
314 | */ | ||
315 | reg_write(client, AK881X_INTERFACE_MODE, ifmode | (20 << 3)); | ||
316 | } | ||
317 | |||
318 | /* Hardware default: NTSC-M */ | ||
319 | ak881x->lines = 480; | ||
320 | |||
321 | dev_info(&client->dev, "Detected an ak881x chip ID %x, revision %x\n", | ||
322 | data, ak881x->revision); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int ak881x_remove(struct i2c_client *client) | ||
328 | { | ||
329 | struct ak881x *ak881x = to_ak881x(client); | ||
330 | |||
331 | v4l2_device_unregister_subdev(&ak881x->subdev); | ||
332 | kfree(ak881x); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static const struct i2c_device_id ak881x_id[] = { | ||
338 | { "ak8813", 0 }, | ||
339 | { "ak8814", 0 }, | ||
340 | { } | ||
341 | }; | ||
342 | MODULE_DEVICE_TABLE(i2c, ak881x_id); | ||
343 | |||
344 | static struct i2c_driver ak881x_i2c_driver = { | ||
345 | .driver = { | ||
346 | .name = "ak881x", | ||
347 | }, | ||
348 | .probe = ak881x_probe, | ||
349 | .remove = ak881x_remove, | ||
350 | .id_table = ak881x_id, | ||
351 | }; | ||
352 | |||
353 | static int __init ak881x_module_init(void) | ||
354 | { | ||
355 | return i2c_add_driver(&ak881x_i2c_driver); | ||
356 | } | ||
357 | |||
358 | static void __exit ak881x_module_exit(void) | ||
359 | { | ||
360 | i2c_del_driver(&ak881x_i2c_driver); | ||
361 | } | ||
362 | |||
363 | module_init(ak881x_module_init); | ||
364 | module_exit(ak881x_module_exit); | ||
365 | |||
366 | MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); | ||
367 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
368 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index a356d6bd3131..31e7a123d19a 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
@@ -27,8 +27,10 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/videodev.h> | 30 | #include <linux/version.h> |
31 | #include <linux/videodev2.h> | ||
31 | #include <media/v4l2-common.h> | 32 | #include <media/v4l2-common.h> |
33 | #include <media/v4l2-device.h> | ||
32 | #include <media/v4l2-ioctl.h> | 34 | #include <media/v4l2-ioctl.h> |
33 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
34 | 36 | ||
@@ -39,7 +41,7 @@ | |||
39 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
40 | 42 | ||
41 | #if 0 | 43 | #if 0 |
42 | #define DEBUG(n, args...) printk(args) | 44 | #define DEBUG(n, args...) printk(KERN_INFO args) |
43 | #define CHECK_LOST 1 | 45 | #define CHECK_LOST 1 |
44 | #else | 46 | #else |
45 | #define DEBUG(n, args...) | 47 | #define DEBUG(n, args...) |
@@ -52,10 +54,10 @@ | |||
52 | */ | 54 | */ |
53 | #define USE_INT 0 /* Don't modify */ | 55 | #define USE_INT 0 /* Don't modify */ |
54 | 56 | ||
55 | #define VERSION "0.03" | 57 | #define VERSION "0.04" |
56 | 58 | ||
57 | #define ar_inl(addr) inl((unsigned long)(addr)) | 59 | #define ar_inl(addr) inl((unsigned long)(addr)) |
58 | #define ar_outl(val, addr) outl((unsigned long)(val),(unsigned long)(addr)) | 60 | #define ar_outl(val, addr) outl((unsigned long)(val), (unsigned long)(addr)) |
59 | 61 | ||
60 | extern struct cpuinfo_m32r boot_cpu_data; | 62 | extern struct cpuinfo_m32r boot_cpu_data; |
61 | 63 | ||
@@ -79,7 +81,7 @@ extern struct cpuinfo_m32r boot_cpu_data; | |||
79 | 81 | ||
80 | /* bits & bytes per pixel */ | 82 | /* bits & bytes per pixel */ |
81 | #define AR_BITS_PER_PIXEL 16 | 83 | #define AR_BITS_PER_PIXEL 16 |
82 | #define AR_BYTES_PER_PIXEL (AR_BITS_PER_PIXEL/8) | 84 | #define AR_BYTES_PER_PIXEL (AR_BITS_PER_PIXEL / 8) |
83 | 85 | ||
84 | /* line buffer size */ | 86 | /* line buffer size */ |
85 | #define AR_LINE_BYTES_VGA (AR_WIDTH_VGA * AR_BYTES_PER_PIXEL) | 87 | #define AR_LINE_BYTES_VGA (AR_WIDTH_VGA * AR_BYTES_PER_PIXEL) |
@@ -104,8 +106,9 @@ extern struct cpuinfo_m32r boot_cpu_data; | |||
104 | #define AR_MODE_INTERLACE 0 | 106 | #define AR_MODE_INTERLACE 0 |
105 | #define AR_MODE_NORMAL 1 | 107 | #define AR_MODE_NORMAL 1 |
106 | 108 | ||
107 | struct ar_device { | 109 | struct ar { |
108 | struct video_device *vdev; | 110 | struct v4l2_device v4l2_dev; |
111 | struct video_device vdev; | ||
109 | unsigned int start_capture; /* duaring capture in INT. mode. */ | 112 | unsigned int start_capture; /* duaring capture in INT. mode. */ |
110 | #if USE_INT | 113 | #if USE_INT |
111 | unsigned char *line_buff; /* DMA line buffer */ | 114 | unsigned char *line_buff; /* DMA line buffer */ |
@@ -116,12 +119,13 @@ struct ar_device { | |||
116 | int width, height; | 119 | int width, height; |
117 | int frame_bytes, line_bytes; | 120 | int frame_bytes, line_bytes; |
118 | wait_queue_head_t wait; | 121 | wait_queue_head_t wait; |
119 | unsigned long in_use; | ||
120 | struct mutex lock; | 122 | struct mutex lock; |
121 | }; | 123 | }; |
122 | 124 | ||
125 | static struct ar ardev; | ||
126 | |||
123 | static int video_nr = -1; /* video device number (first free) */ | 127 | static int video_nr = -1; /* video device number (first free) */ |
124 | static unsigned char yuv[MAX_AR_FRAME_BYTES]; | 128 | static unsigned char yuv[MAX_AR_FRAME_BYTES]; |
125 | 129 | ||
126 | /* module parameters */ | 130 | /* module parameters */ |
127 | /* default frequency */ | 131 | /* default frequency */ |
@@ -133,9 +137,7 @@ module_param(freq, int, 0); | |||
133 | module_param(vga, int, 0); | 137 | module_param(vga, int, 0); |
134 | module_param(vga_interlace, int, 0); | 138 | module_param(vga_interlace, int, 0); |
135 | 139 | ||
136 | static int ar_initialize(struct video_device *dev); | 140 | static void wait_for_vsync(void) |
137 | |||
138 | static inline void wait_for_vsync(void) | ||
139 | { | 141 | { |
140 | while (ar_inl(ARVCR0) & ARVCR0_VDS) /* wait for VSYNC */ | 142 | while (ar_inl(ARVCR0) & ARVCR0_VDS) /* wait for VSYNC */ |
141 | cpu_relax(); | 143 | cpu_relax(); |
@@ -143,7 +145,7 @@ static inline void wait_for_vsync(void) | |||
143 | cpu_relax(); | 145 | cpu_relax(); |
144 | } | 146 | } |
145 | 147 | ||
146 | static inline void wait_acknowledge(void) | 148 | static void wait_acknowledge(void) |
147 | { | 149 | { |
148 | int i; | 150 | int i; |
149 | 151 | ||
@@ -156,7 +158,7 @@ static inline void wait_acknowledge(void) | |||
156 | /******************************************************************* | 158 | /******************************************************************* |
157 | * I2C functions | 159 | * I2C functions |
158 | *******************************************************************/ | 160 | *******************************************************************/ |
159 | void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, | 161 | static void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, |
160 | unsigned long data3) | 162 | unsigned long data3) |
161 | { | 163 | { |
162 | int i; | 164 | int i; |
@@ -200,7 +202,7 @@ void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, | |||
200 | } | 202 | } |
201 | 203 | ||
202 | 204 | ||
203 | void init_iic(void) | 205 | static void init_iic(void) |
204 | { | 206 | { |
205 | DEBUG(1, "init_iic:\n"); | 207 | DEBUG(1, "init_iic:\n"); |
206 | 208 | ||
@@ -214,13 +216,12 @@ void init_iic(void) | |||
214 | 216 | ||
215 | /* I2C CLK */ | 217 | /* I2C CLK */ |
216 | /* 50MH-100k */ | 218 | /* 50MH-100k */ |
217 | if (freq == 75) { | 219 | if (freq == 75) |
218 | ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ | 220 | ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ |
219 | } else if (freq == 50) { | 221 | else if (freq == 50) |
220 | ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ | 222 | ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ |
221 | } else { | 223 | else |
222 | ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ | 224 | ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ |
223 | } | ||
224 | ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ | 225 | ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ |
225 | } | 226 | } |
226 | 227 | ||
@@ -245,7 +246,7 @@ static inline void clear_dma_status(void) | |||
245 | ar_outl(0x8000, M32R_DMAEDET_PORTL); /* clear status */ | 246 | ar_outl(0x8000, M32R_DMAEDET_PORTL); /* clear status */ |
246 | } | 247 | } |
247 | 248 | ||
248 | static inline void wait_for_vertical_sync(int exp_line) | 249 | static void wait_for_vertical_sync(struct ar *ar, int exp_line) |
249 | { | 250 | { |
250 | #if CHECK_LOST | 251 | #if CHECK_LOST |
251 | int tmout = 10000; /* FIXME */ | 252 | int tmout = 10000; /* FIXME */ |
@@ -260,7 +261,7 @@ static inline void wait_for_vertical_sync(int exp_line) | |||
260 | break; | 261 | break; |
261 | } | 262 | } |
262 | if (tmout < 0) | 263 | if (tmout < 0) |
263 | printk("arv: lost %d -> %d\n", exp_line, l); | 264 | v4l2_err(&ar->v4l2_dev, "lost %d -> %d\n", exp_line, l); |
264 | #else | 265 | #else |
265 | while (ar_inl(ARVHCOUNT) != exp_line) | 266 | while (ar_inl(ARVHCOUNT) != exp_line) |
266 | cpu_relax(); | 267 | cpu_relax(); |
@@ -269,15 +270,14 @@ static inline void wait_for_vertical_sync(int exp_line) | |||
269 | 270 | ||
270 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | 271 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) |
271 | { | 272 | { |
272 | struct video_device *v = video_devdata(file); | 273 | struct ar *ar = video_drvdata(file); |
273 | struct ar_device *ar = video_get_drvdata(v); | ||
274 | long ret = ar->frame_bytes; /* return read bytes */ | 274 | long ret = ar->frame_bytes; /* return read bytes */ |
275 | unsigned long arvcr1 = 0; | 275 | unsigned long arvcr1 = 0; |
276 | unsigned long flags; | 276 | unsigned long flags; |
277 | unsigned char *p; | 277 | unsigned char *p; |
278 | int h, w; | 278 | int h, w; |
279 | unsigned char *py, *pu, *pv; | 279 | unsigned char *py, *pu, *pv; |
280 | #if ! USE_INT | 280 | #if !USE_INT |
281 | int l; | 281 | int l; |
282 | #endif | 282 | #endif |
283 | 283 | ||
@@ -305,7 +305,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |||
305 | ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); /* reload count (bytes) */ | 305 | ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); /* reload count (bytes) */ |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * Okey , kicks AR LSI to invoke an interrupt | 308 | * Okay, kick AR LSI to invoke an interrupt |
309 | */ | 309 | */ |
310 | ar->start_capture = 0; | 310 | ar->start_capture = 0; |
311 | ar_outl(arvcr1 | ARVCR1_HIEN, ARVCR1); | 311 | ar_outl(arvcr1 | ARVCR1_HIEN, ARVCR1); |
@@ -313,7 +313,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |||
313 | /* .... AR interrupts .... */ | 313 | /* .... AR interrupts .... */ |
314 | interruptible_sleep_on(&ar->wait); | 314 | interruptible_sleep_on(&ar->wait); |
315 | if (signal_pending(current)) { | 315 | if (signal_pending(current)) { |
316 | printk("arv: interrupted while get frame data.\n"); | 316 | printk(KERN_ERR "arv: interrupted while get frame data.\n"); |
317 | ret = -EINTR; | 317 | ret = -EINTR; |
318 | goto out_up; | 318 | goto out_up; |
319 | } | 319 | } |
@@ -334,7 +334,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |||
334 | cpu_relax(); | 334 | cpu_relax(); |
335 | if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { | 335 | if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { |
336 | for (h = 0; h < ar->height; h++) { | 336 | for (h = 0; h < ar->height; h++) { |
337 | wait_for_vertical_sync(h); | 337 | wait_for_vertical_sync(ar, h); |
338 | if (h < (AR_HEIGHT_VGA/2)) | 338 | if (h < (AR_HEIGHT_VGA/2)) |
339 | l = h << 1; | 339 | l = h << 1; |
340 | else | 340 | else |
@@ -349,7 +349,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |||
349 | } | 349 | } |
350 | } else { | 350 | } else { |
351 | for (h = 0; h < ar->height; h++) { | 351 | for (h = 0; h < ar->height; h++) { |
352 | wait_for_vertical_sync(h); | 352 | wait_for_vertical_sync(ar, h); |
353 | ar_outl(virt_to_phys(ar->frame[h]), M32R_DMA0CDA_PORTL); | 353 | ar_outl(virt_to_phys(ar->frame[h]), M32R_DMA0CDA_PORTL); |
354 | enable_dma(); | 354 | enable_dma(); |
355 | while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000)) | 355 | while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000)) |
@@ -386,7 +386,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | |||
386 | } | 386 | } |
387 | } | 387 | } |
388 | if (copy_to_user(buf, yuv, ar->frame_bytes)) { | 388 | if (copy_to_user(buf, yuv, ar->frame_bytes)) { |
389 | printk("arv: failed while copy_to_user yuv.\n"); | 389 | v4l2_err(&ar->v4l2_dev, "failed while copy_to_user yuv.\n"); |
390 | ret = -EFAULT; | 390 | ret = -EFAULT; |
391 | goto out_up; | 391 | goto out_up; |
392 | } | 392 | } |
@@ -396,153 +396,127 @@ out_up: | |||
396 | return ret; | 396 | return ret; |
397 | } | 397 | } |
398 | 398 | ||
399 | static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 399 | static int ar_querycap(struct file *file, void *priv, |
400 | struct v4l2_capability *vcap) | ||
400 | { | 401 | { |
401 | struct video_device *dev = video_devdata(file); | 402 | struct ar *ar = video_drvdata(file); |
402 | struct ar_device *ar = video_get_drvdata(dev); | 403 | |
403 | 404 | strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver)); | |
404 | DEBUG(1, "ar_ioctl()\n"); | 405 | strlcpy(vcap->card, "Colour AR VGA", sizeof(vcap->card)); |
405 | switch(cmd) { | 406 | strlcpy(vcap->bus_info, "Platform", sizeof(vcap->bus_info)); |
406 | case VIDIOCGCAP: | 407 | vcap->version = KERNEL_VERSION(0, 0, 4); |
407 | { | 408 | vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; |
408 | struct video_capability *b = arg; | 409 | return 0; |
409 | DEBUG(1, "VIDIOCGCAP:\n"); | 410 | } |
410 | strcpy(b->name, ar->vdev->name); | 411 | |
411 | b->type = VID_TYPE_CAPTURE; | 412 | static int ar_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
412 | b->channels = 0; | 413 | { |
413 | b->audios = 0; | 414 | if (vin->index > 0) |
414 | b->maxwidth = MAX_AR_WIDTH; | ||
415 | b->maxheight = MAX_AR_HEIGHT; | ||
416 | b->minwidth = MIN_AR_WIDTH; | ||
417 | b->minheight = MIN_AR_HEIGHT; | ||
418 | return 0; | ||
419 | } | ||
420 | case VIDIOCGCHAN: | ||
421 | DEBUG(1, "VIDIOCGCHAN:\n"); | ||
422 | return 0; | ||
423 | case VIDIOCSCHAN: | ||
424 | DEBUG(1, "VIDIOCSCHAN:\n"); | ||
425 | return 0; | ||
426 | case VIDIOCGTUNER: | ||
427 | DEBUG(1, "VIDIOCGTUNER:\n"); | ||
428 | return 0; | ||
429 | case VIDIOCSTUNER: | ||
430 | DEBUG(1, "VIDIOCSTUNER:\n"); | ||
431 | return 0; | ||
432 | case VIDIOCGPICT: | ||
433 | DEBUG(1, "VIDIOCGPICT:\n"); | ||
434 | return 0; | ||
435 | case VIDIOCSPICT: | ||
436 | DEBUG(1, "VIDIOCSPICT:\n"); | ||
437 | return 0; | ||
438 | case VIDIOCCAPTURE: | ||
439 | DEBUG(1, "VIDIOCCAPTURE:\n"); | ||
440 | return -EINVAL; | 415 | return -EINVAL; |
441 | case VIDIOCGWIN: | 416 | strlcpy(vin->name, "Camera", sizeof(vin->name)); |
442 | { | 417 | vin->type = V4L2_INPUT_TYPE_CAMERA; |
443 | struct video_window *w = arg; | 418 | vin->audioset = 0; |
444 | DEBUG(1, "VIDIOCGWIN:\n"); | 419 | vin->tuner = 0; |
445 | memset(w, 0, sizeof(*w)); | 420 | vin->std = V4L2_STD_ALL; |
446 | w->width = ar->width; | 421 | vin->status = 0; |
447 | w->height = ar->height; | 422 | return 0; |
448 | return 0; | 423 | } |
424 | |||
425 | static int ar_g_input(struct file *file, void *fh, unsigned int *inp) | ||
426 | { | ||
427 | *inp = 0; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int ar_s_input(struct file *file, void *fh, unsigned int inp) | ||
432 | { | ||
433 | return inp ? -EINVAL : 0; | ||
434 | } | ||
435 | |||
436 | static int ar_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
437 | { | ||
438 | struct ar *ar = video_drvdata(file); | ||
439 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
440 | |||
441 | pix->width = ar->width; | ||
442 | pix->height = ar->height; | ||
443 | pix->pixelformat = V4L2_PIX_FMT_YUV422P; | ||
444 | pix->field = (ar->mode == AR_MODE_NORMAL) ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED; | ||
445 | pix->bytesperline = ar->width; | ||
446 | pix->sizeimage = 2 * ar->width * ar->height; | ||
447 | /* Just a guess */ | ||
448 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ar_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
453 | { | ||
454 | struct ar *ar = video_drvdata(file); | ||
455 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
456 | |||
457 | if (pix->height <= AR_HEIGHT_QVGA || pix->width <= AR_WIDTH_QVGA) { | ||
458 | pix->height = AR_HEIGHT_QVGA; | ||
459 | pix->width = AR_WIDTH_QVGA; | ||
460 | pix->field = V4L2_FIELD_INTERLACED; | ||
461 | } else { | ||
462 | pix->height = AR_HEIGHT_VGA; | ||
463 | pix->width = AR_WIDTH_VGA; | ||
464 | pix->field = vga_interlace ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; | ||
449 | } | 465 | } |
450 | case VIDIOCSWIN: | 466 | pix->pixelformat = V4L2_PIX_FMT_YUV422P; |
451 | { | 467 | pix->bytesperline = ar->width; |
452 | struct video_window *w = arg; | 468 | pix->sizeimage = 2 * ar->width * ar->height; |
453 | DEBUG(1, "VIDIOCSWIN:\n"); | 469 | /* Just a guess */ |
454 | if ((w->width != AR_WIDTH_VGA || w->height != AR_HEIGHT_VGA) && | 470 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; |
455 | (w->width != AR_WIDTH_QVGA || w->height != AR_HEIGHT_QVGA)) | 471 | return 0; |
456 | return -EINVAL; | 472 | } |
457 | 473 | ||
458 | mutex_lock(&ar->lock); | 474 | static int ar_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
459 | ar->width = w->width; | 475 | { |
460 | ar->height = w->height; | 476 | struct ar *ar = video_drvdata(file); |
461 | if (ar->width == AR_WIDTH_VGA) { | 477 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
462 | ar->size = AR_SIZE_VGA; | 478 | int ret = ar_try_fmt_vid_cap(file, fh, fmt); |
463 | ar->frame_bytes = AR_FRAME_BYTES_VGA; | 479 | |
464 | ar->line_bytes = AR_LINE_BYTES_VGA; | 480 | if (ret) |
465 | if (vga_interlace) | 481 | return ret; |
466 | ar->mode = AR_MODE_INTERLACE; | 482 | mutex_lock(&ar->lock); |
467 | else | 483 | ar->width = pix->width; |
468 | ar->mode = AR_MODE_NORMAL; | 484 | ar->height = pix->height; |
469 | } else { | 485 | if (ar->width == AR_WIDTH_VGA) { |
470 | ar->size = AR_SIZE_QVGA; | 486 | ar->size = AR_SIZE_VGA; |
471 | ar->frame_bytes = AR_FRAME_BYTES_QVGA; | 487 | ar->frame_bytes = AR_FRAME_BYTES_VGA; |
472 | ar->line_bytes = AR_LINE_BYTES_QVGA; | 488 | ar->line_bytes = AR_LINE_BYTES_VGA; |
489 | if (vga_interlace) | ||
473 | ar->mode = AR_MODE_INTERLACE; | 490 | ar->mode = AR_MODE_INTERLACE; |
474 | } | 491 | else |
475 | mutex_unlock(&ar->lock); | 492 | ar->mode = AR_MODE_NORMAL; |
476 | return 0; | 493 | } else { |
477 | } | 494 | ar->size = AR_SIZE_QVGA; |
478 | case VIDIOCGFBUF: | 495 | ar->frame_bytes = AR_FRAME_BYTES_QVGA; |
479 | DEBUG(1, "VIDIOCGFBUF:\n"); | 496 | ar->line_bytes = AR_LINE_BYTES_QVGA; |
480 | return -EINVAL; | 497 | ar->mode = AR_MODE_INTERLACE; |
481 | case VIDIOCSFBUF: | ||
482 | DEBUG(1, "VIDIOCSFBUF:\n"); | ||
483 | return -EINVAL; | ||
484 | case VIDIOCKEY: | ||
485 | DEBUG(1, "VIDIOCKEY:\n"); | ||
486 | return 0; | ||
487 | case VIDIOCGFREQ: | ||
488 | DEBUG(1, "VIDIOCGFREQ:\n"); | ||
489 | return -EINVAL; | ||
490 | case VIDIOCSFREQ: | ||
491 | DEBUG(1, "VIDIOCSFREQ:\n"); | ||
492 | return -EINVAL; | ||
493 | case VIDIOCGAUDIO: | ||
494 | DEBUG(1, "VIDIOCGAUDIO:\n"); | ||
495 | return -EINVAL; | ||
496 | case VIDIOCSAUDIO: | ||
497 | DEBUG(1, "VIDIOCSAUDIO:\n"); | ||
498 | return -EINVAL; | ||
499 | case VIDIOCSYNC: | ||
500 | DEBUG(1, "VIDIOCSYNC:\n"); | ||
501 | return -EINVAL; | ||
502 | case VIDIOCMCAPTURE: | ||
503 | DEBUG(1, "VIDIOCMCAPTURE:\n"); | ||
504 | return -EINVAL; | ||
505 | case VIDIOCGMBUF: | ||
506 | DEBUG(1, "VIDIOCGMBUF:\n"); | ||
507 | return -EINVAL; | ||
508 | case VIDIOCGUNIT: | ||
509 | DEBUG(1, "VIDIOCGUNIT:\n"); | ||
510 | return -EINVAL; | ||
511 | case VIDIOCGCAPTURE: | ||
512 | DEBUG(1, "VIDIOCGCAPTURE:\n"); | ||
513 | return -EINVAL; | ||
514 | case VIDIOCSCAPTURE: | ||
515 | DEBUG(1, "VIDIOCSCAPTURE:\n"); | ||
516 | return -EINVAL; | ||
517 | case VIDIOCSPLAYMODE: | ||
518 | DEBUG(1, "VIDIOCSPLAYMODE:\n"); | ||
519 | return -EINVAL; | ||
520 | case VIDIOCSWRITEMODE: | ||
521 | DEBUG(1, "VIDIOCSWRITEMODE:\n"); | ||
522 | return -EINVAL; | ||
523 | case VIDIOCGPLAYINFO: | ||
524 | DEBUG(1, "VIDIOCGPLAYINFO:\n"); | ||
525 | return -EINVAL; | ||
526 | case VIDIOCSMICROCODE: | ||
527 | DEBUG(1, "VIDIOCSMICROCODE:\n"); | ||
528 | return -EINVAL; | ||
529 | case VIDIOCGVBIFMT: | ||
530 | DEBUG(1, "VIDIOCGVBIFMT:\n"); | ||
531 | return -EINVAL; | ||
532 | case VIDIOCSVBIFMT: | ||
533 | DEBUG(1, "VIDIOCSVBIFMT:\n"); | ||
534 | return -EINVAL; | ||
535 | default: | ||
536 | DEBUG(1, "Unknown ioctl(0x%08x)\n", cmd); | ||
537 | return -ENOIOCTLCMD; | ||
538 | } | 498 | } |
499 | /* Ok we figured out what to use from our wide choice */ | ||
500 | mutex_unlock(&ar->lock); | ||
539 | return 0; | 501 | return 0; |
540 | } | 502 | } |
541 | 503 | ||
542 | static long ar_ioctl(struct file *file, unsigned int cmd, | 504 | static int ar_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) |
543 | unsigned long arg) | ||
544 | { | 505 | { |
545 | return video_usercopy(file, cmd, arg, ar_do_ioctl); | 506 | static struct v4l2_fmtdesc formats[] = { |
507 | { 0, 0, 0, | ||
508 | "YUV 4:2:2 Planar", V4L2_PIX_FMT_YUV422P, | ||
509 | { 0, 0, 0, 0 } | ||
510 | }, | ||
511 | }; | ||
512 | enum v4l2_buf_type type = fmt->type; | ||
513 | |||
514 | if (fmt->index > 0) | ||
515 | return -EINVAL; | ||
516 | |||
517 | *fmt = formats[fmt->index]; | ||
518 | fmt->type = type; | ||
519 | return 0; | ||
546 | } | 520 | } |
547 | 521 | ||
548 | #if USE_INT | 522 | #if USE_INT |
@@ -551,7 +525,7 @@ static long ar_ioctl(struct file *file, unsigned int cmd, | |||
551 | */ | 525 | */ |
552 | static void ar_interrupt(int irq, void *dev) | 526 | static void ar_interrupt(int irq, void *dev) |
553 | { | 527 | { |
554 | struct ar_device *ar = dev; | 528 | struct ar *ar = dev; |
555 | unsigned int line_count; | 529 | unsigned int line_count; |
556 | unsigned int line_number; | 530 | unsigned int line_number; |
557 | unsigned int arvcr1; | 531 | unsigned int arvcr1; |
@@ -559,11 +533,11 @@ static void ar_interrupt(int irq, void *dev) | |||
559 | line_count = ar_inl(ARVHCOUNT); /* line number */ | 533 | line_count = ar_inl(ARVHCOUNT); /* line number */ |
560 | if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { | 534 | if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { |
561 | /* operations for interlace mode */ | 535 | /* operations for interlace mode */ |
562 | if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */ | 536 | if (line_count < (AR_HEIGHT_VGA / 2)) /* even line */ |
563 | line_number = (line_count << 1); | 537 | line_number = (line_count << 1); |
564 | else /* odd line */ | 538 | else /* odd line */ |
565 | line_number = | 539 | line_number = |
566 | (((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1); | 540 | (((line_count - (AR_HEIGHT_VGA / 2)) << 1) + 1); |
567 | } else { | 541 | } else { |
568 | line_number = line_count; | 542 | line_number = line_count; |
569 | } | 543 | } |
@@ -623,11 +597,10 @@ static void ar_interrupt(int irq, void *dev) | |||
623 | * 0 is returned in success. | 597 | * 0 is returned in success. |
624 | * | 598 | * |
625 | */ | 599 | */ |
626 | static int ar_initialize(struct video_device *dev) | 600 | static int ar_initialize(struct ar *ar) |
627 | { | 601 | { |
628 | struct ar_device *ar = video_get_drvdata(dev); | ||
629 | unsigned long cr = 0; | 602 | unsigned long cr = 0; |
630 | int i,found=0; | 603 | int i, found = 0; |
631 | 604 | ||
632 | DEBUG(1, "ar_initialize:\n"); | 605 | DEBUG(1, "ar_initialize:\n"); |
633 | 606 | ||
@@ -666,129 +639,119 @@ static int ar_initialize(struct video_device *dev) | |||
666 | if (found == 0) | 639 | if (found == 0) |
667 | return -ENODEV; | 640 | return -ENODEV; |
668 | 641 | ||
669 | printk("arv: Initializing "); | 642 | v4l2_info(&ar->v4l2_dev, "Initializing "); |
670 | 643 | ||
671 | iic(2,0x78,0x11,0x01,0x00); /* start */ | 644 | iic(2, 0x78, 0x11, 0x01, 0x00); /* start */ |
672 | iic(3,0x78,0x12,0x00,0x06); | 645 | iic(3, 0x78, 0x12, 0x00, 0x06); |
673 | iic(3,0x78,0x12,0x12,0x30); | 646 | iic(3, 0x78, 0x12, 0x12, 0x30); |
674 | iic(3,0x78,0x12,0x15,0x58); | 647 | iic(3, 0x78, 0x12, 0x15, 0x58); |
675 | iic(3,0x78,0x12,0x17,0x30); | 648 | iic(3, 0x78, 0x12, 0x17, 0x30); |
676 | printk("."); | 649 | printk(KERN_CONT "."); |
677 | iic(3,0x78,0x12,0x1a,0x97); | 650 | iic(3, 0x78, 0x12, 0x1a, 0x97); |
678 | iic(3,0x78,0x12,0x1b,0xff); | 651 | iic(3, 0x78, 0x12, 0x1b, 0xff); |
679 | iic(3,0x78,0x12,0x1c,0xff); | 652 | iic(3, 0x78, 0x12, 0x1c, 0xff); |
680 | iic(3,0x78,0x12,0x26,0x10); | 653 | iic(3, 0x78, 0x12, 0x26, 0x10); |
681 | iic(3,0x78,0x12,0x27,0x00); | 654 | iic(3, 0x78, 0x12, 0x27, 0x00); |
682 | printk("."); | 655 | printk(KERN_CONT "."); |
683 | iic(2,0x78,0x34,0x02,0x00); | 656 | iic(2, 0x78, 0x34, 0x02, 0x00); |
684 | iic(2,0x78,0x7a,0x10,0x00); | 657 | iic(2, 0x78, 0x7a, 0x10, 0x00); |
685 | iic(2,0x78,0x80,0x39,0x00); | 658 | iic(2, 0x78, 0x80, 0x39, 0x00); |
686 | iic(2,0x78,0x81,0xe6,0x00); | 659 | iic(2, 0x78, 0x81, 0xe6, 0x00); |
687 | iic(2,0x78,0x8d,0x00,0x00); | 660 | iic(2, 0x78, 0x8d, 0x00, 0x00); |
688 | printk("."); | 661 | printk(KERN_CONT "."); |
689 | iic(2,0x78,0x8e,0x0c,0x00); | 662 | iic(2, 0x78, 0x8e, 0x0c, 0x00); |
690 | iic(2,0x78,0x8f,0x00,0x00); | 663 | iic(2, 0x78, 0x8f, 0x00, 0x00); |
691 | #if 0 | 664 | #if 0 |
692 | iic(2,0x78,0x90,0x00,0x00); /* AWB on=1 off=0 */ | 665 | iic(2, 0x78, 0x90, 0x00, 0x00); /* AWB on=1 off=0 */ |
693 | #endif | 666 | #endif |
694 | iic(2,0x78,0x93,0x01,0x00); | 667 | iic(2, 0x78, 0x93, 0x01, 0x00); |
695 | iic(2,0x78,0x94,0xcd,0x00); | 668 | iic(2, 0x78, 0x94, 0xcd, 0x00); |
696 | iic(2,0x78,0x95,0x00,0x00); | 669 | iic(2, 0x78, 0x95, 0x00, 0x00); |
697 | printk("."); | 670 | printk(KERN_CONT "."); |
698 | iic(2,0x78,0x96,0xa0,0x00); | 671 | iic(2, 0x78, 0x96, 0xa0, 0x00); |
699 | iic(2,0x78,0x97,0x00,0x00); | 672 | iic(2, 0x78, 0x97, 0x00, 0x00); |
700 | iic(2,0x78,0x98,0x60,0x00); | 673 | iic(2, 0x78, 0x98, 0x60, 0x00); |
701 | iic(2,0x78,0x99,0x01,0x00); | 674 | iic(2, 0x78, 0x99, 0x01, 0x00); |
702 | iic(2,0x78,0x9a,0x19,0x00); | 675 | iic(2, 0x78, 0x9a, 0x19, 0x00); |
703 | printk("."); | 676 | printk(KERN_CONT "."); |
704 | iic(2,0x78,0x9b,0x02,0x00); | 677 | iic(2, 0x78, 0x9b, 0x02, 0x00); |
705 | iic(2,0x78,0x9c,0xe8,0x00); | 678 | iic(2, 0x78, 0x9c, 0xe8, 0x00); |
706 | iic(2,0x78,0x9d,0x02,0x00); | 679 | iic(2, 0x78, 0x9d, 0x02, 0x00); |
707 | iic(2,0x78,0x9e,0x2e,0x00); | 680 | iic(2, 0x78, 0x9e, 0x2e, 0x00); |
708 | iic(2,0x78,0xb8,0x78,0x00); | 681 | iic(2, 0x78, 0xb8, 0x78, 0x00); |
709 | iic(2,0x78,0xba,0x05,0x00); | 682 | iic(2, 0x78, 0xba, 0x05, 0x00); |
710 | #if 0 | 683 | #if 0 |
711 | iic(2,0x78,0x83,0x8c,0x00); /* brightness */ | 684 | iic(2, 0x78, 0x83, 0x8c, 0x00); /* brightness */ |
712 | #endif | 685 | #endif |
713 | printk("."); | 686 | printk(KERN_CONT "."); |
714 | 687 | ||
715 | /* color correction */ | 688 | /* color correction */ |
716 | iic(3,0x78,0x49,0x00,0x95); /* a */ | 689 | iic(3, 0x78, 0x49, 0x00, 0x95); /* a */ |
717 | iic(3,0x78,0x49,0x01,0x96); /* b */ | 690 | iic(3, 0x78, 0x49, 0x01, 0x96); /* b */ |
718 | iic(3,0x78,0x49,0x03,0x85); /* c */ | 691 | iic(3, 0x78, 0x49, 0x03, 0x85); /* c */ |
719 | iic(3,0x78,0x49,0x04,0x97); /* d */ | 692 | iic(3, 0x78, 0x49, 0x04, 0x97); /* d */ |
720 | iic(3,0x78,0x49,0x02,0x7e); /* e(Lo) */ | 693 | iic(3, 0x78, 0x49, 0x02, 0x7e); /* e(Lo) */ |
721 | iic(3,0x78,0x49,0x05,0xa4); /* f(Lo) */ | 694 | iic(3, 0x78, 0x49, 0x05, 0xa4); /* f(Lo) */ |
722 | iic(3,0x78,0x49,0x06,0x04); /* e(Hi) */ | 695 | iic(3, 0x78, 0x49, 0x06, 0x04); /* e(Hi) */ |
723 | iic(3,0x78,0x49,0x07,0x04); /* e(Hi) */ | 696 | iic(3, 0x78, 0x49, 0x07, 0x04); /* e(Hi) */ |
724 | iic(2,0x78,0x48,0x01,0x00); /* on=1 off=0 */ | 697 | iic(2, 0x78, 0x48, 0x01, 0x00); /* on=1 off=0 */ |
725 | 698 | ||
726 | printk("."); | 699 | printk(KERN_CONT "."); |
727 | iic(2,0x78,0x11,0x00,0x00); /* end */ | 700 | iic(2, 0x78, 0x11, 0x00, 0x00); /* end */ |
728 | printk(" done\n"); | 701 | printk(KERN_CONT " done\n"); |
729 | return 0; | 702 | return 0; |
730 | } | 703 | } |
731 | 704 | ||
732 | 705 | ||
733 | void ar_release(struct video_device *vfd) | ||
734 | { | ||
735 | struct ar_device *ar = video_get_drvdata(vfd); | ||
736 | mutex_lock(&ar->lock); | ||
737 | video_device_release(vfd); | ||
738 | } | ||
739 | |||
740 | /**************************************************************************** | 706 | /**************************************************************************** |
741 | * | 707 | * |
742 | * Video4Linux Module functions | 708 | * Video4Linux Module functions |
743 | * | 709 | * |
744 | ****************************************************************************/ | 710 | ****************************************************************************/ |
745 | static struct ar_device ardev; | ||
746 | |||
747 | static int ar_exclusive_open(struct file *file) | ||
748 | { | ||
749 | return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; | ||
750 | } | ||
751 | |||
752 | static int ar_exclusive_release(struct file *file) | ||
753 | { | ||
754 | clear_bit(0, &ardev.in_use); | ||
755 | return 0; | ||
756 | } | ||
757 | 711 | ||
758 | static const struct v4l2_file_operations ar_fops = { | 712 | static const struct v4l2_file_operations ar_fops = { |
759 | .owner = THIS_MODULE, | 713 | .owner = THIS_MODULE, |
760 | .open = ar_exclusive_open, | ||
761 | .release = ar_exclusive_release, | ||
762 | .read = ar_read, | 714 | .read = ar_read, |
763 | .ioctl = ar_ioctl, | 715 | .ioctl = video_ioctl2, |
764 | }; | 716 | }; |
765 | 717 | ||
766 | static struct video_device ar_template = { | 718 | static const struct v4l2_ioctl_ops ar_ioctl_ops = { |
767 | .name = "Colour AR VGA", | 719 | .vidioc_querycap = ar_querycap, |
768 | .fops = &ar_fops, | 720 | .vidioc_g_input = ar_g_input, |
769 | .release = ar_release, | 721 | .vidioc_s_input = ar_s_input, |
722 | .vidioc_enum_input = ar_enum_input, | ||
723 | .vidioc_enum_fmt_vid_cap = ar_enum_fmt_vid_cap, | ||
724 | .vidioc_g_fmt_vid_cap = ar_g_fmt_vid_cap, | ||
725 | .vidioc_s_fmt_vid_cap = ar_s_fmt_vid_cap, | ||
726 | .vidioc_try_fmt_vid_cap = ar_try_fmt_vid_cap, | ||
770 | }; | 727 | }; |
771 | 728 | ||
772 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) | 729 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) |
773 | 730 | ||
774 | static int __init ar_init(void) | 731 | static int __init ar_init(void) |
775 | { | 732 | { |
776 | struct ar_device *ar; | 733 | struct ar *ar; |
734 | struct v4l2_device *v4l2_dev; | ||
777 | int ret; | 735 | int ret; |
778 | int i; | 736 | int i; |
779 | 737 | ||
780 | DEBUG(1, "ar_init:\n"); | ||
781 | ret = -EIO; | ||
782 | printk(KERN_INFO "arv: Colour AR VGA driver %s\n", VERSION); | ||
783 | |||
784 | ar = &ardev; | 738 | ar = &ardev; |
785 | memset(ar, 0, sizeof(struct ar_device)); | 739 | v4l2_dev = &ar->v4l2_dev; |
740 | strlcpy(v4l2_dev->name, "arv", sizeof(v4l2_dev->name)); | ||
741 | v4l2_info(v4l2_dev, "Colour AR VGA driver %s\n", VERSION); | ||
742 | |||
743 | ret = v4l2_device_register(NULL, v4l2_dev); | ||
744 | if (ret < 0) { | ||
745 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
746 | return ret; | ||
747 | } | ||
748 | ret = -EIO; | ||
786 | 749 | ||
787 | #if USE_INT | 750 | #if USE_INT |
788 | /* allocate a DMA buffer for 1 line. */ | 751 | /* allocate a DMA buffer for 1 line. */ |
789 | ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA); | 752 | ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA); |
790 | if (ar->line_buff == NULL || ! ALIGN4(ar->line_buff)) { | 753 | if (ar->line_buff == NULL || !ALIGN4(ar->line_buff)) { |
791 | printk("arv: buffer allocation failed for DMA.\n"); | 754 | v4l2_err(v4l2_dev, "buffer allocation failed for DMA.\n"); |
792 | ret = -ENOMEM; | 755 | ret = -ENOMEM; |
793 | goto out_end; | 756 | goto out_end; |
794 | } | 757 | } |
@@ -796,20 +759,19 @@ static int __init ar_init(void) | |||
796 | /* allocate buffers for a frame */ | 759 | /* allocate buffers for a frame */ |
797 | for (i = 0; i < MAX_AR_HEIGHT; i++) { | 760 | for (i = 0; i < MAX_AR_HEIGHT; i++) { |
798 | ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL); | 761 | ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL); |
799 | if (ar->frame[i] == NULL || ! ALIGN4(ar->frame[i])) { | 762 | if (ar->frame[i] == NULL || !ALIGN4(ar->frame[i])) { |
800 | printk("arv: buffer allocation failed for frame.\n"); | 763 | v4l2_err(v4l2_dev, "buffer allocation failed for frame.\n"); |
801 | ret = -ENOMEM; | 764 | ret = -ENOMEM; |
802 | goto out_line_buff; | 765 | goto out_line_buff; |
803 | } | 766 | } |
804 | } | 767 | } |
805 | 768 | ||
806 | ar->vdev = video_device_alloc(); | 769 | strlcpy(ar->vdev.name, "Colour AR VGA", sizeof(ar->vdev.name)); |
807 | if (!ar->vdev) { | 770 | ar->vdev.v4l2_dev = v4l2_dev; |
808 | printk(KERN_ERR "arv: video_device_alloc() failed\n"); | 771 | ar->vdev.fops = &ar_fops; |
809 | return -ENOMEM; | 772 | ar->vdev.ioctl_ops = &ar_ioctl_ops; |
810 | } | 773 | ar->vdev.release = video_device_release_empty; |
811 | memcpy(ar->vdev, &ar_template, sizeof(ar_template)); | 774 | video_set_drvdata(&ar->vdev, ar); |
812 | video_set_drvdata(ar->vdev, ar); | ||
813 | 775 | ||
814 | if (vga) { | 776 | if (vga) { |
815 | ar->width = AR_WIDTH_VGA; | 777 | ar->width = AR_WIDTH_VGA; |
@@ -834,14 +796,14 @@ static int __init ar_init(void) | |||
834 | 796 | ||
835 | #if USE_INT | 797 | #if USE_INT |
836 | if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) { | 798 | if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) { |
837 | printk("arv: request_irq(%d) failed.\n", M32R_IRQ_INT3); | 799 | v4l2_err("request_irq(%d) failed.\n", M32R_IRQ_INT3); |
838 | ret = -EIO; | 800 | ret = -EIO; |
839 | goto out_irq; | 801 | goto out_irq; |
840 | } | 802 | } |
841 | #endif | 803 | #endif |
842 | 804 | ||
843 | if (ar_initialize(ar->vdev) != 0) { | 805 | if (ar_initialize(ar) != 0) { |
844 | printk("arv: M64278 not found.\n"); | 806 | v4l2_err(v4l2_dev, "M64278 not found.\n"); |
845 | ret = -ENODEV; | 807 | ret = -ENODEV; |
846 | goto out_dev; | 808 | goto out_dev; |
847 | } | 809 | } |
@@ -852,15 +814,15 @@ static int __init ar_init(void) | |||
852 | * device is named "video[0-64]". | 814 | * device is named "video[0-64]". |
853 | * video_register_device() initializes h/w using ar_initialize(). | 815 | * video_register_device() initializes h/w using ar_initialize(). |
854 | */ | 816 | */ |
855 | if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { | 817 | if (video_register_device(&ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { |
856 | /* return -1, -ENFILE(full) or others */ | 818 | /* return -1, -ENFILE(full) or others */ |
857 | printk("arv: register video (Colour AR) failed.\n"); | 819 | v4l2_err(v4l2_dev, "register video (Colour AR) failed.\n"); |
858 | ret = -ENODEV; | 820 | ret = -ENODEV; |
859 | goto out_dev; | 821 | goto out_dev; |
860 | } | 822 | } |
861 | 823 | ||
862 | printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", | 824 | v4l2_info(v4l2_dev, "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", |
863 | video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq); | 825 | video_device_node_name(&ar->vdev), M32R_IRQ_INT3, freq); |
864 | 826 | ||
865 | return 0; | 827 | return 0; |
866 | 828 | ||
@@ -879,6 +841,7 @@ out_line_buff: | |||
879 | 841 | ||
880 | out_end: | 842 | out_end: |
881 | #endif | 843 | #endif |
844 | v4l2_device_unregister(&ar->v4l2_dev); | ||
882 | return ret; | 845 | return ret; |
883 | } | 846 | } |
884 | 847 | ||
@@ -886,7 +849,7 @@ out_end: | |||
886 | static int __init ar_init_module(void) | 849 | static int __init ar_init_module(void) |
887 | { | 850 | { |
888 | freq = (boot_cpu_data.bus_clock / 1000000); | 851 | freq = (boot_cpu_data.bus_clock / 1000000); |
889 | printk("arv: Bus clock %d\n", freq); | 852 | printk(KERN_INFO "arv: Bus clock %d\n", freq); |
890 | if (freq != 50 && freq != 75) | 853 | if (freq != 50 && freq != 75) |
891 | freq = DEFAULT_FREQ; | 854 | freq = DEFAULT_FREQ; |
892 | return ar_init(); | 855 | return ar_init(); |
@@ -894,11 +857,11 @@ static int __init ar_init_module(void) | |||
894 | 857 | ||
895 | static void __exit ar_cleanup_module(void) | 858 | static void __exit ar_cleanup_module(void) |
896 | { | 859 | { |
897 | struct ar_device *ar; | 860 | struct ar *ar; |
898 | int i; | 861 | int i; |
899 | 862 | ||
900 | ar = &ardev; | 863 | ar = &ardev; |
901 | video_unregister_device(ar->vdev); | 864 | video_unregister_device(&ar->vdev); |
902 | #if USE_INT | 865 | #if USE_INT |
903 | free_irq(M32R_IRQ_INT3, ar); | 866 | free_irq(M32R_IRQ_INT3, ar); |
904 | #endif | 867 | #endif |
@@ -907,6 +870,7 @@ static void __exit ar_cleanup_module(void) | |||
907 | #if USE_INT | 870 | #if USE_INT |
908 | kfree(ar->line_buff); | 871 | kfree(ar->line_buff); |
909 | #endif | 872 | #endif |
873 | v4l2_device_unregister(&ar->v4l2_dev); | ||
910 | } | 874 | } |
911 | 875 | ||
912 | module_init(ar_init_module); | 876 | module_init(ar_init_module); |
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 8c140c01c5e6..66150216f976 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -1105,7 +1105,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1105 | 1105 | ||
1106 | tmp = input->index; | 1106 | tmp = input->index; |
1107 | 1107 | ||
1108 | if (tmp > AU0828_MAX_INPUT) | 1108 | if (tmp >= AU0828_MAX_INPUT) |
1109 | return -EINVAL; | 1109 | return -EINVAL; |
1110 | if (AUVI_INPUT(tmp).type == 0) | 1110 | if (AUVI_INPUT(tmp).type == 0) |
1111 | return -EINVAL; | 1111 | return -EINVAL; |
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 716870ae85d5..7af56cde0c79 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -241,6 +241,10 @@ static struct CARD { | |||
241 | { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, | 241 | { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, |
242 | { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, | 242 | { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, |
243 | { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, | 243 | { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, |
244 | { 0xa1550800, BTTV_BOARD_IVC200, "IVC-200" }, | ||
245 | { 0xa1550801, BTTV_BOARD_IVC200, "IVC-200" }, | ||
246 | { 0xa1550802, BTTV_BOARD_IVC200, "IVC-200" }, | ||
247 | { 0xa1550803, BTTV_BOARD_IVC200, "IVC-200" }, | ||
244 | { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, | 248 | { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, |
245 | { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, | 249 | { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, |
246 | { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, | 250 | { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index f4860f03dfc3..38c7f78ad9cf 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -1525,7 +1525,7 @@ static int bttv_s_ctrl(struct file *file, void *f, | |||
1525 | struct bttv_fh *fh = f; | 1525 | struct bttv_fh *fh = f; |
1526 | struct bttv *btv = fh->btv; | 1526 | struct bttv *btv = fh->btv; |
1527 | 1527 | ||
1528 | err = v4l2_prio_check(&btv->prio, &fh->prio); | 1528 | err = v4l2_prio_check(&btv->prio, fh->prio); |
1529 | if (0 != err) | 1529 | if (0 != err) |
1530 | return err; | 1530 | return err; |
1531 | 1531 | ||
@@ -1806,8 +1806,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |||
1806 | *size = fh->fmt->depth*fh->width*fh->height >> 3; | 1806 | *size = fh->fmt->depth*fh->width*fh->height >> 3; |
1807 | if (0 == *count) | 1807 | if (0 == *count) |
1808 | *count = gbuffers; | 1808 | *count = gbuffers; |
1809 | while (*size * *count > gbuffers * gbufsize) | 1809 | if (*size * *count > gbuffers * gbufsize) |
1810 | (*count)--; | 1810 | *count = (gbuffers * gbufsize) / *size; |
1811 | return 0; | 1811 | return 0; |
1812 | } | 1812 | } |
1813 | 1813 | ||
@@ -1859,7 +1859,7 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
1859 | unsigned int i; | 1859 | unsigned int i; |
1860 | int err; | 1860 | int err; |
1861 | 1861 | ||
1862 | err = v4l2_prio_check(&btv->prio, &fh->prio); | 1862 | err = v4l2_prio_check(&btv->prio, fh->prio); |
1863 | if (0 != err) | 1863 | if (0 != err) |
1864 | return err; | 1864 | return err; |
1865 | 1865 | ||
@@ -1941,7 +1941,7 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i) | |||
1941 | 1941 | ||
1942 | int err; | 1942 | int err; |
1943 | 1943 | ||
1944 | err = v4l2_prio_check(&btv->prio, &fh->prio); | 1944 | err = v4l2_prio_check(&btv->prio, fh->prio); |
1945 | if (0 != err) | 1945 | if (0 != err) |
1946 | return err; | 1946 | return err; |
1947 | 1947 | ||
@@ -1961,7 +1961,7 @@ static int bttv_s_tuner(struct file *file, void *priv, | |||
1961 | struct bttv *btv = fh->btv; | 1961 | struct bttv *btv = fh->btv; |
1962 | int err; | 1962 | int err; |
1963 | 1963 | ||
1964 | err = v4l2_prio_check(&btv->prio, &fh->prio); | 1964 | err = v4l2_prio_check(&btv->prio, fh->prio); |
1965 | if (0 != err) | 1965 | if (0 != err) |
1966 | return err; | 1966 | return err; |
1967 | 1967 | ||
@@ -1987,11 +1987,6 @@ static int bttv_g_frequency(struct file *file, void *priv, | |||
1987 | { | 1987 | { |
1988 | struct bttv_fh *fh = priv; | 1988 | struct bttv_fh *fh = priv; |
1989 | struct bttv *btv = fh->btv; | 1989 | struct bttv *btv = fh->btv; |
1990 | int err; | ||
1991 | |||
1992 | err = v4l2_prio_check(&btv->prio, &fh->prio); | ||
1993 | if (0 != err) | ||
1994 | return err; | ||
1995 | 1990 | ||
1996 | f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | 1991 | f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; |
1997 | f->frequency = btv->freq; | 1992 | f->frequency = btv->freq; |
@@ -2006,7 +2001,7 @@ static int bttv_s_frequency(struct file *file, void *priv, | |||
2006 | struct bttv *btv = fh->btv; | 2001 | struct bttv *btv = fh->btv; |
2007 | int err; | 2002 | int err; |
2008 | 2003 | ||
2009 | err = v4l2_prio_check(&btv->prio, &fh->prio); | 2004 | err = v4l2_prio_check(&btv->prio, fh->prio); |
2010 | if (0 != err) | 2005 | if (0 != err) |
2011 | return err; | 2006 | return err; |
2012 | 2007 | ||
@@ -3029,7 +3024,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) | |||
3029 | crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) | 3024 | crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) |
3030 | return -EINVAL; | 3025 | return -EINVAL; |
3031 | 3026 | ||
3032 | retval = v4l2_prio_check(&btv->prio, &fh->prio); | 3027 | retval = v4l2_prio_check(&btv->prio, fh->prio); |
3033 | if (0 != retval) | 3028 | if (0 != retval) |
3034 | return retval; | 3029 | return retval; |
3035 | 3030 | ||
@@ -3241,7 +3236,7 @@ static int bttv_open(struct file *file) | |||
3241 | *fh = btv->init; | 3236 | *fh = btv->init; |
3242 | fh->type = type; | 3237 | fh->type = type; |
3243 | fh->ov.setup_ok = 0; | 3238 | fh->ov.setup_ok = 0; |
3244 | v4l2_prio_open(&btv->prio,&fh->prio); | 3239 | v4l2_prio_open(&btv->prio, &fh->prio); |
3245 | 3240 | ||
3246 | videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, | 3241 | videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, |
3247 | &btv->c.pci->dev, &btv->s_lock, | 3242 | &btv->c.pci->dev, &btv->s_lock, |
@@ -3312,7 +3307,7 @@ static int bttv_release(struct file *file) | |||
3312 | /* free stuff */ | 3307 | /* free stuff */ |
3313 | videobuf_mmap_free(&fh->cap); | 3308 | videobuf_mmap_free(&fh->cap); |
3314 | videobuf_mmap_free(&fh->vbi); | 3309 | videobuf_mmap_free(&fh->vbi); |
3315 | v4l2_prio_close(&btv->prio,&fh->prio); | 3310 | v4l2_prio_close(&btv->prio, fh->prio); |
3316 | file->private_data = NULL; | 3311 | file->private_data = NULL; |
3317 | kfree(fh); | 3312 | kfree(fh); |
3318 | 3313 | ||
@@ -3449,7 +3444,7 @@ static int radio_release(struct file *file) | |||
3449 | struct bttv *btv = fh->btv; | 3444 | struct bttv *btv = fh->btv; |
3450 | struct rds_command cmd; | 3445 | struct rds_command cmd; |
3451 | 3446 | ||
3452 | v4l2_prio_close(&btv->prio,&fh->prio); | 3447 | v4l2_prio_close(&btv->prio, fh->prio); |
3453 | file->private_data = NULL; | 3448 | file->private_data = NULL; |
3454 | kfree(fh); | 3449 | kfree(fh); |
3455 | 3450 | ||
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index aa153a986ade..f68717a4bdec 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -49,6 +49,8 @@ module_param(ir_rc5_key_timeout, int, 0644); | |||
49 | 49 | ||
50 | #define DEVNAME "bttv-input" | 50 | #define DEVNAME "bttv-input" |
51 | 51 | ||
52 | #define MODULE_NAME "bttv" | ||
53 | |||
52 | /* ---------------------------------------------------------------------- */ | 54 | /* ---------------------------------------------------------------------- */ |
53 | 55 | ||
54 | static void ir_handle_key(struct bttv *btv) | 56 | static void ir_handle_key(struct bttv *btv) |
@@ -246,7 +248,7 @@ static void bttv_ir_stop(struct bttv *btv) | |||
246 | int bttv_input_init(struct bttv *btv) | 248 | int bttv_input_init(struct bttv *btv) |
247 | { | 249 | { |
248 | struct card_ir *ir; | 250 | struct card_ir *ir; |
249 | struct ir_scancode_table *ir_codes = NULL; | 251 | char *ir_codes = NULL; |
250 | struct input_dev *input_dev; | 252 | struct input_dev *input_dev; |
251 | u64 ir_type = IR_TYPE_OTHER; | 253 | u64 ir_type = IR_TYPE_OTHER; |
252 | int err = -ENOMEM; | 254 | int err = -ENOMEM; |
@@ -264,7 +266,7 @@ int bttv_input_init(struct bttv *btv) | |||
264 | case BTTV_BOARD_AVERMEDIA: | 266 | case BTTV_BOARD_AVERMEDIA: |
265 | case BTTV_BOARD_AVPHONE98: | 267 | case BTTV_BOARD_AVPHONE98: |
266 | case BTTV_BOARD_AVERMEDIA98: | 268 | case BTTV_BOARD_AVERMEDIA98: |
267 | ir_codes = &ir_codes_avermedia_table; | 269 | ir_codes = RC_MAP_AVERMEDIA; |
268 | ir->mask_keycode = 0xf88000; | 270 | ir->mask_keycode = 0xf88000; |
269 | ir->mask_keydown = 0x010000; | 271 | ir->mask_keydown = 0x010000; |
270 | ir->polling = 50; // ms | 272 | ir->polling = 50; // ms |
@@ -272,14 +274,14 @@ int bttv_input_init(struct bttv *btv) | |||
272 | 274 | ||
273 | case BTTV_BOARD_AVDVBT_761: | 275 | case BTTV_BOARD_AVDVBT_761: |
274 | case BTTV_BOARD_AVDVBT_771: | 276 | case BTTV_BOARD_AVDVBT_771: |
275 | ir_codes = &ir_codes_avermedia_dvbt_table; | 277 | ir_codes = RC_MAP_AVERMEDIA_DVBT; |
276 | ir->mask_keycode = 0x0f00c0; | 278 | ir->mask_keycode = 0x0f00c0; |
277 | ir->mask_keydown = 0x000020; | 279 | ir->mask_keydown = 0x000020; |
278 | ir->polling = 50; // ms | 280 | ir->polling = 50; // ms |
279 | break; | 281 | break; |
280 | 282 | ||
281 | case BTTV_BOARD_PXELVWPLTVPAK: | 283 | case BTTV_BOARD_PXELVWPLTVPAK: |
282 | ir_codes = &ir_codes_pixelview_table; | 284 | ir_codes = RC_MAP_PIXELVIEW; |
283 | ir->mask_keycode = 0x003e00; | 285 | ir->mask_keycode = 0x003e00; |
284 | ir->mask_keyup = 0x010000; | 286 | ir->mask_keyup = 0x010000; |
285 | ir->polling = 50; // ms | 287 | ir->polling = 50; // ms |
@@ -287,24 +289,24 @@ int bttv_input_init(struct bttv *btv) | |||
287 | case BTTV_BOARD_PV_M4900: | 289 | case BTTV_BOARD_PV_M4900: |
288 | case BTTV_BOARD_PV_BT878P_9B: | 290 | case BTTV_BOARD_PV_BT878P_9B: |
289 | case BTTV_BOARD_PV_BT878P_PLUS: | 291 | case BTTV_BOARD_PV_BT878P_PLUS: |
290 | ir_codes = &ir_codes_pixelview_table; | 292 | ir_codes = RC_MAP_PIXELVIEW; |
291 | ir->mask_keycode = 0x001f00; | 293 | ir->mask_keycode = 0x001f00; |
292 | ir->mask_keyup = 0x008000; | 294 | ir->mask_keyup = 0x008000; |
293 | ir->polling = 50; // ms | 295 | ir->polling = 50; // ms |
294 | break; | 296 | break; |
295 | 297 | ||
296 | case BTTV_BOARD_WINFAST2000: | 298 | case BTTV_BOARD_WINFAST2000: |
297 | ir_codes = &ir_codes_winfast_table; | 299 | ir_codes = RC_MAP_WINFAST; |
298 | ir->mask_keycode = 0x1f8; | 300 | ir->mask_keycode = 0x1f8; |
299 | break; | 301 | break; |
300 | case BTTV_BOARD_MAGICTVIEW061: | 302 | case BTTV_BOARD_MAGICTVIEW061: |
301 | case BTTV_BOARD_MAGICTVIEW063: | 303 | case BTTV_BOARD_MAGICTVIEW063: |
302 | ir_codes = &ir_codes_winfast_table; | 304 | ir_codes = RC_MAP_WINFAST; |
303 | ir->mask_keycode = 0x0008e000; | 305 | ir->mask_keycode = 0x0008e000; |
304 | ir->mask_keydown = 0x00200000; | 306 | ir->mask_keydown = 0x00200000; |
305 | break; | 307 | break; |
306 | case BTTV_BOARD_APAC_VIEWCOMP: | 308 | case BTTV_BOARD_APAC_VIEWCOMP: |
307 | ir_codes = &ir_codes_apac_viewcomp_table; | 309 | ir_codes = RC_MAP_APAC_VIEWCOMP; |
308 | ir->mask_keycode = 0x001f00; | 310 | ir->mask_keycode = 0x001f00; |
309 | ir->mask_keyup = 0x008000; | 311 | ir->mask_keyup = 0x008000; |
310 | ir->polling = 50; // ms | 312 | ir->polling = 50; // ms |
@@ -312,30 +314,30 @@ int bttv_input_init(struct bttv *btv) | |||
312 | case BTTV_BOARD_ASKEY_CPH03X: | 314 | case BTTV_BOARD_ASKEY_CPH03X: |
313 | case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: | 315 | case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: |
314 | case BTTV_BOARD_CONTVFMI: | 316 | case BTTV_BOARD_CONTVFMI: |
315 | ir_codes = &ir_codes_pixelview_table; | 317 | ir_codes = RC_MAP_PIXELVIEW; |
316 | ir->mask_keycode = 0x001F00; | 318 | ir->mask_keycode = 0x001F00; |
317 | ir->mask_keyup = 0x006000; | 319 | ir->mask_keyup = 0x006000; |
318 | ir->polling = 50; // ms | 320 | ir->polling = 50; // ms |
319 | break; | 321 | break; |
320 | case BTTV_BOARD_NEBULA_DIGITV: | 322 | case BTTV_BOARD_NEBULA_DIGITV: |
321 | ir_codes = &ir_codes_nebula_table; | 323 | ir_codes = RC_MAP_NEBULA; |
322 | btv->custom_irq = bttv_rc5_irq; | 324 | btv->custom_irq = bttv_rc5_irq; |
323 | ir->rc5_gpio = 1; | 325 | ir->rc5_gpio = 1; |
324 | break; | 326 | break; |
325 | case BTTV_BOARD_MACHTV_MAGICTV: | 327 | case BTTV_BOARD_MACHTV_MAGICTV: |
326 | ir_codes = &ir_codes_apac_viewcomp_table; | 328 | ir_codes = RC_MAP_APAC_VIEWCOMP; |
327 | ir->mask_keycode = 0x001F00; | 329 | ir->mask_keycode = 0x001F00; |
328 | ir->mask_keyup = 0x004000; | 330 | ir->mask_keyup = 0x004000; |
329 | ir->polling = 50; /* ms */ | 331 | ir->polling = 50; /* ms */ |
330 | break; | 332 | break; |
331 | case BTTV_BOARD_KOZUMI_KTV_01C: | 333 | case BTTV_BOARD_KOZUMI_KTV_01C: |
332 | ir_codes = &ir_codes_pctv_sedna_table; | 334 | ir_codes = RC_MAP_PCTV_SEDNA; |
333 | ir->mask_keycode = 0x001f00; | 335 | ir->mask_keycode = 0x001f00; |
334 | ir->mask_keyup = 0x006000; | 336 | ir->mask_keyup = 0x006000; |
335 | ir->polling = 50; /* ms */ | 337 | ir->polling = 50; /* ms */ |
336 | break; | 338 | break; |
337 | case BTTV_BOARD_ENLTV_FM_2: | 339 | case BTTV_BOARD_ENLTV_FM_2: |
338 | ir_codes = &ir_codes_encore_enltv2_table; | 340 | ir_codes = RC_MAP_ENCORE_ENLTV2; |
339 | ir->mask_keycode = 0x00fd00; | 341 | ir->mask_keycode = 0x00fd00; |
340 | ir->mask_keyup = 0x000080; | 342 | ir->mask_keyup = 0x000080; |
341 | ir->polling = 1; /* ms */ | 343 | ir->polling = 1; /* ms */ |
@@ -390,7 +392,7 @@ int bttv_input_init(struct bttv *btv) | |||
390 | bttv_ir_start(btv, ir); | 392 | bttv_ir_start(btv, ir); |
391 | 393 | ||
392 | /* all done */ | 394 | /* all done */ |
393 | err = ir_input_register(btv->remote->dev, ir_codes, NULL); | 395 | err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); |
394 | if (err) | 396 | if (err) |
395 | goto err_out_stop; | 397 | goto err_out_stop; |
396 | 398 | ||
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 9e39bc5f7b00..3c9e754d73a0 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
@@ -80,8 +80,8 @@ OTHER DEALINGS IN THE SOFTWARE. | |||
80 | 80 | ||
81 | #include "bw-qcam.h" | 81 | #include "bw-qcam.h" |
82 | 82 | ||
83 | static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */ | 83 | static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ |
84 | static unsigned int yieldlines=4; /* Yield after this many during capture */ | 84 | static unsigned int yieldlines = 4; /* Yield after this many during capture */ |
85 | static int video_nr = -1; | 85 | static int video_nr = -1; |
86 | static unsigned int force_init; /* Whether to probe aggressively */ | 86 | static unsigned int force_init; /* Whether to probe aggressively */ |
87 | 87 | ||
@@ -156,7 +156,7 @@ static int qc_calibrate(struct qcam_device *q) | |||
156 | mdelay(1); | 156 | mdelay(1); |
157 | schedule(); | 157 | schedule(); |
158 | count++; | 158 | count++; |
159 | } while (value == 0xff && count<2048); | 159 | } while (value == 0xff && count < 2048); |
160 | 160 | ||
161 | q->whitebal = value; | 161 | q->whitebal = value; |
162 | return value; | 162 | return value; |
@@ -170,16 +170,15 @@ static struct qcam_device *qcam_init(struct parport *port) | |||
170 | struct qcam_device *q; | 170 | struct qcam_device *q; |
171 | 171 | ||
172 | q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); | 172 | q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); |
173 | if(q==NULL) | 173 | if (q == NULL) |
174 | return NULL; | 174 | return NULL; |
175 | 175 | ||
176 | q->pport = port; | 176 | q->pport = port; |
177 | q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, | 177 | q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, |
178 | NULL, 0, NULL); | 178 | NULL, 0, NULL); |
179 | if (q->pdev == NULL) | 179 | if (q->pdev == NULL) { |
180 | { | ||
181 | printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", | 180 | printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", |
182 | port->name); | 181 | port->name); |
183 | kfree(q); | 182 | kfree(q); |
184 | return NULL; | 183 | return NULL; |
185 | } | 184 | } |
@@ -247,12 +246,10 @@ static int qc_readparam(struct qcam_device *q) | |||
247 | static int qc_waithand(struct qcam_device *q, int val) | 246 | static int qc_waithand(struct qcam_device *q, int val) |
248 | { | 247 | { |
249 | int status; | 248 | int status; |
250 | int runs=0; | 249 | int runs = 0; |
251 | 250 | ||
252 | if (val) | 251 | if (val) { |
253 | { | 252 | while (!((status = read_lpstatus(q)) & 8)) { |
254 | while (!((status = read_lpstatus(q)) & 8)) | ||
255 | { | ||
256 | /* 1000 is enough spins on the I/O for all normal | 253 | /* 1000 is enough spins on the I/O for all normal |
257 | cases, at that point we start to poll slowly | 254 | cases, at that point we start to poll slowly |
258 | until the camera wakes up. However, we are | 255 | until the camera wakes up. However, we are |
@@ -260,18 +257,13 @@ static int qc_waithand(struct qcam_device *q, int val) | |||
260 | setting it lower is much better for interactive | 257 | setting it lower is much better for interactive |
261 | response. */ | 258 | response. */ |
262 | 259 | ||
263 | if(runs++>maxpoll) | 260 | if (runs++ > maxpoll) |
264 | { | ||
265 | msleep_interruptible(5); | 261 | msleep_interruptible(5); |
266 | } | 262 | if (runs > (maxpoll + 1000)) /* 5 seconds */ |
267 | if(runs>(maxpoll+1000)) /* 5 seconds */ | ||
268 | return -1; | 263 | return -1; |
269 | } | 264 | } |
270 | } | 265 | } else { |
271 | else | 266 | while (((status = read_lpstatus(q)) & 8)) { |
272 | { | ||
273 | while (((status = read_lpstatus(q)) & 8)) | ||
274 | { | ||
275 | /* 1000 is enough spins on the I/O for all normal | 267 | /* 1000 is enough spins on the I/O for all normal |
276 | cases, at that point we start to poll slowly | 268 | cases, at that point we start to poll slowly |
277 | until the camera wakes up. However, we are | 269 | until the camera wakes up. However, we are |
@@ -279,11 +271,9 @@ static int qc_waithand(struct qcam_device *q, int val) | |||
279 | setting it lower is much better for interactive | 271 | setting it lower is much better for interactive |
280 | response. */ | 272 | response. */ |
281 | 273 | ||
282 | if(runs++>maxpoll) | 274 | if (runs++ > maxpoll) |
283 | { | ||
284 | msleep_interruptible(5); | 275 | msleep_interruptible(5); |
285 | } | 276 | if (runs++ > (maxpoll + 1000)) /* 5 seconds */ |
286 | if(runs++>(maxpoll+1000)) /* 5 seconds */ | ||
287 | return -1; | 277 | return -1; |
288 | } | 278 | } |
289 | } | 279 | } |
@@ -299,10 +289,9 @@ static int qc_waithand(struct qcam_device *q, int val) | |||
299 | static unsigned int qc_waithand2(struct qcam_device *q, int val) | 289 | static unsigned int qc_waithand2(struct qcam_device *q, int val) |
300 | { | 290 | { |
301 | unsigned int status; | 291 | unsigned int status; |
302 | int runs=0; | 292 | int runs = 0; |
303 | 293 | ||
304 | do | 294 | do { |
305 | { | ||
306 | status = read_lpdata(q); | 295 | status = read_lpdata(q); |
307 | /* 1000 is enough spins on the I/O for all normal | 296 | /* 1000 is enough spins on the I/O for all normal |
308 | cases, at that point we start to poll slowly | 297 | cases, at that point we start to poll slowly |
@@ -311,14 +300,11 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) | |||
311 | setting it lower is much better for interactive | 300 | setting it lower is much better for interactive |
312 | response. */ | 301 | response. */ |
313 | 302 | ||
314 | if(runs++>maxpoll) | 303 | if (runs++ > maxpoll) |
315 | { | ||
316 | msleep_interruptible(5); | 304 | msleep_interruptible(5); |
317 | } | 305 | if (runs++ > (maxpoll + 1000)) /* 5 seconds */ |
318 | if(runs++>(maxpoll+1000)) /* 5 seconds */ | ||
319 | return 0; | 306 | return 0; |
320 | } | 307 | } while ((status & 1) != val); |
321 | while ((status & 1) != val); | ||
322 | 308 | ||
323 | return status; | 309 | return status; |
324 | } | 310 | } |
@@ -342,8 +328,7 @@ static int qc_detect(struct qcam_device *q) | |||
342 | 328 | ||
343 | lastreg = reg = read_lpstatus(q) & 0xf0; | 329 | lastreg = reg = read_lpstatus(q) & 0xf0; |
344 | 330 | ||
345 | for (i = 0; i < 500; i++) | 331 | for (i = 0; i < 500; i++) { |
346 | { | ||
347 | reg = read_lpstatus(q) & 0xf0; | 332 | reg = read_lpstatus(q) & 0xf0; |
348 | if (reg != lastreg) | 333 | if (reg != lastreg) |
349 | count++; | 334 | count++; |
@@ -357,7 +342,7 @@ static int qc_detect(struct qcam_device *q) | |||
357 | won't be flashing these bits. Possibly unloading the module | 342 | won't be flashing these bits. Possibly unloading the module |
358 | in the middle of a grab? Or some timeout condition? | 343 | in the middle of a grab? Or some timeout condition? |
359 | I've seen this parameter as low as 19 on my 450Mhz box - mpc */ | 344 | I've seen this parameter as low as 19 on my 450Mhz box - mpc */ |
360 | printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); | 345 | printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); |
361 | return 1; | 346 | return 1; |
362 | #endif | 347 | #endif |
363 | 348 | ||
@@ -367,7 +352,7 @@ static int qc_detect(struct qcam_device *q) | |||
367 | return 1; /* found */ | 352 | return 1; /* found */ |
368 | } else { | 353 | } else { |
369 | printk(KERN_ERR "No Quickcam found on port %s\n", | 354 | printk(KERN_ERR "No Quickcam found on port %s\n", |
370 | q->pport->name); | 355 | q->pport->name); |
371 | printk(KERN_DEBUG "Quickcam detection counter: %u\n", count); | 356 | printk(KERN_DEBUG "Quickcam detection counter: %u\n", count); |
372 | return 0; /* not found */ | 357 | return 0; /* not found */ |
373 | } | 358 | } |
@@ -381,26 +366,24 @@ static int qc_detect(struct qcam_device *q) | |||
381 | 366 | ||
382 | static void qc_reset(struct qcam_device *q) | 367 | static void qc_reset(struct qcam_device *q) |
383 | { | 368 | { |
384 | switch (q->port_mode & QC_FORCE_MASK) | 369 | switch (q->port_mode & QC_FORCE_MASK) { |
385 | { | 370 | case QC_FORCE_UNIDIR: |
386 | case QC_FORCE_UNIDIR: | 371 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; |
387 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | 372 | break; |
388 | break; | ||
389 | 373 | ||
390 | case QC_FORCE_BIDIR: | 374 | case QC_FORCE_BIDIR: |
391 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | 375 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; |
392 | break; | 376 | break; |
393 | 377 | ||
394 | case QC_ANY: | 378 | case QC_ANY: |
395 | write_lpcontrol(q, 0x20); | 379 | write_lpcontrol(q, 0x20); |
396 | write_lpdata(q, 0x75); | 380 | write_lpdata(q, 0x75); |
397 | 381 | ||
398 | if (read_lpdata(q) != 0x75) { | 382 | if (read_lpdata(q) != 0x75) |
399 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | 383 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; |
400 | } else { | 384 | else |
401 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | 385 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; |
402 | } | 386 | break; |
403 | break; | ||
404 | } | 387 | } |
405 | 388 | ||
406 | write_lpcontrol(q, 0xb); | 389 | write_lpcontrol(q, 0xb); |
@@ -423,36 +406,33 @@ static int qc_setscanmode(struct qcam_device *q) | |||
423 | { | 406 | { |
424 | int old_mode = q->mode; | 407 | int old_mode = q->mode; |
425 | 408 | ||
426 | switch (q->transfer_scale) | 409 | switch (q->transfer_scale) { |
427 | { | 410 | case 1: |
428 | case 1: | 411 | q->mode = 0; |
429 | q->mode = 0; | 412 | break; |
430 | break; | 413 | case 2: |
431 | case 2: | 414 | q->mode = 4; |
432 | q->mode = 4; | 415 | break; |
433 | break; | 416 | case 4: |
434 | case 4: | 417 | q->mode = 8; |
435 | q->mode = 8; | 418 | break; |
436 | break; | ||
437 | } | 419 | } |
438 | 420 | ||
439 | switch (q->bpp) | 421 | switch (q->bpp) { |
440 | { | 422 | case 4: |
441 | case 4: | 423 | break; |
442 | break; | 424 | case 6: |
443 | case 6: | 425 | q->mode += 2; |
444 | q->mode += 2; | 426 | break; |
445 | break; | ||
446 | } | 427 | } |
447 | 428 | ||
448 | switch (q->port_mode & QC_MODE_MASK) | 429 | switch (q->port_mode & QC_MODE_MASK) { |
449 | { | 430 | case QC_BIDIR: |
450 | case QC_BIDIR: | 431 | q->mode += 1; |
451 | q->mode += 1; | 432 | break; |
452 | break; | 433 | case QC_NOTSET: |
453 | case QC_NOTSET: | 434 | case QC_UNIDIR: |
454 | case QC_UNIDIR: | 435 | break; |
455 | break; | ||
456 | } | 436 | } |
457 | 437 | ||
458 | if (q->mode != old_mode) | 438 | if (q->mode != old_mode) |
@@ -493,7 +473,7 @@ static void qc_set(struct qcam_device *q) | |||
493 | } else { | 473 | } else { |
494 | val = q->width * q->bpp; | 474 | val = q->width * q->bpp; |
495 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 475 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
496 | q->transfer_scale; | 476 | q->transfer_scale; |
497 | } | 477 | } |
498 | val = DIV_ROUND_UP(val, val2); | 478 | val = DIV_ROUND_UP(val, val2); |
499 | qc_command(q, 0x13); | 479 | qc_command(q, 0x13); |
@@ -521,85 +501,80 @@ static void qc_set(struct qcam_device *q) | |||
521 | 501 | ||
522 | static inline int qc_readbytes(struct qcam_device *q, char buffer[]) | 502 | static inline int qc_readbytes(struct qcam_device *q, char buffer[]) |
523 | { | 503 | { |
524 | int ret=1; | 504 | int ret = 1; |
525 | unsigned int hi, lo; | 505 | unsigned int hi, lo; |
526 | unsigned int hi2, lo2; | 506 | unsigned int hi2, lo2; |
527 | static int state; | 507 | static int state; |
528 | 508 | ||
529 | if (buffer == NULL) | 509 | if (buffer == NULL) { |
530 | { | ||
531 | state = 0; | 510 | state = 0; |
532 | return 0; | 511 | return 0; |
533 | } | 512 | } |
534 | 513 | ||
535 | switch (q->port_mode & QC_MODE_MASK) | 514 | switch (q->port_mode & QC_MODE_MASK) { |
536 | { | 515 | case QC_BIDIR: /* Bi-directional Port */ |
537 | case QC_BIDIR: /* Bi-directional Port */ | 516 | write_lpcontrol(q, 0x26); |
538 | write_lpcontrol(q, 0x26); | 517 | lo = (qc_waithand2(q, 1) >> 1); |
539 | lo = (qc_waithand2(q, 1) >> 1); | 518 | hi = (read_lpstatus(q) >> 3) & 0x1f; |
540 | hi = (read_lpstatus(q) >> 3) & 0x1f; | 519 | write_lpcontrol(q, 0x2e); |
541 | write_lpcontrol(q, 0x2e); | 520 | lo2 = (qc_waithand2(q, 0) >> 1); |
542 | lo2 = (qc_waithand2(q, 0) >> 1); | 521 | hi2 = (read_lpstatus(q) >> 3) & 0x1f; |
543 | hi2 = (read_lpstatus(q) >> 3) & 0x1f; | 522 | switch (q->bpp) { |
544 | switch (q->bpp) | 523 | case 4: |
545 | { | 524 | buffer[0] = lo & 0xf; |
546 | case 4: | 525 | buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); |
547 | buffer[0] = lo & 0xf; | 526 | buffer[2] = (hi & 0x1e) >> 1; |
548 | buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); | 527 | buffer[3] = lo2 & 0xf; |
549 | buffer[2] = (hi & 0x1e) >> 1; | 528 | buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); |
550 | buffer[3] = lo2 & 0xf; | 529 | buffer[5] = (hi2 & 0x1e) >> 1; |
551 | buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); | 530 | ret = 6; |
552 | buffer[5] = (hi2 & 0x1e) >> 1; | 531 | break; |
553 | ret = 6; | 532 | case 6: |
554 | break; | 533 | buffer[0] = lo & 0x3f; |
555 | case 6: | 534 | buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); |
556 | buffer[0] = lo & 0x3f; | 535 | buffer[2] = lo2 & 0x3f; |
557 | buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); | 536 | buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); |
558 | buffer[2] = lo2 & 0x3f; | 537 | ret = 4; |
559 | buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); | ||
560 | ret = 4; | ||
561 | break; | ||
562 | } | ||
563 | break; | 538 | break; |
539 | } | ||
540 | break; | ||
541 | |||
542 | case QC_UNIDIR: /* Unidirectional Port */ | ||
543 | write_lpcontrol(q, 6); | ||
544 | lo = (qc_waithand(q, 1) & 0xf0) >> 4; | ||
545 | write_lpcontrol(q, 0xe); | ||
546 | hi = (qc_waithand(q, 0) & 0xf0) >> 4; | ||
564 | 547 | ||
565 | case QC_UNIDIR: /* Unidirectional Port */ | 548 | switch (q->bpp) { |
566 | write_lpcontrol(q, 6); | 549 | case 4: |
567 | lo = (qc_waithand(q, 1) & 0xf0) >> 4; | 550 | buffer[0] = lo; |
568 | write_lpcontrol(q, 0xe); | 551 | buffer[1] = hi; |
569 | hi = (qc_waithand(q, 0) & 0xf0) >> 4; | 552 | ret = 2; |
570 | 553 | break; | |
571 | switch (q->bpp) | 554 | case 6: |
572 | { | 555 | switch (state) { |
573 | case 4: | 556 | case 0: |
574 | buffer[0] = lo; | 557 | buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); |
575 | buffer[1] = hi; | 558 | q->saved_bits = (hi & 3) << 4; |
576 | ret = 2; | 559 | state = 1; |
577 | break; | 560 | ret = 1; |
578 | case 6: | 561 | break; |
579 | switch (state) | 562 | case 1: |
580 | { | 563 | buffer[0] = lo | q->saved_bits; |
581 | case 0: | 564 | q->saved_bits = hi << 2; |
582 | buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); | 565 | state = 2; |
583 | q->saved_bits = (hi & 3) << 4; | 566 | ret = 1; |
584 | state = 1; | 567 | break; |
585 | ret = 1; | 568 | case 2: |
586 | break; | 569 | buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; |
587 | case 1: | 570 | buffer[1] = ((lo & 3) << 4) | hi; |
588 | buffer[0] = lo | q->saved_bits; | 571 | state = 0; |
589 | q->saved_bits = hi << 2; | 572 | ret = 2; |
590 | state = 2; | 573 | break; |
591 | ret = 1; | ||
592 | break; | ||
593 | case 2: | ||
594 | buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; | ||
595 | buffer[1] = ((lo & 3) << 4) | hi; | ||
596 | state = 0; | ||
597 | ret = 2; | ||
598 | break; | ||
599 | } | ||
600 | break; | ||
601 | } | 574 | } |
602 | break; | 575 | break; |
576 | } | ||
577 | break; | ||
603 | } | 578 | } |
604 | return ret; | 579 | return ret; |
605 | } | 580 | } |
@@ -615,7 +590,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) | |||
615 | * n=2^(bit depth)-1. Ask me for more details if you don't understand | 590 | * n=2^(bit depth)-1. Ask me for more details if you don't understand |
616 | * this. */ | 591 | * this. */ |
617 | 592 | ||
618 | static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long len) | 593 | static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) |
619 | { | 594 | { |
620 | int i, j, k, yield; | 595 | int i, j, k, yield; |
621 | int bytes; | 596 | int bytes; |
@@ -623,9 +598,9 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
623 | int divisor; | 598 | int divisor; |
624 | int pixels_per_line; | 599 | int pixels_per_line; |
625 | int pixels_read = 0; | 600 | int pixels_read = 0; |
626 | int got=0; | 601 | int got = 0; |
627 | char buffer[6]; | 602 | char buffer[6]; |
628 | int shift=8-q->bpp; | 603 | int shift = 8 - q->bpp; |
629 | char invert; | 604 | char invert; |
630 | 605 | ||
631 | if (q->mode == -1) | 606 | if (q->mode == -1) |
@@ -634,13 +609,12 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
634 | qc_command(q, 0x7); | 609 | qc_command(q, 0x7); |
635 | qc_command(q, q->mode); | 610 | qc_command(q, q->mode); |
636 | 611 | ||
637 | if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) | 612 | if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { |
638 | { | ||
639 | write_lpcontrol(q, 0x2e); /* turn port around */ | 613 | write_lpcontrol(q, 0x2e); /* turn port around */ |
640 | write_lpcontrol(q, 0x26); | 614 | write_lpcontrol(q, 0x26); |
641 | (void) qc_waithand(q, 1); | 615 | qc_waithand(q, 1); |
642 | write_lpcontrol(q, 0x2e); | 616 | write_lpcontrol(q, 0x2e); |
643 | (void) qc_waithand(q, 0); | 617 | qc_waithand(q, 0); |
644 | } | 618 | } |
645 | 619 | ||
646 | /* strange -- should be 15:63 below, but 4bpp is odd */ | 620 | /* strange -- should be 15:63 below, but 4bpp is odd */ |
@@ -650,33 +624,28 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
650 | pixels_per_line = q->width / q->transfer_scale; | 624 | pixels_per_line = q->width / q->transfer_scale; |
651 | transperline = q->width * q->bpp; | 625 | transperline = q->width * q->bpp; |
652 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 626 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
653 | q->transfer_scale; | 627 | q->transfer_scale; |
654 | transperline = DIV_ROUND_UP(transperline, divisor); | 628 | transperline = DIV_ROUND_UP(transperline, divisor); |
655 | 629 | ||
656 | for (i = 0, yield = yieldlines; i < linestotrans; i++) | 630 | for (i = 0, yield = yieldlines; i < linestotrans; i++) { |
657 | { | 631 | for (pixels_read = j = 0; j < transperline; j++) { |
658 | for (pixels_read = j = 0; j < transperline; j++) | ||
659 | { | ||
660 | bytes = qc_readbytes(q, buffer); | 632 | bytes = qc_readbytes(q, buffer); |
661 | for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) | 633 | for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) { |
662 | { | ||
663 | int o; | 634 | int o; |
664 | if (buffer[k] == 0 && invert == 16) | 635 | if (buffer[k] == 0 && invert == 16) { |
665 | { | ||
666 | /* 4bpp is odd (again) -- inverter is 16, not 15, but output | 636 | /* 4bpp is odd (again) -- inverter is 16, not 15, but output |
667 | must be 0-15 -- bls */ | 637 | must be 0-15 -- bls */ |
668 | buffer[k] = 16; | 638 | buffer[k] = 16; |
669 | } | 639 | } |
670 | o=i*pixels_per_line + pixels_read + k; | 640 | o = i * pixels_per_line + pixels_read + k; |
671 | if(o<len) | 641 | if (o < len) { |
672 | { | ||
673 | got++; | 642 | got++; |
674 | put_user((invert - buffer[k])<<shift, buf+o); | 643 | put_user((invert - buffer[k]) << shift, buf + o); |
675 | } | 644 | } |
676 | } | 645 | } |
677 | pixels_read += bytes; | 646 | pixels_read += bytes; |
678 | } | 647 | } |
679 | (void) qc_readbytes(q, NULL); /* reset state machine */ | 648 | qc_readbytes(q, NULL); /* reset state machine */ |
680 | 649 | ||
681 | /* Grabbing an entire frame from the quickcam is a lengthy | 650 | /* Grabbing an entire frame from the quickcam is a lengthy |
682 | process. We don't (usually) want to busy-block the | 651 | process. We don't (usually) want to busy-block the |
@@ -690,14 +659,13 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
690 | } | 659 | } |
691 | } | 660 | } |
692 | 661 | ||
693 | if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) | 662 | if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { |
694 | { | ||
695 | write_lpcontrol(q, 2); | 663 | write_lpcontrol(q, 2); |
696 | write_lpcontrol(q, 6); | 664 | write_lpcontrol(q, 6); |
697 | udelay(3); | 665 | udelay(3); |
698 | write_lpcontrol(q, 0xe); | 666 | write_lpcontrol(q, 0xe); |
699 | } | 667 | } |
700 | if(got<len) | 668 | if (got < len) |
701 | return got; | 669 | return got; |
702 | return len; | 670 | return len; |
703 | } | 671 | } |
@@ -709,11 +677,10 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
709 | static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 677 | static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) |
710 | { | 678 | { |
711 | struct video_device *dev = video_devdata(file); | 679 | struct video_device *dev = video_devdata(file); |
712 | struct qcam_device *qcam=(struct qcam_device *)dev; | 680 | struct qcam_device *qcam = (struct qcam_device *)dev; |
713 | 681 | ||
714 | switch(cmd) | 682 | switch (cmd) { |
715 | { | 683 | case VIDIOCGCAP: |
716 | case VIDIOCGCAP: | ||
717 | { | 684 | { |
718 | struct video_capability *b = arg; | 685 | struct video_capability *b = arg; |
719 | strcpy(b->name, "Quickcam"); | 686 | strcpy(b->name, "Quickcam"); |
@@ -726,73 +693,73 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
726 | b->minheight = 60; | 693 | b->minheight = 60; |
727 | return 0; | 694 | return 0; |
728 | } | 695 | } |
729 | case VIDIOCGCHAN: | 696 | case VIDIOCGCHAN: |
730 | { | 697 | { |
731 | struct video_channel *v = arg; | 698 | struct video_channel *v = arg; |
732 | if(v->channel!=0) | 699 | if (v->channel != 0) |
733 | return -EINVAL; | 700 | return -EINVAL; |
734 | v->flags=0; | 701 | v->flags = 0; |
735 | v->tuners=0; | 702 | v->tuners = 0; |
736 | /* Good question.. its composite or SVHS so.. */ | 703 | /* Good question.. its composite or SVHS so.. */ |
737 | v->type = VIDEO_TYPE_CAMERA; | 704 | v->type = VIDEO_TYPE_CAMERA; |
738 | strcpy(v->name, "Camera"); | 705 | strcpy(v->name, "Camera"); |
739 | return 0; | 706 | return 0; |
740 | } | 707 | } |
741 | case VIDIOCSCHAN: | 708 | case VIDIOCSCHAN: |
742 | { | 709 | { |
743 | struct video_channel *v = arg; | 710 | struct video_channel *v = arg; |
744 | if(v->channel!=0) | 711 | if (v->channel != 0) |
745 | return -EINVAL; | 712 | return -EINVAL; |
746 | return 0; | 713 | return 0; |
747 | } | 714 | } |
748 | case VIDIOCGTUNER: | 715 | case VIDIOCGTUNER: |
749 | { | 716 | { |
750 | struct video_tuner *v = arg; | 717 | struct video_tuner *v = arg; |
751 | if(v->tuner) | 718 | if (v->tuner) |
752 | return -EINVAL; | 719 | return -EINVAL; |
753 | strcpy(v->name, "Format"); | 720 | strcpy(v->name, "Format"); |
754 | v->rangelow=0; | 721 | v->rangelow = 0; |
755 | v->rangehigh=0; | 722 | v->rangehigh = 0; |
756 | v->flags= 0; | 723 | v->flags = 0; |
757 | v->mode = VIDEO_MODE_AUTO; | 724 | v->mode = VIDEO_MODE_AUTO; |
758 | return 0; | 725 | return 0; |
759 | } | 726 | } |
760 | case VIDIOCSTUNER: | 727 | case VIDIOCSTUNER: |
761 | { | 728 | { |
762 | struct video_tuner *v = arg; | 729 | struct video_tuner *v = arg; |
763 | if(v->tuner) | 730 | if (v->tuner) |
764 | return -EINVAL; | 731 | return -EINVAL; |
765 | if(v->mode!=VIDEO_MODE_AUTO) | 732 | if (v->mode != VIDEO_MODE_AUTO) |
766 | return -EINVAL; | 733 | return -EINVAL; |
767 | return 0; | 734 | return 0; |
768 | } | 735 | } |
769 | case VIDIOCGPICT: | 736 | case VIDIOCGPICT: |
770 | { | 737 | { |
771 | struct video_picture *p = arg; | 738 | struct video_picture *p = arg; |
772 | p->colour=0x8000; | 739 | p->colour = 0x8000; |
773 | p->hue=0x8000; | 740 | p->hue = 0x8000; |
774 | p->brightness=qcam->brightness<<8; | 741 | p->brightness = qcam->brightness << 8; |
775 | p->contrast=qcam->contrast<<8; | 742 | p->contrast = qcam->contrast << 8; |
776 | p->whiteness=qcam->whitebal<<8; | 743 | p->whiteness = qcam->whitebal << 8; |
777 | p->depth=qcam->bpp; | 744 | p->depth = qcam->bpp; |
778 | p->palette=VIDEO_PALETTE_GREY; | 745 | p->palette = VIDEO_PALETTE_GREY; |
779 | return 0; | 746 | return 0; |
780 | } | 747 | } |
781 | case VIDIOCSPICT: | 748 | case VIDIOCSPICT: |
782 | { | 749 | { |
783 | struct video_picture *p = arg; | 750 | struct video_picture *p = arg; |
784 | if(p->palette!=VIDEO_PALETTE_GREY) | 751 | if (p->palette != VIDEO_PALETTE_GREY) |
785 | return -EINVAL; | 752 | return -EINVAL; |
786 | if(p->depth!=4 && p->depth!=6) | 753 | if (p->depth != 4 && p->depth != 6) |
787 | return -EINVAL; | 754 | return -EINVAL; |
788 | 755 | ||
789 | /* | 756 | /* |
790 | * Now load the camera. | 757 | * Now load the camera. |
791 | */ | 758 | */ |
792 | 759 | ||
793 | qcam->brightness = p->brightness>>8; | 760 | qcam->brightness = p->brightness >> 8; |
794 | qcam->contrast = p->contrast>>8; | 761 | qcam->contrast = p->contrast >> 8; |
795 | qcam->whitebal = p->whiteness>>8; | 762 | qcam->whitebal = p->whiteness >> 8; |
796 | qcam->bpp = p->depth; | 763 | qcam->bpp = p->depth; |
797 | 764 | ||
798 | mutex_lock(&qcam->lock); | 765 | mutex_lock(&qcam->lock); |
@@ -802,28 +769,25 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
802 | 769 | ||
803 | return 0; | 770 | return 0; |
804 | } | 771 | } |
805 | case VIDIOCSWIN: | 772 | case VIDIOCSWIN: |
806 | { | 773 | { |
807 | struct video_window *vw = arg; | 774 | struct video_window *vw = arg; |
808 | if(vw->flags) | 775 | if (vw->flags) |
809 | return -EINVAL; | 776 | return -EINVAL; |
810 | if(vw->clipcount) | 777 | if (vw->clipcount) |
811 | return -EINVAL; | 778 | return -EINVAL; |
812 | if(vw->height<60||vw->height>240) | 779 | if (vw->height < 60 || vw->height > 240) |
813 | return -EINVAL; | 780 | return -EINVAL; |
814 | if(vw->width<80||vw->width>320) | 781 | if (vw->width < 80 || vw->width > 320) |
815 | return -EINVAL; | 782 | return -EINVAL; |
816 | 783 | ||
817 | qcam->width = 320; | 784 | qcam->width = 320; |
818 | qcam->height = 240; | 785 | qcam->height = 240; |
819 | qcam->transfer_scale = 4; | 786 | qcam->transfer_scale = 4; |
820 | 787 | ||
821 | if(vw->width>=160 && vw->height>=120) | 788 | if (vw->width >= 160 && vw->height >= 120) |
822 | { | ||
823 | qcam->transfer_scale = 2; | 789 | qcam->transfer_scale = 2; |
824 | } | 790 | if (vw->width >= 320 && vw->height >= 240) { |
825 | if(vw->width>=320 && vw->height>=240) | ||
826 | { | ||
827 | qcam->width = 320; | 791 | qcam->width = 320; |
828 | qcam->height = 240; | 792 | qcam->height = 240; |
829 | qcam->transfer_scale = 1; | 793 | qcam->transfer_scale = 1; |
@@ -839,41 +803,42 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
839 | /* Ok we figured out what to use from our wide choice */ | 803 | /* Ok we figured out what to use from our wide choice */ |
840 | return 0; | 804 | return 0; |
841 | } | 805 | } |
842 | case VIDIOCGWIN: | 806 | case VIDIOCGWIN: |
843 | { | 807 | { |
844 | struct video_window *vw = arg; | 808 | struct video_window *vw = arg; |
809 | |||
845 | memset(vw, 0, sizeof(*vw)); | 810 | memset(vw, 0, sizeof(*vw)); |
846 | vw->width=qcam->width/qcam->transfer_scale; | 811 | vw->width = qcam->width / qcam->transfer_scale; |
847 | vw->height=qcam->height/qcam->transfer_scale; | 812 | vw->height = qcam->height / qcam->transfer_scale; |
848 | return 0; | 813 | return 0; |
849 | } | 814 | } |
850 | case VIDIOCKEY: | 815 | case VIDIOCKEY: |
851 | return 0; | 816 | return 0; |
852 | case VIDIOCCAPTURE: | 817 | case VIDIOCCAPTURE: |
853 | case VIDIOCGFBUF: | 818 | case VIDIOCGFBUF: |
854 | case VIDIOCSFBUF: | 819 | case VIDIOCSFBUF: |
855 | case VIDIOCGFREQ: | 820 | case VIDIOCGFREQ: |
856 | case VIDIOCSFREQ: | 821 | case VIDIOCSFREQ: |
857 | case VIDIOCGAUDIO: | 822 | case VIDIOCGAUDIO: |
858 | case VIDIOCSAUDIO: | 823 | case VIDIOCSAUDIO: |
859 | return -EINVAL; | 824 | return -EINVAL; |
860 | default: | 825 | default: |
861 | return -ENOIOCTLCMD; | 826 | return -ENOIOCTLCMD; |
862 | } | 827 | } |
863 | return 0; | 828 | return 0; |
864 | } | 829 | } |
865 | 830 | ||
866 | static long qcam_ioctl(struct file *file, | 831 | static long qcam_ioctl(struct file *file, |
867 | unsigned int cmd, unsigned long arg) | 832 | unsigned int cmd, unsigned long arg) |
868 | { | 833 | { |
869 | return video_usercopy(file, cmd, arg, qcam_do_ioctl); | 834 | return video_usercopy(file, cmd, arg, qcam_do_ioctl); |
870 | } | 835 | } |
871 | 836 | ||
872 | static ssize_t qcam_read(struct file *file, char __user *buf, | 837 | static ssize_t qcam_read(struct file *file, char __user *buf, |
873 | size_t count, loff_t *ppos) | 838 | size_t count, loff_t *ppos) |
874 | { | 839 | { |
875 | struct video_device *v = video_devdata(file); | 840 | struct video_device *v = video_devdata(file); |
876 | struct qcam_device *qcam=(struct qcam_device *)v; | 841 | struct qcam_device *qcam = (struct qcam_device *)v; |
877 | int len; | 842 | int len; |
878 | parport_claim_or_block(qcam->pdev); | 843 | parport_claim_or_block(qcam->pdev); |
879 | 844 | ||
@@ -885,7 +850,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
885 | if (qcam->status & QC_PARAM_CHANGE) | 850 | if (qcam->status & QC_PARAM_CHANGE) |
886 | qc_set(qcam); | 851 | qc_set(qcam); |
887 | 852 | ||
888 | len=qc_capture(qcam, buf,count); | 853 | len = qc_capture(qcam, buf, count); |
889 | 854 | ||
890 | mutex_unlock(&qcam->lock); | 855 | mutex_unlock(&qcam->lock); |
891 | 856 | ||
@@ -917,8 +882,7 @@ static const struct v4l2_file_operations qcam_fops = { | |||
917 | .ioctl = qcam_ioctl, | 882 | .ioctl = qcam_ioctl, |
918 | .read = qcam_read, | 883 | .read = qcam_read, |
919 | }; | 884 | }; |
920 | static struct video_device qcam_template= | 885 | static struct video_device qcam_template = { |
921 | { | ||
922 | .name = "Connectix Quickcam", | 886 | .name = "Connectix Quickcam", |
923 | .fops = &qcam_fops, | 887 | .fops = &qcam_fops, |
924 | .release = video_device_release_empty, | 888 | .release = video_device_release_empty, |
@@ -932,22 +896,20 @@ static int init_bwqcam(struct parport *port) | |||
932 | { | 896 | { |
933 | struct qcam_device *qcam; | 897 | struct qcam_device *qcam; |
934 | 898 | ||
935 | if (num_cams == MAX_CAMS) | 899 | if (num_cams == MAX_CAMS) { |
936 | { | ||
937 | printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); | 900 | printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); |
938 | return -ENOSPC; | 901 | return -ENOSPC; |
939 | } | 902 | } |
940 | 903 | ||
941 | qcam=qcam_init(port); | 904 | qcam = qcam_init(port); |
942 | if(qcam==NULL) | 905 | if (qcam == NULL) |
943 | return -ENODEV; | 906 | return -ENODEV; |
944 | 907 | ||
945 | parport_claim_or_block(qcam->pdev); | 908 | parport_claim_or_block(qcam->pdev); |
946 | 909 | ||
947 | qc_reset(qcam); | 910 | qc_reset(qcam); |
948 | 911 | ||
949 | if(qc_detect(qcam)==0) | 912 | if (qc_detect(qcam) == 0) { |
950 | { | ||
951 | parport_release(qcam->pdev); | 913 | parport_release(qcam->pdev); |
952 | parport_unregister_device(qcam->pdev); | 914 | parport_unregister_device(qcam->pdev); |
953 | kfree(qcam); | 915 | kfree(qcam); |
@@ -1045,12 +1007,12 @@ static int __init init_bw_qcams(void) | |||
1045 | #ifdef MODULE | 1007 | #ifdef MODULE |
1046 | /* Do some sanity checks on the module parameters. */ | 1008 | /* Do some sanity checks on the module parameters. */ |
1047 | if (maxpoll > 5000) { | 1009 | if (maxpoll > 5000) { |
1048 | printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); | 1010 | printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n"); |
1049 | maxpoll = 5000; | 1011 | maxpoll = 5000; |
1050 | } | 1012 | } |
1051 | 1013 | ||
1052 | if (yieldlines < 1) { | 1014 | if (yieldlines < 1) { |
1053 | printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); | 1015 | printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n"); |
1054 | yieldlines = 1; | 1016 | yieldlines = 1; |
1055 | } | 1017 | } |
1056 | #endif | 1018 | #endif |
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index e2cbebab959b..8f1dd88b32a6 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c | |||
@@ -79,17 +79,17 @@ static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) | |||
79 | { | 79 | { |
80 | /* note: the QC specs refer to the PCAck pin by voltage, not | 80 | /* note: the QC specs refer to the PCAck pin by voltage, not |
81 | software level. PC ports have builtin inverters. */ | 81 | software level. PC ports have builtin inverters. */ |
82 | parport_frob_control(qcam->pport, 8, i?8:0); | 82 | parport_frob_control(qcam->pport, 8, i ? 8 : 0); |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline unsigned int qcam_ready1(struct qcam_device *qcam) | 85 | static inline unsigned int qcam_ready1(struct qcam_device *qcam) |
86 | { | 86 | { |
87 | return (parport_read_status(qcam->pport) & 0x8)?1:0; | 87 | return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static inline unsigned int qcam_ready2(struct qcam_device *qcam) | 90 | static inline unsigned int qcam_ready2(struct qcam_device *qcam) |
91 | { | 91 | { |
92 | return (parport_read_data(qcam->pport) & 0x1)?1:0; | 92 | return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | static unsigned int qcam_await_ready1(struct qcam_device *qcam, | 95 | static unsigned int qcam_await_ready1(struct qcam_device *qcam, |
@@ -99,14 +99,13 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, | |||
99 | unsigned int i; | 99 | unsigned int i; |
100 | 100 | ||
101 | for (oldjiffies = jiffies; | 101 | for (oldjiffies = jiffies; |
102 | time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) | 102 | time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) |
103 | if (qcam_ready1(qcam) == value) | 103 | if (qcam_ready1(qcam) == value) |
104 | return 0; | 104 | return 0; |
105 | 105 | ||
106 | /* If the camera didn't respond within 1/25 second, poll slowly | 106 | /* If the camera didn't respond within 1/25 second, poll slowly |
107 | for a while. */ | 107 | for a while. */ |
108 | for (i = 0; i < 50; i++) | 108 | for (i = 0; i < 50; i++) { |
109 | { | ||
110 | if (qcam_ready1(qcam) == value) | 109 | if (qcam_ready1(qcam) == value) |
111 | return 0; | 110 | return 0; |
112 | msleep_interruptible(100); | 111 | msleep_interruptible(100); |
@@ -125,14 +124,13 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) | |||
125 | unsigned int i; | 124 | unsigned int i; |
126 | 125 | ||
127 | for (oldjiffies = jiffies; | 126 | for (oldjiffies = jiffies; |
128 | time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) | 127 | time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) |
129 | if (qcam_ready2(qcam) == value) | 128 | if (qcam_ready2(qcam) == value) |
130 | return 0; | 129 | return 0; |
131 | 130 | ||
132 | /* If the camera didn't respond within 1/25 second, poll slowly | 131 | /* If the camera didn't respond within 1/25 second, poll slowly |
133 | for a while. */ | 132 | for a while. */ |
134 | for (i = 0; i < 50; i++) | 133 | for (i = 0; i < 50; i++) { |
135 | { | ||
136 | if (qcam_ready2(qcam) == value) | 134 | if (qcam_ready2(qcam) == value) |
137 | return 0; | 135 | return 0; |
138 | msleep_interruptible(100); | 136 | msleep_interruptible(100); |
@@ -149,22 +147,25 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) | |||
149 | static int qcam_read_data(struct qcam_device *qcam) | 147 | static int qcam_read_data(struct qcam_device *qcam) |
150 | { | 148 | { |
151 | unsigned int idata; | 149 | unsigned int idata; |
150 | |||
152 | qcam_set_ack(qcam, 0); | 151 | qcam_set_ack(qcam, 0); |
153 | if (qcam_await_ready1(qcam, 1)) return -1; | 152 | if (qcam_await_ready1(qcam, 1)) |
153 | return -1; | ||
154 | idata = parport_read_status(qcam->pport) & 0xf0; | 154 | idata = parport_read_status(qcam->pport) & 0xf0; |
155 | qcam_set_ack(qcam, 1); | 155 | qcam_set_ack(qcam, 1); |
156 | if (qcam_await_ready1(qcam, 0)) return -1; | 156 | if (qcam_await_ready1(qcam, 0)) |
157 | idata |= (parport_read_status(qcam->pport) >> 4); | 157 | return -1; |
158 | idata |= parport_read_status(qcam->pport) >> 4; | ||
158 | return idata; | 159 | return idata; |
159 | } | 160 | } |
160 | 161 | ||
161 | static int qcam_write_data(struct qcam_device *qcam, unsigned int data) | 162 | static int qcam_write_data(struct qcam_device *qcam, unsigned int data) |
162 | { | 163 | { |
163 | unsigned int idata; | 164 | unsigned int idata; |
165 | |||
164 | parport_write_data(qcam->pport, data); | 166 | parport_write_data(qcam->pport, data); |
165 | idata = qcam_read_data(qcam); | 167 | idata = qcam_read_data(qcam); |
166 | if (data != idata) | 168 | if (data != idata) { |
167 | { | ||
168 | printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, | 169 | printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, |
169 | idata); | 170 | idata); |
170 | return 1; | 171 | return 1; |
@@ -212,13 +213,12 @@ static int qc_detect(struct qcam_device *qcam) | |||
212 | 213 | ||
213 | /* look for a heartbeat */ | 214 | /* look for a heartbeat */ |
214 | ostat = stat = parport_read_status(qcam->pport); | 215 | ostat = stat = parport_read_status(qcam->pport); |
215 | for (i=0; i<250; i++) | 216 | for (i = 0; i < 250; i++) { |
216 | { | ||
217 | mdelay(1); | 217 | mdelay(1); |
218 | stat = parport_read_status(qcam->pport); | 218 | stat = parport_read_status(qcam->pport); |
219 | if (ostat != stat) | 219 | if (ostat != stat) { |
220 | { | 220 | if (++count >= 3) |
221 | if (++count >= 3) return 1; | 221 | return 1; |
222 | ostat = stat; | 222 | ostat = stat; |
223 | } | 223 | } |
224 | } | 224 | } |
@@ -232,13 +232,12 @@ static int qc_detect(struct qcam_device *qcam) | |||
232 | count = 0; | 232 | count = 0; |
233 | 233 | ||
234 | ostat = stat = parport_read_status(qcam->pport); | 234 | ostat = stat = parport_read_status(qcam->pport); |
235 | for (i=0; i<250; i++) | 235 | for (i = 0; i < 250; i++) { |
236 | { | ||
237 | mdelay(1); | 236 | mdelay(1); |
238 | stat = parport_read_status(qcam->pport); | 237 | stat = parport_read_status(qcam->pport); |
239 | if (ostat != stat) | 238 | if (ostat != stat) { |
240 | { | 239 | if (++count >= 3) |
241 | if (++count >= 3) return 1; | 240 | return 1; |
242 | ostat = stat; | 241 | ostat = stat; |
243 | } | 242 | } |
244 | } | 243 | } |
@@ -263,7 +262,7 @@ static void qc_setup(struct qcam_device *q) | |||
263 | { | 262 | { |
264 | qc_reset(q); | 263 | qc_reset(q); |
265 | 264 | ||
266 | /* Set the brightness. */ | 265 | /* Set the brightness. */ |
267 | qcam_set(q, 11, q->brightness); | 266 | qcam_set(q, 11, q->brightness); |
268 | 267 | ||
269 | /* Set the height and width. These refer to the actual | 268 | /* Set the height and width. These refer to the actual |
@@ -292,25 +291,25 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u | |||
292 | unsigned int bytes = 0; | 291 | unsigned int bytes = 0; |
293 | 292 | ||
294 | qcam_set_ack(q, 0); | 293 | qcam_set_ack(q, 0); |
295 | if (q->bidirectional) | 294 | if (q->bidirectional) { |
296 | { | ||
297 | /* It's a bidirectional port */ | 295 | /* It's a bidirectional port */ |
298 | while (bytes < nbytes) | 296 | while (bytes < nbytes) { |
299 | { | ||
300 | unsigned int lo1, hi1, lo2, hi2; | 297 | unsigned int lo1, hi1, lo2, hi2; |
301 | unsigned char r, g, b; | 298 | unsigned char r, g, b; |
302 | 299 | ||
303 | if (qcam_await_ready2(q, 1)) return bytes; | 300 | if (qcam_await_ready2(q, 1)) |
301 | return bytes; | ||
304 | lo1 = parport_read_data(q->pport) >> 1; | 302 | lo1 = parport_read_data(q->pport) >> 1; |
305 | hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; | 303 | hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; |
306 | qcam_set_ack(q, 1); | 304 | qcam_set_ack(q, 1); |
307 | if (qcam_await_ready2(q, 0)) return bytes; | 305 | if (qcam_await_ready2(q, 0)) |
306 | return bytes; | ||
308 | lo2 = parport_read_data(q->pport) >> 1; | 307 | lo2 = parport_read_data(q->pport) >> 1; |
309 | hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; | 308 | hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; |
310 | qcam_set_ack(q, 0); | 309 | qcam_set_ack(q, 0); |
311 | r = (lo1 | ((hi1 & 1)<<7)); | 310 | r = lo1 | ((hi1 & 1) << 7); |
312 | g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1); | 311 | g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); |
313 | b = (lo2 | ((hi2 & 1)<<7)); | 312 | b = lo2 | ((hi2 & 1) << 7); |
314 | if (force_rgb) { | 313 | if (force_rgb) { |
315 | buf[bytes++] = r; | 314 | buf[bytes++] = r; |
316 | buf[bytes++] = g; | 315 | buf[bytes++] = g; |
@@ -321,21 +320,20 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u | |||
321 | buf[bytes++] = r; | 320 | buf[bytes++] = r; |
322 | } | 321 | } |
323 | } | 322 | } |
324 | } | 323 | } else { |
325 | else | ||
326 | { | ||
327 | /* It's a unidirectional port */ | 324 | /* It's a unidirectional port */ |
328 | int i = 0, n = bytes; | 325 | int i = 0, n = bytes; |
329 | unsigned char rgb[3]; | 326 | unsigned char rgb[3]; |
330 | 327 | ||
331 | while (bytes < nbytes) | 328 | while (bytes < nbytes) { |
332 | { | ||
333 | unsigned int hi, lo; | 329 | unsigned int hi, lo; |
334 | 330 | ||
335 | if (qcam_await_ready1(q, 1)) return bytes; | 331 | if (qcam_await_ready1(q, 1)) |
332 | return bytes; | ||
336 | hi = (parport_read_status(q->pport) & 0xf0); | 333 | hi = (parport_read_status(q->pport) & 0xf0); |
337 | qcam_set_ack(q, 1); | 334 | qcam_set_ack(q, 1); |
338 | if (qcam_await_ready1(q, 0)) return bytes; | 335 | if (qcam_await_ready1(q, 0)) |
336 | return bytes; | ||
339 | lo = (parport_read_status(q->pport) & 0xf0); | 337 | lo = (parport_read_status(q->pport) & 0xf0); |
340 | qcam_set_ack(q, 0); | 338 | qcam_set_ack(q, 0); |
341 | /* flip some bits */ | 339 | /* flip some bits */ |
@@ -374,28 +372,26 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
374 | return -EFAULT; | 372 | return -EFAULT; |
375 | 373 | ||
376 | /* Wait for camera to become ready */ | 374 | /* Wait for camera to become ready */ |
377 | for (;;) | 375 | for (;;) { |
378 | { | ||
379 | int i = qcam_get(q, 41); | 376 | int i = qcam_get(q, 41); |
377 | |||
380 | if (i == -1) { | 378 | if (i == -1) { |
381 | qc_setup(q); | 379 | qc_setup(q); |
382 | return -EIO; | 380 | return -EIO; |
383 | } | 381 | } |
384 | if ((i & 0x80) == 0) | 382 | if ((i & 0x80) == 0) |
385 | break; | 383 | break; |
386 | else | 384 | schedule(); |
387 | schedule(); | ||
388 | } | 385 | } |
389 | 386 | ||
390 | if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1)) | 387 | if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) |
391 | return -EIO; | 388 | return -EIO; |
392 | 389 | ||
393 | lines = q->height; | 390 | lines = q->height; |
394 | pixelsperline = q->width; | 391 | pixelsperline = q->width; |
395 | bitsperxfer = (is_bi_dir) ? 24 : 8; | 392 | bitsperxfer = (is_bi_dir) ? 24 : 8; |
396 | 393 | ||
397 | if (is_bi_dir) | 394 | if (is_bi_dir) { |
398 | { | ||
399 | /* Turn the port around */ | 395 | /* Turn the port around */ |
400 | parport_data_reverse(q->pport); | 396 | parport_data_reverse(q->pport); |
401 | mdelay(3); | 397 | mdelay(3); |
@@ -413,16 +409,17 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
413 | 409 | ||
414 | wantlen = lines * pixelsperline * 24 / 8; | 410 | wantlen = lines * pixelsperline * 24 / 8; |
415 | 411 | ||
416 | while (wantlen) | 412 | while (wantlen) { |
417 | { | ||
418 | size_t t, s; | 413 | size_t t, s; |
419 | s = (wantlen > BUFSZ)?BUFSZ:wantlen; | 414 | |
415 | s = (wantlen > BUFSZ) ? BUFSZ : wantlen; | ||
420 | t = qcam_read_bytes(q, tmpbuf, s); | 416 | t = qcam_read_bytes(q, tmpbuf, s); |
421 | if (outptr < len) | 417 | if (outptr < len) { |
422 | { | ||
423 | size_t sz = len - outptr; | 418 | size_t sz = len - outptr; |
424 | if (sz > t) sz = t; | 419 | |
425 | if (__copy_to_user(buf+outptr, tmpbuf, sz)) | 420 | if (sz > t) |
421 | sz = t; | ||
422 | if (__copy_to_user(buf + outptr, tmpbuf, sz)) | ||
426 | break; | 423 | break; |
427 | outptr += sz; | 424 | outptr += sz; |
428 | } | 425 | } |
@@ -434,33 +431,31 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
434 | 431 | ||
435 | len = outptr; | 432 | len = outptr; |
436 | 433 | ||
437 | if (wantlen) | 434 | if (wantlen) { |
438 | { | 435 | printk(KERN_ERR "qcam: short read.\n"); |
439 | printk("qcam: short read.\n"); | ||
440 | if (is_bi_dir) | 436 | if (is_bi_dir) |
441 | parport_data_forward(q->pport); | 437 | parport_data_forward(q->pport); |
442 | qc_setup(q); | 438 | qc_setup(q); |
443 | return len; | 439 | return len; |
444 | } | 440 | } |
445 | 441 | ||
446 | if (is_bi_dir) | 442 | if (is_bi_dir) { |
447 | { | ||
448 | int l; | 443 | int l; |
444 | |||
449 | do { | 445 | do { |
450 | l = qcam_read_bytes(q, tmpbuf, 3); | 446 | l = qcam_read_bytes(q, tmpbuf, 3); |
451 | cond_resched(); | 447 | cond_resched(); |
452 | } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); | 448 | } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); |
453 | if (force_rgb) { | 449 | if (force_rgb) { |
454 | if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) | 450 | if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) |
455 | printk("qcam: bad EOF\n"); | 451 | printk(KERN_ERR "qcam: bad EOF\n"); |
456 | } else { | 452 | } else { |
457 | if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) | 453 | if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) |
458 | printk("qcam: bad EOF\n"); | 454 | printk(KERN_ERR "qcam: bad EOF\n"); |
459 | } | 455 | } |
460 | qcam_set_ack(q, 0); | 456 | qcam_set_ack(q, 0); |
461 | if (qcam_await_ready1(q, 1)) | 457 | if (qcam_await_ready1(q, 1)) { |
462 | { | 458 | printk(KERN_ERR "qcam: no ack after EOF\n"); |
463 | printk("qcam: no ack after EOF\n"); | ||
464 | parport_data_forward(q->pport); | 459 | parport_data_forward(q->pport); |
465 | qc_setup(q); | 460 | qc_setup(q); |
466 | return len; | 461 | return len; |
@@ -468,27 +463,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
468 | parport_data_forward(q->pport); | 463 | parport_data_forward(q->pport); |
469 | mdelay(3); | 464 | mdelay(3); |
470 | qcam_set_ack(q, 1); | 465 | qcam_set_ack(q, 1); |
471 | if (qcam_await_ready1(q, 0)) | 466 | if (qcam_await_ready1(q, 0)) { |
472 | { | 467 | printk(KERN_ERR "qcam: no ack to port turnaround\n"); |
473 | printk("qcam: no ack to port turnaround\n"); | ||
474 | qc_setup(q); | 468 | qc_setup(q); |
475 | return len; | 469 | return len; |
476 | } | 470 | } |
477 | } | 471 | } else { |
478 | else | ||
479 | { | ||
480 | int l; | 472 | int l; |
473 | |||
481 | do { | 474 | do { |
482 | l = qcam_read_bytes(q, tmpbuf, 1); | 475 | l = qcam_read_bytes(q, tmpbuf, 1); |
483 | cond_resched(); | 476 | cond_resched(); |
484 | } while (l && tmpbuf[0] == 0x7e); | 477 | } while (l && tmpbuf[0] == 0x7e); |
485 | l = qcam_read_bytes(q, tmpbuf+1, 2); | 478 | l = qcam_read_bytes(q, tmpbuf + 1, 2); |
486 | if (force_rgb) { | 479 | if (force_rgb) { |
487 | if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) | 480 | if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) |
488 | printk("qcam: bad EOF\n"); | 481 | printk(KERN_ERR "qcam: bad EOF\n"); |
489 | } else { | 482 | } else { |
490 | if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) | 483 | if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) |
491 | printk("qcam: bad EOF\n"); | 484 | printk(KERN_ERR "qcam: bad EOF\n"); |
492 | } | 485 | } |
493 | } | 486 | } |
494 | 487 | ||
@@ -503,164 +496,166 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
503 | static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 496 | static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) |
504 | { | 497 | { |
505 | struct video_device *dev = video_devdata(file); | 498 | struct video_device *dev = video_devdata(file); |
506 | struct qcam_device *qcam=(struct qcam_device *)dev; | 499 | struct qcam_device *qcam = (struct qcam_device *)dev; |
507 | 500 | ||
508 | switch(cmd) | 501 | switch (cmd) { |
502 | case VIDIOCGCAP: | ||
509 | { | 503 | { |
510 | case VIDIOCGCAP: | 504 | struct video_capability *b = arg; |
511 | { | 505 | |
512 | struct video_capability *b = arg; | 506 | strcpy(b->name, "Quickcam"); |
513 | strcpy(b->name, "Quickcam"); | 507 | b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; |
514 | b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; | 508 | b->channels = 1; |
515 | b->channels = 1; | 509 | b->audios = 0; |
516 | b->audios = 0; | 510 | b->maxwidth = 320; |
517 | b->maxwidth = 320; | 511 | b->maxheight = 240; |
518 | b->maxheight = 240; | 512 | b->minwidth = 80; |
519 | b->minwidth = 80; | 513 | b->minheight = 60; |
520 | b->minheight = 60; | 514 | return 0; |
521 | return 0; | 515 | } |
522 | } | 516 | case VIDIOCGCHAN: |
523 | case VIDIOCGCHAN: | 517 | { |
524 | { | 518 | struct video_channel *v = arg; |
525 | struct video_channel *v = arg; | 519 | |
526 | if(v->channel!=0) | 520 | if (v->channel != 0) |
527 | return -EINVAL; | 521 | return -EINVAL; |
528 | v->flags=0; | 522 | v->flags = 0; |
529 | v->tuners=0; | 523 | v->tuners = 0; |
530 | /* Good question.. its composite or SVHS so.. */ | 524 | /* Good question.. its composite or SVHS so.. */ |
531 | v->type = VIDEO_TYPE_CAMERA; | 525 | v->type = VIDEO_TYPE_CAMERA; |
532 | strcpy(v->name, "Camera"); | 526 | strcpy(v->name, "Camera"); |
533 | return 0; | 527 | return 0; |
534 | } | 528 | } |
535 | case VIDIOCSCHAN: | 529 | case VIDIOCSCHAN: |
536 | { | 530 | { |
537 | struct video_channel *v = arg; | 531 | struct video_channel *v = arg; |
538 | if(v->channel!=0) | 532 | |
539 | return -EINVAL; | 533 | if (v->channel != 0) |
540 | return 0; | 534 | return -EINVAL; |
541 | } | 535 | return 0; |
542 | case VIDIOCGTUNER: | 536 | } |
543 | { | 537 | case VIDIOCGTUNER: |
544 | struct video_tuner *v = arg; | 538 | { |
545 | if(v->tuner) | 539 | struct video_tuner *v = arg; |
546 | return -EINVAL; | 540 | |
547 | memset(v,0,sizeof(*v)); | 541 | if (v->tuner) |
548 | strcpy(v->name, "Format"); | 542 | return -EINVAL; |
549 | v->mode = VIDEO_MODE_AUTO; | 543 | memset(v, 0, sizeof(*v)); |
550 | return 0; | 544 | strcpy(v->name, "Format"); |
551 | } | 545 | v->mode = VIDEO_MODE_AUTO; |
552 | case VIDIOCSTUNER: | 546 | return 0; |
553 | { | 547 | } |
554 | struct video_tuner *v = arg; | 548 | case VIDIOCSTUNER: |
555 | if(v->tuner) | 549 | { |
556 | return -EINVAL; | 550 | struct video_tuner *v = arg; |
557 | if(v->mode!=VIDEO_MODE_AUTO) | 551 | |
558 | return -EINVAL; | 552 | if (v->tuner) |
559 | return 0; | 553 | return -EINVAL; |
560 | } | 554 | if (v->mode != VIDEO_MODE_AUTO) |
561 | case VIDIOCGPICT: | 555 | return -EINVAL; |
562 | { | 556 | return 0; |
563 | struct video_picture *p = arg; | 557 | } |
564 | p->colour=0x8000; | 558 | case VIDIOCGPICT: |
565 | p->hue=0x8000; | 559 | { |
566 | p->brightness=qcam->brightness<<8; | 560 | struct video_picture *p = arg; |
567 | p->contrast=qcam->contrast<<8; | 561 | |
568 | p->whiteness=qcam->whitebal<<8; | 562 | p->colour = 0x8000; |
569 | p->depth=24; | 563 | p->hue = 0x8000; |
570 | p->palette=VIDEO_PALETTE_RGB24; | 564 | p->brightness = qcam->brightness << 8; |
571 | return 0; | 565 | p->contrast = qcam->contrast << 8; |
566 | p->whiteness = qcam->whitebal << 8; | ||
567 | p->depth = 24; | ||
568 | p->palette = VIDEO_PALETTE_RGB24; | ||
569 | return 0; | ||
570 | } | ||
571 | case VIDIOCSPICT: | ||
572 | { | ||
573 | struct video_picture *p = arg; | ||
574 | |||
575 | /* | ||
576 | * Sanity check args | ||
577 | */ | ||
578 | if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) | ||
579 | return -EINVAL; | ||
580 | |||
581 | /* | ||
582 | * Now load the camera. | ||
583 | */ | ||
584 | qcam->brightness = p->brightness >> 8; | ||
585 | qcam->contrast = p->contrast >> 8; | ||
586 | qcam->whitebal = p->whiteness >> 8; | ||
587 | |||
588 | mutex_lock(&qcam->lock); | ||
589 | parport_claim_or_block(qcam->pdev); | ||
590 | qc_setup(qcam); | ||
591 | parport_release(qcam->pdev); | ||
592 | mutex_unlock(&qcam->lock); | ||
593 | return 0; | ||
594 | } | ||
595 | case VIDIOCSWIN: | ||
596 | { | ||
597 | struct video_window *vw = arg; | ||
598 | |||
599 | if (vw->flags) | ||
600 | return -EINVAL; | ||
601 | if (vw->clipcount) | ||
602 | return -EINVAL; | ||
603 | if (vw->height < 60 || vw->height > 240) | ||
604 | return -EINVAL; | ||
605 | if (vw->width < 80 || vw->width > 320) | ||
606 | return -EINVAL; | ||
607 | |||
608 | qcam->width = 80; | ||
609 | qcam->height = 60; | ||
610 | qcam->mode = QC_DECIMATION_4; | ||
611 | |||
612 | if (vw->width >= 160 && vw->height >= 120) { | ||
613 | qcam->width = 160; | ||
614 | qcam->height = 120; | ||
615 | qcam->mode = QC_DECIMATION_2; | ||
572 | } | 616 | } |
573 | case VIDIOCSPICT: | 617 | if (vw->width >= 320 && vw->height >= 240) { |
574 | { | 618 | qcam->width = 320; |
575 | struct video_picture *p = arg; | 619 | qcam->height = 240; |
576 | 620 | qcam->mode = QC_DECIMATION_1; | |
577 | /* | ||
578 | * Sanity check args | ||
579 | */ | ||
580 | if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) | ||
581 | return -EINVAL; | ||
582 | |||
583 | /* | ||
584 | * Now load the camera. | ||
585 | */ | ||
586 | qcam->brightness = p->brightness>>8; | ||
587 | qcam->contrast = p->contrast>>8; | ||
588 | qcam->whitebal = p->whiteness>>8; | ||
589 | |||
590 | mutex_lock(&qcam->lock); | ||
591 | parport_claim_or_block(qcam->pdev); | ||
592 | qc_setup(qcam); | ||
593 | parport_release(qcam->pdev); | ||
594 | mutex_unlock(&qcam->lock); | ||
595 | return 0; | ||
596 | } | 621 | } |
597 | case VIDIOCSWIN: | 622 | qcam->mode |= QC_MILLIONS; |
598 | { | ||
599 | struct video_window *vw = arg; | ||
600 | |||
601 | if(vw->flags) | ||
602 | return -EINVAL; | ||
603 | if(vw->clipcount) | ||
604 | return -EINVAL; | ||
605 | if(vw->height<60||vw->height>240) | ||
606 | return -EINVAL; | ||
607 | if(vw->width<80||vw->width>320) | ||
608 | return -EINVAL; | ||
609 | |||
610 | qcam->width = 80; | ||
611 | qcam->height = 60; | ||
612 | qcam->mode = QC_DECIMATION_4; | ||
613 | |||
614 | if(vw->width>=160 && vw->height>=120) | ||
615 | { | ||
616 | qcam->width = 160; | ||
617 | qcam->height = 120; | ||
618 | qcam->mode = QC_DECIMATION_2; | ||
619 | } | ||
620 | if(vw->width>=320 && vw->height>=240) | ||
621 | { | ||
622 | qcam->width = 320; | ||
623 | qcam->height = 240; | ||
624 | qcam->mode = QC_DECIMATION_1; | ||
625 | } | ||
626 | qcam->mode |= QC_MILLIONS; | ||
627 | #if 0 | 623 | #if 0 |
628 | if(vw->width>=640 && vw->height>=480) | 624 | if (vw->width >= 640 && vw->height >= 480) { |
629 | { | 625 | qcam->width = 640; |
630 | qcam->width = 640; | 626 | qcam->height = 480; |
631 | qcam->height = 480; | 627 | qcam->mode = QC_BILLIONS | QC_DECIMATION_1; |
632 | qcam->mode = QC_BILLIONS | QC_DECIMATION_1; | ||
633 | } | ||
634 | #endif | ||
635 | /* Ok we figured out what to use from our | ||
636 | wide choice */ | ||
637 | mutex_lock(&qcam->lock); | ||
638 | parport_claim_or_block(qcam->pdev); | ||
639 | qc_setup(qcam); | ||
640 | parport_release(qcam->pdev); | ||
641 | mutex_unlock(&qcam->lock); | ||
642 | return 0; | ||
643 | } | ||
644 | case VIDIOCGWIN: | ||
645 | { | ||
646 | struct video_window *vw = arg; | ||
647 | memset(vw, 0, sizeof(*vw)); | ||
648 | vw->width=qcam->width; | ||
649 | vw->height=qcam->height; | ||
650 | return 0; | ||
651 | } | 628 | } |
652 | case VIDIOCKEY: | 629 | #endif |
653 | return 0; | 630 | /* Ok we figured out what to use from our |
654 | case VIDIOCCAPTURE: | 631 | wide choice */ |
655 | case VIDIOCGFBUF: | 632 | mutex_lock(&qcam->lock); |
656 | case VIDIOCSFBUF: | 633 | parport_claim_or_block(qcam->pdev); |
657 | case VIDIOCGFREQ: | 634 | qc_setup(qcam); |
658 | case VIDIOCSFREQ: | 635 | parport_release(qcam->pdev); |
659 | case VIDIOCGAUDIO: | 636 | mutex_unlock(&qcam->lock); |
660 | case VIDIOCSAUDIO: | 637 | return 0; |
661 | return -EINVAL; | 638 | } |
662 | default: | 639 | case VIDIOCGWIN: |
663 | return -ENOIOCTLCMD; | 640 | { |
641 | struct video_window *vw = arg; | ||
642 | memset(vw, 0, sizeof(*vw)); | ||
643 | vw->width = qcam->width; | ||
644 | vw->height = qcam->height; | ||
645 | return 0; | ||
646 | } | ||
647 | case VIDIOCKEY: | ||
648 | return 0; | ||
649 | case VIDIOCCAPTURE: | ||
650 | case VIDIOCGFBUF: | ||
651 | case VIDIOCSFBUF: | ||
652 | case VIDIOCGFREQ: | ||
653 | case VIDIOCSFREQ: | ||
654 | case VIDIOCGAUDIO: | ||
655 | case VIDIOCSAUDIO: | ||
656 | return -EINVAL; | ||
657 | default: | ||
658 | return -ENOIOCTLCMD; | ||
664 | } | 659 | } |
665 | return 0; | 660 | return 0; |
666 | } | 661 | } |
@@ -675,13 +670,13 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
675 | size_t count, loff_t *ppos) | 670 | size_t count, loff_t *ppos) |
676 | { | 671 | { |
677 | struct video_device *v = video_devdata(file); | 672 | struct video_device *v = video_devdata(file); |
678 | struct qcam_device *qcam=(struct qcam_device *)v; | 673 | struct qcam_device *qcam = (struct qcam_device *)v; |
679 | int len; | 674 | int len; |
680 | 675 | ||
681 | mutex_lock(&qcam->lock); | 676 | mutex_lock(&qcam->lock); |
682 | parport_claim_or_block(qcam->pdev); | 677 | parport_claim_or_block(qcam->pdev); |
683 | /* Probably should have a semaphore against multiple users */ | 678 | /* Probably should have a semaphore against multiple users */ |
684 | len = qc_capture(qcam, buf,count); | 679 | len = qc_capture(qcam, buf, count); |
685 | parport_release(qcam->pdev); | 680 | parport_release(qcam->pdev); |
686 | mutex_unlock(&qcam->lock); | 681 | mutex_unlock(&qcam->lock); |
687 | return len; | 682 | return len; |
@@ -713,8 +708,7 @@ static const struct v4l2_file_operations qcam_fops = { | |||
713 | .read = qcam_read, | 708 | .read = qcam_read, |
714 | }; | 709 | }; |
715 | 710 | ||
716 | static struct video_device qcam_template= | 711 | static struct video_device qcam_template = { |
717 | { | ||
718 | .name = "Colour QuickCam", | 712 | .name = "Colour QuickCam", |
719 | .fops = &qcam_fops, | 713 | .fops = &qcam_fops, |
720 | .release = video_device_release_empty, | 714 | .release = video_device_release_empty, |
@@ -727,17 +721,16 @@ static struct qcam_device *qcam_init(struct parport *port) | |||
727 | struct qcam_device *q; | 721 | struct qcam_device *q; |
728 | 722 | ||
729 | q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); | 723 | q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); |
730 | if(q==NULL) | 724 | if (q == NULL) |
731 | return NULL; | 725 | return NULL; |
732 | 726 | ||
733 | q->pport = port; | 727 | q->pport = port; |
734 | q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, | 728 | q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, |
735 | NULL, 0, NULL); | 729 | NULL, 0, NULL); |
736 | 730 | ||
737 | q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0; | 731 | q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; |
738 | 732 | ||
739 | if (q->pdev == NULL) | 733 | if (q->pdev == NULL) { |
740 | { | ||
741 | printk(KERN_ERR "c-qcam: couldn't register for %s.\n", | 734 | printk(KERN_ERR "c-qcam: couldn't register for %s.\n", |
742 | port->name); | 735 | port->name); |
743 | kfree(q); | 736 | kfree(q); |
@@ -765,12 +758,11 @@ static int init_cqcam(struct parport *port) | |||
765 | { | 758 | { |
766 | struct qcam_device *qcam; | 759 | struct qcam_device *qcam; |
767 | 760 | ||
768 | if (parport[0] != -1) | 761 | if (parport[0] != -1) { |
769 | { | ||
770 | /* The user gave specific instructions */ | 762 | /* The user gave specific instructions */ |
771 | int i, found = 0; | 763 | int i, found = 0; |
772 | for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) | 764 | |
773 | { | 765 | for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) { |
774 | if (parport[0] == port->number) | 766 | if (parport[0] == port->number) |
775 | found = 1; | 767 | found = 1; |
776 | } | 768 | } |
@@ -782,15 +774,14 @@ static int init_cqcam(struct parport *port) | |||
782 | return -ENOSPC; | 774 | return -ENOSPC; |
783 | 775 | ||
784 | qcam = qcam_init(port); | 776 | qcam = qcam_init(port); |
785 | if (qcam==NULL) | 777 | if (qcam == NULL) |
786 | return -ENODEV; | 778 | return -ENODEV; |
787 | 779 | ||
788 | parport_claim_or_block(qcam->pdev); | 780 | parport_claim_or_block(qcam->pdev); |
789 | 781 | ||
790 | qc_reset(qcam); | 782 | qc_reset(qcam); |
791 | 783 | ||
792 | if (probe && qc_detect(qcam)==0) | 784 | if (probe && qc_detect(qcam) == 0) { |
793 | { | ||
794 | parport_release(qcam->pdev); | 785 | parport_release(qcam->pdev); |
795 | parport_unregister_device(qcam->pdev); | 786 | parport_unregister_device(qcam->pdev); |
796 | kfree(qcam); | 787 | kfree(qcam); |
@@ -840,14 +831,14 @@ static struct parport_driver cqcam_driver = { | |||
840 | .detach = cq_detach, | 831 | .detach = cq_detach, |
841 | }; | 832 | }; |
842 | 833 | ||
843 | static int __init cqcam_init (void) | 834 | static int __init cqcam_init(void) |
844 | { | 835 | { |
845 | printk(BANNER "\n"); | 836 | printk(BANNER "\n"); |
846 | 837 | ||
847 | return parport_register_driver(&cqcam_driver); | 838 | return parport_register_driver(&cqcam_driver); |
848 | } | 839 | } |
849 | 840 | ||
850 | static void __exit cqcam_cleanup (void) | 841 | static void __exit cqcam_cleanup(void) |
851 | { | 842 | { |
852 | unsigned int i; | 843 | unsigned int i; |
853 | 844 | ||
@@ -862,9 +853,9 @@ MODULE_DESCRIPTION(BANNER); | |||
862 | MODULE_LICENSE("GPL"); | 853 | MODULE_LICENSE("GPL"); |
863 | 854 | ||
864 | /* FIXME: parport=auto would never have worked, surely? --RR */ | 855 | /* FIXME: parport=auto would never have worked, surely? --RR */ |
865 | MODULE_PARM_DESC(parport ,"parport=<auto|n[,n]...> for port detection method\n\ | 856 | MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n" |
866 | probe=<0|1|2> for camera detection method\n\ | 857 | "probe=<0|1|2> for camera detection method\n" |
867 | force_rgb=<0|1> for RGB data format (default BGR)"); | 858 | "force_rgb=<0|1> for RGB data format (default BGR)"); |
868 | module_param_array(parport, int, NULL, 0); | 859 | module_param_array(parport, int, NULL, 0); |
869 | module_param(probe, int, 0); | 860 | module_param(probe, int, 0); |
870 | module_param(force_rgb, bool, 0); | 861 | module_param(force_rgb, bool, 0); |
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 6f91415eb7b4..5520789854da 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -324,7 +324,7 @@ static int cpia2_close(struct file *file) | |||
324 | { | 324 | { |
325 | if(fh->mmapped) | 325 | if(fh->mmapped) |
326 | cam->mmapped = 0; | 326 | cam->mmapped = 0; |
327 | v4l2_prio_close(&cam->prio,&fh->prio); | 327 | v4l2_prio_close(&cam->prio, fh->prio); |
328 | file->private_data = NULL; | 328 | file->private_data = NULL; |
329 | kfree(fh); | 329 | kfree(fh); |
330 | } | 330 | } |
@@ -1592,7 +1592,7 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
1592 | case VIDIOC_S_FMT: | 1592 | case VIDIOC_S_FMT: |
1593 | { | 1593 | { |
1594 | struct cpia2_fh *fh = file->private_data; | 1594 | struct cpia2_fh *fh = file->private_data; |
1595 | retval = v4l2_prio_check(&cam->prio, &fh->prio); | 1595 | retval = v4l2_prio_check(&cam->prio, fh->prio); |
1596 | if(retval) { | 1596 | if(retval) { |
1597 | mutex_unlock(&cam->busy_lock); | 1597 | mutex_unlock(&cam->busy_lock); |
1598 | return retval; | 1598 | return retval; |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 4392c76af5df..0e5006b14279 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -579,6 +579,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
579 | 579 | ||
580 | u8 afe_mux_cfg; | 580 | u8 afe_mux_cfg; |
581 | u8 adc2_cfg; | 581 | u8 adc2_cfg; |
582 | u8 input_mode; | ||
582 | u32 afe_cfg; | 583 | u32 afe_cfg; |
583 | int i; | 584 | int i; |
584 | 585 | ||
@@ -589,6 +590,30 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
589 | vid_input <= CX18_AV_COMPOSITE8) { | 590 | vid_input <= CX18_AV_COMPOSITE8) { |
590 | afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); | 591 | afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); |
591 | ch[0] = CVBS; | 592 | ch[0] = CVBS; |
593 | input_mode = 0x0; | ||
594 | } else if (vid_input >= CX18_AV_COMPONENT_LUMA1) { | ||
595 | int luma = vid_input & 0xf000; | ||
596 | int r_chroma = vid_input & 0xf0000; | ||
597 | int b_chroma = vid_input & 0xf00000; | ||
598 | |||
599 | if ((vid_input & ~0xfff000) || | ||
600 | luma < CX18_AV_COMPONENT_LUMA1 || | ||
601 | luma > CX18_AV_COMPONENT_LUMA8 || | ||
602 | r_chroma < CX18_AV_COMPONENT_R_CHROMA4 || | ||
603 | r_chroma > CX18_AV_COMPONENT_R_CHROMA6 || | ||
604 | b_chroma < CX18_AV_COMPONENT_B_CHROMA7 || | ||
605 | b_chroma > CX18_AV_COMPONENT_B_CHROMA8) { | ||
606 | CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n", | ||
607 | vid_input); | ||
608 | return -EINVAL; | ||
609 | } | ||
610 | afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12; | ||
611 | ch[0] = Y; | ||
612 | afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12; | ||
613 | ch[1] = Pr; | ||
614 | afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14; | ||
615 | ch[2] = Pb; | ||
616 | input_mode = 0x6; | ||
592 | } else { | 617 | } else { |
593 | int luma = vid_input & 0xf0; | 618 | int luma = vid_input & 0xf0; |
594 | int chroma = vid_input & 0xf00; | 619 | int chroma = vid_input & 0xf00; |
@@ -598,7 +623,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
598 | luma > CX18_AV_SVIDEO_LUMA8 || | 623 | luma > CX18_AV_SVIDEO_LUMA8 || |
599 | chroma < CX18_AV_SVIDEO_CHROMA4 || | 624 | chroma < CX18_AV_SVIDEO_CHROMA4 || |
600 | chroma > CX18_AV_SVIDEO_CHROMA8) { | 625 | chroma > CX18_AV_SVIDEO_CHROMA8) { |
601 | CX18_ERR_DEV(sd, "0x%04x is not a valid video input!\n", | 626 | CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n", |
602 | vid_input); | 627 | vid_input); |
603 | return -EINVAL; | 628 | return -EINVAL; |
604 | } | 629 | } |
@@ -613,8 +638,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
613 | afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; | 638 | afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; |
614 | ch[1] = C; | 639 | ch[1] = C; |
615 | } | 640 | } |
641 | input_mode = 0x2; | ||
616 | } | 642 | } |
617 | /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */ | ||
618 | 643 | ||
619 | switch (aud_input) { | 644 | switch (aud_input) { |
620 | case CX18_AV_AUDIO_SERIAL1: | 645 | case CX18_AV_AUDIO_SERIAL1: |
@@ -650,8 +675,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
650 | 675 | ||
651 | /* Set up analog front end multiplexers */ | 676 | /* Set up analog front end multiplexers */ |
652 | cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7); | 677 | cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7); |
653 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ | 678 | /* Set INPUT_MODE to Composite, S-Video, or Component */ |
654 | cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02); | 679 | cx18_av_and_or(cx, 0x401, ~0x6, input_mode); |
655 | 680 | ||
656 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 681 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
657 | adc2_cfg = cx18_av_read(cx, 0x102); | 682 | adc2_cfg = cx18_av_read(cx, 0x102); |
@@ -998,9 +1023,9 @@ static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | |||
998 | 1023 | ||
999 | static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 1024 | static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
1000 | { | 1025 | { |
1001 | struct cx18 *cx = v4l2_get_subdevdata(sd); | 1026 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) |
1002 | 1027 | return -EINVAL; | |
1003 | return cx18_av_vbi_g_fmt(cx, fmt); | 1028 | return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced); |
1004 | } | 1029 | } |
1005 | 1030 | ||
1006 | static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 1031 | static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
@@ -1073,12 +1098,6 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
1073 | cx18_av_write(cx, 0x41e, 0x8 | filter); | 1098 | cx18_av_write(cx, 0x41e, 0x8 | filter); |
1074 | break; | 1099 | break; |
1075 | 1100 | ||
1076 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
1077 | return cx18_av_vbi_s_fmt(cx, fmt); | ||
1078 | |||
1079 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
1080 | return cx18_av_vbi_s_fmt(cx, fmt); | ||
1081 | |||
1082 | default: | 1101 | default: |
1083 | return -EINVAL; | 1102 | return -EINVAL; |
1084 | } | 1103 | } |
@@ -1378,17 +1397,24 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { | |||
1378 | 1397 | ||
1379 | static const struct v4l2_subdev_video_ops cx18_av_video_ops = { | 1398 | static const struct v4l2_subdev_video_ops cx18_av_video_ops = { |
1380 | .s_routing = cx18_av_s_video_routing, | 1399 | .s_routing = cx18_av_s_video_routing, |
1381 | .decode_vbi_line = cx18_av_decode_vbi_line, | ||
1382 | .s_stream = cx18_av_s_stream, | 1400 | .s_stream = cx18_av_s_stream, |
1383 | .g_fmt = cx18_av_g_fmt, | 1401 | .g_fmt = cx18_av_g_fmt, |
1384 | .s_fmt = cx18_av_s_fmt, | 1402 | .s_fmt = cx18_av_s_fmt, |
1385 | }; | 1403 | }; |
1386 | 1404 | ||
1405 | static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { | ||
1406 | .decode_vbi_line = cx18_av_decode_vbi_line, | ||
1407 | .g_sliced_fmt = cx18_av_g_sliced_fmt, | ||
1408 | .s_sliced_fmt = cx18_av_s_sliced_fmt, | ||
1409 | .s_raw_fmt = cx18_av_s_raw_fmt, | ||
1410 | }; | ||
1411 | |||
1387 | static const struct v4l2_subdev_ops cx18_av_ops = { | 1412 | static const struct v4l2_subdev_ops cx18_av_ops = { |
1388 | .core = &cx18_av_general_ops, | 1413 | .core = &cx18_av_general_ops, |
1389 | .tuner = &cx18_av_tuner_ops, | 1414 | .tuner = &cx18_av_tuner_ops, |
1390 | .audio = &cx18_av_audio_ops, | 1415 | .audio = &cx18_av_audio_ops, |
1391 | .video = &cx18_av_video_ops, | 1416 | .video = &cx18_av_video_ops, |
1417 | .vbi = &cx18_av_vbi_ops, | ||
1392 | }; | 1418 | }; |
1393 | 1419 | ||
1394 | int cx18_av_probe(struct cx18 *cx) | 1420 | int cx18_av_probe(struct cx18 *cx) |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index cafb7e99b9a0..c106967bdcc3 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
@@ -61,6 +61,25 @@ enum cx18_av_video_input { | |||
61 | CX18_AV_SVIDEO2 = 0x620, | 61 | CX18_AV_SVIDEO2 = 0x620, |
62 | CX18_AV_SVIDEO3 = 0x730, | 62 | CX18_AV_SVIDEO3 = 0x730, |
63 | CX18_AV_SVIDEO4 = 0x840, | 63 | CX18_AV_SVIDEO4 = 0x840, |
64 | |||
65 | /* Component Video inputs consist of one luma input (In1-In8) ORed | ||
66 | with a red chroma (In4-In6) and blue chroma input (In7-In8) */ | ||
67 | CX18_AV_COMPONENT_LUMA1 = 0x1000, | ||
68 | CX18_AV_COMPONENT_LUMA2 = 0x2000, | ||
69 | CX18_AV_COMPONENT_LUMA3 = 0x3000, | ||
70 | CX18_AV_COMPONENT_LUMA4 = 0x4000, | ||
71 | CX18_AV_COMPONENT_LUMA5 = 0x5000, | ||
72 | CX18_AV_COMPONENT_LUMA6 = 0x6000, | ||
73 | CX18_AV_COMPONENT_LUMA7 = 0x7000, | ||
74 | CX18_AV_COMPONENT_LUMA8 = 0x8000, | ||
75 | CX18_AV_COMPONENT_R_CHROMA4 = 0x40000, | ||
76 | CX18_AV_COMPONENT_R_CHROMA5 = 0x50000, | ||
77 | CX18_AV_COMPONENT_R_CHROMA6 = 0x60000, | ||
78 | CX18_AV_COMPONENT_B_CHROMA7 = 0x700000, | ||
79 | CX18_AV_COMPONENT_B_CHROMA8 = 0x800000, | ||
80 | |||
81 | /* Component Video aliases for common combinations */ | ||
82 | CX18_AV_COMPONENT1 = 0x861000, | ||
64 | }; | 83 | }; |
65 | 84 | ||
66 | enum cx18_av_audio_input { | 85 | enum cx18_av_audio_input { |
@@ -359,7 +378,8 @@ void cx18_av_audio_set_path(struct cx18 *cx); | |||
359 | /* cx18_av-vbi.c */ | 378 | /* cx18_av-vbi.c */ |
360 | int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, | 379 | int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, |
361 | struct v4l2_decode_vbi_line *vbi); | 380 | struct v4l2_decode_vbi_line *vbi); |
362 | int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt); | 381 | int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); |
363 | int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt); | 382 | int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); |
383 | int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); | ||
364 | 384 | ||
365 | #endif | 385 | #endif |
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index a51732bcca4b..baa36fbcd4d4 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c | |||
@@ -129,10 +129,10 @@ static int decode_vps(u8 *dst, u8 *p) | |||
129 | return err & 0xf0; | 129 | return err & 0xf0; |
130 | } | 130 | } |
131 | 131 | ||
132 | int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) | 132 | int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) |
133 | { | 133 | { |
134 | struct cx18 *cx = v4l2_get_subdevdata(sd); | ||
134 | struct cx18_av_state *state = &cx->av_state; | 135 | struct cx18_av_state *state = &cx->av_state; |
135 | struct v4l2_sliced_vbi_format *svbi; | ||
136 | static const u16 lcr2vbi[] = { | 136 | static const u16 lcr2vbi[] = { |
137 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | 137 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ |
138 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | 138 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ |
@@ -143,9 +143,6 @@ int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) | |||
143 | int is_pal = !(state->std & V4L2_STD_525_60); | 143 | int is_pal = !(state->std & V4L2_STD_525_60); |
144 | int i; | 144 | int i; |
145 | 145 | ||
146 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
147 | return -EINVAL; | ||
148 | svbi = &fmt->fmt.sliced; | ||
149 | memset(svbi, 0, sizeof(*svbi)); | 146 | memset(svbi, 0, sizeof(*svbi)); |
150 | /* we're done if raw VBI is active */ | 147 | /* we're done if raw VBI is active */ |
151 | if ((cx18_av_read(cx, 0x404) & 0x10) == 0) | 148 | if ((cx18_av_read(cx, 0x404) & 0x10) == 0) |
@@ -173,30 +170,27 @@ int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) | |||
173 | return 0; | 170 | return 0; |
174 | } | 171 | } |
175 | 172 | ||
176 | int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) | 173 | int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) |
177 | { | 174 | { |
175 | struct cx18 *cx = v4l2_get_subdevdata(sd); | ||
178 | struct cx18_av_state *state = &cx->av_state; | 176 | struct cx18_av_state *state = &cx->av_state; |
179 | struct v4l2_sliced_vbi_format *svbi; | ||
180 | int is_pal = !(state->std & V4L2_STD_525_60); | ||
181 | int i, x; | ||
182 | u8 lcr[24]; | ||
183 | 177 | ||
184 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && | 178 | /* Setup standard */ |
185 | fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) | 179 | cx18_av_std_setup(cx); |
186 | return -EINVAL; | ||
187 | svbi = &fmt->fmt.sliced; | ||
188 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
189 | /* raw VBI */ | ||
190 | memset(svbi, 0, sizeof(*svbi)); | ||
191 | 180 | ||
192 | /* Setup standard */ | 181 | /* VBI Offset */ |
193 | cx18_av_std_setup(cx); | 182 | cx18_av_write(cx, 0x47f, state->slicer_line_delay); |
183 | cx18_av_write(cx, 0x404, 0x2e); | ||
184 | return 0; | ||
185 | } | ||
194 | 186 | ||
195 | /* VBI Offset */ | 187 | int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) |
196 | cx18_av_write(cx, 0x47f, state->slicer_line_delay); | 188 | { |
197 | cx18_av_write(cx, 0x404, 0x2e); | 189 | struct cx18 *cx = v4l2_get_subdevdata(sd); |
198 | return 0; | 190 | struct cx18_av_state *state = &cx->av_state; |
199 | } | 191 | int is_pal = !(state->std & V4L2_STD_525_60); |
192 | int i, x; | ||
193 | u8 lcr[24]; | ||
200 | 194 | ||
201 | for (x = 0; x <= 23; x++) | 195 | for (x = 0; x <= 23; x++) |
202 | lcr[x] = 0x00; | 196 | lcr[x] = 0x00; |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f808fb6fc1c1..74e122b5fc49 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -370,6 +370,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { | |||
370 | { CX18_CARD_INPUT_SVIDEO1, 1, | 370 | { CX18_CARD_INPUT_SVIDEO1, 1, |
371 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | 371 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
372 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, | 372 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, |
373 | { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 }, | ||
373 | }, | 374 | }, |
374 | .audio_inputs = { | 375 | .audio_inputs = { |
375 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | 376 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
@@ -422,6 +423,7 @@ static const struct cx18_card cx18_card_leadtek_dvr3100h = { | |||
422 | { CX18_CARD_INPUT_SVIDEO1, 1, | 423 | { CX18_CARD_INPUT_SVIDEO1, 1, |
423 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | 424 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
424 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, | 425 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, |
426 | { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 }, | ||
425 | }, | 427 | }, |
426 | .audio_inputs = { | 428 | .audio_inputs = { |
427 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | 429 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
@@ -480,7 +482,7 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input) | |||
480 | "S-Video 2", | 482 | "S-Video 2", |
481 | "Composite 1", | 483 | "Composite 1", |
482 | "Composite 2", | 484 | "Composite 2", |
483 | "Composite 3" | 485 | "Component 1" |
484 | }; | 486 | }; |
485 | 487 | ||
486 | memset(input, 0, sizeof(*input)); | 488 | memset(input, 0, sizeof(*input)); |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index af3d71607dc9..796e517300ac 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
@@ -43,7 +43,7 @@ | |||
43 | #define CX18_CARD_INPUT_SVIDEO2 3 | 43 | #define CX18_CARD_INPUT_SVIDEO2 3 |
44 | #define CX18_CARD_INPUT_COMPOSITE1 4 | 44 | #define CX18_CARD_INPUT_COMPOSITE1 4 |
45 | #define CX18_CARD_INPUT_COMPOSITE2 5 | 45 | #define CX18_CARD_INPUT_COMPOSITE2 5 |
46 | #define CX18_CARD_INPUT_COMPOSITE3 6 | 46 | #define CX18_CARD_INPUT_COMPONENT1 6 |
47 | 47 | ||
48 | /* audio inputs */ | 48 | /* audio inputs */ |
49 | #define CX18_CARD_INPUT_AUD_TUNER 1 | 49 | #define CX18_CARD_INPUT_AUD_TUNER 1 |
@@ -62,7 +62,7 @@ | |||
62 | struct cx18_card_video_input { | 62 | struct cx18_card_video_input { |
63 | u8 video_type; /* video input type */ | 63 | u8 video_type; /* video input type */ |
64 | u8 audio_index; /* index in cx18_card_audio_input array */ | 64 | u8 audio_index; /* index in cx18_card_audio_input array */ |
65 | u16 video_input; /* hardware video input */ | 65 | u32 video_input; /* hardware video input */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct cx18_card_audio_input { | 68 | struct cx18_card_audio_input { |
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 7fa589240ff2..4b4b46544d5a 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -263,7 +263,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) | |||
263 | int ret; | 263 | int ret; |
264 | struct v4l2_control ctrl; | 264 | struct v4l2_control ctrl; |
265 | 265 | ||
266 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 266 | ret = v4l2_prio_check(&cx->prio, id->prio); |
267 | if (ret) | 267 | if (ret) |
268 | return ret; | 268 | return ret; |
269 | 269 | ||
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 863ce7758239..e12a15020cda 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -700,7 +700,7 @@ int cx18_v4l2_close(struct file *filp) | |||
700 | 700 | ||
701 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); | 701 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); |
702 | 702 | ||
703 | v4l2_prio_close(&cx->prio, &id->prio); | 703 | v4l2_prio_close(&cx->prio, id->prio); |
704 | 704 | ||
705 | /* Easy case first: this stream was never claimed by us */ | 705 | /* Easy case first: this stream was never claimed by us */ |
706 | if (s->id != id->open_id) { | 706 | if (s->id != id->open_id) { |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index eecf29af916c..cfa1f289b0f5 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -109,7 +109,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, | |||
109 | /* Our default information for ir-kbd-i2c.c to use */ | 109 | /* Our default information for ir-kbd-i2c.c to use */ |
110 | switch (hw) { | 110 | switch (hw) { |
111 | case CX18_HW_Z8F0811_IR_RX_HAUP: | 111 | case CX18_HW_Z8F0811_IR_RX_HAUP: |
112 | init_data->ir_codes = &ir_codes_hauppauge_new_table; | 112 | init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; |
113 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; | 113 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; |
114 | init_data->type = IR_TYPE_RC5; | 114 | init_data->type = IR_TYPE_RC5; |
115 | init_data->name = cx->card_name; | 115 | init_data->name = cx->card_name; |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index b81dd0ea8eb9..2530fc54daaf 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -208,7 +208,7 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, | |||
208 | * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in | 208 | * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in |
209 | * fmt->fmt.sliced under valid calling conditions | 209 | * fmt->fmt.sliced under valid calling conditions |
210 | */ | 210 | */ |
211 | if (v4l2_subdev_call(cx->sd_av, video, g_fmt, fmt)) | 211 | if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced)) |
212 | return -EINVAL; | 212 | return -EINVAL; |
213 | 213 | ||
214 | /* Ensure V4L2 spec compliant output */ | 214 | /* Ensure V4L2 spec compliant output */ |
@@ -277,7 +277,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
277 | int ret; | 277 | int ret; |
278 | int w, h; | 278 | int w, h; |
279 | 279 | ||
280 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 280 | ret = v4l2_prio_check(&cx->prio, id->prio); |
281 | if (ret) | 281 | if (ret) |
282 | return ret; | 282 | return ret; |
283 | 283 | ||
@@ -306,7 +306,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, | |||
306 | struct cx18 *cx = id->cx; | 306 | struct cx18 *cx = id->cx; |
307 | int ret; | 307 | int ret; |
308 | 308 | ||
309 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 309 | ret = v4l2_prio_check(&cx->prio, id->prio); |
310 | if (ret) | 310 | if (ret) |
311 | return ret; | 311 | return ret; |
312 | 312 | ||
@@ -322,7 +322,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, | |||
322 | * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid | 322 | * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid |
323 | * calling conditions | 323 | * calling conditions |
324 | */ | 324 | */ |
325 | ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); | 325 | ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi); |
326 | if (ret) | 326 | if (ret) |
327 | return ret; | 327 | return ret; |
328 | 328 | ||
@@ -341,7 +341,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, | |||
341 | int ret; | 341 | int ret; |
342 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | 342 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
343 | 343 | ||
344 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 344 | ret = v4l2_prio_check(&cx->prio, id->prio); |
345 | if (ret) | 345 | if (ret) |
346 | return ret; | 346 | return ret; |
347 | 347 | ||
@@ -359,7 +359,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, | |||
359 | * Note, cx18_av_vbi() wipes some "impossible" service lines in the | 359 | * Note, cx18_av_vbi() wipes some "impossible" service lines in the |
360 | * passed in fmt->fmt.sliced under valid calling conditions | 360 | * passed in fmt->fmt.sliced under valid calling conditions |
361 | */ | 361 | */ |
362 | ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); | 362 | ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced); |
363 | if (ret) | 363 | if (ret) |
364 | return ret; | 364 | return ret; |
365 | /* Store our current v4l2 sliced VBI settings */ | 365 | /* Store our current v4l2 sliced VBI settings */ |
@@ -549,7 +549,7 @@ static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) | |||
549 | struct cx18 *cx = id->cx; | 549 | struct cx18 *cx = id->cx; |
550 | int ret; | 550 | int ret; |
551 | 551 | ||
552 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 552 | ret = v4l2_prio_check(&cx->prio, id->prio); |
553 | if (ret) | 553 | if (ret) |
554 | return ret; | 554 | return ret; |
555 | 555 | ||
@@ -601,7 +601,7 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp) | |||
601 | struct cx18 *cx = id->cx; | 601 | struct cx18 *cx = id->cx; |
602 | int ret; | 602 | int ret; |
603 | 603 | ||
604 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 604 | ret = v4l2_prio_check(&cx->prio, id->prio); |
605 | if (ret) | 605 | if (ret) |
606 | return ret; | 606 | return ret; |
607 | 607 | ||
@@ -647,7 +647,7 @@ int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) | |||
647 | struct cx18 *cx = id->cx; | 647 | struct cx18 *cx = id->cx; |
648 | int ret; | 648 | int ret; |
649 | 649 | ||
650 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 650 | ret = v4l2_prio_check(&cx->prio, id->prio); |
651 | if (ret) | 651 | if (ret) |
652 | return ret; | 652 | return ret; |
653 | 653 | ||
@@ -675,7 +675,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) | |||
675 | struct cx18 *cx = id->cx; | 675 | struct cx18 *cx = id->cx; |
676 | int ret; | 676 | int ret; |
677 | 677 | ||
678 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 678 | ret = v4l2_prio_check(&cx->prio, id->prio); |
679 | if (ret) | 679 | if (ret) |
680 | return ret; | 680 | return ret; |
681 | 681 | ||
@@ -715,7 +715,7 @@ static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | |||
715 | struct cx18 *cx = id->cx; | 715 | struct cx18 *cx = id->cx; |
716 | int ret; | 716 | int ret; |
717 | 717 | ||
718 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 718 | ret = v4l2_prio_check(&cx->prio, id->prio); |
719 | if (ret) | 719 | if (ret) |
720 | return ret; | 720 | return ret; |
721 | 721 | ||
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 054450f65a60..f5c91261b2db 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -374,7 +374,10 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
374 | } | 374 | } |
375 | 375 | ||
376 | /* setup VBI registers */ | 376 | /* setup VBI registers */ |
377 | v4l2_subdev_call(cx->sd_av, video, s_fmt, &cx->vbi.in); | 377 | if (raw) |
378 | v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi); | ||
379 | else | ||
380 | v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced); | ||
378 | 381 | ||
379 | /* | 382 | /* |
380 | * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw | 383 | * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw |
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 574c1c6974f8..582227522cf0 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c | |||
@@ -174,7 +174,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, | |||
174 | p[3] != sliced_vbi_eav_rp[1])) | 174 | p[3] != sliced_vbi_eav_rp[1])) |
175 | continue; | 175 | continue; |
176 | vbi.p = p + 4; | 176 | vbi.p = p + 4; |
177 | v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); | 177 | v4l2_subdev_call(cx->sd_av, vbi, decode_vbi_line, &vbi); |
178 | if (vbi.type) { | 178 | if (vbi.type) { |
179 | cx->vbi.sliced_data[line].id = vbi.type; | 179 | cx->vbi.sliced_data[line].id = vbi.type; |
180 | cx->vbi.sliced_data[line].field = vbi.is_second_field; | 180 | cx->vbi.sliced_data[line].field = vbi.is_second_field; |
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index 7793d60966db..7cae95a2245e 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c | |||
@@ -495,7 +495,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) | |||
495 | pcm->info_flags = 0; | 495 | pcm->info_flags = 0; |
496 | pcm->private_data = dev; | 496 | pcm->private_data = dev; |
497 | strcpy(pcm->name, "Conexant cx231xx Capture"); | 497 | strcpy(pcm->name, "Conexant cx231xx Capture"); |
498 | strcpy(card->driver, "Conexant cx231xx Audio"); | 498 | strcpy(card->driver, "Cx231xx-Audio"); |
499 | strcpy(card->shortname, "Cx231xx Audio"); | 499 | strcpy(card->shortname, "Cx231xx Audio"); |
500 | strcpy(card->longname, "Conexant cx231xx Audio"); | 500 | strcpy(card->longname, "Conexant cx231xx Audio"); |
501 | 501 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index b24eee115e7e..f5e1a2315fcc 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c | |||
@@ -96,10 +96,9 @@ int cx231xx_register_extension(struct cx231xx_ops *ops) | |||
96 | mutex_lock(&cx231xx_devlist_mutex); | 96 | mutex_lock(&cx231xx_devlist_mutex); |
97 | mutex_lock(&cx231xx_extension_devlist_lock); | 97 | mutex_lock(&cx231xx_extension_devlist_lock); |
98 | list_add_tail(&ops->next, &cx231xx_extension_devlist); | 98 | list_add_tail(&ops->next, &cx231xx_extension_devlist); |
99 | list_for_each_entry(dev, &cx231xx_devlist, devlist) { | 99 | list_for_each_entry(dev, &cx231xx_devlist, devlist) |
100 | if (dev) | 100 | ops->init(dev); |
101 | ops->init(dev); | 101 | |
102 | } | ||
103 | printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); | 102 | printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); |
104 | mutex_unlock(&cx231xx_extension_devlist_lock); | 103 | mutex_unlock(&cx231xx_extension_devlist_lock); |
105 | mutex_unlock(&cx231xx_devlist_mutex); | 104 | mutex_unlock(&cx231xx_devlist_mutex); |
@@ -112,10 +111,8 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) | |||
112 | struct cx231xx *dev = NULL; | 111 | struct cx231xx *dev = NULL; |
113 | 112 | ||
114 | mutex_lock(&cx231xx_devlist_mutex); | 113 | mutex_lock(&cx231xx_devlist_mutex); |
115 | list_for_each_entry(dev, &cx231xx_devlist, devlist) { | 114 | list_for_each_entry(dev, &cx231xx_devlist, devlist) |
116 | if (dev) | 115 | ops->fini(dev); |
117 | ops->fini(dev); | ||
118 | } | ||
119 | 116 | ||
120 | mutex_lock(&cx231xx_extension_devlist_lock); | 117 | mutex_lock(&cx231xx_extension_devlist_lock); |
121 | printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); | 118 | printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index b473cd8367f5..fd099153b746 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -35,6 +35,8 @@ static unsigned int ir_debug; | |||
35 | module_param(ir_debug, int, 0644); | 35 | module_param(ir_debug, int, 0644); |
36 | MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); | 36 | MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); |
37 | 37 | ||
38 | #define MODULE_NAME "cx231xx" | ||
39 | |||
38 | #define i2cdprintk(fmt, arg...) \ | 40 | #define i2cdprintk(fmt, arg...) \ |
39 | if (ir_debug) { \ | 41 | if (ir_debug) { \ |
40 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ | 42 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ |
@@ -59,7 +61,6 @@ struct cx231xx_ir_poll_result { | |||
59 | struct cx231xx_IR { | 61 | struct cx231xx_IR { |
60 | struct cx231xx *dev; | 62 | struct cx231xx *dev; |
61 | struct input_dev *input; | 63 | struct input_dev *input; |
62 | struct ir_input_state ir; | ||
63 | char name[32]; | 64 | char name[32]; |
64 | char phys[32]; | 65 | char phys[32]; |
65 | 66 | ||
@@ -67,9 +68,7 @@ struct cx231xx_IR { | |||
67 | int polling; | 68 | int polling; |
68 | struct work_struct work; | 69 | struct work_struct work; |
69 | struct timer_list timer; | 70 | struct timer_list timer; |
70 | unsigned int last_toggle:1; | ||
71 | unsigned int last_readcount; | 71 | unsigned int last_readcount; |
72 | unsigned int repeat_interval; | ||
73 | 72 | ||
74 | int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *); | 73 | int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *); |
75 | }; | 74 | }; |
@@ -81,7 +80,6 @@ struct cx231xx_IR { | |||
81 | static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) | 80 | static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) |
82 | { | 81 | { |
83 | int result; | 82 | int result; |
84 | int do_sendkey = 0; | ||
85 | struct cx231xx_ir_poll_result poll_result; | 83 | struct cx231xx_ir_poll_result poll_result; |
86 | 84 | ||
87 | /* read the registers containing the IR status */ | 85 | /* read the registers containing the IR status */ |
@@ -95,44 +93,23 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) | |||
95 | poll_result.toggle_bit, poll_result.read_count, | 93 | poll_result.toggle_bit, poll_result.read_count, |
96 | ir->last_readcount, poll_result.rc_data[0]); | 94 | ir->last_readcount, poll_result.rc_data[0]); |
97 | 95 | ||
98 | if (ir->dev->chip_id == CHIP_ID_EM2874) { | 96 | if (poll_result.read_count > 0 && |
97 | poll_result.read_count != ir->last_readcount) | ||
98 | ir_keydown(ir->input, | ||
99 | poll_result.rc_data[0], | ||
100 | poll_result.toggle_bit); | ||
101 | |||
102 | if (ir->dev->chip_id == CHIP_ID_EM2874) | ||
99 | /* The em2874 clears the readcount field every time the | 103 | /* The em2874 clears the readcount field every time the |
100 | register is read. The em2860/2880 datasheet says that it | 104 | register is read. The em2860/2880 datasheet says that it |
101 | is supposed to clear the readcount, but it doesn't. So with | 105 | is supposed to clear the readcount, but it doesn't. So with |
102 | the em2874, we are looking for a non-zero read count as | 106 | the em2874, we are looking for a non-zero read count as |
103 | opposed to a readcount that is incrementing */ | 107 | opposed to a readcount that is incrementing */ |
104 | ir->last_readcount = 0; | 108 | ir->last_readcount = 0; |
105 | } | 109 | else |
106 | 110 | ir->last_readcount = poll_result.read_count; | |
107 | if (poll_result.read_count == 0) { | ||
108 | /* The button has not been pressed since the last read */ | ||
109 | } else if (ir->last_toggle != poll_result.toggle_bit) { | ||
110 | /* A button has been pressed */ | ||
111 | dprintk("button has been pressed\n"); | ||
112 | ir->last_toggle = poll_result.toggle_bit; | ||
113 | ir->repeat_interval = 0; | ||
114 | do_sendkey = 1; | ||
115 | } else if (poll_result.toggle_bit == ir->last_toggle && | ||
116 | poll_result.read_count > 0 && | ||
117 | poll_result.read_count != ir->last_readcount) { | ||
118 | /* The button is still being held down */ | ||
119 | dprintk("button being held down\n"); | ||
120 | |||
121 | /* Debouncer for first keypress */ | ||
122 | if (ir->repeat_interval++ > 9) { | ||
123 | /* Start repeating after 1 second */ | ||
124 | do_sendkey = 1; | ||
125 | } | ||
126 | } | ||
127 | 111 | ||
128 | if (do_sendkey) { | ||
129 | dprintk("sending keypress\n"); | ||
130 | ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); | ||
131 | ir_input_nokey(ir->input, &ir->ir); | ||
132 | } | 112 | } |
133 | |||
134 | ir->last_readcount = poll_result.read_count; | ||
135 | return; | ||
136 | } | 113 | } |
137 | 114 | ||
138 | static void ir_timer(unsigned long data) | 115 | static void ir_timer(unsigned long data) |
@@ -198,10 +175,6 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
198 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 175 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
199 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 176 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
200 | 177 | ||
201 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | ||
202 | if (err < 0) | ||
203 | goto err_out_free; | ||
204 | |||
205 | input_dev->name = ir->name; | 178 | input_dev->name = ir->name; |
206 | input_dev->phys = ir->phys; | 179 | input_dev->phys = ir->phys; |
207 | input_dev->id.bustype = BUS_USB; | 180 | input_dev->id.bustype = BUS_USB; |
@@ -217,7 +190,8 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
217 | cx231xx_ir_start(ir); | 190 | cx231xx_ir_start(ir); |
218 | 191 | ||
219 | /* all done */ | 192 | /* all done */ |
220 | err = ir_input_register(ir->input, dev->board.ir_codes, NULL); | 193 | err = __ir_input_register(ir->input, dev->board.ir_codes, |
194 | NULL, MODULE_NAME); | ||
221 | if (err) | 195 | if (err) |
222 | goto err_out_stop; | 196 | goto err_out_stop; |
223 | 197 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 16a73eab6726..2782709b263f 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -1669,7 +1669,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, | |||
1669 | 1669 | ||
1670 | f->fmt.sliced.service_set = 0; | 1670 | f->fmt.sliced.service_set = 0; |
1671 | 1671 | ||
1672 | call_all(dev, video, g_fmt, f); | 1672 | call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); |
1673 | 1673 | ||
1674 | if (f->fmt.sliced.service_set == 0) | 1674 | if (f->fmt.sliced.service_set == 0) |
1675 | rc = -EINVAL; | 1675 | rc = -EINVAL; |
@@ -1690,7 +1690,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, | |||
1690 | return rc; | 1690 | return rc; |
1691 | 1691 | ||
1692 | mutex_lock(&dev->lock); | 1692 | mutex_lock(&dev->lock); |
1693 | call_all(dev, video, g_fmt, f); | 1693 | call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); |
1694 | mutex_unlock(&dev->lock); | 1694 | mutex_unlock(&dev->lock); |
1695 | 1695 | ||
1696 | if (f->fmt.sliced.service_set == 0) | 1696 | if (f->fmt.sliced.service_set == 0) |
@@ -1902,9 +1902,12 @@ static int radio_queryctrl(struct file *file, void *priv, | |||
1902 | if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) | 1902 | if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) |
1903 | return -EINVAL; | 1903 | return -EINVAL; |
1904 | if (c->id == V4L2_CID_AUDIO_MUTE) { | 1904 | if (c->id == V4L2_CID_AUDIO_MUTE) { |
1905 | for (i = 0; i < CX231XX_CTLS; i++) | 1905 | for (i = 0; i < CX231XX_CTLS; i++) { |
1906 | if (cx231xx_ctls[i].v.id == c->id) | 1906 | if (cx231xx_ctls[i].v.id == c->id) |
1907 | break; | 1907 | break; |
1908 | } | ||
1909 | if (i == CX231XX_CTLS) | ||
1910 | return -EINVAL; | ||
1908 | *c = cx231xx_ctls[i].v; | 1911 | *c = cx231xx_ctls[i].v; |
1909 | } else | 1912 | } else |
1910 | *c = no_ctl; | 1913 | *c = no_ctl; |
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 17d4d1a800ce..38d417191a65 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include <media/videobuf-vmalloc.h> | 33 | #include <media/videobuf-vmalloc.h> |
34 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
35 | #include <media/ir-kbd-i2c.h> | 35 | #include <media/ir-core.h> |
36 | #if defined(CONFIG_VIDEO_CX231XX_DVB) || \ | 36 | #if defined(CONFIG_VIDEO_CX231XX_DVB) || \ |
37 | defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) | 37 | defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) |
38 | #include <media/videobuf-dvb.h> | 38 | #include <media/videobuf-dvb.h> |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 4c8e95853fa3..022b480918cd 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -1000,20 +1000,6 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, | |||
1000 | h, w); | 1000 | h, w); |
1001 | if (err) return err; | 1001 | if (err) return err; |
1002 | } | 1002 | } |
1003 | |||
1004 | if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) { | ||
1005 | /* Adjust temporal filter if necessary. The problem with the | ||
1006 | temporal filter is that it works well with full resolution | ||
1007 | capturing, but not when the capture window is scaled (the | ||
1008 | filter introduces a ghosting effect). So if the capture | ||
1009 | window is scaled, then force the filter to 0. | ||
1010 | |||
1011 | For full resolution the filter really improves the video | ||
1012 | quality, especially if the original video quality is | ||
1013 | suboptimal. */ | ||
1014 | temporal = 0; | ||
1015 | } | ||
1016 | |||
1017 | if (force || NEQ(stream_type)) { | 1003 | if (force || NEQ(stream_type)) { |
1018 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, | 1004 | err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, |
1019 | mpeg_stream_type[new->stream_type]); | 1005 | mpeg_stream_type[new->stream_type]); |
diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index d4a9d2c5947c..c95e7bc14745 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c | |||
@@ -60,12 +60,18 @@ static unsigned int ci_dbg; | |||
60 | module_param(ci_dbg, int, 0644); | 60 | module_param(ci_dbg, int, 0644); |
61 | MODULE_PARM_DESC(ci_dbg, "Enable CI debugging"); | 61 | MODULE_PARM_DESC(ci_dbg, "Enable CI debugging"); |
62 | 62 | ||
63 | static unsigned int ci_irq_enable; | ||
64 | module_param(ci_irq_enable, int, 0644); | ||
65 | MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM"); | ||
66 | |||
63 | #define ci_dbg_print(args...) \ | 67 | #define ci_dbg_print(args...) \ |
64 | do { \ | 68 | do { \ |
65 | if (ci_dbg) \ | 69 | if (ci_dbg) \ |
66 | printk(KERN_DEBUG args); \ | 70 | printk(KERN_DEBUG args); \ |
67 | } while (0) | 71 | } while (0) |
68 | 72 | ||
73 | #define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0) | ||
74 | |||
69 | /* stores all private variables for communication with CI */ | 75 | /* stores all private variables for communication with CI */ |
70 | struct netup_ci_state { | 76 | struct netup_ci_state { |
71 | struct dvb_ca_en50221 ca; | 77 | struct dvb_ca_en50221 ca; |
@@ -392,7 +398,7 @@ int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open | |||
392 | if (0 != slot) | 398 | if (0 != slot) |
393 | return -EINVAL; | 399 | return -EINVAL; |
394 | 400 | ||
395 | netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | NETUP_IRQ_IRQAM) | 401 | netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags()) |
396 | : NETUP_IRQ_DETAM); | 402 | : NETUP_IRQ_DETAM); |
397 | 403 | ||
398 | return state->status; | 404 | return state->status; |
@@ -429,7 +435,7 @@ int netup_ci_init(struct cx23885_tsport *port) | |||
429 | 0x01, /* power on (use it like store place) */ | 435 | 0x01, /* power on (use it like store place) */ |
430 | 0x00, /* RFU */ | 436 | 0x00, /* RFU */ |
431 | 0x00, /* int status read only */ | 437 | 0x00, /* int status read only */ |
432 | NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */ | 438 | ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */ |
433 | 0x05, /* EXTINT=active-high, INT=push-pull */ | 439 | 0x05, /* EXTINT=active-high, INT=push-pull */ |
434 | 0x00, /* USCG1 */ | 440 | 0x00, /* USCG1 */ |
435 | 0x04, /* ack active low */ | 441 | 0x04, /* ack active low */ |
@@ -470,7 +476,7 @@ int netup_ci_init(struct cx23885_tsport *port) | |||
470 | state->ca.poll_slot_status = netup_poll_ci_slot_status; | 476 | state->ca.poll_slot_status = netup_poll_ci_slot_status; |
471 | state->ca.data = state; | 477 | state->ca.data = state; |
472 | state->priv = port; | 478 | state->priv = port; |
473 | state->current_irq_mode = NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM; | 479 | state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM; |
474 | 480 | ||
475 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, | 481 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, |
476 | 0, &cimax_init[0], 34); | 482 | 0, &cimax_init[0], 34); |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index a8ddc227cf86..abd64e89f60f 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -1356,7 +1356,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
1356 | struct cx23885_dev *dev = fh->dev; | 1356 | struct cx23885_dev *dev = fh->dev; |
1357 | struct cx23885_tsport *tsport = &dev->ts1; | 1357 | struct cx23885_tsport *tsport = &dev->ts1; |
1358 | 1358 | ||
1359 | strcpy(cap->driver, dev->name); | 1359 | strlcpy(cap->driver, dev->name, sizeof(cap->driver)); |
1360 | strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, | 1360 | strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, |
1361 | sizeof(cap->card)); | 1361 | sizeof(cap->card)); |
1362 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); | 1362 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 939079d7bbb9..9e1460828b2f 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -1006,6 +1006,22 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1006 | netup_ci_init(port); | 1006 | netup_ci_init(port); |
1007 | break; | 1007 | break; |
1008 | } | 1008 | } |
1009 | case CX23885_BOARD_TEVII_S470: { | ||
1010 | u8 eeprom[256]; /* 24C02 i2c eeprom */ | ||
1011 | |||
1012 | if (port->nr != 1) | ||
1013 | break; | ||
1014 | |||
1015 | /* Read entire EEPROM */ | ||
1016 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | ||
1017 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); | ||
1018 | printk(KERN_INFO "TeVii S470 MAC= " | ||
1019 | "%02X:%02X:%02X:%02X:%02X:%02X\n", | ||
1020 | eeprom[0xa0], eeprom[0xa1], eeprom[0xa2], | ||
1021 | eeprom[0xa3], eeprom[0xa4], eeprom[0xa5]); | ||
1022 | memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); | ||
1023 | break; | ||
1024 | } | ||
1009 | } | 1025 | } |
1010 | 1026 | ||
1011 | return ret; | 1027 | return ret; |
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 8e9d990dbe93..8d306d8bb61c 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -51,6 +51,8 @@ | |||
51 | 51 | ||
52 | #define RC5_EXTENDED_COMMAND_OFFSET 64 | 52 | #define RC5_EXTENDED_COMMAND_OFFSET 64 |
53 | 53 | ||
54 | #define MODULE_NAME "cx23885" | ||
55 | |||
54 | static inline unsigned int rc5_command(u32 rc5_baseband) | 56 | static inline unsigned int rc5_command(u32 rc5_baseband) |
55 | { | 57 | { |
56 | return RC5_INSTR(rc5_baseband) + | 58 | return RC5_INSTR(rc5_baseband) + |
@@ -338,7 +340,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
338 | { | 340 | { |
339 | struct card_ir *ir; | 341 | struct card_ir *ir; |
340 | struct input_dev *input_dev; | 342 | struct input_dev *input_dev; |
341 | struct ir_scancode_table *ir_codes = NULL; | 343 | char *ir_codes = NULL; |
342 | int ir_type, ir_addr, ir_start; | 344 | int ir_type, ir_addr, ir_start; |
343 | int ret; | 345 | int ret; |
344 | 346 | ||
@@ -353,7 +355,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
353 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 355 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
354 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 356 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
355 | /* Parameters for the grey Hauppauge remote for the HVR-1850 */ | 357 | /* Parameters for the grey Hauppauge remote for the HVR-1850 */ |
356 | ir_codes = &ir_codes_hauppauge_new_table; | 358 | ir_codes = RC_MAP_HAUPPAUGE_NEW; |
357 | ir_type = IR_TYPE_RC5; | 359 | ir_type = IR_TYPE_RC5; |
358 | ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ | 360 | ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ |
359 | ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ | 361 | ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ |
@@ -398,7 +400,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
398 | dev->ir_input = ir; | 400 | dev->ir_input = ir; |
399 | cx23885_input_ir_start(dev); | 401 | cx23885_input_ir_start(dev); |
400 | 402 | ||
401 | ret = ir_input_register(ir->dev, ir_codes, NULL); | 403 | ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); |
402 | if (ret) | 404 | if (ret) |
403 | goto err_out_stop; | 405 | goto err_out_stop; |
404 | 406 | ||
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 2d3ac8b83dc3..543b854f6a62 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -514,8 +514,8 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
514 | *size = fh->fmt->depth*fh->width*fh->height >> 3; | 514 | *size = fh->fmt->depth*fh->width*fh->height >> 3; |
515 | if (0 == *count) | 515 | if (0 == *count) |
516 | *count = 32; | 516 | *count = 32; |
517 | while (*size * *count > vid_limit * 1024 * 1024) | 517 | if (*size * *count > vid_limit * 1024 * 1024) |
518 | (*count)--; | 518 | *count = (vid_limit * 1024 * 1024) / *size; |
519 | return 0; | 519 | return 0; |
520 | } | 520 | } |
521 | 521 | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index f2461cd3de5a..8b6fb3544376 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -1018,7 +1018,7 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
1018 | { | 1018 | { |
1019 | switch (fmt->type) { | 1019 | switch (fmt->type) { |
1020 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | 1020 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: |
1021 | return cx25840_vbi_g_fmt(sd, fmt); | 1021 | return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced); |
1022 | default: | 1022 | default: |
1023 | return -EINVAL; | 1023 | return -EINVAL; |
1024 | } | 1024 | } |
@@ -1079,12 +1079,6 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
1079 | cx25840_write(client, 0x41e, 0x8 | filter); | 1079 | cx25840_write(client, 0x41e, 0x8 | filter); |
1080 | break; | 1080 | break; |
1081 | 1081 | ||
1082 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
1083 | return cx25840_vbi_s_fmt(sd, fmt); | ||
1084 | |||
1085 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
1086 | return cx25840_vbi_s_fmt(sd, fmt); | ||
1087 | |||
1088 | default: | 1082 | default: |
1089 | return -EINVAL; | 1083 | return -EINVAL; |
1090 | } | 1084 | } |
@@ -1635,15 +1629,22 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { | |||
1635 | .s_routing = cx25840_s_video_routing, | 1629 | .s_routing = cx25840_s_video_routing, |
1636 | .g_fmt = cx25840_g_fmt, | 1630 | .g_fmt = cx25840_g_fmt, |
1637 | .s_fmt = cx25840_s_fmt, | 1631 | .s_fmt = cx25840_s_fmt, |
1638 | .decode_vbi_line = cx25840_decode_vbi_line, | ||
1639 | .s_stream = cx25840_s_stream, | 1632 | .s_stream = cx25840_s_stream, |
1640 | }; | 1633 | }; |
1641 | 1634 | ||
1635 | static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { | ||
1636 | .decode_vbi_line = cx25840_decode_vbi_line, | ||
1637 | .s_raw_fmt = cx25840_s_raw_fmt, | ||
1638 | .s_sliced_fmt = cx25840_s_sliced_fmt, | ||
1639 | .g_sliced_fmt = cx25840_g_sliced_fmt, | ||
1640 | }; | ||
1641 | |||
1642 | static const struct v4l2_subdev_ops cx25840_ops = { | 1642 | static const struct v4l2_subdev_ops cx25840_ops = { |
1643 | .core = &cx25840_core_ops, | 1643 | .core = &cx25840_core_ops, |
1644 | .tuner = &cx25840_tuner_ops, | 1644 | .tuner = &cx25840_tuner_ops, |
1645 | .audio = &cx25840_audio_ops, | 1645 | .audio = &cx25840_audio_ops, |
1646 | .video = &cx25840_video_ops, | 1646 | .video = &cx25840_video_ops, |
1647 | .vbi = &cx25840_vbi_ops, | ||
1647 | }; | 1648 | }; |
1648 | 1649 | ||
1649 | /* ----------------------------------------------------------------------- */ | 1650 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 55345444417f..04393b971567 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -99,8 +99,9 @@ int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); | |||
99 | 99 | ||
100 | /* ----------------------------------------------------------------------- */ | 100 | /* ----------------------------------------------------------------------- */ |
101 | /* cx25850-vbi.c */ | 101 | /* cx25850-vbi.c */ |
102 | int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); | 102 | int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); |
103 | int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); | 103 | int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); |
104 | int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); | ||
104 | int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); | 105 | int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); |
105 | 106 | ||
106 | #endif | 107 | #endif |
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 35f6592f6c47..64a4004f8a97 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -82,11 +82,10 @@ static int decode_vps(u8 * dst, u8 * p) | |||
82 | return err & 0xf0; | 82 | return err & 0xf0; |
83 | } | 83 | } |
84 | 84 | ||
85 | int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 85 | int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) |
86 | { | 86 | { |
87 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 87 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
88 | struct cx25840_state *state = to_state(sd); | 88 | struct cx25840_state *state = to_state(sd); |
89 | struct v4l2_sliced_vbi_format *svbi; | ||
90 | static const u16 lcr2vbi[] = { | 89 | static const u16 lcr2vbi[] = { |
91 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | 90 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ |
92 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | 91 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ |
@@ -97,9 +96,6 @@ int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
97 | int is_pal = !(state->std & V4L2_STD_525_60); | 96 | int is_pal = !(state->std & V4L2_STD_525_60); |
98 | int i; | 97 | int i; |
99 | 98 | ||
100 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
101 | return -EINVAL; | ||
102 | svbi = &fmt->fmt.sliced; | ||
103 | memset(svbi, 0, sizeof(*svbi)); | 99 | memset(svbi, 0, sizeof(*svbi)); |
104 | /* we're done if raw VBI is active */ | 100 | /* we're done if raw VBI is active */ |
105 | if ((cx25840_read(client, 0x404) & 0x10) == 0) | 101 | if ((cx25840_read(client, 0x404) & 0x10) == 0) |
@@ -127,32 +123,30 @@ int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
127 | return 0; | 123 | return 0; |
128 | } | 124 | } |
129 | 125 | ||
130 | int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 126 | int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) |
131 | { | 127 | { |
132 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 128 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
133 | struct cx25840_state *state = to_state(sd); | 129 | struct cx25840_state *state = to_state(sd); |
134 | struct v4l2_sliced_vbi_format *svbi; | ||
135 | int is_pal = !(state->std & V4L2_STD_525_60); | 130 | int is_pal = !(state->std & V4L2_STD_525_60); |
136 | int vbi_offset = is_pal ? 1 : 0; | 131 | int vbi_offset = is_pal ? 1 : 0; |
137 | int i, x; | ||
138 | u8 lcr[24]; | ||
139 | 132 | ||
140 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && | 133 | /* Setup standard */ |
141 | fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) | 134 | cx25840_std_setup(client); |
142 | return -EINVAL; | ||
143 | svbi = &fmt->fmt.sliced; | ||
144 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
145 | /* raw VBI */ | ||
146 | memset(svbi, 0, sizeof(*svbi)); | ||
147 | 135 | ||
148 | /* Setup standard */ | 136 | /* VBI Offset */ |
149 | cx25840_std_setup(client); | 137 | cx25840_write(client, 0x47f, vbi_offset); |
138 | cx25840_write(client, 0x404, 0x2e); | ||
139 | return 0; | ||
140 | } | ||
150 | 141 | ||
151 | /* VBI Offset */ | 142 | int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) |
152 | cx25840_write(client, 0x47f, vbi_offset); | 143 | { |
153 | cx25840_write(client, 0x404, 0x2e); | 144 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
154 | return 0; | 145 | struct cx25840_state *state = to_state(sd); |
155 | } | 146 | int is_pal = !(state->std & V4L2_STD_525_60); |
147 | int vbi_offset = is_pal ? 1 : 0; | ||
148 | int i, x; | ||
149 | u8 lcr[24]; | ||
156 | 150 | ||
157 | for (x = 0; x <= 23; x++) | 151 | for (x = 0; x <= 23; x++) |
158 | lcr[x] = 0x00; | 152 | lcr[x] = 0x00; |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index b35411160f04..8b21457111b1 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -847,7 +847,8 @@ static int set_tvaudio(struct cx88_core *core) | |||
847 | { | 847 | { |
848 | v4l2_std_id norm = core->tvnorm; | 848 | v4l2_std_id norm = core->tvnorm; |
849 | 849 | ||
850 | if (CX88_VMUX_TELEVISION != INPUT(core->input).type) | 850 | if (CX88_VMUX_TELEVISION != INPUT(core->input).type && |
851 | CX88_VMUX_CABLE != INPUT(core->input).type) | ||
851 | return 0; | 852 | return 0; |
852 | 853 | ||
853 | if (V4L2_STD_PAL_BG & norm) { | 854 | if (V4L2_STD_PAL_BG & norm) { |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 94ab862f0219..faa8e8163a4a 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -1231,7 +1231,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1231 | fe->ops.tuner_ops.set_config(fe, &ctl); | 1231 | fe->ops.tuner_ops.set_config(fe, &ctl); |
1232 | } | 1232 | } |
1233 | break; | 1233 | break; |
1234 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | 1234 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: |
1235 | case CX88_BOARD_WINFAST_DTV1800H: | 1235 | case CX88_BOARD_WINFAST_DTV1800H: |
1236 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | 1236 | fe0->dvb.frontend = dvb_attach(zl10353_attach, |
1237 | &cx88_pinnacle_hybrid_pctv, | 1237 | &cx88_pinnacle_hybrid_pctv, |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6b6abf062c21..e185289e446c 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -32,12 +32,18 @@ | |||
32 | #include "cx88.h" | 32 | #include "cx88.h" |
33 | #include <media/ir-common.h> | 33 | #include <media/ir-common.h> |
34 | 34 | ||
35 | #define MODULE_NAME "cx88xx" | ||
36 | |||
35 | /* ---------------------------------------------------------------------- */ | 37 | /* ---------------------------------------------------------------------- */ |
36 | 38 | ||
37 | struct cx88_IR { | 39 | struct cx88_IR { |
38 | struct cx88_core *core; | 40 | struct cx88_core *core; |
39 | struct input_dev *input; | 41 | struct input_dev *input; |
40 | struct ir_input_state ir; | 42 | struct ir_input_state ir; |
43 | struct ir_dev_props props; | ||
44 | |||
45 | int users; | ||
46 | |||
41 | char name[32]; | 47 | char name[32]; |
42 | char phys[32]; | 48 | char phys[32]; |
43 | 49 | ||
@@ -159,8 +165,16 @@ static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) | |||
159 | return HRTIMER_RESTART; | 165 | return HRTIMER_RESTART; |
160 | } | 166 | } |
161 | 167 | ||
162 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | 168 | static int __cx88_ir_start(void *priv) |
163 | { | 169 | { |
170 | struct cx88_core *core = priv; | ||
171 | struct cx88_IR *ir; | ||
172 | |||
173 | if (!core || !core->ir) | ||
174 | return -EINVAL; | ||
175 | |||
176 | ir = core->ir; | ||
177 | |||
164 | if (ir->polling) { | 178 | if (ir->polling) { |
165 | hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 179 | hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
166 | ir->timer.function = cx88_ir_work; | 180 | ir->timer.function = cx88_ir_work; |
@@ -173,10 +187,18 @@ void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) | |||
173 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ | 187 | cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ |
174 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ | 188 | cx_write(MO_DDSCFG_IO, 0x5); /* enable */ |
175 | } | 189 | } |
190 | return 0; | ||
176 | } | 191 | } |
177 | 192 | ||
178 | void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | 193 | static void __cx88_ir_stop(void *priv) |
179 | { | 194 | { |
195 | struct cx88_core *core = priv; | ||
196 | struct cx88_IR *ir; | ||
197 | |||
198 | if (!core || !core->ir) | ||
199 | return; | ||
200 | |||
201 | ir = core->ir; | ||
180 | if (ir->sampling) { | 202 | if (ir->sampling) { |
181 | cx_write(MO_DDSCFG_IO, 0x0); | 203 | cx_write(MO_DDSCFG_IO, 0x0); |
182 | core->pci_irqmask &= ~PCI_INT_IR_SMPINT; | 204 | core->pci_irqmask &= ~PCI_INT_IR_SMPINT; |
@@ -186,15 +208,49 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) | |||
186 | hrtimer_cancel(&ir->timer); | 208 | hrtimer_cancel(&ir->timer); |
187 | } | 209 | } |
188 | 210 | ||
211 | int cx88_ir_start(struct cx88_core *core) | ||
212 | { | ||
213 | if (core->ir->users) | ||
214 | return __cx88_ir_start(core); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | void cx88_ir_stop(struct cx88_core *core) | ||
220 | { | ||
221 | if (core->ir->users) | ||
222 | __cx88_ir_stop(core); | ||
223 | } | ||
224 | |||
225 | static int cx88_ir_open(void *priv) | ||
226 | { | ||
227 | struct cx88_core *core = priv; | ||
228 | |||
229 | core->ir->users++; | ||
230 | return __cx88_ir_start(core); | ||
231 | } | ||
232 | |||
233 | static void cx88_ir_close(void *priv) | ||
234 | { | ||
235 | struct cx88_core *core = priv; | ||
236 | |||
237 | core->ir->users--; | ||
238 | if (!core->ir->users) | ||
239 | __cx88_ir_stop(core); | ||
240 | } | ||
241 | |||
189 | /* ---------------------------------------------------------------------- */ | 242 | /* ---------------------------------------------------------------------- */ |
190 | 243 | ||
191 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | 244 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) |
192 | { | 245 | { |
193 | struct cx88_IR *ir; | 246 | struct cx88_IR *ir; |
194 | struct input_dev *input_dev; | 247 | struct input_dev *input_dev; |
195 | struct ir_scancode_table *ir_codes = NULL; | 248 | char *ir_codes = NULL; |
196 | u64 ir_type = IR_TYPE_OTHER; | 249 | u64 ir_type = IR_TYPE_OTHER; |
197 | int err = -ENOMEM; | 250 | int err = -ENOMEM; |
251 | u32 hardware_mask = 0; /* For devices with a hardware mask, when | ||
252 | * used with a full-code IR table | ||
253 | */ | ||
198 | 254 | ||
199 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 255 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
200 | input_dev = input_allocate_device(); | 256 | input_dev = input_allocate_device(); |
@@ -208,15 +264,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
208 | case CX88_BOARD_DNTV_LIVE_DVB_T: | 264 | case CX88_BOARD_DNTV_LIVE_DVB_T: |
209 | case CX88_BOARD_KWORLD_DVB_T: | 265 | case CX88_BOARD_KWORLD_DVB_T: |
210 | case CX88_BOARD_KWORLD_DVB_T_CX22702: | 266 | case CX88_BOARD_KWORLD_DVB_T_CX22702: |
211 | ir_codes = &ir_codes_dntv_live_dvb_t_table; | 267 | ir_codes = RC_MAP_DNTV_LIVE_DVB_T; |
212 | ir->gpio_addr = MO_GP1_IO; | 268 | ir->gpio_addr = MO_GP1_IO; |
213 | ir->mask_keycode = 0x1f; | 269 | ir->mask_keycode = 0x1f; |
214 | ir->mask_keyup = 0x60; | 270 | ir->mask_keyup = 0x60; |
215 | ir->polling = 50; /* ms */ | 271 | ir->polling = 50; /* ms */ |
216 | break; | 272 | break; |
217 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 273 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
218 | ir_codes = &ir_codes_cinergy_1400_table; | 274 | ir_codes = RC_MAP_CINERGY_1400; |
219 | ir_type = IR_TYPE_PD; | 275 | ir_type = IR_TYPE_NEC; |
220 | ir->sampling = 0xeb04; /* address */ | 276 | ir->sampling = 0xeb04; /* address */ |
221 | break; | 277 | break; |
222 | case CX88_BOARD_HAUPPAUGE: | 278 | case CX88_BOARD_HAUPPAUGE: |
@@ -230,14 +286,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
230 | case CX88_BOARD_PCHDTV_HD3000: | 286 | case CX88_BOARD_PCHDTV_HD3000: |
231 | case CX88_BOARD_PCHDTV_HD5500: | 287 | case CX88_BOARD_PCHDTV_HD5500: |
232 | case CX88_BOARD_HAUPPAUGE_IRONLY: | 288 | case CX88_BOARD_HAUPPAUGE_IRONLY: |
233 | ir_codes = &ir_codes_hauppauge_new_table; | 289 | ir_codes = RC_MAP_HAUPPAUGE_NEW; |
234 | ir_type = IR_TYPE_RC5; | 290 | ir_type = IR_TYPE_RC5; |
235 | ir->sampling = 1; | 291 | ir->sampling = 1; |
236 | break; | 292 | break; |
237 | case CX88_BOARD_WINFAST_DTV2000H: | 293 | case CX88_BOARD_WINFAST_DTV2000H: |
238 | case CX88_BOARD_WINFAST_DTV2000H_J: | 294 | case CX88_BOARD_WINFAST_DTV2000H_J: |
239 | case CX88_BOARD_WINFAST_DTV1800H: | 295 | case CX88_BOARD_WINFAST_DTV1800H: |
240 | ir_codes = &ir_codes_winfast_table; | 296 | ir_codes = RC_MAP_WINFAST; |
241 | ir->gpio_addr = MO_GP0_IO; | 297 | ir->gpio_addr = MO_GP0_IO; |
242 | ir->mask_keycode = 0x8f8; | 298 | ir->mask_keycode = 0x8f8; |
243 | ir->mask_keyup = 0x100; | 299 | ir->mask_keyup = 0x100; |
@@ -246,14 +302,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
246 | case CX88_BOARD_WINFAST2000XP_EXPERT: | 302 | case CX88_BOARD_WINFAST2000XP_EXPERT: |
247 | case CX88_BOARD_WINFAST_DTV1000: | 303 | case CX88_BOARD_WINFAST_DTV1000: |
248 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | 304 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: |
249 | ir_codes = &ir_codes_winfast_table; | 305 | ir_codes = RC_MAP_WINFAST; |
250 | ir->gpio_addr = MO_GP0_IO; | 306 | ir->gpio_addr = MO_GP0_IO; |
251 | ir->mask_keycode = 0x8f8; | 307 | ir->mask_keycode = 0x8f8; |
252 | ir->mask_keyup = 0x100; | 308 | ir->mask_keyup = 0x100; |
253 | ir->polling = 1; /* ms */ | 309 | ir->polling = 1; /* ms */ |
254 | break; | 310 | break; |
255 | case CX88_BOARD_IODATA_GVBCTV7E: | 311 | case CX88_BOARD_IODATA_GVBCTV7E: |
256 | ir_codes = &ir_codes_iodata_bctv7e_table; | 312 | ir_codes = RC_MAP_IODATA_BCTV7E; |
257 | ir->gpio_addr = MO_GP0_IO; | 313 | ir->gpio_addr = MO_GP0_IO; |
258 | ir->mask_keycode = 0xfd; | 314 | ir->mask_keycode = 0xfd; |
259 | ir->mask_keydown = 0x02; | 315 | ir->mask_keydown = 0x02; |
@@ -261,36 +317,43 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
261 | break; | 317 | break; |
262 | case CX88_BOARD_PROLINK_PLAYTVPVR: | 318 | case CX88_BOARD_PROLINK_PLAYTVPVR: |
263 | case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: | 319 | case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: |
264 | ir_codes = &ir_codes_pixelview_table; | 320 | /* |
321 | * It seems that this hardware is paired with NEC extended | ||
322 | * address 0x866b. So, unfortunately, its usage with other | ||
323 | * IR's with different address won't work. Still, there are | ||
324 | * other IR's from the same manufacturer that works, like the | ||
325 | * 002-T mini RC, provided with newer PV hardware | ||
326 | */ | ||
327 | ir_codes = RC_MAP_PIXELVIEW_MK12; | ||
265 | ir->gpio_addr = MO_GP1_IO; | 328 | ir->gpio_addr = MO_GP1_IO; |
266 | ir->mask_keycode = 0x1f; | ||
267 | ir->mask_keyup = 0x80; | 329 | ir->mask_keyup = 0x80; |
268 | ir->polling = 1; /* ms */ | 330 | ir->polling = 10; /* ms */ |
331 | hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */ | ||
269 | break; | 332 | break; |
270 | case CX88_BOARD_PROLINK_PV_8000GT: | 333 | case CX88_BOARD_PROLINK_PV_8000GT: |
271 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | 334 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: |
272 | ir_codes = &ir_codes_pixelview_new_table; | 335 | ir_codes = RC_MAP_PIXELVIEW_NEW; |
273 | ir->gpio_addr = MO_GP1_IO; | 336 | ir->gpio_addr = MO_GP1_IO; |
274 | ir->mask_keycode = 0x3f; | 337 | ir->mask_keycode = 0x3f; |
275 | ir->mask_keyup = 0x80; | 338 | ir->mask_keyup = 0x80; |
276 | ir->polling = 1; /* ms */ | 339 | ir->polling = 1; /* ms */ |
277 | break; | 340 | break; |
278 | case CX88_BOARD_KWORLD_LTV883: | 341 | case CX88_BOARD_KWORLD_LTV883: |
279 | ir_codes = &ir_codes_pixelview_table; | 342 | ir_codes = RC_MAP_PIXELVIEW; |
280 | ir->gpio_addr = MO_GP1_IO; | 343 | ir->gpio_addr = MO_GP1_IO; |
281 | ir->mask_keycode = 0x1f; | 344 | ir->mask_keycode = 0x1f; |
282 | ir->mask_keyup = 0x60; | 345 | ir->mask_keyup = 0x60; |
283 | ir->polling = 1; /* ms */ | 346 | ir->polling = 1; /* ms */ |
284 | break; | 347 | break; |
285 | case CX88_BOARD_ADSTECH_DVB_T_PCI: | 348 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
286 | ir_codes = &ir_codes_adstech_dvb_t_pci_table; | 349 | ir_codes = RC_MAP_ADSTECH_DVB_T_PCI; |
287 | ir->gpio_addr = MO_GP1_IO; | 350 | ir->gpio_addr = MO_GP1_IO; |
288 | ir->mask_keycode = 0xbf; | 351 | ir->mask_keycode = 0xbf; |
289 | ir->mask_keyup = 0x40; | 352 | ir->mask_keyup = 0x40; |
290 | ir->polling = 50; /* ms */ | 353 | ir->polling = 50; /* ms */ |
291 | break; | 354 | break; |
292 | case CX88_BOARD_MSI_TVANYWHERE_MASTER: | 355 | case CX88_BOARD_MSI_TVANYWHERE_MASTER: |
293 | ir_codes = &ir_codes_msi_tvanywhere_table; | 356 | ir_codes = RC_MAP_MSI_TVANYWHERE; |
294 | ir->gpio_addr = MO_GP1_IO; | 357 | ir->gpio_addr = MO_GP1_IO; |
295 | ir->mask_keycode = 0x1f; | 358 | ir->mask_keycode = 0x1f; |
296 | ir->mask_keyup = 0x40; | 359 | ir->mask_keyup = 0x40; |
@@ -298,7 +361,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
298 | break; | 361 | break; |
299 | case CX88_BOARD_AVERTV_303: | 362 | case CX88_BOARD_AVERTV_303: |
300 | case CX88_BOARD_AVERTV_STUDIO_303: | 363 | case CX88_BOARD_AVERTV_STUDIO_303: |
301 | ir_codes = &ir_codes_avertv_303_table; | 364 | ir_codes = RC_MAP_AVERTV_303; |
302 | ir->gpio_addr = MO_GP2_IO; | 365 | ir->gpio_addr = MO_GP2_IO; |
303 | ir->mask_keycode = 0xfb; | 366 | ir->mask_keycode = 0xfb; |
304 | ir->mask_keydown = 0x02; | 367 | ir->mask_keydown = 0x02; |
@@ -311,41 +374,41 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
311 | case CX88_BOARD_PROF_7300: | 374 | case CX88_BOARD_PROF_7300: |
312 | case CX88_BOARD_PROF_7301: | 375 | case CX88_BOARD_PROF_7301: |
313 | case CX88_BOARD_PROF_6200: | 376 | case CX88_BOARD_PROF_6200: |
314 | ir_codes = &ir_codes_tbs_nec_table; | 377 | ir_codes = RC_MAP_TBS_NEC; |
315 | ir_type = IR_TYPE_PD; | 378 | ir_type = IR_TYPE_NEC; |
316 | ir->sampling = 0xff00; /* address */ | 379 | ir->sampling = 0xff00; /* address */ |
317 | break; | 380 | break; |
318 | case CX88_BOARD_TEVII_S460: | 381 | case CX88_BOARD_TEVII_S460: |
319 | case CX88_BOARD_TEVII_S420: | 382 | case CX88_BOARD_TEVII_S420: |
320 | ir_codes = &ir_codes_tevii_nec_table; | 383 | ir_codes = RC_MAP_TEVII_NEC; |
321 | ir_type = IR_TYPE_PD; | 384 | ir_type = IR_TYPE_NEC; |
322 | ir->sampling = 0xff00; /* address */ | 385 | ir->sampling = 0xff00; /* address */ |
323 | break; | 386 | break; |
324 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 387 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
325 | ir_codes = &ir_codes_dntv_live_dvbt_pro_table; | 388 | ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; |
326 | ir_type = IR_TYPE_PD; | 389 | ir_type = IR_TYPE_NEC; |
327 | ir->sampling = 0xff00; /* address */ | 390 | ir->sampling = 0xff00; /* address */ |
328 | break; | 391 | break; |
329 | case CX88_BOARD_NORWOOD_MICRO: | 392 | case CX88_BOARD_NORWOOD_MICRO: |
330 | ir_codes = &ir_codes_norwood_table; | 393 | ir_codes = RC_MAP_NORWOOD; |
331 | ir->gpio_addr = MO_GP1_IO; | 394 | ir->gpio_addr = MO_GP1_IO; |
332 | ir->mask_keycode = 0x0e; | 395 | ir->mask_keycode = 0x0e; |
333 | ir->mask_keyup = 0x80; | 396 | ir->mask_keyup = 0x80; |
334 | ir->polling = 50; /* ms */ | 397 | ir->polling = 50; /* ms */ |
335 | break; | 398 | break; |
336 | case CX88_BOARD_NPGTECH_REALTV_TOP10FM: | 399 | case CX88_BOARD_NPGTECH_REALTV_TOP10FM: |
337 | ir_codes = &ir_codes_npgtech_table; | 400 | ir_codes = RC_MAP_NPGTECH; |
338 | ir->gpio_addr = MO_GP0_IO; | 401 | ir->gpio_addr = MO_GP0_IO; |
339 | ir->mask_keycode = 0xfa; | 402 | ir->mask_keycode = 0xfa; |
340 | ir->polling = 50; /* ms */ | 403 | ir->polling = 50; /* ms */ |
341 | break; | 404 | break; |
342 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 405 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
343 | ir_codes = &ir_codes_pinnacle_pctv_hd_table; | 406 | ir_codes = RC_MAP_PINNACLE_PCTV_HD; |
344 | ir_type = IR_TYPE_RC5; | 407 | ir_type = IR_TYPE_RC5; |
345 | ir->sampling = 1; | 408 | ir->sampling = 1; |
346 | break; | 409 | break; |
347 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | 410 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: |
348 | ir_codes = &ir_codes_powercolor_real_angel_table; | 411 | ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL; |
349 | ir->gpio_addr = MO_GP2_IO; | 412 | ir->gpio_addr = MO_GP2_IO; |
350 | ir->mask_keycode = 0x7e; | 413 | ir->mask_keycode = 0x7e; |
351 | ir->polling = 100; /* ms */ | 414 | ir->polling = 100; /* ms */ |
@@ -357,6 +420,21 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
357 | goto err_out_free; | 420 | goto err_out_free; |
358 | } | 421 | } |
359 | 422 | ||
423 | /* | ||
424 | * The usage of mask_keycode were very convenient, due to several | ||
425 | * reasons. Among others, the scancode tables were using the scancode | ||
426 | * as the index elements. So, the less bits it was used, the smaller | ||
427 | * the table were stored. After the input changes, the better is to use | ||
428 | * the full scancodes, since it allows replacing the IR remote by | ||
429 | * another one. Unfortunately, there are still some hardware, like | ||
430 | * Pixelview Ultra Pro, where only part of the scancode is sent via | ||
431 | * GPIO. So, there's no way to get the full scancode. Due to that, | ||
432 | * hardware_mask were introduced here: it represents those hardware | ||
433 | * that has such limits. | ||
434 | */ | ||
435 | if (hardware_mask && !ir->mask_keycode) | ||
436 | ir->mask_keycode = hardware_mask; | ||
437 | |||
360 | /* init input device */ | 438 | /* init input device */ |
361 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); | 439 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); |
362 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); | 440 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); |
@@ -381,19 +459,20 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
381 | ir->core = core; | 459 | ir->core = core; |
382 | core->ir = ir; | 460 | core->ir = ir; |
383 | 461 | ||
384 | cx88_ir_start(core, ir); | 462 | ir->props.priv = core; |
463 | ir->props.open = cx88_ir_open; | ||
464 | ir->props.close = cx88_ir_close; | ||
465 | ir->props.scanmask = hardware_mask; | ||
385 | 466 | ||
386 | /* all done */ | 467 | /* all done */ |
387 | err = ir_input_register(ir->input, ir_codes, NULL); | 468 | err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); |
388 | if (err) | 469 | if (err) |
389 | goto err_out_stop; | 470 | goto err_out_free; |
390 | 471 | ||
391 | return 0; | 472 | return 0; |
392 | 473 | ||
393 | err_out_stop: | ||
394 | cx88_ir_stop(core, ir); | ||
395 | core->ir = NULL; | ||
396 | err_out_free: | 474 | err_out_free: |
475 | core->ir = NULL; | ||
397 | kfree(ir); | 476 | kfree(ir); |
398 | return err; | 477 | return err; |
399 | } | 478 | } |
@@ -406,7 +485,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
406 | if (NULL == ir) | 485 | if (NULL == ir) |
407 | return 0; | 486 | return 0; |
408 | 487 | ||
409 | cx88_ir_stop(core, ir); | 488 | cx88_ir_stop(core); |
410 | ir_input_unregister(ir->input); | 489 | ir_input_unregister(ir->input); |
411 | kfree(ir); | 490 | kfree(ir); |
412 | 491 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6aba7af9160a..499f8d512ad6 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -599,13 +599,22 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board | |||
599 | static int cx8802_request_acquire(struct cx8802_driver *drv) | 599 | static int cx8802_request_acquire(struct cx8802_driver *drv) |
600 | { | 600 | { |
601 | struct cx88_core *core = drv->core; | 601 | struct cx88_core *core = drv->core; |
602 | unsigned int i; | ||
602 | 603 | ||
603 | /* Fail a request for hardware if the device is busy. */ | 604 | /* Fail a request for hardware if the device is busy. */ |
604 | if (core->active_type_id != CX88_BOARD_NONE && | 605 | if (core->active_type_id != CX88_BOARD_NONE && |
605 | core->active_type_id != drv->type_id) | 606 | core->active_type_id != drv->type_id) |
606 | return -EBUSY; | 607 | return -EBUSY; |
607 | 608 | ||
608 | core->input = CX88_VMUX_DVB; | 609 | core->input = 0; |
610 | for (i = 0; | ||
611 | i < (sizeof(core->board.input) / sizeof(struct cx88_input)); | ||
612 | i++) { | ||
613 | if (core->board.input[i].type == CX88_VMUX_DVB) { | ||
614 | core->input = i; | ||
615 | break; | ||
616 | } | ||
617 | } | ||
609 | 618 | ||
610 | if (drv->advise_acquire) | 619 | if (drv->advise_acquire) |
611 | { | 620 | { |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 48c450f4a85a..0fab65c3ab39 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -426,12 +426,13 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
426 | if (core->board.audio_chip && | 426 | if (core->board.audio_chip && |
427 | core->board.audio_chip == V4L2_IDENT_WM8775) { | 427 | core->board.audio_chip == V4L2_IDENT_WM8775) { |
428 | call_all(core, audio, s_routing, | 428 | call_all(core, audio, s_routing, |
429 | INPUT(input).audioroute, 0, 0); | 429 | INPUT(input).audioroute, 0, 0); |
430 | } | 430 | } |
431 | /* cx2388's C-ADC is connected to the tuner only. | 431 | /* cx2388's C-ADC is connected to the tuner only. |
432 | When used with S-Video, that ADC is busy dealing with | 432 | When used with S-Video, that ADC is busy dealing with |
433 | chroma, so an external must be used for baseband audio */ | 433 | chroma, so an external must be used for baseband audio */ |
434 | if (INPUT(input).type != CX88_VMUX_TELEVISION ) { | 434 | if (INPUT(input).type != CX88_VMUX_TELEVISION && |
435 | INPUT(input).type != CX88_VMUX_CABLE) { | ||
435 | /* "I2S ADC mode" */ | 436 | /* "I2S ADC mode" */ |
436 | core->tvaudio = WW_I2SADC; | 437 | core->tvaudio = WW_I2SADC; |
437 | cx88_set_tvaudio(core); | 438 | cx88_set_tvaudio(core); |
@@ -561,8 +562,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |||
561 | *size = fh->fmt->depth*fh->width*fh->height >> 3; | 562 | *size = fh->fmt->depth*fh->width*fh->height >> 3; |
562 | if (0 == *count) | 563 | if (0 == *count) |
563 | *count = 32; | 564 | *count = 32; |
564 | while (*size * *count > vid_limit * 1024 * 1024) | 565 | if (*size * *count > vid_limit * 1024 * 1024) |
565 | (*count)--; | 566 | *count = (vid_limit * 1024 * 1024) / *size; |
566 | return 0; | 567 | return 0; |
567 | } | 568 | } |
568 | 569 | ||
@@ -1537,9 +1538,12 @@ static int radio_queryctrl (struct file *file, void *priv, | |||
1537 | c->id >= V4L2_CID_LASTP1) | 1538 | c->id >= V4L2_CID_LASTP1) |
1538 | return -EINVAL; | 1539 | return -EINVAL; |
1539 | if (c->id == V4L2_CID_AUDIO_MUTE) { | 1540 | if (c->id == V4L2_CID_AUDIO_MUTE) { |
1540 | for (i = 0; i < CX8800_CTLS; i++) | 1541 | for (i = 0; i < CX8800_CTLS; i++) { |
1541 | if (cx8800_ctls[i].v.id == c->id) | 1542 | if (cx8800_ctls[i].v.id == c->id) |
1542 | break; | 1543 | break; |
1544 | } | ||
1545 | if (i == CX8800_CTLS) | ||
1546 | return -EINVAL; | ||
1543 | *c = cx8800_ctls[i].v; | 1547 | *c = cx8800_ctls[i].v; |
1544 | } else | 1548 | } else |
1545 | *c = no_ctl; | 1549 | *c = no_ctl; |
@@ -1977,7 +1981,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) | |||
1977 | } | 1981 | } |
1978 | 1982 | ||
1979 | if (core->ir) | 1983 | if (core->ir) |
1980 | cx88_ir_stop(core, core->ir); | 1984 | cx88_ir_stop(core); |
1981 | 1985 | ||
1982 | cx88_shutdown(core); /* FIXME */ | 1986 | cx88_shutdown(core); /* FIXME */ |
1983 | pci_disable_device(pci_dev); | 1987 | pci_disable_device(pci_dev); |
@@ -2015,7 +2019,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
2015 | spin_unlock(&dev->slock); | 2019 | spin_unlock(&dev->slock); |
2016 | 2020 | ||
2017 | if (core->ir) | 2021 | if (core->ir) |
2018 | cx88_ir_stop(core, core->ir); | 2022 | cx88_ir_stop(core); |
2019 | /* FIXME -- shutdown device */ | 2023 | /* FIXME -- shutdown device */ |
2020 | cx88_shutdown(core); | 2024 | cx88_shutdown(core); |
2021 | 2025 | ||
@@ -2056,7 +2060,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) | |||
2056 | /* FIXME: re-initialize hardware */ | 2060 | /* FIXME: re-initialize hardware */ |
2057 | cx88_reset(core); | 2061 | cx88_reset(core); |
2058 | if (core->ir) | 2062 | if (core->ir) |
2059 | cx88_ir_start(core, core->ir); | 2063 | cx88_ir_start(core); |
2060 | 2064 | ||
2061 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); | 2065 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); |
2062 | 2066 | ||
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 48b6c04fb497..bdb03d336536 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | #include <linux/version.h> | 42 | #include <linux/version.h> |
43 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
44 | #define CX88_VERSION_CODE KERNEL_VERSION(0,0,7) | 44 | #define CX88_VERSION_CODE KERNEL_VERSION(0, 0, 8) |
45 | 45 | ||
46 | #define UNSET (-1U) | 46 | #define UNSET (-1U) |
47 | 47 | ||
@@ -290,7 +290,7 @@ struct cx88_subid { | |||
290 | #define RESOURCE_VIDEO 2 | 290 | #define RESOURCE_VIDEO 2 |
291 | #define RESOURCE_VBI 4 | 291 | #define RESOURCE_VBI 4 |
292 | 292 | ||
293 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ | 293 | #define BUFFER_TIMEOUT msecs_to_jiffies(2000) |
294 | 294 | ||
295 | /* buffer for one video frame */ | 295 | /* buffer for one video frame */ |
296 | struct cx88_buffer { | 296 | struct cx88_buffer { |
@@ -683,8 +683,8 @@ s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core); | |||
683 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); | 683 | int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); |
684 | int cx88_ir_fini(struct cx88_core *core); | 684 | int cx88_ir_fini(struct cx88_core *core); |
685 | void cx88_ir_irq(struct cx88_core *core); | 685 | void cx88_ir_irq(struct cx88_core *core); |
686 | void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir); | 686 | int cx88_ir_start(struct cx88_core *core); |
687 | void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir); | 687 | void cx88_ir_stop(struct cx88_core *core); |
688 | 688 | ||
689 | /* ----------------------------------------------------------- */ | 689 | /* ----------------------------------------------------------- */ |
690 | /* cx88-mpeg.c */ | 690 | /* cx88-mpeg.c */ |
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index b4cc96dc99ef..490aafb34e2f 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c | |||
@@ -101,6 +101,9 @@ static u32 ccdc_raw_bayer_pix_formats[] = | |||
101 | static u32 ccdc_raw_yuv_pix_formats[] = | 101 | static u32 ccdc_raw_yuv_pix_formats[] = |
102 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; | 102 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; |
103 | 103 | ||
104 | /* CCDC Save/Restore context */ | ||
105 | static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)]; | ||
106 | |||
104 | /* register access routines */ | 107 | /* register access routines */ |
105 | static inline u32 regr(u32 offset) | 108 | static inline u32 regr(u32 offset) |
106 | { | 109 | { |
@@ -400,7 +403,11 @@ void ccdc_config_ycbcr(void) | |||
400 | * configure the FID, VD, HD pin polarity, | 403 | * configure the FID, VD, HD pin polarity, |
401 | * fld,hd pol positive, vd negative, 8-bit data | 404 | * fld,hd pol positive, vd negative, 8-bit data |
402 | */ | 405 | */ |
403 | syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE | CCDC_SYN_MODE_8BITS; | 406 | syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE; |
407 | if (ccdc_cfg.if_type == VPFE_BT656_10BIT) | ||
408 | syn_mode |= CCDC_SYN_MODE_10BITS; | ||
409 | else | ||
410 | syn_mode |= CCDC_SYN_MODE_8BITS; | ||
404 | } else { | 411 | } else { |
405 | /* y/c external sync mode */ | 412 | /* y/c external sync mode */ |
406 | syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) << | 413 | syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) << |
@@ -419,8 +426,13 @@ void ccdc_config_ycbcr(void) | |||
419 | * configure the order of y cb cr in SDRAM, and disable latch | 426 | * configure the order of y cb cr in SDRAM, and disable latch |
420 | * internal register on vsync | 427 | * internal register on vsync |
421 | */ | 428 | */ |
422 | regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | | 429 | if (ccdc_cfg.if_type == VPFE_BT656_10BIT) |
423 | CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); | 430 | regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | |
431 | CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_BW656_10BIT, | ||
432 | CCDC_CCDCFG); | ||
433 | else | ||
434 | regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | | ||
435 | CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); | ||
424 | 436 | ||
425 | /* | 437 | /* |
426 | * configure the horizontal line offset. This should be a | 438 | * configure the horizontal line offset. This should be a |
@@ -435,7 +447,6 @@ void ccdc_config_ycbcr(void) | |||
435 | 447 | ||
436 | ccdc_sbl_reset(); | 448 | ccdc_sbl_reset(); |
437 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); | 449 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); |
438 | ccdc_readregs(); | ||
439 | } | 450 | } |
440 | 451 | ||
441 | static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) | 452 | static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) |
@@ -827,6 +838,7 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | |||
827 | case VPFE_BT656: | 838 | case VPFE_BT656: |
828 | case VPFE_YCBCR_SYNC_16: | 839 | case VPFE_YCBCR_SYNC_16: |
829 | case VPFE_YCBCR_SYNC_8: | 840 | case VPFE_YCBCR_SYNC_8: |
841 | case VPFE_BT656_10BIT: | ||
830 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; | 842 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; |
831 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; | 843 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; |
832 | break; | 844 | break; |
@@ -837,6 +849,87 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | |||
837 | return 0; | 849 | return 0; |
838 | } | 850 | } |
839 | 851 | ||
852 | static void ccdc_save_context(void) | ||
853 | { | ||
854 | ccdc_ctx[CCDC_PCR >> 2] = regr(CCDC_PCR); | ||
855 | ccdc_ctx[CCDC_SYN_MODE >> 2] = regr(CCDC_SYN_MODE); | ||
856 | ccdc_ctx[CCDC_HD_VD_WID >> 2] = regr(CCDC_HD_VD_WID); | ||
857 | ccdc_ctx[CCDC_PIX_LINES >> 2] = regr(CCDC_PIX_LINES); | ||
858 | ccdc_ctx[CCDC_HORZ_INFO >> 2] = regr(CCDC_HORZ_INFO); | ||
859 | ccdc_ctx[CCDC_VERT_START >> 2] = regr(CCDC_VERT_START); | ||
860 | ccdc_ctx[CCDC_VERT_LINES >> 2] = regr(CCDC_VERT_LINES); | ||
861 | ccdc_ctx[CCDC_CULLING >> 2] = regr(CCDC_CULLING); | ||
862 | ccdc_ctx[CCDC_HSIZE_OFF >> 2] = regr(CCDC_HSIZE_OFF); | ||
863 | ccdc_ctx[CCDC_SDOFST >> 2] = regr(CCDC_SDOFST); | ||
864 | ccdc_ctx[CCDC_SDR_ADDR >> 2] = regr(CCDC_SDR_ADDR); | ||
865 | ccdc_ctx[CCDC_CLAMP >> 2] = regr(CCDC_CLAMP); | ||
866 | ccdc_ctx[CCDC_DCSUB >> 2] = regr(CCDC_DCSUB); | ||
867 | ccdc_ctx[CCDC_COLPTN >> 2] = regr(CCDC_COLPTN); | ||
868 | ccdc_ctx[CCDC_BLKCMP >> 2] = regr(CCDC_BLKCMP); | ||
869 | ccdc_ctx[CCDC_FPC >> 2] = regr(CCDC_FPC); | ||
870 | ccdc_ctx[CCDC_FPC_ADDR >> 2] = regr(CCDC_FPC_ADDR); | ||
871 | ccdc_ctx[CCDC_VDINT >> 2] = regr(CCDC_VDINT); | ||
872 | ccdc_ctx[CCDC_ALAW >> 2] = regr(CCDC_ALAW); | ||
873 | ccdc_ctx[CCDC_REC656IF >> 2] = regr(CCDC_REC656IF); | ||
874 | ccdc_ctx[CCDC_CCDCFG >> 2] = regr(CCDC_CCDCFG); | ||
875 | ccdc_ctx[CCDC_FMTCFG >> 2] = regr(CCDC_FMTCFG); | ||
876 | ccdc_ctx[CCDC_FMT_HORZ >> 2] = regr(CCDC_FMT_HORZ); | ||
877 | ccdc_ctx[CCDC_FMT_VERT >> 2] = regr(CCDC_FMT_VERT); | ||
878 | ccdc_ctx[CCDC_FMT_ADDR0 >> 2] = regr(CCDC_FMT_ADDR0); | ||
879 | ccdc_ctx[CCDC_FMT_ADDR1 >> 2] = regr(CCDC_FMT_ADDR1); | ||
880 | ccdc_ctx[CCDC_FMT_ADDR2 >> 2] = regr(CCDC_FMT_ADDR2); | ||
881 | ccdc_ctx[CCDC_FMT_ADDR3 >> 2] = regr(CCDC_FMT_ADDR3); | ||
882 | ccdc_ctx[CCDC_FMT_ADDR4 >> 2] = regr(CCDC_FMT_ADDR4); | ||
883 | ccdc_ctx[CCDC_FMT_ADDR5 >> 2] = regr(CCDC_FMT_ADDR5); | ||
884 | ccdc_ctx[CCDC_FMT_ADDR6 >> 2] = regr(CCDC_FMT_ADDR6); | ||
885 | ccdc_ctx[CCDC_FMT_ADDR7 >> 2] = regr(CCDC_FMT_ADDR7); | ||
886 | ccdc_ctx[CCDC_PRGEVEN_0 >> 2] = regr(CCDC_PRGEVEN_0); | ||
887 | ccdc_ctx[CCDC_PRGEVEN_1 >> 2] = regr(CCDC_PRGEVEN_1); | ||
888 | ccdc_ctx[CCDC_PRGODD_0 >> 2] = regr(CCDC_PRGODD_0); | ||
889 | ccdc_ctx[CCDC_PRGODD_1 >> 2] = regr(CCDC_PRGODD_1); | ||
890 | ccdc_ctx[CCDC_VP_OUT >> 2] = regr(CCDC_VP_OUT); | ||
891 | } | ||
892 | |||
893 | static void ccdc_restore_context(void) | ||
894 | { | ||
895 | regw(ccdc_ctx[CCDC_SYN_MODE >> 2], CCDC_SYN_MODE); | ||
896 | regw(ccdc_ctx[CCDC_HD_VD_WID >> 2], CCDC_HD_VD_WID); | ||
897 | regw(ccdc_ctx[CCDC_PIX_LINES >> 2], CCDC_PIX_LINES); | ||
898 | regw(ccdc_ctx[CCDC_HORZ_INFO >> 2], CCDC_HORZ_INFO); | ||
899 | regw(ccdc_ctx[CCDC_VERT_START >> 2], CCDC_VERT_START); | ||
900 | regw(ccdc_ctx[CCDC_VERT_LINES >> 2], CCDC_VERT_LINES); | ||
901 | regw(ccdc_ctx[CCDC_CULLING >> 2], CCDC_CULLING); | ||
902 | regw(ccdc_ctx[CCDC_HSIZE_OFF >> 2], CCDC_HSIZE_OFF); | ||
903 | regw(ccdc_ctx[CCDC_SDOFST >> 2], CCDC_SDOFST); | ||
904 | regw(ccdc_ctx[CCDC_SDR_ADDR >> 2], CCDC_SDR_ADDR); | ||
905 | regw(ccdc_ctx[CCDC_CLAMP >> 2], CCDC_CLAMP); | ||
906 | regw(ccdc_ctx[CCDC_DCSUB >> 2], CCDC_DCSUB); | ||
907 | regw(ccdc_ctx[CCDC_COLPTN >> 2], CCDC_COLPTN); | ||
908 | regw(ccdc_ctx[CCDC_BLKCMP >> 2], CCDC_BLKCMP); | ||
909 | regw(ccdc_ctx[CCDC_FPC >> 2], CCDC_FPC); | ||
910 | regw(ccdc_ctx[CCDC_FPC_ADDR >> 2], CCDC_FPC_ADDR); | ||
911 | regw(ccdc_ctx[CCDC_VDINT >> 2], CCDC_VDINT); | ||
912 | regw(ccdc_ctx[CCDC_ALAW >> 2], CCDC_ALAW); | ||
913 | regw(ccdc_ctx[CCDC_REC656IF >> 2], CCDC_REC656IF); | ||
914 | regw(ccdc_ctx[CCDC_CCDCFG >> 2], CCDC_CCDCFG); | ||
915 | regw(ccdc_ctx[CCDC_FMTCFG >> 2], CCDC_FMTCFG); | ||
916 | regw(ccdc_ctx[CCDC_FMT_HORZ >> 2], CCDC_FMT_HORZ); | ||
917 | regw(ccdc_ctx[CCDC_FMT_VERT >> 2], CCDC_FMT_VERT); | ||
918 | regw(ccdc_ctx[CCDC_FMT_ADDR0 >> 2], CCDC_FMT_ADDR0); | ||
919 | regw(ccdc_ctx[CCDC_FMT_ADDR1 >> 2], CCDC_FMT_ADDR1); | ||
920 | regw(ccdc_ctx[CCDC_FMT_ADDR2 >> 2], CCDC_FMT_ADDR2); | ||
921 | regw(ccdc_ctx[CCDC_FMT_ADDR3 >> 2], CCDC_FMT_ADDR3); | ||
922 | regw(ccdc_ctx[CCDC_FMT_ADDR4 >> 2], CCDC_FMT_ADDR4); | ||
923 | regw(ccdc_ctx[CCDC_FMT_ADDR5 >> 2], CCDC_FMT_ADDR5); | ||
924 | regw(ccdc_ctx[CCDC_FMT_ADDR6 >> 2], CCDC_FMT_ADDR6); | ||
925 | regw(ccdc_ctx[CCDC_FMT_ADDR7 >> 2], CCDC_FMT_ADDR7); | ||
926 | regw(ccdc_ctx[CCDC_PRGEVEN_0 >> 2], CCDC_PRGEVEN_0); | ||
927 | regw(ccdc_ctx[CCDC_PRGEVEN_1 >> 2], CCDC_PRGEVEN_1); | ||
928 | regw(ccdc_ctx[CCDC_PRGODD_0 >> 2], CCDC_PRGODD_0); | ||
929 | regw(ccdc_ctx[CCDC_PRGODD_1 >> 2], CCDC_PRGODD_1); | ||
930 | regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT); | ||
931 | regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR); | ||
932 | } | ||
840 | static struct ccdc_hw_device ccdc_hw_dev = { | 933 | static struct ccdc_hw_device ccdc_hw_dev = { |
841 | .name = "DM6446 CCDC", | 934 | .name = "DM6446 CCDC", |
842 | .owner = THIS_MODULE, | 935 | .owner = THIS_MODULE, |
@@ -945,10 +1038,40 @@ static int dm644x_ccdc_remove(struct platform_device *pdev) | |||
945 | return 0; | 1038 | return 0; |
946 | } | 1039 | } |
947 | 1040 | ||
1041 | static int dm644x_ccdc_suspend(struct device *dev) | ||
1042 | { | ||
1043 | /* Save CCDC context */ | ||
1044 | ccdc_save_context(); | ||
1045 | /* Disable CCDC */ | ||
1046 | ccdc_enable(0); | ||
1047 | /* Disable both master and slave clock */ | ||
1048 | clk_disable(ccdc_cfg.mclk); | ||
1049 | clk_disable(ccdc_cfg.sclk); | ||
1050 | |||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | static int dm644x_ccdc_resume(struct device *dev) | ||
1055 | { | ||
1056 | /* Enable both master and slave clock */ | ||
1057 | clk_enable(ccdc_cfg.mclk); | ||
1058 | clk_enable(ccdc_cfg.sclk); | ||
1059 | /* Restore CCDC context */ | ||
1060 | ccdc_restore_context(); | ||
1061 | |||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static const struct dev_pm_ops dm644x_ccdc_pm_ops = { | ||
1066 | .suspend = dm644x_ccdc_suspend, | ||
1067 | .resume = dm644x_ccdc_resume, | ||
1068 | }; | ||
1069 | |||
948 | static struct platform_driver dm644x_ccdc_driver = { | 1070 | static struct platform_driver dm644x_ccdc_driver = { |
949 | .driver = { | 1071 | .driver = { |
950 | .name = "dm644x_ccdc", | 1072 | .name = "dm644x_ccdc", |
951 | .owner = THIS_MODULE, | 1073 | .owner = THIS_MODULE, |
1074 | .pm = &dm644x_ccdc_pm_ops, | ||
952 | }, | 1075 | }, |
953 | .remove = __devexit_p(dm644x_ccdc_remove), | 1076 | .remove = __devexit_p(dm644x_ccdc_remove), |
954 | .probe = dm644x_ccdc_probe, | 1077 | .probe = dm644x_ccdc_probe, |
diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h index 6e5d05324466..90370e414e2c 100644 --- a/drivers/media/video/davinci/dm644x_ccdc_regs.h +++ b/drivers/media/video/davinci/dm644x_ccdc_regs.h | |||
@@ -59,7 +59,7 @@ | |||
59 | #define CCDC_PRGODD_0 0x8c | 59 | #define CCDC_PRGODD_0 0x8c |
60 | #define CCDC_PRGODD_1 0x90 | 60 | #define CCDC_PRGODD_1 0x90 |
61 | #define CCDC_VP_OUT 0x94 | 61 | #define CCDC_VP_OUT 0x94 |
62 | 62 | #define CCDC_REG_END 0x98 | |
63 | 63 | ||
64 | /*************************************************************** | 64 | /*************************************************************** |
65 | * Define for various register bit mask and shifts for CCDC | 65 | * Define for various register bit mask and shifts for CCDC |
@@ -135,11 +135,19 @@ | |||
135 | #define CCDC_SYN_MODE_INPMOD_SHIFT 12 | 135 | #define CCDC_SYN_MODE_INPMOD_SHIFT 12 |
136 | #define CCDC_SYN_MODE_INPMOD_MASK 3 | 136 | #define CCDC_SYN_MODE_INPMOD_MASK 3 |
137 | #define CCDC_SYN_MODE_8BITS (7 << 8) | 137 | #define CCDC_SYN_MODE_8BITS (7 << 8) |
138 | #define CCDC_SYN_MODE_10BITS (6 << 8) | ||
139 | #define CCDC_SYN_MODE_11BITS (5 << 8) | ||
140 | #define CCDC_SYN_MODE_12BITS (4 << 8) | ||
141 | #define CCDC_SYN_MODE_13BITS (3 << 8) | ||
142 | #define CCDC_SYN_MODE_14BITS (2 << 8) | ||
143 | #define CCDC_SYN_MODE_15BITS (1 << 8) | ||
144 | #define CCDC_SYN_MODE_16BITS (0 << 8) | ||
138 | #define CCDC_SYN_FLDMODE_MASK 1 | 145 | #define CCDC_SYN_FLDMODE_MASK 1 |
139 | #define CCDC_SYN_FLDMODE_SHIFT 7 | 146 | #define CCDC_SYN_FLDMODE_SHIFT 7 |
140 | #define CCDC_REC656IF_BT656_EN 3 | 147 | #define CCDC_REC656IF_BT656_EN 3 |
141 | #define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2) | 148 | #define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2) |
142 | #define CCDC_CCDCFG_Y8POS_SHIFT 11 | 149 | #define CCDC_CCDCFG_Y8POS_SHIFT 11 |
150 | #define CCDC_CCDCFG_BW656_10BIT (1 << 5) | ||
143 | #define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 | 151 | #define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 |
144 | #define CCDC_NO_CULLING 0xffff00ff | 152 | #define CCDC_NO_CULLING 0xffff00ff |
145 | #endif | 153 | #endif |
diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h index f7b8893a2957..aa69a463c122 100644 --- a/drivers/media/video/davinci/isif_regs.h +++ b/drivers/media/video/davinci/isif_regs.h | |||
@@ -158,7 +158,7 @@ | |||
158 | 158 | ||
159 | /* gain - offset masks */ | 159 | /* gain - offset masks */ |
160 | #define GAIN_INTEGER_SHIFT 9 | 160 | #define GAIN_INTEGER_SHIFT 9 |
161 | #define OFFSET_MASK 0xFFF | 161 | #define OFFSET_MASK 0xFFF |
162 | #define GAIN_SDRAM_EN_SHIFT 12 | 162 | #define GAIN_SDRAM_EN_SHIFT 12 |
163 | #define GAIN_IPIPE_EN_SHIFT 13 | 163 | #define GAIN_IPIPE_EN_SHIFT 13 |
164 | #define GAIN_H3A_EN_SHIFT 14 | 164 | #define GAIN_H3A_EN_SHIFT 14 |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 398dbe71cb82..1c2588247289 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -475,6 +475,11 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe_dev) | |||
475 | ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); | 475 | ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); |
476 | if (!ret) | 476 | if (!ret) |
477 | vpfe_dev->initialized = 1; | 477 | vpfe_dev->initialized = 1; |
478 | |||
479 | /* Clear all VPFE/CCDC interrupts */ | ||
480 | if (vpfe_dev->cfg->clr_intr) | ||
481 | vpfe_dev->cfg->clr_intr(-1); | ||
482 | |||
478 | unlock: | 483 | unlock: |
479 | mutex_unlock(&ccdc_lock); | 484 | mutex_unlock(&ccdc_lock); |
480 | return ret; | 485 | return ret; |
@@ -534,6 +539,16 @@ static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev) | |||
534 | list_del(&vpfe_dev->next_frm->queue); | 539 | list_del(&vpfe_dev->next_frm->queue); |
535 | vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; | 540 | vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; |
536 | addr = videobuf_to_dma_contig(vpfe_dev->next_frm); | 541 | addr = videobuf_to_dma_contig(vpfe_dev->next_frm); |
542 | |||
543 | ccdc_dev->hw_ops.setfbaddr(addr); | ||
544 | } | ||
545 | |||
546 | static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev) | ||
547 | { | ||
548 | unsigned long addr; | ||
549 | |||
550 | addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); | ||
551 | addr += vpfe_dev->field_off; | ||
537 | ccdc_dev->hw_ops.setfbaddr(addr); | 552 | ccdc_dev->hw_ops.setfbaddr(addr); |
538 | } | 553 | } |
539 | 554 | ||
@@ -554,7 +569,6 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) | |||
554 | { | 569 | { |
555 | struct vpfe_device *vpfe_dev = dev_id; | 570 | struct vpfe_device *vpfe_dev = dev_id; |
556 | enum v4l2_field field; | 571 | enum v4l2_field field; |
557 | unsigned long addr; | ||
558 | int fid; | 572 | int fid; |
559 | 573 | ||
560 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); | 574 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); |
@@ -562,7 +576,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) | |||
562 | 576 | ||
563 | /* if streaming not started, don't do anything */ | 577 | /* if streaming not started, don't do anything */ |
564 | if (!vpfe_dev->started) | 578 | if (!vpfe_dev->started) |
565 | return IRQ_HANDLED; | 579 | goto clear_intr; |
566 | 580 | ||
567 | /* only for 6446 this will be applicable */ | 581 | /* only for 6446 this will be applicable */ |
568 | if (NULL != ccdc_dev->hw_ops.reset) | 582 | if (NULL != ccdc_dev->hw_ops.reset) |
@@ -574,7 +588,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) | |||
574 | "frame format is progressive...\n"); | 588 | "frame format is progressive...\n"); |
575 | if (vpfe_dev->cur_frm != vpfe_dev->next_frm) | 589 | if (vpfe_dev->cur_frm != vpfe_dev->next_frm) |
576 | vpfe_process_buffer_complete(vpfe_dev); | 590 | vpfe_process_buffer_complete(vpfe_dev); |
577 | return IRQ_HANDLED; | 591 | goto clear_intr; |
578 | } | 592 | } |
579 | 593 | ||
580 | /* interlaced or TB capture check which field we are in hardware */ | 594 | /* interlaced or TB capture check which field we are in hardware */ |
@@ -599,12 +613,9 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) | |||
599 | * the CCDC memory address | 613 | * the CCDC memory address |
600 | */ | 614 | */ |
601 | if (field == V4L2_FIELD_SEQ_TB) { | 615 | if (field == V4L2_FIELD_SEQ_TB) { |
602 | addr = | 616 | vpfe_schedule_bottom_field(vpfe_dev); |
603 | videobuf_to_dma_contig(vpfe_dev->cur_frm); | ||
604 | addr += vpfe_dev->field_off; | ||
605 | ccdc_dev->hw_ops.setfbaddr(addr); | ||
606 | } | 617 | } |
607 | return IRQ_HANDLED; | 618 | goto clear_intr; |
608 | } | 619 | } |
609 | /* | 620 | /* |
610 | * if one field is just being captured configure | 621 | * if one field is just being captured configure |
@@ -624,6 +635,10 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) | |||
624 | */ | 635 | */ |
625 | vpfe_dev->field_id = fid; | 636 | vpfe_dev->field_id = fid; |
626 | } | 637 | } |
638 | clear_intr: | ||
639 | if (vpfe_dev->cfg->clr_intr) | ||
640 | vpfe_dev->cfg->clr_intr(irq); | ||
641 | |||
627 | return IRQ_HANDLED; | 642 | return IRQ_HANDLED; |
628 | } | 643 | } |
629 | 644 | ||
@@ -635,8 +650,11 @@ static irqreturn_t vdint1_isr(int irq, void *dev_id) | |||
635 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); | 650 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); |
636 | 651 | ||
637 | /* if streaming not started, don't do anything */ | 652 | /* if streaming not started, don't do anything */ |
638 | if (!vpfe_dev->started) | 653 | if (!vpfe_dev->started) { |
654 | if (vpfe_dev->cfg->clr_intr) | ||
655 | vpfe_dev->cfg->clr_intr(irq); | ||
639 | return IRQ_HANDLED; | 656 | return IRQ_HANDLED; |
657 | } | ||
640 | 658 | ||
641 | spin_lock(&vpfe_dev->dma_queue_lock); | 659 | spin_lock(&vpfe_dev->dma_queue_lock); |
642 | if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && | 660 | if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && |
@@ -644,6 +662,10 @@ static irqreturn_t vdint1_isr(int irq, void *dev_id) | |||
644 | vpfe_dev->cur_frm == vpfe_dev->next_frm) | 662 | vpfe_dev->cur_frm == vpfe_dev->next_frm) |
645 | vpfe_schedule_next_buffer(vpfe_dev); | 663 | vpfe_schedule_next_buffer(vpfe_dev); |
646 | spin_unlock(&vpfe_dev->dma_queue_lock); | 664 | spin_unlock(&vpfe_dev->dma_queue_lock); |
665 | |||
666 | if (vpfe_dev->cfg->clr_intr) | ||
667 | vpfe_dev->cfg->clr_intr(irq); | ||
668 | |||
647 | return IRQ_HANDLED; | 669 | return IRQ_HANDLED; |
648 | } | 670 | } |
649 | 671 | ||
@@ -714,7 +736,7 @@ static int vpfe_release(struct file *file) | |||
714 | /* Decrement device usrs counter */ | 736 | /* Decrement device usrs counter */ |
715 | vpfe_dev->usrs--; | 737 | vpfe_dev->usrs--; |
716 | /* Close the priority */ | 738 | /* Close the priority */ |
717 | v4l2_prio_close(&vpfe_dev->prio, &fh->prio); | 739 | v4l2_prio_close(&vpfe_dev->prio, fh->prio); |
718 | /* If this is the last file handle */ | 740 | /* If this is the last file handle */ |
719 | if (!vpfe_dev->usrs) { | 741 | if (!vpfe_dev->usrs) { |
720 | vpfe_dev->initialized = 0; | 742 | vpfe_dev->initialized = 0; |
@@ -1218,7 +1240,10 @@ static int vpfe_videobuf_setup(struct videobuf_queue *vq, | |||
1218 | struct vpfe_device *vpfe_dev = fh->vpfe_dev; | 1240 | struct vpfe_device *vpfe_dev = fh->vpfe_dev; |
1219 | 1241 | ||
1220 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); | 1242 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); |
1221 | *size = config_params.device_bufsize; | 1243 | *size = vpfe_dev->fmt.fmt.pix.sizeimage; |
1244 | if (vpfe_dev->memory == V4L2_MEMORY_MMAP && | ||
1245 | vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize) | ||
1246 | *size = config_params.device_bufsize; | ||
1222 | 1247 | ||
1223 | if (*count < config_params.min_numbuffers) | 1248 | if (*count < config_params.min_numbuffers) |
1224 | *count = config_params.min_numbuffers; | 1249 | *count = config_params.min_numbuffers; |
@@ -1233,6 +1258,8 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, | |||
1233 | { | 1258 | { |
1234 | struct vpfe_fh *fh = vq->priv_data; | 1259 | struct vpfe_fh *fh = vq->priv_data; |
1235 | struct vpfe_device *vpfe_dev = fh->vpfe_dev; | 1260 | struct vpfe_device *vpfe_dev = fh->vpfe_dev; |
1261 | unsigned long addr; | ||
1262 | int ret; | ||
1236 | 1263 | ||
1237 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); | 1264 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); |
1238 | 1265 | ||
@@ -1242,8 +1269,18 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, | |||
1242 | vb->height = vpfe_dev->fmt.fmt.pix.height; | 1269 | vb->height = vpfe_dev->fmt.fmt.pix.height; |
1243 | vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; | 1270 | vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; |
1244 | vb->field = field; | 1271 | vb->field = field; |
1272 | |||
1273 | ret = videobuf_iolock(vq, vb, NULL);; | ||
1274 | if (ret < 0) | ||
1275 | return ret; | ||
1276 | |||
1277 | addr = videobuf_to_dma_contig(vb); | ||
1278 | /* Make sure user addresses are aligned to 32 bytes */ | ||
1279 | if (!ALIGN(addr, 32)) | ||
1280 | return -EINVAL; | ||
1281 | |||
1282 | vb->state = VIDEOBUF_PREPARED; | ||
1245 | } | 1283 | } |
1246 | vb->state = VIDEOBUF_PREPARED; | ||
1247 | return 0; | 1284 | return 0; |
1248 | } | 1285 | } |
1249 | 1286 | ||
@@ -1311,13 +1348,6 @@ static int vpfe_reqbufs(struct file *file, void *priv, | |||
1311 | return -EINVAL; | 1348 | return -EINVAL; |
1312 | } | 1349 | } |
1313 | 1350 | ||
1314 | if (V4L2_MEMORY_USERPTR == req_buf->memory) { | ||
1315 | /* we don't support user ptr IO */ | ||
1316 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:" | ||
1317 | " USERPTR IO not supported\n"); | ||
1318 | return -EINVAL; | ||
1319 | } | ||
1320 | |||
1321 | ret = mutex_lock_interruptible(&vpfe_dev->lock); | 1351 | ret = mutex_lock_interruptible(&vpfe_dev->lock); |
1322 | if (ret) | 1352 | if (ret) |
1323 | return ret; | 1353 | return ret; |
@@ -1831,7 +1861,6 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1831 | goto probe_free_dev_mem; | 1861 | goto probe_free_dev_mem; |
1832 | } | 1862 | } |
1833 | 1863 | ||
1834 | mutex_lock(&ccdc_lock); | ||
1835 | /* Allocate memory for ccdc configuration */ | 1864 | /* Allocate memory for ccdc configuration */ |
1836 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); | 1865 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); |
1837 | if (NULL == ccdc_cfg) { | 1866 | if (NULL == ccdc_cfg) { |
@@ -1840,6 +1869,8 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1840 | goto probe_free_lock; | 1869 | goto probe_free_lock; |
1841 | } | 1870 | } |
1842 | 1871 | ||
1872 | mutex_lock(&ccdc_lock); | ||
1873 | |||
1843 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); | 1874 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); |
1844 | /* Get VINT0 irq resource */ | 1875 | /* Get VINT0 irq resource */ |
1845 | res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1876 | res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
@@ -2015,18 +2046,14 @@ static int __devexit vpfe_remove(struct platform_device *pdev) | |||
2015 | return 0; | 2046 | return 0; |
2016 | } | 2047 | } |
2017 | 2048 | ||
2018 | static int | 2049 | static int vpfe_suspend(struct device *dev) |
2019 | vpfe_suspend(struct device *dev) | ||
2020 | { | 2050 | { |
2021 | /* add suspend code here later */ | 2051 | return 0; |
2022 | return -1; | ||
2023 | } | 2052 | } |
2024 | 2053 | ||
2025 | static int | 2054 | static int vpfe_resume(struct device *dev) |
2026 | vpfe_resume(struct device *dev) | ||
2027 | { | 2055 | { |
2028 | /* add resume code here later */ | 2056 | return 0; |
2029 | return -1; | ||
2030 | } | 2057 | } |
2031 | 2058 | ||
2032 | static const struct dev_pm_ops vpfe_dev_pm_ops = { | 2059 | static const struct dev_pm_ops vpfe_dev_pm_ops = { |
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 2e5a7fb2d0c9..a7f48b53d3fc 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c | |||
@@ -869,7 +869,7 @@ static int vpif_release(struct file *filep) | |||
869 | mutex_unlock(&common->lock); | 869 | mutex_unlock(&common->lock); |
870 | 870 | ||
871 | /* Close the priority */ | 871 | /* Close the priority */ |
872 | v4l2_prio_close(&ch->prio, &fh->prio); | 872 | v4l2_prio_close(&ch->prio, fh->prio); |
873 | 873 | ||
874 | if (fh->initialized) | 874 | if (fh->initialized) |
875 | ch->initialized = 0; | 875 | ch->initialized = 0; |
@@ -1444,7 +1444,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | |||
1444 | } | 1444 | } |
1445 | } | 1445 | } |
1446 | 1446 | ||
1447 | ret = v4l2_prio_check(&ch->prio, &fh->prio); | 1447 | ret = v4l2_prio_check(&ch->prio, fh->prio); |
1448 | if (0 != ret) | 1448 | if (0 != ret) |
1449 | return ret; | 1449 | return ret; |
1450 | 1450 | ||
@@ -1554,7 +1554,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) | |||
1554 | } | 1554 | } |
1555 | } | 1555 | } |
1556 | 1556 | ||
1557 | ret = v4l2_prio_check(&ch->prio, &fh->prio); | 1557 | ret = v4l2_prio_check(&ch->prio, fh->prio); |
1558 | if (0 != ret) | 1558 | if (0 != ret) |
1559 | return ret; | 1559 | return ret; |
1560 | 1560 | ||
@@ -1710,7 +1710,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, | |||
1710 | } | 1710 | } |
1711 | } | 1711 | } |
1712 | 1712 | ||
1713 | ret = v4l2_prio_check(&ch->prio, &fh->prio); | 1713 | ret = v4l2_prio_check(&ch->prio, fh->prio); |
1714 | if (0 != ret) | 1714 | if (0 != ret) |
1715 | return ret; | 1715 | return ret; |
1716 | 1716 | ||
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 13c3a1b97760..da07607cbc55 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c | |||
@@ -384,7 +384,7 @@ static int vpif_get_std_info(struct channel_obj *ch) | |||
384 | int index; | 384 | int index; |
385 | 385 | ||
386 | std_info->stdid = vid_ch->stdid; | 386 | std_info->stdid = vid_ch->stdid; |
387 | if (!std_info) | 387 | if (!std_info->stdid) |
388 | return -1; | 388 | return -1; |
389 | 389 | ||
390 | for (index = 0; index < ARRAY_SIZE(ch_params); index++) { | 390 | for (index = 0; index < ARRAY_SIZE(ch_params); index++) { |
@@ -671,7 +671,7 @@ static int vpif_release(struct file *filep) | |||
671 | ch->initialized = 0; | 671 | ch->initialized = 0; |
672 | 672 | ||
673 | /* Close the priority */ | 673 | /* Close the priority */ |
674 | v4l2_prio_close(&ch->prio, &fh->prio); | 674 | v4l2_prio_close(&ch->prio, fh->prio); |
675 | filep->private_data = NULL; | 675 | filep->private_data = NULL; |
676 | fh->initialized = 0; | 676 | fh->initialized = 0; |
677 | kfree(fh); | 677 | kfree(fh); |
@@ -753,7 +753,7 @@ static int vpif_s_fmt_vid_out(struct file *file, void *priv, | |||
753 | } | 753 | } |
754 | 754 | ||
755 | /* Check for the priority */ | 755 | /* Check for the priority */ |
756 | ret = v4l2_prio_check(&ch->prio, &fh->prio); | 756 | ret = v4l2_prio_check(&ch->prio, fh->prio); |
757 | if (0 != ret) | 757 | if (0 != ret) |
758 | return ret; | 758 | return ret; |
759 | fh->initialized = 1; | 759 | fh->initialized = 1; |
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index bd783387b37d..e182abf476c9 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -491,7 +491,7 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
491 | strcpy(pcm->name, "Empia 28xx Capture"); | 491 | strcpy(pcm->name, "Empia 28xx Capture"); |
492 | 492 | ||
493 | snd_card_set_dev(card, &dev->udev->dev); | 493 | snd_card_set_dev(card, &dev->udev->dev); |
494 | strcpy(card->driver, "Empia Em28xx Audio"); | 494 | strcpy(card->driver, "Em28xx-Audio"); |
495 | strcpy(card->shortname, "Em28xx Audio"); | 495 | strcpy(card->shortname, "Em28xx Audio"); |
496 | strcpy(card->longname, "Empia Em28xx Audio"); | 496 | strcpy(card->longname, "Empia Em28xx Audio"); |
497 | 497 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index b0fb08337710..3a4fd8514511 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -602,7 +602,7 @@ struct em28xx_board em28xx_boards[] = { | |||
602 | .name = "Gadmei UTV330+", | 602 | .name = "Gadmei UTV330+", |
603 | .tuner_type = TUNER_TNF_5335MF, | 603 | .tuner_type = TUNER_TNF_5335MF, |
604 | .tda9887_conf = TDA9887_PRESENT, | 604 | .tda9887_conf = TDA9887_PRESENT, |
605 | .ir_codes = &ir_codes_gadmei_rm008z_table, | 605 | .ir_codes = RC_MAP_GADMEI_RM008Z, |
606 | .decoder = EM28XX_SAA711X, | 606 | .decoder = EM28XX_SAA711X, |
607 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | 607 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, |
608 | .input = { { | 608 | .input = { { |
@@ -681,6 +681,20 @@ struct em28xx_board em28xx_boards[] = { | |||
681 | .amux = EM28XX_AMUX_LINE_IN, | 681 | .amux = EM28XX_AMUX_LINE_IN, |
682 | } }, | 682 | } }, |
683 | }, | 683 | }, |
684 | [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = { | ||
685 | .name = "EM2860/TVP5150 Reference Design", | ||
686 | .tuner_type = TUNER_ABSENT, /* Capture only device */ | ||
687 | .decoder = EM28XX_TVP5150, | ||
688 | .input = { { | ||
689 | .type = EM28XX_VMUX_COMPOSITE1, | ||
690 | .vmux = TVP5150_COMPOSITE1, | ||
691 | .amux = EM28XX_AMUX_LINE_IN, | ||
692 | }, { | ||
693 | .type = EM28XX_VMUX_SVIDEO, | ||
694 | .vmux = TVP5150_SVIDEO, | ||
695 | .amux = EM28XX_AMUX_LINE_IN, | ||
696 | } }, | ||
697 | }, | ||
684 | [EM2861_BOARD_PLEXTOR_PX_TV100U] = { | 698 | [EM2861_BOARD_PLEXTOR_PX_TV100U] = { |
685 | .name = "Plextor ConvertX PX-TV100U", | 699 | .name = "Plextor ConvertX PX-TV100U", |
686 | .tuner_type = TUNER_TNF_5335MF, | 700 | .tuner_type = TUNER_TNF_5335MF, |
@@ -777,7 +791,7 @@ struct em28xx_board em28xx_boards[] = { | |||
777 | .mts_firmware = 1, | 791 | .mts_firmware = 1, |
778 | .has_dvb = 1, | 792 | .has_dvb = 1, |
779 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 793 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
780 | .ir_codes = &ir_codes_hauppauge_new_table, | 794 | .ir_codes = RC_MAP_HAUPPAUGE_NEW, |
781 | .decoder = EM28XX_TVP5150, | 795 | .decoder = EM28XX_TVP5150, |
782 | .input = { { | 796 | .input = { { |
783 | .type = EM28XX_VMUX_TELEVISION, | 797 | .type = EM28XX_VMUX_TELEVISION, |
@@ -802,7 +816,7 @@ struct em28xx_board em28xx_boards[] = { | |||
802 | .tuner_type = TUNER_XC2028, | 816 | .tuner_type = TUNER_XC2028, |
803 | .tuner_gpio = default_tuner_gpio, | 817 | .tuner_gpio = default_tuner_gpio, |
804 | .mts_firmware = 1, | 818 | .mts_firmware = 1, |
805 | .ir_codes = &ir_codes_hauppauge_new_table, | 819 | .ir_codes = RC_MAP_HAUPPAUGE_NEW, |
806 | .decoder = EM28XX_TVP5150, | 820 | .decoder = EM28XX_TVP5150, |
807 | .input = { { | 821 | .input = { { |
808 | .type = EM28XX_VMUX_TELEVISION, | 822 | .type = EM28XX_VMUX_TELEVISION, |
@@ -828,7 +842,7 @@ struct em28xx_board em28xx_boards[] = { | |||
828 | .mts_firmware = 1, | 842 | .mts_firmware = 1, |
829 | .has_dvb = 1, | 843 | .has_dvb = 1, |
830 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 844 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
831 | .ir_codes = &ir_codes_hauppauge_new_table, | 845 | .ir_codes = RC_MAP_HAUPPAUGE_NEW, |
832 | .decoder = EM28XX_TVP5150, | 846 | .decoder = EM28XX_TVP5150, |
833 | .input = { { | 847 | .input = { { |
834 | .type = EM28XX_VMUX_TELEVISION, | 848 | .type = EM28XX_VMUX_TELEVISION, |
@@ -854,7 +868,7 @@ struct em28xx_board em28xx_boards[] = { | |||
854 | .mts_firmware = 1, | 868 | .mts_firmware = 1, |
855 | .has_dvb = 1, | 869 | .has_dvb = 1, |
856 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 870 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
857 | .ir_codes = &ir_codes_rc5_hauppauge_new_table, | 871 | .ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW, |
858 | .decoder = EM28XX_TVP5150, | 872 | .decoder = EM28XX_TVP5150, |
859 | .input = { { | 873 | .input = { { |
860 | .type = EM28XX_VMUX_TELEVISION, | 874 | .type = EM28XX_VMUX_TELEVISION, |
@@ -880,7 +894,7 @@ struct em28xx_board em28xx_boards[] = { | |||
880 | .mts_firmware = 1, | 894 | .mts_firmware = 1, |
881 | .has_dvb = 1, | 895 | .has_dvb = 1, |
882 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 896 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
883 | .ir_codes = &ir_codes_pinnacle_pctv_hd_table, | 897 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, |
884 | .decoder = EM28XX_TVP5150, | 898 | .decoder = EM28XX_TVP5150, |
885 | .input = { { | 899 | .input = { { |
886 | .type = EM28XX_VMUX_TELEVISION, | 900 | .type = EM28XX_VMUX_TELEVISION, |
@@ -906,7 +920,7 @@ struct em28xx_board em28xx_boards[] = { | |||
906 | .mts_firmware = 1, | 920 | .mts_firmware = 1, |
907 | .has_dvb = 1, | 921 | .has_dvb = 1, |
908 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 922 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
909 | .ir_codes = &ir_codes_ati_tv_wonder_hd_600_table, | 923 | .ir_codes = RC_MAP_ATI_TV_WONDER_HD_600, |
910 | .decoder = EM28XX_TVP5150, | 924 | .decoder = EM28XX_TVP5150, |
911 | .input = { { | 925 | .input = { { |
912 | .type = EM28XX_VMUX_TELEVISION, | 926 | .type = EM28XX_VMUX_TELEVISION, |
@@ -932,7 +946,7 @@ struct em28xx_board em28xx_boards[] = { | |||
932 | .decoder = EM28XX_TVP5150, | 946 | .decoder = EM28XX_TVP5150, |
933 | .has_dvb = 1, | 947 | .has_dvb = 1, |
934 | .dvb_gpio = default_digital, | 948 | .dvb_gpio = default_digital, |
935 | .ir_codes = &ir_codes_terratec_cinergy_xs_table, | 949 | .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, |
936 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ | 950 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ |
937 | .input = { { | 951 | .input = { { |
938 | .type = EM28XX_VMUX_TELEVISION, | 952 | .type = EM28XX_VMUX_TELEVISION, |
@@ -1282,7 +1296,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1282 | .decoder = EM28XX_SAA711X, | 1296 | .decoder = EM28XX_SAA711X, |
1283 | .has_dvb = 1, | 1297 | .has_dvb = 1, |
1284 | .dvb_gpio = em2882_kworld_315u_digital, | 1298 | .dvb_gpio = em2882_kworld_315u_digital, |
1285 | .ir_codes = &ir_codes_kworld_315u_table, | 1299 | .ir_codes = RC_MAP_KWORLD_315U, |
1286 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | 1300 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, |
1287 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, | 1301 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, |
1288 | /* Analog mode - still not ready */ | 1302 | /* Analog mode - still not ready */ |
@@ -1404,10 +1418,14 @@ struct em28xx_board em28xx_boards[] = { | |||
1404 | }, | 1418 | }, |
1405 | [EM2882_BOARD_KWORLD_VS_DVBT] = { | 1419 | [EM2882_BOARD_KWORLD_VS_DVBT] = { |
1406 | .name = "Kworld VS-DVB-T 323UR", | 1420 | .name = "Kworld VS-DVB-T 323UR", |
1407 | .valid = EM28XX_BOARD_NOT_VALIDATED, | ||
1408 | .tuner_type = TUNER_XC2028, | 1421 | .tuner_type = TUNER_XC2028, |
1409 | .tuner_gpio = default_tuner_gpio, | 1422 | .tuner_gpio = default_tuner_gpio, |
1410 | .decoder = EM28XX_TVP5150, | 1423 | .decoder = EM28XX_TVP5150, |
1424 | .mts_firmware = 1, | ||
1425 | .has_dvb = 1, | ||
1426 | .dvb_gpio = kworld_330u_digital, | ||
1427 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ | ||
1428 | .ir_codes = RC_MAP_KWORLD_315U, | ||
1411 | .input = { { | 1429 | .input = { { |
1412 | .type = EM28XX_VMUX_TELEVISION, | 1430 | .type = EM28XX_VMUX_TELEVISION, |
1413 | .vmux = TVP5150_COMPOSITE0, | 1431 | .vmux = TVP5150_COMPOSITE0, |
@@ -1430,7 +1448,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1430 | .decoder = EM28XX_TVP5150, | 1448 | .decoder = EM28XX_TVP5150, |
1431 | .has_dvb = 1, | 1449 | .has_dvb = 1, |
1432 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 1450 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
1433 | .ir_codes = &ir_codes_terratec_cinergy_xs_table, | 1451 | .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, |
1434 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | 1452 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, |
1435 | .input = { { | 1453 | .input = { { |
1436 | .type = EM28XX_VMUX_TELEVISION, | 1454 | .type = EM28XX_VMUX_TELEVISION, |
@@ -1523,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1523 | .mts_firmware = 1, | 1541 | .mts_firmware = 1, |
1524 | .decoder = EM28XX_TVP5150, | 1542 | .decoder = EM28XX_TVP5150, |
1525 | .tuner_gpio = default_tuner_gpio, | 1543 | .tuner_gpio = default_tuner_gpio, |
1526 | .ir_codes = &ir_codes_kaiomy_table, | 1544 | .ir_codes = RC_MAP_KAIOMY, |
1527 | .input = { { | 1545 | .input = { { |
1528 | .type = EM28XX_VMUX_TELEVISION, | 1546 | .type = EM28XX_VMUX_TELEVISION, |
1529 | .vmux = TVP5150_COMPOSITE0, | 1547 | .vmux = TVP5150_COMPOSITE0, |
@@ -1623,7 +1641,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1623 | .mts_firmware = 1, | 1641 | .mts_firmware = 1, |
1624 | .has_dvb = 1, | 1642 | .has_dvb = 1, |
1625 | .dvb_gpio = evga_indtube_digital, | 1643 | .dvb_gpio = evga_indtube_digital, |
1626 | .ir_codes = &ir_codes_evga_indtube_table, | 1644 | .ir_codes = RC_MAP_EVGA_INDTUBE, |
1627 | .input = { { | 1645 | .input = { { |
1628 | .type = EM28XX_VMUX_TELEVISION, | 1646 | .type = EM28XX_VMUX_TELEVISION, |
1629 | .vmux = TVP5150_COMPOSITE0, | 1647 | .vmux = TVP5150_COMPOSITE0, |
@@ -1672,6 +1690,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
1672 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1690 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1673 | { USB_DEVICE(0xeb1a, 0x2862), | 1691 | { USB_DEVICE(0xeb1a, 0x2862), |
1674 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1692 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1693 | { USB_DEVICE(0xeb1a, 0x2863), | ||
1694 | .driver_info = EM2820_BOARD_UNKNOWN }, | ||
1675 | { USB_DEVICE(0xeb1a, 0x2870), | 1695 | { USB_DEVICE(0xeb1a, 0x2870), |
1676 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1696 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1677 | { USB_DEVICE(0xeb1a, 0x2881), | 1697 | { USB_DEVICE(0xeb1a, 0x2881), |
@@ -1792,6 +1812,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { | |||
1792 | {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, | 1812 | {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, |
1793 | {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, | 1813 | {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, |
1794 | {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, | 1814 | {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, |
1815 | {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, | ||
1795 | {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, | 1816 | {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, |
1796 | {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, | 1817 | {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, |
1797 | }; | 1818 | }; |
@@ -2138,6 +2159,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
2138 | break; | 2159 | break; |
2139 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 2160 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
2140 | case EM2882_BOARD_DIKOM_DK300: | 2161 | case EM2882_BOARD_DIKOM_DK300: |
2162 | case EM2882_BOARD_KWORLD_VS_DVBT: | ||
2141 | ctl->demod = XC3028_FE_CHINA; | 2163 | ctl->demod = XC3028_FE_CHINA; |
2142 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | 2164 | ctl->fname = XC2028_DEFAULT_FIRMWARE; |
2143 | break; | 2165 | break; |
@@ -2313,21 +2335,21 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2313 | switch (dev->model) { | 2335 | switch (dev->model) { |
2314 | case EM2800_BOARD_TERRATEC_CINERGY_200: | 2336 | case EM2800_BOARD_TERRATEC_CINERGY_200: |
2315 | case EM2820_BOARD_TERRATEC_CINERGY_250: | 2337 | case EM2820_BOARD_TERRATEC_CINERGY_250: |
2316 | dev->init_data.ir_codes = &ir_codes_em_terratec_table; | 2338 | dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; |
2317 | dev->init_data.get_key = em28xx_get_key_terratec; | 2339 | dev->init_data.get_key = em28xx_get_key_terratec; |
2318 | dev->init_data.name = "i2c IR (EM28XX Terratec)"; | 2340 | dev->init_data.name = "i2c IR (EM28XX Terratec)"; |
2319 | break; | 2341 | break; |
2320 | case EM2820_BOARD_PINNACLE_USB_2: | 2342 | case EM2820_BOARD_PINNACLE_USB_2: |
2321 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; | 2343 | dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; |
2322 | dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; | 2344 | dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; |
2323 | dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; | 2345 | dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; |
2324 | break; | 2346 | break; |
2325 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: | 2347 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: |
2326 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; | 2348 | dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; |
2327 | dev->init_data.get_key = em28xx_get_key_em_haup; | 2349 | dev->init_data.get_key = em28xx_get_key_em_haup; |
2328 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; | 2350 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; |
2329 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: | 2351 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: |
2330 | dev->init_data.ir_codes = &ir_codes_winfast_usbii_deluxe_table;; | 2352 | dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;; |
2331 | dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; | 2353 | dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; |
2332 | dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; | 2354 | dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; |
2333 | break; | 2355 | break; |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a41cc5566778..d3813ed789d9 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -782,11 +782,15 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
782 | 782 | ||
783 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); | 783 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); |
784 | 784 | ||
785 | /* If we don't set the start position to 4 in VBI mode, we end up | 785 | /* If we don't set the start position to 2 in VBI mode, we end up |
786 | with line 21 being YUYV encoded instead of being in 8-bit | 786 | with line 20/21 being YUYV encoded instead of being in 8-bit |
787 | greyscale */ | 787 | greyscale. The core of the issue is that line 21 (and line 23 for |
788 | PAL WSS) are inside of active video region, and as a result they | ||
789 | get the pixelformatting associated with that area. So by cropping | ||
790 | it out, we end up with the same format as the rest of the VBI | ||
791 | region */ | ||
788 | if (em28xx_vbi_supported(dev) == 1) | 792 | if (em28xx_vbi_supported(dev) == 1) |
789 | em28xx_capture_area_set(dev, 0, 4, width >> 2, height >> 2); | 793 | em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2); |
790 | else | 794 | else |
791 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); | 795 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); |
792 | 796 | ||
@@ -1174,21 +1178,18 @@ void em28xx_add_into_devlist(struct em28xx *dev) | |||
1174 | */ | 1178 | */ |
1175 | 1179 | ||
1176 | static LIST_HEAD(em28xx_extension_devlist); | 1180 | static LIST_HEAD(em28xx_extension_devlist); |
1177 | static DEFINE_MUTEX(em28xx_extension_devlist_lock); | ||
1178 | 1181 | ||
1179 | int em28xx_register_extension(struct em28xx_ops *ops) | 1182 | int em28xx_register_extension(struct em28xx_ops *ops) |
1180 | { | 1183 | { |
1181 | struct em28xx *dev = NULL; | 1184 | struct em28xx *dev = NULL; |
1182 | 1185 | ||
1183 | mutex_lock(&em28xx_devlist_mutex); | 1186 | mutex_lock(&em28xx_devlist_mutex); |
1184 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1185 | list_add_tail(&ops->next, &em28xx_extension_devlist); | 1187 | list_add_tail(&ops->next, &em28xx_extension_devlist); |
1186 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | 1188 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
1187 | if (dev) | 1189 | if (dev) |
1188 | ops->init(dev); | 1190 | ops->init(dev); |
1189 | } | 1191 | } |
1190 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | 1192 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); |
1191 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1192 | mutex_unlock(&em28xx_devlist_mutex); | 1193 | mutex_unlock(&em28xx_devlist_mutex); |
1193 | return 0; | 1194 | return 0; |
1194 | } | 1195 | } |
@@ -1204,10 +1205,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) | |||
1204 | ops->fini(dev); | 1205 | ops->fini(dev); |
1205 | } | 1206 | } |
1206 | 1207 | ||
1207 | mutex_lock(&em28xx_extension_devlist_lock); | ||
1208 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | 1208 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); |
1209 | list_del(&ops->next); | 1209 | list_del(&ops->next); |
1210 | mutex_unlock(&em28xx_extension_devlist_lock); | ||
1211 | mutex_unlock(&em28xx_devlist_mutex); | 1210 | mutex_unlock(&em28xx_devlist_mutex); |
1212 | } | 1211 | } |
1213 | EXPORT_SYMBOL(em28xx_unregister_extension); | 1212 | EXPORT_SYMBOL(em28xx_unregister_extension); |
@@ -1216,26 +1215,26 @@ void em28xx_init_extension(struct em28xx *dev) | |||
1216 | { | 1215 | { |
1217 | struct em28xx_ops *ops = NULL; | 1216 | struct em28xx_ops *ops = NULL; |
1218 | 1217 | ||
1219 | mutex_lock(&em28xx_extension_devlist_lock); | 1218 | mutex_lock(&em28xx_devlist_mutex); |
1220 | if (!list_empty(&em28xx_extension_devlist)) { | 1219 | if (!list_empty(&em28xx_extension_devlist)) { |
1221 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | 1220 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { |
1222 | if (ops->init) | 1221 | if (ops->init) |
1223 | ops->init(dev); | 1222 | ops->init(dev); |
1224 | } | 1223 | } |
1225 | } | 1224 | } |
1226 | mutex_unlock(&em28xx_extension_devlist_lock); | 1225 | mutex_unlock(&em28xx_devlist_mutex); |
1227 | } | 1226 | } |
1228 | 1227 | ||
1229 | void em28xx_close_extension(struct em28xx *dev) | 1228 | void em28xx_close_extension(struct em28xx *dev) |
1230 | { | 1229 | { |
1231 | struct em28xx_ops *ops = NULL; | 1230 | struct em28xx_ops *ops = NULL; |
1232 | 1231 | ||
1233 | mutex_lock(&em28xx_extension_devlist_lock); | 1232 | mutex_lock(&em28xx_devlist_mutex); |
1234 | if (!list_empty(&em28xx_extension_devlist)) { | 1233 | if (!list_empty(&em28xx_extension_devlist)) { |
1235 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | 1234 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { |
1236 | if (ops->fini) | 1235 | if (ops->fini) |
1237 | ops->fini(dev); | 1236 | ops->fini(dev); |
1238 | } | 1237 | } |
1239 | } | 1238 | } |
1240 | mutex_unlock(&em28xx_extension_devlist_lock); | 1239 | mutex_unlock(&em28xx_devlist_mutex); |
1241 | } | 1240 | } |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index bcd3c371009b..cf1d8c3655fc 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -467,6 +467,7 @@ static int dvb_init(struct em28xx *dev) | |||
467 | } | 467 | } |
468 | dev->dvb = dvb; | 468 | dev->dvb = dvb; |
469 | 469 | ||
470 | mutex_lock(&dev->lock); | ||
470 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | 471 | em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); |
471 | /* init frontend */ | 472 | /* init frontend */ |
472 | switch (dev->model) { | 473 | switch (dev->model) { |
@@ -506,6 +507,7 @@ static int dvb_init(struct em28xx *dev) | |||
506 | case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: | 507 | case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: |
507 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: | 508 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: |
508 | case EM2882_BOARD_DIKOM_DK300: | 509 | case EM2882_BOARD_DIKOM_DK300: |
510 | case EM2882_BOARD_KWORLD_VS_DVBT: | ||
509 | dvb->frontend = dvb_attach(zl10353_attach, | 511 | dvb->frontend = dvb_attach(zl10353_attach, |
510 | &em28xx_zl10353_xc3028_no_i2c_gate, | 512 | &em28xx_zl10353_xc3028_no_i2c_gate, |
511 | &dev->i2c_adap); | 513 | &dev->i2c_adap); |
@@ -589,15 +591,16 @@ static int dvb_init(struct em28xx *dev) | |||
589 | if (result < 0) | 591 | if (result < 0) |
590 | goto out_free; | 592 | goto out_free; |
591 | 593 | ||
592 | em28xx_set_mode(dev, EM28XX_SUSPEND); | ||
593 | em28xx_info("Successfully loaded em28xx-dvb\n"); | 594 | em28xx_info("Successfully loaded em28xx-dvb\n"); |
594 | return 0; | 595 | ret: |
596 | em28xx_set_mode(dev, EM28XX_SUSPEND); | ||
597 | mutex_unlock(&dev->lock); | ||
598 | return result; | ||
595 | 599 | ||
596 | out_free: | 600 | out_free: |
597 | em28xx_set_mode(dev, EM28XX_SUSPEND); | ||
598 | kfree(dvb); | 601 | kfree(dvb); |
599 | dev->dvb = NULL; | 602 | dev->dvb = NULL; |
600 | return result; | 603 | goto ret; |
601 | } | 604 | } |
602 | 605 | ||
603 | static int dvb_fini(struct em28xx *dev) | 606 | static int dvb_fini(struct em28xx *dev) |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 20a0001e8885..5c3fd9411b1f 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -39,6 +39,8 @@ static unsigned int ir_debug; | |||
39 | module_param(ir_debug, int, 0644); | 39 | module_param(ir_debug, int, 0644); |
40 | MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); | 40 | MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); |
41 | 41 | ||
42 | #define MODULE_NAME "em28xx" | ||
43 | |||
42 | #define i2cdprintk(fmt, arg...) \ | 44 | #define i2cdprintk(fmt, arg...) \ |
43 | if (ir_debug) { \ | 45 | if (ir_debug) { \ |
44 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ | 46 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ |
@@ -360,14 +362,20 @@ static void em28xx_ir_work(struct work_struct *work) | |||
360 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | 362 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); |
361 | } | 363 | } |
362 | 364 | ||
363 | static void em28xx_ir_start(struct em28xx_IR *ir) | 365 | static int em28xx_ir_start(void *priv) |
364 | { | 366 | { |
367 | struct em28xx_IR *ir = priv; | ||
368 | |||
365 | INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); | 369 | INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); |
366 | schedule_delayed_work(&ir->work, 0); | 370 | schedule_delayed_work(&ir->work, 0); |
371 | |||
372 | return 0; | ||
367 | } | 373 | } |
368 | 374 | ||
369 | static void em28xx_ir_stop(struct em28xx_IR *ir) | 375 | static void em28xx_ir_stop(void *priv) |
370 | { | 376 | { |
377 | struct em28xx_IR *ir = priv; | ||
378 | |||
371 | cancel_delayed_work_sync(&ir->work); | 379 | cancel_delayed_work_sync(&ir->work); |
372 | } | 380 | } |
373 | 381 | ||
@@ -380,7 +388,6 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) | |||
380 | 388 | ||
381 | /* Adjust xclk based o IR table for RC5/NEC tables */ | 389 | /* Adjust xclk based o IR table for RC5/NEC tables */ |
382 | 390 | ||
383 | dev->board.ir_codes->ir_type = IR_TYPE_OTHER; | ||
384 | if (ir_type == IR_TYPE_RC5) { | 391 | if (ir_type == IR_TYPE_RC5) { |
385 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | 392 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
386 | ir->full_code = 1; | 393 | ir->full_code = 1; |
@@ -388,11 +395,9 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) | |||
388 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | 395 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; |
389 | ir_config = EM2874_IR_NEC; | 396 | ir_config = EM2874_IR_NEC; |
390 | ir->full_code = 1; | 397 | ir->full_code = 1; |
391 | } else | 398 | } else if (ir_type != IR_TYPE_UNKNOWN) |
392 | rc = -EINVAL; | 399 | rc = -EINVAL; |
393 | 400 | ||
394 | dev->board.ir_codes->ir_type = ir_type; | ||
395 | |||
396 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 401 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
397 | EM28XX_XCLK_IR_RC5_MODE); | 402 | EM28XX_XCLK_IR_RC5_MODE); |
398 | 403 | ||
@@ -443,6 +448,13 @@ int em28xx_ir_init(struct em28xx *dev) | |||
443 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | 448 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; |
444 | ir->props.priv = ir; | 449 | ir->props.priv = ir; |
445 | ir->props.change_protocol = em28xx_ir_change_protocol; | 450 | ir->props.change_protocol = em28xx_ir_change_protocol; |
451 | ir->props.open = em28xx_ir_start; | ||
452 | ir->props.close = em28xx_ir_stop; | ||
453 | |||
454 | /* By default, keep protocol field untouched */ | ||
455 | err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN); | ||
456 | if (err) | ||
457 | goto err_out_free; | ||
446 | 458 | ||
447 | /* This is how often we ask the chip for IR information */ | 459 | /* This is how often we ask the chip for IR information */ |
448 | ir->polling = 100; /* ms */ | 460 | ir->polling = 100; /* ms */ |
@@ -455,7 +467,6 @@ int em28xx_ir_init(struct em28xx *dev) | |||
455 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 467 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
456 | 468 | ||
457 | /* Set IR protocol */ | 469 | /* Set IR protocol */ |
458 | em28xx_ir_change_protocol(ir, dev->board.ir_codes->ir_type); | ||
459 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | 470 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
460 | if (err < 0) | 471 | if (err < 0) |
461 | goto err_out_free; | 472 | goto err_out_free; |
@@ -470,17 +481,15 @@ int em28xx_ir_init(struct em28xx *dev) | |||
470 | input_dev->dev.parent = &dev->udev->dev; | 481 | input_dev->dev.parent = &dev->udev->dev; |
471 | 482 | ||
472 | 483 | ||
473 | em28xx_ir_start(ir); | ||
474 | 484 | ||
475 | /* all done */ | 485 | /* all done */ |
476 | err = ir_input_register(ir->input, dev->board.ir_codes, | 486 | err = ir_input_register(ir->input, dev->board.ir_codes, |
477 | &ir->props); | 487 | &ir->props, MODULE_NAME); |
478 | if (err) | 488 | if (err) |
479 | goto err_out_stop; | 489 | goto err_out_stop; |
480 | 490 | ||
481 | return 0; | 491 | return 0; |
482 | err_out_stop: | 492 | err_out_stop: |
483 | em28xx_ir_stop(ir); | ||
484 | dev->ir = NULL; | 493 | dev->ir = NULL; |
485 | err_out_free: | 494 | err_out_free: |
486 | kfree(ir); | 495 | kfree(ir); |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0fe20110bfd6..20090e34173a 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -203,12 +203,6 @@ static void em28xx_copy_video(struct em28xx *dev, | |||
203 | if (dma_q->pos + len > buf->vb.size) | 203 | if (dma_q->pos + len > buf->vb.size) |
204 | len = buf->vb.size - dma_q->pos; | 204 | len = buf->vb.size - dma_q->pos; |
205 | 205 | ||
206 | if (p[0] != 0x88 && p[0] != 0x22) { | ||
207 | em28xx_isocdbg("frame is not complete\n"); | ||
208 | len += 4; | ||
209 | } else | ||
210 | p += 4; | ||
211 | |||
212 | startread = p; | 206 | startread = p; |
213 | remain = len; | 207 | remain = len; |
214 | 208 | ||
@@ -309,14 +303,6 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
309 | if (dma_q->pos + len > buf->vb.size) | 303 | if (dma_q->pos + len > buf->vb.size) |
310 | len = buf->vb.size - dma_q->pos; | 304 | len = buf->vb.size - dma_q->pos; |
311 | 305 | ||
312 | if ((p[0] == 0x33 && p[1] == 0x95) || | ||
313 | (p[0] == 0x88 && p[1] == 0x88)) { | ||
314 | /* Header field, advance past it */ | ||
315 | p += 4; | ||
316 | } else { | ||
317 | len += 4; | ||
318 | } | ||
319 | |||
320 | startread = p; | 306 | startread = p; |
321 | 307 | ||
322 | startwrite = outp + dma_q->pos; | 308 | startwrite = outp + dma_q->pos; |
@@ -507,8 +493,15 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) | |||
507 | 493 | ||
508 | dma_q->pos = 0; | 494 | dma_q->pos = 0; |
509 | } | 495 | } |
510 | if (buf != NULL) | 496 | if (buf != NULL) { |
497 | if (p[0] != 0x88 && p[0] != 0x22) { | ||
498 | em28xx_isocdbg("frame is not complete\n"); | ||
499 | len += 4; | ||
500 | } else { | ||
501 | p += 4; | ||
502 | } | ||
511 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); | 503 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); |
504 | } | ||
512 | } | 505 | } |
513 | return rc; | 506 | return rc; |
514 | } | 507 | } |
@@ -555,8 +548,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
555 | continue; | 548 | continue; |
556 | } | 549 | } |
557 | 550 | ||
558 | len = urb->iso_frame_desc[i].actual_length - 4; | 551 | len = urb->iso_frame_desc[i].actual_length; |
559 | |||
560 | if (urb->iso_frame_desc[i].actual_length <= 0) { | 552 | if (urb->iso_frame_desc[i].actual_length <= 0) { |
561 | /* em28xx_isocdbg("packet %d is empty",i); - spammy */ | 553 | /* em28xx_isocdbg("packet %d is empty",i); - spammy */ |
562 | continue; | 554 | continue; |
@@ -577,6 +569,17 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
577 | dev->vbi_read = 0; | 569 | dev->vbi_read = 0; |
578 | em28xx_isocdbg("VBI START HEADER!!!\n"); | 570 | em28xx_isocdbg("VBI START HEADER!!!\n"); |
579 | dev->cur_field = p[2]; | 571 | dev->cur_field = p[2]; |
572 | p += 4; | ||
573 | len -= 4; | ||
574 | } else if (p[0] == 0x88 && p[1] == 0x88 && | ||
575 | p[2] == 0x88 && p[3] == 0x88) { | ||
576 | /* continuation */ | ||
577 | p += 4; | ||
578 | len -= 4; | ||
579 | } else if (p[0] == 0x22 && p[1] == 0x5a) { | ||
580 | /* start video */ | ||
581 | p += 4; | ||
582 | len -= 4; | ||
580 | } | 583 | } |
581 | 584 | ||
582 | vbi_size = dev->vbi_width * dev->vbi_height; | 585 | vbi_size = dev->vbi_width * dev->vbi_height; |
@@ -631,9 +634,6 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
631 | 634 | ||
632 | if (dev->capture_type == 1) { | 635 | if (dev->capture_type == 1) { |
633 | dev->capture_type = 2; | 636 | dev->capture_type = 2; |
634 | em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], | ||
635 | len, (p[2] & 1) ? "odd" : "even"); | ||
636 | |||
637 | if (dev->progressive || !(dev->cur_field & 1)) { | 637 | if (dev->progressive || !(dev->cur_field & 1)) { |
638 | if (buf != NULL) | 638 | if (buf != NULL) |
639 | buffer_filled(dev, dma_q, buf); | 639 | buffer_filled(dev, dma_q, buf); |
@@ -652,8 +652,25 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
652 | 652 | ||
653 | dma_q->pos = 0; | 653 | dma_q->pos = 0; |
654 | } | 654 | } |
655 | if (buf != NULL && dev->capture_type == 2) | 655 | |
656 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); | 656 | if (buf != NULL && dev->capture_type == 2) { |
657 | if (len > 4 && p[0] == 0x88 && p[1] == 0x88 && | ||
658 | p[2] == 0x88 && p[3] == 0x88) { | ||
659 | p += 4; | ||
660 | len -= 4; | ||
661 | } | ||
662 | if (len > 4 && p[0] == 0x22 && p[1] == 0x5a) { | ||
663 | em28xx_isocdbg("Video frame %d, len=%i, %s\n", | ||
664 | p[2], len, (p[2] & 1) ? | ||
665 | "odd" : "even"); | ||
666 | p += 4; | ||
667 | len -= 4; | ||
668 | } | ||
669 | |||
670 | if (len > 0) | ||
671 | em28xx_copy_video(dev, dma_q, buf, p, outp, | ||
672 | len); | ||
673 | } | ||
657 | } | 674 | } |
658 | return rc; | 675 | return rc; |
659 | } | 676 | } |
@@ -1483,6 +1500,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
1483 | return -EINVAL; | 1500 | return -EINVAL; |
1484 | 1501 | ||
1485 | strcpy(t->name, "Tuner"); | 1502 | strcpy(t->name, "Tuner"); |
1503 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1486 | 1504 | ||
1487 | mutex_lock(&dev->lock); | 1505 | mutex_lock(&dev->lock); |
1488 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); | 1506 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); |
@@ -1814,7 +1832,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, | |||
1814 | mutex_lock(&dev->lock); | 1832 | mutex_lock(&dev->lock); |
1815 | 1833 | ||
1816 | f->fmt.sliced.service_set = 0; | 1834 | f->fmt.sliced.service_set = 0; |
1817 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); | 1835 | v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); |
1818 | 1836 | ||
1819 | if (f->fmt.sliced.service_set == 0) | 1837 | if (f->fmt.sliced.service_set == 0) |
1820 | rc = -EINVAL; | 1838 | rc = -EINVAL; |
@@ -1836,7 +1854,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, | |||
1836 | return rc; | 1854 | return rc; |
1837 | 1855 | ||
1838 | mutex_lock(&dev->lock); | 1856 | mutex_lock(&dev->lock); |
1839 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); | 1857 | v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); |
1840 | mutex_unlock(&dev->lock); | 1858 | mutex_unlock(&dev->lock); |
1841 | 1859 | ||
1842 | if (f->fmt.sliced.service_set == 0) | 1860 | if (f->fmt.sliced.service_set == 0) |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index ba6fe5daff84..b252d1b1b2a7 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -68,6 +68,7 @@ | |||
68 | #define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 | 68 | #define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 |
69 | #define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 | 69 | #define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 |
70 | #define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 | 70 | #define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 |
71 | #define EM2860_BOARD_TVP5150_REFERENCE_DESIGN 29 | ||
71 | #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 | 72 | #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 |
72 | #define EM2821_BOARD_USBGEAR_VD204 31 | 73 | #define EM2821_BOARD_USBGEAR_VD204 31 |
73 | #define EM2821_BOARD_SUPERCOMP_USB_2 32 | 74 | #define EM2821_BOARD_SUPERCOMP_USB_2 32 |
@@ -140,10 +141,10 @@ | |||
140 | #define EM28XX_NUM_BUFS 5 | 141 | #define EM28XX_NUM_BUFS 5 |
141 | 142 | ||
142 | /* number of packets for each buffer | 143 | /* number of packets for each buffer |
143 | windows requests only 40 packets .. so we better do the same | 144 | windows requests only 64 packets .. so we better do the same |
144 | this is what I found out for all alternate numbers there! | 145 | this is what I found out for all alternate numbers there! |
145 | */ | 146 | */ |
146 | #define EM28XX_NUM_PACKETS 40 | 147 | #define EM28XX_NUM_PACKETS 64 |
147 | 148 | ||
148 | #define EM28XX_INTERLACED_DEFAULT 1 | 149 | #define EM28XX_INTERLACED_DEFAULT 1 |
149 | 150 | ||
@@ -411,7 +412,7 @@ struct em28xx_board { | |||
411 | 412 | ||
412 | struct em28xx_input input[MAX_EM28XX_INPUT]; | 413 | struct em28xx_input input[MAX_EM28XX_INPUT]; |
413 | struct em28xx_input radio; | 414 | struct em28xx_input radio; |
414 | struct ir_scancode_table *ir_codes; | 415 | char *ir_codes; |
415 | }; | 416 | }; |
416 | 417 | ||
417 | struct em28xx_eeprom { | 418 | struct em28xx_eeprom { |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index e6c23d509862..a5cfc76b40b7 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -1713,7 +1713,7 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) | |||
1713 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 1713 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
1714 | return -EFAULT; | 1714 | return -EFAULT; |
1715 | 1715 | ||
1716 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | 1716 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { |
1717 | if (ctrl.id == s->qctrl[i].id) { | 1717 | if (ctrl.id == s->qctrl[i].id) { |
1718 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) | 1718 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) |
1719 | return -EINVAL; | 1719 | return -EINVAL; |
@@ -1723,7 +1723,9 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) | |||
1723 | ctrl.value -= ctrl.value % s->qctrl[i].step; | 1723 | ctrl.value -= ctrl.value % s->qctrl[i].step; |
1724 | break; | 1724 | break; |
1725 | } | 1725 | } |
1726 | 1726 | } | |
1727 | if (i == ARRAY_SIZE(s->qctrl)) | ||
1728 | return -EINVAL; | ||
1727 | if ((err = s->set_ctrl(cam, &ctrl))) | 1729 | if ((err = s->set_ctrl(cam, &ctrl))) |
1728 | return err; | 1730 | return err; |
1729 | 1731 | ||
diff --git a/drivers/media/video/font.h b/drivers/media/video/font.h deleted file mode 100644 index 8b1fecc37599..000000000000 --- a/drivers/media/video/font.h +++ /dev/null | |||
@@ -1,407 +0,0 @@ | |||
1 | static unsigned char rom8x16_bits[] = { | ||
2 | /* Character 0 (0x30): | ||
3 | ht=16, width=8 | ||
4 | +--------+ | ||
5 | | | | ||
6 | | | | ||
7 | | ***** | | ||
8 | |** ** | | ||
9 | |** ** | | ||
10 | |** *** | | ||
11 | |** **** | | ||
12 | |**** ** | | ||
13 | |*** ** | | ||
14 | |** ** | | ||
15 | |** ** | | ||
16 | | ***** | | ||
17 | | | | ||
18 | | | | ||
19 | | | | ||
20 | | | | ||
21 | +--------+ */ | ||
22 | 0x00, | ||
23 | 0x00, | ||
24 | 0x7c, | ||
25 | 0xc6, | ||
26 | 0xc6, | ||
27 | 0xce, | ||
28 | 0xde, | ||
29 | 0xf6, | ||
30 | 0xe6, | ||
31 | 0xc6, | ||
32 | 0xc6, | ||
33 | 0x7c, | ||
34 | 0x00, | ||
35 | 0x00, | ||
36 | 0x00, | ||
37 | 0x00, | ||
38 | |||
39 | /* Character 1 (0x31): | ||
40 | ht=16, width=8 | ||
41 | +--------+ | ||
42 | | | | ||
43 | | | | ||
44 | | ** | | ||
45 | | **** | | ||
46 | | ** | | ||
47 | | ** | | ||
48 | | ** | | ||
49 | | ** | | ||
50 | | ** | | ||
51 | | ** | | ||
52 | | ** | | ||
53 | | ****** | | ||
54 | | | | ||
55 | | | | ||
56 | | | | ||
57 | | | | ||
58 | +--------+ */ | ||
59 | 0x00, | ||
60 | 0x00, | ||
61 | 0x18, | ||
62 | 0x78, | ||
63 | 0x18, | ||
64 | 0x18, | ||
65 | 0x18, | ||
66 | 0x18, | ||
67 | 0x18, | ||
68 | 0x18, | ||
69 | 0x18, | ||
70 | 0x7e, | ||
71 | 0x00, | ||
72 | 0x00, | ||
73 | 0x00, | ||
74 | 0x00, | ||
75 | |||
76 | /* Character 2 (0x32): | ||
77 | ht=16, width=8 | ||
78 | +--------+ | ||
79 | | | | ||
80 | | | | ||
81 | | ***** | | ||
82 | |** ** | | ||
83 | |** ** | | ||
84 | | ** | | ||
85 | | ** | | ||
86 | | ** | | ||
87 | | ** | | ||
88 | | ** | | ||
89 | |** ** | | ||
90 | |******* | | ||
91 | | | | ||
92 | | | | ||
93 | | | | ||
94 | | | | ||
95 | +--------+ */ | ||
96 | 0x00, | ||
97 | 0x00, | ||
98 | 0x7c, | ||
99 | 0xc6, | ||
100 | 0xc6, | ||
101 | 0x06, | ||
102 | 0x0c, | ||
103 | 0x18, | ||
104 | 0x30, | ||
105 | 0x60, | ||
106 | 0xc6, | ||
107 | 0xfe, | ||
108 | 0x00, | ||
109 | 0x00, | ||
110 | 0x00, | ||
111 | 0x00, | ||
112 | |||
113 | /* Character 3 (0x33): | ||
114 | ht=16, width=8 | ||
115 | +--------+ | ||
116 | | | | ||
117 | | | | ||
118 | | ***** | | ||
119 | |** ** | | ||
120 | | ** | | ||
121 | | ** | | ||
122 | | **** | | ||
123 | | ** | | ||
124 | | ** | | ||
125 | | ** | | ||
126 | |** ** | | ||
127 | | ***** | | ||
128 | | | | ||
129 | | | | ||
130 | | | | ||
131 | | | | ||
132 | +--------+ */ | ||
133 | 0x00, | ||
134 | 0x00, | ||
135 | 0x7c, | ||
136 | 0xc6, | ||
137 | 0x06, | ||
138 | 0x06, | ||
139 | 0x3c, | ||
140 | 0x06, | ||
141 | 0x06, | ||
142 | 0x06, | ||
143 | 0xc6, | ||
144 | 0x7c, | ||
145 | 0x00, | ||
146 | 0x00, | ||
147 | 0x00, | ||
148 | 0x00, | ||
149 | |||
150 | /* Character 4 (0x34): | ||
151 | ht=16, width=8 | ||
152 | +--------+ | ||
153 | | | | ||
154 | | | | ||
155 | | ** | | ||
156 | | *** | | ||
157 | | **** | | ||
158 | | ** ** | | ||
159 | |** ** | | ||
160 | |** ** | | ||
161 | |******* | | ||
162 | | ** | | ||
163 | | ** | | ||
164 | | **** | | ||
165 | | | | ||
166 | | | | ||
167 | | | | ||
168 | | | | ||
169 | +--------+ */ | ||
170 | 0x00, | ||
171 | 0x00, | ||
172 | 0x0c, | ||
173 | 0x1c, | ||
174 | 0x3c, | ||
175 | 0x6c, | ||
176 | 0xcc, | ||
177 | 0xcc, | ||
178 | 0xfe, | ||
179 | 0x0c, | ||
180 | 0x0c, | ||
181 | 0x1e, | ||
182 | 0x00, | ||
183 | 0x00, | ||
184 | 0x00, | ||
185 | 0x00, | ||
186 | |||
187 | /* Character 5 (0x35): | ||
188 | ht=16, width=8 | ||
189 | +--------+ | ||
190 | | | | ||
191 | | | | ||
192 | |******* | | ||
193 | |** | | ||
194 | |** | | ||
195 | |** | | ||
196 | |****** | | ||
197 | | ** | | ||
198 | | ** | | ||
199 | | ** | | ||
200 | |** ** | | ||
201 | | ***** | | ||
202 | | | | ||
203 | | | | ||
204 | | | | ||
205 | | | | ||
206 | +--------+ */ | ||
207 | 0x00, | ||
208 | 0x00, | ||
209 | 0xfe, | ||
210 | 0xc0, | ||
211 | 0xc0, | ||
212 | 0xc0, | ||
213 | 0xfc, | ||
214 | 0x06, | ||
215 | 0x06, | ||
216 | 0x06, | ||
217 | 0xc6, | ||
218 | 0x7c, | ||
219 | 0x00, | ||
220 | 0x00, | ||
221 | 0x00, | ||
222 | 0x00, | ||
223 | |||
224 | /* Character 6 (0x36): | ||
225 | ht=16, width=8 | ||
226 | +--------+ | ||
227 | | | | ||
228 | | | | ||
229 | | ***** | | ||
230 | |** ** | | ||
231 | |** | | ||
232 | |** | | ||
233 | |****** | | ||
234 | |** ** | | ||
235 | |** ** | | ||
236 | |** ** | | ||
237 | |** ** | | ||
238 | | ***** | | ||
239 | | | | ||
240 | | | | ||
241 | | | | ||
242 | | | | ||
243 | +--------+ */ | ||
244 | 0x00, | ||
245 | 0x00, | ||
246 | 0x7c, | ||
247 | 0xc6, | ||
248 | 0xc0, | ||
249 | 0xc0, | ||
250 | 0xfc, | ||
251 | 0xc6, | ||
252 | 0xc6, | ||
253 | 0xc6, | ||
254 | 0xc6, | ||
255 | 0x7c, | ||
256 | 0x00, | ||
257 | 0x00, | ||
258 | 0x00, | ||
259 | 0x00, | ||
260 | |||
261 | /* Character 7 (0x37): | ||
262 | ht=16, width=8 | ||
263 | +--------+ | ||
264 | | | | ||
265 | | | | ||
266 | |******* | | ||
267 | |** ** | | ||
268 | | ** | | ||
269 | | ** | | ||
270 | | ** | | ||
271 | | ** | | ||
272 | | ** | | ||
273 | | ** | | ||
274 | | ** | | ||
275 | | ** | | ||
276 | | | | ||
277 | | | | ||
278 | | | | ||
279 | | | | ||
280 | +--------+ */ | ||
281 | 0x00, | ||
282 | 0x00, | ||
283 | 0xfe, | ||
284 | 0xc6, | ||
285 | 0x06, | ||
286 | 0x0c, | ||
287 | 0x18, | ||
288 | 0x30, | ||
289 | 0x30, | ||
290 | 0x30, | ||
291 | 0x30, | ||
292 | 0x30, | ||
293 | 0x00, | ||
294 | 0x00, | ||
295 | 0x00, | ||
296 | 0x00, | ||
297 | |||
298 | /* Character 8 (0x38): | ||
299 | ht=16, width=8 | ||
300 | +--------+ | ||
301 | | | | ||
302 | | | | ||
303 | | ***** | | ||
304 | |** ** | | ||
305 | |** ** | | ||
306 | |** ** | | ||
307 | | ***** | | ||
308 | |** ** | | ||
309 | |** ** | | ||
310 | |** ** | | ||
311 | |** ** | | ||
312 | | ***** | | ||
313 | | | | ||
314 | | | | ||
315 | | | | ||
316 | | | | ||
317 | +--------+ */ | ||
318 | 0x00, | ||
319 | 0x00, | ||
320 | 0x7c, | ||
321 | 0xc6, | ||
322 | 0xc6, | ||
323 | 0xc6, | ||
324 | 0x7c, | ||
325 | 0xc6, | ||
326 | 0xc6, | ||
327 | 0xc6, | ||
328 | 0xc6, | ||
329 | 0x7c, | ||
330 | 0x00, | ||
331 | 0x00, | ||
332 | 0x00, | ||
333 | 0x00, | ||
334 | |||
335 | /* Character 9 (0x39): | ||
336 | ht=16, width=8 | ||
337 | +--------+ | ||
338 | | | | ||
339 | | | | ||
340 | | ***** | | ||
341 | |** ** | | ||
342 | |** ** | | ||
343 | |** ** | | ||
344 | |** ** | | ||
345 | | ****** | | ||
346 | | ** | | ||
347 | | ** | | ||
348 | |** ** | | ||
349 | | ***** | | ||
350 | | | | ||
351 | | | | ||
352 | | | | ||
353 | | | | ||
354 | +--------+ */ | ||
355 | 0x00, | ||
356 | 0x00, | ||
357 | 0x7c, | ||
358 | 0xc6, | ||
359 | 0xc6, | ||
360 | 0xc6, | ||
361 | 0xc6, | ||
362 | 0x7e, | ||
363 | 0x06, | ||
364 | 0x06, | ||
365 | 0xc6, | ||
366 | 0x7c, | ||
367 | 0x00, | ||
368 | 0x00, | ||
369 | 0x00, | ||
370 | 0x00, | ||
371 | /* Character : (0x3a): | ||
372 | ht=16, width=8 | ||
373 | +--------+ | ||
374 | | | | ||
375 | | | | ||
376 | | | | ||
377 | | | | ||
378 | | | | ||
379 | | ** | | ||
380 | | ** | | ||
381 | | | | ||
382 | | | | ||
383 | | ** | | ||
384 | | ** | | ||
385 | | | | ||
386 | | | | ||
387 | | | | ||
388 | | | | ||
389 | | | | ||
390 | +--------+ */ | ||
391 | 0x00, | ||
392 | 0x00, | ||
393 | 0x00, | ||
394 | 0x00, | ||
395 | 0x00, | ||
396 | 0x0c, | ||
397 | 0x0c, | ||
398 | 0x00, | ||
399 | 0x00, | ||
400 | 0x0c, | ||
401 | 0x0c, | ||
402 | 0x00, | ||
403 | 0x00, | ||
404 | 0x00, | ||
405 | 0x00, | ||
406 | 0x00, | ||
407 | }; | ||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index e0060c1f0544..5d920e584de7 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -172,12 +172,6 @@ config USB_GSPCA_SN9C20X | |||
172 | To compile this driver as a module, choose M here: the | 172 | To compile this driver as a module, choose M here: the |
173 | module will be called gspca_sn9c20x. | 173 | module will be called gspca_sn9c20x. |
174 | 174 | ||
175 | config USB_GSPCA_SN9C20X_EVDEV | ||
176 | bool "Enable evdev support" | ||
177 | depends on USB_GSPCA_SN9C20X && INPUT | ||
178 | ---help--- | ||
179 | Say Y here in order to enable evdev support for sn9c20x webcam button. | ||
180 | |||
181 | config USB_GSPCA_SONIXB | 175 | config USB_GSPCA_SONIXB |
182 | tristate "SONIX Bayer USB Camera Driver" | 176 | tristate "SONIX Bayer USB Camera Driver" |
183 | depends on VIDEO_V4L2 && USB_GSPCA | 177 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 82945ed5cbe5..58b696f455be 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c | |||
@@ -374,7 +374,7 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | |||
374 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); | 374 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); |
375 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); | 375 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); |
376 | 376 | ||
377 | static struct ctrl sd_ctrls[] = { | 377 | static const struct ctrl sd_ctrls[] = { |
378 | { | 378 | { |
379 | { | 379 | { |
380 | .id = V4L2_CID_BRIGHTNESS, | 380 | .id = V4L2_CID_BRIGHTNESS, |
@@ -861,7 +861,7 @@ static int save_camera_state(struct gspca_dev *gspca_dev) | |||
861 | return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); | 861 | return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); |
862 | } | 862 | } |
863 | 863 | ||
864 | int command_setformat(struct gspca_dev *gspca_dev) | 864 | static int command_setformat(struct gspca_dev *gspca_dev) |
865 | { | 865 | { |
866 | struct sd *sd = (struct sd *) gspca_dev; | 866 | struct sd *sd = (struct sd *) gspca_dev; |
867 | int ret; | 867 | int ret; |
@@ -878,7 +878,7 @@ int command_setformat(struct gspca_dev *gspca_dev) | |||
878 | sd->params.roi.rowStart, sd->params.roi.rowEnd); | 878 | sd->params.roi.rowStart, sd->params.roi.rowEnd); |
879 | } | 879 | } |
880 | 880 | ||
881 | int command_setcolourparams(struct gspca_dev *gspca_dev) | 881 | static int command_setcolourparams(struct gspca_dev *gspca_dev) |
882 | { | 882 | { |
883 | struct sd *sd = (struct sd *) gspca_dev; | 883 | struct sd *sd = (struct sd *) gspca_dev; |
884 | return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, | 884 | return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, |
@@ -887,7 +887,7 @@ int command_setcolourparams(struct gspca_dev *gspca_dev) | |||
887 | sd->params.colourParams.saturation, 0); | 887 | sd->params.colourParams.saturation, 0); |
888 | } | 888 | } |
889 | 889 | ||
890 | int command_setapcor(struct gspca_dev *gspca_dev) | 890 | static int command_setapcor(struct gspca_dev *gspca_dev) |
891 | { | 891 | { |
892 | struct sd *sd = (struct sd *) gspca_dev; | 892 | struct sd *sd = (struct sd *) gspca_dev; |
893 | return do_command(gspca_dev, CPIA_COMMAND_SetApcor, | 893 | return do_command(gspca_dev, CPIA_COMMAND_SetApcor, |
@@ -897,7 +897,7 @@ int command_setapcor(struct gspca_dev *gspca_dev) | |||
897 | sd->params.apcor.gain8); | 897 | sd->params.apcor.gain8); |
898 | } | 898 | } |
899 | 899 | ||
900 | int command_setvloffset(struct gspca_dev *gspca_dev) | 900 | static int command_setvloffset(struct gspca_dev *gspca_dev) |
901 | { | 901 | { |
902 | struct sd *sd = (struct sd *) gspca_dev; | 902 | struct sd *sd = (struct sd *) gspca_dev; |
903 | return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, | 903 | return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, |
@@ -907,7 +907,7 @@ int command_setvloffset(struct gspca_dev *gspca_dev) | |||
907 | sd->params.vlOffset.gain8); | 907 | sd->params.vlOffset.gain8); |
908 | } | 908 | } |
909 | 909 | ||
910 | int command_setexposure(struct gspca_dev *gspca_dev) | 910 | static int command_setexposure(struct gspca_dev *gspca_dev) |
911 | { | 911 | { |
912 | struct sd *sd = (struct sd *) gspca_dev; | 912 | struct sd *sd = (struct sd *) gspca_dev; |
913 | int ret; | 913 | int ret; |
@@ -943,7 +943,7 @@ int command_setexposure(struct gspca_dev *gspca_dev) | |||
943 | return ret; | 943 | return ret; |
944 | } | 944 | } |
945 | 945 | ||
946 | int command_setcolourbalance(struct gspca_dev *gspca_dev) | 946 | static int command_setcolourbalance(struct gspca_dev *gspca_dev) |
947 | { | 947 | { |
948 | struct sd *sd = (struct sd *) gspca_dev; | 948 | struct sd *sd = (struct sd *) gspca_dev; |
949 | 949 | ||
@@ -973,7 +973,7 @@ int command_setcolourbalance(struct gspca_dev *gspca_dev) | |||
973 | return -EINVAL; | 973 | return -EINVAL; |
974 | } | 974 | } |
975 | 975 | ||
976 | int command_setcompressiontarget(struct gspca_dev *gspca_dev) | 976 | static int command_setcompressiontarget(struct gspca_dev *gspca_dev) |
977 | { | 977 | { |
978 | struct sd *sd = (struct sd *) gspca_dev; | 978 | struct sd *sd = (struct sd *) gspca_dev; |
979 | 979 | ||
@@ -983,7 +983,7 @@ int command_setcompressiontarget(struct gspca_dev *gspca_dev) | |||
983 | sd->params.compressionTarget.targetQ, 0); | 983 | sd->params.compressionTarget.targetQ, 0); |
984 | } | 984 | } |
985 | 985 | ||
986 | int command_setyuvtresh(struct gspca_dev *gspca_dev) | 986 | static int command_setyuvtresh(struct gspca_dev *gspca_dev) |
987 | { | 987 | { |
988 | struct sd *sd = (struct sd *) gspca_dev; | 988 | struct sd *sd = (struct sd *) gspca_dev; |
989 | 989 | ||
@@ -992,7 +992,7 @@ int command_setyuvtresh(struct gspca_dev *gspca_dev) | |||
992 | sd->params.yuvThreshold.uvThreshold, 0, 0); | 992 | sd->params.yuvThreshold.uvThreshold, 0, 0); |
993 | } | 993 | } |
994 | 994 | ||
995 | int command_setcompressionparams(struct gspca_dev *gspca_dev) | 995 | static int command_setcompressionparams(struct gspca_dev *gspca_dev) |
996 | { | 996 | { |
997 | struct sd *sd = (struct sd *) gspca_dev; | 997 | struct sd *sd = (struct sd *) gspca_dev; |
998 | 998 | ||
@@ -1009,7 +1009,7 @@ int command_setcompressionparams(struct gspca_dev *gspca_dev) | |||
1009 | sd->params.compressionParams.decimationThreshMod); | 1009 | sd->params.compressionParams.decimationThreshMod); |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | int command_setcompression(struct gspca_dev *gspca_dev) | 1012 | static int command_setcompression(struct gspca_dev *gspca_dev) |
1013 | { | 1013 | { |
1014 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
1015 | 1015 | ||
@@ -1018,7 +1018,7 @@ int command_setcompression(struct gspca_dev *gspca_dev) | |||
1018 | sd->params.compression.decimation, 0, 0); | 1018 | sd->params.compression.decimation, 0, 0); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | int command_setsensorfps(struct gspca_dev *gspca_dev) | 1021 | static int command_setsensorfps(struct gspca_dev *gspca_dev) |
1022 | { | 1022 | { |
1023 | struct sd *sd = (struct sd *) gspca_dev; | 1023 | struct sd *sd = (struct sd *) gspca_dev; |
1024 | 1024 | ||
@@ -1027,7 +1027,7 @@ int command_setsensorfps(struct gspca_dev *gspca_dev) | |||
1027 | sd->params.sensorFps.baserate, 0, 0); | 1027 | sd->params.sensorFps.baserate, 0, 0); |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | int command_setflickerctrl(struct gspca_dev *gspca_dev) | 1030 | static int command_setflickerctrl(struct gspca_dev *gspca_dev) |
1031 | { | 1031 | { |
1032 | struct sd *sd = (struct sd *) gspca_dev; | 1032 | struct sd *sd = (struct sd *) gspca_dev; |
1033 | 1033 | ||
@@ -1038,7 +1038,7 @@ int command_setflickerctrl(struct gspca_dev *gspca_dev) | |||
1038 | 0); | 1038 | 0); |
1039 | } | 1039 | } |
1040 | 1040 | ||
1041 | int command_setecptiming(struct gspca_dev *gspca_dev) | 1041 | static int command_setecptiming(struct gspca_dev *gspca_dev) |
1042 | { | 1042 | { |
1043 | struct sd *sd = (struct sd *) gspca_dev; | 1043 | struct sd *sd = (struct sd *) gspca_dev; |
1044 | 1044 | ||
@@ -1046,12 +1046,12 @@ int command_setecptiming(struct gspca_dev *gspca_dev) | |||
1046 | sd->params.ecpTiming, 0, 0, 0); | 1046 | sd->params.ecpTiming, 0, 0, 0); |
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | int command_pause(struct gspca_dev *gspca_dev) | 1049 | static int command_pause(struct gspca_dev *gspca_dev) |
1050 | { | 1050 | { |
1051 | return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); | 1051 | return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | int command_resume(struct gspca_dev *gspca_dev) | 1054 | static int command_resume(struct gspca_dev *gspca_dev) |
1055 | { | 1055 | { |
1056 | struct sd *sd = (struct sd *) gspca_dev; | 1056 | struct sd *sd = (struct sd *) gspca_dev; |
1057 | 1057 | ||
@@ -1059,7 +1059,8 @@ int command_resume(struct gspca_dev *gspca_dev) | |||
1059 | 0, sd->params.streamStartLine, 0, 0); | 1059 | 0, sd->params.streamStartLine, 0, 0); |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | int command_setlights(struct gspca_dev *gspca_dev) | 1062 | #if 0 /* Currently unused */ |
1063 | static int command_setlights(struct gspca_dev *gspca_dev) | ||
1063 | { | 1064 | { |
1064 | struct sd *sd = (struct sd *) gspca_dev; | 1065 | struct sd *sd = (struct sd *) gspca_dev; |
1065 | int ret, p1, p2; | 1066 | int ret, p1, p2; |
@@ -1078,6 +1079,7 @@ int command_setlights(struct gspca_dev *gspca_dev) | |||
1078 | return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, | 1079 | return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, |
1079 | p1 | p2 | 0xE0, 0); | 1080 | p1 | p2 | 0xE0, 0); |
1080 | } | 1081 | } |
1082 | #endif | ||
1081 | 1083 | ||
1082 | static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) | 1084 | static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) |
1083 | { | 1085 | { |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 222af479150b..efe615938783 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Main USB camera driver | 2 | * Main USB camera driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008-2010 Jean-François Moine <http://moinejf.free.fr> |
5 | * | 5 | * |
6 | * Camera button input handling by Márton Németh | 6 | * Camera button input handling by Márton Németh |
7 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | 7 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> |
@@ -35,12 +35,12 @@ | |||
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | #include <asm/page.h> | 36 | #include <asm/page.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/jiffies.h> | 38 | #include <linux/ktime.h> |
39 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
40 | 40 | ||
41 | #include "gspca.h" | 41 | #include "gspca.h" |
42 | 42 | ||
43 | #ifdef CONFIG_INPUT | 43 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
44 | #include <linux/input.h> | 44 | #include <linux/input.h> |
45 | #include <linux/usb/input.h> | 45 | #include <linux/usb/input.h> |
46 | #endif | 46 | #endif |
@@ -51,7 +51,7 @@ | |||
51 | #error "DEF_NURBS too big" | 51 | #error "DEF_NURBS too big" |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 54 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); |
55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
56 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
57 | 57 | ||
@@ -115,7 +115,7 @@ static const struct vm_operations_struct gspca_vm_ops = { | |||
115 | /* | 115 | /* |
116 | * Input and interrupt endpoint handling functions | 116 | * Input and interrupt endpoint handling functions |
117 | */ | 117 | */ |
118 | #ifdef CONFIG_INPUT | 118 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
119 | static void int_irq(struct urb *urb) | 119 | static void int_irq(struct urb *urb) |
120 | { | 120 | { |
121 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | 121 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; |
@@ -199,7 +199,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | |||
199 | void *buffer = NULL; | 199 | void *buffer = NULL; |
200 | int ret = -EINVAL; | 200 | int ret = -EINVAL; |
201 | 201 | ||
202 | buffer_len = ep->wMaxPacketSize; | 202 | buffer_len = le16_to_cpu(ep->wMaxPacketSize); |
203 | interval = ep->bInterval; | 203 | interval = ep->bInterval; |
204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " | 204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " |
205 | "buffer_len=%u, interval=%u", | 205 | "buffer_len=%u, interval=%u", |
@@ -213,7 +213,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | |||
213 | goto error; | 213 | goto error; |
214 | } | 214 | } |
215 | 215 | ||
216 | buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, | 216 | buffer = usb_buffer_alloc(dev, buffer_len, |
217 | GFP_KERNEL, &urb->transfer_dma); | 217 | GFP_KERNEL, &urb->transfer_dma); |
218 | if (!buffer) { | 218 | if (!buffer) { |
219 | ret = -ENOMEM; | 219 | ret = -ENOMEM; |
@@ -280,9 +280,18 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) | |||
280 | } | 280 | } |
281 | } | 281 | } |
282 | #else | 282 | #else |
283 | #define gspca_input_connect(gspca_dev) 0 | 283 | static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) |
284 | #define gspca_input_create_urb(gspca_dev) | 284 | { |
285 | #define gspca_input_destroy_urb(gspca_dev) | 285 | } |
286 | |||
287 | static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev) | ||
288 | { | ||
289 | } | ||
290 | |||
291 | static inline int gspca_input_connect(struct gspca_dev *dev) | ||
292 | { | ||
293 | return 0; | ||
294 | } | ||
286 | #endif | 295 | #endif |
287 | 296 | ||
288 | /* get the current input frame buffer */ | 297 | /* get the current input frame buffer */ |
@@ -442,8 +451,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, | |||
442 | * is not queued, discard the whole frame */ | 451 | * is not queued, discard the whole frame */ |
443 | if (packet_type == FIRST_PACKET) { | 452 | if (packet_type == FIRST_PACKET) { |
444 | frame->data_end = frame->data; | 453 | frame->data_end = frame->data; |
445 | jiffies_to_timeval(get_jiffies_64(), | 454 | frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); |
446 | &frame->v4l2_buf.timestamp); | ||
447 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; | 455 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; |
448 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { | 456 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { |
449 | if (packet_type == LAST_PACKET) | 457 | if (packet_type == LAST_PACKET) |
@@ -605,6 +613,37 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) | |||
605 | } | 613 | } |
606 | } | 614 | } |
607 | 615 | ||
616 | static int gspca_set_alt0(struct gspca_dev *gspca_dev) | ||
617 | { | ||
618 | int ret; | ||
619 | |||
620 | if (gspca_dev->alt == 0) | ||
621 | return 0; | ||
622 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); | ||
623 | if (ret < 0) | ||
624 | PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); | ||
625 | return ret; | ||
626 | } | ||
627 | |||
628 | /* Note: both the queue and the usb locks should be held when calling this */ | ||
629 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | ||
630 | { | ||
631 | gspca_dev->streaming = 0; | ||
632 | if (gspca_dev->present) { | ||
633 | if (gspca_dev->sd_desc->stopN) | ||
634 | gspca_dev->sd_desc->stopN(gspca_dev); | ||
635 | destroy_urbs(gspca_dev); | ||
636 | gspca_input_destroy_urb(gspca_dev); | ||
637 | gspca_set_alt0(gspca_dev); | ||
638 | gspca_input_create_urb(gspca_dev); | ||
639 | } | ||
640 | |||
641 | /* always call stop0 to free the subdriver's resources */ | ||
642 | if (gspca_dev->sd_desc->stop0) | ||
643 | gspca_dev->sd_desc->stop0(gspca_dev); | ||
644 | PDEBUG(D_STREAM, "stream off OK"); | ||
645 | } | ||
646 | |||
608 | /* | 647 | /* |
609 | * look for an input transfer endpoint in an alternate setting | 648 | * look for an input transfer endpoint in an alternate setting |
610 | */ | 649 | */ |
@@ -830,8 +869,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
830 | } | 869 | } |
831 | if (ret >= 0) | 870 | if (ret >= 0) |
832 | break; | 871 | break; |
833 | gspca_dev->streaming = 0; | 872 | gspca_stream_off(gspca_dev); |
834 | destroy_urbs(gspca_dev); | ||
835 | if (ret != -ENOSPC) { | 873 | if (ret != -ENOSPC) { |
836 | PDEBUG(D_ERR|D_STREAM, | 874 | PDEBUG(D_ERR|D_STREAM, |
837 | "usb_submit_urb alt %d err %d", | 875 | "usb_submit_urb alt %d err %d", |
@@ -861,37 +899,6 @@ out: | |||
861 | return ret; | 899 | return ret; |
862 | } | 900 | } |
863 | 901 | ||
864 | static int gspca_set_alt0(struct gspca_dev *gspca_dev) | ||
865 | { | ||
866 | int ret; | ||
867 | |||
868 | if (gspca_dev->alt == 0) | ||
869 | return 0; | ||
870 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); | ||
871 | if (ret < 0) | ||
872 | PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | /* Note: both the queue and the usb locks should be held when calling this */ | ||
877 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | ||
878 | { | ||
879 | gspca_dev->streaming = 0; | ||
880 | if (gspca_dev->present) { | ||
881 | if (gspca_dev->sd_desc->stopN) | ||
882 | gspca_dev->sd_desc->stopN(gspca_dev); | ||
883 | destroy_urbs(gspca_dev); | ||
884 | gspca_input_destroy_urb(gspca_dev); | ||
885 | gspca_set_alt0(gspca_dev); | ||
886 | gspca_input_create_urb(gspca_dev); | ||
887 | } | ||
888 | |||
889 | /* always call stop0 to free the subdriver's resources */ | ||
890 | if (gspca_dev->sd_desc->stop0) | ||
891 | gspca_dev->sd_desc->stop0(gspca_dev); | ||
892 | PDEBUG(D_STREAM, "stream off OK"); | ||
893 | } | ||
894 | |||
895 | static void gspca_set_default_mode(struct gspca_dev *gspca_dev) | 902 | static void gspca_set_default_mode(struct gspca_dev *gspca_dev) |
896 | { | 903 | { |
897 | int i; | 904 | int i; |
@@ -1495,7 +1502,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1495 | struct v4l2_requestbuffers *rb) | 1502 | struct v4l2_requestbuffers *rb) |
1496 | { | 1503 | { |
1497 | struct gspca_dev *gspca_dev = priv; | 1504 | struct gspca_dev *gspca_dev = priv; |
1498 | int i, ret = 0; | 1505 | int i, ret = 0, streaming; |
1499 | 1506 | ||
1500 | switch (rb->memory) { | 1507 | switch (rb->memory) { |
1501 | case GSPCA_MEMORY_READ: /* (internal call) */ | 1508 | case GSPCA_MEMORY_READ: /* (internal call) */ |
@@ -1530,7 +1537,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1530 | } | 1537 | } |
1531 | 1538 | ||
1532 | /* stop streaming */ | 1539 | /* stop streaming */ |
1533 | if (gspca_dev->streaming) { | 1540 | streaming = gspca_dev->streaming; |
1541 | if (streaming) { | ||
1534 | mutex_lock(&gspca_dev->usb_lock); | 1542 | mutex_lock(&gspca_dev->usb_lock); |
1535 | gspca_dev->usb_err = 0; | 1543 | gspca_dev->usb_err = 0; |
1536 | gspca_stream_off(gspca_dev); | 1544 | gspca_stream_off(gspca_dev); |
@@ -1549,6 +1557,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1549 | if (ret == 0) { | 1557 | if (ret == 0) { |
1550 | rb->count = gspca_dev->nframes; | 1558 | rb->count = gspca_dev->nframes; |
1551 | gspca_dev->capt_file = file; | 1559 | gspca_dev->capt_file = file; |
1560 | if (streaming) | ||
1561 | ret = gspca_init_transfer(gspca_dev); | ||
1552 | } | 1562 | } |
1553 | out: | 1563 | out: |
1554 | mutex_unlock(&gspca_dev->queue_lock); | 1564 | mutex_unlock(&gspca_dev->queue_lock); |
@@ -1582,6 +1592,12 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1582 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1592 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1583 | return -ERESTARTSYS; | 1593 | return -ERESTARTSYS; |
1584 | 1594 | ||
1595 | /* check the capture file */ | ||
1596 | if (gspca_dev->capt_file != file) { | ||
1597 | ret = -EBUSY; | ||
1598 | goto out; | ||
1599 | } | ||
1600 | |||
1585 | if (gspca_dev->nframes == 0 | 1601 | if (gspca_dev->nframes == 0 |
1586 | || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { | 1602 | || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { |
1587 | ret = -EINVAL; | 1603 | ret = -EINVAL; |
@@ -1619,6 +1635,12 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1619 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1635 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1620 | return -ERESTARTSYS; | 1636 | return -ERESTARTSYS; |
1621 | 1637 | ||
1638 | /* check the capture file */ | ||
1639 | if (gspca_dev->capt_file != file) { | ||
1640 | ret = -EBUSY; | ||
1641 | goto out; | ||
1642 | } | ||
1643 | |||
1622 | /* stop streaming */ | 1644 | /* stop streaming */ |
1623 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { | 1645 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { |
1624 | ret = -ERESTARTSYS; | 1646 | ret = -ERESTARTSYS; |
@@ -2124,7 +2146,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
2124 | } | 2146 | } |
2125 | 2147 | ||
2126 | /* get a frame */ | 2148 | /* get a frame */ |
2127 | jiffies_to_timeval(get_jiffies_64(), ×tamp); | 2149 | timestamp = ktime_to_timeval(ktime_get()); |
2128 | timestamp.tv_sec--; | 2150 | timestamp.tv_sec--; |
2129 | n = 2; | 2151 | n = 2; |
2130 | for (;;) { | 2152 | for (;;) { |
@@ -2315,7 +2337,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2315 | 2337 | ||
2316 | return 0; | 2338 | return 0; |
2317 | out: | 2339 | out: |
2318 | #ifdef CONFIG_INPUT | 2340 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
2319 | if (gspca_dev->input_dev) | 2341 | if (gspca_dev->input_dev) |
2320 | input_unregister_device(gspca_dev->input_dev); | 2342 | input_unregister_device(gspca_dev->input_dev); |
2321 | #endif | 2343 | #endif |
@@ -2334,7 +2356,7 @@ EXPORT_SYMBOL(gspca_dev_probe); | |||
2334 | void gspca_disconnect(struct usb_interface *intf) | 2356 | void gspca_disconnect(struct usb_interface *intf) |
2335 | { | 2357 | { |
2336 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2358 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2337 | #ifdef CONFIG_INPUT | 2359 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
2338 | struct input_dev *input_dev; | 2360 | struct input_dev *input_dev; |
2339 | #endif | 2361 | #endif |
2340 | 2362 | ||
@@ -2348,7 +2370,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2348 | wake_up_interruptible(&gspca_dev->wq); | 2370 | wake_up_interruptible(&gspca_dev->wq); |
2349 | } | 2371 | } |
2350 | 2372 | ||
2351 | #ifdef CONFIG_INPUT | 2373 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
2352 | gspca_input_destroy_urb(gspca_dev); | 2374 | gspca_input_destroy_urb(gspca_dev); |
2353 | input_dev = gspca_dev->input_dev; | 2375 | input_dev = gspca_dev->input_dev; |
2354 | if (input_dev) { | 2376 | if (input_dev) { |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 8bb242fb79de..8b963dfae861 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -130,7 +130,7 @@ struct sd_desc { | |||
130 | cam_reg_op get_register; | 130 | cam_reg_op get_register; |
131 | #endif | 131 | #endif |
132 | cam_ident_op get_chip_ident; | 132 | cam_ident_op get_chip_ident; |
133 | #ifdef CONFIG_INPUT | 133 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
134 | cam_int_pkt_op int_pkt_scan; | 134 | cam_int_pkt_op int_pkt_scan; |
135 | /* other_input makes the gspca core create gspca_dev->input even when | 135 | /* other_input makes the gspca core create gspca_dev->input even when |
136 | int_pkt_scan is NULL, for cams with non interrupt driven buttons */ | 136 | int_pkt_scan is NULL, for cams with non interrupt driven buttons */ |
@@ -158,7 +158,7 @@ struct gspca_dev { | |||
158 | struct module *module; /* subdriver handling the device */ | 158 | struct module *module; /* subdriver handling the device */ |
159 | struct usb_device *dev; | 159 | struct usb_device *dev; |
160 | struct file *capt_file; /* file doing video capture */ | 160 | struct file *capt_file; /* file doing video capture */ |
161 | #ifdef CONFIG_INPUT | 161 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
162 | struct input_dev *input_dev; | 162 | struct input_dev *input_dev; |
163 | char phys[64]; /* physical device path */ | 163 | char phys[64]; /* physical device path */ |
164 | #endif | 164 | #endif |
@@ -171,7 +171,7 @@ struct gspca_dev { | |||
171 | #define USB_BUF_SZ 64 | 171 | #define USB_BUF_SZ 64 |
172 | __u8 *usb_buf; /* buffer for USB exchanges */ | 172 | __u8 *usb_buf; /* buffer for USB exchanges */ |
173 | struct urb *urb[MAX_NURBS]; | 173 | struct urb *urb[MAX_NURBS]; |
174 | #ifdef CONFIG_INPUT | 174 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
175 | struct urb *int_urb; | 175 | struct urb *int_urb; |
176 | #endif | 176 | #endif |
177 | 177 | ||
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 957e05e2d08f..dc1e4efe30fb 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -10,8 +10,8 @@ | |||
10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ | 10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ |
11 | * | 11 | * |
12 | * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr | 12 | * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr |
13 | * PS3 Eye camera, brightness, contrast, hue, AWB control added | 13 | * PS3 Eye camera - brightness, contrast, awb, agc, aec controls |
14 | * by Max Thrun <bear24rw@gmail.com> | 14 | * added by Max Thrun <bear24rw@gmail.com> |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -60,15 +60,13 @@ struct sd { | |||
60 | u8 contrast; | 60 | u8 contrast; |
61 | u8 gain; | 61 | u8 gain; |
62 | u8 exposure; | 62 | u8 exposure; |
63 | u8 redblc; | 63 | u8 agc; |
64 | u8 blueblc; | ||
65 | u8 hue; | ||
66 | u8 autogain; | ||
67 | u8 awb; | 64 | u8 awb; |
65 | u8 aec; | ||
68 | s8 sharpness; | 66 | s8 sharpness; |
69 | u8 hflip; | 67 | u8 hflip; |
70 | u8 vflip; | 68 | u8 vflip; |
71 | 69 | u8 freqfltr; | |
72 | }; | 70 | }; |
73 | 71 | ||
74 | /* V4L2 controls supported by the driver */ | 72 | /* V4L2 controls supported by the driver */ |
@@ -76,197 +74,183 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | |||
76 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 74 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
77 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 75 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
78 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 76 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
79 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val); | 77 | static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val); |
80 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val); | 78 | static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val); |
81 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 79 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
86 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 80 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
87 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | 81 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); |
88 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 82 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
89 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 83 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
90 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 84 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
91 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
92 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
93 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); | 85 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); |
94 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); | 86 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); |
87 | static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val); | ||
88 | static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val); | ||
95 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
96 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 90 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
97 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 91 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
98 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 92 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
93 | static int sd_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val); | ||
94 | static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val); | ||
95 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
96 | struct v4l2_querymenu *menu); | ||
99 | 97 | ||
100 | static const struct ctrl sd_ctrls[] = { | 98 | static const struct ctrl sd_ctrls[] = { |
101 | { /* 0 */ | 99 | { /* 0 */ |
102 | { | 100 | { |
103 | .id = V4L2_CID_BRIGHTNESS, | 101 | .id = V4L2_CID_BRIGHTNESS, |
104 | .type = V4L2_CTRL_TYPE_INTEGER, | 102 | .type = V4L2_CTRL_TYPE_INTEGER, |
105 | .name = "Brightness", | 103 | .name = "Brightness", |
106 | .minimum = 0, | 104 | .minimum = 0, |
107 | .maximum = 255, | 105 | .maximum = 255, |
108 | .step = 1, | 106 | .step = 1, |
109 | #define BRIGHTNESS_DEF 20 | 107 | #define BRIGHTNESS_DEF 0 |
110 | .default_value = BRIGHTNESS_DEF, | 108 | .default_value = BRIGHTNESS_DEF, |
109 | }, | ||
110 | .set = sd_setbrightness, | ||
111 | .get = sd_getbrightness, | ||
111 | }, | 112 | }, |
112 | .set = sd_setbrightness, | 113 | { /* 1 */ |
113 | .get = sd_getbrightness, | 114 | { |
114 | }, | 115 | .id = V4L2_CID_CONTRAST, |
115 | { /* 1 */ | 116 | .type = V4L2_CTRL_TYPE_INTEGER, |
116 | { | 117 | .name = "Contrast", |
117 | .id = V4L2_CID_CONTRAST, | 118 | .minimum = 0, |
118 | .type = V4L2_CTRL_TYPE_INTEGER, | 119 | .maximum = 255, |
119 | .name = "Contrast", | 120 | .step = 1, |
120 | .minimum = 0, | 121 | #define CONTRAST_DEF 32 |
121 | .maximum = 255, | 122 | .default_value = CONTRAST_DEF, |
122 | .step = 1, | 123 | }, |
123 | #define CONTRAST_DEF 37 | 124 | .set = sd_setcontrast, |
124 | .default_value = CONTRAST_DEF, | 125 | .get = sd_getcontrast, |
125 | }, | 126 | }, |
126 | .set = sd_setcontrast, | 127 | { /* 2 */ |
127 | .get = sd_getcontrast, | 128 | { |
128 | }, | 129 | .id = V4L2_CID_GAIN, |
129 | { /* 2 */ | 130 | .type = V4L2_CTRL_TYPE_INTEGER, |
130 | { | 131 | .name = "Main Gain", |
131 | .id = V4L2_CID_GAIN, | 132 | .minimum = 0, |
132 | .type = V4L2_CTRL_TYPE_INTEGER, | 133 | .maximum = 63, |
133 | .name = "Main Gain", | 134 | .step = 1, |
134 | .minimum = 0, | ||
135 | .maximum = 63, | ||
136 | .step = 1, | ||
137 | #define GAIN_DEF 20 | 135 | #define GAIN_DEF 20 |
138 | .default_value = GAIN_DEF, | 136 | .default_value = GAIN_DEF, |
137 | }, | ||
138 | .set = sd_setgain, | ||
139 | .get = sd_getgain, | ||
139 | }, | 140 | }, |
140 | .set = sd_setgain, | 141 | { /* 3 */ |
141 | .get = sd_getgain, | 142 | { |
142 | }, | 143 | .id = V4L2_CID_EXPOSURE, |
143 | { /* 3 */ | 144 | .type = V4L2_CTRL_TYPE_INTEGER, |
144 | { | 145 | .name = "Exposure", |
145 | .id = V4L2_CID_EXPOSURE, | 146 | .minimum = 0, |
146 | .type = V4L2_CTRL_TYPE_INTEGER, | 147 | .maximum = 255, |
147 | .name = "Exposure", | 148 | .step = 1, |
148 | .minimum = 0, | ||
149 | .maximum = 255, | ||
150 | .step = 1, | ||
151 | #define EXPO_DEF 120 | 149 | #define EXPO_DEF 120 |
152 | .default_value = EXPO_DEF, | 150 | .default_value = EXPO_DEF, |
153 | }, | 151 | }, |
154 | .set = sd_setexposure, | 152 | .set = sd_setexposure, |
155 | .get = sd_getexposure, | 153 | .get = sd_getexposure, |
156 | }, | ||
157 | { /* 4 */ | ||
158 | { | ||
159 | .id = V4L2_CID_RED_BALANCE, | ||
160 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
161 | .name = "Red Balance", | ||
162 | .minimum = 0, | ||
163 | .maximum = 255, | ||
164 | .step = 1, | ||
165 | #define RED_BALANCE_DEF 128 | ||
166 | .default_value = RED_BALANCE_DEF, | ||
167 | }, | 154 | }, |
168 | .set = sd_setredblc, | 155 | { /* 4 */ |
169 | .get = sd_getredblc, | 156 | { |
170 | }, | 157 | .id = V4L2_CID_AUTOGAIN, |
171 | { /* 5 */ | 158 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
172 | { | 159 | .name = "Auto Gain", |
173 | .id = V4L2_CID_BLUE_BALANCE, | 160 | .minimum = 0, |
174 | .type = V4L2_CTRL_TYPE_INTEGER, | 161 | .maximum = 1, |
175 | .name = "Blue Balance", | 162 | .step = 1, |
176 | .minimum = 0, | 163 | #define AGC_DEF 1 |
177 | .maximum = 255, | 164 | .default_value = AGC_DEF, |
178 | .step = 1, | 165 | }, |
179 | #define BLUE_BALANCE_DEF 128 | 166 | .set = sd_setagc, |
180 | .default_value = BLUE_BALANCE_DEF, | 167 | .get = sd_getagc, |
181 | }, | 168 | }, |
182 | .set = sd_setblueblc, | 169 | #define AWB_IDX 5 |
183 | .get = sd_getblueblc, | 170 | { /* 5 */ |
184 | }, | 171 | { |
185 | { /* 6 */ | 172 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
186 | { | 173 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
187 | .id = V4L2_CID_HUE, | 174 | .name = "Auto White Balance", |
188 | .type = V4L2_CTRL_TYPE_INTEGER, | 175 | .minimum = 0, |
189 | .name = "Hue", | 176 | .maximum = 1, |
190 | .minimum = 0, | 177 | .step = 1, |
191 | .maximum = 255, | 178 | #define AWB_DEF 1 |
192 | .step = 1, | 179 | .default_value = AWB_DEF, |
193 | #define HUE_DEF 143 | 180 | }, |
194 | .default_value = HUE_DEF, | 181 | .set = sd_setawb, |
182 | .get = sd_getawb, | ||
195 | }, | 183 | }, |
196 | .set = sd_sethue, | 184 | { /* 6 */ |
197 | .get = sd_gethue, | 185 | { |
198 | }, | 186 | .id = V4L2_CID_EXPOSURE_AUTO, |
199 | { /* 7 */ | 187 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
200 | { | 188 | .name = "Auto Exposure", |
201 | .id = V4L2_CID_AUTOGAIN, | 189 | .minimum = 0, |
202 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 190 | .maximum = 1, |
203 | .name = "Autogain", | 191 | .step = 1, |
204 | .minimum = 0, | 192 | #define AEC_DEF 1 |
205 | .maximum = 1, | 193 | .default_value = AEC_DEF, |
206 | .step = 1, | 194 | }, |
207 | #define AUTOGAIN_DEF 0 | 195 | .set = sd_setaec, |
208 | .default_value = AUTOGAIN_DEF, | 196 | .get = sd_getaec, |
209 | }, | 197 | }, |
210 | .set = sd_setautogain, | 198 | { /* 7 */ |
211 | .get = sd_getautogain, | 199 | { |
212 | }, | 200 | .id = V4L2_CID_SHARPNESS, |
213 | #define AWB_IDX 8 | 201 | .type = V4L2_CTRL_TYPE_INTEGER, |
214 | { /* 8 */ | 202 | .name = "Sharpness", |
215 | { | 203 | .minimum = 0, |
216 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 204 | .maximum = 63, |
217 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 205 | .step = 1, |
218 | .name = "Auto White Balance", | ||
219 | .minimum = 0, | ||
220 | .maximum = 1, | ||
221 | .step = 1, | ||
222 | #define AWB_DEF 0 | ||
223 | .default_value = AWB_DEF, | ||
224 | }, | ||
225 | .set = sd_setawb, | ||
226 | .get = sd_getawb, | ||
227 | }, | ||
228 | { /* 9 */ | ||
229 | { | ||
230 | .id = V4L2_CID_SHARPNESS, | ||
231 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
232 | .name = "Sharpness", | ||
233 | .minimum = 0, | ||
234 | .maximum = 63, | ||
235 | .step = 1, | ||
236 | #define SHARPNESS_DEF 0 | 206 | #define SHARPNESS_DEF 0 |
237 | .default_value = SHARPNESS_DEF, | 207 | .default_value = SHARPNESS_DEF, |
208 | }, | ||
209 | .set = sd_setsharpness, | ||
210 | .get = sd_getsharpness, | ||
238 | }, | 211 | }, |
239 | .set = sd_setsharpness, | 212 | { /* 8 */ |
240 | .get = sd_getsharpness, | 213 | { |
241 | }, | 214 | .id = V4L2_CID_HFLIP, |
242 | { /* 10 */ | 215 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
243 | { | 216 | .name = "HFlip", |
244 | .id = V4L2_CID_HFLIP, | 217 | .minimum = 0, |
245 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 218 | .maximum = 1, |
246 | .name = "HFlip", | 219 | .step = 1, |
247 | .minimum = 0, | ||
248 | .maximum = 1, | ||
249 | .step = 1, | ||
250 | #define HFLIP_DEF 0 | 220 | #define HFLIP_DEF 0 |
251 | .default_value = HFLIP_DEF, | 221 | .default_value = HFLIP_DEF, |
222 | }, | ||
223 | .set = sd_sethflip, | ||
224 | .get = sd_gethflip, | ||
252 | }, | 225 | }, |
253 | .set = sd_sethflip, | 226 | { /* 9 */ |
254 | .get = sd_gethflip, | 227 | { |
255 | }, | 228 | .id = V4L2_CID_VFLIP, |
256 | { /* 11 */ | 229 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
257 | { | 230 | .name = "VFlip", |
258 | .id = V4L2_CID_VFLIP, | 231 | .minimum = 0, |
259 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 232 | .maximum = 1, |
260 | .name = "VFlip", | 233 | .step = 1, |
261 | .minimum = 0, | ||
262 | .maximum = 1, | ||
263 | .step = 1, | ||
264 | #define VFLIP_DEF 0 | 234 | #define VFLIP_DEF 0 |
265 | .default_value = VFLIP_DEF, | 235 | .default_value = VFLIP_DEF, |
236 | }, | ||
237 | .set = sd_setvflip, | ||
238 | .get = sd_getvflip, | ||
239 | }, | ||
240 | { /* 10 */ | ||
241 | { | ||
242 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
243 | .type = V4L2_CTRL_TYPE_MENU, | ||
244 | .name = "Light Frequency Filter", | ||
245 | .minimum = 0, | ||
246 | .maximum = 1, | ||
247 | .step = 1, | ||
248 | #define FREQFLTR_DEF 0 | ||
249 | .default_value = FREQFLTR_DEF, | ||
250 | }, | ||
251 | .set = sd_setfreqfltr, | ||
252 | .get = sd_getfreqfltr, | ||
266 | }, | 253 | }, |
267 | .set = sd_setvflip, | ||
268 | .get = sd_getvflip, | ||
269 | }, | ||
270 | }; | 254 | }; |
271 | 255 | ||
272 | static const struct v4l2_pix_format ov772x_mode[] = { | 256 | static const struct v4l2_pix_format ov772x_mode[] = { |
@@ -675,14 +659,14 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
675 | { | 659 | { |
676 | struct sd *sd = (struct sd *) gspca_dev; | 660 | struct sd *sd = (struct sd *) gspca_dev; |
677 | 661 | ||
678 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); | 662 | sccb_reg_write(gspca_dev, 0x9b, sd->brightness); |
679 | } | 663 | } |
680 | 664 | ||
681 | static void setcontrast(struct gspca_dev *gspca_dev) | 665 | static void setcontrast(struct gspca_dev *gspca_dev) |
682 | { | 666 | { |
683 | struct sd *sd = (struct sd *) gspca_dev; | 667 | struct sd *sd = (struct sd *) gspca_dev; |
684 | 668 | ||
685 | sccb_reg_write(gspca_dev, 0x9C, sd->contrast); | 669 | sccb_reg_write(gspca_dev, 0x9c, sd->contrast); |
686 | } | 670 | } |
687 | 671 | ||
688 | static void setgain(struct gspca_dev *gspca_dev) | 672 | static void setgain(struct gspca_dev *gspca_dev) |
@@ -690,6 +674,9 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
690 | struct sd *sd = (struct sd *) gspca_dev; | 674 | struct sd *sd = (struct sd *) gspca_dev; |
691 | u8 val; | 675 | u8 val; |
692 | 676 | ||
677 | if (sd->agc) | ||
678 | return; | ||
679 | |||
693 | val = sd->gain; | 680 | val = sd->gain; |
694 | switch (val & 0x30) { | 681 | switch (val & 0x30) { |
695 | case 0x00: | 682 | case 0x00: |
@@ -717,55 +704,68 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
717 | struct sd *sd = (struct sd *) gspca_dev; | 704 | struct sd *sd = (struct sd *) gspca_dev; |
718 | u8 val; | 705 | u8 val; |
719 | 706 | ||
707 | if (sd->aec) | ||
708 | return; | ||
709 | |||
710 | /* 'val' is one byte and represents half of the exposure value we are | ||
711 | * going to set into registers, a two bytes value: | ||
712 | * | ||
713 | * MSB: ((u16) val << 1) >> 8 == val >> 7 | ||
714 | * LSB: ((u16) val << 1) & 0xff == val << 1 | ||
715 | */ | ||
720 | val = sd->exposure; | 716 | val = sd->exposure; |
721 | sccb_reg_write(gspca_dev, 0x08, val >> 7); | 717 | sccb_reg_write(gspca_dev, 0x08, val >> 7); |
722 | sccb_reg_write(gspca_dev, 0x10, val << 1); | 718 | sccb_reg_write(gspca_dev, 0x10, val << 1); |
723 | } | 719 | } |
724 | 720 | ||
725 | static void setredblc(struct gspca_dev *gspca_dev) | 721 | static void setagc(struct gspca_dev *gspca_dev) |
726 | { | 722 | { |
727 | struct sd *sd = (struct sd *) gspca_dev; | 723 | struct sd *sd = (struct sd *) gspca_dev; |
728 | 724 | ||
729 | sccb_reg_write(gspca_dev, 0x43, sd->redblc); | 725 | if (sd->agc) { |
730 | } | 726 | sccb_reg_write(gspca_dev, 0x13, |
731 | 727 | sccb_reg_read(gspca_dev, 0x13) | 0x04); | |
732 | static void setblueblc(struct gspca_dev *gspca_dev) | 728 | sccb_reg_write(gspca_dev, 0x64, |
733 | { | 729 | sccb_reg_read(gspca_dev, 0x64) | 0x03); |
734 | struct sd *sd = (struct sd *) gspca_dev; | 730 | } else { |
735 | 731 | sccb_reg_write(gspca_dev, 0x13, | |
736 | sccb_reg_write(gspca_dev, 0x42, sd->blueblc); | 732 | sccb_reg_read(gspca_dev, 0x13) & ~0x04); |
737 | } | 733 | sccb_reg_write(gspca_dev, 0x64, |
738 | 734 | sccb_reg_read(gspca_dev, 0x64) & ~0x03); | |
739 | static void sethue(struct gspca_dev *gspca_dev) | ||
740 | { | ||
741 | struct sd *sd = (struct sd *) gspca_dev; | ||
742 | 735 | ||
743 | sccb_reg_write(gspca_dev, 0x01, sd->hue); | 736 | setgain(gspca_dev); |
737 | } | ||
744 | } | 738 | } |
745 | 739 | ||
746 | static void setautogain(struct gspca_dev *gspca_dev) | 740 | static void setawb(struct gspca_dev *gspca_dev) |
747 | { | 741 | { |
748 | struct sd *sd = (struct sd *) gspca_dev; | 742 | struct sd *sd = (struct sd *) gspca_dev; |
749 | 743 | ||
750 | if (sd->autogain) { | 744 | if (sd->awb) { |
751 | sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */ | 745 | sccb_reg_write(gspca_dev, 0x13, |
752 | sccb_reg_write(gspca_dev, 0x64, | 746 | sccb_reg_read(gspca_dev, 0x13) | 0x02); |
753 | sccb_reg_read(gspca_dev, 0x64) | 0x03); | 747 | sccb_reg_write(gspca_dev, 0x63, |
748 | sccb_reg_read(gspca_dev, 0x63) | 0xc0); | ||
754 | } else { | 749 | } else { |
755 | sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */ | 750 | sccb_reg_write(gspca_dev, 0x13, |
756 | sccb_reg_write(gspca_dev, 0x64, | 751 | sccb_reg_read(gspca_dev, 0x13) & ~0x02); |
757 | sccb_reg_read(gspca_dev, 0x64) & 0xfc); | 752 | sccb_reg_write(gspca_dev, 0x63, |
753 | sccb_reg_read(gspca_dev, 0x63) & ~0xc0); | ||
758 | } | 754 | } |
759 | } | 755 | } |
760 | 756 | ||
761 | static void setawb(struct gspca_dev *gspca_dev) | 757 | static void setaec(struct gspca_dev *gspca_dev) |
762 | { | 758 | { |
763 | struct sd *sd = (struct sd *) gspca_dev; | 759 | struct sd *sd = (struct sd *) gspca_dev; |
764 | 760 | ||
765 | if (sd->awb) | 761 | if (sd->aec) |
766 | sccb_reg_write(gspca_dev, 0x63, 0xe0); /* AWB on */ | 762 | sccb_reg_write(gspca_dev, 0x13, |
767 | else | 763 | sccb_reg_read(gspca_dev, 0x13) | 0x01); |
768 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ | 764 | else { |
765 | sccb_reg_write(gspca_dev, 0x13, | ||
766 | sccb_reg_read(gspca_dev, 0x13) & ~0x01); | ||
767 | setexposure(gspca_dev); | ||
768 | } | ||
769 | } | 769 | } |
770 | 770 | ||
771 | static void setsharpness(struct gspca_dev *gspca_dev) | 771 | static void setsharpness(struct gspca_dev *gspca_dev) |
@@ -774,8 +774,8 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
774 | u8 val; | 774 | u8 val; |
775 | 775 | ||
776 | val = sd->sharpness; | 776 | val = sd->sharpness; |
777 | sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */ | 777 | sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */ |
778 | sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */ | 778 | sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */ |
779 | } | 779 | } |
780 | 780 | ||
781 | static void sethflip(struct gspca_dev *gspca_dev) | 781 | static void sethflip(struct gspca_dev *gspca_dev) |
@@ -787,7 +787,7 @@ static void sethflip(struct gspca_dev *gspca_dev) | |||
787 | sccb_reg_read(gspca_dev, 0x0c) | 0x40); | 787 | sccb_reg_read(gspca_dev, 0x0c) | 0x40); |
788 | else | 788 | else |
789 | sccb_reg_write(gspca_dev, 0x0c, | 789 | sccb_reg_write(gspca_dev, 0x0c, |
790 | sccb_reg_read(gspca_dev, 0x0c) & 0xbf); | 790 | sccb_reg_read(gspca_dev, 0x0c) & ~0x40); |
791 | } | 791 | } |
792 | 792 | ||
793 | static void setvflip(struct gspca_dev *gspca_dev) | 793 | static void setvflip(struct gspca_dev *gspca_dev) |
@@ -799,9 +799,20 @@ static void setvflip(struct gspca_dev *gspca_dev) | |||
799 | sccb_reg_read(gspca_dev, 0x0c) | 0x80); | 799 | sccb_reg_read(gspca_dev, 0x0c) | 0x80); |
800 | else | 800 | else |
801 | sccb_reg_write(gspca_dev, 0x0c, | 801 | sccb_reg_write(gspca_dev, 0x0c, |
802 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | 802 | sccb_reg_read(gspca_dev, 0x0c) & ~0x80); |
803 | } | 803 | } |
804 | 804 | ||
805 | static void setfreqfltr(struct gspca_dev *gspca_dev) | ||
806 | { | ||
807 | struct sd *sd = (struct sd *) gspca_dev; | ||
808 | |||
809 | if (sd->freqfltr == 0) | ||
810 | sccb_reg_write(gspca_dev, 0x2b, 0x00); | ||
811 | else | ||
812 | sccb_reg_write(gspca_dev, 0x2b, 0x9e); | ||
813 | } | ||
814 | |||
815 | |||
805 | /* this function is called at probe time */ | 816 | /* this function is called at probe time */ |
806 | static int sd_config(struct gspca_dev *gspca_dev, | 817 | static int sd_config(struct gspca_dev *gspca_dev, |
807 | const struct usb_device_id *id) | 818 | const struct usb_device_id *id) |
@@ -825,26 +836,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
825 | sd->contrast = CONTRAST_DEF; | 836 | sd->contrast = CONTRAST_DEF; |
826 | sd->gain = GAIN_DEF; | 837 | sd->gain = GAIN_DEF; |
827 | sd->exposure = EXPO_DEF; | 838 | sd->exposure = EXPO_DEF; |
828 | sd->redblc = RED_BALANCE_DEF; | 839 | #if AGC_DEF != 0 |
829 | sd->blueblc = BLUE_BALANCE_DEF; | 840 | sd->agc = AGC_DEF; |
830 | sd->hue = HUE_DEF; | ||
831 | #if AUTOGAIN_DEF != 0 | ||
832 | sd->autogain = AUTOGAIN_DEF; | ||
833 | #else | 841 | #else |
834 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); | 842 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
835 | #endif | 843 | #endif |
836 | #if AWB_DEF != 0 | 844 | sd->awb = AWB_DEF; |
837 | sd->awb = AWB_DEF | 845 | sd->aec = AEC_DEF; |
838 | #endif | ||
839 | #if SHARPNESS_DEF != 0 | ||
840 | sd->sharpness = SHARPNESS_DEF; | 846 | sd->sharpness = SHARPNESS_DEF; |
841 | #endif | ||
842 | #if HFLIP_DEF != 0 | ||
843 | sd->hflip = HFLIP_DEF; | 847 | sd->hflip = HFLIP_DEF; |
844 | #endif | ||
845 | #if VFLIP_DEF != 0 | ||
846 | sd->vflip = VFLIP_DEF; | 848 | sd->vflip = VFLIP_DEF; |
847 | #endif | 849 | sd->freqfltr = FREQFLTR_DEF; |
848 | 850 | ||
849 | return 0; | 851 | return 0; |
850 | } | 852 | } |
@@ -904,18 +906,17 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
904 | } | 906 | } |
905 | set_frame_rate(gspca_dev); | 907 | set_frame_rate(gspca_dev); |
906 | 908 | ||
907 | setautogain(gspca_dev); | 909 | setagc(gspca_dev); |
908 | setawb(gspca_dev); | 910 | setawb(gspca_dev); |
911 | setaec(gspca_dev); | ||
909 | setgain(gspca_dev); | 912 | setgain(gspca_dev); |
910 | setredblc(gspca_dev); | ||
911 | setblueblc(gspca_dev); | ||
912 | sethue(gspca_dev); | ||
913 | setexposure(gspca_dev); | 913 | setexposure(gspca_dev); |
914 | setbrightness(gspca_dev); | 914 | setbrightness(gspca_dev); |
915 | setcontrast(gspca_dev); | 915 | setcontrast(gspca_dev); |
916 | setsharpness(gspca_dev); | 916 | setsharpness(gspca_dev); |
917 | setvflip(gspca_dev); | 917 | setvflip(gspca_dev); |
918 | sethflip(gspca_dev); | 918 | sethflip(gspca_dev); |
919 | setfreqfltr(gspca_dev); | ||
919 | 920 | ||
920 | ov534_set_led(gspca_dev, 1); | 921 | ov534_set_led(gspca_dev, 1); |
921 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | 922 | ov534_reg_write(gspca_dev, 0xe0, 0x00); |
@@ -1092,65 +1093,11 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
1092 | return 0; | 1093 | return 0; |
1093 | } | 1094 | } |
1094 | 1095 | ||
1095 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | 1096 | static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val) |
1096 | { | ||
1097 | struct sd *sd = (struct sd *) gspca_dev; | ||
1098 | |||
1099 | sd->redblc = val; | ||
1100 | if (gspca_dev->streaming) | ||
1101 | setredblc(gspca_dev); | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
1106 | { | ||
1107 | struct sd *sd = (struct sd *) gspca_dev; | ||
1108 | |||
1109 | *val = sd->redblc; | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val) | ||
1114 | { | ||
1115 | struct sd *sd = (struct sd *) gspca_dev; | ||
1116 | |||
1117 | sd->blueblc = val; | ||
1118 | if (gspca_dev->streaming) | ||
1119 | setblueblc(gspca_dev); | ||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
1124 | { | 1097 | { |
1125 | struct sd *sd = (struct sd *) gspca_dev; | 1098 | struct sd *sd = (struct sd *) gspca_dev; |
1126 | 1099 | ||
1127 | *val = sd->blueblc; | 1100 | sd->agc = val; |
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) | ||
1132 | { | ||
1133 | struct sd *sd = (struct sd *) gspca_dev; | ||
1134 | |||
1135 | sd->hue = val; | ||
1136 | if (gspca_dev->streaming) | ||
1137 | sethue(gspca_dev); | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) | ||
1142 | { | ||
1143 | struct sd *sd = (struct sd *) gspca_dev; | ||
1144 | |||
1145 | *val = sd->hue; | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1150 | { | ||
1151 | struct sd *sd = (struct sd *) gspca_dev; | ||
1152 | |||
1153 | sd->autogain = val; | ||
1154 | 1101 | ||
1155 | if (gspca_dev->streaming) { | 1102 | if (gspca_dev->streaming) { |
1156 | 1103 | ||
@@ -1160,16 +1107,16 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1160 | gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); | 1107 | gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); |
1161 | else | 1108 | else |
1162 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); | 1109 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
1163 | setautogain(gspca_dev); | 1110 | setagc(gspca_dev); |
1164 | } | 1111 | } |
1165 | return 0; | 1112 | return 0; |
1166 | } | 1113 | } |
1167 | 1114 | ||
1168 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 1115 | static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val) |
1169 | { | 1116 | { |
1170 | struct sd *sd = (struct sd *) gspca_dev; | 1117 | struct sd *sd = (struct sd *) gspca_dev; |
1171 | 1118 | ||
1172 | *val = sd->autogain; | 1119 | *val = sd->agc; |
1173 | return 0; | 1120 | return 0; |
1174 | } | 1121 | } |
1175 | 1122 | ||
@@ -1191,6 +1138,24 @@ static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) | |||
1191 | return 0; | 1138 | return 0; |
1192 | } | 1139 | } |
1193 | 1140 | ||
1141 | static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val) | ||
1142 | { | ||
1143 | struct sd *sd = (struct sd *) gspca_dev; | ||
1144 | |||
1145 | sd->aec = val; | ||
1146 | if (gspca_dev->streaming) | ||
1147 | setaec(gspca_dev); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val) | ||
1152 | { | ||
1153 | struct sd *sd = (struct sd *) gspca_dev; | ||
1154 | |||
1155 | *val = sd->aec; | ||
1156 | return 0; | ||
1157 | } | ||
1158 | |||
1194 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | 1159 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) |
1195 | { | 1160 | { |
1196 | struct sd *sd = (struct sd *) gspca_dev; | 1161 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1245,6 +1210,43 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
1245 | return 0; | 1210 | return 0; |
1246 | } | 1211 | } |
1247 | 1212 | ||
1213 | static int sd_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val) | ||
1214 | { | ||
1215 | struct sd *sd = (struct sd *) gspca_dev; | ||
1216 | |||
1217 | sd->freqfltr = val; | ||
1218 | if (gspca_dev->streaming) | ||
1219 | setfreqfltr(gspca_dev); | ||
1220 | return 0; | ||
1221 | } | ||
1222 | |||
1223 | static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val) | ||
1224 | { | ||
1225 | struct sd *sd = (struct sd *) gspca_dev; | ||
1226 | |||
1227 | *val = sd->freqfltr; | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
1232 | struct v4l2_querymenu *menu) | ||
1233 | { | ||
1234 | switch (menu->id) { | ||
1235 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
1236 | switch (menu->index) { | ||
1237 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1238 | strcpy((char *) menu->name, "Disabled"); | ||
1239 | return 0; | ||
1240 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1241 | strcpy((char *) menu->name, "50 Hz"); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | return -EINVAL; | ||
1248 | } | ||
1249 | |||
1248 | /* get stream parameters (framerate) */ | 1250 | /* get stream parameters (framerate) */ |
1249 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, | 1251 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, |
1250 | struct v4l2_streamparm *parm) | 1252 | struct v4l2_streamparm *parm) |
@@ -1296,6 +1298,7 @@ static const struct sd_desc sd_desc = { | |||
1296 | .start = sd_start, | 1298 | .start = sd_start, |
1297 | .stopN = sd_stopN, | 1299 | .stopN = sd_stopN, |
1298 | .pkt_scan = sd_pkt_scan, | 1300 | .pkt_scan = sd_pkt_scan, |
1301 | .querymenu = sd_querymenu, | ||
1299 | .get_streamparm = sd_get_streamparm, | 1302 | .get_streamparm = sd_get_streamparm, |
1300 | .set_streamparm = sd_set_streamparm, | 1303 | .set_streamparm = sd_set_streamparm, |
1301 | }; | 1304 | }; |
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 0c87c3490b1e..a40f8893310d 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -99,7 +99,7 @@ static const struct ctrl sd_ctrls[] = { | |||
99 | { | 99 | { |
100 | .id = V4L2_CID_EXPOSURE, | 100 | .id = V4L2_CID_EXPOSURE, |
101 | .type = V4L2_CTRL_TYPE_INTEGER, | 101 | .type = V4L2_CTRL_TYPE_INTEGER, |
102 | .name = "exposure", | 102 | .name = "Exposure", |
103 | .minimum = PAC207_EXPOSURE_MIN, | 103 | .minimum = PAC207_EXPOSURE_MIN, |
104 | .maximum = PAC207_EXPOSURE_MAX, | 104 | .maximum = PAC207_EXPOSURE_MAX, |
105 | .step = 1, | 105 | .step = 1, |
@@ -130,7 +130,7 @@ static const struct ctrl sd_ctrls[] = { | |||
130 | { | 130 | { |
131 | .id = V4L2_CID_GAIN, | 131 | .id = V4L2_CID_GAIN, |
132 | .type = V4L2_CTRL_TYPE_INTEGER, | 132 | .type = V4L2_CTRL_TYPE_INTEGER, |
133 | .name = "gain", | 133 | .name = "Gain", |
134 | .minimum = PAC207_GAIN_MIN, | 134 | .minimum = PAC207_GAIN_MIN, |
135 | .maximum = PAC207_GAIN_MAX, | 135 | .maximum = PAC207_GAIN_MAX, |
136 | .step = 1, | 136 | .step = 1, |
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c index dda5fd4aa69e..71d9447a7986 100644 --- a/drivers/media/video/gspca/sn9c2028.c +++ b/drivers/media/video/gspca/sn9c2028.c | |||
@@ -39,7 +39,7 @@ struct init_command { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* V4L2 controls supported by the driver */ | 41 | /* V4L2 controls supported by the driver */ |
42 | static struct ctrl sd_ctrls[] = { | 42 | static const struct ctrl sd_ctrls[] = { |
43 | }; | 43 | }; |
44 | 44 | ||
45 | /* How to change the resolution of any of the VGA cams is unknown */ | 45 | /* How to change the resolution of any of the VGA cams is unknown */ |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 3dee3e5844b6..644a7fd4701a 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -18,10 +18,7 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV | 21 | #ifdef CONFIG_INPUT |
22 | #include <linux/kthread.h> | ||
23 | #include <linux/freezer.h> | ||
24 | #include <linux/usb/input.h> | ||
25 | #include <linux/input.h> | 22 | #include <linux/input.h> |
26 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
27 | #endif | 24 | #endif |
@@ -30,6 +27,7 @@ | |||
30 | #include "jpeg.h" | 27 | #include "jpeg.h" |
31 | 28 | ||
32 | #include <media/v4l2-chip-ident.h> | 29 | #include <media/v4l2-chip-ident.h> |
30 | #include <linux/dmi.h> | ||
33 | 31 | ||
34 | MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " | 32 | MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " |
35 | "microdia project <microdia@googlegroups.com>"); | 33 | "microdia project <microdia@googlegroups.com>"); |
@@ -52,9 +50,15 @@ MODULE_LICENSE("GPL"); | |||
52 | #define SENSOR_MT9V112 7 | 50 | #define SENSOR_MT9V112 7 |
53 | #define SENSOR_MT9M001 8 | 51 | #define SENSOR_MT9M001 8 |
54 | #define SENSOR_MT9M111 9 | 52 | #define SENSOR_MT9M111 9 |
55 | #define SENSOR_HV7131R 10 | 53 | #define SENSOR_MT9M112 10 |
54 | #define SENSOR_HV7131R 11 | ||
56 | #define SENSOR_MT9VPRB 20 | 55 | #define SENSOR_MT9VPRB 20 |
57 | 56 | ||
57 | /* camera flags */ | ||
58 | #define HAS_NO_BUTTON 0x1 | ||
59 | #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ | ||
60 | #define FLIP_DETECT 0x4 | ||
61 | |||
58 | /* specific webcam descriptor */ | 62 | /* specific webcam descriptor */ |
59 | struct sd { | 63 | struct sd { |
60 | struct gspca_dev gspca_dev; | 64 | struct gspca_dev gspca_dev; |
@@ -88,11 +92,7 @@ struct sd { | |||
88 | u8 *jpeg_hdr; | 92 | u8 *jpeg_hdr; |
89 | u8 quality; | 93 | u8 quality; |
90 | 94 | ||
91 | #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV | 95 | u8 flags; |
92 | struct input_dev *input_dev; | ||
93 | u8 input_gpio; | ||
94 | struct task_struct *input_task; | ||
95 | #endif | ||
96 | }; | 96 | }; |
97 | 97 | ||
98 | struct i2c_reg_u8 { | 98 | struct i2c_reg_u8 { |
@@ -130,6 +130,39 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); | |||
130 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); | 130 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); |
131 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); | 131 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); |
132 | 132 | ||
133 | static const struct dmi_system_id flip_dmi_table[] = { | ||
134 | { | ||
135 | .ident = "MSI MS-1034", | ||
136 | .matches = { | ||
137 | DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), | ||
138 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), | ||
139 | DMI_MATCH(DMI_PRODUCT_VERSION, "0341") | ||
140 | } | ||
141 | }, | ||
142 | { | ||
143 | .ident = "MSI MS-1632", | ||
144 | .matches = { | ||
145 | DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), | ||
146 | DMI_MATCH(DMI_BOARD_NAME, "MS-1632") | ||
147 | } | ||
148 | }, | ||
149 | { | ||
150 | .ident = "MSI MS-1635X", | ||
151 | .matches = { | ||
152 | DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), | ||
153 | DMI_MATCH(DMI_BOARD_NAME, "MS-1635X") | ||
154 | } | ||
155 | }, | ||
156 | { | ||
157 | .ident = "ASUSTeK W7J", | ||
158 | .matches = { | ||
159 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), | ||
160 | DMI_MATCH(DMI_BOARD_NAME, "W7J ") | ||
161 | } | ||
162 | }, | ||
163 | {} | ||
164 | }; | ||
165 | |||
133 | static const struct ctrl sd_ctrls[] = { | 166 | static const struct ctrl sd_ctrls[] = { |
134 | { | 167 | { |
135 | #define BRIGHTNESS_IDX 0 | 168 | #define BRIGHTNESS_IDX 0 |
@@ -713,6 +746,7 @@ static u16 i2c_ident[] = { | |||
713 | V4L2_IDENT_MT9V112, | 746 | V4L2_IDENT_MT9V112, |
714 | V4L2_IDENT_MT9M001C12ST, | 747 | V4L2_IDENT_MT9M001C12ST, |
715 | V4L2_IDENT_MT9M111, | 748 | V4L2_IDENT_MT9M111, |
749 | V4L2_IDENT_MT9M112, | ||
716 | V4L2_IDENT_HV7131R, | 750 | V4L2_IDENT_HV7131R, |
717 | }; | 751 | }; |
718 | 752 | ||
@@ -735,7 +769,8 @@ static u16 bridge_init[][2] = { | |||
735 | {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, | 769 | {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, |
736 | {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, | 770 | {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, |
737 | {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, | 771 | {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, |
738 | {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80} | 772 | {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}, |
773 | {0x1007, 0x00} | ||
739 | }; | 774 | }; |
740 | 775 | ||
741 | /* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ | 776 | /* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ |
@@ -914,40 +949,30 @@ static struct i2c_reg_u8 ov9650_init[] = { | |||
914 | }; | 949 | }; |
915 | 950 | ||
916 | static struct i2c_reg_u8 ov9655_init[] = { | 951 | static struct i2c_reg_u8 ov9655_init[] = { |
917 | {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61}, | 952 | {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, |
918 | {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24}, | 953 | {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, |
919 | {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08}, | 954 | {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, |
920 | {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf}, | 955 | {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, |
921 | {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12}, | 956 | {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19}, |
922 | {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, | 957 | {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80}, |
923 | {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, | 958 | {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c}, |
924 | {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, | 959 | {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc}, |
925 | {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, | 960 | {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05}, |
926 | {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04}, | 961 | {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e}, |
927 | {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02}, | 962 | {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, |
928 | {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c}, | 963 | {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, |
929 | {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60}, | 964 | {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, |
930 | {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04}, | 965 | {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, |
931 | {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80}, | 966 | {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, |
932 | {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf}, | 967 | {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01}, |
933 | {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b}, | ||
934 | {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01}, | ||
935 | {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, | 968 | {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, |
936 | {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61}, | 969 | {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00}, |
970 | {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61}, | ||
937 | {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, | 971 | {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, |
938 | {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01}, | 972 | {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01}, |
939 | {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10}, | 973 | {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a}, |
940 | {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04}, | 974 | {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c}, |
941 | {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00}, | 975 | {0x04, 0x03}, {0x00, 0x13}, |
942 | {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80}, | ||
943 | {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d}, | ||
944 | {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14}, | ||
945 | {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf}, | ||
946 | {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00}, | ||
947 | {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00}, | ||
948 | {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03}, | ||
949 | {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03}, | ||
950 | {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13}, | ||
951 | }; | 976 | }; |
952 | 977 | ||
953 | static struct i2c_reg_u16 mt9v112_init[] = { | 978 | static struct i2c_reg_u16 mt9v112_init[] = { |
@@ -971,29 +996,12 @@ static struct i2c_reg_u16 mt9v112_init[] = { | |||
971 | 996 | ||
972 | static struct i2c_reg_u16 mt9v111_init[] = { | 997 | static struct i2c_reg_u16 mt9v111_init[] = { |
973 | {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, | 998 | {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, |
974 | {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1}, | 999 | {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0}, |
975 | {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002}, | 1000 | {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e}, |
976 | {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03}, | 1001 | {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016}, |
977 | {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c}, | 1002 | {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004}, |
978 | {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064}, | 1003 | {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008}, |
979 | {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480}, | 1004 | {0x0e, 0x0008}, {0x20, 0x0000} |
980 | {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6}, | ||
981 | {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000}, | ||
982 | {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000}, | ||
983 | {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000}, | ||
984 | {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0}, | ||
985 | {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000}, | ||
986 | {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000}, | ||
987 | {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000}, | ||
988 | {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000}, | ||
989 | {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016}, | ||
990 | {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004}, | ||
991 | {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d}, | ||
992 | {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0}, | ||
993 | {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0}, | ||
994 | {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281}, | ||
995 | {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002}, | ||
996 | {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004}, | ||
997 | }; | 1005 | }; |
998 | 1006 | ||
999 | static struct i2c_reg_u16 mt9v011_init[] = { | 1007 | static struct i2c_reg_u16 mt9v011_init[] = { |
@@ -1043,6 +1051,13 @@ static struct i2c_reg_u16 mt9m111_init[] = { | |||
1043 | {0xf0, 0x0000}, | 1051 | {0xf0, 0x0000}, |
1044 | }; | 1052 | }; |
1045 | 1053 | ||
1054 | static struct i2c_reg_u16 mt9m112_init[] = { | ||
1055 | {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, | ||
1056 | {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, | ||
1057 | {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, | ||
1058 | {0xf0, 0x0000}, | ||
1059 | }; | ||
1060 | |||
1046 | static struct i2c_reg_u8 hv7131r_init[] = { | 1061 | static struct i2c_reg_u8 hv7131r_init[] = { |
1047 | {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, | 1062 | {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, |
1048 | {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, | 1063 | {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, |
@@ -1240,8 +1255,8 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev) | |||
1240 | } | 1255 | } |
1241 | /* disable hflip and vflip */ | 1256 | /* disable hflip and vflip */ |
1242 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); | 1257 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); |
1243 | sd->hstart = 0; | 1258 | sd->hstart = 1; |
1244 | sd->vstart = 7; | 1259 | sd->vstart = 2; |
1245 | return 0; | 1260 | return 0; |
1246 | } | 1261 | } |
1247 | 1262 | ||
@@ -1337,6 +1352,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) | |||
1337 | return -ENODEV; | 1352 | return -ENODEV; |
1338 | } | 1353 | } |
1339 | } | 1354 | } |
1355 | gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX); | ||
1340 | sd->hstart = 2; | 1356 | sd->hstart = 2; |
1341 | sd->vstart = 2; | 1357 | sd->vstart = 2; |
1342 | sd->sensor = SENSOR_MT9V111; | 1358 | sd->sensor = SENSOR_MT9V111; |
@@ -1369,6 +1385,23 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) | |||
1369 | return -ENODEV; | 1385 | return -ENODEV; |
1370 | } | 1386 | } |
1371 | 1387 | ||
1388 | static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) | ||
1389 | { | ||
1390 | struct sd *sd = (struct sd *) gspca_dev; | ||
1391 | int i; | ||
1392 | for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { | ||
1393 | if (i2c_w2(gspca_dev, mt9m112_init[i].reg, | ||
1394 | mt9m112_init[i].val) < 0) { | ||
1395 | err("MT9M112 sensor initialization failed"); | ||
1396 | return -ENODEV; | ||
1397 | } | ||
1398 | } | ||
1399 | gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX); | ||
1400 | sd->hstart = 0; | ||
1401 | sd->vstart = 2; | ||
1402 | return 0; | ||
1403 | } | ||
1404 | |||
1372 | static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) | 1405 | static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) |
1373 | { | 1406 | { |
1374 | struct sd *sd = (struct sd *) gspca_dev; | 1407 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1421,87 +1454,6 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) | |||
1421 | return 0; | 1454 | return 0; |
1422 | } | 1455 | } |
1423 | 1456 | ||
1424 | #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV | ||
1425 | static int input_kthread(void *data) | ||
1426 | { | ||
1427 | struct gspca_dev *gspca_dev = (struct gspca_dev *)data; | ||
1428 | struct sd *sd = (struct sd *) gspca_dev; | ||
1429 | |||
1430 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait); | ||
1431 | set_freezable(); | ||
1432 | for (;;) { | ||
1433 | if (kthread_should_stop()) | ||
1434 | break; | ||
1435 | |||
1436 | if (reg_r(gspca_dev, 0x1005, 1) < 0) | ||
1437 | continue; | ||
1438 | |||
1439 | input_report_key(sd->input_dev, | ||
1440 | KEY_CAMERA, | ||
1441 | gspca_dev->usb_buf[0] & sd->input_gpio); | ||
1442 | input_sync(sd->input_dev); | ||
1443 | |||
1444 | wait_event_freezable_timeout(wait, | ||
1445 | kthread_should_stop(), | ||
1446 | msecs_to_jiffies(100)); | ||
1447 | } | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | |||
1452 | static int sn9c20x_input_init(struct gspca_dev *gspca_dev) | ||
1453 | { | ||
1454 | struct sd *sd = (struct sd *) gspca_dev; | ||
1455 | if (sd->input_gpio == 0) | ||
1456 | return 0; | ||
1457 | |||
1458 | sd->input_dev = input_allocate_device(); | ||
1459 | if (!sd->input_dev) | ||
1460 | return -ENOMEM; | ||
1461 | |||
1462 | sd->input_dev->name = "SN9C20X Webcam"; | ||
1463 | |||
1464 | sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s", | ||
1465 | gspca_dev->dev->bus->bus_name, | ||
1466 | gspca_dev->dev->devpath); | ||
1467 | |||
1468 | if (!sd->input_dev->phys) | ||
1469 | return -ENOMEM; | ||
1470 | |||
1471 | usb_to_input_id(gspca_dev->dev, &sd->input_dev->id); | ||
1472 | sd->input_dev->dev.parent = &gspca_dev->dev->dev; | ||
1473 | |||
1474 | set_bit(EV_KEY, sd->input_dev->evbit); | ||
1475 | set_bit(KEY_CAMERA, sd->input_dev->keybit); | ||
1476 | |||
1477 | if (input_register_device(sd->input_dev)) | ||
1478 | return -EINVAL; | ||
1479 | |||
1480 | sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s", | ||
1481 | gspca_dev->dev->bus->bus_name, | ||
1482 | gspca_dev->dev->devpath); | ||
1483 | |||
1484 | if (IS_ERR(sd->input_task)) | ||
1485 | return -EINVAL; | ||
1486 | |||
1487 | return 0; | ||
1488 | } | ||
1489 | |||
1490 | static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev) | ||
1491 | { | ||
1492 | struct sd *sd = (struct sd *) gspca_dev; | ||
1493 | if (sd->input_task != NULL && !IS_ERR(sd->input_task)) | ||
1494 | kthread_stop(sd->input_task); | ||
1495 | |||
1496 | if (sd->input_dev != NULL) { | ||
1497 | input_unregister_device(sd->input_dev); | ||
1498 | kfree(sd->input_dev->phys); | ||
1499 | input_free_device(sd->input_dev); | ||
1500 | sd->input_dev = NULL; | ||
1501 | } | ||
1502 | } | ||
1503 | #endif | ||
1504 | |||
1505 | static int set_cmatrix(struct gspca_dev *gspca_dev) | 1457 | static int set_cmatrix(struct gspca_dev *gspca_dev) |
1506 | { | 1458 | { |
1507 | struct sd *sd = (struct sd *) gspca_dev; | 1459 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1579,17 +1531,26 @@ static int set_redblue(struct gspca_dev *gspca_dev) | |||
1579 | 1531 | ||
1580 | static int set_hvflip(struct gspca_dev *gspca_dev) | 1532 | static int set_hvflip(struct gspca_dev *gspca_dev) |
1581 | { | 1533 | { |
1582 | u8 value, tslb; | 1534 | u8 value, tslb, hflip, vflip; |
1583 | u16 value2; | 1535 | u16 value2; |
1584 | struct sd *sd = (struct sd *) gspca_dev; | 1536 | struct sd *sd = (struct sd *) gspca_dev; |
1537 | |||
1538 | if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { | ||
1539 | hflip = !sd->hflip; | ||
1540 | vflip = !sd->vflip; | ||
1541 | } else { | ||
1542 | hflip = sd->hflip; | ||
1543 | vflip = sd->vflip; | ||
1544 | } | ||
1545 | |||
1585 | switch (sd->sensor) { | 1546 | switch (sd->sensor) { |
1586 | case SENSOR_OV9650: | 1547 | case SENSOR_OV9650: |
1587 | i2c_r1(gspca_dev, 0x1e, &value); | 1548 | i2c_r1(gspca_dev, 0x1e, &value); |
1588 | value &= ~0x30; | 1549 | value &= ~0x30; |
1589 | tslb = 0x01; | 1550 | tslb = 0x01; |
1590 | if (sd->hflip) | 1551 | if (hflip) |
1591 | value |= 0x20; | 1552 | value |= 0x20; |
1592 | if (sd->vflip) { | 1553 | if (vflip) { |
1593 | value |= 0x10; | 1554 | value |= 0x10; |
1594 | tslb = 0x49; | 1555 | tslb = 0x49; |
1595 | } | 1556 | } |
@@ -1600,28 +1561,29 @@ static int set_hvflip(struct gspca_dev *gspca_dev) | |||
1600 | case SENSOR_MT9V011: | 1561 | case SENSOR_MT9V011: |
1601 | i2c_r2(gspca_dev, 0x20, &value2); | 1562 | i2c_r2(gspca_dev, 0x20, &value2); |
1602 | value2 &= ~0xc0a0; | 1563 | value2 &= ~0xc0a0; |
1603 | if (sd->hflip) | 1564 | if (hflip) |
1604 | value2 |= 0x8080; | 1565 | value2 |= 0x8080; |
1605 | if (sd->vflip) | 1566 | if (vflip) |
1606 | value2 |= 0x4020; | 1567 | value2 |= 0x4020; |
1607 | i2c_w2(gspca_dev, 0x20, value2); | 1568 | i2c_w2(gspca_dev, 0x20, value2); |
1608 | break; | 1569 | break; |
1570 | case SENSOR_MT9M112: | ||
1609 | case SENSOR_MT9M111: | 1571 | case SENSOR_MT9M111: |
1610 | case SENSOR_MT9V112: | 1572 | case SENSOR_MT9V112: |
1611 | i2c_r2(gspca_dev, 0x20, &value2); | 1573 | i2c_r2(gspca_dev, 0x20, &value2); |
1612 | value2 &= ~0x0003; | 1574 | value2 &= ~0x0003; |
1613 | if (sd->hflip) | 1575 | if (hflip) |
1614 | value2 |= 0x0002; | 1576 | value2 |= 0x0002; |
1615 | if (sd->vflip) | 1577 | if (vflip) |
1616 | value2 |= 0x0001; | 1578 | value2 |= 0x0001; |
1617 | i2c_w2(gspca_dev, 0x20, value2); | 1579 | i2c_w2(gspca_dev, 0x20, value2); |
1618 | break; | 1580 | break; |
1619 | case SENSOR_HV7131R: | 1581 | case SENSOR_HV7131R: |
1620 | i2c_r1(gspca_dev, 0x01, &value); | 1582 | i2c_r1(gspca_dev, 0x01, &value); |
1621 | value &= ~0x03; | 1583 | value &= ~0x03; |
1622 | if (sd->vflip) | 1584 | if (vflip) |
1623 | value |= 0x01; | 1585 | value |= 0x01; |
1624 | if (sd->hflip) | 1586 | if (hflip) |
1625 | value |= 0x02; | 1587 | value |= 0x02; |
1626 | i2c_w1(gspca_dev, 0x01, value); | 1588 | i2c_w1(gspca_dev, 0x01, value); |
1627 | break; | 1589 | break; |
@@ -1645,7 +1607,6 @@ static int set_exposure(struct gspca_dev *gspca_dev) | |||
1645 | break; | 1607 | break; |
1646 | case SENSOR_MT9M001: | 1608 | case SENSOR_MT9M001: |
1647 | case SENSOR_MT9V112: | 1609 | case SENSOR_MT9V112: |
1648 | case SENSOR_MT9V111: | ||
1649 | case SENSOR_MT9V011: | 1610 | case SENSOR_MT9V011: |
1650 | exp[0] |= (3 << 4); | 1611 | exp[0] |= (3 << 4); |
1651 | exp[2] = 0x09; | 1612 | exp[2] = 0x09; |
@@ -1655,9 +1616,9 @@ static int set_exposure(struct gspca_dev *gspca_dev) | |||
1655 | case SENSOR_HV7131R: | 1616 | case SENSOR_HV7131R: |
1656 | exp[0] |= (4 << 4); | 1617 | exp[0] |= (4 << 4); |
1657 | exp[2] = 0x25; | 1618 | exp[2] = 0x25; |
1658 | exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16; | 1619 | exp[3] = (sd->exposure >> 5) & 0xff; |
1659 | exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; | 1620 | exp[4] = (sd->exposure << 3) & 0xff; |
1660 | exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; | 1621 | exp[5] = 0; |
1661 | break; | 1622 | break; |
1662 | default: | 1623 | default: |
1663 | return 0; | 1624 | return 0; |
@@ -1680,7 +1641,6 @@ static int set_gain(struct gspca_dev *gspca_dev) | |||
1680 | gain[3] = ov_gain[sd->gain]; | 1641 | gain[3] = ov_gain[sd->gain]; |
1681 | break; | 1642 | break; |
1682 | case SENSOR_MT9V011: | 1643 | case SENSOR_MT9V011: |
1683 | case SENSOR_MT9V111: | ||
1684 | gain[0] |= (3 << 4); | 1644 | gain[0] |= (3 << 4); |
1685 | gain[2] = 0x35; | 1645 | gain[2] = 0x35; |
1686 | gain[3] = micron1_gain[sd->gain] >> 8; | 1646 | gain[3] = micron1_gain[sd->gain] >> 8; |
@@ -1931,7 +1891,7 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, | |||
1931 | if (reg->match.addr != sd->i2c_addr) | 1891 | if (reg->match.addr != sd->i2c_addr) |
1932 | return -EINVAL; | 1892 | return -EINVAL; |
1933 | if (sd->sensor >= SENSOR_MT9V011 && | 1893 | if (sd->sensor >= SENSOR_MT9V011 && |
1934 | sd->sensor <= SENSOR_MT9M111) { | 1894 | sd->sensor <= SENSOR_MT9M112) { |
1935 | if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) | 1895 | if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) |
1936 | return -EINVAL; | 1896 | return -EINVAL; |
1937 | } else { | 1897 | } else { |
@@ -1960,7 +1920,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
1960 | if (reg->match.addr != sd->i2c_addr) | 1920 | if (reg->match.addr != sd->i2c_addr) |
1961 | return -EINVAL; | 1921 | return -EINVAL; |
1962 | if (sd->sensor >= SENSOR_MT9V011 && | 1922 | if (sd->sensor >= SENSOR_MT9V011 && |
1963 | sd->sensor <= SENSOR_MT9M111) { | 1923 | sd->sensor <= SENSOR_MT9M112) { |
1964 | if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) | 1924 | if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) |
1965 | return -EINVAL; | 1925 | return -EINVAL; |
1966 | } else { | 1926 | } else { |
@@ -2005,8 +1965,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2005 | 1965 | ||
2006 | sd->sensor = (id->driver_info >> 8) & 0xff; | 1966 | sd->sensor = (id->driver_info >> 8) & 0xff; |
2007 | sd->i2c_addr = id->driver_info & 0xff; | 1967 | sd->i2c_addr = id->driver_info & 0xff; |
1968 | sd->flags = (id->driver_info >> 16) & 0xff; | ||
2008 | 1969 | ||
2009 | switch (sd->sensor) { | 1970 | switch (sd->sensor) { |
1971 | case SENSOR_MT9M112: | ||
2010 | case SENSOR_MT9M111: | 1972 | case SENSOR_MT9M111: |
2011 | case SENSOR_OV9650: | 1973 | case SENSOR_OV9650: |
2012 | case SENSOR_SOI968: | 1974 | case SENSOR_SOI968: |
@@ -2039,11 +2001,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2039 | 2001 | ||
2040 | sd->quality = 95; | 2002 | sd->quality = 95; |
2041 | 2003 | ||
2042 | #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV | ||
2043 | sd->input_gpio = (id->driver_info >> 16) & 0xff; | ||
2044 | if (sn9c20x_input_init(gspca_dev) < 0) | ||
2045 | return -ENODEV; | ||
2046 | #endif | ||
2047 | return 0; | 2004 | return 0; |
2048 | } | 2005 | } |
2049 | 2006 | ||
@@ -2063,6 +2020,11 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
2063 | } | 2020 | } |
2064 | } | 2021 | } |
2065 | 2022 | ||
2023 | if (sd->flags & LED_REVERSE) | ||
2024 | reg_w1(gspca_dev, 0x1006, 0x00); | ||
2025 | else | ||
2026 | reg_w1(gspca_dev, 0x1006, 0x20); | ||
2027 | |||
2066 | if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { | 2028 | if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { |
2067 | err("Device initialization failed"); | 2029 | err("Device initialization failed"); |
2068 | return -ENODEV; | 2030 | return -ENODEV; |
@@ -2103,6 +2065,11 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
2103 | return -ENODEV; | 2065 | return -ENODEV; |
2104 | info("MT9M111 sensor detected"); | 2066 | info("MT9M111 sensor detected"); |
2105 | break; | 2067 | break; |
2068 | case SENSOR_MT9M112: | ||
2069 | if (mt9m112_init_sensor(gspca_dev) < 0) | ||
2070 | return -ENODEV; | ||
2071 | info("MT9M112 sensor detected"); | ||
2072 | break; | ||
2106 | case SENSOR_MT9M001: | 2073 | case SENSOR_MT9M001: |
2107 | if (mt9m001_init_sensor(gspca_dev) < 0) | 2074 | if (mt9m001_init_sensor(gspca_dev) < 0) |
2108 | return -ENODEV; | 2075 | return -ENODEV; |
@@ -2162,6 +2129,7 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) | |||
2162 | i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); | 2129 | i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); |
2163 | } | 2130 | } |
2164 | break; | 2131 | break; |
2132 | case SENSOR_MT9M112: | ||
2165 | case SENSOR_MT9M111: | 2133 | case SENSOR_MT9M111: |
2166 | if (mode & MODE_SXGA) { | 2134 | if (mode & MODE_SXGA) { |
2167 | i2c_w2(gspca_dev, 0xf0, 0x0002); | 2135 | i2c_w2(gspca_dev, 0xf0, 0x0002); |
@@ -2243,6 +2211,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2243 | set_exposure(gspca_dev); | 2211 | set_exposure(gspca_dev); |
2244 | set_hvflip(gspca_dev); | 2212 | set_hvflip(gspca_dev); |
2245 | 2213 | ||
2214 | reg_w1(gspca_dev, 0x1007, 0x20); | ||
2215 | |||
2246 | reg_r(gspca_dev, 0x1061, 1); | 2216 | reg_r(gspca_dev, 0x1061, 1); |
2247 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); | 2217 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); |
2248 | return 0; | 2218 | return 0; |
@@ -2250,6 +2220,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2250 | 2220 | ||
2251 | static void sd_stopN(struct gspca_dev *gspca_dev) | 2221 | static void sd_stopN(struct gspca_dev *gspca_dev) |
2252 | { | 2222 | { |
2223 | reg_w1(gspca_dev, 0x1007, 0x00); | ||
2224 | |||
2253 | reg_r(gspca_dev, 0x1061, 1); | 2225 | reg_r(gspca_dev, 0x1061, 1); |
2254 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); | 2226 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); |
2255 | } | 2227 | } |
@@ -2343,6 +2315,24 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) | |||
2343 | do_autoexposure(gspca_dev, avg_lum); | 2315 | do_autoexposure(gspca_dev, avg_lum); |
2344 | } | 2316 | } |
2345 | 2317 | ||
2318 | #ifdef CONFIG_INPUT | ||
2319 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
2320 | u8 *data, /* interrupt packet */ | ||
2321 | int len) /* interrupt packet length */ | ||
2322 | { | ||
2323 | struct sd *sd = (struct sd *) gspca_dev; | ||
2324 | int ret = -EINVAL; | ||
2325 | if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { | ||
2326 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
2327 | input_sync(gspca_dev->input_dev); | ||
2328 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
2329 | input_sync(gspca_dev->input_dev); | ||
2330 | ret = 0; | ||
2331 | } | ||
2332 | return ret; | ||
2333 | } | ||
2334 | #endif | ||
2335 | |||
2346 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2336 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2347 | u8 *data, /* isoc packet */ | 2337 | u8 *data, /* isoc packet */ |
2348 | int len) /* iso packet length */ | 2338 | int len) /* iso packet length */ |
@@ -2409,6 +2399,9 @@ static const struct sd_desc sd_desc = { | |||
2409 | .stopN = sd_stopN, | 2399 | .stopN = sd_stopN, |
2410 | .stop0 = sd_stop0, | 2400 | .stop0 = sd_stop0, |
2411 | .pkt_scan = sd_pkt_scan, | 2401 | .pkt_scan = sd_pkt_scan, |
2402 | #ifdef CONFIG_INPUT | ||
2403 | .int_pkt_scan = sd_int_pkt_scan, | ||
2404 | #endif | ||
2412 | .dq_callback = sd_dqcallback, | 2405 | .dq_callback = sd_dqcallback, |
2413 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2406 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2414 | .set_register = sd_dbg_s_register, | 2407 | .set_register = sd_dbg_s_register, |
@@ -2417,8 +2410,8 @@ static const struct sd_desc sd_desc = { | |||
2417 | .get_chip_ident = sd_chip_ident, | 2410 | .get_chip_ident = sd_chip_ident, |
2418 | }; | 2411 | }; |
2419 | 2412 | ||
2420 | #define SN9C20X(sensor, i2c_addr, button_mask) \ | 2413 | #define SN9C20X(sensor, i2c_addr, flags) \ |
2421 | .driver_info = (button_mask << 16) \ | 2414 | .driver_info = ((flags & 0xff) << 16) \ |
2422 | | (SENSOR_ ## sensor << 8) \ | 2415 | | (SENSOR_ ## sensor << 8) \ |
2423 | | (i2c_addr) | 2416 | | (i2c_addr) |
2424 | 2417 | ||
@@ -2426,8 +2419,10 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2426 | {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, | 2419 | {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, |
2427 | {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, | 2420 | {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, |
2428 | {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, | 2421 | {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, |
2429 | {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)}, | 2422 | {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, |
2430 | {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, | 2423 | {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)}, |
2424 | {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, | ||
2425 | (FLIP_DETECT | HAS_NO_BUTTON))}, | ||
2431 | {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, | 2426 | {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, |
2432 | {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, | 2427 | {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, |
2433 | {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, | 2428 | {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, |
@@ -2438,6 +2433,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2438 | {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, | 2433 | {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, |
2439 | {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, | 2434 | {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, |
2440 | {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, | 2435 | {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, |
2436 | {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, | ||
2441 | {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, | 2437 | {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, |
2442 | {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, | 2438 | {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, |
2443 | {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, | 2439 | {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, |
@@ -2448,6 +2444,8 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2448 | {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, | 2444 | {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, |
2449 | {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, | 2445 | {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, |
2450 | {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, | 2446 | {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, |
2447 | {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, | ||
2448 | {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, | ||
2451 | {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, | 2449 | {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, |
2452 | {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, | 2450 | {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, |
2453 | {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, | 2451 | {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, |
@@ -2467,22 +2465,11 @@ static int sd_probe(struct usb_interface *intf, | |||
2467 | THIS_MODULE); | 2465 | THIS_MODULE); |
2468 | } | 2466 | } |
2469 | 2467 | ||
2470 | static void sd_disconnect(struct usb_interface *intf) | ||
2471 | { | ||
2472 | #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV | ||
2473 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | ||
2474 | |||
2475 | sn9c20x_input_cleanup(gspca_dev); | ||
2476 | #endif | ||
2477 | |||
2478 | gspca_disconnect(intf); | ||
2479 | } | ||
2480 | |||
2481 | static struct usb_driver sd_driver = { | 2468 | static struct usb_driver sd_driver = { |
2482 | .name = MODULE_NAME, | 2469 | .name = MODULE_NAME, |
2483 | .id_table = device_table, | 2470 | .id_table = device_table, |
2484 | .probe = sd_probe, | 2471 | .probe = sd_probe, |
2485 | .disconnect = sd_disconnect, | 2472 | .disconnect = gspca_disconnect, |
2486 | #ifdef CONFIG_PM | 2473 | #ifdef CONFIG_PM |
2487 | .suspend = gspca_suspend, | 2474 | .suspend = gspca_suspend, |
2488 | .resume = gspca_resume, | 2475 | .resume = gspca_resume, |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 1d61b92f6bfc..bb923efb75bd 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver | 2 | * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr | 5 | * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -28,7 +28,7 @@ | |||
28 | 28 | ||
29 | #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) | 29 | #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) |
30 | 30 | ||
31 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 31 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); |
32 | MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); | 32 | MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
@@ -67,20 +67,25 @@ struct sd { | |||
67 | #define BRIDGE_SN9C110 2 | 67 | #define BRIDGE_SN9C110 2 |
68 | #define BRIDGE_SN9C120 3 | 68 | #define BRIDGE_SN9C120 3 |
69 | u8 sensor; /* Type of image sensor chip */ | 69 | u8 sensor; /* Type of image sensor chip */ |
70 | #define SENSOR_ADCM1700 0 | 70 | enum { |
71 | #define SENSOR_HV7131R 1 | 71 | SENSOR_ADCM1700, |
72 | #define SENSOR_MI0360 2 | 72 | SENSOR_GC0307, |
73 | #define SENSOR_MO4000 3 | 73 | SENSOR_HV7131R, |
74 | #define SENSOR_MT9V111 4 | 74 | SENSOR_MI0360, |
75 | #define SENSOR_OM6802 5 | 75 | SENSOR_MO4000, |
76 | #define SENSOR_OV7630 6 | 76 | SENSOR_MT9V111, |
77 | #define SENSOR_OV7648 7 | 77 | SENSOR_OM6802, |
78 | #define SENSOR_OV7660 8 | 78 | SENSOR_OV7630, |
79 | #define SENSOR_PO1030 9 | 79 | SENSOR_OV7648, |
80 | #define SENSOR_SP80708 10 | 80 | SENSOR_OV7660, |
81 | SENSOR_PO1030, | ||
82 | SENSOR_PO2030N, | ||
83 | SENSOR_SOI768, | ||
84 | SENSOR_SP80708, | ||
85 | } sensors; | ||
81 | u8 i2c_addr; | 86 | u8 i2c_addr; |
82 | 87 | ||
83 | u8 *jpeg_hdr; | 88 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
84 | }; | 89 | }; |
85 | 90 | ||
86 | /* V4L2 controls supported by the driver */ | 91 | /* V4L2 controls supported by the driver */ |
@@ -281,29 +286,60 @@ static const struct ctrl sd_ctrls[] = { | |||
281 | }; | 286 | }; |
282 | 287 | ||
283 | /* table of the disabled controls */ | 288 | /* table of the disabled controls */ |
284 | static __u32 ctrl_dis[] = { | 289 | static const __u32 ctrl_dis[] = { |
285 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) | | 290 | [SENSOR_ADCM1700] = (1 << AUTOGAIN_IDX) | |
286 | (1 << AUTOGAIN_IDX), /* SENSOR_ADCM1700 0 */ | 291 | (1 << INFRARED_IDX) | |
287 | (1 << INFRARED_IDX) | (1 << FREQ_IDX), | 292 | (1 << VFLIP_IDX) | |
288 | /* SENSOR_HV7131R 1 */ | 293 | (1 << FREQ_IDX), |
289 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 294 | |
290 | /* SENSOR_MI0360 2 */ | 295 | [SENSOR_GC0307] = (1 << INFRARED_IDX) | |
291 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 296 | (1 << VFLIP_IDX) | |
292 | /* SENSOR_MO4000 3 */ | 297 | (1 << FREQ_IDX), |
293 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 298 | |
294 | /* SENSOR_MT9V111 4 */ | 299 | [SENSOR_HV7131R] = (1 << INFRARED_IDX) | |
295 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 300 | (1 << FREQ_IDX), |
296 | /* SENSOR_OM6802 5 */ | 301 | |
297 | (1 << INFRARED_IDX), | 302 | [SENSOR_MI0360] = (1 << INFRARED_IDX) | |
298 | /* SENSOR_OV7630 6 */ | 303 | (1 << VFLIP_IDX) | |
299 | (1 << INFRARED_IDX), | 304 | (1 << FREQ_IDX), |
300 | /* SENSOR_OV7648 7 */ | 305 | |
301 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 306 | [SENSOR_MO4000] = (1 << INFRARED_IDX) | |
302 | /* SENSOR_OV7660 8 */ | 307 | (1 << VFLIP_IDX) | |
303 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 308 | (1 << FREQ_IDX), |
304 | (1 << FREQ_IDX), /* SENSOR_PO1030 9 */ | 309 | |
305 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 310 | [SENSOR_MT9V111] = (1 << VFLIP_IDX) | |
306 | (1 << FREQ_IDX), /* SENSOR_SP80708 10 */ | 311 | (1 << FREQ_IDX), |
312 | |||
313 | [SENSOR_OM6802] = (1 << INFRARED_IDX) | | ||
314 | (1 << VFLIP_IDX) | | ||
315 | (1 << FREQ_IDX), | ||
316 | |||
317 | [SENSOR_OV7630] = (1 << INFRARED_IDX), | ||
318 | |||
319 | [SENSOR_OV7648] = (1 << INFRARED_IDX), | ||
320 | |||
321 | [SENSOR_OV7660] = (1 << AUTOGAIN_IDX) | | ||
322 | (1 << INFRARED_IDX) | | ||
323 | (1 << VFLIP_IDX), | ||
324 | |||
325 | [SENSOR_PO1030] = (1 << AUTOGAIN_IDX) | | ||
326 | (1 << INFRARED_IDX) | | ||
327 | (1 << VFLIP_IDX) | | ||
328 | (1 << FREQ_IDX), | ||
329 | |||
330 | [SENSOR_PO2030N] = (1 << AUTOGAIN_IDX) | | ||
331 | (1 << INFRARED_IDX) | | ||
332 | (1 << VFLIP_IDX) | | ||
333 | (1 << FREQ_IDX), | ||
334 | [SENSOR_SOI768] = (1 << AUTOGAIN_IDX) | | ||
335 | (1 << INFRARED_IDX) | | ||
336 | (1 << VFLIP_IDX) | | ||
337 | (1 << FREQ_IDX), | ||
338 | |||
339 | [SENSOR_SP80708] = (1 << AUTOGAIN_IDX) | | ||
340 | (1 << INFRARED_IDX) | | ||
341 | (1 << VFLIP_IDX) | | ||
342 | (1 << FREQ_IDX), | ||
307 | }; | 343 | }; |
308 | 344 | ||
309 | static const struct v4l2_pix_format cif_mode[] = { | 345 | static const struct v4l2_pix_format cif_mode[] = { |
@@ -343,7 +379,17 @@ static const u8 sn_adcm1700[0x1c] = { | |||
343 | 0x06, 0x00, 0x00, 0x00 | 379 | 0x06, 0x00, 0x00, 0x00 |
344 | }; | 380 | }; |
345 | 381 | ||
346 | /*Data from sn9c102p+hv7131r */ | 382 | static const u8 sn_gc0307[0x1c] = { |
383 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
384 | 0x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00, | ||
385 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
386 | 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
387 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
388 | 0x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02, | ||
389 | /* reg18 reg19 reg1a reg1b */ | ||
390 | 0x06, 0x00, 0x00, 0x00 | ||
391 | }; | ||
392 | |||
347 | static const u8 sn_hv7131[0x1c] = { | 393 | static const u8 sn_hv7131[0x1c] = { |
348 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 394 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
349 | 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, | 395 | 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, |
@@ -401,7 +447,7 @@ static const u8 sn_om6802[0x1c] = { | |||
401 | 447 | ||
402 | static const u8 sn_ov7630[0x1c] = { | 448 | static const u8 sn_ov7630[0x1c] = { |
403 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 449 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
404 | 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, | 450 | 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, |
405 | /* reg8 reg9 rega regb regc regd rege regf */ | 451 | /* reg8 reg9 rega regb regc regd rege regf */ |
406 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 452 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
407 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 453 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
@@ -443,6 +489,28 @@ static const u8 sn_po1030[0x1c] = { | |||
443 | 0x07, 0x00, 0x00, 0x00 | 489 | 0x07, 0x00, 0x00, 0x00 |
444 | }; | 490 | }; |
445 | 491 | ||
492 | static const u8 sn_po2030n[0x1c] = { | ||
493 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
494 | 0x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, | ||
495 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
496 | 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
497 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
498 | 0x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00, | ||
499 | /* reg18 reg19 reg1a reg1b */ | ||
500 | 0x07, 0x00, 0x00, 0x00 | ||
501 | }; | ||
502 | |||
503 | static const u8 sn_soi768[0x1c] = { | ||
504 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
505 | 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, | ||
506 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
507 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
508 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
509 | 0x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00, | ||
510 | /* reg18 reg19 reg1a reg1b */ | ||
511 | 0x07, 0x00, 0x00, 0x00 | ||
512 | }; | ||
513 | |||
446 | static const u8 sn_sp80708[0x1c] = { | 514 | static const u8 sn_sp80708[0x1c] = { |
447 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 515 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
448 | 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, | 516 | 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, |
@@ -456,17 +524,20 @@ static const u8 sn_sp80708[0x1c] = { | |||
456 | 524 | ||
457 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ | 525 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ |
458 | static const u8 *sn_tb[] = { | 526 | static const u8 *sn_tb[] = { |
459 | sn_adcm1700, | 527 | [SENSOR_ADCM1700] = sn_adcm1700, |
460 | sn_hv7131, | 528 | [SENSOR_GC0307] = sn_gc0307, |
461 | sn_mi0360, | 529 | [SENSOR_HV7131R] = sn_hv7131, |
462 | sn_mo4000, | 530 | [SENSOR_MI0360] = sn_mi0360, |
463 | sn_mt9v111, | 531 | [SENSOR_MO4000] = sn_mo4000, |
464 | sn_om6802, | 532 | [SENSOR_MT9V111] = sn_mt9v111, |
465 | sn_ov7630, | 533 | [SENSOR_OM6802] = sn_om6802, |
466 | sn_ov7648, | 534 | [SENSOR_OV7630] = sn_ov7630, |
467 | sn_ov7660, | 535 | [SENSOR_OV7648] = sn_ov7648, |
468 | sn_po1030, | 536 | [SENSOR_OV7660] = sn_ov7660, |
469 | sn_sp80708 | 537 | [SENSOR_PO1030] = sn_po1030, |
538 | [SENSOR_PO2030N] = sn_po2030n, | ||
539 | [SENSOR_SOI768] = sn_soi768, | ||
540 | [SENSOR_SP80708] = sn_sp80708, | ||
470 | }; | 541 | }; |
471 | 542 | ||
472 | /* default gamma table */ | 543 | /* default gamma table */ |
@@ -484,8 +555,13 @@ static const u8 gamma_spec_1[17] = { | |||
484 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, | 555 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, |
485 | 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 | 556 | 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 |
486 | }; | 557 | }; |
487 | /* gamma for sensor SP80708 */ | 558 | /* gamma for sensor GC0307 */ |
488 | static const u8 gamma_spec_2[17] = { | 559 | static const u8 gamma_spec_2[17] = { |
560 | 0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab, | ||
561 | 0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb | ||
562 | }; | ||
563 | /* gamma for sensor SP80708 */ | ||
564 | static const u8 gamma_spec_3[17] = { | ||
489 | 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, | 565 | 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, |
490 | 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 | 566 | 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 |
491 | }; | 567 | }; |
@@ -533,6 +609,58 @@ static const u8 adcm1700_sensor_param1[][8] = { | |||
533 | {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, | 609 | {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, |
534 | {} | 610 | {} |
535 | }; | 611 | }; |
612 | static const u8 gc0307_sensor_init[][8] = { | ||
613 | {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
614 | {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10}, | ||
615 | {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10}, | ||
616 | {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10}, | ||
617 | {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
618 | {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
619 | {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
620 | {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10}, | ||
621 | {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
622 | {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
623 | {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
624 | {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
625 | {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
626 | {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10}, | ||
627 | {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
628 | {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10}, | ||
629 | {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10}, | ||
630 | {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
631 | {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10}, | ||
632 | {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10}, | ||
633 | {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/ | ||
634 | {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
635 | {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10}, | ||
636 | {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10}, | ||
637 | {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10}, | ||
638 | {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10}, | ||
639 | {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10}, | ||
640 | {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10}, | ||
641 | {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10}, | ||
642 | {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10}, | ||
643 | {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10}, | ||
644 | {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10}, | ||
645 | {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
646 | {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10}, | ||
647 | {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10}, | ||
648 | {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10}, | ||
649 | {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10}, | ||
650 | {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10}, | ||
651 | {} | ||
652 | }; | ||
653 | static const u8 gc0307_sensor_param1[][8] = { | ||
654 | {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10}, | ||
655 | {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10}, | ||
656 | {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10}, | ||
657 | {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10}, | ||
658 | /*param3*/ | ||
659 | {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10}, | ||
660 | {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10}, | ||
661 | {} | ||
662 | }; | ||
663 | |||
536 | static const u8 hv7131r_sensor_init[][8] = { | 664 | static const u8 hv7131r_sensor_init[][8] = { |
537 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, | 665 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, |
538 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, | 666 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, |
@@ -767,7 +895,9 @@ static const u8 ov7630_sensor_init[][8] = { | |||
767 | {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10}, | 895 | {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10}, |
768 | {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, | 896 | {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, |
769 | {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, | 897 | {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, |
770 | /* */ | 898 | {} |
899 | }; | ||
900 | static const u8 ov7630_sensor_param1[][8] = { | ||
771 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 901 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
772 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 902 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
773 | /*fixme: + 0x12, 0x04*/ | 903 | /*fixme: + 0x12, 0x04*/ |
@@ -984,6 +1114,113 @@ static const u8 po1030_sensor_param1[][8] = { | |||
984 | {} | 1114 | {} |
985 | }; | 1115 | }; |
986 | 1116 | ||
1117 | static const u8 po2030n_sensor_init[][8] = { | ||
1118 | {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10}, | ||
1119 | {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10}, | ||
1120 | {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ | ||
1121 | {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10}, | ||
1122 | {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10}, | ||
1123 | {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ | ||
1124 | {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10}, | ||
1125 | {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
1126 | {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10}, | ||
1127 | {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
1128 | {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, | ||
1129 | {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10}, | ||
1130 | {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10}, | ||
1131 | {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10}, | ||
1132 | {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1133 | {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1134 | {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1135 | {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1136 | {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1137 | {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1138 | {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1139 | {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1140 | {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1141 | {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1142 | {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1143 | {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10}, | ||
1144 | {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10}, | ||
1145 | {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1146 | {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1147 | {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1148 | {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1149 | {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1150 | {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1151 | {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1152 | {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1153 | {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1154 | {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1155 | {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1156 | {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1157 | {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10}, | ||
1158 | {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10}, | ||
1159 | {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1160 | {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1161 | {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10}, | ||
1162 | {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10}, | ||
1163 | {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10}, | ||
1164 | {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10}, | ||
1165 | {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10}, | ||
1166 | {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10}, | ||
1167 | {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10}, | ||
1168 | {} | ||
1169 | }; | ||
1170 | static const u8 po2030n_sensor_param1[][8] = { | ||
1171 | {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
1172 | {0xdd, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */ | ||
1173 | {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10}, | ||
1174 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
1175 | {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10}, | ||
1176 | /*param2*/ | ||
1177 | {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1178 | {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
1179 | {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, | ||
1180 | {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
1181 | {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, | ||
1182 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
1183 | {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, | ||
1184 | /*after start*/ | ||
1185 | {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, | ||
1186 | {0xdd, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ | ||
1187 | {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, | ||
1188 | {0xdd, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ | ||
1189 | {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, | ||
1190 | {} | ||
1191 | }; | ||
1192 | |||
1193 | static const u8 soi768_sensor_init[][8] = { | ||
1194 | {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ | ||
1195 | {0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */ | ||
1196 | {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1197 | {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, | ||
1198 | {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
1199 | {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1200 | {} | ||
1201 | }; | ||
1202 | static const u8 soi768_sensor_param1[][8] = { | ||
1203 | {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
1204 | {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1205 | {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1206 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1207 | {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10}, | ||
1208 | /* */ | ||
1209 | /* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */ | ||
1210 | /* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */ | ||
1211 | {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
1212 | /* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */ | ||
1213 | {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10}, | ||
1214 | /* the next sequence should be used for auto gain */ | ||
1215 | {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10}, | ||
1216 | /* global gain ? : 07 - change with 0x15 at the end */ | ||
1217 | {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */ | ||
1218 | {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10}, | ||
1219 | {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10}, | ||
1220 | /* exposure ? : 0200 - change with 0x1e at the end */ | ||
1221 | {} | ||
1222 | }; | ||
1223 | |||
987 | static const u8 sp80708_sensor_init[][8] = { | 1224 | static const u8 sp80708_sensor_init[][8] = { |
988 | {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, | 1225 | {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, |
989 | {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, | 1226 | {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, |
@@ -1069,18 +1306,21 @@ static const u8 sp80708_sensor_param1[][8] = { | |||
1069 | {} | 1306 | {} |
1070 | }; | 1307 | }; |
1071 | 1308 | ||
1072 | static const u8 (*sensor_init[11])[8] = { | 1309 | static const u8 (*sensor_init[])[8] = { |
1073 | adcm1700_sensor_init, /* ADCM1700 0 */ | 1310 | [SENSOR_ADCM1700] = adcm1700_sensor_init, |
1074 | hv7131r_sensor_init, /* HV7131R 1 */ | 1311 | [SENSOR_GC0307] = gc0307_sensor_init, |
1075 | mi0360_sensor_init, /* MI0360 2 */ | 1312 | [SENSOR_HV7131R] = hv7131r_sensor_init, |
1076 | mo4000_sensor_init, /* MO4000 3 */ | 1313 | [SENSOR_MI0360] = mi0360_sensor_init, |
1077 | mt9v111_sensor_init, /* MT9V111 4 */ | 1314 | [SENSOR_MO4000] = mo4000_sensor_init, |
1078 | om6802_sensor_init, /* OM6802 5 */ | 1315 | [SENSOR_MT9V111] = mt9v111_sensor_init, |
1079 | ov7630_sensor_init, /* OV7630 6 */ | 1316 | [SENSOR_OM6802] = om6802_sensor_init, |
1080 | ov7648_sensor_init, /* OV7648 7 */ | 1317 | [SENSOR_OV7630] = ov7630_sensor_init, |
1081 | ov7660_sensor_init, /* OV7660 8 */ | 1318 | [SENSOR_OV7648] = ov7648_sensor_init, |
1082 | po1030_sensor_init, /* PO1030 9 */ | 1319 | [SENSOR_OV7660] = ov7660_sensor_init, |
1083 | sp80708_sensor_init, /* SP80708 10 */ | 1320 | [SENSOR_PO1030] = po1030_sensor_init, |
1321 | [SENSOR_PO2030N] = po2030n_sensor_init, | ||
1322 | [SENSOR_SOI768] = soi768_sensor_init, | ||
1323 | [SENSOR_SP80708] = sp80708_sensor_init, | ||
1084 | }; | 1324 | }; |
1085 | 1325 | ||
1086 | /* read <len> bytes to gspca_dev->usb_buf */ | 1326 | /* read <len> bytes to gspca_dev->usb_buf */ |
@@ -1146,10 +1386,11 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1146 | { | 1386 | { |
1147 | struct sd *sd = (struct sd *) gspca_dev; | 1387 | struct sd *sd = (struct sd *) gspca_dev; |
1148 | 1388 | ||
1149 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); | 1389 | PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val); |
1150 | switch (sd->sensor) { | 1390 | switch (sd->sensor) { |
1151 | case SENSOR_ADCM1700: | 1391 | case SENSOR_ADCM1700: |
1152 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ | 1392 | case SENSOR_OM6802: |
1393 | case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ | ||
1153 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); | 1394 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); |
1154 | break; | 1395 | break; |
1155 | default: /* i2c command = a1 (400 kHz) */ | 1396 | default: /* i2c command = a1 (400 kHz) */ |
@@ -1177,6 +1418,8 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1177 | static void i2c_w8(struct gspca_dev *gspca_dev, | 1418 | static void i2c_w8(struct gspca_dev *gspca_dev, |
1178 | const u8 *buffer) | 1419 | const u8 *buffer) |
1179 | { | 1420 | { |
1421 | PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..", | ||
1422 | buffer[2], buffer[3]); | ||
1180 | memcpy(gspca_dev->usb_buf, buffer, 8); | 1423 | memcpy(gspca_dev->usb_buf, buffer, 8); |
1181 | usb_control_msg(gspca_dev->dev, | 1424 | usb_control_msg(gspca_dev->dev, |
1182 | usb_sndctrlpipe(gspca_dev->dev, 0), | 1425 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -1196,7 +1439,8 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) | |||
1196 | 1439 | ||
1197 | switch (sd->sensor) { | 1440 | switch (sd->sensor) { |
1198 | case SENSOR_ADCM1700: | 1441 | case SENSOR_ADCM1700: |
1199 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ | 1442 | case SENSOR_OM6802: |
1443 | case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ | ||
1200 | mode[0] = 0x80 | 0x10; | 1444 | mode[0] = 0x80 | 0x10; |
1201 | break; | 1445 | break; |
1202 | default: /* i2c command = 91 (400 kHz) */ | 1446 | default: /* i2c command = 91 (400 kHz) */ |
@@ -1300,39 +1544,100 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) | |||
1300 | } | 1544 | } |
1301 | } | 1545 | } |
1302 | 1546 | ||
1303 | static void ov7648_probe(struct gspca_dev *gspca_dev) | 1547 | static void ov7630_probe(struct gspca_dev *gspca_dev) |
1304 | { | 1548 | { |
1305 | struct sd *sd = (struct sd *) gspca_dev; | 1549 | struct sd *sd = (struct sd *) gspca_dev; |
1550 | u16 val; | ||
1306 | 1551 | ||
1307 | /* check ov76xx */ | 1552 | /* check ov76xx */ |
1308 | reg_w1(gspca_dev, 0x17, 0x62); | 1553 | reg_w1(gspca_dev, 0x17, 0x62); |
1309 | reg_w1(gspca_dev, 0x01, 0x08); | 1554 | reg_w1(gspca_dev, 0x01, 0x08); |
1310 | sd->i2c_addr = 0x21; | 1555 | sd->i2c_addr = 0x21; |
1311 | i2c_r(gspca_dev, 0x0a, 2); | 1556 | i2c_r(gspca_dev, 0x0a, 2); |
1312 | if (gspca_dev->usb_buf[3] == 0x76) { /* ov76xx */ | 1557 | val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; |
1313 | PDEBUG(D_PROBE, "Sensor ov%02x%02x", | 1558 | reg_w1(gspca_dev, 0x01, 0x29); |
1314 | gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); | 1559 | reg_w1(gspca_dev, 0x17, 0x42); |
1560 | if (val == 0x7628) { /* soi768 */ | ||
1561 | sd->sensor = SENSOR_SOI768; | ||
1562 | /*fixme: only valid for 0c45:613e?*/ | ||
1563 | gspca_dev->cam.input_flags = | ||
1564 | V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; | ||
1565 | PDEBUG(D_PROBE, "Sensor soi768"); | ||
1315 | return; | 1566 | return; |
1316 | } | 1567 | } |
1568 | PDEBUG(D_PROBE, "Sensor ov%04x", val); | ||
1569 | } | ||
1317 | 1570 | ||
1318 | /* reset */ | 1571 | static void ov7648_probe(struct gspca_dev *gspca_dev) |
1572 | { | ||
1573 | struct sd *sd = (struct sd *) gspca_dev; | ||
1574 | u16 val; | ||
1575 | |||
1576 | /* check ov76xx */ | ||
1577 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1578 | reg_w1(gspca_dev, 0x01, 0x08); | ||
1579 | sd->i2c_addr = 0x21; | ||
1580 | i2c_r(gspca_dev, 0x0a, 2); | ||
1581 | val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; | ||
1319 | reg_w1(gspca_dev, 0x01, 0x29); | 1582 | reg_w1(gspca_dev, 0x01, 0x29); |
1320 | reg_w1(gspca_dev, 0x17, 0x42); | 1583 | reg_w1(gspca_dev, 0x17, 0x42); |
1584 | if ((val & 0xff00) == 0x7600) { /* ov76xx */ | ||
1585 | PDEBUG(D_PROBE, "Sensor ov%04x", val); | ||
1586 | return; | ||
1587 | } | ||
1321 | 1588 | ||
1322 | /* check po1030 */ | 1589 | /* check po1030 */ |
1323 | reg_w1(gspca_dev, 0x17, 0x62); | 1590 | reg_w1(gspca_dev, 0x17, 0x62); |
1324 | reg_w1(gspca_dev, 0x01, 0x08); | 1591 | reg_w1(gspca_dev, 0x01, 0x08); |
1325 | sd->i2c_addr = 0x6e; | 1592 | sd->i2c_addr = 0x6e; |
1326 | i2c_r(gspca_dev, 0x00, 2); | 1593 | i2c_r(gspca_dev, 0x00, 2); |
1327 | if (gspca_dev->usb_buf[3] == 0x10 /* po1030 */ | 1594 | val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; |
1328 | && gspca_dev->usb_buf[4] == 0x30) { | 1595 | reg_w1(gspca_dev, 0x01, 0x29); |
1596 | reg_w1(gspca_dev, 0x17, 0x42); | ||
1597 | if (val == 0x1030) { /* po1030 */ | ||
1329 | PDEBUG(D_PROBE, "Sensor po1030"); | 1598 | PDEBUG(D_PROBE, "Sensor po1030"); |
1330 | sd->sensor = SENSOR_PO1030; | 1599 | sd->sensor = SENSOR_PO1030; |
1331 | return; | 1600 | return; |
1332 | } | 1601 | } |
1333 | 1602 | ||
1334 | PDEBUG(D_PROBE, "Unknown sensor %02x%02x", | 1603 | PDEBUG(D_PROBE, "Unknown sensor %04x", val); |
1335 | gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); | 1604 | } |
1605 | |||
1606 | /* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */ | ||
1607 | static void po2030n_probe(struct gspca_dev *gspca_dev) | ||
1608 | { | ||
1609 | struct sd *sd = (struct sd *) gspca_dev; | ||
1610 | u16 val; | ||
1611 | |||
1612 | /* check gc0307 */ | ||
1613 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1614 | reg_w1(gspca_dev, 0x01, 0x08); | ||
1615 | reg_w1(gspca_dev, 0x02, 0x22); | ||
1616 | sd->i2c_addr = 0x21; | ||
1617 | i2c_r(gspca_dev, 0x00, 1); | ||
1618 | val = gspca_dev->usb_buf[4]; | ||
1619 | reg_w1(gspca_dev, 0x01, 0x29); /* reset */ | ||
1620 | reg_w1(gspca_dev, 0x17, 0x42); | ||
1621 | if (val == 0x99) { /* gc0307 (?) */ | ||
1622 | PDEBUG(D_PROBE, "Sensor gc0307"); | ||
1623 | sd->sensor = SENSOR_GC0307; | ||
1624 | return; | ||
1625 | } | ||
1626 | |||
1627 | /* check po2030n */ | ||
1628 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1629 | reg_w1(gspca_dev, 0x01, 0x0a); | ||
1630 | sd->i2c_addr = 0x6e; | ||
1631 | i2c_r(gspca_dev, 0x00, 2); | ||
1632 | val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; | ||
1633 | reg_w1(gspca_dev, 0x01, 0x29); | ||
1634 | reg_w1(gspca_dev, 0x17, 0x42); | ||
1635 | if (val == 0x2030) { | ||
1636 | PDEBUG(D_PROBE, "Sensor po2030n"); | ||
1637 | /* sd->sensor = SENSOR_PO2030N; */ | ||
1638 | } else { | ||
1639 | PDEBUG(D_PROBE, "Unknown sensor ID %04x", val); | ||
1640 | } | ||
1336 | } | 1641 | } |
1337 | 1642 | ||
1338 | static void bridge_init(struct gspca_dev *gspca_dev, | 1643 | static void bridge_init(struct gspca_dev *gspca_dev, |
@@ -1355,8 +1660,11 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1355 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); | 1660 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); |
1356 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); | 1661 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); |
1357 | switch (sd->sensor) { | 1662 | switch (sd->sensor) { |
1663 | case SENSOR_GC0307: | ||
1358 | case SENSOR_OV7660: | 1664 | case SENSOR_OV7660: |
1359 | case SENSOR_PO1030: | 1665 | case SENSOR_PO1030: |
1666 | case SENSOR_PO2030N: | ||
1667 | case SENSOR_SOI768: | ||
1360 | case SENSOR_SP80708: | 1668 | case SENSOR_SP80708: |
1361 | reg9a = reg9a_spec; | 1669 | reg9a = reg9a_spec; |
1362 | break; | 1670 | break; |
@@ -1377,6 +1685,14 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1377 | reg_w1(gspca_dev, 0x01, 0x42); | 1685 | reg_w1(gspca_dev, 0x01, 0x42); |
1378 | reg_w1(gspca_dev, 0x01, 0x42); | 1686 | reg_w1(gspca_dev, 0x01, 0x42); |
1379 | break; | 1687 | break; |
1688 | case SENSOR_GC0307: | ||
1689 | msleep(50); | ||
1690 | reg_w1(gspca_dev, 0x01, 0x61); | ||
1691 | reg_w1(gspca_dev, 0x17, 0x22); | ||
1692 | reg_w1(gspca_dev, 0x01, 0x60); | ||
1693 | reg_w1(gspca_dev, 0x01, 0x40); | ||
1694 | msleep(50); | ||
1695 | break; | ||
1380 | case SENSOR_MT9V111: | 1696 | case SENSOR_MT9V111: |
1381 | reg_w1(gspca_dev, 0x01, 0x61); | 1697 | reg_w1(gspca_dev, 0x01, 0x61); |
1382 | reg_w1(gspca_dev, 0x17, 0x61); | 1698 | reg_w1(gspca_dev, 0x17, 0x61); |
@@ -1414,11 +1730,18 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1414 | reg_w1(gspca_dev, 0x01, 0x42); | 1730 | reg_w1(gspca_dev, 0x01, 0x42); |
1415 | break; | 1731 | break; |
1416 | case SENSOR_PO1030: | 1732 | case SENSOR_PO1030: |
1733 | case SENSOR_SOI768: | ||
1417 | reg_w1(gspca_dev, 0x01, 0x61); | 1734 | reg_w1(gspca_dev, 0x01, 0x61); |
1418 | reg_w1(gspca_dev, 0x17, 0x20); | 1735 | reg_w1(gspca_dev, 0x17, 0x20); |
1419 | reg_w1(gspca_dev, 0x01, 0x60); | 1736 | reg_w1(gspca_dev, 0x01, 0x60); |
1420 | reg_w1(gspca_dev, 0x01, 0x40); | 1737 | reg_w1(gspca_dev, 0x01, 0x40); |
1421 | break; | 1738 | break; |
1739 | case SENSOR_PO2030N: | ||
1740 | reg_w1(gspca_dev, 0x01, 0x63); | ||
1741 | reg_w1(gspca_dev, 0x17, 0x20); | ||
1742 | reg_w1(gspca_dev, 0x01, 0x62); | ||
1743 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1744 | break; | ||
1422 | case SENSOR_OV7660: | 1745 | case SENSOR_OV7660: |
1423 | /* fall thru */ | 1746 | /* fall thru */ |
1424 | case SENSOR_SP80708: | 1747 | case SENSOR_SP80708: |
@@ -1523,9 +1846,15 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1523 | case SENSOR_MI0360: | 1846 | case SENSOR_MI0360: |
1524 | mi0360_probe(gspca_dev); | 1847 | mi0360_probe(gspca_dev); |
1525 | break; | 1848 | break; |
1849 | case SENSOR_OV7630: | ||
1850 | ov7630_probe(gspca_dev); | ||
1851 | break; | ||
1526 | case SENSOR_OV7648: | 1852 | case SENSOR_OV7648: |
1527 | ov7648_probe(gspca_dev); | 1853 | ov7648_probe(gspca_dev); |
1528 | break; | 1854 | break; |
1855 | case SENSOR_PO2030N: | ||
1856 | po2030n_probe(gspca_dev); | ||
1857 | break; | ||
1529 | } | 1858 | } |
1530 | regGpio[1] = 0x70; | 1859 | regGpio[1] = 0x70; |
1531 | reg_w(gspca_dev, 0x01, regGpio, 2); | 1860 | reg_w(gspca_dev, 0x01, regGpio, 2); |
@@ -1558,6 +1887,18 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1558 | struct sd *sd = (struct sd *) gspca_dev; | 1887 | struct sd *sd = (struct sd *) gspca_dev; |
1559 | 1888 | ||
1560 | switch (sd->sensor) { | 1889 | switch (sd->sensor) { |
1890 | case SENSOR_GC0307: { | ||
1891 | int a, b; | ||
1892 | |||
1893 | /* expo = 0..255 -> a = 19..43 */ | ||
1894 | a = 19 + expo * 25 / 256; | ||
1895 | i2c_w1(gspca_dev, 0x68, a); | ||
1896 | a -= 12; | ||
1897 | b = a * a * 4; /* heuristic */ | ||
1898 | i2c_w1(gspca_dev, 0x03, b >> 8); | ||
1899 | i2c_w1(gspca_dev, 0x04, b); | ||
1900 | break; | ||
1901 | } | ||
1561 | case SENSOR_HV7131R: { | 1902 | case SENSOR_HV7131R: { |
1562 | u8 Expodoit[] = | 1903 | u8 Expodoit[] = |
1563 | { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; | 1904 | { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; |
@@ -1668,6 +2009,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1668 | expo = sd->brightness >> 4; | 2009 | expo = sd->brightness >> 4; |
1669 | sd->exposure = setexposure(gspca_dev, expo); | 2010 | sd->exposure = setexposure(gspca_dev, expo); |
1670 | break; | 2011 | break; |
2012 | case SENSOR_GC0307: | ||
1671 | case SENSOR_MT9V111: | 2013 | case SENSOR_MT9V111: |
1672 | expo = sd->brightness >> 8; | 2014 | expo = sd->brightness >> 8; |
1673 | sd->exposure = setexposure(gspca_dev, expo); | 2015 | sd->exposure = setexposure(gspca_dev, expo); |
@@ -1703,7 +2045,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
1703 | struct sd *sd = (struct sd *) gspca_dev; | 2045 | struct sd *sd = (struct sd *) gspca_dev; |
1704 | int i, v; | 2046 | int i, v; |
1705 | u8 reg8a[12]; /* U & V gains */ | 2047 | u8 reg8a[12]; /* U & V gains */ |
1706 | static s16 uv[6] = { /* same as reg84 in signed decimal */ | 2048 | static const s16 uv[6] = { /* same as reg84 in signed decimal */ |
1707 | -24, -38, 64, /* UR UG UB */ | 2049 | -24, -38, 64, /* UR UG UB */ |
1708 | 62, -51, -9 /* VR VG VB */ | 2050 | 62, -51, -9 /* VR VG VB */ |
1709 | }; | 2051 | }; |
@@ -1744,9 +2086,12 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
1744 | case SENSOR_MT9V111: | 2086 | case SENSOR_MT9V111: |
1745 | gamma_base = gamma_spec_1; | 2087 | gamma_base = gamma_spec_1; |
1746 | break; | 2088 | break; |
1747 | case SENSOR_SP80708: | 2089 | case SENSOR_GC0307: |
1748 | gamma_base = gamma_spec_2; | 2090 | gamma_base = gamma_spec_2; |
1749 | break; | 2091 | break; |
2092 | case SENSOR_SP80708: | ||
2093 | gamma_base = gamma_spec_3; | ||
2094 | break; | ||
1750 | default: | 2095 | default: |
1751 | gamma_base = gamma_def; | 2096 | gamma_base = gamma_def; |
1752 | break; | 2097 | break; |
@@ -1937,14 +2282,17 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1937 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; | 2282 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; |
1938 | static const u8 CA_adcm1700[] = | 2283 | static const u8 CA_adcm1700[] = |
1939 | { 0x14, 0xec, 0x0a, 0xf6 }; | 2284 | { 0x14, 0xec, 0x0a, 0xf6 }; |
2285 | static const u8 CA_po2030n[] = | ||
2286 | { 0x1e, 0xe2, 0x14, 0xec }; | ||
1940 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ | 2287 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ |
2288 | static const u8 CE_gc0307[] = | ||
2289 | { 0x32, 0xce, 0x2d, 0xd3 }; | ||
1941 | static const u8 CE_ov76xx[] = | 2290 | static const u8 CE_ov76xx[] = |
1942 | { 0x32, 0xdd, 0x32, 0xdd }; | 2291 | { 0x32, 0xdd, 0x32, 0xdd }; |
2292 | static const u8 CE_po2030n[] = | ||
2293 | { 0x14, 0xe7, 0x1e, 0xdd }; | ||
1943 | 2294 | ||
1944 | /* create the JPEG header */ | 2295 | /* create the JPEG header */ |
1945 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
1946 | if (!sd->jpeg_hdr) | ||
1947 | return -ENOMEM; | ||
1948 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 2296 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
1949 | 0x21); /* JPEG 422 */ | 2297 | 0x21); /* JPEG 422 */ |
1950 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 2298 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -1996,6 +2344,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1996 | } | 2344 | } |
1997 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); | 2345 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); |
1998 | switch (sd->sensor) { | 2346 | switch (sd->sensor) { |
2347 | case SENSOR_GC0307: | ||
2348 | reg17 = 0xa2; | ||
2349 | break; | ||
1999 | case SENSOR_MT9V111: | 2350 | case SENSOR_MT9V111: |
2000 | reg17 = 0xe0; | 2351 | reg17 = 0xe0; |
2001 | break; | 2352 | break; |
@@ -2007,9 +2358,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2007 | reg17 = 0x20; | 2358 | reg17 = 0x20; |
2008 | break; | 2359 | break; |
2009 | case SENSOR_OV7660: | 2360 | case SENSOR_OV7660: |
2361 | case SENSOR_SOI768: | ||
2010 | reg17 = 0xa0; | 2362 | reg17 = 0xa0; |
2011 | break; | 2363 | break; |
2012 | case SENSOR_PO1030: | 2364 | case SENSOR_PO1030: |
2365 | case SENSOR_PO2030N: | ||
2013 | reg17 = 0xa0; | 2366 | reg17 = 0xa0; |
2014 | break; | 2367 | break; |
2015 | default: | 2368 | default: |
@@ -2034,12 +2387,18 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2034 | case SENSOR_SP80708: | 2387 | case SENSOR_SP80708: |
2035 | reg_w1(gspca_dev, 0x9a, 0x05); | 2388 | reg_w1(gspca_dev, 0x9a, 0x05); |
2036 | break; | 2389 | break; |
2390 | case SENSOR_GC0307: | ||
2037 | case SENSOR_MT9V111: | 2391 | case SENSOR_MT9V111: |
2038 | reg_w1(gspca_dev, 0x9a, 0x07); | 2392 | reg_w1(gspca_dev, 0x9a, 0x07); |
2039 | break; | 2393 | break; |
2394 | case SENSOR_OV7630: | ||
2040 | case SENSOR_OV7648: | 2395 | case SENSOR_OV7648: |
2041 | reg_w1(gspca_dev, 0x9a, 0x0a); | 2396 | reg_w1(gspca_dev, 0x9a, 0x0a); |
2042 | break; | 2397 | break; |
2398 | case SENSOR_PO2030N: | ||
2399 | case SENSOR_SOI768: | ||
2400 | reg_w1(gspca_dev, 0x9a, 0x06); | ||
2401 | break; | ||
2043 | default: | 2402 | default: |
2044 | reg_w1(gspca_dev, 0x9a, 0x08); | 2403 | reg_w1(gspca_dev, 0x9a, 0x08); |
2045 | break; | 2404 | break; |
@@ -2064,6 +2423,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2064 | reg1 = 0x46; | 2423 | reg1 = 0x46; |
2065 | reg17 = 0xe2; | 2424 | reg17 = 0xe2; |
2066 | break; | 2425 | break; |
2426 | case SENSOR_GC0307: | ||
2427 | init = gc0307_sensor_param1; | ||
2428 | reg17 = 0xa2; | ||
2429 | reg1 = 0x44; | ||
2430 | break; | ||
2067 | case SENSOR_MO4000: | 2431 | case SENSOR_MO4000: |
2068 | if (mode) { | 2432 | if (mode) { |
2069 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ | 2433 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ |
@@ -2087,6 +2451,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2087 | reg17 = 0x64; /* 640 MCKSIZE */ | 2451 | reg17 = 0x64; /* 640 MCKSIZE */ |
2088 | break; | 2452 | break; |
2089 | case SENSOR_OV7630: | 2453 | case SENSOR_OV7630: |
2454 | init = ov7630_sensor_param1; | ||
2090 | reg17 = 0xe2; | 2455 | reg17 = 0xe2; |
2091 | reg1 = 0x44; | 2456 | reg1 = 0x44; |
2092 | break; | 2457 | break; |
@@ -2113,6 +2478,16 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2113 | reg17 = 0xa2; | 2478 | reg17 = 0xa2; |
2114 | reg1 = 0x44; | 2479 | reg1 = 0x44; |
2115 | break; | 2480 | break; |
2481 | case SENSOR_PO2030N: | ||
2482 | init = po2030n_sensor_param1; | ||
2483 | reg1 = 0x46; | ||
2484 | reg17 = 0xa2; | ||
2485 | break; | ||
2486 | case SENSOR_SOI768: | ||
2487 | init = soi768_sensor_param1; | ||
2488 | reg1 = 0x44; | ||
2489 | reg17 = 0xa2; | ||
2490 | break; | ||
2116 | default: | 2491 | default: |
2117 | /* case SENSOR_SP80708: */ | 2492 | /* case SENSOR_SP80708: */ |
2118 | init = sp80708_sensor_param1; | 2493 | init = sp80708_sensor_param1; |
@@ -2132,17 +2507,33 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2132 | } | 2507 | } |
2133 | 2508 | ||
2134 | reg_w(gspca_dev, 0xc0, C0, 6); | 2509 | reg_w(gspca_dev, 0xc0, C0, 6); |
2135 | if (sd->sensor == SENSOR_ADCM1700) | 2510 | switch (sd->sensor) { |
2511 | case SENSOR_ADCM1700: | ||
2512 | case SENSOR_GC0307: | ||
2513 | case SENSOR_SOI768: | ||
2136 | reg_w(gspca_dev, 0xca, CA_adcm1700, 4); | 2514 | reg_w(gspca_dev, 0xca, CA_adcm1700, 4); |
2137 | else | 2515 | break; |
2516 | case SENSOR_PO2030N: | ||
2517 | reg_w(gspca_dev, 0xca, CA_po2030n, 4); | ||
2518 | break; | ||
2519 | default: | ||
2138 | reg_w(gspca_dev, 0xca, CA, 4); | 2520 | reg_w(gspca_dev, 0xca, CA, 4); |
2521 | break; | ||
2522 | } | ||
2139 | switch (sd->sensor) { | 2523 | switch (sd->sensor) { |
2140 | case SENSOR_ADCM1700: | 2524 | case SENSOR_ADCM1700: |
2141 | case SENSOR_OV7630: | 2525 | case SENSOR_OV7630: |
2142 | case SENSOR_OV7648: | 2526 | case SENSOR_OV7648: |
2143 | case SENSOR_OV7660: | 2527 | case SENSOR_OV7660: |
2528 | case SENSOR_SOI768: | ||
2144 | reg_w(gspca_dev, 0xce, CE_ov76xx, 4); | 2529 | reg_w(gspca_dev, 0xce, CE_ov76xx, 4); |
2145 | break; | 2530 | break; |
2531 | case SENSOR_GC0307: | ||
2532 | reg_w(gspca_dev, 0xce, CE_gc0307, 4); | ||
2533 | break; | ||
2534 | case SENSOR_PO2030N: | ||
2535 | reg_w(gspca_dev, 0xce, CE_po2030n, 4); | ||
2536 | break; | ||
2146 | default: | 2537 | default: |
2147 | reg_w(gspca_dev, 0xce, CE, 4); | 2538 | reg_w(gspca_dev, 0xce, CE, 4); |
2148 | /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */ | 2539 | /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */ |
@@ -2161,6 +2552,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2161 | setvflip(sd); | 2552 | setvflip(sd); |
2162 | setbrightness(gspca_dev); | 2553 | setbrightness(gspca_dev); |
2163 | setcontrast(gspca_dev); | 2554 | setcontrast(gspca_dev); |
2555 | setcolors(gspca_dev); | ||
2164 | setautogain(gspca_dev); | 2556 | setautogain(gspca_dev); |
2165 | setfreq(gspca_dev); | 2557 | setfreq(gspca_dev); |
2166 | return 0; | 2558 | return 0; |
@@ -2175,11 +2567,16 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2175 | { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 }; | 2567 | { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 }; |
2176 | static const u8 stopov7648[] = | 2568 | static const u8 stopov7648[] = |
2177 | { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; | 2569 | { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; |
2570 | static const u8 stopsoi768[] = | ||
2571 | { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; | ||
2178 | u8 data; | 2572 | u8 data; |
2179 | const u8 *sn9c1xx; | 2573 | const u8 *sn9c1xx; |
2180 | 2574 | ||
2181 | data = 0x0b; | 2575 | data = 0x0b; |
2182 | switch (sd->sensor) { | 2576 | switch (sd->sensor) { |
2577 | case SENSOR_GC0307: | ||
2578 | data = 0x29; | ||
2579 | break; | ||
2183 | case SENSOR_HV7131R: | 2580 | case SENSOR_HV7131R: |
2184 | i2c_w8(gspca_dev, stophv7131); | 2581 | i2c_w8(gspca_dev, stophv7131); |
2185 | data = 0x2b; | 2582 | data = 0x2b; |
@@ -2196,6 +2593,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2196 | case SENSOR_PO1030: | 2593 | case SENSOR_PO1030: |
2197 | data = 0x29; | 2594 | data = 0x29; |
2198 | break; | 2595 | break; |
2596 | case SENSOR_SOI768: | ||
2597 | i2c_w8(gspca_dev, stopsoi768); | ||
2598 | data = 0x29; | ||
2599 | break; | ||
2199 | } | 2600 | } |
2200 | sn9c1xx = sn_tb[sd->sensor]; | 2601 | sn9c1xx = sn_tb[sd->sensor]; |
2201 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 2602 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
@@ -2206,13 +2607,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2206 | /* reg_w1(gspca_dev, 0xf1, 0x01); */ | 2607 | /* reg_w1(gspca_dev, 0xf1, 0x01); */ |
2207 | } | 2608 | } |
2208 | 2609 | ||
2209 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
2210 | { | ||
2211 | struct sd *sd = (struct sd *) gspca_dev; | ||
2212 | |||
2213 | kfree(sd->jpeg_hdr); | ||
2214 | } | ||
2215 | |||
2216 | static void do_autogain(struct gspca_dev *gspca_dev) | 2610 | static void do_autogain(struct gspca_dev *gspca_dev) |
2217 | { | 2611 | { |
2218 | struct sd *sd = (struct sd *) gspca_dev; | 2612 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2233,6 +2627,14 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2233 | if (delta < luma_mean - luma_delta || | 2627 | if (delta < luma_mean - luma_delta || |
2234 | delta > luma_mean + luma_delta) { | 2628 | delta > luma_mean + luma_delta) { |
2235 | switch (sd->sensor) { | 2629 | switch (sd->sensor) { |
2630 | case SENSOR_GC0307: | ||
2631 | expotimes = sd->exposure; | ||
2632 | expotimes += (luma_mean - delta) >> 6; | ||
2633 | if (expotimes < 0) | ||
2634 | expotimes = 0; | ||
2635 | sd->exposure = setexposure(gspca_dev, | ||
2636 | (unsigned int) expotimes); | ||
2637 | break; | ||
2236 | case SENSOR_HV7131R: | 2638 | case SENSOR_HV7131R: |
2237 | expotimes = sd->exposure >> 8; | 2639 | expotimes = sd->exposure >> 8; |
2238 | expotimes += (luma_mean - delta) >> 4; | 2640 | expotimes += (luma_mean - delta) >> 4; |
@@ -2584,7 +2986,6 @@ static const struct sd_desc sd_desc = { | |||
2584 | .init = sd_init, | 2986 | .init = sd_init, |
2585 | .start = sd_start, | 2987 | .start = sd_start, |
2586 | .stopN = sd_stopN, | 2988 | .stopN = sd_stopN, |
2587 | .stop0 = sd_stop0, | ||
2588 | .pkt_scan = sd_pkt_scan, | 2989 | .pkt_scan = sd_pkt_scan, |
2589 | .dq_callback = do_autogain, | 2990 | .dq_callback = do_autogain, |
2590 | .get_jcomp = sd_get_jcomp, | 2991 | .get_jcomp = sd_get_jcomp, |
@@ -2656,7 +3057,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2656 | #endif | 3057 | #endif |
2657 | {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, | 3058 | {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, |
2658 | {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, | 3059 | {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, |
2659 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ | 3060 | {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ |
2660 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ | 3061 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ |
2661 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ | 3062 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ |
2662 | {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ | 3063 | {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index b9c80e2103b9..7bb2355005dc 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #define MODULE_NAME "spca561" | 23 | #define MODULE_NAME "spca561" |
24 | 24 | ||
25 | #include <linux/input.h> | ||
25 | #include "gspca.h" | 26 | #include "gspca.h" |
26 | 27 | ||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
@@ -249,9 +250,9 @@ static const __u16 Pb100_2map8300[][2] = { | |||
249 | }; | 250 | }; |
250 | 251 | ||
251 | static const __u16 spca561_161rev12A_data1[][2] = { | 252 | static const __u16 spca561_161rev12A_data1[][2] = { |
252 | {0x29, 0x8118}, /* white balance - was 21 */ | 253 | {0x29, 0x8118}, /* Control register (various enable bits) */ |
253 | {0x08, 0x8114}, /* white balance - was 01 */ | 254 | {0x08, 0x8114}, /* GPIO: Led off */ |
254 | {0x0e, 0x8112}, /* white balance - was 00 */ | 255 | {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */ |
255 | {0x00, 0x8102}, /* white balance - new */ | 256 | {0x00, 0x8102}, /* white balance - new */ |
256 | {0x92, 0x8804}, | 257 | {0x92, 0x8804}, |
257 | {0x04, 0x8802}, /* windows uses 08 */ | 258 | {0x04, 0x8802}, /* windows uses 08 */ |
@@ -263,15 +264,11 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
263 | {0x07, 0x8601}, | 264 | {0x07, 0x8601}, |
264 | {0x07, 0x8602}, | 265 | {0x07, 0x8602}, |
265 | {0x04, 0x8501}, | 266 | {0x04, 0x8501}, |
266 | {0x21, 0x8118}, | ||
267 | 267 | ||
268 | {0x07, 0x8201}, /* windows uses 02 */ | 268 | {0x07, 0x8201}, /* windows uses 02 */ |
269 | {0x08, 0x8200}, | 269 | {0x08, 0x8200}, |
270 | {0x01, 0x8200}, | 270 | {0x01, 0x8200}, |
271 | 271 | ||
272 | {0x00, 0x8114}, | ||
273 | {0x01, 0x8114}, /* windows uses 00 */ | ||
274 | |||
275 | {0x90, 0x8604}, | 272 | {0x90, 0x8604}, |
276 | {0x00, 0x8605}, | 273 | {0x00, 0x8605}, |
277 | {0xb0, 0x8603}, | 274 | {0xb0, 0x8603}, |
@@ -302,6 +299,9 @@ static const __u16 spca561_161rev12A_data2[][2] = { | |||
302 | {0xf0, 0x8505}, | 299 | {0xf0, 0x8505}, |
303 | {0x32, 0x850a}, | 300 | {0x32, 0x850a}, |
304 | /* {0x99, 0x8700}, * - white balance - new (removed) */ | 301 | /* {0x99, 0x8700}, * - white balance - new (removed) */ |
302 | /* HDG we used to do this in stop0, making the init state and the state | ||
303 | after a start / stop different, so do this here instead. */ | ||
304 | {0x29, 0x8118}, | ||
305 | {} | 305 | {} |
306 | }; | 306 | }; |
307 | 307 | ||
@@ -645,6 +645,9 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) | |||
645 | setwhite(gspca_dev); | 645 | setwhite(gspca_dev); |
646 | setgain(gspca_dev); | 646 | setgain(gspca_dev); |
647 | setexposure(gspca_dev); | 647 | setexposure(gspca_dev); |
648 | |||
649 | /* Led ON (bit 3 -> 0 */ | ||
650 | reg_w_val(gspca_dev->dev, 0x8114, 0x00); | ||
648 | return 0; | 651 | return 0; |
649 | } | 652 | } |
650 | static int sd_start_72a(struct gspca_dev *gspca_dev) | 653 | static int sd_start_72a(struct gspca_dev *gspca_dev) |
@@ -691,26 +694,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
691 | 694 | ||
692 | if (sd->chip_revision == Rev012A) { | 695 | if (sd->chip_revision == Rev012A) { |
693 | reg_w_val(gspca_dev->dev, 0x8112, 0x0e); | 696 | reg_w_val(gspca_dev->dev, 0x8112, 0x0e); |
697 | /* Led Off (bit 3 -> 1 */ | ||
698 | reg_w_val(gspca_dev->dev, 0x8114, 0x08); | ||
694 | } else { | 699 | } else { |
695 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); | 700 | reg_w_val(gspca_dev->dev, 0x8112, 0x20); |
696 | /* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ | 701 | /* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ |
697 | } | 702 | } |
698 | } | 703 | } |
699 | 704 | ||
700 | /* called on streamoff with alt 0 and on disconnect */ | ||
701 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
702 | { | ||
703 | struct sd *sd = (struct sd *) gspca_dev; | ||
704 | |||
705 | if (!gspca_dev->present) | ||
706 | return; | ||
707 | if (sd->chip_revision == Rev012A) { | ||
708 | reg_w_val(gspca_dev->dev, 0x8118, 0x29); | ||
709 | reg_w_val(gspca_dev->dev, 0x8114, 0x08); | ||
710 | } | ||
711 | /* reg_w_val(gspca_dev->dev, 0x8114, 0); */ | ||
712 | } | ||
713 | |||
714 | static void do_autogain(struct gspca_dev *gspca_dev) | 705 | static void do_autogain(struct gspca_dev *gspca_dev) |
715 | { | 706 | { |
716 | struct sd *sd = (struct sd *) gspca_dev; | 707 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -788,6 +779,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
788 | switch (*data++) { /* sequence number */ | 779 | switch (*data++) { /* sequence number */ |
789 | case 0: /* start of frame */ | 780 | case 0: /* start of frame */ |
790 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | 781 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
782 | |||
783 | /* This should never happen */ | ||
784 | if (len < 2) { | ||
785 | PDEBUG(D_ERR, "Short SOF packet, ignoring"); | ||
786 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
787 | return; | ||
788 | } | ||
789 | |||
790 | #ifdef CONFIG_INPUT | ||
791 | if (data[0] & 0x20) { | ||
792 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
793 | input_sync(gspca_dev->input_dev); | ||
794 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
795 | input_sync(gspca_dev->input_dev); | ||
796 | } | ||
797 | #endif | ||
798 | |||
791 | if (data[1] & 0x10) { | 799 | if (data[1] & 0x10) { |
792 | /* compressed bayer */ | 800 | /* compressed bayer */ |
793 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | 801 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
@@ -1028,8 +1036,10 @@ static const struct sd_desc sd_desc_12a = { | |||
1028 | .init = sd_init_12a, | 1036 | .init = sd_init_12a, |
1029 | .start = sd_start_12a, | 1037 | .start = sd_start_12a, |
1030 | .stopN = sd_stopN, | 1038 | .stopN = sd_stopN, |
1031 | .stop0 = sd_stop0, | ||
1032 | .pkt_scan = sd_pkt_scan, | 1039 | .pkt_scan = sd_pkt_scan, |
1040 | #ifdef CONFIG_INPUT | ||
1041 | .other_input = 1, | ||
1042 | #endif | ||
1033 | }; | 1043 | }; |
1034 | static const struct sd_desc sd_desc_72a = { | 1044 | static const struct sd_desc sd_desc_72a = { |
1035 | .name = MODULE_NAME, | 1045 | .name = MODULE_NAME, |
@@ -1039,9 +1049,11 @@ static const struct sd_desc sd_desc_72a = { | |||
1039 | .init = sd_init_72a, | 1049 | .init = sd_init_72a, |
1040 | .start = sd_start_72a, | 1050 | .start = sd_start_72a, |
1041 | .stopN = sd_stopN, | 1051 | .stopN = sd_stopN, |
1042 | .stop0 = sd_stop0, | ||
1043 | .pkt_scan = sd_pkt_scan, | 1052 | .pkt_scan = sd_pkt_scan, |
1044 | .dq_callback = do_autogain, | 1053 | .dq_callback = do_autogain, |
1054 | #ifdef CONFIG_INPUT | ||
1055 | .other_input = 1, | ||
1056 | #endif | ||
1045 | }; | 1057 | }; |
1046 | static const struct sd_desc *sd_desc[2] = { | 1058 | static const struct sd_desc *sd_desc[2] = { |
1047 | &sd_desc_12a, | 1059 | &sd_desc_12a, |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 668a7536af90..63014372adbc 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -44,7 +44,10 @@ struct sd { | |||
44 | u8 gamma; | 44 | u8 gamma; |
45 | u8 sharpness; | 45 | u8 sharpness; |
46 | u8 freq; | 46 | u8 freq; |
47 | u8 whitebalance; | 47 | u8 red_balance; /* split balance */ |
48 | u8 blue_balance; | ||
49 | u8 global_gain; /* aka gain */ | ||
50 | u8 whitebalance; /* set default r/g/b and activate */ | ||
48 | u8 mirror; | 51 | u8 mirror; |
49 | u8 effect; | 52 | u8 effect; |
50 | 53 | ||
@@ -70,8 +73,17 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | |||
70 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 73 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
71 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 74 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
72 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 75 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
76 | |||
77 | |||
73 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); |
74 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); |
80 | static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
81 | static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
82 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
84 | static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | |||
75 | static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val); | 87 | static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val); |
76 | static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val); | 88 | static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val); |
77 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); |
@@ -79,6 +91,7 @@ static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | |||
79 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 91 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
80 | struct v4l2_querymenu *menu); | 92 | struct v4l2_querymenu *menu); |
81 | 93 | ||
94 | |||
82 | static const struct ctrl sd_ctrls[] = { | 95 | static const struct ctrl sd_ctrls[] = { |
83 | { | 96 | { |
84 | { | 97 | { |
@@ -139,7 +152,7 @@ static const struct ctrl sd_ctrls[] = { | |||
139 | }, | 152 | }, |
140 | { | 153 | { |
141 | { | 154 | { |
142 | .id = V4L2_CID_GAIN, /* here, i activate only the lowlight, | 155 | .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight, |
143 | * some apps dont bring up the | 156 | * some apps dont bring up the |
144 | * backligth_compensation control) */ | 157 | * backligth_compensation control) */ |
145 | .type = V4L2_CTRL_TYPE_INTEGER, | 158 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -183,7 +196,7 @@ static const struct ctrl sd_ctrls[] = { | |||
183 | 196 | ||
184 | { | 197 | { |
185 | { | 198 | { |
186 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, | 199 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
187 | .type = V4L2_CTRL_TYPE_INTEGER, | 200 | .type = V4L2_CTRL_TYPE_INTEGER, |
188 | .name = "White Balance", | 201 | .name = "White Balance", |
189 | .minimum = 0, | 202 | .minimum = 0, |
@@ -223,6 +236,48 @@ static const struct ctrl sd_ctrls[] = { | |||
223 | .set = sd_seteffect, | 236 | .set = sd_seteffect, |
224 | .get = sd_geteffect | 237 | .get = sd_geteffect |
225 | }, | 238 | }, |
239 | { | ||
240 | { | ||
241 | .id = V4L2_CID_BLUE_BALANCE, | ||
242 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
243 | .name = "Blue Balance", | ||
244 | .minimum = 0x10, | ||
245 | .maximum = 0x40, | ||
246 | .step = 1, | ||
247 | #define BLUE_BALANCE_DEF 0x20 | ||
248 | .default_value = BLUE_BALANCE_DEF, | ||
249 | }, | ||
250 | .set = sd_setblue_balance, | ||
251 | .get = sd_getblue_balance, | ||
252 | }, | ||
253 | { | ||
254 | { | ||
255 | .id = V4L2_CID_RED_BALANCE, | ||
256 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
257 | .name = "Red Balance", | ||
258 | .minimum = 0x10, | ||
259 | .maximum = 0x40, | ||
260 | .step = 1, | ||
261 | #define RED_BALANCE_DEF 0x20 | ||
262 | .default_value = RED_BALANCE_DEF, | ||
263 | }, | ||
264 | .set = sd_setred_balance, | ||
265 | .get = sd_getred_balance, | ||
266 | }, | ||
267 | { | ||
268 | { | ||
269 | .id = V4L2_CID_GAIN, | ||
270 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
271 | .name = "Gain", | ||
272 | .minimum = 0x10, | ||
273 | .maximum = 0x40, | ||
274 | .step = 1, | ||
275 | #define global_gain_DEF 0x20 | ||
276 | .default_value = global_gain_DEF, | ||
277 | }, | ||
278 | .set = sd_setglobal_gain, | ||
279 | .get = sd_getglobal_gain, | ||
280 | }, | ||
226 | }; | 281 | }; |
227 | 282 | ||
228 | static char *effects_control[] = { | 283 | static char *effects_control[] = { |
@@ -523,6 +578,10 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
523 | u8 *tmpbuf; | 578 | u8 *tmpbuf; |
524 | 579 | ||
525 | tmpbuf = kmalloc(len, GFP_KERNEL); | 580 | tmpbuf = kmalloc(len, GFP_KERNEL); |
581 | if (!tmpbuf) { | ||
582 | err("Out of memory"); | ||
583 | return; | ||
584 | } | ||
526 | memcpy(tmpbuf, buffer, len); | 585 | memcpy(tmpbuf, buffer, len); |
527 | usb_control_msg(gspca_dev->dev, | 586 | usb_control_msg(gspca_dev->dev, |
528 | usb_sndctrlpipe(gspca_dev->dev, 0), | 587 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -542,10 +601,15 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev, | |||
542 | int i; | 601 | int i; |
543 | u8 *p, *tmpbuf; | 602 | u8 *p, *tmpbuf; |
544 | 603 | ||
545 | if (len * 2 <= USB_BUF_SZ) | 604 | if (len * 2 <= USB_BUF_SZ) { |
546 | p = tmpbuf = gspca_dev->usb_buf; | 605 | p = tmpbuf = gspca_dev->usb_buf; |
547 | else | 606 | } else { |
548 | p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); | 607 | p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); |
608 | if (!tmpbuf) { | ||
609 | err("Out of memory"); | ||
610 | return; | ||
611 | } | ||
612 | } | ||
549 | i = len; | 613 | i = len; |
550 | while (--i >= 0) { | 614 | while (--i >= 0) { |
551 | *p++ = reg++; | 615 | *p++ = reg++; |
@@ -642,6 +706,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
642 | sd->whitebalance = WHITE_BALANCE_DEF; | 706 | sd->whitebalance = WHITE_BALANCE_DEF; |
643 | sd->sharpness = SHARPNESS_DEF; | 707 | sd->sharpness = SHARPNESS_DEF; |
644 | sd->effect = EFFECTS_DEF; | 708 | sd->effect = EFFECTS_DEF; |
709 | sd->red_balance = RED_BALANCE_DEF; | ||
710 | sd->blue_balance = BLUE_BALANCE_DEF; | ||
711 | sd->global_gain = global_gain_DEF; | ||
712 | |||
645 | return 0; | 713 | return 0; |
646 | } | 714 | } |
647 | 715 | ||
@@ -693,18 +761,40 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
693 | reg_w_ixbuf(gspca_dev, 0x90, | 761 | reg_w_ixbuf(gspca_dev, 0x90, |
694 | gamma_table[sd->gamma], sizeof gamma_table[0]); | 762 | gamma_table[sd->gamma], sizeof gamma_table[0]); |
695 | } | 763 | } |
764 | static void setglobalgain(struct gspca_dev *gspca_dev) | ||
765 | { | ||
696 | 766 | ||
697 | static void setwhitebalance(struct gspca_dev *gspca_dev) | 767 | struct sd *sd = (struct sd *) gspca_dev; |
768 | reg_w(gspca_dev, (sd->red_balance << 8) + 0x87); | ||
769 | reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88); | ||
770 | reg_w(gspca_dev, (sd->global_gain << 8) + 0x89); | ||
771 | } | ||
772 | |||
773 | /* Generic fnc for r/b balance, exposure and whitebalance */ | ||
774 | static void setbalance(struct gspca_dev *gspca_dev) | ||
698 | { | 775 | { |
699 | struct sd *sd = (struct sd *) gspca_dev; | 776 | struct sd *sd = (struct sd *) gspca_dev; |
700 | 777 | ||
701 | u8 white_balance[8] = | 778 | /* on whitebalance leave defaults values */ |
702 | {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38}; | 779 | if (sd->whitebalance) { |
780 | reg_w(gspca_dev, 0x3c80); | ||
781 | } else { | ||
782 | reg_w(gspca_dev, 0x3880); | ||
783 | /* shoud we wait here.. */ | ||
784 | /* update and reset 'global gain' with webcam parameters */ | ||
785 | sd->red_balance = reg_r(gspca_dev, 0x0087); | ||
786 | sd->blue_balance = reg_r(gspca_dev, 0x0088); | ||
787 | sd->global_gain = reg_r(gspca_dev, 0x0089); | ||
788 | setglobalgain(gspca_dev); | ||
789 | } | ||
790 | |||
791 | } | ||
792 | |||
703 | 793 | ||
704 | if (sd->whitebalance) | ||
705 | white_balance[7] = 0x3c; | ||
706 | 794 | ||
707 | reg_w_buf(gspca_dev, white_balance, sizeof white_balance); | 795 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
796 | { | ||
797 | setbalance(gspca_dev); | ||
708 | } | 798 | } |
709 | 799 | ||
710 | static void setsharpness(struct gspca_dev *gspca_dev) | 800 | static void setsharpness(struct gspca_dev *gspca_dev) |
@@ -1018,6 +1108,66 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1018 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 1108 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
1019 | } | 1109 | } |
1020 | 1110 | ||
1111 | |||
1112 | static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
1113 | { | ||
1114 | struct sd *sd = (struct sd *) gspca_dev; | ||
1115 | |||
1116 | sd->blue_balance = val; | ||
1117 | if (gspca_dev->streaming) | ||
1118 | reg_w(gspca_dev, (val << 8) + 0x88); | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
1123 | { | ||
1124 | struct sd *sd = (struct sd *) gspca_dev; | ||
1125 | |||
1126 | *val = sd->blue_balance; | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
1131 | { | ||
1132 | struct sd *sd = (struct sd *) gspca_dev; | ||
1133 | |||
1134 | sd->red_balance = val; | ||
1135 | if (gspca_dev->streaming) | ||
1136 | reg_w(gspca_dev, (val << 8) + 0x87); | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
1142 | { | ||
1143 | struct sd *sd = (struct sd *) gspca_dev; | ||
1144 | |||
1145 | *val = sd->red_balance; | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | |||
1150 | |||
1151 | static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
1152 | { | ||
1153 | struct sd *sd = (struct sd *) gspca_dev; | ||
1154 | |||
1155 | sd->global_gain = val; | ||
1156 | if (gspca_dev->streaming) | ||
1157 | setglobalgain(gspca_dev); | ||
1158 | |||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1163 | { | ||
1164 | struct sd *sd = (struct sd *) gspca_dev; | ||
1165 | |||
1166 | *val = sd->global_gain; | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | |||
1021 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1171 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
1022 | { | 1172 | { |
1023 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 4989f9afb46e..732c3dfe46ff 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Z-star vc0321 library | 2 | * Z-star vc0321 library |
3 | * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl | ||
4 | * Copyright (C) 2006 Michel Xhaard | ||
5 | * | 3 | * |
6 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl | ||
6 | * Copyright (C) 2006 Michel Xhaard | ||
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "gspca.h" | 25 | #include "gspca.h" |
26 | 26 | ||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 27 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); |
28 | MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver"); | 28 | MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver"); |
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | 30 | ||
@@ -1971,268 +1971,489 @@ static const u8 ov7660_NoFliker[][4] = { | |||
1971 | {} | 1971 | {} |
1972 | }; | 1972 | }; |
1973 | 1973 | ||
1974 | static const u8 ov7670_initVGA_JPG[][4] = { | 1974 | static const u8 ov7670_InitVGA[][4] = { |
1975 | {0xb3, 0x01, 0x05, 0xcc}, | 1975 | {0xb3, 0x01, 0x05, 0xcc}, |
1976 | {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, | 1976 | {0x00, 0x00, 0x30, 0xdd}, |
1977 | {0xb0, 0x03, 0x19, 0xcc}, | ||
1978 | {0x00, 0x00, 0x10, 0xdd}, | ||
1979 | {0xb0, 0x04, 0x02, 0xcc}, | ||
1977 | {0x00, 0x00, 0x10, 0xdd}, | 1980 | {0x00, 0x00, 0x10, 0xdd}, |
1978 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, | 1981 | {0xb3, 0x00, 0x66, 0xcc}, |
1979 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, | 1982 | {0xb3, 0x00, 0x67, 0xcc}, |
1983 | {0xb0, 0x16, 0x01, 0xcc}, | ||
1980 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ | 1984 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
1981 | {0xb3, 0x34, 0x01, 0xcc}, | 1985 | {0xb3, 0x34, 0x01, 0xcc}, |
1982 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, | 1986 | {0xb3, 0x05, 0x01, 0xcc}, |
1983 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, | 1987 | {0xb3, 0x06, 0x01, 0xcc}, |
1984 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, | 1988 | {0xb3, 0x08, 0x01, 0xcc}, |
1985 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, | 1989 | {0xb3, 0x09, 0x0c, 0xcc}, |
1986 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, | 1990 | {0xb3, 0x02, 0x02, 0xcc}, |
1987 | {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, | 1991 | {0xb3, 0x03, 0x1f, 0xcc}, |
1988 | {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, | 1992 | {0xb3, 0x14, 0x00, 0xcc}, |
1989 | {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0x41, 0xcc}, | 1993 | {0xb3, 0x15, 0x00, 0xcc}, |
1990 | {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa}, | 1994 | {0xb3, 0x16, 0x02, 0xcc}, |
1991 | {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa}, | 1995 | {0xb3, 0x17, 0x7f, 0xcc}, |
1992 | {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa}, | 1996 | {0xb3, 0x04, 0x05, 0xcc}, |
1993 | {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, | 1997 | {0xb3, 0x20, 0x00, 0xcc}, |
1994 | {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa}, | 1998 | {0xb3, 0x21, 0x00, 0xcc}, |
1995 | {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa}, | 1999 | {0xb3, 0x22, 0x01, 0xcc}, |
1996 | {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa}, | 2000 | {0xb3, 0x23, 0xe0, 0xcc}, |
1997 | {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa}, | 2001 | {0xbc, 0x00, 0x41, 0xcc}, |
1998 | {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa}, | 2002 | {0xbc, 0x01, 0x01, 0xcc}, |
1999 | {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa}, | 2003 | {0x00, 0x12, 0x80, 0xaa}, |
2000 | {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa}, | 2004 | {0x00, 0x00, 0x20, 0xdd}, |
2001 | {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa}, | 2005 | {0x00, 0x12, 0x00, 0xaa}, |
2002 | {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa}, | 2006 | {0x00, 0x11, 0x40, 0xaa}, |
2003 | {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa}, | 2007 | {0x00, 0x6b, 0x0a, 0xaa}, |
2004 | {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa}, | 2008 | {0x00, 0x3a, 0x04, 0xaa}, |
2005 | {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa}, | 2009 | {0x00, 0x40, 0xc0, 0xaa}, |
2006 | {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa}, | 2010 | {0x00, 0x8c, 0x00, 0xaa}, |
2007 | {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa}, | 2011 | {0x00, 0x7a, 0x29, 0xaa}, |
2008 | {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa}, | 2012 | {0x00, 0x7b, 0x0e, 0xaa}, |
2009 | {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa}, | 2013 | {0x00, 0x7c, 0x1a, 0xaa}, |
2010 | {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa}, | 2014 | {0x00, 0x7d, 0x31, 0xaa}, |
2011 | {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, | 2015 | {0x00, 0x7e, 0x53, 0xaa}, |
2012 | {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, | 2016 | {0x00, 0x7f, 0x60, 0xaa}, |
2013 | {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, | 2017 | {0x00, 0x80, 0x6b, 0xaa}, |
2018 | {0x00, 0x81, 0x73, 0xaa}, | ||
2019 | {0x00, 0x82, 0x7b, 0xaa}, | ||
2020 | {0x00, 0x83, 0x82, 0xaa}, | ||
2021 | {0x00, 0x84, 0x89, 0xaa}, | ||
2022 | {0x00, 0x85, 0x96, 0xaa}, | ||
2023 | {0x00, 0x86, 0xa1, 0xaa}, | ||
2024 | {0x00, 0x87, 0xb7, 0xaa}, | ||
2025 | {0x00, 0x88, 0xcc, 0xaa}, | ||
2026 | {0x00, 0x89, 0xe1, 0xaa}, | ||
2027 | {0x00, 0x13, 0xe0, 0xaa}, | ||
2028 | {0x00, 0x00, 0x00, 0xaa}, | ||
2029 | {0x00, 0x10, 0x00, 0xaa}, | ||
2030 | {0x00, 0x0d, 0x40, 0xaa}, | ||
2031 | {0x00, 0x14, 0x28, 0xaa}, | ||
2032 | {0x00, 0xa5, 0x05, 0xaa}, | ||
2033 | {0x00, 0xab, 0x07, 0xaa}, | ||
2034 | {0x00, 0x24, 0x95, 0xaa}, | ||
2035 | {0x00, 0x25, 0x33, 0xaa}, | ||
2036 | {0x00, 0x26, 0xe3, 0xaa}, | ||
2037 | {0x00, 0x9f, 0x88, 0xaa}, | ||
2038 | {0x00, 0xa0, 0x78, 0xaa}, | ||
2039 | {0x00, 0x55, 0x90, 0xaa}, | ||
2040 | {0x00, 0xa1, 0x03, 0xaa}, | ||
2041 | {0x00, 0xa6, 0xe0, 0xaa}, | ||
2042 | {0x00, 0xa7, 0xd8, 0xaa}, | ||
2043 | {0x00, 0xa8, 0xf0, 0xaa}, | ||
2044 | {0x00, 0xa9, 0x90, 0xaa}, | ||
2045 | {0x00, 0xaa, 0x14, 0xaa}, | ||
2046 | {0x00, 0x13, 0xe5, 0xaa}, | ||
2047 | {0x00, 0x0e, 0x61, 0xaa}, | ||
2048 | {0x00, 0x0f, 0x4b, 0xaa}, | ||
2049 | {0x00, 0x16, 0x02, 0xaa}, | ||
2014 | {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ | 2050 | {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ |
2015 | {0x00, 0x21, 0x02, 0xaa}, | 2051 | {0x00, 0x21, 0x02, 0xaa}, |
2016 | {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, | 2052 | {0x00, 0x22, 0x91, 0xaa}, |
2017 | {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, | 2053 | {0x00, 0x29, 0x07, 0xaa}, |
2018 | {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, | 2054 | {0x00, 0x33, 0x0b, 0xaa}, |
2019 | {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa}, | 2055 | {0x00, 0x35, 0x0b, 0xaa}, |
2020 | {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa}, | 2056 | {0x00, 0x37, 0x1d, 0xaa}, |
2021 | {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa}, | 2057 | {0x00, 0x38, 0x71, 0xaa}, |
2022 | {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa}, | 2058 | {0x00, 0x39, 0x2a, 0xaa}, |
2023 | {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa}, | 2059 | {0x00, 0x3c, 0x78, 0xaa}, |
2024 | {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa}, | 2060 | {0x00, 0x4d, 0x40, 0xaa}, |
2025 | {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, | 2061 | {0x00, 0x4e, 0x20, 0xaa}, |
2026 | {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa}, | 2062 | {0x00, 0x74, 0x19, 0xaa}, |
2027 | {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa}, | 2063 | {0x00, 0x8d, 0x4f, 0xaa}, |
2028 | {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa}, | 2064 | {0x00, 0x8e, 0x00, 0xaa}, |
2029 | {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa}, | 2065 | {0x00, 0x8f, 0x00, 0xaa}, |
2030 | {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa}, | 2066 | {0x00, 0x90, 0x00, 0xaa}, |
2031 | {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa}, | 2067 | {0x00, 0x91, 0x00, 0xaa}, |
2032 | {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa}, | 2068 | {0x00, 0x96, 0x00, 0xaa}, |
2033 | {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa}, | 2069 | {0x00, 0x9a, 0x80, 0xaa}, |
2034 | {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa}, | 2070 | {0x00, 0xb0, 0x84, 0xaa}, |
2035 | {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa}, | 2071 | {0x00, 0xb1, 0x0c, 0xaa}, |
2036 | {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa}, | 2072 | {0x00, 0xb2, 0x0e, 0xaa}, |
2037 | {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa}, | 2073 | {0x00, 0xb3, 0x82, 0xaa}, |
2038 | {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa}, | 2074 | {0x00, 0xb8, 0x0a, 0xaa}, |
2039 | {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa}, | 2075 | {0x00, 0x43, 0x14, 0xaa}, |
2040 | {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa}, | 2076 | {0x00, 0x44, 0xf0, 0xaa}, |
2041 | {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa}, | 2077 | {0x00, 0x45, 0x45, 0xaa}, |
2042 | {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa}, | 2078 | {0x00, 0x46, 0x63, 0xaa}, |
2043 | {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa}, | 2079 | {0x00, 0x47, 0x2d, 0xaa}, |
2044 | {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, | 2080 | {0x00, 0x48, 0x46, 0xaa}, |
2045 | {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa}, | 2081 | {0x00, 0x59, 0x88, 0xaa}, |
2046 | {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, | 2082 | {0x00, 0x5a, 0xa0, 0xaa}, |
2047 | {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa}, | 2083 | {0x00, 0x5b, 0xc6, 0xaa}, |
2048 | {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, | 2084 | {0x00, 0x5c, 0x7d, 0xaa}, |
2049 | {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa}, | 2085 | {0x00, 0x5d, 0x5f, 0xaa}, |
2050 | {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, | 2086 | {0x00, 0x5e, 0x19, 0xaa}, |
2051 | {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa}, | 2087 | {0x00, 0x6c, 0x0a, 0xaa}, |
2052 | {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa}, | 2088 | {0x00, 0x6d, 0x55, 0xaa}, |
2053 | {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa}, | 2089 | {0x00, 0x6e, 0x11, 0xaa}, |
2054 | {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa}, | 2090 | {0x00, 0x6f, 0x9e, 0xaa}, |
2055 | {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa}, | 2091 | {0x00, 0x69, 0x00, 0xaa}, |
2056 | {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa}, | 2092 | {0x00, 0x6a, 0x40, 0xaa}, |
2057 | {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa}, | 2093 | {0x00, 0x01, 0x40, 0xaa}, |
2058 | {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa}, | 2094 | {0x00, 0x02, 0x40, 0xaa}, |
2059 | {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa}, | 2095 | {0x00, 0x13, 0xe7, 0xaa}, |
2060 | {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa}, | 2096 | {0x00, 0x5f, 0xf0, 0xaa}, |
2061 | {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa}, | 2097 | {0x00, 0x60, 0xf0, 0xaa}, |
2062 | {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa}, | 2098 | {0x00, 0x61, 0xf0, 0xaa}, |
2063 | {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa}, | 2099 | {0x00, 0x27, 0xa0, 0xaa}, |
2064 | {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa}, | 2100 | {0x00, 0x28, 0x80, 0xaa}, |
2065 | {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa}, | 2101 | {0x00, 0x2c, 0x90, 0xaa}, |
2066 | {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa}, | 2102 | {0x00, 0x4f, 0x66, 0xaa}, |
2067 | {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa}, | 2103 | {0x00, 0x50, 0x66, 0xaa}, |
2068 | {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa}, | 2104 | {0x00, 0x51, 0x00, 0xaa}, |
2069 | {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa}, | 2105 | {0x00, 0x52, 0x22, 0xaa}, |
2070 | {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa}, | 2106 | {0x00, 0x53, 0x5e, 0xaa}, |
2071 | {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, | 2107 | {0x00, 0x54, 0x80, 0xaa}, |
2072 | {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa}, | 2108 | {0x00, 0x58, 0x9e, 0xaa}, |
2073 | {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa}, | 2109 | {0x00, 0x41, 0x08, 0xaa}, |
2074 | {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa}, | 2110 | {0x00, 0x3f, 0x00, 0xaa}, |
2075 | {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa}, | 2111 | {0x00, 0x75, 0x85, 0xaa}, |
2076 | {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa}, | 2112 | {0x00, 0x76, 0xe1, 0xaa}, |
2077 | {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, | 2113 | {0x00, 0x4c, 0x00, 0xaa}, |
2078 | {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, | 2114 | {0x00, 0x77, 0x0a, 0xaa}, |
2079 | {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, | 2115 | {0x00, 0x3d, 0x88, 0xaa}, |
2116 | {0x00, 0x4b, 0x09, 0xaa}, | ||
2117 | {0x00, 0xc9, 0x60, 0xaa}, | ||
2118 | {0x00, 0x41, 0x38, 0xaa}, | ||
2119 | {0x00, 0x62, 0x30, 0xaa}, | ||
2120 | {0x00, 0x63, 0x30, 0xaa}, | ||
2121 | {0x00, 0x64, 0x08, 0xaa}, | ||
2122 | {0x00, 0x94, 0x07, 0xaa}, | ||
2123 | {0x00, 0x95, 0x0b, 0xaa}, | ||
2124 | {0x00, 0x65, 0x00, 0xaa}, | ||
2125 | {0x00, 0x66, 0x05, 0xaa}, | ||
2126 | {0x00, 0x56, 0x50, 0xaa}, | ||
2127 | {0x00, 0x34, 0x11, 0xaa}, | ||
2128 | {0x00, 0xa4, 0x88, 0xaa}, | ||
2129 | {0x00, 0x96, 0x00, 0xaa}, | ||
2130 | {0x00, 0x97, 0x30, 0xaa}, | ||
2131 | {0x00, 0x98, 0x20, 0xaa}, | ||
2132 | {0x00, 0x99, 0x30, 0xaa}, | ||
2133 | {0x00, 0x9a, 0x84, 0xaa}, | ||
2134 | {0x00, 0x9b, 0x29, 0xaa}, | ||
2135 | {0x00, 0x9c, 0x03, 0xaa}, | ||
2136 | {0x00, 0x78, 0x04, 0xaa}, | ||
2137 | {0x00, 0x79, 0x01, 0xaa}, | ||
2138 | {0x00, 0xc8, 0xf0, 0xaa}, | ||
2139 | {0x00, 0x79, 0x0f, 0xaa}, | ||
2140 | {0x00, 0xc8, 0x00, 0xaa}, | ||
2141 | {0x00, 0x79, 0x10, 0xaa}, | ||
2142 | {0x00, 0xc8, 0x7e, 0xaa}, | ||
2143 | {0x00, 0x79, 0x0a, 0xaa}, | ||
2144 | {0x00, 0xc8, 0x80, 0xaa}, | ||
2145 | {0x00, 0x79, 0x0b, 0xaa}, | ||
2146 | {0x00, 0xc8, 0x01, 0xaa}, | ||
2147 | {0x00, 0x79, 0x0c, 0xaa}, | ||
2148 | {0x00, 0xc8, 0x0f, 0xaa}, | ||
2149 | {0x00, 0x79, 0x0d, 0xaa}, | ||
2150 | {0x00, 0xc8, 0x20, 0xaa}, | ||
2151 | {0x00, 0x79, 0x09, 0xaa}, | ||
2152 | {0x00, 0xc8, 0x80, 0xaa}, | ||
2153 | {0x00, 0x79, 0x02, 0xaa}, | ||
2154 | {0x00, 0xc8, 0xc0, 0xaa}, | ||
2155 | {0x00, 0x79, 0x03, 0xaa}, | ||
2156 | {0x00, 0xc8, 0x40, 0xaa}, | ||
2157 | {0x00, 0x79, 0x05, 0xaa}, | ||
2158 | {0x00, 0xc8, 0x30, 0xaa}, | ||
2159 | {0x00, 0x79, 0x26, 0xaa}, | ||
2160 | {0x00, 0x11, 0x40, 0xaa}, | ||
2161 | {0x00, 0x3a, 0x04, 0xaa}, | ||
2162 | {0x00, 0x12, 0x00, 0xaa}, | ||
2163 | {0x00, 0x40, 0xc0, 0xaa}, | ||
2164 | {0x00, 0x8c, 0x00, 0xaa}, | ||
2165 | {0x00, 0x17, 0x14, 0xaa}, | ||
2166 | {0x00, 0x18, 0x02, 0xaa}, | ||
2167 | {0x00, 0x32, 0x92, 0xaa}, | ||
2168 | {0x00, 0x19, 0x02, 0xaa}, | ||
2169 | {0x00, 0x1a, 0x7a, 0xaa}, | ||
2170 | {0x00, 0x03, 0x0a, 0xaa}, | ||
2171 | {0x00, 0x0c, 0x00, 0xaa}, | ||
2172 | {0x00, 0x3e, 0x00, 0xaa}, | ||
2173 | {0x00, 0x70, 0x3a, 0xaa}, | ||
2174 | {0x00, 0x71, 0x35, 0xaa}, | ||
2175 | {0x00, 0x72, 0x11, 0xaa}, | ||
2176 | {0x00, 0x73, 0xf0, 0xaa}, | ||
2177 | {0x00, 0xa2, 0x02, 0xaa}, | ||
2178 | {0x00, 0xb1, 0x00, 0xaa}, | ||
2179 | {0x00, 0xb1, 0x0c, 0xaa}, | ||
2080 | {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ | 2180 | {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ |
2081 | {0x00, 0xaa, 0x14, 0xaa}, | 2181 | {0x00, 0xaa, 0x14, 0xaa}, |
2082 | {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, | 2182 | {0x00, 0x24, 0x80, 0xaa}, |
2083 | {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, | 2183 | {0x00, 0x25, 0x74, 0xaa}, |
2084 | {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, | 2184 | {0x00, 0x26, 0xd3, 0xaa}, |
2085 | {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, | 2185 | {0x00, 0x0d, 0x00, 0xaa}, |
2086 | {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa}, | 2186 | {0x00, 0x14, 0x18, 0xaa}, |
2087 | {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, | 2187 | {0x00, 0x9d, 0x99, 0xaa}, |
2088 | {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa}, | 2188 | {0x00, 0x9e, 0x7f, 0xaa}, |
2089 | {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, | 2189 | {0x00, 0x64, 0x08, 0xaa}, |
2090 | {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa}, | 2190 | {0x00, 0x94, 0x07, 0xaa}, |
2091 | {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, | 2191 | {0x00, 0x95, 0x06, 0xaa}, |
2092 | {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc}, | 2192 | {0x00, 0x66, 0x05, 0xaa}, |
2093 | {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, | 2193 | {0x00, 0x41, 0x08, 0xaa}, |
2094 | {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, | 2194 | {0x00, 0x3f, 0x00, 0xaa}, |
2095 | {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x13, 0xcc}, | 2195 | {0x00, 0x75, 0x07, 0xaa}, |
2096 | {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, | 2196 | {0x00, 0x76, 0xe1, 0xaa}, |
2097 | {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, | 2197 | {0x00, 0x4c, 0x00, 0xaa}, |
2098 | {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, | 2198 | {0x00, 0x77, 0x00, 0xaa}, |
2099 | {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, | 2199 | {0x00, 0x3d, 0xc2, 0xaa}, |
2100 | {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc}, | 2200 | {0x00, 0x4b, 0x09, 0xaa}, |
2201 | {0x00, 0xc9, 0x60, 0xaa}, | ||
2202 | {0x00, 0x41, 0x38, 0xaa}, | ||
2203 | {0xbf, 0xc0, 0x26, 0xcc}, | ||
2204 | {0xbf, 0xc1, 0x02, 0xcc}, | ||
2205 | {0xbf, 0xcc, 0x04, 0xcc}, | ||
2206 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2207 | {0xb3, 0x01, 0x45, 0xcc}, | ||
2101 | {0x00, 0x77, 0x05, 0xaa}, | 2208 | {0x00, 0x77, 0x05, 0xaa}, |
2102 | {}, | 2209 | {}, |
2103 | }; | 2210 | }; |
2104 | 2211 | ||
2105 | static const u8 ov7670_initQVGA_JPG[][4] = { | 2212 | static const u8 ov7670_InitQVGA[][4] = { |
2106 | {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd}, | 2213 | {0xb3, 0x01, 0x05, 0xcc}, |
2107 | {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, | 2214 | {0x00, 0x00, 0x30, 0xdd}, |
2108 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, | 2215 | {0xb0, 0x03, 0x19, 0xcc}, |
2109 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, | 2216 | {0x00, 0x00, 0x10, 0xdd}, |
2110 | {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, | 2217 | {0xb0, 0x04, 0x02, 0xcc}, |
2111 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, | 2218 | {0x00, 0x00, 0x10, 0xdd}, |
2112 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, | 2219 | {0xb3, 0x00, 0x66, 0xcc}, |
2113 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, | 2220 | {0xb3, 0x00, 0x67, 0xcc}, |
2114 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, | 2221 | {0xb0, 0x16, 0x01, 0xcc}, |
2115 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, | 2222 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
2116 | {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, | 2223 | {0xb3, 0x34, 0x01, 0xcc}, |
2117 | {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, | 2224 | {0xb3, 0x05, 0x01, 0xcc}, |
2118 | {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc}, | 2225 | {0xb3, 0x06, 0x01, 0xcc}, |
2119 | {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa}, | 2226 | {0xb3, 0x08, 0x01, 0xcc}, |
2120 | {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa}, | 2227 | {0xb3, 0x09, 0x0c, 0xcc}, |
2121 | {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa}, | 2228 | {0xb3, 0x02, 0x02, 0xcc}, |
2122 | {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, | 2229 | {0xb3, 0x03, 0x1f, 0xcc}, |
2123 | {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa}, | 2230 | {0xb3, 0x14, 0x00, 0xcc}, |
2124 | {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa}, | 2231 | {0xb3, 0x15, 0x00, 0xcc}, |
2125 | {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa}, | 2232 | {0xb3, 0x16, 0x02, 0xcc}, |
2126 | {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa}, | 2233 | {0xb3, 0x17, 0x7f, 0xcc}, |
2127 | {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa}, | 2234 | {0xb3, 0x04, 0x05, 0xcc}, |
2128 | {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa}, | 2235 | {0xb3, 0x20, 0x00, 0xcc}, |
2129 | {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa}, | 2236 | {0xb3, 0x21, 0x00, 0xcc}, |
2130 | {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa}, | 2237 | {0xb3, 0x22, 0x01, 0xcc}, |
2131 | {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa}, | 2238 | {0xb3, 0x23, 0xe0, 0xcc}, |
2132 | {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa}, | 2239 | {0xbc, 0x00, 0xd1, 0xcc}, |
2133 | {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa}, | 2240 | {0xbc, 0x01, 0x01, 0xcc}, |
2134 | {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa}, | 2241 | {0x00, 0x12, 0x80, 0xaa}, |
2135 | {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa}, | 2242 | {0x00, 0x00, 0x20, 0xdd}, |
2136 | {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa}, | 2243 | {0x00, 0x12, 0x00, 0xaa}, |
2137 | {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa}, | 2244 | {0x00, 0x11, 0x40, 0xaa}, |
2138 | {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa}, | 2245 | {0x00, 0x6b, 0x0a, 0xaa}, |
2139 | {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa}, | 2246 | {0x00, 0x3a, 0x04, 0xaa}, |
2140 | {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, | 2247 | {0x00, 0x40, 0xc0, 0xaa}, |
2141 | {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, | 2248 | {0x00, 0x8c, 0x00, 0xaa}, |
2142 | {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, | 2249 | {0x00, 0x7a, 0x29, 0xaa}, |
2250 | {0x00, 0x7b, 0x0e, 0xaa}, | ||
2251 | {0x00, 0x7c, 0x1a, 0xaa}, | ||
2252 | {0x00, 0x7d, 0x31, 0xaa}, | ||
2253 | {0x00, 0x7e, 0x53, 0xaa}, | ||
2254 | {0x00, 0x7f, 0x60, 0xaa}, | ||
2255 | {0x00, 0x80, 0x6b, 0xaa}, | ||
2256 | {0x00, 0x81, 0x73, 0xaa}, | ||
2257 | {0x00, 0x82, 0x7b, 0xaa}, | ||
2258 | {0x00, 0x83, 0x82, 0xaa}, | ||
2259 | {0x00, 0x84, 0x89, 0xaa}, | ||
2260 | {0x00, 0x85, 0x96, 0xaa}, | ||
2261 | {0x00, 0x86, 0xa1, 0xaa}, | ||
2262 | {0x00, 0x87, 0xb7, 0xaa}, | ||
2263 | {0x00, 0x88, 0xcc, 0xaa}, | ||
2264 | {0x00, 0x89, 0xe1, 0xaa}, | ||
2265 | {0x00, 0x13, 0xe0, 0xaa}, | ||
2266 | {0x00, 0x00, 0x00, 0xaa}, | ||
2267 | {0x00, 0x10, 0x00, 0xaa}, | ||
2268 | {0x00, 0x0d, 0x40, 0xaa}, | ||
2269 | {0x00, 0x14, 0x28, 0xaa}, | ||
2270 | {0x00, 0xa5, 0x05, 0xaa}, | ||
2271 | {0x00, 0xab, 0x07, 0xaa}, | ||
2272 | {0x00, 0x24, 0x95, 0xaa}, | ||
2273 | {0x00, 0x25, 0x33, 0xaa}, | ||
2274 | {0x00, 0x26, 0xe3, 0xaa}, | ||
2275 | {0x00, 0x9f, 0x88, 0xaa}, | ||
2276 | {0x00, 0xa0, 0x78, 0xaa}, | ||
2277 | {0x00, 0x55, 0x90, 0xaa}, | ||
2278 | {0x00, 0xa1, 0x03, 0xaa}, | ||
2279 | {0x00, 0xa6, 0xe0, 0xaa}, | ||
2280 | {0x00, 0xa7, 0xd8, 0xaa}, | ||
2281 | {0x00, 0xa8, 0xf0, 0xaa}, | ||
2282 | {0x00, 0xa9, 0x90, 0xaa}, | ||
2283 | {0x00, 0xaa, 0x14, 0xaa}, | ||
2284 | {0x00, 0x13, 0xe5, 0xaa}, | ||
2285 | {0x00, 0x0e, 0x61, 0xaa}, | ||
2286 | {0x00, 0x0f, 0x4b, 0xaa}, | ||
2287 | {0x00, 0x16, 0x02, 0xaa}, | ||
2143 | {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ | 2288 | {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ |
2144 | {0x00, 0x21, 0x02, 0xaa}, | 2289 | {0x00, 0x21, 0x02, 0xaa}, |
2145 | {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, | 2290 | {0x00, 0x22, 0x91, 0xaa}, |
2146 | {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, | 2291 | {0x00, 0x29, 0x07, 0xaa}, |
2147 | {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, | 2292 | {0x00, 0x33, 0x0b, 0xaa}, |
2148 | {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa}, | 2293 | {0x00, 0x35, 0x0b, 0xaa}, |
2149 | {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa}, | 2294 | {0x00, 0x37, 0x1d, 0xaa}, |
2150 | {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa}, | 2295 | {0x00, 0x38, 0x71, 0xaa}, |
2151 | {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa}, | 2296 | {0x00, 0x39, 0x2a, 0xaa}, |
2152 | {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa}, | 2297 | {0x00, 0x3c, 0x78, 0xaa}, |
2153 | {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa}, | 2298 | {0x00, 0x4d, 0x40, 0xaa}, |
2154 | {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, | 2299 | {0x00, 0x4e, 0x20, 0xaa}, |
2155 | {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa}, | 2300 | {0x00, 0x74, 0x19, 0xaa}, |
2156 | {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa}, | 2301 | {0x00, 0x8d, 0x4f, 0xaa}, |
2157 | {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa}, | 2302 | {0x00, 0x8e, 0x00, 0xaa}, |
2158 | {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa}, | 2303 | {0x00, 0x8f, 0x00, 0xaa}, |
2159 | {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa}, | 2304 | {0x00, 0x90, 0x00, 0xaa}, |
2160 | {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa}, | 2305 | {0x00, 0x91, 0x00, 0xaa}, |
2161 | {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa}, | 2306 | {0x00, 0x96, 0x00, 0xaa}, |
2162 | {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa}, | 2307 | {0x00, 0x9a, 0x80, 0xaa}, |
2163 | {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa}, | 2308 | {0x00, 0xb0, 0x84, 0xaa}, |
2164 | {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa}, | 2309 | {0x00, 0xb1, 0x0c, 0xaa}, |
2165 | {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa}, | 2310 | {0x00, 0xb2, 0x0e, 0xaa}, |
2166 | {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa}, | 2311 | {0x00, 0xb3, 0x82, 0xaa}, |
2167 | {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa}, | 2312 | {0x00, 0xb8, 0x0a, 0xaa}, |
2168 | {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa}, | 2313 | {0x00, 0x43, 0x14, 0xaa}, |
2169 | {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa}, | 2314 | {0x00, 0x44, 0xf0, 0xaa}, |
2170 | {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa}, | 2315 | {0x00, 0x45, 0x45, 0xaa}, |
2171 | {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa}, | 2316 | {0x00, 0x46, 0x63, 0xaa}, |
2172 | {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa}, | 2317 | {0x00, 0x47, 0x2d, 0xaa}, |
2173 | {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, | 2318 | {0x00, 0x48, 0x46, 0xaa}, |
2174 | {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa}, | 2319 | {0x00, 0x59, 0x88, 0xaa}, |
2175 | {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, | 2320 | {0x00, 0x5a, 0xa0, 0xaa}, |
2176 | {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa}, | 2321 | {0x00, 0x5b, 0xc6, 0xaa}, |
2177 | {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, | 2322 | {0x00, 0x5c, 0x7d, 0xaa}, |
2178 | {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa}, | 2323 | {0x00, 0x5d, 0x5f, 0xaa}, |
2179 | {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, | 2324 | {0x00, 0x5e, 0x19, 0xaa}, |
2180 | {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa}, | 2325 | {0x00, 0x6c, 0x0a, 0xaa}, |
2181 | {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa}, | 2326 | {0x00, 0x6d, 0x55, 0xaa}, |
2182 | {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa}, | 2327 | {0x00, 0x6e, 0x11, 0xaa}, |
2183 | {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa}, | 2328 | {0x00, 0x6f, 0x9e, 0xaa}, |
2184 | {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa}, | 2329 | {0x00, 0x69, 0x00, 0xaa}, |
2185 | {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa}, | 2330 | {0x00, 0x6a, 0x40, 0xaa}, |
2186 | {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa}, | 2331 | {0x00, 0x01, 0x40, 0xaa}, |
2187 | {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa}, | 2332 | {0x00, 0x02, 0x40, 0xaa}, |
2188 | {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa}, | 2333 | {0x00, 0x13, 0xe7, 0xaa}, |
2189 | {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa}, | 2334 | {0x00, 0x5f, 0xf0, 0xaa}, |
2190 | {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa}, | 2335 | {0x00, 0x60, 0xf0, 0xaa}, |
2191 | {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa}, | 2336 | {0x00, 0x61, 0xf0, 0xaa}, |
2192 | {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa}, | 2337 | {0x00, 0x27, 0xa0, 0xaa}, |
2193 | {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa}, | 2338 | {0x00, 0x28, 0x80, 0xaa}, |
2194 | {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa}, | 2339 | {0x00, 0x2c, 0x90, 0xaa}, |
2195 | {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa}, | 2340 | {0x00, 0x4f, 0x66, 0xaa}, |
2196 | {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa}, | 2341 | {0x00, 0x50, 0x66, 0xaa}, |
2197 | {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa}, | 2342 | {0x00, 0x51, 0x00, 0xaa}, |
2198 | {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa}, | 2343 | {0x00, 0x52, 0x22, 0xaa}, |
2199 | {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa}, | 2344 | {0x00, 0x53, 0x5e, 0xaa}, |
2200 | {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, | 2345 | {0x00, 0x54, 0x80, 0xaa}, |
2201 | {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa}, | 2346 | {0x00, 0x58, 0x9e, 0xaa}, |
2202 | {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa}, | 2347 | {0x00, 0x41, 0x08, 0xaa}, |
2203 | {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa}, | 2348 | {0x00, 0x3f, 0x00, 0xaa}, |
2204 | {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa}, | 2349 | {0x00, 0x75, 0x85, 0xaa}, |
2205 | {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa}, | 2350 | {0x00, 0x76, 0xe1, 0xaa}, |
2206 | {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, | 2351 | {0x00, 0x4c, 0x00, 0xaa}, |
2207 | {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, | 2352 | {0x00, 0x77, 0x0a, 0xaa}, |
2208 | {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, | 2353 | {0x00, 0x3d, 0x88, 0xaa}, |
2354 | {0x00, 0x4b, 0x09, 0xaa}, | ||
2355 | {0x00, 0xc9, 0x60, 0xaa}, | ||
2356 | {0x00, 0x41, 0x38, 0xaa}, | ||
2357 | {0x00, 0x62, 0x30, 0xaa}, | ||
2358 | {0x00, 0x63, 0x30, 0xaa}, | ||
2359 | {0x00, 0x64, 0x08, 0xaa}, | ||
2360 | {0x00, 0x94, 0x07, 0xaa}, | ||
2361 | {0x00, 0x95, 0x0b, 0xaa}, | ||
2362 | {0x00, 0x65, 0x00, 0xaa}, | ||
2363 | {0x00, 0x66, 0x05, 0xaa}, | ||
2364 | {0x00, 0x56, 0x50, 0xaa}, | ||
2365 | {0x00, 0x34, 0x11, 0xaa}, | ||
2366 | {0x00, 0xa4, 0x88, 0xaa}, | ||
2367 | {0x00, 0x96, 0x00, 0xaa}, | ||
2368 | {0x00, 0x97, 0x30, 0xaa}, | ||
2369 | {0x00, 0x98, 0x20, 0xaa}, | ||
2370 | {0x00, 0x99, 0x30, 0xaa}, | ||
2371 | {0x00, 0x9a, 0x84, 0xaa}, | ||
2372 | {0x00, 0x9b, 0x29, 0xaa}, | ||
2373 | {0x00, 0x9c, 0x03, 0xaa}, | ||
2374 | {0x00, 0x78, 0x04, 0xaa}, | ||
2375 | {0x00, 0x79, 0x01, 0xaa}, | ||
2376 | {0x00, 0xc8, 0xf0, 0xaa}, | ||
2377 | {0x00, 0x79, 0x0f, 0xaa}, | ||
2378 | {0x00, 0xc8, 0x00, 0xaa}, | ||
2379 | {0x00, 0x79, 0x10, 0xaa}, | ||
2380 | {0x00, 0xc8, 0x7e, 0xaa}, | ||
2381 | {0x00, 0x79, 0x0a, 0xaa}, | ||
2382 | {0x00, 0xc8, 0x80, 0xaa}, | ||
2383 | {0x00, 0x79, 0x0b, 0xaa}, | ||
2384 | {0x00, 0xc8, 0x01, 0xaa}, | ||
2385 | {0x00, 0x79, 0x0c, 0xaa}, | ||
2386 | {0x00, 0xc8, 0x0f, 0xaa}, | ||
2387 | {0x00, 0x79, 0x0d, 0xaa}, | ||
2388 | {0x00, 0xc8, 0x20, 0xaa}, | ||
2389 | {0x00, 0x79, 0x09, 0xaa}, | ||
2390 | {0x00, 0xc8, 0x80, 0xaa}, | ||
2391 | {0x00, 0x79, 0x02, 0xaa}, | ||
2392 | {0x00, 0xc8, 0xc0, 0xaa}, | ||
2393 | {0x00, 0x79, 0x03, 0xaa}, | ||
2394 | {0x00, 0xc8, 0x40, 0xaa}, | ||
2395 | {0x00, 0x79, 0x05, 0xaa}, | ||
2396 | {0x00, 0xc8, 0x30, 0xaa}, | ||
2397 | {0x00, 0x79, 0x26, 0xaa}, | ||
2398 | {0x00, 0x11, 0x40, 0xaa}, | ||
2399 | {0x00, 0x3a, 0x04, 0xaa}, | ||
2400 | {0x00, 0x12, 0x00, 0xaa}, | ||
2401 | {0x00, 0x40, 0xc0, 0xaa}, | ||
2402 | {0x00, 0x8c, 0x00, 0xaa}, | ||
2403 | {0x00, 0x17, 0x14, 0xaa}, | ||
2404 | {0x00, 0x18, 0x02, 0xaa}, | ||
2405 | {0x00, 0x32, 0x92, 0xaa}, | ||
2406 | {0x00, 0x19, 0x02, 0xaa}, | ||
2407 | {0x00, 0x1a, 0x7a, 0xaa}, | ||
2408 | {0x00, 0x03, 0x0a, 0xaa}, | ||
2409 | {0x00, 0x0c, 0x00, 0xaa}, | ||
2410 | {0x00, 0x3e, 0x00, 0xaa}, | ||
2411 | {0x00, 0x70, 0x3a, 0xaa}, | ||
2412 | {0x00, 0x71, 0x35, 0xaa}, | ||
2413 | {0x00, 0x72, 0x11, 0xaa}, | ||
2414 | {0x00, 0x73, 0xf0, 0xaa}, | ||
2415 | {0x00, 0xa2, 0x02, 0xaa}, | ||
2416 | {0x00, 0xb1, 0x00, 0xaa}, | ||
2417 | {0x00, 0xb1, 0x0c, 0xaa}, | ||
2209 | {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ | 2418 | {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ |
2210 | {0x00, 0xaa, 0x14, 0xaa}, | 2419 | {0x00, 0xaa, 0x14, 0xaa}, |
2211 | {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, | 2420 | {0x00, 0x24, 0x80, 0xaa}, |
2212 | {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, | 2421 | {0x00, 0x25, 0x74, 0xaa}, |
2213 | {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, | 2422 | {0x00, 0x26, 0xd3, 0xaa}, |
2214 | {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, | 2423 | {0x00, 0x0d, 0x00, 0xaa}, |
2215 | {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa}, | 2424 | {0x00, 0x14, 0x18, 0xaa}, |
2216 | {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, | 2425 | {0x00, 0x9d, 0x99, 0xaa}, |
2217 | {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa}, | 2426 | {0x00, 0x9e, 0x7f, 0xaa}, |
2218 | {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, | 2427 | {0x00, 0x64, 0x08, 0xaa}, |
2219 | {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa}, | 2428 | {0x00, 0x94, 0x07, 0xaa}, |
2220 | {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, | 2429 | {0x00, 0x95, 0x06, 0xaa}, |
2221 | {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc}, | 2430 | {0x00, 0x66, 0x05, 0xaa}, |
2222 | {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, | 2431 | {0x00, 0x41, 0x08, 0xaa}, |
2223 | {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, | 2432 | {0x00, 0x3f, 0x00, 0xaa}, |
2224 | {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x21, 0xcc}, | 2433 | {0x00, 0x75, 0x07, 0xaa}, |
2225 | {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, | 2434 | {0x00, 0x76, 0xe1, 0xaa}, |
2226 | {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, | 2435 | {0x00, 0x4c, 0x00, 0xaa}, |
2227 | {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, | 2436 | {0x00, 0x77, 0x00, 0xaa}, |
2228 | {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, | 2437 | {0x00, 0x3d, 0xc2, 0xaa}, |
2229 | {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, | 2438 | {0x00, 0x4b, 0x09, 0xaa}, |
2230 | {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc}, | 2439 | {0x00, 0xc9, 0x60, 0xaa}, |
2231 | {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc}, | 2440 | {0x00, 0x41, 0x38, 0xaa}, |
2232 | {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc}, | 2441 | {0xbc, 0x02, 0x18, 0xcc}, |
2233 | {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, | 2442 | {0xbc, 0x03, 0x50, 0xcc}, |
2234 | {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc}, | 2443 | {0xbc, 0x04, 0x18, 0xcc}, |
2235 | {0x00, 0x77, 0x05, 0xaa }, | 2444 | {0xbc, 0x05, 0x00, 0xcc}, |
2445 | {0xbc, 0x06, 0x00, 0xcc}, | ||
2446 | {0xbc, 0x08, 0x30, 0xcc}, | ||
2447 | {0xbc, 0x09, 0x40, 0xcc}, | ||
2448 | {0xbc, 0x0a, 0x10, 0xcc}, | ||
2449 | {0xbc, 0x0b, 0x00, 0xcc}, | ||
2450 | {0xbc, 0x0c, 0x00, 0xcc}, | ||
2451 | {0xbf, 0xc0, 0x26, 0xcc}, | ||
2452 | {0xbf, 0xc1, 0x02, 0xcc}, | ||
2453 | {0xbf, 0xcc, 0x04, 0xcc}, | ||
2454 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2455 | {0xb3, 0x01, 0x45, 0xcc}, | ||
2456 | {0x00, 0x77, 0x05, 0xaa}, | ||
2236 | {}, | 2457 | {}, |
2237 | }; | 2458 | }; |
2238 | 2459 | ||
@@ -3117,6 +3338,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3117 | cam->cam_mode = bi_mode; | 3338 | cam->cam_mode = bi_mode; |
3118 | cam->nmodes = ARRAY_SIZE(bi_mode); | 3339 | cam->nmodes = ARRAY_SIZE(bi_mode); |
3119 | break; | 3340 | break; |
3341 | case SENSOR_OV7670: | ||
3342 | cam->cam_mode = bi_mode; | ||
3343 | cam->nmodes = ARRAY_SIZE(bi_mode) - 1; | ||
3344 | break; | ||
3120 | default: | 3345 | default: |
3121 | cam->cam_mode = vc0323_mode; | 3346 | cam->cam_mode = vc0323_mode; |
3122 | cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; | 3347 | cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; |
@@ -3329,14 +3554,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3329 | else | 3554 | else |
3330 | init = ov7660_initVGA_data; /* 640x480 */ | 3555 | init = ov7660_initVGA_data; /* 640x480 */ |
3331 | break; | 3556 | break; |
3332 | case SENSOR_OV7670: | ||
3333 | /*GammaT = ov7660_gamma; */ | ||
3334 | /*MatrixT = ov7660_matrix; */ | ||
3335 | if (mode) | ||
3336 | init = ov7670_initQVGA_JPG; /* 320x240 */ | ||
3337 | else | ||
3338 | init = ov7670_initVGA_JPG; /* 640x480 */ | ||
3339 | break; | ||
3340 | case SENSOR_MI0360: | 3557 | case SENSOR_MI0360: |
3341 | GammaT = mi1320_gamma; | 3558 | GammaT = mi1320_gamma; |
3342 | MatrixT = mi0360_matrix; | 3559 | MatrixT = mi0360_matrix; |
@@ -3373,6 +3590,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3373 | MatrixT = mi1320_matrix; | 3590 | MatrixT = mi1320_matrix; |
3374 | init = mi1320_soc_init[mode]; | 3591 | init = mi1320_soc_init[mode]; |
3375 | break; | 3592 | break; |
3593 | case SENSOR_OV7670: | ||
3594 | init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA; | ||
3595 | break; | ||
3376 | case SENSOR_PO3130NC: | 3596 | case SENSOR_PO3130NC: |
3377 | GammaT = po3130_gamma; | 3597 | GammaT = po3130_gamma; |
3378 | MatrixT = po3130_matrix; | 3598 | MatrixT = po3130_matrix; |
@@ -3426,7 +3646,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3426 | sethvflip(gspca_dev); | 3646 | sethvflip(gspca_dev); |
3427 | setlightfreq(gspca_dev); | 3647 | setlightfreq(gspca_dev); |
3428 | } | 3648 | } |
3429 | if (sd->sensor == SENSOR_POxxxx) { | 3649 | switch (sd->sensor) { |
3650 | case SENSOR_OV7670: | ||
3651 | reg_w(gspca_dev->dev, 0x87, 0xffff, 0xffff); | ||
3652 | reg_w(gspca_dev->dev, 0x88, 0xff00, 0xf0f1); | ||
3653 | reg_w(gspca_dev->dev, 0xa0, 0x0000, 0xbfff); | ||
3654 | break; | ||
3655 | case SENSOR_POxxxx: | ||
3430 | setcolors(gspca_dev); | 3656 | setcolors(gspca_dev); |
3431 | setbrightness(gspca_dev); | 3657 | setbrightness(gspca_dev); |
3432 | setcontrast(gspca_dev); | 3658 | setcontrast(gspca_dev); |
@@ -3435,6 +3661,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3435 | msleep(80); | 3661 | msleep(80); |
3436 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | 3662 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); |
3437 | usb_exchange(gspca_dev, poxxxx_init_end_2); | 3663 | usb_exchange(gspca_dev, poxxxx_init_end_2); |
3664 | break; | ||
3438 | } | 3665 | } |
3439 | return 0; | 3666 | return 0; |
3440 | } | 3667 | } |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 7d7814c43f92..d02aa5c8472a 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -40,7 +40,6 @@ static int force_sensor = -1; | |||
40 | struct sd { | 40 | struct sd { |
41 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 41 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
42 | 42 | ||
43 | u8 brightness; | ||
44 | u8 contrast; | 43 | u8 contrast; |
45 | u8 gamma; | 44 | u8 gamma; |
46 | u8 autogain; | 45 | u8 autogain; |
@@ -80,8 +79,6 @@ struct sd { | |||
80 | }; | 79 | }; |
81 | 80 | ||
82 | /* V4L2 controls supported by the driver */ | 81 | /* V4L2 controls supported by the driver */ |
83 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 82 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
86 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 83 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
87 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 84 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
@@ -94,21 +91,6 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | |||
94 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 91 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
95 | 92 | ||
96 | static const struct ctrl sd_ctrls[] = { | 93 | static const struct ctrl sd_ctrls[] = { |
97 | #define BRIGHTNESS_IDX 0 | ||
98 | { | ||
99 | { | ||
100 | .id = V4L2_CID_BRIGHTNESS, | ||
101 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
102 | .name = "Brightness", | ||
103 | .minimum = 0, | ||
104 | .maximum = 255, | ||
105 | .step = 1, | ||
106 | #define BRIGHTNESS_DEF 128 | ||
107 | .default_value = BRIGHTNESS_DEF, | ||
108 | }, | ||
109 | .set = sd_setbrightness, | ||
110 | .get = sd_getbrightness, | ||
111 | }, | ||
112 | { | 94 | { |
113 | { | 95 | { |
114 | .id = V4L2_CID_CONTRAST, | 96 | .id = V4L2_CID_CONTRAST, |
@@ -150,7 +132,7 @@ static const struct ctrl sd_ctrls[] = { | |||
150 | .set = sd_setautogain, | 132 | .set = sd_setautogain, |
151 | .get = sd_getautogain, | 133 | .get = sd_getautogain, |
152 | }, | 134 | }, |
153 | #define LIGHTFREQ_IDX 4 | 135 | #define LIGHTFREQ_IDX 3 |
154 | { | 136 | { |
155 | { | 137 | { |
156 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 138 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -6004,33 +5986,6 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
6004 | reg_w(gspca_dev->dev, matrix[i], 0x010a + i); | 5986 | reg_w(gspca_dev->dev, matrix[i], 0x010a + i); |
6005 | } | 5987 | } |
6006 | 5988 | ||
6007 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
6008 | { | ||
6009 | struct sd *sd = (struct sd *) gspca_dev; | ||
6010 | u8 brightness; | ||
6011 | |||
6012 | switch (sd->sensor) { | ||
6013 | case SENSOR_GC0305: | ||
6014 | case SENSOR_OV7620: | ||
6015 | case SENSOR_PAS202B: | ||
6016 | case SENSOR_PO2030: | ||
6017 | return; | ||
6018 | } | ||
6019 | /*fixme: is it really write to 011d and 018d for all other sensors? */ | ||
6020 | brightness = sd->brightness; | ||
6021 | reg_w(gspca_dev->dev, brightness, 0x011d); | ||
6022 | switch (sd->sensor) { | ||
6023 | case SENSOR_ADCM2700: | ||
6024 | case SENSOR_HV7131B: | ||
6025 | return; | ||
6026 | } | ||
6027 | if (brightness < 0x70) | ||
6028 | brightness += 0x10; | ||
6029 | else | ||
6030 | brightness = 0x80; | ||
6031 | reg_w(gspca_dev->dev, brightness, 0x018d); | ||
6032 | } | ||
6033 | |||
6034 | static void setsharpness(struct gspca_dev *gspca_dev) | 5989 | static void setsharpness(struct gspca_dev *gspca_dev) |
6035 | { | 5990 | { |
6036 | struct sd *sd = (struct sd *) gspca_dev; | 5991 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -6059,8 +6014,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6059 | int g, i, k, adj, gp; | 6014 | int g, i, k, adj, gp; |
6060 | u8 gr[16]; | 6015 | u8 gr[16]; |
6061 | static const u8 delta_tb[16] = /* delta for contrast */ | 6016 | static const u8 delta_tb[16] = /* delta for contrast */ |
6062 | {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, | 6017 | {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, |
6063 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; | 6018 | 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; |
6064 | static const u8 gamma_tb[6][16] = { | 6019 | static const u8 gamma_tb[6][16] = { |
6065 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, | 6020 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, |
6066 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, | 6021 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, |
@@ -6082,11 +6037,11 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6082 | adj = 0; | 6037 | adj = 0; |
6083 | gp = 0; | 6038 | gp = 0; |
6084 | for (i = 0; i < 16; i++) { | 6039 | for (i = 0; i < 16; i++) { |
6085 | g = Tgamma[i] - delta_tb[i] * k / 128 - adj / 2; | 6040 | g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2; |
6086 | if (g > 0xff) | 6041 | if (g > 0xff) |
6087 | g = 0xff; | 6042 | g = 0xff; |
6088 | else if (g <= 0) | 6043 | else if (g < 0) |
6089 | g = 1; | 6044 | g = 0; |
6090 | reg_w(dev, g, 0x0120 + i); /* gamma */ | 6045 | reg_w(dev, g, 0x0120 + i); /* gamma */ |
6091 | if (k > 0) | 6046 | if (k > 0) |
6092 | adj--; | 6047 | adj--; |
@@ -6203,13 +6158,13 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6203 | pas106b_50HZ, pas106b_50HZ, | 6158 | pas106b_50HZ, pas106b_50HZ, |
6204 | pas106b_60HZ, pas106b_60HZ}, | 6159 | pas106b_60HZ, pas106b_60HZ}, |
6205 | /* SENSOR_PAS202B 13 */ | 6160 | /* SENSOR_PAS202B 13 */ |
6206 | {pas202b_NoFlikerScale, pas202b_NoFliker, | 6161 | {pas202b_NoFliker, pas202b_NoFlikerScale, |
6207 | pas202b_50HZScale, pas202b_50HZ, | 6162 | pas202b_50HZ, pas202b_50HZScale, |
6208 | pas202b_60HZScale, pas202b_60HZ}, | 6163 | pas202b_60HZ, pas202b_60HZScale}, |
6209 | /* SENSOR_PB0330 14 */ | 6164 | /* SENSOR_PB0330 14 */ |
6210 | {pb0330_NoFlikerScale, pb0330_NoFliker, | 6165 | {pb0330_NoFliker, pb0330_NoFlikerScale, |
6211 | pb0330_50HZScale, pb0330_50HZ, | 6166 | pb0330_50HZ, pb0330_50HZScale, |
6212 | pb0330_60HZScale, pb0330_60HZ}, | 6167 | pb0330_60HZ, pb0330_60HZScale}, |
6213 | /* SENSOR_PO2030 15 */ | 6168 | /* SENSOR_PO2030 15 */ |
6214 | {po2030_NoFliker, po2030_NoFliker, | 6169 | {po2030_NoFliker, po2030_NoFliker, |
6215 | po2030_50HZ, po2030_50HZ, | 6170 | po2030_50HZ, po2030_50HZ, |
@@ -6789,7 +6744,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6789 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); | 6744 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); |
6790 | break; | 6745 | break; |
6791 | } | 6746 | } |
6792 | sd->brightness = BRIGHTNESS_DEF; | ||
6793 | sd->contrast = CONTRAST_DEF; | 6747 | sd->contrast = CONTRAST_DEF; |
6794 | sd->gamma = gamma[sd->sensor]; | 6748 | sd->gamma = gamma[sd->sensor]; |
6795 | sd->autogain = AUTOGAIN_DEF; | 6749 | sd->autogain = AUTOGAIN_DEF; |
@@ -6797,12 +6751,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6797 | sd->quality = QUALITY_DEF; | 6751 | sd->quality = QUALITY_DEF; |
6798 | 6752 | ||
6799 | switch (sd->sensor) { | 6753 | switch (sd->sensor) { |
6800 | case SENSOR_GC0305: | ||
6801 | case SENSOR_OV7620: | ||
6802 | case SENSOR_PAS202B: | ||
6803 | case SENSOR_PO2030: | ||
6804 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); | ||
6805 | break; | ||
6806 | case SENSOR_HV7131B: | 6754 | case SENSOR_HV7131B: |
6807 | case SENSOR_HV7131C: | 6755 | case SENSOR_HV7131C: |
6808 | case SENSOR_OV7630C: | 6756 | case SENSOR_OV7630C: |
@@ -6893,7 +6841,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6893 | } | 6841 | } |
6894 | 6842 | ||
6895 | setmatrix(gspca_dev); | 6843 | setmatrix(gspca_dev); |
6896 | setbrightness(gspca_dev); | ||
6897 | switch (sd->sensor) { | 6844 | switch (sd->sensor) { |
6898 | case SENSOR_ADCM2700: | 6845 | case SENSOR_ADCM2700: |
6899 | case SENSOR_OV7620: | 6846 | case SENSOR_OV7620: |
@@ -7015,24 +6962,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
7015 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 6962 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
7016 | } | 6963 | } |
7017 | 6964 | ||
7018 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
7019 | { | ||
7020 | struct sd *sd = (struct sd *) gspca_dev; | ||
7021 | |||
7022 | sd->brightness = val; | ||
7023 | if (gspca_dev->streaming) | ||
7024 | setbrightness(gspca_dev); | ||
7025 | return 0; | ||
7026 | } | ||
7027 | |||
7028 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
7029 | { | ||
7030 | struct sd *sd = (struct sd *) gspca_dev; | ||
7031 | |||
7032 | *val = sd->brightness; | ||
7033 | return 0; | ||
7034 | } | ||
7035 | |||
7036 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 6965 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) |
7037 | { | 6966 | { |
7038 | struct sd *sd = (struct sd *) gspca_dev; | 6967 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 2fc9865fd486..830d47b05e1d 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -373,9 +373,6 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
373 | } | 373 | } |
374 | #endif /* CONFIG_I2C */ | 374 | #endif /* CONFIG_I2C */ |
375 | 375 | ||
376 | /* save our data pointer in this interface device */ | ||
377 | usb_set_intfdata(interface, dev); | ||
378 | |||
379 | /* let the user know what node this device is now attached to */ | 376 | /* let the user know what node this device is now attached to */ |
380 | v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", | 377 | v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", |
381 | video_device_node_name(dev->video_dev)); | 378 | video_device_node_name(dev->video_dev)); |
@@ -391,44 +388,24 @@ error: | |||
391 | 388 | ||
392 | static void hdpvr_disconnect(struct usb_interface *interface) | 389 | static void hdpvr_disconnect(struct usb_interface *interface) |
393 | { | 390 | { |
394 | struct hdpvr_device *dev; | 391 | struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface)); |
395 | |||
396 | dev = usb_get_intfdata(interface); | ||
397 | usb_set_intfdata(interface, NULL); | ||
398 | 392 | ||
393 | v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", | ||
394 | video_device_node_name(dev->video_dev)); | ||
399 | /* prevent more I/O from starting and stop any ongoing */ | 395 | /* prevent more I/O from starting and stop any ongoing */ |
400 | mutex_lock(&dev->io_mutex); | 396 | mutex_lock(&dev->io_mutex); |
401 | dev->status = STATUS_DISCONNECTED; | 397 | dev->status = STATUS_DISCONNECTED; |
402 | v4l2_device_disconnect(&dev->v4l2_dev); | ||
403 | video_unregister_device(dev->video_dev); | ||
404 | wake_up_interruptible(&dev->wait_data); | 398 | wake_up_interruptible(&dev->wait_data); |
405 | wake_up_interruptible(&dev->wait_buffer); | 399 | wake_up_interruptible(&dev->wait_buffer); |
406 | mutex_unlock(&dev->io_mutex); | 400 | mutex_unlock(&dev->io_mutex); |
401 | v4l2_device_disconnect(&dev->v4l2_dev); | ||
407 | msleep(100); | 402 | msleep(100); |
408 | flush_workqueue(dev->workqueue); | 403 | flush_workqueue(dev->workqueue); |
409 | mutex_lock(&dev->io_mutex); | 404 | mutex_lock(&dev->io_mutex); |
410 | hdpvr_cancel_queue(dev); | 405 | hdpvr_cancel_queue(dev); |
411 | destroy_workqueue(dev->workqueue); | ||
412 | mutex_unlock(&dev->io_mutex); | 406 | mutex_unlock(&dev->io_mutex); |
413 | 407 | video_unregister_device(dev->video_dev); | |
414 | /* deregister I2C adapter */ | ||
415 | #ifdef CONFIG_I2C | ||
416 | mutex_lock(&dev->i2c_mutex); | ||
417 | if (dev->i2c_adapter) | ||
418 | i2c_del_adapter(dev->i2c_adapter); | ||
419 | kfree(dev->i2c_adapter); | ||
420 | dev->i2c_adapter = NULL; | ||
421 | mutex_unlock(&dev->i2c_mutex); | ||
422 | #endif /* CONFIG_I2C */ | ||
423 | |||
424 | atomic_dec(&dev_nr); | 408 | atomic_dec(&dev_nr); |
425 | |||
426 | v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", | ||
427 | video_device_node_name(dev->video_dev)); | ||
428 | |||
429 | v4l2_device_unregister(&dev->v4l2_dev); | ||
430 | kfree(dev->usbc_buf); | ||
431 | kfree(dev); | ||
432 | } | 409 | } |
433 | 410 | ||
434 | 411 | ||
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 196f82de48f0..d2f0ee29737f 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -1214,6 +1214,24 @@ static void hdpvr_device_release(struct video_device *vdev) | |||
1214 | struct hdpvr_device *dev = video_get_drvdata(vdev); | 1214 | struct hdpvr_device *dev = video_get_drvdata(vdev); |
1215 | 1215 | ||
1216 | hdpvr_delete(dev); | 1216 | hdpvr_delete(dev); |
1217 | mutex_lock(&dev->io_mutex); | ||
1218 | destroy_workqueue(dev->workqueue); | ||
1219 | mutex_unlock(&dev->io_mutex); | ||
1220 | |||
1221 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1222 | |||
1223 | /* deregister I2C adapter */ | ||
1224 | #ifdef CONFIG_I2C | ||
1225 | mutex_lock(&dev->i2c_mutex); | ||
1226 | if (dev->i2c_adapter) | ||
1227 | i2c_del_adapter(dev->i2c_adapter); | ||
1228 | kfree(dev->i2c_adapter); | ||
1229 | dev->i2c_adapter = NULL; | ||
1230 | mutex_unlock(&dev->i2c_mutex); | ||
1231 | #endif /* CONFIG_I2C */ | ||
1232 | |||
1233 | kfree(dev->usbc_buf); | ||
1234 | kfree(dev); | ||
1217 | } | 1235 | } |
1218 | 1236 | ||
1219 | static const struct video_device hdpvr_video_template = { | 1237 | static const struct video_device hdpvr_video_template = { |
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 49ae25d83d10..b0f046df3cd8 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h | |||
@@ -111,6 +111,11 @@ struct hdpvr_device { | |||
111 | u8 *usbc_buf; | 111 | u8 *usbc_buf; |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) | ||
115 | { | ||
116 | return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev); | ||
117 | } | ||
118 | |||
114 | 119 | ||
115 | /* buffer one bulk urb of data */ | 120 | /* buffer one bulk urb of data */ |
116 | struct hdpvr_buffer { | 121 | struct hdpvr_buffer { |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index da18d698e7f2..29d439742653 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -61,9 +61,9 @@ module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ | |||
61 | MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); | 61 | MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); |
62 | 62 | ||
63 | 63 | ||
64 | #define DEVNAME "ir-kbd-i2c" | 64 | #define MODULE_NAME "ir-kbd-i2c" |
65 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | 65 | #define dprintk(level, fmt, arg...) if (debug >= level) \ |
66 | printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) | 66 | printk(KERN_DEBUG MODULE_NAME ": " fmt , ## arg) |
67 | 67 | ||
68 | /* ----------------------------------------------------------------------- */ | 68 | /* ----------------------------------------------------------------------- */ |
69 | 69 | ||
@@ -297,7 +297,7 @@ static void ir_work(struct work_struct *work) | |||
297 | 297 | ||
298 | static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | 298 | static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) |
299 | { | 299 | { |
300 | struct ir_scancode_table *ir_codes = NULL; | 300 | char *ir_codes = NULL; |
301 | const char *name = NULL; | 301 | const char *name = NULL; |
302 | u64 ir_type = 0; | 302 | u64 ir_type = 0; |
303 | struct IR_i2c *ir; | 303 | struct IR_i2c *ir; |
@@ -322,13 +322,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
322 | name = "Pixelview"; | 322 | name = "Pixelview"; |
323 | ir->get_key = get_key_pixelview; | 323 | ir->get_key = get_key_pixelview; |
324 | ir_type = IR_TYPE_OTHER; | 324 | ir_type = IR_TYPE_OTHER; |
325 | ir_codes = &ir_codes_empty_table; | 325 | ir_codes = RC_MAP_EMPTY; |
326 | break; | 326 | break; |
327 | case 0x4b: | 327 | case 0x4b: |
328 | name = "PV951"; | 328 | name = "PV951"; |
329 | ir->get_key = get_key_pv951; | 329 | ir->get_key = get_key_pv951; |
330 | ir_type = IR_TYPE_OTHER; | 330 | ir_type = IR_TYPE_OTHER; |
331 | ir_codes = &ir_codes_pv951_table; | 331 | ir_codes = RC_MAP_PV951; |
332 | break; | 332 | break; |
333 | case 0x18: | 333 | case 0x18: |
334 | case 0x1f: | 334 | case 0x1f: |
@@ -337,22 +337,22 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
337 | ir->get_key = get_key_haup; | 337 | ir->get_key = get_key_haup; |
338 | ir_type = IR_TYPE_RC5; | 338 | ir_type = IR_TYPE_RC5; |
339 | if (hauppauge == 1) { | 339 | if (hauppauge == 1) { |
340 | ir_codes = &ir_codes_hauppauge_new_table; | 340 | ir_codes = RC_MAP_HAUPPAUGE_NEW; |
341 | } else { | 341 | } else { |
342 | ir_codes = &ir_codes_rc5_tv_table; | 342 | ir_codes = RC_MAP_RC5_TV; |
343 | } | 343 | } |
344 | break; | 344 | break; |
345 | case 0x30: | 345 | case 0x30: |
346 | name = "KNC One"; | 346 | name = "KNC One"; |
347 | ir->get_key = get_key_knc1; | 347 | ir->get_key = get_key_knc1; |
348 | ir_type = IR_TYPE_OTHER; | 348 | ir_type = IR_TYPE_OTHER; |
349 | ir_codes = &ir_codes_empty_table; | 349 | ir_codes = RC_MAP_EMPTY; |
350 | break; | 350 | break; |
351 | case 0x6b: | 351 | case 0x6b: |
352 | name = "FusionHDTV"; | 352 | name = "FusionHDTV"; |
353 | ir->get_key = get_key_fusionhdtv; | 353 | ir->get_key = get_key_fusionhdtv; |
354 | ir_type = IR_TYPE_RC5; | 354 | ir_type = IR_TYPE_RC5; |
355 | ir_codes = &ir_codes_fusionhdtv_mce_table; | 355 | ir_codes = RC_MAP_FUSIONHDTV_MCE; |
356 | break; | 356 | break; |
357 | case 0x0b: | 357 | case 0x0b: |
358 | case 0x47: | 358 | case 0x47: |
@@ -365,9 +365,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
365 | ir_type = IR_TYPE_RC5; | 365 | ir_type = IR_TYPE_RC5; |
366 | ir->get_key = get_key_haup_xvr; | 366 | ir->get_key = get_key_haup_xvr; |
367 | if (hauppauge == 1) { | 367 | if (hauppauge == 1) { |
368 | ir_codes = &ir_codes_hauppauge_new_table; | 368 | ir_codes = RC_MAP_HAUPPAUGE_NEW; |
369 | } else { | 369 | } else { |
370 | ir_codes = &ir_codes_rc5_tv_table; | 370 | ir_codes = RC_MAP_RC5_TV; |
371 | } | 371 | } |
372 | } else { | 372 | } else { |
373 | /* Handled by saa7134-input */ | 373 | /* Handled by saa7134-input */ |
@@ -379,7 +379,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
379 | name = "AVerMedia Cardbus remote"; | 379 | name = "AVerMedia Cardbus remote"; |
380 | ir->get_key = get_key_avermedia_cardbus; | 380 | ir->get_key = get_key_avermedia_cardbus; |
381 | ir_type = IR_TYPE_OTHER; | 381 | ir_type = IR_TYPE_OTHER; |
382 | ir_codes = &ir_codes_avermedia_cardbus_table; | 382 | ir_codes = RC_MAP_AVERMEDIA_CARDBUS; |
383 | break; | 383 | break; |
384 | } | 384 | } |
385 | 385 | ||
@@ -447,11 +447,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
447 | input_dev->name = ir->name; | 447 | input_dev->name = ir->name; |
448 | input_dev->phys = ir->phys; | 448 | input_dev->phys = ir->phys; |
449 | 449 | ||
450 | err = ir_input_register(ir->input, ir->ir_codes, NULL); | 450 | err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); |
451 | if (err) | 451 | if (err) |
452 | goto err_out_free; | 452 | goto err_out_free; |
453 | 453 | ||
454 | printk(DEVNAME ": %s detected at %s [%s]\n", | 454 | printk(MODULE_NAME ": %s detected at %s [%s]\n", |
455 | ir->input->name, ir->input->phys, adap->name); | 455 | ir->input->name, ir->input->phys, adap->name); |
456 | 456 | ||
457 | /* start polling via eventd */ | 457 | /* start polling via eventd */ |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 9a250548be4d..1b79475ca134 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -1293,7 +1293,6 @@ int ivtv_init_on_first_open(struct ivtv *itv) | |||
1293 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); | 1293 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); |
1294 | ivtv_init_mpeg_decoder(itv); | 1294 | ivtv_init_mpeg_decoder(itv); |
1295 | } | 1295 | } |
1296 | ivtv_s_std(NULL, &fh, &itv->tuner_std); | ||
1297 | 1296 | ||
1298 | /* On a cx23416 this seems to be able to enable DMA to the chip? */ | 1297 | /* On a cx23416 this seems to be able to enable DMA to the chip? */ |
1299 | if (!itv->has_cx23415) | 1298 | if (!itv->has_cx23415) |
@@ -1310,6 +1309,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) | |||
1310 | } | 1309 | } |
1311 | else | 1310 | else |
1312 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); | 1311 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); |
1312 | |||
1313 | /* For cards with video out, this call needs interrupts enabled */ | ||
1314 | ivtv_s_std(NULL, &fh, &itv->tuner_std); | ||
1315 | |||
1313 | return 0; | 1316 | return 0; |
1314 | } | 1317 | } |
1315 | 1318 | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 5028e31c564a..5b45fd2b2645 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <media/v4l2-common.h> | 63 | #include <media/v4l2-common.h> |
64 | #include <media/v4l2-ioctl.h> | 64 | #include <media/v4l2-ioctl.h> |
65 | #include <media/v4l2-device.h> | 65 | #include <media/v4l2-device.h> |
66 | #include <media/v4l2-fh.h> | ||
66 | #include <media/tuner.h> | 67 | #include <media/tuner.h> |
67 | #include <media/cx2341x.h> | 68 | #include <media/cx2341x.h> |
68 | #include <media/ir-kbd-i2c.h> | 69 | #include <media/ir-kbd-i2c.h> |
@@ -116,6 +117,9 @@ | |||
116 | #define IVTV_REG_VPU (0x9058) | 117 | #define IVTV_REG_VPU (0x9058) |
117 | #define IVTV_REG_APU (0xA064) | 118 | #define IVTV_REG_APU (0xA064) |
118 | 119 | ||
120 | /* Other registers */ | ||
121 | #define IVTV_REG_DEC_LINE_FIELD (0x28C0) | ||
122 | |||
119 | /* debugging */ | 123 | /* debugging */ |
120 | extern int ivtv_debug; | 124 | extern int ivtv_debug; |
121 | 125 | ||
@@ -372,6 +376,7 @@ struct ivtv_stream { | |||
372 | }; | 376 | }; |
373 | 377 | ||
374 | struct ivtv_open_id { | 378 | struct ivtv_open_id { |
379 | struct v4l2_fh fh; | ||
375 | u32 open_id; /* unique ID for this file descriptor */ | 380 | u32 open_id; /* unique ID for this file descriptor */ |
376 | int type; /* stream type */ | 381 | int type; /* stream type */ |
377 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ | 382 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ |
@@ -379,6 +384,11 @@ struct ivtv_open_id { | |||
379 | struct ivtv *itv; | 384 | struct ivtv *itv; |
380 | }; | 385 | }; |
381 | 386 | ||
387 | static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh) | ||
388 | { | ||
389 | return container_of(fh, struct ivtv_open_id, fh); | ||
390 | } | ||
391 | |||
382 | struct yuv_frame_info | 392 | struct yuv_frame_info |
383 | { | 393 | { |
384 | u32 update; | 394 | u32 update; |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index babcabd73c08..abf410943cc9 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "ivtv-yuv.h" | 32 | #include "ivtv-yuv.h" |
33 | #include "ivtv-ioctl.h" | 33 | #include "ivtv-ioctl.h" |
34 | #include "ivtv-cards.h" | 34 | #include "ivtv-cards.h" |
35 | #include <media/v4l2-event.h> | ||
35 | #include <media/saa7115.h> | 36 | #include <media/saa7115.h> |
36 | 37 | ||
37 | /* This function tries to claim the stream for a specific file descriptor. | 38 | /* This function tries to claim the stream for a specific file descriptor. |
@@ -506,7 +507,7 @@ int ivtv_start_capture(struct ivtv_open_id *id) | |||
506 | 507 | ||
507 | ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) | 508 | ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) |
508 | { | 509 | { |
509 | struct ivtv_open_id *id = filp->private_data; | 510 | struct ivtv_open_id *id = fh2id(filp->private_data); |
510 | struct ivtv *itv = id->itv; | 511 | struct ivtv *itv = id->itv; |
511 | struct ivtv_stream *s = &itv->streams[id->type]; | 512 | struct ivtv_stream *s = &itv->streams[id->type]; |
512 | int rc; | 513 | int rc; |
@@ -541,7 +542,7 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) | |||
541 | 542 | ||
542 | ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) | 543 | ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) |
543 | { | 544 | { |
544 | struct ivtv_open_id *id = filp->private_data; | 545 | struct ivtv_open_id *id = fh2id(filp->private_data); |
545 | struct ivtv *itv = id->itv; | 546 | struct ivtv *itv = id->itv; |
546 | struct ivtv_stream *s = &itv->streams[id->type]; | 547 | struct ivtv_stream *s = &itv->streams[id->type]; |
547 | struct yuv_playback_info *yi = &itv->yuv_info; | 548 | struct yuv_playback_info *yi = &itv->yuv_info; |
@@ -711,19 +712,31 @@ retry: | |||
711 | 712 | ||
712 | unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) | 713 | unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) |
713 | { | 714 | { |
714 | struct ivtv_open_id *id = filp->private_data; | 715 | struct ivtv_open_id *id = fh2id(filp->private_data); |
715 | struct ivtv *itv = id->itv; | 716 | struct ivtv *itv = id->itv; |
716 | struct ivtv_stream *s = &itv->streams[id->type]; | 717 | struct ivtv_stream *s = &itv->streams[id->type]; |
717 | int res = 0; | 718 | int res = 0; |
718 | 719 | ||
719 | /* add stream's waitq to the poll list */ | 720 | /* add stream's waitq to the poll list */ |
720 | IVTV_DEBUG_HI_FILE("Decoder poll\n"); | 721 | IVTV_DEBUG_HI_FILE("Decoder poll\n"); |
721 | poll_wait(filp, &s->waitq, wait); | ||
722 | 722 | ||
723 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | 723 | /* If there are subscribed events, then only use the new event |
724 | if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || | 724 | API instead of the old video.h based API. */ |
725 | test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) | 725 | if (!list_empty(&id->fh.events->subscribed)) { |
726 | res = POLLPRI; | 726 | poll_wait(filp, &id->fh.events->wait, wait); |
727 | /* Turn off the old-style vsync events */ | ||
728 | clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | ||
729 | if (v4l2_event_pending(&id->fh)) | ||
730 | res = POLLPRI; | ||
731 | } else { | ||
732 | /* This is the old-style API which is here only for backwards | ||
733 | compatibility. */ | ||
734 | poll_wait(filp, &s->waitq, wait); | ||
735 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | ||
736 | if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || | ||
737 | test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) | ||
738 | res = POLLPRI; | ||
739 | } | ||
727 | 740 | ||
728 | /* Allow write if buffers are available for writing */ | 741 | /* Allow write if buffers are available for writing */ |
729 | if (s->q_free.buffers) | 742 | if (s->q_free.buffers) |
@@ -733,7 +746,7 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) | |||
733 | 746 | ||
734 | unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | 747 | unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) |
735 | { | 748 | { |
736 | struct ivtv_open_id *id = filp->private_data; | 749 | struct ivtv_open_id *id = fh2id(filp->private_data); |
737 | struct ivtv *itv = id->itv; | 750 | struct ivtv *itv = id->itv; |
738 | struct ivtv_stream *s = &itv->streams[id->type]; | 751 | struct ivtv_stream *s = &itv->streams[id->type]; |
739 | int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 752 | int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); |
@@ -833,13 +846,16 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | |||
833 | 846 | ||
834 | int ivtv_v4l2_close(struct file *filp) | 847 | int ivtv_v4l2_close(struct file *filp) |
835 | { | 848 | { |
836 | struct ivtv_open_id *id = filp->private_data; | 849 | struct v4l2_fh *fh = filp->private_data; |
850 | struct ivtv_open_id *id = fh2id(fh); | ||
837 | struct ivtv *itv = id->itv; | 851 | struct ivtv *itv = id->itv; |
838 | struct ivtv_stream *s = &itv->streams[id->type]; | 852 | struct ivtv_stream *s = &itv->streams[id->type]; |
839 | 853 | ||
840 | IVTV_DEBUG_FILE("close %s\n", s->name); | 854 | IVTV_DEBUG_FILE("close %s\n", s->name); |
841 | 855 | ||
842 | v4l2_prio_close(&itv->prio, &id->prio); | 856 | v4l2_prio_close(&itv->prio, id->prio); |
857 | v4l2_fh_del(fh); | ||
858 | v4l2_fh_exit(fh); | ||
843 | 859 | ||
844 | /* Easy case first: this stream was never claimed by us */ | 860 | /* Easy case first: this stream was never claimed by us */ |
845 | if (s->id != id->open_id) { | 861 | if (s->id != id->open_id) { |
@@ -895,6 +911,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
895 | { | 911 | { |
896 | struct ivtv *itv = s->itv; | 912 | struct ivtv *itv = s->itv; |
897 | struct ivtv_open_id *item; | 913 | struct ivtv_open_id *item; |
914 | int res = 0; | ||
898 | 915 | ||
899 | IVTV_DEBUG_FILE("open %s\n", s->name); | 916 | IVTV_DEBUG_FILE("open %s\n", s->name); |
900 | 917 | ||
@@ -915,17 +932,27 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
915 | } | 932 | } |
916 | 933 | ||
917 | /* Allocate memory */ | 934 | /* Allocate memory */ |
918 | item = kmalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); | 935 | item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); |
919 | if (NULL == item) { | 936 | if (NULL == item) { |
920 | IVTV_DEBUG_WARN("nomem on v4l2 open\n"); | 937 | IVTV_DEBUG_WARN("nomem on v4l2 open\n"); |
921 | return -ENOMEM; | 938 | return -ENOMEM; |
922 | } | 939 | } |
940 | v4l2_fh_init(&item->fh, s->vdev); | ||
941 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV || | ||
942 | s->type == IVTV_DEC_STREAM_TYPE_MPG) { | ||
943 | res = v4l2_event_alloc(&item->fh, 60); | ||
944 | } | ||
945 | if (res < 0) { | ||
946 | v4l2_fh_exit(&item->fh); | ||
947 | kfree(item); | ||
948 | return res; | ||
949 | } | ||
923 | item->itv = itv; | 950 | item->itv = itv; |
924 | item->type = s->type; | 951 | item->type = s->type; |
925 | v4l2_prio_open(&itv->prio, &item->prio); | 952 | v4l2_prio_open(&itv->prio, &item->prio); |
926 | 953 | ||
927 | item->open_id = itv->open_id++; | 954 | item->open_id = itv->open_id++; |
928 | filp->private_data = item; | 955 | filp->private_data = &item->fh; |
929 | 956 | ||
930 | if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { | 957 | if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { |
931 | /* Try to claim this stream */ | 958 | /* Try to claim this stream */ |
@@ -940,6 +967,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
940 | /* switching to radio while capture is | 967 | /* switching to radio while capture is |
941 | in progress is not polite */ | 968 | in progress is not polite */ |
942 | ivtv_release_stream(s); | 969 | ivtv_release_stream(s); |
970 | v4l2_fh_exit(&item->fh); | ||
943 | kfree(item); | 971 | kfree(item); |
944 | return -EBUSY; | 972 | return -EBUSY; |
945 | } | 973 | } |
@@ -970,6 +998,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
970 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); | 998 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
971 | itv->yuv_info.stream_size = 0; | 999 | itv->yuv_info.stream_size = 0; |
972 | } | 1000 | } |
1001 | v4l2_fh_add(&item->fh); | ||
973 | return 0; | 1002 | return 0; |
974 | } | 1003 | } |
975 | 1004 | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 2ee03c2a1b58..a5b92d109c6c 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -193,7 +193,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
193 | /* Our default information for ir-kbd-i2c.c to use */ | 193 | /* Our default information for ir-kbd-i2c.c to use */ |
194 | switch (hw) { | 194 | switch (hw) { |
195 | case IVTV_HW_I2C_IR_RX_AVER: | 195 | case IVTV_HW_I2C_IR_RX_AVER: |
196 | init_data->ir_codes = &ir_codes_avermedia_cardbus_table; | 196 | init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; |
197 | init_data->internal_get_key_func = | 197 | init_data->internal_get_key_func = |
198 | IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; | 198 | IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; |
199 | init_data->type = IR_TYPE_OTHER; | 199 | init_data->type = IR_TYPE_OTHER; |
@@ -202,14 +202,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
202 | case IVTV_HW_I2C_IR_RX_HAUP_EXT: | 202 | case IVTV_HW_I2C_IR_RX_HAUP_EXT: |
203 | case IVTV_HW_I2C_IR_RX_HAUP_INT: | 203 | case IVTV_HW_I2C_IR_RX_HAUP_INT: |
204 | /* Default to old black remote */ | 204 | /* Default to old black remote */ |
205 | init_data->ir_codes = &ir_codes_rc5_tv_table; | 205 | init_data->ir_codes = RC_MAP_RC5_TV; |
206 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; | 206 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; |
207 | init_data->type = IR_TYPE_RC5; | 207 | init_data->type = IR_TYPE_RC5; |
208 | init_data->name = itv->card_name; | 208 | init_data->name = itv->card_name; |
209 | break; | 209 | break; |
210 | case IVTV_HW_Z8F0811_IR_RX_HAUP: | 210 | case IVTV_HW_Z8F0811_IR_RX_HAUP: |
211 | /* Default to grey remote */ | 211 | /* Default to grey remote */ |
212 | init_data->ir_codes = &ir_codes_hauppauge_new_table; | 212 | init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; |
213 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; | 213 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; |
214 | init_data->type = IR_TYPE_RC5; | 214 | init_data->type = IR_TYPE_RC5; |
215 | init_data->name = itv->card_name; | 215 | init_data->name = itv->card_name; |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 99f3c39a118b..fa9f0d958f96 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <media/saa7127.h> | 35 | #include <media/saa7127.h> |
36 | #include <media/tveeprom.h> | 36 | #include <media/tveeprom.h> |
37 | #include <media/v4l2-chip-ident.h> | 37 | #include <media/v4l2-chip-ident.h> |
38 | #include <media/v4l2-event.h> | ||
38 | #include <linux/dvb/audio.h> | 39 | #include <linux/dvb/audio.h> |
39 | #include <linux/i2c-id.h> | 40 | #include <linux/i2c-id.h> |
40 | 41 | ||
@@ -391,7 +392,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo | |||
391 | return 0; | 392 | return 0; |
392 | } | 393 | } |
393 | 394 | ||
394 | v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt); | 395 | v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt); |
395 | vbifmt->service_set = ivtv_get_service_set(vbifmt); | 396 | vbifmt->service_set = ivtv_get_service_set(vbifmt); |
396 | return 0; | 397 | return 0; |
397 | } | 398 | } |
@@ -597,7 +598,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f | |||
597 | return -EBUSY; | 598 | return -EBUSY; |
598 | itv->vbi.sliced_in->service_set = 0; | 599 | itv->vbi.sliced_in->service_set = 0; |
599 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; | 600 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
600 | v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); | 601 | v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi); |
601 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); | 602 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); |
602 | } | 603 | } |
603 | 604 | ||
@@ -615,7 +616,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo | |||
615 | if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) | 616 | if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) |
616 | return -EBUSY; | 617 | return -EBUSY; |
617 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | 618 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; |
618 | v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); | 619 | v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt); |
619 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); | 620 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); |
620 | return 0; | 621 | return 0; |
621 | } | 622 | } |
@@ -1087,8 +1088,10 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) | |||
1087 | 1088 | ||
1088 | int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) | 1089 | int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) |
1089 | { | 1090 | { |
1091 | DEFINE_WAIT(wait); | ||
1090 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; | 1092 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; |
1091 | struct yuv_playback_info *yi = &itv->yuv_info; | 1093 | struct yuv_playback_info *yi = &itv->yuv_info; |
1094 | int f; | ||
1092 | 1095 | ||
1093 | if ((*std & V4L2_STD_ALL) == 0) | 1096 | if ((*std & V4L2_STD_ALL) == 0) |
1094 | return -EINVAL; | 1097 | return -EINVAL; |
@@ -1128,6 +1131,25 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) | |||
1128 | itv->is_out_60hz = itv->is_60hz; | 1131 | itv->is_out_60hz = itv->is_60hz; |
1129 | itv->is_out_50hz = itv->is_50hz; | 1132 | itv->is_out_50hz = itv->is_50hz; |
1130 | ivtv_call_all(itv, video, s_std_output, itv->std_out); | 1133 | ivtv_call_all(itv, video, s_std_output, itv->std_out); |
1134 | |||
1135 | /* | ||
1136 | * The next firmware call is time sensitive. Time it to | ||
1137 | * avoid risk of a hard lock, by trying to ensure the call | ||
1138 | * happens within the first 100 lines of the top field. | ||
1139 | * Make 4 attempts to sync to the decoder before giving up. | ||
1140 | */ | ||
1141 | for (f = 0; f < 4; f++) { | ||
1142 | prepare_to_wait(&itv->vsync_waitq, &wait, | ||
1143 | TASK_UNINTERRUPTIBLE); | ||
1144 | if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) | ||
1145 | break; | ||
1146 | schedule_timeout(msecs_to_jiffies(25)); | ||
1147 | } | ||
1148 | finish_wait(&itv->vsync_waitq, &wait); | ||
1149 | |||
1150 | if (f == 4) | ||
1151 | IVTV_WARN("Mode change failed to sync to decoder\n"); | ||
1152 | |||
1131 | ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); | 1153 | ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); |
1132 | itv->main_rect.left = itv->main_rect.top = 0; | 1154 | itv->main_rect.left = itv->main_rect.top = 0; |
1133 | itv->main_rect.width = 720; | 1155 | itv->main_rect.width = 720; |
@@ -1431,6 +1453,18 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on) | |||
1431 | return 0; | 1453 | return 0; |
1432 | } | 1454 | } |
1433 | 1455 | ||
1456 | static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) | ||
1457 | { | ||
1458 | switch (sub->type) { | ||
1459 | case V4L2_EVENT_VSYNC: | ||
1460 | case V4L2_EVENT_EOS: | ||
1461 | break; | ||
1462 | default: | ||
1463 | return -EINVAL; | ||
1464 | } | ||
1465 | return v4l2_event_subscribe(fh, sub); | ||
1466 | } | ||
1467 | |||
1434 | static int ivtv_log_status(struct file *file, void *fh) | 1468 | static int ivtv_log_status(struct file *file, void *fh) |
1435 | { | 1469 | { |
1436 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; | 1470 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; |
@@ -1539,10 +1573,11 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1539 | 1573 | ||
1540 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | 1574 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) |
1541 | { | 1575 | { |
1542 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | 1576 | struct ivtv_open_id *id = fh2id(filp->private_data); |
1543 | struct ivtv *itv = id->itv; | 1577 | struct ivtv *itv = id->itv; |
1544 | int nonblocking = filp->f_flags & O_NONBLOCK; | 1578 | int nonblocking = filp->f_flags & O_NONBLOCK; |
1545 | struct ivtv_stream *s = &itv->streams[id->type]; | 1579 | struct ivtv_stream *s = &itv->streams[id->type]; |
1580 | unsigned long iarg = (unsigned long)arg; | ||
1546 | 1581 | ||
1547 | switch (cmd) { | 1582 | switch (cmd) { |
1548 | case IVTV_IOC_DMA_FRAME: { | 1583 | case IVTV_IOC_DMA_FRAME: { |
@@ -1724,6 +1759,33 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1724 | break; | 1759 | break; |
1725 | } | 1760 | } |
1726 | 1761 | ||
1762 | case VIDEO_SELECT_SOURCE: | ||
1763 | IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); | ||
1764 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1765 | return -EINVAL; | ||
1766 | return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX); | ||
1767 | |||
1768 | case AUDIO_SET_MUTE: | ||
1769 | IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); | ||
1770 | itv->speed_mute_audio = iarg; | ||
1771 | return 0; | ||
1772 | |||
1773 | case AUDIO_CHANNEL_SELECT: | ||
1774 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); | ||
1775 | if (iarg > AUDIO_STEREO_SWAPPED) | ||
1776 | return -EINVAL; | ||
1777 | itv->audio_stereo_mode = iarg; | ||
1778 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1779 | return 0; | ||
1780 | |||
1781 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1782 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | ||
1783 | if (iarg > AUDIO_STEREO_SWAPPED) | ||
1784 | return -EINVAL; | ||
1785 | itv->audio_bilingual_mode = iarg; | ||
1786 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1787 | return 0; | ||
1788 | |||
1727 | default: | 1789 | default: |
1728 | return -EINVAL; | 1790 | return -EINVAL; |
1729 | } | 1791 | } |
@@ -1755,6 +1817,10 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) | |||
1755 | case VIDEO_CONTINUE: | 1817 | case VIDEO_CONTINUE: |
1756 | case VIDEO_COMMAND: | 1818 | case VIDEO_COMMAND: |
1757 | case VIDEO_TRY_COMMAND: | 1819 | case VIDEO_TRY_COMMAND: |
1820 | case VIDEO_SELECT_SOURCE: | ||
1821 | case AUDIO_SET_MUTE: | ||
1822 | case AUDIO_CHANNEL_SELECT: | ||
1823 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1758 | return ivtv_decoder_ioctls(file, cmd, (void *)arg); | 1824 | return ivtv_decoder_ioctls(file, cmd, (void *)arg); |
1759 | 1825 | ||
1760 | default: | 1826 | default: |
@@ -1767,42 +1833,9 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1767 | unsigned int cmd, unsigned long arg) | 1833 | unsigned int cmd, unsigned long arg) |
1768 | { | 1834 | { |
1769 | struct video_device *vfd = video_devdata(filp); | 1835 | struct video_device *vfd = video_devdata(filp); |
1770 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | 1836 | struct ivtv_open_id *id = fh2id(filp->private_data); |
1771 | long ret; | 1837 | long ret; |
1772 | 1838 | ||
1773 | /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */ | ||
1774 | switch (cmd) { | ||
1775 | case VIDEO_SELECT_SOURCE: | ||
1776 | IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); | ||
1777 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1778 | return -EINVAL; | ||
1779 | return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX); | ||
1780 | |||
1781 | case AUDIO_SET_MUTE: | ||
1782 | IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); | ||
1783 | itv->speed_mute_audio = arg; | ||
1784 | return 0; | ||
1785 | |||
1786 | case AUDIO_CHANNEL_SELECT: | ||
1787 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); | ||
1788 | if (arg > AUDIO_STEREO_SWAPPED) | ||
1789 | return -EINVAL; | ||
1790 | itv->audio_stereo_mode = arg; | ||
1791 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1792 | return 0; | ||
1793 | |||
1794 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1795 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | ||
1796 | if (arg > AUDIO_STEREO_SWAPPED) | ||
1797 | return -EINVAL; | ||
1798 | itv->audio_bilingual_mode = arg; | ||
1799 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1800 | return 0; | ||
1801 | |||
1802 | default: | ||
1803 | break; | ||
1804 | } | ||
1805 | |||
1806 | /* check priority */ | 1839 | /* check priority */ |
1807 | switch (cmd) { | 1840 | switch (cmd) { |
1808 | case VIDIOC_S_CTRL: | 1841 | case VIDIOC_S_CTRL: |
@@ -1817,8 +1850,9 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1817 | case VIDIOC_S_AUDOUT: | 1850 | case VIDIOC_S_AUDOUT: |
1818 | case VIDIOC_S_EXT_CTRLS: | 1851 | case VIDIOC_S_EXT_CTRLS: |
1819 | case VIDIOC_S_FBUF: | 1852 | case VIDIOC_S_FBUF: |
1853 | case VIDIOC_S_PRIORITY: | ||
1820 | case VIDIOC_OVERLAY: | 1854 | case VIDIOC_OVERLAY: |
1821 | ret = v4l2_prio_check(&itv->prio, &id->prio); | 1855 | ret = v4l2_prio_check(&itv->prio, id->prio); |
1822 | if (ret) | 1856 | if (ret) |
1823 | return ret; | 1857 | return ret; |
1824 | } | 1858 | } |
@@ -1832,10 +1866,13 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1832 | 1866 | ||
1833 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 1867 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1834 | { | 1868 | { |
1835 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | 1869 | struct ivtv_open_id *id = fh2id(filp->private_data); |
1836 | struct ivtv *itv = id->itv; | 1870 | struct ivtv *itv = id->itv; |
1837 | long res; | 1871 | long res; |
1838 | 1872 | ||
1873 | /* DQEVENT can block, so this should not run with the serialize lock */ | ||
1874 | if (cmd == VIDIOC_DQEVENT) | ||
1875 | return ivtv_serialized_ioctl(itv, filp, cmd, arg); | ||
1839 | mutex_lock(&itv->serialize_lock); | 1876 | mutex_lock(&itv->serialize_lock); |
1840 | res = ivtv_serialized_ioctl(itv, filp, cmd, arg); | 1877 | res = ivtv_serialized_ioctl(itv, filp, cmd, arg); |
1841 | mutex_unlock(&itv->serialize_lock); | 1878 | mutex_unlock(&itv->serialize_lock); |
@@ -1906,6 +1943,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { | |||
1906 | .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls, | 1943 | .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls, |
1907 | .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls, | 1944 | .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls, |
1908 | .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls, | 1945 | .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls, |
1946 | .vidioc_subscribe_event = ivtv_subscribe_event, | ||
1947 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
1909 | }; | 1948 | }; |
1910 | 1949 | ||
1911 | void ivtv_set_funcs(struct video_device *vdev) | 1950 | void ivtv_set_funcs(struct video_device *vdev) |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 12d36ca91d53..fea1ec33b0df 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "ivtv-mailbox.h" | 25 | #include "ivtv-mailbox.h" |
26 | #include "ivtv-vbi.h" | 26 | #include "ivtv-vbi.h" |
27 | #include "ivtv-yuv.h" | 27 | #include "ivtv-yuv.h" |
28 | #include <media/v4l2-event.h> | ||
28 | 29 | ||
29 | #define DMA_MAGIC_COOKIE 0x000001fe | 30 | #define DMA_MAGIC_COOKIE 0x000001fe |
30 | 31 | ||
@@ -752,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
752 | * to determine the line being displayed and ensure we handle | 753 | * to determine the line being displayed and ensure we handle |
753 | * one vsync per frame. | 754 | * one vsync per frame. |
754 | */ | 755 | */ |
755 | unsigned int frame = read_reg(0x28c0) & 1; | 756 | unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1; |
756 | struct yuv_playback_info *yi = &itv->yuv_info; | 757 | struct yuv_playback_info *yi = &itv->yuv_info; |
757 | int last_dma_frame = atomic_read(&yi->next_dma_frame); | 758 | int last_dma_frame = atomic_read(&yi->next_dma_frame); |
758 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; | 759 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; |
@@ -778,6 +779,14 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
778 | } | 779 | } |
779 | } | 780 | } |
780 | if (frame != (itv->last_vsync_field & 1)) { | 781 | if (frame != (itv->last_vsync_field & 1)) { |
782 | static const struct v4l2_event evtop = { | ||
783 | .type = V4L2_EVENT_VSYNC, | ||
784 | .u.vsync.field = V4L2_FIELD_TOP, | ||
785 | }; | ||
786 | static const struct v4l2_event evbottom = { | ||
787 | .type = V4L2_EVENT_VSYNC, | ||
788 | .u.vsync.field = V4L2_FIELD_BOTTOM, | ||
789 | }; | ||
781 | struct ivtv_stream *s = ivtv_get_output_stream(itv); | 790 | struct ivtv_stream *s = ivtv_get_output_stream(itv); |
782 | 791 | ||
783 | itv->last_vsync_field += 1; | 792 | itv->last_vsync_field += 1; |
@@ -791,10 +800,12 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
791 | if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) { | 800 | if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) { |
792 | set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags); | 801 | set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags); |
793 | wake_up(&itv->event_waitq); | 802 | wake_up(&itv->event_waitq); |
803 | if (s) | ||
804 | wake_up(&s->waitq); | ||
794 | } | 805 | } |
806 | if (s && s->vdev) | ||
807 | v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom); | ||
795 | wake_up(&itv->vsync_waitq); | 808 | wake_up(&itv->vsync_waitq); |
796 | if (s) | ||
797 | wake_up(&s->waitq); | ||
798 | 809 | ||
799 | /* Send VBI to saa7127 */ | 810 | /* Send VBI to saa7127 */ |
800 | if (frame && (itv->output_mode == OUT_PASSTHROUGH || | 811 | if (frame && (itv->output_mode == OUT_PASSTHROUGH || |
@@ -852,9 +863,11 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
852 | */ | 863 | */ |
853 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { | 864 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { |
854 | /* vsync is enabled, see if we're in a new field */ | 865 | /* vsync is enabled, see if we're in a new field */ |
855 | if ((itv->last_vsync_field & 1) != (read_reg(0x28c0) & 1)) { | 866 | if ((itv->last_vsync_field & 1) != |
867 | (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) { | ||
856 | /* New field, looks like we missed it */ | 868 | /* New field, looks like we missed it */ |
857 | IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16); | 869 | IVTV_DEBUG_YUV("VSync interrupt missed %d\n", |
870 | read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16); | ||
858 | vsync_force = 1; | 871 | vsync_force = 1; |
859 | } | 872 | } |
860 | } | 873 | } |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 1f9387f6ca24..de4288cc1889 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "ivtv-yuv.h" | 42 | #include "ivtv-yuv.h" |
43 | #include "ivtv-cards.h" | 43 | #include "ivtv-cards.h" |
44 | #include "ivtv-streams.h" | 44 | #include "ivtv-streams.h" |
45 | #include <media/v4l2-event.h> | ||
45 | 46 | ||
46 | static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { | 47 | static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { |
47 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
@@ -343,7 +344,10 @@ static void ivtv_vbi_setup(struct ivtv *itv) | |||
343 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); | 344 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); |
344 | 345 | ||
345 | /* setup VBI registers */ | 346 | /* setup VBI registers */ |
346 | v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in); | 347 | if (raw) |
348 | v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi); | ||
349 | else | ||
350 | v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced); | ||
347 | 351 | ||
348 | /* determine number of lines and total number of VBI bytes. | 352 | /* determine number of lines and total number of VBI bytes. |
349 | A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 | 353 | A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 |
@@ -581,10 +585,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
581 | v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); | 585 | v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); |
582 | /* Avoid unpredictable PCI bus hang - disable video clocks */ | 586 | /* Avoid unpredictable PCI bus hang - disable video clocks */ |
583 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); | 587 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); |
584 | ivtv_msleep_timeout(150, 1); | 588 | ivtv_msleep_timeout(300, 1); |
585 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | 589 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); |
586 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); | 590 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); |
587 | ivtv_msleep_timeout(150, 1); | ||
588 | } | 591 | } |
589 | 592 | ||
590 | /* begin_capture */ | 593 | /* begin_capture */ |
@@ -830,6 +833,10 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
830 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | 833 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); |
831 | } | 834 | } |
832 | 835 | ||
836 | /* Raw-passthrough is implied on start. Make sure it's stopped so | ||
837 | the encoder will re-initialize when next started */ | ||
838 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7); | ||
839 | |||
833 | wake_up(&s->waitq); | 840 | wake_up(&s->waitq); |
834 | 841 | ||
835 | return 0; | 842 | return 0; |
@@ -837,6 +844,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
837 | 844 | ||
838 | int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | 845 | int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) |
839 | { | 846 | { |
847 | static const struct v4l2_event ev = { | ||
848 | .type = V4L2_EVENT_EOS, | ||
849 | }; | ||
840 | struct ivtv *itv = s->itv; | 850 | struct ivtv *itv = s->itv; |
841 | 851 | ||
842 | if (s->vdev == NULL) | 852 | if (s->vdev == NULL) |
@@ -888,6 +898,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | |||
888 | 898 | ||
889 | set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags); | 899 | set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags); |
890 | wake_up(&itv->event_waitq); | 900 | wake_up(&itv->event_waitq); |
901 | v4l2_event_queue(s->vdev, &ev); | ||
891 | 902 | ||
892 | /* wake up wait queues */ | 903 | /* wake up wait queues */ |
893 | wake_up(&s->waitq); | 904 | wake_up(&s->waitq); |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index f420d31b937d..e1c347e5ebd8 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -38,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled) | |||
38 | data.data[9] = itv->vbi.vps_payload.data[2]; | 38 | data.data[9] = itv->vbi.vps_payload.data[2]; |
39 | data.data[10] = itv->vbi.vps_payload.data[3]; | 39 | data.data[10] = itv->vbi.vps_payload.data[3]; |
40 | data.data[11] = itv->vbi.vps_payload.data[4]; | 40 | data.data[11] = itv->vbi.vps_payload.data[4]; |
41 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); | 41 | ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); |
42 | } | 42 | } |
43 | 43 | ||
44 | static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) | 44 | static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) |
@@ -52,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) | |||
52 | data.line = (mode & 1) ? 21 : 0; | 52 | data.line = (mode & 1) ? 21 : 0; |
53 | data.data[0] = cc->odd[0]; | 53 | data.data[0] = cc->odd[0]; |
54 | data.data[1] = cc->odd[1]; | 54 | data.data[1] = cc->odd[1]; |
55 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); | 55 | ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); |
56 | data.field = 1; | 56 | data.field = 1; |
57 | data.line = (mode & 2) ? 21 : 0; | 57 | data.line = (mode & 2) ? 21 : 0; |
58 | data.data[0] = cc->even[0]; | 58 | data.data[0] = cc->even[0]; |
59 | data.data[1] = cc->even[1]; | 59 | data.data[1] = cc->even[1]; |
60 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); | 60 | ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) | 63 | static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) |
@@ -80,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) | |||
80 | data.line = enabled ? 23 : 0; | 80 | data.line = enabled ? 23 : 0; |
81 | data.data[0] = mode & 0xff; | 81 | data.data[0] = mode & 0xff; |
82 | data.data[1] = (mode >> 8) & 0xff; | 82 | data.data[1] = (mode >> 8) & 0xff; |
83 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); | 83 | ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); |
84 | } | 84 | } |
85 | 85 | ||
86 | static int odd_parity(u8 c) | 86 | static int odd_parity(u8 c) |
@@ -134,7 +134,7 @@ void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | } | 136 | } |
137 | if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) { | 137 | if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { |
138 | vi->cc_payload[vi->cc_payload_idx++] = cc; | 138 | vi->cc_payload[vi->cc_payload_idx++] = cc; |
139 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | 139 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); |
140 | } | 140 | } |
@@ -316,7 +316,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 | |||
316 | continue; | 316 | continue; |
317 | } | 317 | } |
318 | vbi.p = p + 4; | 318 | vbi.p = p + 4; |
319 | v4l2_subdev_call(itv->sd_video, video, decode_vbi_line, &vbi); | 319 | v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi); |
320 | if (vbi.type && !(lines & (1 << vbi.line))) { | 320 | if (vbi.type && !(lines & (1 << vbi.line))) { |
321 | lines |= 1 << vbi.line; | 321 | lines |= 1 << vbi.line; |
322 | itv->vbi.sliced_data[line].id = vbi.type; | 322 | itv->vbi.sliced_data[line].id = vbi.type; |
@@ -440,7 +440,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) | |||
440 | data.id = V4L2_SLICED_WSS_625; | 440 | data.id = V4L2_SLICED_WSS_625; |
441 | data.field = 0; | 441 | data.field = 0; |
442 | 442 | ||
443 | if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { | 443 | if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { |
444 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); | 444 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); |
445 | vi->wss_missing_cnt = 0; | 445 | vi->wss_missing_cnt = 0; |
446 | } else if (vi->wss_missing_cnt == 4) { | 446 | } else if (vi->wss_missing_cnt == 4) { |
@@ -454,13 +454,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv) | |||
454 | 454 | ||
455 | data.id = V4L2_SLICED_CAPTION_525; | 455 | data.id = V4L2_SLICED_CAPTION_525; |
456 | data.field = 0; | 456 | data.field = 0; |
457 | if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { | 457 | if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { |
458 | mode |= 1; | 458 | mode |= 1; |
459 | cc.odd[0] = data.data[0]; | 459 | cc.odd[0] = data.data[0]; |
460 | cc.odd[1] = data.data[1]; | 460 | cc.odd[1] = data.data[1]; |
461 | } | 461 | } |
462 | data.field = 1; | 462 | data.field = 1; |
463 | if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { | 463 | if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { |
464 | mode |= 2; | 464 | mode |= 2; |
465 | cc.even[0] = data.data[0]; | 465 | cc.even[0] = data.data[0]; |
466 | cc.even[1] = data.data[1]; | 466 | cc.even[1] = data.data[1]; |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index de2ff1c6ac34..49e1a283ed36 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -460,7 +460,7 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar | |||
460 | 460 | ||
461 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | | 461 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | |
462 | FB_VBLANK_HAVE_VSYNC; | 462 | FB_VBLANK_HAVE_VSYNC; |
463 | trace = read_reg(0x028c0) >> 16; | 463 | trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; |
464 | if (itv->is_50hz && trace > 312) | 464 | if (itv->is_50hz && trace > 312) |
465 | trace -= 312; | 465 | trace -= 312; |
466 | else if (itv->is_60hz && trace > 262) | 466 | else if (itv->is_60hz && trace > 262) |
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c new file mode 100644 index 000000000000..554eaf140128 --- /dev/null +++ b/drivers/media/video/mem2mem_testdev.c | |||
@@ -0,0 +1,1052 @@ | |||
1 | /* | ||
2 | * A virtual v4l2-mem2mem example device. | ||
3 | * | ||
4 | * This is a virtual device driver for testing mem-to-mem videobuf framework. | ||
5 | * It simulates a device that uses memory buffers for both source and | ||
6 | * destination, processes the data and issues an "irq" (simulated by a timer). | ||
7 | * The device is capable of multi-instance, multi-buffer-per-transaction | ||
8 | * operation (via the mem2mem framework). | ||
9 | * | ||
10 | * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. | ||
11 | * Pawel Osciak, <p.osciak@samsung.com> | ||
12 | * Marek Szyprowski, <m.szyprowski@samsung.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the | ||
17 | * License, or (at your option) any later version | ||
18 | */ | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/version.h> | ||
23 | #include <linux/timer.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <linux/platform_device.h> | ||
28 | #include <media/v4l2-mem2mem.h> | ||
29 | #include <media/v4l2-device.h> | ||
30 | #include <media/v4l2-ioctl.h> | ||
31 | #include <media/videobuf-vmalloc.h> | ||
32 | |||
33 | #define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev" | ||
34 | |||
35 | MODULE_DESCRIPTION("Virtual device for mem2mem framework testing"); | ||
36 | MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | |||
40 | #define MIN_W 32 | ||
41 | #define MIN_H 32 | ||
42 | #define MAX_W 640 | ||
43 | #define MAX_H 480 | ||
44 | #define DIM_ALIGN_MASK 0x08 /* 8-alignment for dimensions */ | ||
45 | |||
46 | /* Flags that indicate a format can be used for capture/output */ | ||
47 | #define MEM2MEM_CAPTURE (1 << 0) | ||
48 | #define MEM2MEM_OUTPUT (1 << 1) | ||
49 | |||
50 | #define MEM2MEM_NAME "m2m-testdev" | ||
51 | |||
52 | /* Per queue */ | ||
53 | #define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME | ||
54 | /* In bytes, per queue */ | ||
55 | #define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024) | ||
56 | |||
57 | /* Default transaction time in msec */ | ||
58 | #define MEM2MEM_DEF_TRANSTIME 1000 | ||
59 | /* Default number of buffers per transaction */ | ||
60 | #define MEM2MEM_DEF_TRANSLEN 1 | ||
61 | #define MEM2MEM_COLOR_STEP (0xff >> 4) | ||
62 | #define MEM2MEM_NUM_TILES 8 | ||
63 | |||
64 | #define dprintk(dev, fmt, arg...) \ | ||
65 | v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) | ||
66 | |||
67 | |||
68 | void m2mtest_dev_release(struct device *dev) | ||
69 | {} | ||
70 | |||
71 | static struct platform_device m2mtest_pdev = { | ||
72 | .name = MEM2MEM_NAME, | ||
73 | .dev.release = m2mtest_dev_release, | ||
74 | }; | ||
75 | |||
76 | struct m2mtest_fmt { | ||
77 | char *name; | ||
78 | u32 fourcc; | ||
79 | int depth; | ||
80 | /* Types the format can be used for */ | ||
81 | u32 types; | ||
82 | }; | ||
83 | |||
84 | static struct m2mtest_fmt formats[] = { | ||
85 | { | ||
86 | .name = "RGB565 (BE)", | ||
87 | .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ | ||
88 | .depth = 16, | ||
89 | /* Both capture and output format */ | ||
90 | .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, | ||
91 | }, | ||
92 | { | ||
93 | .name = "4:2:2, packed, YUYV", | ||
94 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
95 | .depth = 16, | ||
96 | /* Output-only format */ | ||
97 | .types = MEM2MEM_OUTPUT, | ||
98 | }, | ||
99 | }; | ||
100 | |||
101 | /* Per-queue, driver-specific private data */ | ||
102 | struct m2mtest_q_data { | ||
103 | unsigned int width; | ||
104 | unsigned int height; | ||
105 | unsigned int sizeimage; | ||
106 | struct m2mtest_fmt *fmt; | ||
107 | }; | ||
108 | |||
109 | enum { | ||
110 | V4L2_M2M_SRC = 0, | ||
111 | V4L2_M2M_DST = 1, | ||
112 | }; | ||
113 | |||
114 | /* Source and destination queue data */ | ||
115 | static struct m2mtest_q_data q_data[2]; | ||
116 | |||
117 | static struct m2mtest_q_data *get_q_data(enum v4l2_buf_type type) | ||
118 | { | ||
119 | switch (type) { | ||
120 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
121 | return &q_data[V4L2_M2M_SRC]; | ||
122 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
123 | return &q_data[V4L2_M2M_DST]; | ||
124 | default: | ||
125 | BUG(); | ||
126 | } | ||
127 | return NULL; | ||
128 | } | ||
129 | |||
130 | #define V4L2_CID_TRANS_TIME_MSEC V4L2_CID_PRIVATE_BASE | ||
131 | #define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_PRIVATE_BASE + 1) | ||
132 | |||
133 | static struct v4l2_queryctrl m2mtest_ctrls[] = { | ||
134 | { | ||
135 | .id = V4L2_CID_TRANS_TIME_MSEC, | ||
136 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
137 | .name = "Transaction time (msec)", | ||
138 | .minimum = 1, | ||
139 | .maximum = 10000, | ||
140 | .step = 100, | ||
141 | .default_value = 1000, | ||
142 | .flags = 0, | ||
143 | }, { | ||
144 | .id = V4L2_CID_TRANS_NUM_BUFS, | ||
145 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
146 | .name = "Buffers per transaction", | ||
147 | .minimum = 1, | ||
148 | .maximum = MEM2MEM_DEF_NUM_BUFS, | ||
149 | .step = 1, | ||
150 | .default_value = 1, | ||
151 | .flags = 0, | ||
152 | }, | ||
153 | }; | ||
154 | |||
155 | #define NUM_FORMATS ARRAY_SIZE(formats) | ||
156 | |||
157 | static struct m2mtest_fmt *find_format(struct v4l2_format *f) | ||
158 | { | ||
159 | struct m2mtest_fmt *fmt; | ||
160 | unsigned int k; | ||
161 | |||
162 | for (k = 0; k < NUM_FORMATS; k++) { | ||
163 | fmt = &formats[k]; | ||
164 | if (fmt->fourcc == f->fmt.pix.pixelformat) | ||
165 | break; | ||
166 | } | ||
167 | |||
168 | if (k == NUM_FORMATS) | ||
169 | return NULL; | ||
170 | |||
171 | return &formats[k]; | ||
172 | } | ||
173 | |||
174 | struct m2mtest_dev { | ||
175 | struct v4l2_device v4l2_dev; | ||
176 | struct video_device *vfd; | ||
177 | |||
178 | atomic_t num_inst; | ||
179 | struct mutex dev_mutex; | ||
180 | spinlock_t irqlock; | ||
181 | |||
182 | struct timer_list timer; | ||
183 | |||
184 | struct v4l2_m2m_dev *m2m_dev; | ||
185 | }; | ||
186 | |||
187 | struct m2mtest_ctx { | ||
188 | struct m2mtest_dev *dev; | ||
189 | |||
190 | /* Processed buffers in this transaction */ | ||
191 | u8 num_processed; | ||
192 | |||
193 | /* Transaction length (i.e. how many buffers per transaction) */ | ||
194 | u32 translen; | ||
195 | /* Transaction time (i.e. simulated processing time) in milliseconds */ | ||
196 | u32 transtime; | ||
197 | |||
198 | /* Abort requested by m2m */ | ||
199 | int aborting; | ||
200 | |||
201 | struct v4l2_m2m_ctx *m2m_ctx; | ||
202 | }; | ||
203 | |||
204 | struct m2mtest_buffer { | ||
205 | /* vb must be first! */ | ||
206 | struct videobuf_buffer vb; | ||
207 | }; | ||
208 | |||
209 | static struct v4l2_queryctrl *get_ctrl(int id) | ||
210 | { | ||
211 | int i; | ||
212 | |||
213 | for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) { | ||
214 | if (id == m2mtest_ctrls[i].id) | ||
215 | return &m2mtest_ctrls[i]; | ||
216 | } | ||
217 | |||
218 | return NULL; | ||
219 | } | ||
220 | |||
221 | static int device_process(struct m2mtest_ctx *ctx, | ||
222 | struct m2mtest_buffer *in_buf, | ||
223 | struct m2mtest_buffer *out_buf) | ||
224 | { | ||
225 | struct m2mtest_dev *dev = ctx->dev; | ||
226 | u8 *p_in, *p_out; | ||
227 | int x, y, t, w; | ||
228 | int tile_w, bytes_left; | ||
229 | struct videobuf_queue *src_q; | ||
230 | struct videobuf_queue *dst_q; | ||
231 | |||
232 | src_q = v4l2_m2m_get_src_vq(ctx->m2m_ctx); | ||
233 | dst_q = v4l2_m2m_get_dst_vq(ctx->m2m_ctx); | ||
234 | p_in = videobuf_queue_to_vaddr(src_q, &in_buf->vb); | ||
235 | p_out = videobuf_queue_to_vaddr(dst_q, &out_buf->vb); | ||
236 | if (!p_in || !p_out) { | ||
237 | v4l2_err(&dev->v4l2_dev, | ||
238 | "Acquiring kernel pointers to buffers failed\n"); | ||
239 | return -EFAULT; | ||
240 | } | ||
241 | |||
242 | if (in_buf->vb.size < out_buf->vb.size) { | ||
243 | v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | tile_w = (in_buf->vb.width * (q_data[V4L2_M2M_DST].fmt->depth >> 3)) | ||
248 | / MEM2MEM_NUM_TILES; | ||
249 | bytes_left = in_buf->vb.bytesperline - tile_w * MEM2MEM_NUM_TILES; | ||
250 | w = 0; | ||
251 | |||
252 | for (y = 0; y < in_buf->vb.height; ++y) { | ||
253 | for (t = 0; t < MEM2MEM_NUM_TILES; ++t) { | ||
254 | if (w & 0x1) { | ||
255 | for (x = 0; x < tile_w; ++x) | ||
256 | *p_out++ = *p_in++ + MEM2MEM_COLOR_STEP; | ||
257 | } else { | ||
258 | for (x = 0; x < tile_w; ++x) | ||
259 | *p_out++ = *p_in++ - MEM2MEM_COLOR_STEP; | ||
260 | } | ||
261 | ++w; | ||
262 | } | ||
263 | p_in += bytes_left; | ||
264 | p_out += bytes_left; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static void schedule_irq(struct m2mtest_dev *dev, int msec_timeout) | ||
271 | { | ||
272 | dprintk(dev, "Scheduling a simulated irq\n"); | ||
273 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout)); | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * mem2mem callbacks | ||
278 | */ | ||
279 | |||
280 | /** | ||
281 | * job_ready() - check whether an instance is ready to be scheduled to run | ||
282 | */ | ||
283 | static int job_ready(void *priv) | ||
284 | { | ||
285 | struct m2mtest_ctx *ctx = priv; | ||
286 | |||
287 | if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen | ||
288 | || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) { | ||
289 | dprintk(ctx->dev, "Not enough buffers available\n"); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | return 1; | ||
294 | } | ||
295 | |||
296 | static void job_abort(void *priv) | ||
297 | { | ||
298 | struct m2mtest_ctx *ctx = priv; | ||
299 | |||
300 | /* Will cancel the transaction in the next interrupt handler */ | ||
301 | ctx->aborting = 1; | ||
302 | } | ||
303 | |||
304 | /* device_run() - prepares and starts the device | ||
305 | * | ||
306 | * This simulates all the immediate preparations required before starting | ||
307 | * a device. This will be called by the framework when it decides to schedule | ||
308 | * a particular instance. | ||
309 | */ | ||
310 | static void device_run(void *priv) | ||
311 | { | ||
312 | struct m2mtest_ctx *ctx = priv; | ||
313 | struct m2mtest_dev *dev = ctx->dev; | ||
314 | struct m2mtest_buffer *src_buf, *dst_buf; | ||
315 | |||
316 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
317 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
318 | |||
319 | device_process(ctx, src_buf, dst_buf); | ||
320 | |||
321 | /* Run a timer, which simulates a hardware irq */ | ||
322 | schedule_irq(dev, ctx->transtime); | ||
323 | } | ||
324 | |||
325 | |||
326 | static void device_isr(unsigned long priv) | ||
327 | { | ||
328 | struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv; | ||
329 | struct m2mtest_ctx *curr_ctx; | ||
330 | struct m2mtest_buffer *src_buf, *dst_buf; | ||
331 | unsigned long flags; | ||
332 | |||
333 | curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev); | ||
334 | |||
335 | if (NULL == curr_ctx) { | ||
336 | printk(KERN_ERR | ||
337 | "Instance released before the end of transaction\n"); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); | ||
342 | dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); | ||
343 | curr_ctx->num_processed++; | ||
344 | |||
345 | if (curr_ctx->num_processed == curr_ctx->translen | ||
346 | || curr_ctx->aborting) { | ||
347 | dprintk(curr_ctx->dev, "Finishing transaction\n"); | ||
348 | curr_ctx->num_processed = 0; | ||
349 | spin_lock_irqsave(&m2mtest_dev->irqlock, flags); | ||
350 | src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; | ||
351 | wake_up(&src_buf->vb.done); | ||
352 | wake_up(&dst_buf->vb.done); | ||
353 | spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags); | ||
354 | v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx); | ||
355 | } else { | ||
356 | spin_lock_irqsave(&m2mtest_dev->irqlock, flags); | ||
357 | src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; | ||
358 | wake_up(&src_buf->vb.done); | ||
359 | wake_up(&dst_buf->vb.done); | ||
360 | spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags); | ||
361 | device_run(curr_ctx); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | |||
366 | /* | ||
367 | * video ioctls | ||
368 | */ | ||
369 | static int vidioc_querycap(struct file *file, void *priv, | ||
370 | struct v4l2_capability *cap) | ||
371 | { | ||
372 | strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); | ||
373 | strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); | ||
374 | cap->bus_info[0] = 0; | ||
375 | cap->version = KERNEL_VERSION(0, 1, 0); | ||
376 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ||
377 | | V4L2_CAP_STREAMING; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) | ||
383 | { | ||
384 | int i, num; | ||
385 | struct m2mtest_fmt *fmt; | ||
386 | |||
387 | num = 0; | ||
388 | |||
389 | for (i = 0; i < NUM_FORMATS; ++i) { | ||
390 | if (formats[i].types & type) { | ||
391 | /* index-th format of type type found ? */ | ||
392 | if (num == f->index) | ||
393 | break; | ||
394 | /* Correct type but haven't reached our index yet, | ||
395 | * just increment per-type index */ | ||
396 | ++num; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | if (i < NUM_FORMATS) { | ||
401 | /* Format found */ | ||
402 | fmt = &formats[i]; | ||
403 | strncpy(f->description, fmt->name, sizeof(f->description) - 1); | ||
404 | f->pixelformat = fmt->fourcc; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | /* Format not found */ | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | |||
412 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
413 | struct v4l2_fmtdesc *f) | ||
414 | { | ||
415 | return enum_fmt(f, MEM2MEM_CAPTURE); | ||
416 | } | ||
417 | |||
418 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, | ||
419 | struct v4l2_fmtdesc *f) | ||
420 | { | ||
421 | return enum_fmt(f, MEM2MEM_OUTPUT); | ||
422 | } | ||
423 | |||
424 | static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) | ||
425 | { | ||
426 | struct videobuf_queue *vq; | ||
427 | struct m2mtest_q_data *q_data; | ||
428 | |||
429 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
430 | if (!vq) | ||
431 | return -EINVAL; | ||
432 | |||
433 | q_data = get_q_data(f->type); | ||
434 | |||
435 | f->fmt.pix.width = q_data->width; | ||
436 | f->fmt.pix.height = q_data->height; | ||
437 | f->fmt.pix.field = vq->field; | ||
438 | f->fmt.pix.pixelformat = q_data->fmt->fourcc; | ||
439 | f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3; | ||
440 | f->fmt.pix.sizeimage = q_data->sizeimage; | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static int vidioc_g_fmt_vid_out(struct file *file, void *priv, | ||
446 | struct v4l2_format *f) | ||
447 | { | ||
448 | return vidioc_g_fmt(priv, f); | ||
449 | } | ||
450 | |||
451 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
452 | struct v4l2_format *f) | ||
453 | { | ||
454 | return vidioc_g_fmt(priv, f); | ||
455 | } | ||
456 | |||
457 | static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) | ||
458 | { | ||
459 | enum v4l2_field field; | ||
460 | |||
461 | field = f->fmt.pix.field; | ||
462 | |||
463 | if (field == V4L2_FIELD_ANY) | ||
464 | field = V4L2_FIELD_NONE; | ||
465 | else if (V4L2_FIELD_NONE != field) | ||
466 | return -EINVAL; | ||
467 | |||
468 | /* V4L2 specification suggests the driver corrects the format struct | ||
469 | * if any of the dimensions is unsupported */ | ||
470 | f->fmt.pix.field = field; | ||
471 | |||
472 | if (f->fmt.pix.height < MIN_H) | ||
473 | f->fmt.pix.height = MIN_H; | ||
474 | else if (f->fmt.pix.height > MAX_H) | ||
475 | f->fmt.pix.height = MAX_H; | ||
476 | |||
477 | if (f->fmt.pix.width < MIN_W) | ||
478 | f->fmt.pix.width = MIN_W; | ||
479 | else if (f->fmt.pix.width > MAX_W) | ||
480 | f->fmt.pix.width = MAX_W; | ||
481 | |||
482 | f->fmt.pix.width &= ~DIM_ALIGN_MASK; | ||
483 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
484 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
490 | struct v4l2_format *f) | ||
491 | { | ||
492 | struct m2mtest_fmt *fmt; | ||
493 | struct m2mtest_ctx *ctx = priv; | ||
494 | |||
495 | fmt = find_format(f); | ||
496 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { | ||
497 | v4l2_err(&ctx->dev->v4l2_dev, | ||
498 | "Fourcc format (0x%08x) invalid.\n", | ||
499 | f->fmt.pix.pixelformat); | ||
500 | return -EINVAL; | ||
501 | } | ||
502 | |||
503 | return vidioc_try_fmt(f, fmt); | ||
504 | } | ||
505 | |||
506 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, | ||
507 | struct v4l2_format *f) | ||
508 | { | ||
509 | struct m2mtest_fmt *fmt; | ||
510 | struct m2mtest_ctx *ctx = priv; | ||
511 | |||
512 | fmt = find_format(f); | ||
513 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { | ||
514 | v4l2_err(&ctx->dev->v4l2_dev, | ||
515 | "Fourcc format (0x%08x) invalid.\n", | ||
516 | f->fmt.pix.pixelformat); | ||
517 | return -EINVAL; | ||
518 | } | ||
519 | |||
520 | return vidioc_try_fmt(f, fmt); | ||
521 | } | ||
522 | |||
523 | static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) | ||
524 | { | ||
525 | struct m2mtest_q_data *q_data; | ||
526 | struct videobuf_queue *vq; | ||
527 | int ret = 0; | ||
528 | |||
529 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
530 | if (!vq) | ||
531 | return -EINVAL; | ||
532 | |||
533 | q_data = get_q_data(f->type); | ||
534 | if (!q_data) | ||
535 | return -EINVAL; | ||
536 | |||
537 | mutex_lock(&vq->vb_lock); | ||
538 | |||
539 | if (videobuf_queue_is_busy(vq)) { | ||
540 | v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); | ||
541 | ret = -EBUSY; | ||
542 | goto out; | ||
543 | } | ||
544 | |||
545 | q_data->fmt = find_format(f); | ||
546 | q_data->width = f->fmt.pix.width; | ||
547 | q_data->height = f->fmt.pix.height; | ||
548 | q_data->sizeimage = q_data->width * q_data->height | ||
549 | * q_data->fmt->depth >> 3; | ||
550 | vq->field = f->fmt.pix.field; | ||
551 | |||
552 | dprintk(ctx->dev, | ||
553 | "Setting format for type %d, wxh: %dx%d, fmt: %d\n", | ||
554 | f->type, q_data->width, q_data->height, q_data->fmt->fourcc); | ||
555 | |||
556 | out: | ||
557 | mutex_unlock(&vq->vb_lock); | ||
558 | return ret; | ||
559 | } | ||
560 | |||
561 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
562 | struct v4l2_format *f) | ||
563 | { | ||
564 | int ret; | ||
565 | |||
566 | ret = vidioc_try_fmt_vid_cap(file, priv, f); | ||
567 | if (ret) | ||
568 | return ret; | ||
569 | |||
570 | return vidioc_s_fmt(priv, f); | ||
571 | } | ||
572 | |||
573 | static int vidioc_s_fmt_vid_out(struct file *file, void *priv, | ||
574 | struct v4l2_format *f) | ||
575 | { | ||
576 | int ret; | ||
577 | |||
578 | ret = vidioc_try_fmt_vid_out(file, priv, f); | ||
579 | if (ret) | ||
580 | return ret; | ||
581 | |||
582 | return vidioc_s_fmt(priv, f); | ||
583 | } | ||
584 | |||
585 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
586 | struct v4l2_requestbuffers *reqbufs) | ||
587 | { | ||
588 | struct m2mtest_ctx *ctx = priv; | ||
589 | |||
590 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | ||
591 | } | ||
592 | |||
593 | static int vidioc_querybuf(struct file *file, void *priv, | ||
594 | struct v4l2_buffer *buf) | ||
595 | { | ||
596 | struct m2mtest_ctx *ctx = priv; | ||
597 | |||
598 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | ||
599 | } | ||
600 | |||
601 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
602 | { | ||
603 | struct m2mtest_ctx *ctx = priv; | ||
604 | |||
605 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | ||
606 | } | ||
607 | |||
608 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
609 | { | ||
610 | struct m2mtest_ctx *ctx = priv; | ||
611 | |||
612 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
613 | } | ||
614 | |||
615 | static int vidioc_streamon(struct file *file, void *priv, | ||
616 | enum v4l2_buf_type type) | ||
617 | { | ||
618 | struct m2mtest_ctx *ctx = priv; | ||
619 | |||
620 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | ||
621 | } | ||
622 | |||
623 | static int vidioc_streamoff(struct file *file, void *priv, | ||
624 | enum v4l2_buf_type type) | ||
625 | { | ||
626 | struct m2mtest_ctx *ctx = priv; | ||
627 | |||
628 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
629 | } | ||
630 | |||
631 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
632 | struct v4l2_queryctrl *qc) | ||
633 | { | ||
634 | struct v4l2_queryctrl *c; | ||
635 | |||
636 | c = get_ctrl(qc->id); | ||
637 | if (!c) | ||
638 | return -EINVAL; | ||
639 | |||
640 | *qc = *c; | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
645 | struct v4l2_control *ctrl) | ||
646 | { | ||
647 | struct m2mtest_ctx *ctx = priv; | ||
648 | |||
649 | switch (ctrl->id) { | ||
650 | case V4L2_CID_TRANS_TIME_MSEC: | ||
651 | ctrl->value = ctx->transtime; | ||
652 | break; | ||
653 | |||
654 | case V4L2_CID_TRANS_NUM_BUFS: | ||
655 | ctrl->value = ctx->translen; | ||
656 | break; | ||
657 | |||
658 | default: | ||
659 | v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); | ||
660 | return -EINVAL; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl) | ||
667 | { | ||
668 | struct v4l2_queryctrl *c; | ||
669 | |||
670 | c = get_ctrl(ctrl->id); | ||
671 | if (!c) | ||
672 | return -EINVAL; | ||
673 | |||
674 | if (ctrl->value < c->minimum || ctrl->value > c->maximum) { | ||
675 | v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n"); | ||
676 | return -ERANGE; | ||
677 | } | ||
678 | |||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
683 | struct v4l2_control *ctrl) | ||
684 | { | ||
685 | struct m2mtest_ctx *ctx = priv; | ||
686 | int ret = 0; | ||
687 | |||
688 | ret = check_ctrl_val(ctx, ctrl); | ||
689 | if (ret != 0) | ||
690 | return ret; | ||
691 | |||
692 | switch (ctrl->id) { | ||
693 | case V4L2_CID_TRANS_TIME_MSEC: | ||
694 | ctx->transtime = ctrl->value; | ||
695 | break; | ||
696 | |||
697 | case V4L2_CID_TRANS_NUM_BUFS: | ||
698 | ctx->translen = ctrl->value; | ||
699 | break; | ||
700 | |||
701 | default: | ||
702 | v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); | ||
703 | return -EINVAL; | ||
704 | } | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | |||
710 | static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { | ||
711 | .vidioc_querycap = vidioc_querycap, | ||
712 | |||
713 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
714 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
715 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
716 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
717 | |||
718 | .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, | ||
719 | .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, | ||
720 | .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, | ||
721 | .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, | ||
722 | |||
723 | .vidioc_reqbufs = vidioc_reqbufs, | ||
724 | .vidioc_querybuf = vidioc_querybuf, | ||
725 | |||
726 | .vidioc_qbuf = vidioc_qbuf, | ||
727 | .vidioc_dqbuf = vidioc_dqbuf, | ||
728 | |||
729 | .vidioc_streamon = vidioc_streamon, | ||
730 | .vidioc_streamoff = vidioc_streamoff, | ||
731 | |||
732 | .vidioc_queryctrl = vidioc_queryctrl, | ||
733 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
734 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
735 | }; | ||
736 | |||
737 | |||
738 | /* | ||
739 | * Queue operations | ||
740 | */ | ||
741 | |||
742 | static void m2mtest_buf_release(struct videobuf_queue *vq, | ||
743 | struct videobuf_buffer *vb) | ||
744 | { | ||
745 | struct m2mtest_ctx *ctx = vq->priv_data; | ||
746 | |||
747 | dprintk(ctx->dev, "type: %d, index: %d, state: %d\n", | ||
748 | vq->type, vb->i, vb->state); | ||
749 | |||
750 | videobuf_vmalloc_free(vb); | ||
751 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
752 | } | ||
753 | |||
754 | static int m2mtest_buf_setup(struct videobuf_queue *vq, unsigned int *count, | ||
755 | unsigned int *size) | ||
756 | { | ||
757 | struct m2mtest_ctx *ctx = vq->priv_data; | ||
758 | struct m2mtest_q_data *q_data; | ||
759 | |||
760 | q_data = get_q_data(vq->type); | ||
761 | |||
762 | *size = q_data->width * q_data->height * q_data->fmt->depth >> 3; | ||
763 | dprintk(ctx->dev, "size:%d, w/h %d/%d, depth: %d\n", | ||
764 | *size, q_data->width, q_data->height, q_data->fmt->depth); | ||
765 | |||
766 | if (0 == *count) | ||
767 | *count = MEM2MEM_DEF_NUM_BUFS; | ||
768 | |||
769 | while (*size * *count > MEM2MEM_VID_MEM_LIMIT) | ||
770 | (*count)--; | ||
771 | |||
772 | v4l2_info(&ctx->dev->v4l2_dev, | ||
773 | "%d buffers of size %d set up.\n", *count, *size); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int m2mtest_buf_prepare(struct videobuf_queue *vq, | ||
779 | struct videobuf_buffer *vb, | ||
780 | enum v4l2_field field) | ||
781 | { | ||
782 | struct m2mtest_ctx *ctx = vq->priv_data; | ||
783 | struct m2mtest_q_data *q_data; | ||
784 | int ret; | ||
785 | |||
786 | dprintk(ctx->dev, "type: %d, index: %d, state: %d\n", | ||
787 | vq->type, vb->i, vb->state); | ||
788 | |||
789 | q_data = get_q_data(vq->type); | ||
790 | |||
791 | if (vb->baddr) { | ||
792 | /* User-provided buffer */ | ||
793 | if (vb->bsize < q_data->sizeimage) { | ||
794 | /* Buffer too small to fit a frame */ | ||
795 | v4l2_err(&ctx->dev->v4l2_dev, | ||
796 | "User-provided buffer too small\n"); | ||
797 | return -EINVAL; | ||
798 | } | ||
799 | } else if (vb->state != VIDEOBUF_NEEDS_INIT | ||
800 | && vb->bsize < q_data->sizeimage) { | ||
801 | /* We provide the buffer, but it's already been initialized | ||
802 | * and is too small */ | ||
803 | return -EINVAL; | ||
804 | } | ||
805 | |||
806 | vb->width = q_data->width; | ||
807 | vb->height = q_data->height; | ||
808 | vb->bytesperline = (q_data->width * q_data->fmt->depth) >> 3; | ||
809 | vb->size = q_data->sizeimage; | ||
810 | vb->field = field; | ||
811 | |||
812 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
813 | ret = videobuf_iolock(vq, vb, NULL); | ||
814 | if (ret) { | ||
815 | v4l2_err(&ctx->dev->v4l2_dev, | ||
816 | "Iolock failed\n"); | ||
817 | goto fail; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | vb->state = VIDEOBUF_PREPARED; | ||
822 | |||
823 | return 0; | ||
824 | fail: | ||
825 | m2mtest_buf_release(vq, vb); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | static void m2mtest_buf_queue(struct videobuf_queue *vq, | ||
830 | struct videobuf_buffer *vb) | ||
831 | { | ||
832 | struct m2mtest_ctx *ctx = vq->priv_data; | ||
833 | |||
834 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb); | ||
835 | } | ||
836 | |||
837 | static struct videobuf_queue_ops m2mtest_qops = { | ||
838 | .buf_setup = m2mtest_buf_setup, | ||
839 | .buf_prepare = m2mtest_buf_prepare, | ||
840 | .buf_queue = m2mtest_buf_queue, | ||
841 | .buf_release = m2mtest_buf_release, | ||
842 | }; | ||
843 | |||
844 | static void queue_init(void *priv, struct videobuf_queue *vq, | ||
845 | enum v4l2_buf_type type) | ||
846 | { | ||
847 | struct m2mtest_ctx *ctx = priv; | ||
848 | |||
849 | videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev, | ||
850 | &ctx->dev->irqlock, type, V4L2_FIELD_NONE, | ||
851 | sizeof(struct m2mtest_buffer), priv); | ||
852 | } | ||
853 | |||
854 | |||
855 | /* | ||
856 | * File operations | ||
857 | */ | ||
858 | static int m2mtest_open(struct file *file) | ||
859 | { | ||
860 | struct m2mtest_dev *dev = video_drvdata(file); | ||
861 | struct m2mtest_ctx *ctx = NULL; | ||
862 | |||
863 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | ||
864 | if (!ctx) | ||
865 | return -ENOMEM; | ||
866 | |||
867 | file->private_data = ctx; | ||
868 | ctx->dev = dev; | ||
869 | ctx->translen = MEM2MEM_DEF_TRANSLEN; | ||
870 | ctx->transtime = MEM2MEM_DEF_TRANSTIME; | ||
871 | ctx->num_processed = 0; | ||
872 | |||
873 | ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init); | ||
874 | if (IS_ERR(ctx->m2m_ctx)) { | ||
875 | int ret = PTR_ERR(ctx->m2m_ctx); | ||
876 | |||
877 | kfree(ctx); | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | atomic_inc(&dev->num_inst); | ||
882 | |||
883 | dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static int m2mtest_release(struct file *file) | ||
889 | { | ||
890 | struct m2mtest_dev *dev = video_drvdata(file); | ||
891 | struct m2mtest_ctx *ctx = file->private_data; | ||
892 | |||
893 | dprintk(dev, "Releasing instance %p\n", ctx); | ||
894 | |||
895 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
896 | kfree(ctx); | ||
897 | |||
898 | atomic_dec(&dev->num_inst); | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static unsigned int m2mtest_poll(struct file *file, | ||
904 | struct poll_table_struct *wait) | ||
905 | { | ||
906 | struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; | ||
907 | |||
908 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
909 | } | ||
910 | |||
911 | static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) | ||
912 | { | ||
913 | struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; | ||
914 | |||
915 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | ||
916 | } | ||
917 | |||
918 | static const struct v4l2_file_operations m2mtest_fops = { | ||
919 | .owner = THIS_MODULE, | ||
920 | .open = m2mtest_open, | ||
921 | .release = m2mtest_release, | ||
922 | .poll = m2mtest_poll, | ||
923 | .ioctl = video_ioctl2, | ||
924 | .mmap = m2mtest_mmap, | ||
925 | }; | ||
926 | |||
927 | static struct video_device m2mtest_videodev = { | ||
928 | .name = MEM2MEM_NAME, | ||
929 | .fops = &m2mtest_fops, | ||
930 | .ioctl_ops = &m2mtest_ioctl_ops, | ||
931 | .minor = -1, | ||
932 | .release = video_device_release, | ||
933 | }; | ||
934 | |||
935 | static struct v4l2_m2m_ops m2m_ops = { | ||
936 | .device_run = device_run, | ||
937 | .job_ready = job_ready, | ||
938 | .job_abort = job_abort, | ||
939 | }; | ||
940 | |||
941 | static int m2mtest_probe(struct platform_device *pdev) | ||
942 | { | ||
943 | struct m2mtest_dev *dev; | ||
944 | struct video_device *vfd; | ||
945 | int ret; | ||
946 | |||
947 | dev = kzalloc(sizeof *dev, GFP_KERNEL); | ||
948 | if (!dev) | ||
949 | return -ENOMEM; | ||
950 | |||
951 | spin_lock_init(&dev->irqlock); | ||
952 | |||
953 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); | ||
954 | if (ret) | ||
955 | goto free_dev; | ||
956 | |||
957 | atomic_set(&dev->num_inst, 0); | ||
958 | mutex_init(&dev->dev_mutex); | ||
959 | |||
960 | vfd = video_device_alloc(); | ||
961 | if (!vfd) { | ||
962 | v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); | ||
963 | ret = -ENOMEM; | ||
964 | goto unreg_dev; | ||
965 | } | ||
966 | |||
967 | *vfd = m2mtest_videodev; | ||
968 | |||
969 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | ||
970 | if (ret) { | ||
971 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
972 | goto rel_vdev; | ||
973 | } | ||
974 | |||
975 | video_set_drvdata(vfd, dev); | ||
976 | snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name); | ||
977 | dev->vfd = vfd; | ||
978 | v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME | ||
979 | "Device registered as /dev/video%d\n", vfd->num); | ||
980 | |||
981 | setup_timer(&dev->timer, device_isr, (long)dev); | ||
982 | platform_set_drvdata(pdev, dev); | ||
983 | |||
984 | dev->m2m_dev = v4l2_m2m_init(&m2m_ops); | ||
985 | if (IS_ERR(dev->m2m_dev)) { | ||
986 | v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); | ||
987 | ret = PTR_ERR(dev->m2m_dev); | ||
988 | goto err_m2m; | ||
989 | } | ||
990 | |||
991 | return 0; | ||
992 | |||
993 | err_m2m: | ||
994 | video_unregister_device(dev->vfd); | ||
995 | rel_vdev: | ||
996 | video_device_release(vfd); | ||
997 | unreg_dev: | ||
998 | v4l2_device_unregister(&dev->v4l2_dev); | ||
999 | free_dev: | ||
1000 | kfree(dev); | ||
1001 | |||
1002 | return ret; | ||
1003 | } | ||
1004 | |||
1005 | static int m2mtest_remove(struct platform_device *pdev) | ||
1006 | { | ||
1007 | struct m2mtest_dev *dev = | ||
1008 | (struct m2mtest_dev *)platform_get_drvdata(pdev); | ||
1009 | |||
1010 | v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME); | ||
1011 | v4l2_m2m_release(dev->m2m_dev); | ||
1012 | del_timer_sync(&dev->timer); | ||
1013 | video_unregister_device(dev->vfd); | ||
1014 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1015 | kfree(dev); | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static struct platform_driver m2mtest_pdrv = { | ||
1021 | .probe = m2mtest_probe, | ||
1022 | .remove = m2mtest_remove, | ||
1023 | .driver = { | ||
1024 | .name = MEM2MEM_NAME, | ||
1025 | .owner = THIS_MODULE, | ||
1026 | }, | ||
1027 | }; | ||
1028 | |||
1029 | static void __exit m2mtest_exit(void) | ||
1030 | { | ||
1031 | platform_driver_unregister(&m2mtest_pdrv); | ||
1032 | platform_device_unregister(&m2mtest_pdev); | ||
1033 | } | ||
1034 | |||
1035 | static int __init m2mtest_init(void) | ||
1036 | { | ||
1037 | int ret; | ||
1038 | |||
1039 | ret = platform_device_register(&m2mtest_pdev); | ||
1040 | if (ret) | ||
1041 | return ret; | ||
1042 | |||
1043 | ret = platform_driver_register(&m2mtest_pdrv); | ||
1044 | if (ret) | ||
1045 | platform_device_unregister(&m2mtest_pdev); | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1050 | module_init(m2mtest_init); | ||
1051 | module_exit(m2mtest_exit); | ||
1052 | |||
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 4404e5ef818f..2be23bccd3c8 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
@@ -30,9 +30,10 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/videodev.h> | ||
34 | #include <linux/gfp.h> | 33 | #include <linux/gfp.h> |
34 | #include <linux/videodev2.h> | ||
35 | #include <media/v4l2-common.h> | 35 | #include <media/v4l2-common.h> |
36 | #include <media/v4l2-device.h> | ||
36 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
@@ -1168,22 +1169,22 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) | |||
1168 | case V4L2_CID_BRIGHTNESS: | 1169 | case V4L2_CID_BRIGHTNESS: |
1169 | sony_pic_camera_command( | 1170 | sony_pic_camera_command( |
1170 | SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); | 1171 | SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); |
1171 | meye.picture.brightness = c->value << 10; | 1172 | meye.brightness = c->value << 10; |
1172 | break; | 1173 | break; |
1173 | case V4L2_CID_HUE: | 1174 | case V4L2_CID_HUE: |
1174 | sony_pic_camera_command( | 1175 | sony_pic_camera_command( |
1175 | SONY_PIC_COMMAND_SETCAMERAHUE, c->value); | 1176 | SONY_PIC_COMMAND_SETCAMERAHUE, c->value); |
1176 | meye.picture.hue = c->value << 10; | 1177 | meye.hue = c->value << 10; |
1177 | break; | 1178 | break; |
1178 | case V4L2_CID_CONTRAST: | 1179 | case V4L2_CID_CONTRAST: |
1179 | sony_pic_camera_command( | 1180 | sony_pic_camera_command( |
1180 | SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); | 1181 | SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); |
1181 | meye.picture.contrast = c->value << 10; | 1182 | meye.contrast = c->value << 10; |
1182 | break; | 1183 | break; |
1183 | case V4L2_CID_SATURATION: | 1184 | case V4L2_CID_SATURATION: |
1184 | sony_pic_camera_command( | 1185 | sony_pic_camera_command( |
1185 | SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); | 1186 | SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); |
1186 | meye.picture.colour = c->value << 10; | 1187 | meye.colour = c->value << 10; |
1187 | break; | 1188 | break; |
1188 | case V4L2_CID_AGC: | 1189 | case V4L2_CID_AGC: |
1189 | sony_pic_camera_command( | 1190 | sony_pic_camera_command( |
@@ -1221,16 +1222,16 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) | |||
1221 | mutex_lock(&meye.lock); | 1222 | mutex_lock(&meye.lock); |
1222 | switch (c->id) { | 1223 | switch (c->id) { |
1223 | case V4L2_CID_BRIGHTNESS: | 1224 | case V4L2_CID_BRIGHTNESS: |
1224 | c->value = meye.picture.brightness >> 10; | 1225 | c->value = meye.brightness >> 10; |
1225 | break; | 1226 | break; |
1226 | case V4L2_CID_HUE: | 1227 | case V4L2_CID_HUE: |
1227 | c->value = meye.picture.hue >> 10; | 1228 | c->value = meye.hue >> 10; |
1228 | break; | 1229 | break; |
1229 | case V4L2_CID_CONTRAST: | 1230 | case V4L2_CID_CONTRAST: |
1230 | c->value = meye.picture.contrast >> 10; | 1231 | c->value = meye.contrast >> 10; |
1231 | break; | 1232 | break; |
1232 | case V4L2_CID_SATURATION: | 1233 | case V4L2_CID_SATURATION: |
1233 | c->value = meye.picture.colour >> 10; | 1234 | c->value = meye.colour >> 10; |
1234 | break; | 1235 | break; |
1235 | case V4L2_CID_AGC: | 1236 | case V4L2_CID_AGC: |
1236 | c->value = meye.params.agc; | 1237 | c->value = meye.params.agc; |
@@ -1729,6 +1730,7 @@ static int meye_resume(struct pci_dev *pdev) | |||
1729 | static int __devinit meye_probe(struct pci_dev *pcidev, | 1730 | static int __devinit meye_probe(struct pci_dev *pcidev, |
1730 | const struct pci_device_id *ent) | 1731 | const struct pci_device_id *ent) |
1731 | { | 1732 | { |
1733 | struct v4l2_device *v4l2_dev = &meye.v4l2_dev; | ||
1732 | int ret = -EBUSY; | 1734 | int ret = -EBUSY; |
1733 | unsigned long mchip_adr; | 1735 | unsigned long mchip_adr; |
1734 | 1736 | ||
@@ -1737,70 +1739,75 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1737 | goto outnotdev; | 1739 | goto outnotdev; |
1738 | } | 1740 | } |
1739 | 1741 | ||
1742 | ret = v4l2_device_register(&pcidev->dev, v4l2_dev); | ||
1743 | if (ret < 0) { | ||
1744 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
1745 | return ret; | ||
1746 | } | ||
1740 | ret = -ENOMEM; | 1747 | ret = -ENOMEM; |
1741 | meye.mchip_dev = pcidev; | 1748 | meye.mchip_dev = pcidev; |
1742 | meye.video_dev = video_device_alloc(); | 1749 | meye.vdev = video_device_alloc(); |
1743 | if (!meye.video_dev) { | 1750 | if (!meye.vdev) { |
1744 | printk(KERN_ERR "meye: video_device_alloc() failed!\n"); | 1751 | v4l2_err(v4l2_dev, "video_device_alloc() failed!\n"); |
1745 | goto outnotdev; | 1752 | goto outnotdev; |
1746 | } | 1753 | } |
1747 | 1754 | ||
1748 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); | 1755 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); |
1749 | if (!meye.grab_temp) { | 1756 | if (!meye.grab_temp) { |
1750 | printk(KERN_ERR "meye: grab buffer allocation failed\n"); | 1757 | v4l2_err(v4l2_dev, "grab buffer allocation failed\n"); |
1751 | goto outvmalloc; | 1758 | goto outvmalloc; |
1752 | } | 1759 | } |
1753 | 1760 | ||
1754 | spin_lock_init(&meye.grabq_lock); | 1761 | spin_lock_init(&meye.grabq_lock); |
1755 | if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, | 1762 | if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, |
1756 | GFP_KERNEL)) { | 1763 | GFP_KERNEL)) { |
1757 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1764 | v4l2_err(v4l2_dev, "fifo allocation failed\n"); |
1758 | goto outkfifoalloc1; | 1765 | goto outkfifoalloc1; |
1759 | } | 1766 | } |
1760 | spin_lock_init(&meye.doneq_lock); | 1767 | spin_lock_init(&meye.doneq_lock); |
1761 | if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, | 1768 | if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, |
1762 | GFP_KERNEL)) { | 1769 | GFP_KERNEL)) { |
1763 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1770 | v4l2_err(v4l2_dev, "fifo allocation failed\n"); |
1764 | goto outkfifoalloc2; | 1771 | goto outkfifoalloc2; |
1765 | } | 1772 | } |
1766 | 1773 | ||
1767 | memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); | 1774 | memcpy(meye.vdev, &meye_template, sizeof(meye_template)); |
1768 | meye.video_dev->parent = &meye.mchip_dev->dev; | 1775 | meye.vdev->v4l2_dev = &meye.v4l2_dev; |
1769 | 1776 | ||
1770 | ret = -EIO; | 1777 | ret = -EIO; |
1771 | if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { | 1778 | if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { |
1772 | printk(KERN_ERR "meye: unable to power on the camera\n"); | 1779 | v4l2_err(v4l2_dev, "meye: unable to power on the camera\n"); |
1773 | printk(KERN_ERR "meye: did you enable the camera in " | 1780 | v4l2_err(v4l2_dev, "meye: did you enable the camera in " |
1774 | "sonypi using the module options ?\n"); | 1781 | "sonypi using the module options ?\n"); |
1775 | goto outsonypienable; | 1782 | goto outsonypienable; |
1776 | } | 1783 | } |
1777 | 1784 | ||
1778 | if ((ret = pci_enable_device(meye.mchip_dev))) { | 1785 | if ((ret = pci_enable_device(meye.mchip_dev))) { |
1779 | printk(KERN_ERR "meye: pci_enable_device failed\n"); | 1786 | v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n"); |
1780 | goto outenabledev; | 1787 | goto outenabledev; |
1781 | } | 1788 | } |
1782 | 1789 | ||
1783 | mchip_adr = pci_resource_start(meye.mchip_dev,0); | 1790 | mchip_adr = pci_resource_start(meye.mchip_dev,0); |
1784 | if (!mchip_adr) { | 1791 | if (!mchip_adr) { |
1785 | printk(KERN_ERR "meye: mchip has no device base address\n"); | 1792 | v4l2_err(v4l2_dev, "meye: mchip has no device base address\n"); |
1786 | goto outregions; | 1793 | goto outregions; |
1787 | } | 1794 | } |
1788 | if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), | 1795 | if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), |
1789 | pci_resource_len(meye.mchip_dev, 0), | 1796 | pci_resource_len(meye.mchip_dev, 0), |
1790 | "meye")) { | 1797 | "meye")) { |
1791 | printk(KERN_ERR "meye: request_mem_region failed\n"); | 1798 | v4l2_err(v4l2_dev, "meye: request_mem_region failed\n"); |
1792 | goto outregions; | 1799 | goto outregions; |
1793 | } | 1800 | } |
1794 | meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); | 1801 | meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); |
1795 | if (!meye.mchip_mmregs) { | 1802 | if (!meye.mchip_mmregs) { |
1796 | printk(KERN_ERR "meye: ioremap failed\n"); | 1803 | v4l2_err(v4l2_dev, "meye: ioremap failed\n"); |
1797 | goto outremap; | 1804 | goto outremap; |
1798 | } | 1805 | } |
1799 | 1806 | ||
1800 | meye.mchip_irq = pcidev->irq; | 1807 | meye.mchip_irq = pcidev->irq; |
1801 | if (request_irq(meye.mchip_irq, meye_irq, | 1808 | if (request_irq(meye.mchip_irq, meye_irq, |
1802 | IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) { | 1809 | IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) { |
1803 | printk(KERN_ERR "meye: request_irq failed\n"); | 1810 | v4l2_err(v4l2_dev, "request_irq failed\n"); |
1804 | goto outreqirq; | 1811 | goto outreqirq; |
1805 | } | 1812 | } |
1806 | 1813 | ||
@@ -1824,21 +1831,18 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1824 | msleep(1); | 1831 | msleep(1); |
1825 | mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); | 1832 | mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); |
1826 | 1833 | ||
1827 | if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER, | 1834 | if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, |
1828 | video_nr) < 0) { | 1835 | video_nr) < 0) { |
1829 | printk(KERN_ERR "meye: video_register_device failed\n"); | 1836 | v4l2_err(v4l2_dev, "video_register_device failed\n"); |
1830 | goto outvideoreg; | 1837 | goto outvideoreg; |
1831 | } | 1838 | } |
1832 | 1839 | ||
1833 | mutex_init(&meye.lock); | 1840 | mutex_init(&meye.lock); |
1834 | init_waitqueue_head(&meye.proc_list); | 1841 | init_waitqueue_head(&meye.proc_list); |
1835 | meye.picture.depth = 16; | 1842 | meye.brightness = 32 << 10; |
1836 | meye.picture.palette = VIDEO_PALETTE_YUV422; | 1843 | meye.hue = 32 << 10; |
1837 | meye.picture.brightness = 32 << 10; | 1844 | meye.colour = 32 << 10; |
1838 | meye.picture.hue = 32 << 10; | 1845 | meye.contrast = 32 << 10; |
1839 | meye.picture.colour = 32 << 10; | ||
1840 | meye.picture.contrast = 32 << 10; | ||
1841 | meye.picture.whiteness = 0; | ||
1842 | meye.params.subsample = 0; | 1846 | meye.params.subsample = 0; |
1843 | meye.params.quality = 8; | 1847 | meye.params.quality = 8; |
1844 | meye.params.sharpness = 32; | 1848 | meye.params.sharpness = 32; |
@@ -1854,9 +1858,9 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1854 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); | 1858 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); |
1855 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); | 1859 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); |
1856 | 1860 | ||
1857 | printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", | 1861 | v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n", |
1858 | MEYE_DRIVER_VERSION); | 1862 | MEYE_DRIVER_VERSION); |
1859 | printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", | 1863 | v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n", |
1860 | meye.mchip_dev->revision, mchip_adr, meye.mchip_irq); | 1864 | meye.mchip_dev->revision, mchip_adr, meye.mchip_irq); |
1861 | 1865 | ||
1862 | return 0; | 1866 | return 0; |
@@ -1879,14 +1883,14 @@ outkfifoalloc2: | |||
1879 | outkfifoalloc1: | 1883 | outkfifoalloc1: |
1880 | vfree(meye.grab_temp); | 1884 | vfree(meye.grab_temp); |
1881 | outvmalloc: | 1885 | outvmalloc: |
1882 | video_device_release(meye.video_dev); | 1886 | video_device_release(meye.vdev); |
1883 | outnotdev: | 1887 | outnotdev: |
1884 | return ret; | 1888 | return ret; |
1885 | } | 1889 | } |
1886 | 1890 | ||
1887 | static void __devexit meye_remove(struct pci_dev *pcidev) | 1891 | static void __devexit meye_remove(struct pci_dev *pcidev) |
1888 | { | 1892 | { |
1889 | video_unregister_device(meye.video_dev); | 1893 | video_unregister_device(meye.vdev); |
1890 | 1894 | ||
1891 | mchip_hic_stop(); | 1895 | mchip_hic_stop(); |
1892 | 1896 | ||
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 1321ad5d6597..4bdeb03f1644 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h | |||
@@ -31,7 +31,7 @@ | |||
31 | #define _MEYE_PRIV_H_ | 31 | #define _MEYE_PRIV_H_ |
32 | 32 | ||
33 | #define MEYE_DRIVER_MAJORVERSION 1 | 33 | #define MEYE_DRIVER_MAJORVERSION 1 |
34 | #define MEYE_DRIVER_MINORVERSION 13 | 34 | #define MEYE_DRIVER_MINORVERSION 14 |
35 | 35 | ||
36 | #define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ | 36 | #define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ |
37 | __stringify(MEYE_DRIVER_MINORVERSION) | 37 | __stringify(MEYE_DRIVER_MINORVERSION) |
@@ -289,6 +289,7 @@ struct meye_grab_buffer { | |||
289 | 289 | ||
290 | /* Motion Eye device structure */ | 290 | /* Motion Eye device structure */ |
291 | struct meye { | 291 | struct meye { |
292 | struct v4l2_device v4l2_dev; /* Main v4l2_device struct */ | ||
292 | struct pci_dev *mchip_dev; /* pci device */ | 293 | struct pci_dev *mchip_dev; /* pci device */ |
293 | u8 mchip_irq; /* irq */ | 294 | u8 mchip_irq; /* irq */ |
294 | u8 mchip_mode; /* actual mchip mode: HIC_MODE... */ | 295 | u8 mchip_mode; /* actual mchip mode: HIC_MODE... */ |
@@ -308,8 +309,11 @@ struct meye { | |||
308 | struct kfifo doneq; /* queue for grabbed buffers */ | 309 | struct kfifo doneq; /* queue for grabbed buffers */ |
309 | spinlock_t doneq_lock; /* lock protecting the queue */ | 310 | spinlock_t doneq_lock; /* lock protecting the queue */ |
310 | wait_queue_head_t proc_list; /* wait queue */ | 311 | wait_queue_head_t proc_list; /* wait queue */ |
311 | struct video_device *video_dev; /* video device parameters */ | 312 | struct video_device *vdev; /* video device parameters */ |
312 | struct video_picture picture; /* video picture parameters */ | 313 | u16 brightness; |
314 | u16 hue; | ||
315 | u16 contrast; | ||
316 | u16 colour; | ||
313 | struct meye_params params; /* additional parameters */ | 317 | struct meye_params params; /* additional parameters */ |
314 | unsigned long in_use; /* set to 1 if the device is in use */ | 318 | unsigned long in_use; /* set to 1 if the device is in use */ |
315 | #ifdef CONFIG_PM | 319 | #ifdef CONFIG_PM |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index a9061bff79b2..78b4e091d2d5 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -8,14 +8,16 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/videodev2.h> | 11 | #include <linux/device.h> |
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
14 | #include <linux/log2.h> | 13 | #include <linux/log2.h> |
14 | #include <linux/pm.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/videodev2.h> | ||
15 | 17 | ||
16 | #include <media/v4l2-subdev.h> | ||
17 | #include <media/v4l2-chip-ident.h> | ||
18 | #include <media/soc_camera.h> | 18 | #include <media/soc_camera.h> |
19 | #include <media/v4l2-chip-ident.h> | ||
20 | #include <media/v4l2-subdev.h> | ||
19 | 21 | ||
20 | /* | 22 | /* |
21 | * mt9t031 i2c address 0x5d | 23 | * mt9t031 i2c address 0x5d |
@@ -681,12 +683,66 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
681 | } | 683 | } |
682 | 684 | ||
683 | /* | 685 | /* |
686 | * Power Management: | ||
687 | * This function does nothing for now but must be present for pm to work | ||
688 | */ | ||
689 | static int mt9t031_runtime_suspend(struct device *dev) | ||
690 | { | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /* | ||
695 | * Power Management: | ||
696 | * COLUMN_ADDRESS_MODE and ROW_ADDRESS_MODE are not rewritten if unchanged | ||
697 | * they are however changed at reset if the platform hook is present | ||
698 | * thus we rewrite them with the values stored by the driver | ||
699 | */ | ||
700 | static int mt9t031_runtime_resume(struct device *dev) | ||
701 | { | ||
702 | struct video_device *vdev = to_video_device(dev); | ||
703 | struct soc_camera_device *icd = container_of(vdev->parent, | ||
704 | struct soc_camera_device, dev); | ||
705 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
706 | struct i2c_client *client = sd->priv; | ||
707 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
708 | |||
709 | int ret; | ||
710 | u16 xbin, ybin; | ||
711 | |||
712 | xbin = min(mt9t031->xskip, (u16)3); | ||
713 | ybin = min(mt9t031->yskip, (u16)3); | ||
714 | |||
715 | ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, | ||
716 | ((xbin - 1) << 4) | (mt9t031->xskip - 1)); | ||
717 | if (ret < 0) | ||
718 | return ret; | ||
719 | |||
720 | ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, | ||
721 | ((ybin - 1) << 4) | (mt9t031->yskip - 1)); | ||
722 | if (ret < 0) | ||
723 | return ret; | ||
724 | |||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | static struct dev_pm_ops mt9t031_dev_pm_ops = { | ||
729 | .runtime_suspend = mt9t031_runtime_suspend, | ||
730 | .runtime_resume = mt9t031_runtime_resume, | ||
731 | }; | ||
732 | |||
733 | static struct device_type mt9t031_dev_type = { | ||
734 | .name = "MT9T031", | ||
735 | .pm = &mt9t031_dev_pm_ops, | ||
736 | }; | ||
737 | |||
738 | /* | ||
684 | * Interface active, can use i2c. If it fails, it can indeed mean, that | 739 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
685 | * this wasn't our capture interface, so, we wait for the right one | 740 | * this wasn't our capture interface, so, we wait for the right one |
686 | */ | 741 | */ |
687 | static int mt9t031_video_probe(struct i2c_client *client) | 742 | static int mt9t031_video_probe(struct i2c_client *client) |
688 | { | 743 | { |
689 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 744 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
745 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | ||
690 | s32 data; | 746 | s32 data; |
691 | int ret; | 747 | int ret; |
692 | 748 | ||
@@ -712,6 +768,8 @@ static int mt9t031_video_probe(struct i2c_client *client) | |||
712 | ret = mt9t031_idle(client); | 768 | ret = mt9t031_idle(client); |
713 | if (ret < 0) | 769 | if (ret < 0) |
714 | dev_err(&client->dev, "Failed to initialise the camera\n"); | 770 | dev_err(&client->dev, "Failed to initialise the camera\n"); |
771 | else | ||
772 | vdev->dev.type = &mt9t031_dev_type; | ||
715 | 773 | ||
716 | /* mt9t031_idle() has reset the chip to default. */ | 774 | /* mt9t031_idle() has reset the chip to default. */ |
717 | mt9t031->exposure = 255; | 775 | mt9t031->exposure = 255; |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 1a34d2993e94..e5bae4c9393b 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -325,7 +325,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
325 | if (ret < 0) | 325 | if (ret < 0) |
326 | return ret; | 326 | return ret; |
327 | 327 | ||
328 | dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect.width, rect.height); | 328 | dev_dbg(&client->dev, "Frame %dx%d pixel\n", rect.width, rect.height); |
329 | 329 | ||
330 | mt9v022->rect = rect; | 330 | mt9v022->rect = rect; |
331 | 331 | ||
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 34a66019190e..5c17f9ec3d7c 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c | |||
@@ -139,8 +139,8 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
139 | if (!*count) | 139 | if (!*count) |
140 | *count = 32; | 140 | *count = 32; |
141 | 141 | ||
142 | while (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) | 142 | if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) |
143 | (*count)--; | 143 | *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; |
144 | 144 | ||
145 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); | 145 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); |
146 | 146 | ||
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index bd297f567dc7..d477e3058002 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -796,7 +796,7 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) | |||
796 | * FIXME: learn to use stride != width, then we can keep stride properly aligned | 796 | * FIXME: learn to use stride != width, then we can keep stride properly aligned |
797 | * and support arbitrary (even) widths. | 797 | * and support arbitrary (even) widths. |
798 | */ | 798 | */ |
799 | static inline void stride_align(__s32 *width) | 799 | static inline void stride_align(__u32 *width) |
800 | { | 800 | { |
801 | if (((*width + 7) & ~7) < 4096) | 801 | if (((*width + 7) & ~7) < 4096) |
802 | *width = (*width + 7) & ~7; | 802 | *width = (*width + 7) & ~7; |
@@ -844,7 +844,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
844 | * So far only direct camera-to-memory is supported | 844 | * So far only direct camera-to-memory is supported |
845 | */ | 845 | */ |
846 | if (channel_change_requested(icd, rect)) { | 846 | if (channel_change_requested(icd, rect)) { |
847 | int ret = acquire_dma_channel(mx3_cam); | 847 | ret = acquire_dma_channel(mx3_cam); |
848 | if (ret < 0) | 848 | if (ret < 0) |
849 | return ret; | 849 | return ret; |
850 | } | 850 | } |
diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig new file mode 100644 index 000000000000..97c53949ca89 --- /dev/null +++ b/drivers/media/video/omap/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | config VIDEO_OMAP2_VOUT | ||
2 | tristate "OMAP2/OMAP3 V4L2-Display driver" | ||
3 | depends on ARCH_OMAP24XX || ARCH_OMAP34XX | ||
4 | select VIDEOBUF_GEN | ||
5 | select VIDEOBUF_DMA_SG | ||
6 | select OMAP2_DSS | ||
7 | select OMAP2_VRAM | ||
8 | select OMAP2_VRFB | ||
9 | default n | ||
10 | ---help--- | ||
11 | V4L2 Display driver support for OMAP2/3 based boards. | ||
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile new file mode 100644 index 000000000000..b8bab00ad010 --- /dev/null +++ b/drivers/media/video/omap/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the omap video device drivers. | ||
3 | # | ||
4 | |||
5 | # OMAP2/3 Display driver | ||
6 | omap-vout-mod-objs := omap_vout.o omap_voutlib.o | ||
7 | obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o | ||
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c new file mode 100644 index 000000000000..4c0ab499228b --- /dev/null +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -0,0 +1,2643 @@ | |||
1 | /* | ||
2 | * omap_vout.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2010 Texas Instruments. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | * Leveraged code from the OMAP2 camera driver | ||
11 | * Video-for-Linux (Version 2) camera capture driver for | ||
12 | * the OMAP24xx camera controller. | ||
13 | * | ||
14 | * Author: Andy Lowe (source@mvista.com) | ||
15 | * | ||
16 | * Copyright (C) 2004 MontaVista Software, Inc. | ||
17 | * Copyright (C) 2010 Texas Instruments. | ||
18 | * | ||
19 | * History: | ||
20 | * 20-APR-2006 Khasim Modified VRFB based Rotation, | ||
21 | * The image data is always read from 0 degree | ||
22 | * view and written | ||
23 | * to the virtual space of desired rotation angle | ||
24 | * 4-DEC-2006 Jian Changed to support better memory management | ||
25 | * | ||
26 | * 17-Nov-2008 Hardik Changed driver to use video_ioctl2 | ||
27 | * | ||
28 | * 23-Feb-2010 Vaibhav H Modified to use new DSS2 interface | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/init.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/types.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/irq.h> | ||
40 | #include <linux/videodev2.h> | ||
41 | |||
42 | #include <media/videobuf-dma-sg.h> | ||
43 | #include <media/v4l2-device.h> | ||
44 | #include <media/v4l2-ioctl.h> | ||
45 | |||
46 | #include <plat/dma.h> | ||
47 | #include <plat/vram.h> | ||
48 | #include <plat/vrfb.h> | ||
49 | #include <plat/display.h> | ||
50 | |||
51 | #include "omap_voutlib.h" | ||
52 | #include "omap_voutdef.h" | ||
53 | |||
54 | MODULE_AUTHOR("Texas Instruments"); | ||
55 | MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); | ||
56 | MODULE_LICENSE("GPL"); | ||
57 | |||
58 | |||
59 | /* Driver Configuration macros */ | ||
60 | #define VOUT_NAME "omap_vout" | ||
61 | |||
62 | enum omap_vout_channels { | ||
63 | OMAP_VIDEO1, | ||
64 | OMAP_VIDEO2, | ||
65 | }; | ||
66 | |||
67 | enum dma_channel_state { | ||
68 | DMA_CHAN_NOT_ALLOTED, | ||
69 | DMA_CHAN_ALLOTED, | ||
70 | }; | ||
71 | |||
72 | #define QQVGA_WIDTH 160 | ||
73 | #define QQVGA_HEIGHT 120 | ||
74 | |||
75 | /* Max Resolution supported by the driver */ | ||
76 | #define VID_MAX_WIDTH 1280 /* Largest width */ | ||
77 | #define VID_MAX_HEIGHT 720 /* Largest height */ | ||
78 | |||
79 | /* Mimimum requirement is 2x2 for DSS */ | ||
80 | #define VID_MIN_WIDTH 2 | ||
81 | #define VID_MIN_HEIGHT 2 | ||
82 | |||
83 | /* 2048 x 2048 is max res supported by OMAP display controller */ | ||
84 | #define MAX_PIXELS_PER_LINE 2048 | ||
85 | |||
86 | #define VRFB_TX_TIMEOUT 1000 | ||
87 | #define VRFB_NUM_BUFS 4 | ||
88 | |||
89 | /* Max buffer size tobe allocated during init */ | ||
90 | #define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4) | ||
91 | |||
92 | static struct videobuf_queue_ops video_vbq_ops; | ||
93 | /* Variables configurable through module params*/ | ||
94 | static u32 video1_numbuffers = 3; | ||
95 | static u32 video2_numbuffers = 3; | ||
96 | static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE; | ||
97 | static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE; | ||
98 | static u32 vid1_static_vrfb_alloc; | ||
99 | static u32 vid2_static_vrfb_alloc; | ||
100 | static int debug; | ||
101 | |||
102 | /* Module parameters */ | ||
103 | module_param(video1_numbuffers, uint, S_IRUGO); | ||
104 | MODULE_PARM_DESC(video1_numbuffers, | ||
105 | "Number of buffers to be allocated at init time for Video1 device."); | ||
106 | |||
107 | module_param(video2_numbuffers, uint, S_IRUGO); | ||
108 | MODULE_PARM_DESC(video2_numbuffers, | ||
109 | "Number of buffers to be allocated at init time for Video2 device."); | ||
110 | |||
111 | module_param(video1_bufsize, uint, S_IRUGO); | ||
112 | MODULE_PARM_DESC(video1_bufsize, | ||
113 | "Size of the buffer to be allocated for video1 device"); | ||
114 | |||
115 | module_param(video2_bufsize, uint, S_IRUGO); | ||
116 | MODULE_PARM_DESC(video2_bufsize, | ||
117 | "Size of the buffer to be allocated for video2 device"); | ||
118 | |||
119 | module_param(vid1_static_vrfb_alloc, bool, S_IRUGO); | ||
120 | MODULE_PARM_DESC(vid1_static_vrfb_alloc, | ||
121 | "Static allocation of the VRFB buffer for video1 device"); | ||
122 | |||
123 | module_param(vid2_static_vrfb_alloc, bool, S_IRUGO); | ||
124 | MODULE_PARM_DESC(vid2_static_vrfb_alloc, | ||
125 | "Static allocation of the VRFB buffer for video2 device"); | ||
126 | |||
127 | module_param(debug, bool, S_IRUGO); | ||
128 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
129 | |||
130 | /* list of image formats supported by OMAP2 video pipelines */ | ||
131 | const static struct v4l2_fmtdesc omap_formats[] = { | ||
132 | { | ||
133 | /* Note: V4L2 defines RGB565 as: | ||
134 | * | ||
135 | * Byte 0 Byte 1 | ||
136 | * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 | ||
137 | * | ||
138 | * We interpret RGB565 as: | ||
139 | * | ||
140 | * Byte 0 Byte 1 | ||
141 | * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 | ||
142 | */ | ||
143 | .description = "RGB565, le", | ||
144 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
145 | }, | ||
146 | { | ||
147 | /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use | ||
148 | * this for RGB24 unpack mode, the last 8 bits are ignored | ||
149 | * */ | ||
150 | .description = "RGB32, le", | ||
151 | .pixelformat = V4L2_PIX_FMT_RGB32, | ||
152 | }, | ||
153 | { | ||
154 | /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use | ||
155 | * this for RGB24 packed mode | ||
156 | * | ||
157 | */ | ||
158 | .description = "RGB24, le", | ||
159 | .pixelformat = V4L2_PIX_FMT_RGB24, | ||
160 | }, | ||
161 | { | ||
162 | .description = "YUYV (YUV 4:2:2), packed", | ||
163 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
164 | }, | ||
165 | { | ||
166 | .description = "UYVY, packed", | ||
167 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) | ||
172 | |||
173 | /* | ||
174 | * Allocate buffers | ||
175 | */ | ||
176 | static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr) | ||
177 | { | ||
178 | u32 order, size; | ||
179 | unsigned long virt_addr, addr; | ||
180 | |||
181 | size = PAGE_ALIGN(buf_size); | ||
182 | order = get_order(size); | ||
183 | virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order); | ||
184 | addr = virt_addr; | ||
185 | |||
186 | if (virt_addr) { | ||
187 | while (size > 0) { | ||
188 | SetPageReserved(virt_to_page(addr)); | ||
189 | addr += PAGE_SIZE; | ||
190 | size -= PAGE_SIZE; | ||
191 | } | ||
192 | } | ||
193 | *phys_addr = (u32) virt_to_phys((void *) virt_addr); | ||
194 | return virt_addr; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Free buffers | ||
199 | */ | ||
200 | static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size) | ||
201 | { | ||
202 | u32 order, size; | ||
203 | unsigned long addr = virtaddr; | ||
204 | |||
205 | size = PAGE_ALIGN(buf_size); | ||
206 | order = get_order(size); | ||
207 | |||
208 | while (size > 0) { | ||
209 | ClearPageReserved(virt_to_page(addr)); | ||
210 | addr += PAGE_SIZE; | ||
211 | size -= PAGE_SIZE; | ||
212 | } | ||
213 | free_pages((unsigned long) virtaddr, order); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Function for allocating video buffers | ||
218 | */ | ||
219 | static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout, | ||
220 | unsigned int *count, int startindex) | ||
221 | { | ||
222 | int i, j; | ||
223 | |||
224 | for (i = 0; i < *count; i++) { | ||
225 | if (!vout->smsshado_virt_addr[i]) { | ||
226 | vout->smsshado_virt_addr[i] = | ||
227 | omap_vout_alloc_buffer(vout->smsshado_size, | ||
228 | &vout->smsshado_phy_addr[i]); | ||
229 | } | ||
230 | if (!vout->smsshado_virt_addr[i] && startindex != -1) { | ||
231 | if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex) | ||
232 | break; | ||
233 | } | ||
234 | if (!vout->smsshado_virt_addr[i]) { | ||
235 | for (j = 0; j < i; j++) { | ||
236 | omap_vout_free_buffer( | ||
237 | vout->smsshado_virt_addr[j], | ||
238 | vout->smsshado_size); | ||
239 | vout->smsshado_virt_addr[j] = 0; | ||
240 | vout->smsshado_phy_addr[j] = 0; | ||
241 | } | ||
242 | *count = 0; | ||
243 | return -ENOMEM; | ||
244 | } | ||
245 | memset((void *) vout->smsshado_virt_addr[i], 0, | ||
246 | vout->smsshado_size); | ||
247 | } | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Try format | ||
253 | */ | ||
254 | static int omap_vout_try_format(struct v4l2_pix_format *pix) | ||
255 | { | ||
256 | int ifmt, bpp = 0; | ||
257 | |||
258 | pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT, | ||
259 | (u32)VID_MAX_HEIGHT); | ||
260 | pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH); | ||
261 | |||
262 | for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) { | ||
263 | if (pix->pixelformat == omap_formats[ifmt].pixelformat) | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | if (ifmt == NUM_OUTPUT_FORMATS) | ||
268 | ifmt = 0; | ||
269 | |||
270 | pix->pixelformat = omap_formats[ifmt].pixelformat; | ||
271 | pix->field = V4L2_FIELD_ANY; | ||
272 | pix->priv = 0; | ||
273 | |||
274 | switch (pix->pixelformat) { | ||
275 | case V4L2_PIX_FMT_YUYV: | ||
276 | case V4L2_PIX_FMT_UYVY: | ||
277 | default: | ||
278 | pix->colorspace = V4L2_COLORSPACE_JPEG; | ||
279 | bpp = YUYV_BPP; | ||
280 | break; | ||
281 | case V4L2_PIX_FMT_RGB565: | ||
282 | case V4L2_PIX_FMT_RGB565X: | ||
283 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
284 | bpp = RGB565_BPP; | ||
285 | break; | ||
286 | case V4L2_PIX_FMT_RGB24: | ||
287 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
288 | bpp = RGB24_BPP; | ||
289 | break; | ||
290 | case V4L2_PIX_FMT_RGB32: | ||
291 | case V4L2_PIX_FMT_BGR32: | ||
292 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
293 | bpp = RGB32_BPP; | ||
294 | break; | ||
295 | } | ||
296 | pix->bytesperline = pix->width * bpp; | ||
297 | pix->sizeimage = pix->bytesperline * pix->height; | ||
298 | |||
299 | return bpp; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * omap_vout_uservirt_to_phys: This inline function is used to convert user | ||
304 | * space virtual address to physical address. | ||
305 | */ | ||
306 | static u32 omap_vout_uservirt_to_phys(u32 virtp) | ||
307 | { | ||
308 | unsigned long physp = 0; | ||
309 | struct vm_area_struct *vma; | ||
310 | struct mm_struct *mm = current->mm; | ||
311 | |||
312 | vma = find_vma(mm, virtp); | ||
313 | /* For kernel direct-mapped memory, take the easy way */ | ||
314 | if (virtp >= PAGE_OFFSET) { | ||
315 | physp = virt_to_phys((void *) virtp); | ||
316 | } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { | ||
317 | /* this will catch, kernel-allocated, mmaped-to-usermode | ||
318 | addresses */ | ||
319 | physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); | ||
320 | } else { | ||
321 | /* otherwise, use get_user_pages() for general userland pages */ | ||
322 | int res, nr_pages = 1; | ||
323 | struct page *pages; | ||
324 | down_read(¤t->mm->mmap_sem); | ||
325 | |||
326 | res = get_user_pages(current, current->mm, virtp, nr_pages, 1, | ||
327 | 0, &pages, NULL); | ||
328 | up_read(¤t->mm->mmap_sem); | ||
329 | |||
330 | if (res == nr_pages) { | ||
331 | physp = __pa(page_address(&pages[0]) + | ||
332 | (virtp & ~PAGE_MASK)); | ||
333 | } else { | ||
334 | printk(KERN_WARNING VOUT_NAME | ||
335 | "get_user_pages failed\n"); | ||
336 | return 0; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | return physp; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Wakes up the application once the DMA transfer to VRFB space is completed. | ||
345 | */ | ||
346 | static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data) | ||
347 | { | ||
348 | struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data; | ||
349 | |||
350 | t->tx_status = 1; | ||
351 | wake_up_interruptible(&t->wait); | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * Release the VRFB context once the module exits | ||
356 | */ | ||
357 | static void omap_vout_release_vrfb(struct omap_vout_device *vout) | ||
358 | { | ||
359 | int i; | ||
360 | |||
361 | for (i = 0; i < VRFB_NUM_BUFS; i++) | ||
362 | omap_vrfb_release_ctx(&vout->vrfb_context[i]); | ||
363 | |||
364 | if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) { | ||
365 | vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; | ||
366 | omap_free_dma(vout->vrfb_dma_tx.dma_ch); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Return true if rotation is 90 or 270 | ||
372 | */ | ||
373 | static inline int rotate_90_or_270(const struct omap_vout_device *vout) | ||
374 | { | ||
375 | return (vout->rotation == dss_rotation_90_degree || | ||
376 | vout->rotation == dss_rotation_270_degree); | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Return true if rotation is enabled | ||
381 | */ | ||
382 | static inline int rotation_enabled(const struct omap_vout_device *vout) | ||
383 | { | ||
384 | return vout->rotation || vout->mirror; | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | * Reverse the rotation degree if mirroring is enabled | ||
389 | */ | ||
390 | static inline int calc_rotation(const struct omap_vout_device *vout) | ||
391 | { | ||
392 | if (!vout->mirror) | ||
393 | return vout->rotation; | ||
394 | |||
395 | switch (vout->rotation) { | ||
396 | case dss_rotation_90_degree: | ||
397 | return dss_rotation_270_degree; | ||
398 | case dss_rotation_270_degree: | ||
399 | return dss_rotation_90_degree; | ||
400 | case dss_rotation_180_degree: | ||
401 | return dss_rotation_0_degree; | ||
402 | default: | ||
403 | return dss_rotation_180_degree; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * Free the V4L2 buffers | ||
409 | */ | ||
410 | static void omap_vout_free_buffers(struct omap_vout_device *vout) | ||
411 | { | ||
412 | int i, numbuffers; | ||
413 | |||
414 | /* Allocate memory for the buffers */ | ||
415 | numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers; | ||
416 | vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize; | ||
417 | |||
418 | for (i = 0; i < numbuffers; i++) { | ||
419 | omap_vout_free_buffer(vout->buf_virt_addr[i], | ||
420 | vout->buffer_size); | ||
421 | vout->buf_phy_addr[i] = 0; | ||
422 | vout->buf_virt_addr[i] = 0; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * Free VRFB buffers | ||
428 | */ | ||
429 | static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) | ||
430 | { | ||
431 | int j; | ||
432 | |||
433 | for (j = 0; j < VRFB_NUM_BUFS; j++) { | ||
434 | omap_vout_free_buffer(vout->smsshado_virt_addr[j], | ||
435 | vout->smsshado_size); | ||
436 | vout->smsshado_virt_addr[j] = 0; | ||
437 | vout->smsshado_phy_addr[j] = 0; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Allocate the buffers for the VRFB space. Data is copied from V4L2 | ||
443 | * buffers to the VRFB buffers using the DMA engine. | ||
444 | */ | ||
445 | static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, | ||
446 | unsigned int *count, unsigned int startindex) | ||
447 | { | ||
448 | int i; | ||
449 | bool yuv_mode; | ||
450 | |||
451 | /* Allocate the VRFB buffers only if the buffers are not | ||
452 | * allocated during init time. | ||
453 | */ | ||
454 | if ((rotation_enabled(vout)) && !vout->vrfb_static_allocation) | ||
455 | if (omap_vout_allocate_vrfb_buffers(vout, count, startindex)) | ||
456 | return -ENOMEM; | ||
457 | |||
458 | if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 || | ||
459 | vout->dss_mode == OMAP_DSS_COLOR_UYVY) | ||
460 | yuv_mode = true; | ||
461 | else | ||
462 | yuv_mode = false; | ||
463 | |||
464 | for (i = 0; i < *count; i++) | ||
465 | omap_vrfb_setup(&vout->vrfb_context[i], | ||
466 | vout->smsshado_phy_addr[i], vout->pix.width, | ||
467 | vout->pix.height, vout->bpp, yuv_mode); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Convert V4L2 rotation to DSS rotation | ||
474 | * V4L2 understand 0, 90, 180, 270. | ||
475 | * Convert to 0, 1, 2 and 3 repsectively for DSS | ||
476 | */ | ||
477 | static int v4l2_rot_to_dss_rot(int v4l2_rotation, | ||
478 | enum dss_rotation *rotation, bool mirror) | ||
479 | { | ||
480 | int ret = 0; | ||
481 | |||
482 | switch (v4l2_rotation) { | ||
483 | case 90: | ||
484 | *rotation = dss_rotation_90_degree; | ||
485 | break; | ||
486 | case 180: | ||
487 | *rotation = dss_rotation_180_degree; | ||
488 | break; | ||
489 | case 270: | ||
490 | *rotation = dss_rotation_270_degree; | ||
491 | break; | ||
492 | case 0: | ||
493 | *rotation = dss_rotation_0_degree; | ||
494 | break; | ||
495 | default: | ||
496 | ret = -EINVAL; | ||
497 | } | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * Calculate the buffer offsets from which the streaming should | ||
503 | * start. This offset calculation is mainly required because of | ||
504 | * the VRFB 32 pixels alignment with rotation. | ||
505 | */ | ||
506 | static int omap_vout_calculate_offset(struct omap_vout_device *vout) | ||
507 | { | ||
508 | struct omap_overlay *ovl; | ||
509 | enum dss_rotation rotation; | ||
510 | struct omapvideo_info *ovid; | ||
511 | bool mirroring = vout->mirror; | ||
512 | struct omap_dss_device *cur_display; | ||
513 | struct v4l2_rect *crop = &vout->crop; | ||
514 | struct v4l2_pix_format *pix = &vout->pix; | ||
515 | int *cropped_offset = &vout->cropped_offset; | ||
516 | int vr_ps = 1, ps = 2, temp_ps = 2; | ||
517 | int offset = 0, ctop = 0, cleft = 0, line_length = 0; | ||
518 | |||
519 | ovid = &vout->vid_info; | ||
520 | ovl = ovid->overlays[0]; | ||
521 | /* get the display device attached to the overlay */ | ||
522 | if (!ovl->manager || !ovl->manager->device) | ||
523 | return -1; | ||
524 | |||
525 | cur_display = ovl->manager->device; | ||
526 | rotation = calc_rotation(vout); | ||
527 | |||
528 | if (V4L2_PIX_FMT_YUYV == pix->pixelformat || | ||
529 | V4L2_PIX_FMT_UYVY == pix->pixelformat) { | ||
530 | if (rotation_enabled(vout)) { | ||
531 | /* | ||
532 | * ps - Actual pixel size for YUYV/UYVY for | ||
533 | * VRFB/Mirroring is 4 bytes | ||
534 | * vr_ps - Virtually pixel size for YUYV/UYVY is | ||
535 | * 2 bytes | ||
536 | */ | ||
537 | ps = 4; | ||
538 | vr_ps = 2; | ||
539 | } else { | ||
540 | ps = 2; /* otherwise the pixel size is 2 byte */ | ||
541 | } | ||
542 | } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) { | ||
543 | ps = 4; | ||
544 | } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) { | ||
545 | ps = 3; | ||
546 | } | ||
547 | vout->ps = ps; | ||
548 | vout->vr_ps = vr_ps; | ||
549 | |||
550 | if (rotation_enabled(vout)) { | ||
551 | line_length = MAX_PIXELS_PER_LINE; | ||
552 | ctop = (pix->height - crop->height) - crop->top; | ||
553 | cleft = (pix->width - crop->width) - crop->left; | ||
554 | } else { | ||
555 | line_length = pix->width; | ||
556 | } | ||
557 | vout->line_length = line_length; | ||
558 | switch (rotation) { | ||
559 | case dss_rotation_90_degree: | ||
560 | offset = vout->vrfb_context[0].yoffset * | ||
561 | vout->vrfb_context[0].bytespp; | ||
562 | temp_ps = ps / vr_ps; | ||
563 | if (mirroring == 0) { | ||
564 | *cropped_offset = offset + line_length * | ||
565 | temp_ps * cleft + crop->top * temp_ps; | ||
566 | } else { | ||
567 | *cropped_offset = offset + line_length * temp_ps * | ||
568 | cleft + crop->top * temp_ps + (line_length * | ||
569 | ((crop->width / (vr_ps)) - 1) * ps); | ||
570 | } | ||
571 | break; | ||
572 | case dss_rotation_180_degree: | ||
573 | offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset * | ||
574 | vout->vrfb_context[0].bytespp) + | ||
575 | (vout->vrfb_context[0].xoffset * | ||
576 | vout->vrfb_context[0].bytespp)); | ||
577 | if (mirroring == 0) { | ||
578 | *cropped_offset = offset + (line_length * ps * ctop) + | ||
579 | (cleft / vr_ps) * ps; | ||
580 | |||
581 | } else { | ||
582 | *cropped_offset = offset + (line_length * ps * ctop) + | ||
583 | (cleft / vr_ps) * ps + (line_length * | ||
584 | (crop->height - 1) * ps); | ||
585 | } | ||
586 | break; | ||
587 | case dss_rotation_270_degree: | ||
588 | offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset * | ||
589 | vout->vrfb_context[0].bytespp; | ||
590 | temp_ps = ps / vr_ps; | ||
591 | if (mirroring == 0) { | ||
592 | *cropped_offset = offset + line_length * | ||
593 | temp_ps * crop->left + ctop * ps; | ||
594 | } else { | ||
595 | *cropped_offset = offset + line_length * | ||
596 | temp_ps * crop->left + ctop * ps + | ||
597 | (line_length * ((crop->width / vr_ps) - 1) * | ||
598 | ps); | ||
599 | } | ||
600 | break; | ||
601 | case dss_rotation_0_degree: | ||
602 | if (mirroring == 0) { | ||
603 | *cropped_offset = (line_length * ps) * | ||
604 | crop->top + (crop->left / vr_ps) * ps; | ||
605 | } else { | ||
606 | *cropped_offset = (line_length * ps) * | ||
607 | crop->top + (crop->left / vr_ps) * ps + | ||
608 | (line_length * (crop->height - 1) * ps); | ||
609 | } | ||
610 | break; | ||
611 | default: | ||
612 | *cropped_offset = (line_length * ps * crop->top) / | ||
613 | vr_ps + (crop->left * ps) / vr_ps + | ||
614 | ((crop->width / vr_ps) - 1) * ps; | ||
615 | break; | ||
616 | } | ||
617 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", | ||
618 | __func__, *cropped_offset); | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Convert V4L2 pixel format to DSS pixel format | ||
624 | */ | ||
625 | static int video_mode_to_dss_mode(struct omap_vout_device *vout) | ||
626 | { | ||
627 | struct omap_overlay *ovl; | ||
628 | struct omapvideo_info *ovid; | ||
629 | struct v4l2_pix_format *pix = &vout->pix; | ||
630 | enum omap_color_mode mode; | ||
631 | |||
632 | ovid = &vout->vid_info; | ||
633 | ovl = ovid->overlays[0]; | ||
634 | |||
635 | switch (pix->pixelformat) { | ||
636 | case 0: | ||
637 | break; | ||
638 | case V4L2_PIX_FMT_YUYV: | ||
639 | mode = OMAP_DSS_COLOR_YUV2; | ||
640 | break; | ||
641 | case V4L2_PIX_FMT_UYVY: | ||
642 | mode = OMAP_DSS_COLOR_UYVY; | ||
643 | break; | ||
644 | case V4L2_PIX_FMT_RGB565: | ||
645 | mode = OMAP_DSS_COLOR_RGB16; | ||
646 | break; | ||
647 | case V4L2_PIX_FMT_RGB24: | ||
648 | mode = OMAP_DSS_COLOR_RGB24P; | ||
649 | break; | ||
650 | case V4L2_PIX_FMT_RGB32: | ||
651 | mode = (ovl->id == OMAP_DSS_VIDEO1) ? | ||
652 | OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32; | ||
653 | break; | ||
654 | case V4L2_PIX_FMT_BGR32: | ||
655 | mode = OMAP_DSS_COLOR_RGBX32; | ||
656 | break; | ||
657 | default: | ||
658 | mode = -EINVAL; | ||
659 | } | ||
660 | return mode; | ||
661 | } | ||
662 | |||
663 | /* | ||
664 | * Setup the overlay | ||
665 | */ | ||
666 | int omapvid_setup_overlay(struct omap_vout_device *vout, | ||
667 | struct omap_overlay *ovl, int posx, int posy, int outw, | ||
668 | int outh, u32 addr) | ||
669 | { | ||
670 | int ret = 0; | ||
671 | struct omap_overlay_info info; | ||
672 | int cropheight, cropwidth, pixheight, pixwidth; | ||
673 | |||
674 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 && | ||
675 | (outw != vout->pix.width || outh != vout->pix.height)) { | ||
676 | ret = -EINVAL; | ||
677 | goto setup_ovl_err; | ||
678 | } | ||
679 | |||
680 | vout->dss_mode = video_mode_to_dss_mode(vout); | ||
681 | if (vout->dss_mode == -EINVAL) { | ||
682 | ret = -EINVAL; | ||
683 | goto setup_ovl_err; | ||
684 | } | ||
685 | |||
686 | /* Setup the input plane parameters according to | ||
687 | * rotation value selected. | ||
688 | */ | ||
689 | if (rotate_90_or_270(vout)) { | ||
690 | cropheight = vout->crop.width; | ||
691 | cropwidth = vout->crop.height; | ||
692 | pixheight = vout->pix.width; | ||
693 | pixwidth = vout->pix.height; | ||
694 | } else { | ||
695 | cropheight = vout->crop.height; | ||
696 | cropwidth = vout->crop.width; | ||
697 | pixheight = vout->pix.height; | ||
698 | pixwidth = vout->pix.width; | ||
699 | } | ||
700 | |||
701 | ovl->get_overlay_info(ovl, &info); | ||
702 | info.paddr = addr; | ||
703 | info.vaddr = NULL; | ||
704 | info.width = cropwidth; | ||
705 | info.height = cropheight; | ||
706 | info.color_mode = vout->dss_mode; | ||
707 | info.mirror = vout->mirror; | ||
708 | info.pos_x = posx; | ||
709 | info.pos_y = posy; | ||
710 | info.out_width = outw; | ||
711 | info.out_height = outh; | ||
712 | info.global_alpha = vout->win.global_alpha; | ||
713 | if (!rotation_enabled(vout)) { | ||
714 | info.rotation = 0; | ||
715 | info.rotation_type = OMAP_DSS_ROT_DMA; | ||
716 | info.screen_width = pixwidth; | ||
717 | } else { | ||
718 | info.rotation = vout->rotation; | ||
719 | info.rotation_type = OMAP_DSS_ROT_VRFB; | ||
720 | info.screen_width = 2048; | ||
721 | } | ||
722 | |||
723 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, | ||
724 | "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n" | ||
725 | "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n" | ||
726 | "out_height=%d rotation_type=%d screen_width=%d\n", | ||
727 | __func__, info.enabled, info.paddr, info.width, info.height, | ||
728 | info.color_mode, info.rotation, info.mirror, info.pos_x, | ||
729 | info.pos_y, info.out_width, info.out_height, info.rotation_type, | ||
730 | info.screen_width); | ||
731 | |||
732 | ret = ovl->set_overlay_info(ovl, &info); | ||
733 | if (ret) | ||
734 | goto setup_ovl_err; | ||
735 | |||
736 | return 0; | ||
737 | |||
738 | setup_ovl_err: | ||
739 | v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n"); | ||
740 | return ret; | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * Initialize the overlay structure | ||
745 | */ | ||
746 | int omapvid_init(struct omap_vout_device *vout, u32 addr) | ||
747 | { | ||
748 | int ret = 0, i; | ||
749 | struct v4l2_window *win; | ||
750 | struct omap_overlay *ovl; | ||
751 | int posx, posy, outw, outh, temp; | ||
752 | struct omap_video_timings *timing; | ||
753 | struct omapvideo_info *ovid = &vout->vid_info; | ||
754 | |||
755 | win = &vout->win; | ||
756 | for (i = 0; i < ovid->num_overlays; i++) { | ||
757 | ovl = ovid->overlays[i]; | ||
758 | if (!ovl->manager || !ovl->manager->device) | ||
759 | return -EINVAL; | ||
760 | |||
761 | timing = &ovl->manager->device->panel.timings; | ||
762 | |||
763 | outw = win->w.width; | ||
764 | outh = win->w.height; | ||
765 | switch (vout->rotation) { | ||
766 | case dss_rotation_90_degree: | ||
767 | /* Invert the height and width for 90 | ||
768 | * and 270 degree rotation | ||
769 | */ | ||
770 | temp = outw; | ||
771 | outw = outh; | ||
772 | outh = temp; | ||
773 | posy = (timing->y_res - win->w.width) - win->w.left; | ||
774 | posx = win->w.top; | ||
775 | break; | ||
776 | |||
777 | case dss_rotation_180_degree: | ||
778 | posx = (timing->x_res - win->w.width) - win->w.left; | ||
779 | posy = (timing->y_res - win->w.height) - win->w.top; | ||
780 | break; | ||
781 | |||
782 | case dss_rotation_270_degree: | ||
783 | temp = outw; | ||
784 | outw = outh; | ||
785 | outh = temp; | ||
786 | posy = win->w.left; | ||
787 | posx = (timing->x_res - win->w.height) - win->w.top; | ||
788 | break; | ||
789 | |||
790 | default: | ||
791 | posx = win->w.left; | ||
792 | posy = win->w.top; | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | ret = omapvid_setup_overlay(vout, ovl, posx, posy, | ||
797 | outw, outh, addr); | ||
798 | if (ret) | ||
799 | goto omapvid_init_err; | ||
800 | } | ||
801 | return 0; | ||
802 | |||
803 | omapvid_init_err: | ||
804 | v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n"); | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | /* | ||
809 | * Apply the changes set the go bit of DSS | ||
810 | */ | ||
811 | int omapvid_apply_changes(struct omap_vout_device *vout) | ||
812 | { | ||
813 | int i; | ||
814 | struct omap_overlay *ovl; | ||
815 | struct omapvideo_info *ovid = &vout->vid_info; | ||
816 | |||
817 | for (i = 0; i < ovid->num_overlays; i++) { | ||
818 | ovl = ovid->overlays[i]; | ||
819 | if (!ovl->manager || !ovl->manager->device) | ||
820 | return -EINVAL; | ||
821 | ovl->manager->apply(ovl->manager); | ||
822 | } | ||
823 | |||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | void omap_vout_isr(void *arg, unsigned int irqstatus) | ||
828 | { | ||
829 | int ret; | ||
830 | u32 addr, fid; | ||
831 | struct omap_overlay *ovl; | ||
832 | struct timeval timevalue; | ||
833 | struct omapvideo_info *ovid; | ||
834 | struct omap_dss_device *cur_display; | ||
835 | struct omap_vout_device *vout = (struct omap_vout_device *)arg; | ||
836 | |||
837 | if (!vout->streaming) | ||
838 | return; | ||
839 | |||
840 | ovid = &vout->vid_info; | ||
841 | ovl = ovid->overlays[0]; | ||
842 | /* get the display device attached to the overlay */ | ||
843 | if (!ovl->manager || !ovl->manager->device) | ||
844 | return; | ||
845 | |||
846 | cur_display = ovl->manager->device; | ||
847 | |||
848 | spin_lock(&vout->vbq_lock); | ||
849 | do_gettimeofday(&timevalue); | ||
850 | if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) { | ||
851 | if (!(irqstatus & DISPC_IRQ_VSYNC)) | ||
852 | goto vout_isr_err; | ||
853 | |||
854 | if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { | ||
855 | vout->cur_frm->ts = timevalue; | ||
856 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
857 | wake_up_interruptible(&vout->cur_frm->done); | ||
858 | vout->cur_frm = vout->next_frm; | ||
859 | } | ||
860 | vout->first_int = 0; | ||
861 | if (list_empty(&vout->dma_queue)) | ||
862 | goto vout_isr_err; | ||
863 | |||
864 | vout->next_frm = list_entry(vout->dma_queue.next, | ||
865 | struct videobuf_buffer, queue); | ||
866 | list_del(&vout->next_frm->queue); | ||
867 | |||
868 | vout->next_frm->state = VIDEOBUF_ACTIVE; | ||
869 | |||
870 | addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] | ||
871 | + vout->cropped_offset; | ||
872 | |||
873 | /* First save the configuration in ovelray structure */ | ||
874 | ret = omapvid_init(vout, addr); | ||
875 | if (ret) | ||
876 | printk(KERN_ERR VOUT_NAME | ||
877 | "failed to set overlay info\n"); | ||
878 | /* Enable the pipeline and set the Go bit */ | ||
879 | ret = omapvid_apply_changes(vout); | ||
880 | if (ret) | ||
881 | printk(KERN_ERR VOUT_NAME "failed to change mode\n"); | ||
882 | } else { | ||
883 | |||
884 | if (vout->first_int) { | ||
885 | vout->first_int = 0; | ||
886 | goto vout_isr_err; | ||
887 | } | ||
888 | if (irqstatus & DISPC_IRQ_EVSYNC_ODD) | ||
889 | fid = 1; | ||
890 | else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) | ||
891 | fid = 0; | ||
892 | else | ||
893 | goto vout_isr_err; | ||
894 | |||
895 | vout->field_id ^= 1; | ||
896 | if (fid != vout->field_id) { | ||
897 | if (0 == fid) | ||
898 | vout->field_id = fid; | ||
899 | |||
900 | goto vout_isr_err; | ||
901 | } | ||
902 | if (0 == fid) { | ||
903 | if (vout->cur_frm == vout->next_frm) | ||
904 | goto vout_isr_err; | ||
905 | |||
906 | vout->cur_frm->ts = timevalue; | ||
907 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
908 | wake_up_interruptible(&vout->cur_frm->done); | ||
909 | vout->cur_frm = vout->next_frm; | ||
910 | } else if (1 == fid) { | ||
911 | if (list_empty(&vout->dma_queue) || | ||
912 | (vout->cur_frm != vout->next_frm)) | ||
913 | goto vout_isr_err; | ||
914 | |||
915 | vout->next_frm = list_entry(vout->dma_queue.next, | ||
916 | struct videobuf_buffer, queue); | ||
917 | list_del(&vout->next_frm->queue); | ||
918 | |||
919 | vout->next_frm->state = VIDEOBUF_ACTIVE; | ||
920 | addr = (unsigned long) | ||
921 | vout->queued_buf_addr[vout->next_frm->i] + | ||
922 | vout->cropped_offset; | ||
923 | /* First save the configuration in ovelray structure */ | ||
924 | ret = omapvid_init(vout, addr); | ||
925 | if (ret) | ||
926 | printk(KERN_ERR VOUT_NAME | ||
927 | "failed to set overlay info\n"); | ||
928 | /* Enable the pipeline and set the Go bit */ | ||
929 | ret = omapvid_apply_changes(vout); | ||
930 | if (ret) | ||
931 | printk(KERN_ERR VOUT_NAME | ||
932 | "failed to change mode\n"); | ||
933 | } | ||
934 | |||
935 | } | ||
936 | |||
937 | vout_isr_err: | ||
938 | spin_unlock(&vout->vbq_lock); | ||
939 | } | ||
940 | |||
941 | |||
942 | /* Video buffer call backs */ | ||
943 | |||
944 | /* | ||
945 | * Buffer setup function is called by videobuf layer when REQBUF ioctl is | ||
946 | * called. This is used to setup buffers and return size and count of | ||
947 | * buffers allocated. After the call to this buffer, videobuf layer will | ||
948 | * setup buffer queue depending on the size and count of buffers | ||
949 | */ | ||
950 | static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | ||
951 | unsigned int *size) | ||
952 | { | ||
953 | int startindex = 0, i, j; | ||
954 | u32 phy_addr = 0, virt_addr = 0; | ||
955 | struct omap_vout_device *vout = q->priv_data; | ||
956 | |||
957 | if (!vout) | ||
958 | return -EINVAL; | ||
959 | |||
960 | if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) | ||
961 | return -EINVAL; | ||
962 | |||
963 | startindex = (vout->vid == OMAP_VIDEO1) ? | ||
964 | video1_numbuffers : video2_numbuffers; | ||
965 | if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) | ||
966 | *count = startindex; | ||
967 | |||
968 | if ((rotation_enabled(vout)) && *count > VRFB_NUM_BUFS) | ||
969 | *count = VRFB_NUM_BUFS; | ||
970 | |||
971 | /* If rotation is enabled, allocate memory for VRFB space also */ | ||
972 | if (rotation_enabled(vout)) | ||
973 | if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) | ||
974 | return -ENOMEM; | ||
975 | |||
976 | if (V4L2_MEMORY_MMAP != vout->memory) | ||
977 | return 0; | ||
978 | |||
979 | /* Now allocated the V4L2 buffers */ | ||
980 | *size = PAGE_ALIGN(vout->pix.width * vout->pix.height * vout->bpp); | ||
981 | startindex = (vout->vid == OMAP_VIDEO1) ? | ||
982 | video1_numbuffers : video2_numbuffers; | ||
983 | |||
984 | for (i = startindex; i < *count; i++) { | ||
985 | vout->buffer_size = *size; | ||
986 | |||
987 | virt_addr = omap_vout_alloc_buffer(vout->buffer_size, | ||
988 | &phy_addr); | ||
989 | if (!virt_addr) { | ||
990 | if (!rotation_enabled(vout)) | ||
991 | break; | ||
992 | /* Free the VRFB buffers if no space for V4L2 buffers */ | ||
993 | for (j = i; j < *count; j++) { | ||
994 | omap_vout_free_buffer( | ||
995 | vout->smsshado_virt_addr[j], | ||
996 | vout->smsshado_size); | ||
997 | vout->smsshado_virt_addr[j] = 0; | ||
998 | vout->smsshado_phy_addr[j] = 0; | ||
999 | } | ||
1000 | } | ||
1001 | vout->buf_virt_addr[i] = virt_addr; | ||
1002 | vout->buf_phy_addr[i] = phy_addr; | ||
1003 | } | ||
1004 | *count = vout->buffer_allocated = i; | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
1010 | * Free the V4L2 buffers additionally allocated than default | ||
1011 | * number of buffers and free all the VRFB buffers | ||
1012 | */ | ||
1013 | static void omap_vout_free_allbuffers(struct omap_vout_device *vout) | ||
1014 | { | ||
1015 | int num_buffers = 0, i; | ||
1016 | |||
1017 | num_buffers = (vout->vid == OMAP_VIDEO1) ? | ||
1018 | video1_numbuffers : video2_numbuffers; | ||
1019 | |||
1020 | for (i = num_buffers; i < vout->buffer_allocated; i++) { | ||
1021 | if (vout->buf_virt_addr[i]) | ||
1022 | omap_vout_free_buffer(vout->buf_virt_addr[i], | ||
1023 | vout->buffer_size); | ||
1024 | |||
1025 | vout->buf_virt_addr[i] = 0; | ||
1026 | vout->buf_phy_addr[i] = 0; | ||
1027 | } | ||
1028 | /* Free the VRFB buffers only if they are allocated | ||
1029 | * during reqbufs. Don't free if init time allocated | ||
1030 | */ | ||
1031 | if (!vout->vrfb_static_allocation) { | ||
1032 | for (i = 0; i < VRFB_NUM_BUFS; i++) { | ||
1033 | if (vout->smsshado_virt_addr[i]) { | ||
1034 | omap_vout_free_buffer( | ||
1035 | vout->smsshado_virt_addr[i], | ||
1036 | vout->smsshado_size); | ||
1037 | vout->smsshado_virt_addr[i] = 0; | ||
1038 | vout->smsshado_phy_addr[i] = 0; | ||
1039 | } | ||
1040 | } | ||
1041 | } | ||
1042 | vout->buffer_allocated = num_buffers; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * This function will be called when VIDIOC_QBUF ioctl is called. | ||
1047 | * It prepare buffers before give out for the display. This function | ||
1048 | * converts user space virtual address into physical address if userptr memory | ||
1049 | * exchange mechanism is used. If rotation is enabled, it copies entire | ||
1050 | * buffer into VRFB memory space before giving it to the DSS. | ||
1051 | */ | ||
1052 | static int omap_vout_buffer_prepare(struct videobuf_queue *q, | ||
1053 | struct videobuf_buffer *vb, | ||
1054 | enum v4l2_field field) | ||
1055 | { | ||
1056 | struct vid_vrfb_dma *tx; | ||
1057 | enum dss_rotation rotation; | ||
1058 | struct videobuf_dmabuf *dmabuf = NULL; | ||
1059 | struct omap_vout_device *vout = q->priv_data; | ||
1060 | u32 dest_frame_index = 0, src_element_index = 0; | ||
1061 | u32 dest_element_index = 0, src_frame_index = 0; | ||
1062 | u32 elem_count = 0, frame_count = 0, pixsize = 2; | ||
1063 | |||
1064 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
1065 | vb->width = vout->pix.width; | ||
1066 | vb->height = vout->pix.height; | ||
1067 | vb->size = vb->width * vb->height * vout->bpp; | ||
1068 | vb->field = field; | ||
1069 | } | ||
1070 | vb->state = VIDEOBUF_PREPARED; | ||
1071 | /* if user pointer memory mechanism is used, get the physical | ||
1072 | * address of the buffer | ||
1073 | */ | ||
1074 | if (V4L2_MEMORY_USERPTR == vb->memory) { | ||
1075 | if (0 == vb->baddr) | ||
1076 | return -EINVAL; | ||
1077 | /* Virtual address */ | ||
1078 | /* priv points to struct videobuf_pci_sg_memory. But we went | ||
1079 | * pointer to videobuf_dmabuf, which is member of | ||
1080 | * videobuf_pci_sg_memory */ | ||
1081 | dmabuf = videobuf_to_dma(q->bufs[vb->i]); | ||
1082 | dmabuf->vmalloc = (void *) vb->baddr; | ||
1083 | |||
1084 | /* Physical address */ | ||
1085 | dmabuf->bus_addr = | ||
1086 | (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr); | ||
1087 | } | ||
1088 | |||
1089 | if (!rotation_enabled(vout)) { | ||
1090 | dmabuf = videobuf_to_dma(q->bufs[vb->i]); | ||
1091 | vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr; | ||
1092 | return 0; | ||
1093 | } | ||
1094 | dmabuf = videobuf_to_dma(q->bufs[vb->i]); | ||
1095 | /* If rotation is enabled, copy input buffer into VRFB | ||
1096 | * memory space using DMA. We are copying input buffer | ||
1097 | * into VRFB memory space of desired angle and DSS will | ||
1098 | * read image VRFB memory for 0 degree angle | ||
1099 | */ | ||
1100 | pixsize = vout->bpp * vout->vrfb_bpp; | ||
1101 | /* | ||
1102 | * DMA transfer in double index mode | ||
1103 | */ | ||
1104 | |||
1105 | /* Frame index */ | ||
1106 | dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - | ||
1107 | (vout->pix.width * vout->bpp)) + 1; | ||
1108 | |||
1109 | /* Source and destination parameters */ | ||
1110 | src_element_index = 0; | ||
1111 | src_frame_index = 0; | ||
1112 | dest_element_index = 1; | ||
1113 | /* Number of elements per frame */ | ||
1114 | elem_count = vout->pix.width * vout->bpp; | ||
1115 | frame_count = vout->pix.height; | ||
1116 | tx = &vout->vrfb_dma_tx; | ||
1117 | tx->tx_status = 0; | ||
1118 | omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
1119 | (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, | ||
1120 | tx->dev_id, 0x0); | ||
1121 | /* src_port required only for OMAP1 */ | ||
1122 | omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
1123 | dmabuf->bus_addr, src_element_index, src_frame_index); | ||
1124 | /*set dma source burst mode for VRFB */ | ||
1125 | omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); | ||
1126 | rotation = calc_rotation(vout); | ||
1127 | |||
1128 | /* dest_port required only for OMAP1 */ | ||
1129 | omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, | ||
1130 | vout->vrfb_context[vb->i].paddr[0], dest_element_index, | ||
1131 | dest_frame_index); | ||
1132 | /*set dma dest burst mode for VRFB */ | ||
1133 | omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); | ||
1134 | omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); | ||
1135 | |||
1136 | omap_start_dma(tx->dma_ch); | ||
1137 | interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT); | ||
1138 | |||
1139 | if (tx->tx_status == 0) { | ||
1140 | omap_stop_dma(tx->dma_ch); | ||
1141 | return -EINVAL; | ||
1142 | } | ||
1143 | /* Store buffers physical address into an array. Addresses | ||
1144 | * from this array will be used to configure DSS */ | ||
1145 | vout->queued_buf_addr[vb->i] = (u8 *) | ||
1146 | vout->vrfb_context[vb->i].paddr[rotation]; | ||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | /* | ||
1151 | * Buffer queue funtion will be called from the videobuf layer when _QBUF | ||
1152 | * ioctl is called. It is used to enqueue buffer, which is ready to be | ||
1153 | * displayed. | ||
1154 | */ | ||
1155 | static void omap_vout_buffer_queue(struct videobuf_queue *q, | ||
1156 | struct videobuf_buffer *vb) | ||
1157 | { | ||
1158 | struct omap_vout_device *vout = q->priv_data; | ||
1159 | |||
1160 | /* Driver is also maintainig a queue. So enqueue buffer in the driver | ||
1161 | * queue */ | ||
1162 | list_add_tail(&vb->queue, &vout->dma_queue); | ||
1163 | |||
1164 | vb->state = VIDEOBUF_QUEUED; | ||
1165 | } | ||
1166 | |||
1167 | /* | ||
1168 | * Buffer release function is called from videobuf layer to release buffer | ||
1169 | * which are already allocated | ||
1170 | */ | ||
1171 | static void omap_vout_buffer_release(struct videobuf_queue *q, | ||
1172 | struct videobuf_buffer *vb) | ||
1173 | { | ||
1174 | struct omap_vout_device *vout = q->priv_data; | ||
1175 | |||
1176 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
1177 | |||
1178 | if (V4L2_MEMORY_MMAP != vout->memory) | ||
1179 | return; | ||
1180 | } | ||
1181 | |||
1182 | /* | ||
1183 | * File operations | ||
1184 | */ | ||
1185 | static void omap_vout_vm_open(struct vm_area_struct *vma) | ||
1186 | { | ||
1187 | struct omap_vout_device *vout = vma->vm_private_data; | ||
1188 | |||
1189 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, | ||
1190 | "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); | ||
1191 | vout->mmap_count++; | ||
1192 | } | ||
1193 | |||
1194 | static void omap_vout_vm_close(struct vm_area_struct *vma) | ||
1195 | { | ||
1196 | struct omap_vout_device *vout = vma->vm_private_data; | ||
1197 | |||
1198 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, | ||
1199 | "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); | ||
1200 | vout->mmap_count--; | ||
1201 | } | ||
1202 | |||
1203 | static struct vm_operations_struct omap_vout_vm_ops = { | ||
1204 | .open = omap_vout_vm_open, | ||
1205 | .close = omap_vout_vm_close, | ||
1206 | }; | ||
1207 | |||
1208 | static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) | ||
1209 | { | ||
1210 | int i; | ||
1211 | void *pos; | ||
1212 | unsigned long start = vma->vm_start; | ||
1213 | unsigned long size = (vma->vm_end - vma->vm_start); | ||
1214 | struct videobuf_dmabuf *dmabuf = NULL; | ||
1215 | struct omap_vout_device *vout = file->private_data; | ||
1216 | struct videobuf_queue *q = &vout->vbq; | ||
1217 | |||
1218 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, | ||
1219 | " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__, | ||
1220 | vma->vm_pgoff, vma->vm_start, vma->vm_end); | ||
1221 | |||
1222 | /* look for the buffer to map */ | ||
1223 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
1224 | if (NULL == q->bufs[i]) | ||
1225 | continue; | ||
1226 | if (V4L2_MEMORY_MMAP != q->bufs[i]->memory) | ||
1227 | continue; | ||
1228 | if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT)) | ||
1229 | break; | ||
1230 | } | ||
1231 | |||
1232 | if (VIDEO_MAX_FRAME == i) { | ||
1233 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, | ||
1234 | "offset invalid [offset=0x%lx]\n", | ||
1235 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
1236 | return -EINVAL; | ||
1237 | } | ||
1238 | q->bufs[i]->baddr = vma->vm_start; | ||
1239 | |||
1240 | vma->vm_flags |= VM_RESERVED; | ||
1241 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | ||
1242 | vma->vm_ops = &omap_vout_vm_ops; | ||
1243 | vma->vm_private_data = (void *) vout; | ||
1244 | dmabuf = videobuf_to_dma(q->bufs[i]); | ||
1245 | pos = dmabuf->vmalloc; | ||
1246 | vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT; | ||
1247 | while (size > 0) { | ||
1248 | unsigned long pfn; | ||
1249 | pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT; | ||
1250 | if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) | ||
1251 | return -EAGAIN; | ||
1252 | start += PAGE_SIZE; | ||
1253 | pos += PAGE_SIZE; | ||
1254 | size -= PAGE_SIZE; | ||
1255 | } | ||
1256 | vout->mmap_count++; | ||
1257 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); | ||
1258 | |||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | static int omap_vout_release(struct file *file) | ||
1263 | { | ||
1264 | unsigned int ret, i; | ||
1265 | struct videobuf_queue *q; | ||
1266 | struct omapvideo_info *ovid; | ||
1267 | struct omap_vout_device *vout = file->private_data; | ||
1268 | |||
1269 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); | ||
1270 | ovid = &vout->vid_info; | ||
1271 | |||
1272 | if (!vout) | ||
1273 | return 0; | ||
1274 | |||
1275 | q = &vout->vbq; | ||
1276 | /* Disable all the overlay managers connected with this interface */ | ||
1277 | for (i = 0; i < ovid->num_overlays; i++) { | ||
1278 | struct omap_overlay *ovl = ovid->overlays[i]; | ||
1279 | if (ovl->manager && ovl->manager->device) { | ||
1280 | struct omap_overlay_info info; | ||
1281 | ovl->get_overlay_info(ovl, &info); | ||
1282 | info.enabled = 0; | ||
1283 | ovl->set_overlay_info(ovl, &info); | ||
1284 | } | ||
1285 | } | ||
1286 | /* Turn off the pipeline */ | ||
1287 | ret = omapvid_apply_changes(vout); | ||
1288 | if (ret) | ||
1289 | v4l2_warn(&vout->vid_dev->v4l2_dev, | ||
1290 | "Unable to apply changes\n"); | ||
1291 | |||
1292 | /* Free all buffers */ | ||
1293 | omap_vout_free_allbuffers(vout); | ||
1294 | videobuf_mmap_free(q); | ||
1295 | |||
1296 | /* Even if apply changes fails we should continue | ||
1297 | freeing allocated memeory */ | ||
1298 | if (vout->streaming) { | ||
1299 | u32 mask = 0; | ||
1300 | |||
1301 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | | ||
1302 | DISPC_IRQ_EVSYNC_ODD; | ||
1303 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); | ||
1304 | vout->streaming = 0; | ||
1305 | |||
1306 | videobuf_streamoff(q); | ||
1307 | videobuf_queue_cancel(q); | ||
1308 | } | ||
1309 | |||
1310 | if (vout->mmap_count != 0) | ||
1311 | vout->mmap_count = 0; | ||
1312 | |||
1313 | vout->opened -= 1; | ||
1314 | file->private_data = NULL; | ||
1315 | |||
1316 | if (vout->buffer_allocated) | ||
1317 | videobuf_mmap_free(q); | ||
1318 | |||
1319 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); | ||
1320 | return ret; | ||
1321 | } | ||
1322 | |||
1323 | static int omap_vout_open(struct file *file) | ||
1324 | { | ||
1325 | struct videobuf_queue *q; | ||
1326 | struct omap_vout_device *vout = NULL; | ||
1327 | |||
1328 | vout = video_drvdata(file); | ||
1329 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); | ||
1330 | |||
1331 | if (vout == NULL) | ||
1332 | return -ENODEV; | ||
1333 | |||
1334 | /* for now, we only support single open */ | ||
1335 | if (vout->opened) | ||
1336 | return -EBUSY; | ||
1337 | |||
1338 | vout->opened += 1; | ||
1339 | |||
1340 | file->private_data = vout; | ||
1341 | vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1342 | |||
1343 | q = &vout->vbq; | ||
1344 | video_vbq_ops.buf_setup = omap_vout_buffer_setup; | ||
1345 | video_vbq_ops.buf_prepare = omap_vout_buffer_prepare; | ||
1346 | video_vbq_ops.buf_release = omap_vout_buffer_release; | ||
1347 | video_vbq_ops.buf_queue = omap_vout_buffer_queue; | ||
1348 | spin_lock_init(&vout->vbq_lock); | ||
1349 | |||
1350 | videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock, | ||
1351 | vout->type, V4L2_FIELD_NONE, | ||
1352 | sizeof(struct videobuf_buffer), vout); | ||
1353 | |||
1354 | v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | /* | ||
1359 | * V4L2 ioctls | ||
1360 | */ | ||
1361 | static int vidioc_querycap(struct file *file, void *fh, | ||
1362 | struct v4l2_capability *cap) | ||
1363 | { | ||
1364 | struct omap_vout_device *vout = fh; | ||
1365 | |||
1366 | strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); | ||
1367 | strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); | ||
1368 | cap->bus_info[0] = '\0'; | ||
1369 | cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; | ||
1370 | |||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, | ||
1375 | struct v4l2_fmtdesc *fmt) | ||
1376 | { | ||
1377 | int index = fmt->index; | ||
1378 | enum v4l2_buf_type type = fmt->type; | ||
1379 | |||
1380 | fmt->index = index; | ||
1381 | fmt->type = type; | ||
1382 | if (index >= NUM_OUTPUT_FORMATS) | ||
1383 | return -EINVAL; | ||
1384 | |||
1385 | fmt->flags = omap_formats[index].flags; | ||
1386 | strlcpy(fmt->description, omap_formats[index].description, | ||
1387 | sizeof(fmt->description)); | ||
1388 | fmt->pixelformat = omap_formats[index].pixelformat; | ||
1389 | |||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | static int vidioc_g_fmt_vid_out(struct file *file, void *fh, | ||
1394 | struct v4l2_format *f) | ||
1395 | { | ||
1396 | struct omap_vout_device *vout = fh; | ||
1397 | |||
1398 | f->fmt.pix = vout->pix; | ||
1399 | return 0; | ||
1400 | |||
1401 | } | ||
1402 | |||
1403 | static int vidioc_try_fmt_vid_out(struct file *file, void *fh, | ||
1404 | struct v4l2_format *f) | ||
1405 | { | ||
1406 | struct omap_overlay *ovl; | ||
1407 | struct omapvideo_info *ovid; | ||
1408 | struct omap_video_timings *timing; | ||
1409 | struct omap_vout_device *vout = fh; | ||
1410 | |||
1411 | ovid = &vout->vid_info; | ||
1412 | ovl = ovid->overlays[0]; | ||
1413 | |||
1414 | if (!ovl->manager || !ovl->manager->device) | ||
1415 | return -EINVAL; | ||
1416 | /* get the display device attached to the overlay */ | ||
1417 | timing = &ovl->manager->device->panel.timings; | ||
1418 | |||
1419 | vout->fbuf.fmt.height = timing->y_res; | ||
1420 | vout->fbuf.fmt.width = timing->x_res; | ||
1421 | |||
1422 | omap_vout_try_format(&f->fmt.pix); | ||
1423 | return 0; | ||
1424 | } | ||
1425 | |||
1426 | static int vidioc_s_fmt_vid_out(struct file *file, void *fh, | ||
1427 | struct v4l2_format *f) | ||
1428 | { | ||
1429 | int ret, bpp; | ||
1430 | struct omap_overlay *ovl; | ||
1431 | struct omapvideo_info *ovid; | ||
1432 | struct omap_video_timings *timing; | ||
1433 | struct omap_vout_device *vout = fh; | ||
1434 | |||
1435 | if (vout->streaming) | ||
1436 | return -EBUSY; | ||
1437 | |||
1438 | mutex_lock(&vout->lock); | ||
1439 | |||
1440 | ovid = &vout->vid_info; | ||
1441 | ovl = ovid->overlays[0]; | ||
1442 | |||
1443 | /* get the display device attached to the overlay */ | ||
1444 | if (!ovl->manager || !ovl->manager->device) { | ||
1445 | ret = -EINVAL; | ||
1446 | goto s_fmt_vid_out_exit; | ||
1447 | } | ||
1448 | timing = &ovl->manager->device->panel.timings; | ||
1449 | |||
1450 | /* We dont support RGB24-packed mode if vrfb rotation | ||
1451 | * is enabled*/ | ||
1452 | if ((rotation_enabled(vout)) && | ||
1453 | f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { | ||
1454 | ret = -EINVAL; | ||
1455 | goto s_fmt_vid_out_exit; | ||
1456 | } | ||
1457 | |||
1458 | /* get the framebuffer parameters */ | ||
1459 | |||
1460 | if (rotate_90_or_270(vout)) { | ||
1461 | vout->fbuf.fmt.height = timing->x_res; | ||
1462 | vout->fbuf.fmt.width = timing->y_res; | ||
1463 | } else { | ||
1464 | vout->fbuf.fmt.height = timing->y_res; | ||
1465 | vout->fbuf.fmt.width = timing->x_res; | ||
1466 | } | ||
1467 | |||
1468 | /* change to samller size is OK */ | ||
1469 | |||
1470 | bpp = omap_vout_try_format(&f->fmt.pix); | ||
1471 | f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp; | ||
1472 | |||
1473 | /* try & set the new output format */ | ||
1474 | vout->bpp = bpp; | ||
1475 | vout->pix = f->fmt.pix; | ||
1476 | vout->vrfb_bpp = 1; | ||
1477 | |||
1478 | /* If YUYV then vrfb bpp is 2, for others its 1 */ | ||
1479 | if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || | ||
1480 | V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) | ||
1481 | vout->vrfb_bpp = 2; | ||
1482 | |||
1483 | /* set default crop and win */ | ||
1484 | omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win); | ||
1485 | |||
1486 | /* Save the changes in the overlay strcuture */ | ||
1487 | ret = omapvid_init(vout, 0); | ||
1488 | if (ret) { | ||
1489 | v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); | ||
1490 | goto s_fmt_vid_out_exit; | ||
1491 | } | ||
1492 | |||
1493 | ret = 0; | ||
1494 | |||
1495 | s_fmt_vid_out_exit: | ||
1496 | mutex_unlock(&vout->lock); | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, | ||
1501 | struct v4l2_format *f) | ||
1502 | { | ||
1503 | int ret = 0; | ||
1504 | struct omap_vout_device *vout = fh; | ||
1505 | struct v4l2_window *win = &f->fmt.win; | ||
1506 | |||
1507 | ret = omap_vout_try_window(&vout->fbuf, win); | ||
1508 | |||
1509 | if (!ret) { | ||
1510 | if (vout->vid == OMAP_VIDEO1) | ||
1511 | win->global_alpha = 255; | ||
1512 | else | ||
1513 | win->global_alpha = f->fmt.win.global_alpha; | ||
1514 | } | ||
1515 | |||
1516 | return ret; | ||
1517 | } | ||
1518 | |||
1519 | static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, | ||
1520 | struct v4l2_format *f) | ||
1521 | { | ||
1522 | int ret = 0; | ||
1523 | struct omap_overlay *ovl; | ||
1524 | struct omapvideo_info *ovid; | ||
1525 | struct omap_vout_device *vout = fh; | ||
1526 | struct v4l2_window *win = &f->fmt.win; | ||
1527 | |||
1528 | mutex_lock(&vout->lock); | ||
1529 | ovid = &vout->vid_info; | ||
1530 | ovl = ovid->overlays[0]; | ||
1531 | |||
1532 | ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); | ||
1533 | if (!ret) { | ||
1534 | /* Video1 plane does not support global alpha */ | ||
1535 | if (ovl->id == OMAP_DSS_VIDEO1) | ||
1536 | vout->win.global_alpha = 255; | ||
1537 | else | ||
1538 | vout->win.global_alpha = f->fmt.win.global_alpha; | ||
1539 | |||
1540 | vout->win.chromakey = f->fmt.win.chromakey; | ||
1541 | } | ||
1542 | mutex_unlock(&vout->lock); | ||
1543 | return ret; | ||
1544 | } | ||
1545 | |||
1546 | static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, | ||
1547 | struct v4l2_fmtdesc *fmt) | ||
1548 | { | ||
1549 | int index = fmt->index; | ||
1550 | enum v4l2_buf_type type = fmt->type; | ||
1551 | |||
1552 | fmt->index = index; | ||
1553 | fmt->type = type; | ||
1554 | if (index >= NUM_OUTPUT_FORMATS) | ||
1555 | return -EINVAL; | ||
1556 | |||
1557 | fmt->flags = omap_formats[index].flags; | ||
1558 | strlcpy(fmt->description, omap_formats[index].description, | ||
1559 | sizeof(fmt->description)); | ||
1560 | fmt->pixelformat = omap_formats[index].pixelformat; | ||
1561 | return 0; | ||
1562 | } | ||
1563 | |||
1564 | static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, | ||
1565 | struct v4l2_format *f) | ||
1566 | { | ||
1567 | u32 key_value = 0; | ||
1568 | struct omap_overlay *ovl; | ||
1569 | struct omapvideo_info *ovid; | ||
1570 | struct omap_vout_device *vout = fh; | ||
1571 | struct omap_overlay_manager_info info; | ||
1572 | struct v4l2_window *win = &f->fmt.win; | ||
1573 | |||
1574 | ovid = &vout->vid_info; | ||
1575 | ovl = ovid->overlays[0]; | ||
1576 | |||
1577 | win->w = vout->win.w; | ||
1578 | win->field = vout->win.field; | ||
1579 | win->global_alpha = vout->win.global_alpha; | ||
1580 | |||
1581 | if (ovl->manager && ovl->manager->get_manager_info) { | ||
1582 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
1583 | key_value = info.trans_key; | ||
1584 | } | ||
1585 | win->chromakey = key_value; | ||
1586 | return 0; | ||
1587 | } | ||
1588 | |||
1589 | static int vidioc_cropcap(struct file *file, void *fh, | ||
1590 | struct v4l2_cropcap *cropcap) | ||
1591 | { | ||
1592 | struct omap_vout_device *vout = fh; | ||
1593 | struct v4l2_pix_format *pix = &vout->pix; | ||
1594 | |||
1595 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1596 | return -EINVAL; | ||
1597 | |||
1598 | /* Width and height are always even */ | ||
1599 | cropcap->bounds.width = pix->width & ~1; | ||
1600 | cropcap->bounds.height = pix->height & ~1; | ||
1601 | |||
1602 | omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect); | ||
1603 | cropcap->pixelaspect.numerator = 1; | ||
1604 | cropcap->pixelaspect.denominator = 1; | ||
1605 | return 0; | ||
1606 | } | ||
1607 | |||
1608 | static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) | ||
1609 | { | ||
1610 | struct omap_vout_device *vout = fh; | ||
1611 | |||
1612 | if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1613 | return -EINVAL; | ||
1614 | crop->c = vout->crop; | ||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1618 | static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) | ||
1619 | { | ||
1620 | int ret = -EINVAL; | ||
1621 | struct omap_vout_device *vout = fh; | ||
1622 | struct omapvideo_info *ovid; | ||
1623 | struct omap_overlay *ovl; | ||
1624 | struct omap_video_timings *timing; | ||
1625 | |||
1626 | if (vout->streaming) | ||
1627 | return -EBUSY; | ||
1628 | |||
1629 | mutex_lock(&vout->lock); | ||
1630 | ovid = &vout->vid_info; | ||
1631 | ovl = ovid->overlays[0]; | ||
1632 | |||
1633 | if (!ovl->manager || !ovl->manager->device) { | ||
1634 | ret = -EINVAL; | ||
1635 | goto s_crop_err; | ||
1636 | } | ||
1637 | /* get the display device attached to the overlay */ | ||
1638 | timing = &ovl->manager->device->panel.timings; | ||
1639 | |||
1640 | if (rotate_90_or_270(vout)) { | ||
1641 | vout->fbuf.fmt.height = timing->x_res; | ||
1642 | vout->fbuf.fmt.width = timing->y_res; | ||
1643 | } else { | ||
1644 | vout->fbuf.fmt.height = timing->y_res; | ||
1645 | vout->fbuf.fmt.width = timing->x_res; | ||
1646 | } | ||
1647 | |||
1648 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1649 | ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win, | ||
1650 | &vout->fbuf, &crop->c); | ||
1651 | |||
1652 | s_crop_err: | ||
1653 | mutex_unlock(&vout->lock); | ||
1654 | return ret; | ||
1655 | } | ||
1656 | |||
1657 | static int vidioc_queryctrl(struct file *file, void *fh, | ||
1658 | struct v4l2_queryctrl *ctrl) | ||
1659 | { | ||
1660 | int ret = 0; | ||
1661 | |||
1662 | switch (ctrl->id) { | ||
1663 | case V4L2_CID_ROTATE: | ||
1664 | ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0); | ||
1665 | break; | ||
1666 | case V4L2_CID_BG_COLOR: | ||
1667 | ret = v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0); | ||
1668 | break; | ||
1669 | case V4L2_CID_VFLIP: | ||
1670 | ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); | ||
1671 | break; | ||
1672 | default: | ||
1673 | ctrl->name[0] = '\0'; | ||
1674 | ret = -EINVAL; | ||
1675 | } | ||
1676 | return ret; | ||
1677 | } | ||
1678 | |||
1679 | static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) | ||
1680 | { | ||
1681 | int ret = 0; | ||
1682 | struct omap_vout_device *vout = fh; | ||
1683 | |||
1684 | switch (ctrl->id) { | ||
1685 | case V4L2_CID_ROTATE: | ||
1686 | ctrl->value = vout->control[0].value; | ||
1687 | break; | ||
1688 | case V4L2_CID_BG_COLOR: | ||
1689 | { | ||
1690 | struct omap_overlay_manager_info info; | ||
1691 | struct omap_overlay *ovl; | ||
1692 | |||
1693 | ovl = vout->vid_info.overlays[0]; | ||
1694 | if (!ovl->manager || !ovl->manager->get_manager_info) { | ||
1695 | ret = -EINVAL; | ||
1696 | break; | ||
1697 | } | ||
1698 | |||
1699 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
1700 | ctrl->value = info.default_color; | ||
1701 | break; | ||
1702 | } | ||
1703 | case V4L2_CID_VFLIP: | ||
1704 | ctrl->value = vout->control[2].value; | ||
1705 | break; | ||
1706 | default: | ||
1707 | ret = -EINVAL; | ||
1708 | } | ||
1709 | return ret; | ||
1710 | } | ||
1711 | |||
1712 | static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) | ||
1713 | { | ||
1714 | int ret = 0; | ||
1715 | struct omap_vout_device *vout = fh; | ||
1716 | |||
1717 | switch (a->id) { | ||
1718 | case V4L2_CID_ROTATE: | ||
1719 | { | ||
1720 | int rotation = a->value; | ||
1721 | |||
1722 | mutex_lock(&vout->lock); | ||
1723 | |||
1724 | if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { | ||
1725 | mutex_unlock(&vout->lock); | ||
1726 | ret = -EINVAL; | ||
1727 | break; | ||
1728 | } | ||
1729 | |||
1730 | if (v4l2_rot_to_dss_rot(rotation, &vout->rotation, | ||
1731 | vout->mirror)) { | ||
1732 | mutex_unlock(&vout->lock); | ||
1733 | ret = -EINVAL; | ||
1734 | break; | ||
1735 | } | ||
1736 | |||
1737 | vout->control[0].value = rotation; | ||
1738 | mutex_unlock(&vout->lock); | ||
1739 | break; | ||
1740 | } | ||
1741 | case V4L2_CID_BG_COLOR: | ||
1742 | { | ||
1743 | struct omap_overlay *ovl; | ||
1744 | unsigned int color = a->value; | ||
1745 | struct omap_overlay_manager_info info; | ||
1746 | |||
1747 | ovl = vout->vid_info.overlays[0]; | ||
1748 | |||
1749 | mutex_lock(&vout->lock); | ||
1750 | if (!ovl->manager || !ovl->manager->get_manager_info) { | ||
1751 | mutex_unlock(&vout->lock); | ||
1752 | ret = -EINVAL; | ||
1753 | break; | ||
1754 | } | ||
1755 | |||
1756 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
1757 | info.default_color = color; | ||
1758 | if (ovl->manager->set_manager_info(ovl->manager, &info)) { | ||
1759 | mutex_unlock(&vout->lock); | ||
1760 | ret = -EINVAL; | ||
1761 | break; | ||
1762 | } | ||
1763 | |||
1764 | vout->control[1].value = color; | ||
1765 | mutex_unlock(&vout->lock); | ||
1766 | break; | ||
1767 | } | ||
1768 | case V4L2_CID_VFLIP: | ||
1769 | { | ||
1770 | struct omap_overlay *ovl; | ||
1771 | struct omapvideo_info *ovid; | ||
1772 | unsigned int mirror = a->value; | ||
1773 | |||
1774 | ovid = &vout->vid_info; | ||
1775 | ovl = ovid->overlays[0]; | ||
1776 | |||
1777 | mutex_lock(&vout->lock); | ||
1778 | |||
1779 | if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { | ||
1780 | mutex_unlock(&vout->lock); | ||
1781 | ret = -EINVAL; | ||
1782 | break; | ||
1783 | } | ||
1784 | vout->mirror = mirror; | ||
1785 | vout->control[2].value = mirror; | ||
1786 | mutex_unlock(&vout->lock); | ||
1787 | break; | ||
1788 | } | ||
1789 | default: | ||
1790 | ret = -EINVAL; | ||
1791 | } | ||
1792 | return ret; | ||
1793 | } | ||
1794 | |||
1795 | static int vidioc_reqbufs(struct file *file, void *fh, | ||
1796 | struct v4l2_requestbuffers *req) | ||
1797 | { | ||
1798 | int ret = 0; | ||
1799 | unsigned int i, num_buffers = 0; | ||
1800 | struct omap_vout_device *vout = fh; | ||
1801 | struct videobuf_queue *q = &vout->vbq; | ||
1802 | struct videobuf_dmabuf *dmabuf = NULL; | ||
1803 | |||
1804 | if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0)) | ||
1805 | return -EINVAL; | ||
1806 | /* if memory is not mmp or userptr | ||
1807 | return error */ | ||
1808 | if ((V4L2_MEMORY_MMAP != req->memory) && | ||
1809 | (V4L2_MEMORY_USERPTR != req->memory)) | ||
1810 | return -EINVAL; | ||
1811 | |||
1812 | mutex_lock(&vout->lock); | ||
1813 | /* Cannot be requested when streaming is on */ | ||
1814 | if (vout->streaming) { | ||
1815 | ret = -EBUSY; | ||
1816 | goto reqbuf_err; | ||
1817 | } | ||
1818 | |||
1819 | /* If buffers are already allocated free them */ | ||
1820 | if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) { | ||
1821 | if (vout->mmap_count) { | ||
1822 | ret = -EBUSY; | ||
1823 | goto reqbuf_err; | ||
1824 | } | ||
1825 | num_buffers = (vout->vid == OMAP_VIDEO1) ? | ||
1826 | video1_numbuffers : video2_numbuffers; | ||
1827 | for (i = num_buffers; i < vout->buffer_allocated; i++) { | ||
1828 | dmabuf = videobuf_to_dma(q->bufs[i]); | ||
1829 | omap_vout_free_buffer((u32)dmabuf->vmalloc, | ||
1830 | vout->buffer_size); | ||
1831 | vout->buf_virt_addr[i] = 0; | ||
1832 | vout->buf_phy_addr[i] = 0; | ||
1833 | } | ||
1834 | vout->buffer_allocated = num_buffers; | ||
1835 | videobuf_mmap_free(q); | ||
1836 | } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) { | ||
1837 | if (vout->buffer_allocated) { | ||
1838 | videobuf_mmap_free(q); | ||
1839 | for (i = 0; i < vout->buffer_allocated; i++) { | ||
1840 | kfree(q->bufs[i]); | ||
1841 | q->bufs[i] = NULL; | ||
1842 | } | ||
1843 | vout->buffer_allocated = 0; | ||
1844 | } | ||
1845 | } | ||
1846 | |||
1847 | /*store the memory type in data structure */ | ||
1848 | vout->memory = req->memory; | ||
1849 | |||
1850 | INIT_LIST_HEAD(&vout->dma_queue); | ||
1851 | |||
1852 | /* call videobuf_reqbufs api */ | ||
1853 | ret = videobuf_reqbufs(q, req); | ||
1854 | if (ret < 0) | ||
1855 | goto reqbuf_err; | ||
1856 | |||
1857 | vout->buffer_allocated = req->count; | ||
1858 | for (i = 0; i < req->count; i++) { | ||
1859 | dmabuf = videobuf_to_dma(q->bufs[i]); | ||
1860 | dmabuf->vmalloc = (void *) vout->buf_virt_addr[i]; | ||
1861 | dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i]; | ||
1862 | dmabuf->sglen = 1; | ||
1863 | } | ||
1864 | reqbuf_err: | ||
1865 | mutex_unlock(&vout->lock); | ||
1866 | return ret; | ||
1867 | } | ||
1868 | |||
1869 | static int vidioc_querybuf(struct file *file, void *fh, | ||
1870 | struct v4l2_buffer *b) | ||
1871 | { | ||
1872 | struct omap_vout_device *vout = fh; | ||
1873 | |||
1874 | return videobuf_querybuf(&vout->vbq, b); | ||
1875 | } | ||
1876 | |||
1877 | static int vidioc_qbuf(struct file *file, void *fh, | ||
1878 | struct v4l2_buffer *buffer) | ||
1879 | { | ||
1880 | struct omap_vout_device *vout = fh; | ||
1881 | struct videobuf_queue *q = &vout->vbq; | ||
1882 | |||
1883 | if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) || | ||
1884 | (buffer->index >= vout->buffer_allocated) || | ||
1885 | (q->bufs[buffer->index]->memory != buffer->memory)) { | ||
1886 | return -EINVAL; | ||
1887 | } | ||
1888 | if (V4L2_MEMORY_USERPTR == buffer->memory) { | ||
1889 | if ((buffer->length < vout->pix.sizeimage) || | ||
1890 | (0 == buffer->m.userptr)) { | ||
1891 | return -EINVAL; | ||
1892 | } | ||
1893 | } | ||
1894 | |||
1895 | if ((rotation_enabled(vout)) && | ||
1896 | vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) { | ||
1897 | v4l2_warn(&vout->vid_dev->v4l2_dev, | ||
1898 | "DMA Channel not allocated for Rotation\n"); | ||
1899 | return -EINVAL; | ||
1900 | } | ||
1901 | |||
1902 | return videobuf_qbuf(q, buffer); | ||
1903 | } | ||
1904 | |||
1905 | static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1906 | { | ||
1907 | struct omap_vout_device *vout = fh; | ||
1908 | struct videobuf_queue *q = &vout->vbq; | ||
1909 | |||
1910 | if (!vout->streaming) | ||
1911 | return -EINVAL; | ||
1912 | |||
1913 | if (file->f_flags & O_NONBLOCK) | ||
1914 | /* Call videobuf_dqbuf for non blocking mode */ | ||
1915 | return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); | ||
1916 | else | ||
1917 | /* Call videobuf_dqbuf for blocking mode */ | ||
1918 | return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); | ||
1919 | } | ||
1920 | |||
1921 | static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) | ||
1922 | { | ||
1923 | int ret = 0, j; | ||
1924 | u32 addr = 0, mask = 0; | ||
1925 | struct omap_vout_device *vout = fh; | ||
1926 | struct videobuf_queue *q = &vout->vbq; | ||
1927 | struct omapvideo_info *ovid = &vout->vid_info; | ||
1928 | |||
1929 | mutex_lock(&vout->lock); | ||
1930 | |||
1931 | if (vout->streaming) { | ||
1932 | ret = -EBUSY; | ||
1933 | goto streamon_err; | ||
1934 | } | ||
1935 | |||
1936 | ret = videobuf_streamon(q); | ||
1937 | if (ret) | ||
1938 | goto streamon_err; | ||
1939 | |||
1940 | if (list_empty(&vout->dma_queue)) { | ||
1941 | ret = -EIO; | ||
1942 | goto streamon_err1; | ||
1943 | } | ||
1944 | |||
1945 | /* Get the next frame from the buffer queue */ | ||
1946 | vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next, | ||
1947 | struct videobuf_buffer, queue); | ||
1948 | /* Remove buffer from the buffer queue */ | ||
1949 | list_del(&vout->cur_frm->queue); | ||
1950 | /* Mark state of the current frame to active */ | ||
1951 | vout->cur_frm->state = VIDEOBUF_ACTIVE; | ||
1952 | /* Initialize field_id and started member */ | ||
1953 | vout->field_id = 0; | ||
1954 | |||
1955 | /* set flag here. Next QBUF will start DMA */ | ||
1956 | vout->streaming = 1; | ||
1957 | |||
1958 | vout->first_int = 1; | ||
1959 | |||
1960 | if (omap_vout_calculate_offset(vout)) { | ||
1961 | ret = -EINVAL; | ||
1962 | goto streamon_err1; | ||
1963 | } | ||
1964 | addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i] | ||
1965 | + vout->cropped_offset; | ||
1966 | |||
1967 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | ||
1968 | |||
1969 | omap_dispc_register_isr(omap_vout_isr, vout, mask); | ||
1970 | |||
1971 | for (j = 0; j < ovid->num_overlays; j++) { | ||
1972 | struct omap_overlay *ovl = ovid->overlays[j]; | ||
1973 | |||
1974 | if (ovl->manager && ovl->manager->device) { | ||
1975 | struct omap_overlay_info info; | ||
1976 | ovl->get_overlay_info(ovl, &info); | ||
1977 | info.enabled = 1; | ||
1978 | info.paddr = addr; | ||
1979 | if (ovl->set_overlay_info(ovl, &info)) { | ||
1980 | ret = -EINVAL; | ||
1981 | goto streamon_err1; | ||
1982 | } | ||
1983 | } | ||
1984 | } | ||
1985 | |||
1986 | /* First save the configuration in ovelray structure */ | ||
1987 | ret = omapvid_init(vout, addr); | ||
1988 | if (ret) | ||
1989 | v4l2_err(&vout->vid_dev->v4l2_dev, | ||
1990 | "failed to set overlay info\n"); | ||
1991 | /* Enable the pipeline and set the Go bit */ | ||
1992 | ret = omapvid_apply_changes(vout); | ||
1993 | if (ret) | ||
1994 | v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); | ||
1995 | |||
1996 | ret = 0; | ||
1997 | |||
1998 | streamon_err1: | ||
1999 | if (ret) | ||
2000 | ret = videobuf_streamoff(q); | ||
2001 | streamon_err: | ||
2002 | mutex_unlock(&vout->lock); | ||
2003 | return ret; | ||
2004 | } | ||
2005 | |||
2006 | static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) | ||
2007 | { | ||
2008 | u32 mask = 0; | ||
2009 | int ret = 0, j; | ||
2010 | struct omap_vout_device *vout = fh; | ||
2011 | struct omapvideo_info *ovid = &vout->vid_info; | ||
2012 | |||
2013 | if (!vout->streaming) | ||
2014 | return -EINVAL; | ||
2015 | |||
2016 | vout->streaming = 0; | ||
2017 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | ||
2018 | |||
2019 | omap_dispc_unregister_isr(omap_vout_isr, vout, mask); | ||
2020 | |||
2021 | for (j = 0; j < ovid->num_overlays; j++) { | ||
2022 | struct omap_overlay *ovl = ovid->overlays[j]; | ||
2023 | |||
2024 | if (ovl->manager && ovl->manager->device) { | ||
2025 | struct omap_overlay_info info; | ||
2026 | |||
2027 | ovl->get_overlay_info(ovl, &info); | ||
2028 | info.enabled = 0; | ||
2029 | ret = ovl->set_overlay_info(ovl, &info); | ||
2030 | if (ret) | ||
2031 | v4l2_err(&vout->vid_dev->v4l2_dev, | ||
2032 | "failed to update overlay info in streamoff\n"); | ||
2033 | } | ||
2034 | } | ||
2035 | |||
2036 | /* Turn of the pipeline */ | ||
2037 | ret = omapvid_apply_changes(vout); | ||
2038 | if (ret) | ||
2039 | v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode in" | ||
2040 | " streamoff\n"); | ||
2041 | |||
2042 | INIT_LIST_HEAD(&vout->dma_queue); | ||
2043 | ret = videobuf_streamoff(&vout->vbq); | ||
2044 | |||
2045 | return ret; | ||
2046 | } | ||
2047 | |||
2048 | static int vidioc_s_fbuf(struct file *file, void *fh, | ||
2049 | struct v4l2_framebuffer *a) | ||
2050 | { | ||
2051 | int enable = 0; | ||
2052 | struct omap_overlay *ovl; | ||
2053 | struct omapvideo_info *ovid; | ||
2054 | struct omap_vout_device *vout = fh; | ||
2055 | struct omap_overlay_manager_info info; | ||
2056 | enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
2057 | |||
2058 | ovid = &vout->vid_info; | ||
2059 | ovl = ovid->overlays[0]; | ||
2060 | |||
2061 | /* OMAP DSS doesn't support Source and Destination color | ||
2062 | key together */ | ||
2063 | if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && | ||
2064 | (a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) | ||
2065 | return -EINVAL; | ||
2066 | /* OMAP DSS Doesn't support the Destination color key | ||
2067 | and alpha blending together */ | ||
2068 | if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) && | ||
2069 | (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA)) | ||
2070 | return -EINVAL; | ||
2071 | |||
2072 | if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) { | ||
2073 | vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; | ||
2074 | key_type = OMAP_DSS_COLOR_KEY_VID_SRC; | ||
2075 | } else | ||
2076 | vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; | ||
2077 | |||
2078 | if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) { | ||
2079 | vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; | ||
2080 | key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
2081 | } else | ||
2082 | vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; | ||
2083 | |||
2084 | if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY | | ||
2085 | V4L2_FBUF_FLAG_SRC_CHROMAKEY)) | ||
2086 | enable = 1; | ||
2087 | else | ||
2088 | enable = 0; | ||
2089 | if (ovl->manager && ovl->manager->get_manager_info && | ||
2090 | ovl->manager->set_manager_info) { | ||
2091 | |||
2092 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
2093 | info.trans_enabled = enable; | ||
2094 | info.trans_key_type = key_type; | ||
2095 | info.trans_key = vout->win.chromakey; | ||
2096 | |||
2097 | if (ovl->manager->set_manager_info(ovl->manager, &info)) | ||
2098 | return -EINVAL; | ||
2099 | } | ||
2100 | if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) { | ||
2101 | vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
2102 | enable = 1; | ||
2103 | } else { | ||
2104 | vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
2105 | enable = 0; | ||
2106 | } | ||
2107 | if (ovl->manager && ovl->manager->get_manager_info && | ||
2108 | ovl->manager->set_manager_info) { | ||
2109 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
2110 | info.alpha_enabled = enable; | ||
2111 | if (ovl->manager->set_manager_info(ovl->manager, &info)) | ||
2112 | return -EINVAL; | ||
2113 | } | ||
2114 | |||
2115 | return 0; | ||
2116 | } | ||
2117 | |||
2118 | static int vidioc_g_fbuf(struct file *file, void *fh, | ||
2119 | struct v4l2_framebuffer *a) | ||
2120 | { | ||
2121 | struct omap_overlay *ovl; | ||
2122 | struct omapvideo_info *ovid; | ||
2123 | struct omap_vout_device *vout = fh; | ||
2124 | struct omap_overlay_manager_info info; | ||
2125 | |||
2126 | ovid = &vout->vid_info; | ||
2127 | ovl = ovid->overlays[0]; | ||
2128 | |||
2129 | a->flags = 0x0; | ||
2130 | a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY | ||
2131 | | V4L2_FBUF_CAP_SRC_CHROMAKEY; | ||
2132 | |||
2133 | if (ovl->manager && ovl->manager->get_manager_info) { | ||
2134 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
2135 | if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC) | ||
2136 | a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; | ||
2137 | if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST) | ||
2138 | a->flags |= V4L2_FBUF_FLAG_CHROMAKEY; | ||
2139 | } | ||
2140 | if (ovl->manager && ovl->manager->get_manager_info) { | ||
2141 | ovl->manager->get_manager_info(ovl->manager, &info); | ||
2142 | if (info.alpha_enabled) | ||
2143 | a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
2144 | } | ||
2145 | |||
2146 | return 0; | ||
2147 | } | ||
2148 | |||
2149 | static const struct v4l2_ioctl_ops vout_ioctl_ops = { | ||
2150 | .vidioc_querycap = vidioc_querycap, | ||
2151 | .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, | ||
2152 | .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, | ||
2153 | .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, | ||
2154 | .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, | ||
2155 | .vidioc_queryctrl = vidioc_queryctrl, | ||
2156 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
2157 | .vidioc_s_fbuf = vidioc_s_fbuf, | ||
2158 | .vidioc_g_fbuf = vidioc_g_fbuf, | ||
2159 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
2160 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, | ||
2161 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, | ||
2162 | .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, | ||
2163 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, | ||
2164 | .vidioc_cropcap = vidioc_cropcap, | ||
2165 | .vidioc_g_crop = vidioc_g_crop, | ||
2166 | .vidioc_s_crop = vidioc_s_crop, | ||
2167 | .vidioc_reqbufs = vidioc_reqbufs, | ||
2168 | .vidioc_querybuf = vidioc_querybuf, | ||
2169 | .vidioc_qbuf = vidioc_qbuf, | ||
2170 | .vidioc_dqbuf = vidioc_dqbuf, | ||
2171 | .vidioc_streamon = vidioc_streamon, | ||
2172 | .vidioc_streamoff = vidioc_streamoff, | ||
2173 | }; | ||
2174 | |||
2175 | static const struct v4l2_file_operations omap_vout_fops = { | ||
2176 | .owner = THIS_MODULE, | ||
2177 | .unlocked_ioctl = video_ioctl2, | ||
2178 | .mmap = omap_vout_mmap, | ||
2179 | .open = omap_vout_open, | ||
2180 | .release = omap_vout_release, | ||
2181 | }; | ||
2182 | |||
2183 | /* Init functions used during driver initialization */ | ||
2184 | /* Initial setup of video_data */ | ||
2185 | static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) | ||
2186 | { | ||
2187 | struct video_device *vfd; | ||
2188 | struct v4l2_pix_format *pix; | ||
2189 | struct v4l2_control *control; | ||
2190 | struct omap_dss_device *display = | ||
2191 | vout->vid_info.overlays[0]->manager->device; | ||
2192 | |||
2193 | /* set the default pix */ | ||
2194 | pix = &vout->pix; | ||
2195 | |||
2196 | /* Set the default picture of QVGA */ | ||
2197 | pix->width = QQVGA_WIDTH; | ||
2198 | pix->height = QQVGA_HEIGHT; | ||
2199 | |||
2200 | /* Default pixel format is RGB 5-6-5 */ | ||
2201 | pix->pixelformat = V4L2_PIX_FMT_RGB565; | ||
2202 | pix->field = V4L2_FIELD_ANY; | ||
2203 | pix->bytesperline = pix->width * 2; | ||
2204 | pix->sizeimage = pix->bytesperline * pix->height; | ||
2205 | pix->priv = 0; | ||
2206 | pix->colorspace = V4L2_COLORSPACE_JPEG; | ||
2207 | |||
2208 | vout->bpp = RGB565_BPP; | ||
2209 | vout->fbuf.fmt.width = display->panel.timings.x_res; | ||
2210 | vout->fbuf.fmt.height = display->panel.timings.y_res; | ||
2211 | |||
2212 | /* Set the data structures for the overlay parameters*/ | ||
2213 | vout->win.global_alpha = 255; | ||
2214 | vout->fbuf.flags = 0; | ||
2215 | vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA | | ||
2216 | V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY; | ||
2217 | vout->win.chromakey = 0; | ||
2218 | |||
2219 | omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win); | ||
2220 | |||
2221 | /*Initialize the control variables for | ||
2222 | rotation, flipping and background color. */ | ||
2223 | control = vout->control; | ||
2224 | control[0].id = V4L2_CID_ROTATE; | ||
2225 | control[0].value = 0; | ||
2226 | vout->rotation = 0; | ||
2227 | vout->mirror = 0; | ||
2228 | vout->control[2].id = V4L2_CID_HFLIP; | ||
2229 | vout->control[2].value = 0; | ||
2230 | vout->vrfb_bpp = 2; | ||
2231 | |||
2232 | control[1].id = V4L2_CID_BG_COLOR; | ||
2233 | control[1].value = 0; | ||
2234 | |||
2235 | /* initialize the video_device struct */ | ||
2236 | vfd = vout->vfd = video_device_alloc(); | ||
2237 | |||
2238 | if (!vfd) { | ||
2239 | printk(KERN_ERR VOUT_NAME ": could not allocate" | ||
2240 | " video device struct\n"); | ||
2241 | return -ENOMEM; | ||
2242 | } | ||
2243 | vfd->release = video_device_release; | ||
2244 | vfd->ioctl_ops = &vout_ioctl_ops; | ||
2245 | |||
2246 | strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); | ||
2247 | |||
2248 | /* need to register for a VID_HARDWARE_* ID in videodev.h */ | ||
2249 | vfd->fops = &omap_vout_fops; | ||
2250 | vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; | ||
2251 | mutex_init(&vout->lock); | ||
2252 | |||
2253 | vfd->minor = -1; | ||
2254 | return 0; | ||
2255 | |||
2256 | } | ||
2257 | |||
2258 | /* Setup video buffers */ | ||
2259 | static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, | ||
2260 | int vid_num) | ||
2261 | { | ||
2262 | u32 numbuffers; | ||
2263 | int ret = 0, i, j; | ||
2264 | int image_width, image_height; | ||
2265 | struct video_device *vfd; | ||
2266 | struct omap_vout_device *vout; | ||
2267 | int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS; | ||
2268 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
2269 | struct omap2video_device *vid_dev = | ||
2270 | container_of(v4l2_dev, struct omap2video_device, v4l2_dev); | ||
2271 | |||
2272 | vout = vid_dev->vouts[vid_num]; | ||
2273 | vfd = vout->vfd; | ||
2274 | |||
2275 | numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; | ||
2276 | vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; | ||
2277 | dev_info(&pdev->dev, "Buffer Size = %d\n", vout->buffer_size); | ||
2278 | |||
2279 | for (i = 0; i < numbuffers; i++) { | ||
2280 | vout->buf_virt_addr[i] = | ||
2281 | omap_vout_alloc_buffer(vout->buffer_size, | ||
2282 | (u32 *) &vout->buf_phy_addr[i]); | ||
2283 | if (!vout->buf_virt_addr[i]) { | ||
2284 | numbuffers = i; | ||
2285 | ret = -ENOMEM; | ||
2286 | goto free_buffers; | ||
2287 | } | ||
2288 | } | ||
2289 | |||
2290 | for (i = 0; i < VRFB_NUM_BUFS; i++) { | ||
2291 | if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) { | ||
2292 | dev_info(&pdev->dev, ": VRFB allocation failed\n"); | ||
2293 | for (j = 0; j < i; j++) | ||
2294 | omap_vrfb_release_ctx(&vout->vrfb_context[j]); | ||
2295 | ret = -ENOMEM; | ||
2296 | goto free_buffers; | ||
2297 | } | ||
2298 | } | ||
2299 | vout->cropped_offset = 0; | ||
2300 | |||
2301 | /* Calculate VRFB memory size */ | ||
2302 | /* allocate for worst case size */ | ||
2303 | image_width = VID_MAX_WIDTH / TILE_SIZE; | ||
2304 | if (VID_MAX_WIDTH % TILE_SIZE) | ||
2305 | image_width++; | ||
2306 | |||
2307 | image_width = image_width * TILE_SIZE; | ||
2308 | image_height = VID_MAX_HEIGHT / TILE_SIZE; | ||
2309 | |||
2310 | if (VID_MAX_HEIGHT % TILE_SIZE) | ||
2311 | image_height++; | ||
2312 | |||
2313 | image_height = image_height * TILE_SIZE; | ||
2314 | vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2); | ||
2315 | |||
2316 | /* | ||
2317 | * Request and Initialize DMA, for DMA based VRFB transfer | ||
2318 | */ | ||
2319 | vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE; | ||
2320 | vout->vrfb_dma_tx.dma_ch = -1; | ||
2321 | vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED; | ||
2322 | ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX", | ||
2323 | omap_vout_vrfb_dma_tx_callback, | ||
2324 | (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch); | ||
2325 | if (ret < 0) { | ||
2326 | vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; | ||
2327 | dev_info(&pdev->dev, ": failed to allocate DMA Channel for" | ||
2328 | " video%d\n", vfd->minor); | ||
2329 | } | ||
2330 | init_waitqueue_head(&vout->vrfb_dma_tx.wait); | ||
2331 | |||
2332 | /* Allocate VRFB buffers if selected through bootargs */ | ||
2333 | static_vrfb_allocation = (vid_num == 0) ? | ||
2334 | vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; | ||
2335 | |||
2336 | /* statically allocated the VRFB buffer is done through | ||
2337 | commands line aruments */ | ||
2338 | if (static_vrfb_allocation) { | ||
2339 | if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) { | ||
2340 | ret = -ENOMEM; | ||
2341 | goto release_vrfb_ctx; | ||
2342 | } | ||
2343 | vout->vrfb_static_allocation = 1; | ||
2344 | } | ||
2345 | return 0; | ||
2346 | |||
2347 | release_vrfb_ctx: | ||
2348 | for (j = 0; j < VRFB_NUM_BUFS; j++) | ||
2349 | omap_vrfb_release_ctx(&vout->vrfb_context[j]); | ||
2350 | |||
2351 | free_buffers: | ||
2352 | for (i = 0; i < numbuffers; i++) { | ||
2353 | omap_vout_free_buffer(vout->buf_virt_addr[i], | ||
2354 | vout->buffer_size); | ||
2355 | vout->buf_virt_addr[i] = 0; | ||
2356 | vout->buf_phy_addr[i] = 0; | ||
2357 | } | ||
2358 | return ret; | ||
2359 | |||
2360 | } | ||
2361 | |||
2362 | /* Create video out devices */ | ||
2363 | static int __init omap_vout_create_video_devices(struct platform_device *pdev) | ||
2364 | { | ||
2365 | int ret = 0, k; | ||
2366 | struct omap_vout_device *vout; | ||
2367 | struct video_device *vfd = NULL; | ||
2368 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
2369 | struct omap2video_device *vid_dev = container_of(v4l2_dev, | ||
2370 | struct omap2video_device, v4l2_dev); | ||
2371 | |||
2372 | for (k = 0; k < pdev->num_resources; k++) { | ||
2373 | |||
2374 | vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL); | ||
2375 | if (!vout) { | ||
2376 | dev_err(&pdev->dev, ": could not allocate memory\n"); | ||
2377 | return -ENOMEM; | ||
2378 | } | ||
2379 | memset(vout, 0, sizeof(struct omap_vout_device)); | ||
2380 | |||
2381 | vout->vid = k; | ||
2382 | vid_dev->vouts[k] = vout; | ||
2383 | vout->vid_dev = vid_dev; | ||
2384 | /* Select video2 if only 1 overlay is controlled by V4L2 */ | ||
2385 | if (pdev->num_resources == 1) | ||
2386 | vout->vid_info.overlays[0] = vid_dev->overlays[k + 2]; | ||
2387 | else | ||
2388 | /* Else select video1 and video2 one by one. */ | ||
2389 | vout->vid_info.overlays[0] = vid_dev->overlays[k + 1]; | ||
2390 | vout->vid_info.num_overlays = 1; | ||
2391 | vout->vid_info.id = k + 1; | ||
2392 | |||
2393 | /* Setup the default configuration for the video devices | ||
2394 | */ | ||
2395 | if (omap_vout_setup_video_data(vout) != 0) { | ||
2396 | ret = -ENOMEM; | ||
2397 | goto error; | ||
2398 | } | ||
2399 | |||
2400 | /* Allocate default number of buffers for the video streaming | ||
2401 | * and reserve the VRFB space for rotation | ||
2402 | */ | ||
2403 | if (omap_vout_setup_video_bufs(pdev, k) != 0) { | ||
2404 | ret = -ENOMEM; | ||
2405 | goto error1; | ||
2406 | } | ||
2407 | |||
2408 | /* Register the Video device with V4L2 | ||
2409 | */ | ||
2410 | vfd = vout->vfd; | ||
2411 | if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) { | ||
2412 | dev_err(&pdev->dev, ": Could not register " | ||
2413 | "Video for Linux device\n"); | ||
2414 | vfd->minor = -1; | ||
2415 | ret = -ENODEV; | ||
2416 | goto error2; | ||
2417 | } | ||
2418 | video_set_drvdata(vfd, vout); | ||
2419 | |||
2420 | /* Configure the overlay structure */ | ||
2421 | ret = omapvid_init(vid_dev->vouts[k], 0); | ||
2422 | if (!ret) | ||
2423 | goto success; | ||
2424 | |||
2425 | error2: | ||
2426 | omap_vout_release_vrfb(vout); | ||
2427 | omap_vout_free_buffers(vout); | ||
2428 | error1: | ||
2429 | video_device_release(vfd); | ||
2430 | error: | ||
2431 | kfree(vout); | ||
2432 | return ret; | ||
2433 | |||
2434 | success: | ||
2435 | dev_info(&pdev->dev, ": registered and initialized" | ||
2436 | " video device %d\n", vfd->minor); | ||
2437 | if (k == (pdev->num_resources - 1)) | ||
2438 | return 0; | ||
2439 | } | ||
2440 | |||
2441 | return -ENODEV; | ||
2442 | } | ||
2443 | /* Driver functions */ | ||
2444 | static void omap_vout_cleanup_device(struct omap_vout_device *vout) | ||
2445 | { | ||
2446 | struct video_device *vfd; | ||
2447 | |||
2448 | if (!vout) | ||
2449 | return; | ||
2450 | |||
2451 | vfd = vout->vfd; | ||
2452 | if (vfd) { | ||
2453 | if (!video_is_registered(vfd)) { | ||
2454 | /* | ||
2455 | * The device was never registered, so release the | ||
2456 | * video_device struct directly. | ||
2457 | */ | ||
2458 | video_device_release(vfd); | ||
2459 | } else { | ||
2460 | /* | ||
2461 | * The unregister function will release the video_device | ||
2462 | * struct as well as unregistering it. | ||
2463 | */ | ||
2464 | video_unregister_device(vfd); | ||
2465 | } | ||
2466 | } | ||
2467 | |||
2468 | omap_vout_release_vrfb(vout); | ||
2469 | omap_vout_free_buffers(vout); | ||
2470 | /* Free the VRFB buffer if allocated | ||
2471 | * init time | ||
2472 | */ | ||
2473 | if (vout->vrfb_static_allocation) | ||
2474 | omap_vout_free_vrfb_buffers(vout); | ||
2475 | |||
2476 | kfree(vout); | ||
2477 | } | ||
2478 | |||
2479 | static int omap_vout_remove(struct platform_device *pdev) | ||
2480 | { | ||
2481 | int k; | ||
2482 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
2483 | struct omap2video_device *vid_dev = container_of(v4l2_dev, struct | ||
2484 | omap2video_device, v4l2_dev); | ||
2485 | |||
2486 | v4l2_device_unregister(v4l2_dev); | ||
2487 | for (k = 0; k < pdev->num_resources; k++) | ||
2488 | omap_vout_cleanup_device(vid_dev->vouts[k]); | ||
2489 | |||
2490 | for (k = 0; k < vid_dev->num_displays; k++) { | ||
2491 | if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) | ||
2492 | vid_dev->displays[k]->disable(vid_dev->displays[k]); | ||
2493 | |||
2494 | omap_dss_put_device(vid_dev->displays[k]); | ||
2495 | } | ||
2496 | kfree(vid_dev); | ||
2497 | return 0; | ||
2498 | } | ||
2499 | |||
2500 | static int __init omap_vout_probe(struct platform_device *pdev) | ||
2501 | { | ||
2502 | int ret = 0, i; | ||
2503 | struct omap_overlay *ovl; | ||
2504 | struct omap_dss_device *dssdev = NULL; | ||
2505 | struct omap_dss_device *def_display; | ||
2506 | struct omap2video_device *vid_dev = NULL; | ||
2507 | |||
2508 | if (pdev->num_resources == 0) { | ||
2509 | dev_err(&pdev->dev, "probed for an unknown device\n"); | ||
2510 | return -ENODEV; | ||
2511 | } | ||
2512 | |||
2513 | vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); | ||
2514 | if (vid_dev == NULL) | ||
2515 | return -ENOMEM; | ||
2516 | |||
2517 | vid_dev->num_displays = 0; | ||
2518 | for_each_dss_dev(dssdev) { | ||
2519 | omap_dss_get_device(dssdev); | ||
2520 | vid_dev->displays[vid_dev->num_displays++] = dssdev; | ||
2521 | } | ||
2522 | |||
2523 | if (vid_dev->num_displays == 0) { | ||
2524 | dev_err(&pdev->dev, "no displays\n"); | ||
2525 | ret = -EINVAL; | ||
2526 | goto probe_err0; | ||
2527 | } | ||
2528 | |||
2529 | vid_dev->num_overlays = omap_dss_get_num_overlays(); | ||
2530 | for (i = 0; i < vid_dev->num_overlays; i++) | ||
2531 | vid_dev->overlays[i] = omap_dss_get_overlay(i); | ||
2532 | |||
2533 | vid_dev->num_managers = omap_dss_get_num_overlay_managers(); | ||
2534 | for (i = 0; i < vid_dev->num_managers; i++) | ||
2535 | vid_dev->managers[i] = omap_dss_get_overlay_manager(i); | ||
2536 | |||
2537 | /* Get the Video1 overlay and video2 overlay. | ||
2538 | * Setup the Display attached to that overlays | ||
2539 | */ | ||
2540 | for (i = 1; i < vid_dev->num_overlays; i++) { | ||
2541 | ovl = omap_dss_get_overlay(i); | ||
2542 | if (ovl->manager && ovl->manager->device) { | ||
2543 | def_display = ovl->manager->device; | ||
2544 | } else { | ||
2545 | dev_warn(&pdev->dev, "cannot find display\n"); | ||
2546 | def_display = NULL; | ||
2547 | } | ||
2548 | if (def_display) { | ||
2549 | ret = def_display->enable(def_display); | ||
2550 | if (ret) { | ||
2551 | /* Here we are not considering a error | ||
2552 | * as display may be enabled by frame | ||
2553 | * buffer driver | ||
2554 | */ | ||
2555 | dev_warn(&pdev->dev, | ||
2556 | "'%s' Display already enabled\n", | ||
2557 | def_display->name); | ||
2558 | } | ||
2559 | /* set the update mode */ | ||
2560 | if (def_display->caps & | ||
2561 | OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | ||
2562 | #ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE | ||
2563 | if (def_display->enable_te) | ||
2564 | def_display->enable_te(def_display, 1); | ||
2565 | if (def_display->set_update_mode) | ||
2566 | def_display->set_update_mode(def_display, | ||
2567 | OMAP_DSS_UPDATE_AUTO); | ||
2568 | #else /* MANUAL_UPDATE */ | ||
2569 | if (def_display->enable_te) | ||
2570 | def_display->enable_te(def_display, 0); | ||
2571 | if (def_display->set_update_mode) | ||
2572 | def_display->set_update_mode(def_display, | ||
2573 | OMAP_DSS_UPDATE_MANUAL); | ||
2574 | #endif | ||
2575 | } else { | ||
2576 | if (def_display->set_update_mode) | ||
2577 | def_display->set_update_mode(def_display, | ||
2578 | OMAP_DSS_UPDATE_AUTO); | ||
2579 | } | ||
2580 | } | ||
2581 | } | ||
2582 | |||
2583 | if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) { | ||
2584 | dev_err(&pdev->dev, "v4l2_device_register failed\n"); | ||
2585 | ret = -ENODEV; | ||
2586 | goto probe_err1; | ||
2587 | } | ||
2588 | |||
2589 | ret = omap_vout_create_video_devices(pdev); | ||
2590 | if (ret) | ||
2591 | goto probe_err2; | ||
2592 | |||
2593 | for (i = 0; i < vid_dev->num_displays; i++) { | ||
2594 | struct omap_dss_device *display = vid_dev->displays[i]; | ||
2595 | |||
2596 | if (display->update) | ||
2597 | display->update(display, 0, 0, | ||
2598 | display->panel.timings.x_res, | ||
2599 | display->panel.timings.y_res); | ||
2600 | } | ||
2601 | return 0; | ||
2602 | |||
2603 | probe_err2: | ||
2604 | v4l2_device_unregister(&vid_dev->v4l2_dev); | ||
2605 | probe_err1: | ||
2606 | for (i = 1; i < vid_dev->num_overlays; i++) { | ||
2607 | def_display = NULL; | ||
2608 | ovl = omap_dss_get_overlay(i); | ||
2609 | if (ovl->manager && ovl->manager->device) | ||
2610 | def_display = ovl->manager->device; | ||
2611 | |||
2612 | if (def_display) | ||
2613 | def_display->disable(def_display); | ||
2614 | } | ||
2615 | probe_err0: | ||
2616 | kfree(vid_dev); | ||
2617 | return ret; | ||
2618 | } | ||
2619 | |||
2620 | static struct platform_driver omap_vout_driver = { | ||
2621 | .driver = { | ||
2622 | .name = VOUT_NAME, | ||
2623 | }, | ||
2624 | .probe = omap_vout_probe, | ||
2625 | .remove = omap_vout_remove, | ||
2626 | }; | ||
2627 | |||
2628 | static int __init omap_vout_init(void) | ||
2629 | { | ||
2630 | if (platform_driver_register(&omap_vout_driver) != 0) { | ||
2631 | printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); | ||
2632 | return -EINVAL; | ||
2633 | } | ||
2634 | return 0; | ||
2635 | } | ||
2636 | |||
2637 | static void omap_vout_cleanup(void) | ||
2638 | { | ||
2639 | platform_driver_unregister(&omap_vout_driver); | ||
2640 | } | ||
2641 | |||
2642 | late_initcall(omap_vout_init); | ||
2643 | module_exit(omap_vout_cleanup); | ||
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h new file mode 100644 index 000000000000..ea3a047f8bca --- /dev/null +++ b/drivers/media/video/omap/omap_voutdef.h | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * omap_voutdef.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #ifndef OMAP_VOUTDEF_H | ||
12 | #define OMAP_VOUTDEF_H | ||
13 | |||
14 | #include <plat/display.h> | ||
15 | |||
16 | #define YUYV_BPP 2 | ||
17 | #define RGB565_BPP 2 | ||
18 | #define RGB24_BPP 3 | ||
19 | #define RGB32_BPP 4 | ||
20 | #define TILE_SIZE 32 | ||
21 | #define YUYV_VRFB_BPP 2 | ||
22 | #define RGB_VRFB_BPP 1 | ||
23 | #define MAX_CID 3 | ||
24 | #define MAC_VRFB_CTXS 4 | ||
25 | #define MAX_VOUT_DEV 2 | ||
26 | #define MAX_OVLS 3 | ||
27 | #define MAX_DISPLAYS 3 | ||
28 | #define MAX_MANAGERS 3 | ||
29 | |||
30 | /* Enum for Rotation | ||
31 | * DSS understands rotation in 0, 1, 2, 3 context | ||
32 | * while V4L2 driver understands it as 0, 90, 180, 270 | ||
33 | */ | ||
34 | enum dss_rotation { | ||
35 | dss_rotation_0_degree = 0, | ||
36 | dss_rotation_90_degree = 1, | ||
37 | dss_rotation_180_degree = 2, | ||
38 | dss_rotation_270_degree = 3, | ||
39 | }; | ||
40 | /* | ||
41 | * This structure is used to store the DMA transfer parameters | ||
42 | * for VRFB hidden buffer | ||
43 | */ | ||
44 | struct vid_vrfb_dma { | ||
45 | int dev_id; | ||
46 | int dma_ch; | ||
47 | int req_status; | ||
48 | int tx_status; | ||
49 | wait_queue_head_t wait; | ||
50 | }; | ||
51 | |||
52 | struct omapvideo_info { | ||
53 | int id; | ||
54 | int num_overlays; | ||
55 | struct omap_overlay *overlays[MAX_OVLS]; | ||
56 | }; | ||
57 | |||
58 | struct omap2video_device { | ||
59 | struct mutex mtx; | ||
60 | |||
61 | int state; | ||
62 | |||
63 | struct v4l2_device v4l2_dev; | ||
64 | struct omap_vout_device *vouts[MAX_VOUT_DEV]; | ||
65 | |||
66 | int num_displays; | ||
67 | struct omap_dss_device *displays[MAX_DISPLAYS]; | ||
68 | int num_overlays; | ||
69 | struct omap_overlay *overlays[MAX_OVLS]; | ||
70 | int num_managers; | ||
71 | struct omap_overlay_manager *managers[MAX_MANAGERS]; | ||
72 | }; | ||
73 | |||
74 | /* per-device data structure */ | ||
75 | struct omap_vout_device { | ||
76 | |||
77 | struct omapvideo_info vid_info; | ||
78 | struct video_device *vfd; | ||
79 | struct omap2video_device *vid_dev; | ||
80 | int vid; | ||
81 | int opened; | ||
82 | |||
83 | /* we don't allow to change image fmt/size once buffer has | ||
84 | * been allocated | ||
85 | */ | ||
86 | int buffer_allocated; | ||
87 | /* allow to reuse previously allocated buffer which is big enough */ | ||
88 | int buffer_size; | ||
89 | /* keep buffer info across opens */ | ||
90 | unsigned long buf_virt_addr[VIDEO_MAX_FRAME]; | ||
91 | unsigned long buf_phy_addr[VIDEO_MAX_FRAME]; | ||
92 | enum omap_color_mode dss_mode; | ||
93 | |||
94 | /* we don't allow to request new buffer when old buffers are | ||
95 | * still mmaped | ||
96 | */ | ||
97 | int mmap_count; | ||
98 | |||
99 | spinlock_t vbq_lock; /* spinlock for videobuf queues */ | ||
100 | unsigned long field_count; /* field counter for videobuf_buffer */ | ||
101 | |||
102 | /* non-NULL means streaming is in progress. */ | ||
103 | bool streaming; | ||
104 | |||
105 | struct v4l2_pix_format pix; | ||
106 | struct v4l2_rect crop; | ||
107 | struct v4l2_window win; | ||
108 | struct v4l2_framebuffer fbuf; | ||
109 | |||
110 | /* Lock to protect the shared data structures in ioctl */ | ||
111 | struct mutex lock; | ||
112 | |||
113 | /* V4L2 control structure for different control id */ | ||
114 | struct v4l2_control control[MAX_CID]; | ||
115 | enum dss_rotation rotation; | ||
116 | bool mirror; | ||
117 | int flicker_filter; | ||
118 | /* V4L2 control structure for different control id */ | ||
119 | |||
120 | int bpp; /* bytes per pixel */ | ||
121 | int vrfb_bpp; /* bytes per pixel with respect to VRFB */ | ||
122 | |||
123 | struct vid_vrfb_dma vrfb_dma_tx; | ||
124 | unsigned int smsshado_phy_addr[MAC_VRFB_CTXS]; | ||
125 | unsigned int smsshado_virt_addr[MAC_VRFB_CTXS]; | ||
126 | struct vrfb vrfb_context[MAC_VRFB_CTXS]; | ||
127 | bool vrfb_static_allocation; | ||
128 | unsigned int smsshado_size; | ||
129 | unsigned char pos; | ||
130 | |||
131 | int ps, vr_ps, line_length, first_int, field_id; | ||
132 | enum v4l2_memory memory; | ||
133 | struct videobuf_buffer *cur_frm, *next_frm; | ||
134 | struct list_head dma_queue; | ||
135 | u8 *queued_buf_addr[VIDEO_MAX_FRAME]; | ||
136 | u32 cropped_offset; | ||
137 | s32 tv_field1_offset; | ||
138 | void *isr_handle; | ||
139 | |||
140 | /* Buffer queue variables */ | ||
141 | struct omap_vout_device *vout; | ||
142 | enum v4l2_buf_type type; | ||
143 | struct videobuf_queue vbq; | ||
144 | int io_allowed; | ||
145 | |||
146 | }; | ||
147 | #endif /* ifndef OMAP_VOUTDEF_H */ | ||
diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c new file mode 100644 index 000000000000..b941c761eef9 --- /dev/null +++ b/drivers/media/video/omap/omap_voutlib.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * omap_voutlib.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2010 Texas Instruments. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | * Based on the OMAP2 camera driver | ||
11 | * Video-for-Linux (Version 2) camera capture driver for | ||
12 | * the OMAP24xx camera controller. | ||
13 | * | ||
14 | * Author: Andy Lowe (source@mvista.com) | ||
15 | * | ||
16 | * Copyright (C) 2004 MontaVista Software, Inc. | ||
17 | * Copyright (C) 2010 Texas Instruments. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/videodev2.h> | ||
26 | |||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | MODULE_AUTHOR("Texas Instruments"); | ||
30 | MODULE_DESCRIPTION("OMAP Video library"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | /* Return the default overlay cropping rectangle in crop given the image | ||
34 | * size in pix and the video display size in fbuf. The default | ||
35 | * cropping rectangle is the largest rectangle no larger than the capture size | ||
36 | * that will fit on the display. The default cropping rectangle is centered in | ||
37 | * the image. All dimensions and offsets are rounded down to even numbers. | ||
38 | */ | ||
39 | void omap_vout_default_crop(struct v4l2_pix_format *pix, | ||
40 | struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop) | ||
41 | { | ||
42 | crop->width = (pix->width < fbuf->fmt.width) ? | ||
43 | pix->width : fbuf->fmt.width; | ||
44 | crop->height = (pix->height < fbuf->fmt.height) ? | ||
45 | pix->height : fbuf->fmt.height; | ||
46 | crop->width &= ~1; | ||
47 | crop->height &= ~1; | ||
48 | crop->left = ((pix->width - crop->width) >> 1) & ~1; | ||
49 | crop->top = ((pix->height - crop->height) >> 1) & ~1; | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(omap_vout_default_crop); | ||
52 | |||
53 | /* Given a new render window in new_win, adjust the window to the | ||
54 | * nearest supported configuration. The adjusted window parameters are | ||
55 | * returned in new_win. | ||
56 | * Returns zero if succesful, or -EINVAL if the requested window is | ||
57 | * impossible and cannot reasonably be adjusted. | ||
58 | */ | ||
59 | int omap_vout_try_window(struct v4l2_framebuffer *fbuf, | ||
60 | struct v4l2_window *new_win) | ||
61 | { | ||
62 | struct v4l2_rect try_win; | ||
63 | |||
64 | /* make a working copy of the new_win rectangle */ | ||
65 | try_win = new_win->w; | ||
66 | |||
67 | /* adjust the preview window so it fits on the display by clipping any | ||
68 | * offscreen areas | ||
69 | */ | ||
70 | if (try_win.left < 0) { | ||
71 | try_win.width += try_win.left; | ||
72 | try_win.left = 0; | ||
73 | } | ||
74 | if (try_win.top < 0) { | ||
75 | try_win.height += try_win.top; | ||
76 | try_win.top = 0; | ||
77 | } | ||
78 | try_win.width = (try_win.width < fbuf->fmt.width) ? | ||
79 | try_win.width : fbuf->fmt.width; | ||
80 | try_win.height = (try_win.height < fbuf->fmt.height) ? | ||
81 | try_win.height : fbuf->fmt.height; | ||
82 | if (try_win.left + try_win.width > fbuf->fmt.width) | ||
83 | try_win.width = fbuf->fmt.width - try_win.left; | ||
84 | if (try_win.top + try_win.height > fbuf->fmt.height) | ||
85 | try_win.height = fbuf->fmt.height - try_win.top; | ||
86 | try_win.width &= ~1; | ||
87 | try_win.height &= ~1; | ||
88 | |||
89 | if (try_win.width <= 0 || try_win.height <= 0) | ||
90 | return -EINVAL; | ||
91 | |||
92 | /* We now have a valid preview window, so go with it */ | ||
93 | new_win->w = try_win; | ||
94 | new_win->field = V4L2_FIELD_ANY; | ||
95 | return 0; | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(omap_vout_try_window); | ||
98 | |||
99 | /* Given a new render window in new_win, adjust the window to the | ||
100 | * nearest supported configuration. The image cropping window in crop | ||
101 | * will also be adjusted if necessary. Preference is given to keeping the | ||
102 | * the window as close to the requested configuration as possible. If | ||
103 | * successful, new_win, vout->win, and crop are updated. | ||
104 | * Returns zero if succesful, or -EINVAL if the requested preview window is | ||
105 | * impossible and cannot reasonably be adjusted. | ||
106 | */ | ||
107 | int omap_vout_new_window(struct v4l2_rect *crop, | ||
108 | struct v4l2_window *win, struct v4l2_framebuffer *fbuf, | ||
109 | struct v4l2_window *new_win) | ||
110 | { | ||
111 | int err; | ||
112 | |||
113 | err = omap_vout_try_window(fbuf, new_win); | ||
114 | if (err) | ||
115 | return err; | ||
116 | |||
117 | /* update our preview window */ | ||
118 | win->w = new_win->w; | ||
119 | win->field = new_win->field; | ||
120 | win->chromakey = new_win->chromakey; | ||
121 | |||
122 | /* Adjust the cropping window to allow for resizing limitation */ | ||
123 | if (cpu_is_omap24xx()) { | ||
124 | /* For 24xx limit is 8x to 1/2x scaling. */ | ||
125 | if ((crop->height/win->w.height) >= 2) | ||
126 | crop->height = win->w.height * 2; | ||
127 | |||
128 | if ((crop->width/win->w.width) >= 2) | ||
129 | crop->width = win->w.width * 2; | ||
130 | |||
131 | if (crop->width > 768) { | ||
132 | /* The OMAP2420 vertical resizing line buffer is 768 | ||
133 | * pixels wide. If the cropped image is wider than | ||
134 | * 768 pixels then it cannot be vertically resized. | ||
135 | */ | ||
136 | if (crop->height != win->w.height) | ||
137 | crop->width = 768; | ||
138 | } | ||
139 | } else if (cpu_is_omap34xx()) { | ||
140 | /* For 34xx limit is 8x to 1/4x scaling. */ | ||
141 | if ((crop->height/win->w.height) >= 4) | ||
142 | crop->height = win->w.height * 4; | ||
143 | |||
144 | if ((crop->width/win->w.width) >= 4) | ||
145 | crop->width = win->w.width * 4; | ||
146 | } | ||
147 | return 0; | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(omap_vout_new_window); | ||
150 | |||
151 | /* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to | ||
152 | * the nearest supported configuration. The image render window in win will | ||
153 | * also be adjusted if necessary. The preview window is adjusted such that the | ||
154 | * horizontal and vertical rescaling ratios stay constant. If the render | ||
155 | * window would fall outside the display boundaries, the cropping rectangle | ||
156 | * will also be adjusted to maintain the rescaling ratios. If successful, crop | ||
157 | * and win are updated. | ||
158 | * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is | ||
159 | * impossible and cannot reasonably be adjusted. | ||
160 | */ | ||
161 | int omap_vout_new_crop(struct v4l2_pix_format *pix, | ||
162 | struct v4l2_rect *crop, struct v4l2_window *win, | ||
163 | struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop) | ||
164 | { | ||
165 | struct v4l2_rect try_crop; | ||
166 | unsigned long vresize, hresize; | ||
167 | |||
168 | /* make a working copy of the new_crop rectangle */ | ||
169 | try_crop = *new_crop; | ||
170 | |||
171 | /* adjust the cropping rectangle so it fits in the image */ | ||
172 | if (try_crop.left < 0) { | ||
173 | try_crop.width += try_crop.left; | ||
174 | try_crop.left = 0; | ||
175 | } | ||
176 | if (try_crop.top < 0) { | ||
177 | try_crop.height += try_crop.top; | ||
178 | try_crop.top = 0; | ||
179 | } | ||
180 | try_crop.width = (try_crop.width < pix->width) ? | ||
181 | try_crop.width : pix->width; | ||
182 | try_crop.height = (try_crop.height < pix->height) ? | ||
183 | try_crop.height : pix->height; | ||
184 | if (try_crop.left + try_crop.width > pix->width) | ||
185 | try_crop.width = pix->width - try_crop.left; | ||
186 | if (try_crop.top + try_crop.height > pix->height) | ||
187 | try_crop.height = pix->height - try_crop.top; | ||
188 | |||
189 | try_crop.width &= ~1; | ||
190 | try_crop.height &= ~1; | ||
191 | |||
192 | if (try_crop.width <= 0 || try_crop.height <= 0) | ||
193 | return -EINVAL; | ||
194 | |||
195 | if (cpu_is_omap24xx()) { | ||
196 | if (crop->height != win->w.height) { | ||
197 | /* If we're resizing vertically, we can't support a | ||
198 | * crop width wider than 768 pixels. | ||
199 | */ | ||
200 | if (try_crop.width > 768) | ||
201 | try_crop.width = 768; | ||
202 | } | ||
203 | } | ||
204 | /* vertical resizing */ | ||
205 | vresize = (1024 * crop->height) / win->w.height; | ||
206 | if (cpu_is_omap24xx() && (vresize > 2048)) | ||
207 | vresize = 2048; | ||
208 | else if (cpu_is_omap34xx() && (vresize > 4096)) | ||
209 | vresize = 4096; | ||
210 | |||
211 | win->w.height = ((1024 * try_crop.height) / vresize) & ~1; | ||
212 | if (win->w.height == 0) | ||
213 | win->w.height = 2; | ||
214 | if (win->w.height + win->w.top > fbuf->fmt.height) { | ||
215 | /* We made the preview window extend below the bottom of the | ||
216 | * display, so clip it to the display boundary and resize the | ||
217 | * cropping height to maintain the vertical resizing ratio. | ||
218 | */ | ||
219 | win->w.height = (fbuf->fmt.height - win->w.top) & ~1; | ||
220 | if (try_crop.height == 0) | ||
221 | try_crop.height = 2; | ||
222 | } | ||
223 | /* horizontal resizing */ | ||
224 | hresize = (1024 * crop->width) / win->w.width; | ||
225 | if (cpu_is_omap24xx() && (hresize > 2048)) | ||
226 | hresize = 2048; | ||
227 | else if (cpu_is_omap34xx() && (hresize > 4096)) | ||
228 | hresize = 4096; | ||
229 | |||
230 | win->w.width = ((1024 * try_crop.width) / hresize) & ~1; | ||
231 | if (win->w.width == 0) | ||
232 | win->w.width = 2; | ||
233 | if (win->w.width + win->w.left > fbuf->fmt.width) { | ||
234 | /* We made the preview window extend past the right side of the | ||
235 | * display, so clip it to the display boundary and resize the | ||
236 | * cropping width to maintain the horizontal resizing ratio. | ||
237 | */ | ||
238 | win->w.width = (fbuf->fmt.width - win->w.left) & ~1; | ||
239 | if (try_crop.width == 0) | ||
240 | try_crop.width = 2; | ||
241 | } | ||
242 | if (cpu_is_omap24xx()) { | ||
243 | if ((try_crop.height/win->w.height) >= 2) | ||
244 | try_crop.height = win->w.height * 2; | ||
245 | |||
246 | if ((try_crop.width/win->w.width) >= 2) | ||
247 | try_crop.width = win->w.width * 2; | ||
248 | |||
249 | if (try_crop.width > 768) { | ||
250 | /* The OMAP2420 vertical resizing line buffer is | ||
251 | * 768 pixels wide. If the cropped image is wider | ||
252 | * than 768 pixels then it cannot be vertically resized. | ||
253 | */ | ||
254 | if (try_crop.height != win->w.height) | ||
255 | try_crop.width = 768; | ||
256 | } | ||
257 | } else if (cpu_is_omap34xx()) { | ||
258 | if ((try_crop.height/win->w.height) >= 4) | ||
259 | try_crop.height = win->w.height * 4; | ||
260 | |||
261 | if ((try_crop.width/win->w.width) >= 4) | ||
262 | try_crop.width = win->w.width * 4; | ||
263 | } | ||
264 | /* update our cropping rectangle and we're done */ | ||
265 | *crop = try_crop; | ||
266 | return 0; | ||
267 | } | ||
268 | EXPORT_SYMBOL_GPL(omap_vout_new_crop); | ||
269 | |||
270 | /* Given a new format in pix and fbuf, crop and win | ||
271 | * structures are initialized to default values. crop | ||
272 | * is initialized to the largest window size that will fit on the display. The | ||
273 | * crop window is centered in the image. win is initialized to | ||
274 | * the same size as crop and is centered on the display. | ||
275 | * All sizes and offsets are constrained to be even numbers. | ||
276 | */ | ||
277 | void omap_vout_new_format(struct v4l2_pix_format *pix, | ||
278 | struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, | ||
279 | struct v4l2_window *win) | ||
280 | { | ||
281 | /* crop defines the preview source window in the image capture | ||
282 | * buffer | ||
283 | */ | ||
284 | omap_vout_default_crop(pix, fbuf, crop); | ||
285 | |||
286 | /* win defines the preview target window on the display */ | ||
287 | win->w.width = crop->width; | ||
288 | win->w.height = crop->height; | ||
289 | win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1; | ||
290 | win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1; | ||
291 | } | ||
292 | EXPORT_SYMBOL_GPL(omap_vout_new_format); | ||
293 | |||
diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h new file mode 100644 index 000000000000..a60b16e8bfc3 --- /dev/null +++ b/drivers/media/video/omap/omap_voutlib.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * omap_voutlib.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef OMAP_VOUTLIB_H | ||
13 | #define OMAP_VOUTLIB_H | ||
14 | |||
15 | extern void omap_vout_default_crop(struct v4l2_pix_format *pix, | ||
16 | struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop); | ||
17 | |||
18 | extern int omap_vout_new_crop(struct v4l2_pix_format *pix, | ||
19 | struct v4l2_rect *crop, struct v4l2_window *win, | ||
20 | struct v4l2_framebuffer *fbuf, | ||
21 | const struct v4l2_rect *new_crop); | ||
22 | |||
23 | extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf, | ||
24 | struct v4l2_window *new_win); | ||
25 | |||
26 | extern int omap_vout_new_window(struct v4l2_rect *crop, | ||
27 | struct v4l2_window *win, struct v4l2_framebuffer *fbuf, | ||
28 | struct v4l2_window *new_win); | ||
29 | |||
30 | extern void omap_vout_new_format(struct v4l2_pix_format *pix, | ||
31 | struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, | ||
32 | struct v4l2_window *win); | ||
33 | #endif /* #ifndef OMAP_VOUTLIB_H */ | ||
34 | |||
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index ce76d952e161..f85b2ed8a2d8 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
@@ -452,8 +452,8 @@ static int omap24xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt, | |||
452 | *size = fh->pix.sizeimage; | 452 | *size = fh->pix.sizeimage; |
453 | 453 | ||
454 | /* accessing fh->cam->capture_mem is ok, it's constant */ | 454 | /* accessing fh->cam->capture_mem is ok, it's constant */ |
455 | while (*size * *cnt > fh->cam->capture_mem) | 455 | if (*size * *cnt > fh->cam->capture_mem) |
456 | (*cnt)--; | 456 | *cnt = fh->cam->capture_mem / *size; |
457 | 457 | ||
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index e0bce8dc74bf..a10912097b7a 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -57,8 +57,8 @@ | |||
57 | #define DRIVER_VERSION "v1.64 for Linux 2.5" | 57 | #define DRIVER_VERSION "v1.64 for Linux 2.5" |
58 | #define EMAIL "mark@alpha.dyndns.org" | 58 | #define EMAIL "mark@alpha.dyndns.org" |
59 | #define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \ | 59 | #define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \ |
60 | & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \ | 60 | & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \ |
61 | <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>" | 61 | <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>" |
62 | #define DRIVER_DESC "ov511 USB Camera Driver" | 62 | #define DRIVER_DESC "ov511 USB Camera Driver" |
63 | 63 | ||
64 | #define OV511_I2C_RETRIES 3 | 64 | #define OV511_I2C_RETRIES 3 |
@@ -5916,11 +5916,6 @@ ov51x_disconnect(struct usb_interface *intf) | |||
5916 | mutex_lock(&ov->lock); | 5916 | mutex_lock(&ov->lock); |
5917 | usb_set_intfdata (intf, NULL); | 5917 | usb_set_intfdata (intf, NULL); |
5918 | 5918 | ||
5919 | if (!ov) { | ||
5920 | mutex_unlock(&ov->lock); | ||
5921 | return; | ||
5922 | } | ||
5923 | |||
5924 | /* Free device number */ | 5919 | /* Free device number */ |
5925 | ov511_devused &= ~(1 << ov->nr); | 5920 | ov511_devused &= ~(1 << ov->nr); |
5926 | 5921 | ||
@@ -5945,7 +5940,7 @@ ov51x_disconnect(struct usb_interface *intf) | |||
5945 | ov->dev = NULL; | 5940 | ov->dev = NULL; |
5946 | 5941 | ||
5947 | /* Free the memory */ | 5942 | /* Free the memory */ |
5948 | if (ov && !ov->user) { | 5943 | if (!ov->user) { |
5949 | mutex_lock(&ov->cbuf_lock); | 5944 | mutex_lock(&ov->cbuf_lock); |
5950 | kfree(ov->cbuf); | 5945 | kfree(ov->cbuf); |
5951 | ov->cbuf = NULL; | 5946 | ov->cbuf = NULL; |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index aaa50f9b8e78..91c886ab15c6 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -198,6 +198,7 @@ struct ov7670_info { | |||
198 | struct ov7670_format_struct *fmt; /* Current format */ | 198 | struct ov7670_format_struct *fmt; /* Current format */ |
199 | unsigned char sat; /* Saturation value */ | 199 | unsigned char sat; /* Saturation value */ |
200 | int hue; /* Hue value */ | 200 | int hue; /* Hue value */ |
201 | u8 clkrc; /* Clock divider value */ | ||
201 | }; | 202 | }; |
202 | 203 | ||
203 | static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) | 204 | static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) |
@@ -351,7 +352,7 @@ static struct regval_list ov7670_default_regs[] = { | |||
351 | static struct regval_list ov7670_fmt_yuv422[] = { | 352 | static struct regval_list ov7670_fmt_yuv422[] = { |
352 | { REG_COM7, 0x0 }, /* Selects YUV mode */ | 353 | { REG_COM7, 0x0 }, /* Selects YUV mode */ |
353 | { REG_RGB444, 0 }, /* No RGB444 please */ | 354 | { REG_RGB444, 0 }, /* No RGB444 please */ |
354 | { REG_COM1, 0 }, | 355 | { REG_COM1, 0 }, /* CCIR601 */ |
355 | { REG_COM15, COM15_R00FF }, | 356 | { REG_COM15, COM15_R00FF }, |
356 | { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ | 357 | { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ |
357 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ | 358 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ |
@@ -367,7 +368,7 @@ static struct regval_list ov7670_fmt_yuv422[] = { | |||
367 | static struct regval_list ov7670_fmt_rgb565[] = { | 368 | static struct regval_list ov7670_fmt_rgb565[] = { |
368 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | 369 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ |
369 | { REG_RGB444, 0 }, /* No RGB444 please */ | 370 | { REG_RGB444, 0 }, /* No RGB444 please */ |
370 | { REG_COM1, 0x0 }, | 371 | { REG_COM1, 0x0 }, /* CCIR601 */ |
371 | { REG_COM15, COM15_RGB565 }, | 372 | { REG_COM15, COM15_RGB565 }, |
372 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | 373 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ |
373 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | 374 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ |
@@ -383,7 +384,7 @@ static struct regval_list ov7670_fmt_rgb565[] = { | |||
383 | static struct regval_list ov7670_fmt_rgb444[] = { | 384 | static struct regval_list ov7670_fmt_rgb444[] = { |
384 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ | 385 | { REG_COM7, COM7_RGB }, /* Selects RGB mode */ |
385 | { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ | 386 | { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ |
386 | { REG_COM1, 0x40 }, /* Magic reserved bit */ | 387 | { REG_COM1, 0x0 }, /* CCIR601 */ |
387 | { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ | 388 | { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ |
388 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ | 389 | { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ |
389 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ | 390 | { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ |
@@ -408,8 +409,13 @@ static struct regval_list ov7670_fmt_raw[] = { | |||
408 | 409 | ||
409 | /* | 410 | /* |
410 | * Low-level register I/O. | 411 | * Low-level register I/O. |
412 | * | ||
413 | * Note that there are two versions of these. On the XO 1, the | ||
414 | * i2c controller only does SMBUS, so that's what we use. The | ||
415 | * ov7670 is not really an SMBUS device, though, so the communication | ||
416 | * is not always entirely reliable. | ||
411 | */ | 417 | */ |
412 | 418 | #ifdef CONFIG_OLPC_XO_1 | |
413 | static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, | 419 | static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, |
414 | unsigned char *value) | 420 | unsigned char *value) |
415 | { | 421 | { |
@@ -432,9 +438,67 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, | |||
432 | int ret = i2c_smbus_write_byte_data(client, reg, value); | 438 | int ret = i2c_smbus_write_byte_data(client, reg, value); |
433 | 439 | ||
434 | if (reg == REG_COM7 && (value & COM7_RESET)) | 440 | if (reg == REG_COM7 && (value & COM7_RESET)) |
435 | msleep(2); /* Wait for reset to run */ | 441 | msleep(5); /* Wait for reset to run */ |
442 | return ret; | ||
443 | } | ||
444 | |||
445 | #else /* ! CONFIG_OLPC_XO_1 */ | ||
446 | /* | ||
447 | * On most platforms, we'd rather do straight i2c I/O. | ||
448 | */ | ||
449 | static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, | ||
450 | unsigned char *value) | ||
451 | { | ||
452 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
453 | u8 data = reg; | ||
454 | struct i2c_msg msg; | ||
455 | int ret; | ||
456 | |||
457 | /* | ||
458 | * Send out the register address... | ||
459 | */ | ||
460 | msg.addr = client->addr; | ||
461 | msg.flags = 0; | ||
462 | msg.len = 1; | ||
463 | msg.buf = &data; | ||
464 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
465 | if (ret < 0) { | ||
466 | printk(KERN_ERR "Error %d on register write\n", ret); | ||
467 | return ret; | ||
468 | } | ||
469 | /* | ||
470 | * ...then read back the result. | ||
471 | */ | ||
472 | msg.flags = I2C_M_RD; | ||
473 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
474 | if (ret >= 0) { | ||
475 | *value = data; | ||
476 | ret = 0; | ||
477 | } | ||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | |||
482 | static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, | ||
483 | unsigned char value) | ||
484 | { | ||
485 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
486 | struct i2c_msg msg; | ||
487 | unsigned char data[2] = { reg, value }; | ||
488 | int ret; | ||
489 | |||
490 | msg.addr = client->addr; | ||
491 | msg.flags = 0; | ||
492 | msg.len = 2; | ||
493 | msg.buf = data; | ||
494 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
495 | if (ret > 0) | ||
496 | ret = 0; | ||
497 | if (reg == REG_COM7 && (value & COM7_RESET)) | ||
498 | msleep(5); /* Wait for reset to run */ | ||
436 | return ret; | 499 | return ret; |
437 | } | 500 | } |
501 | #endif /* CONFIG_OLPC_XO_1 */ | ||
438 | 502 | ||
439 | 503 | ||
440 | /* | 504 | /* |
@@ -744,22 +808,12 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
744 | struct ov7670_format_struct *ovfmt; | 808 | struct ov7670_format_struct *ovfmt; |
745 | struct ov7670_win_size *wsize; | 809 | struct ov7670_win_size *wsize; |
746 | struct ov7670_info *info = to_state(sd); | 810 | struct ov7670_info *info = to_state(sd); |
747 | unsigned char com7, clkrc = 0; | 811 | unsigned char com7; |
748 | 812 | ||
749 | ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); | 813 | ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); |
750 | if (ret) | 814 | if (ret) |
751 | return ret; | 815 | return ret; |
752 | /* | 816 | /* |
753 | * HACK: if we're running rgb565 we need to grab then rewrite | ||
754 | * CLKRC. If we're *not*, however, then rewriting clkrc hoses | ||
755 | * the colors. | ||
756 | */ | ||
757 | if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { | ||
758 | ret = ov7670_read(sd, REG_CLKRC, &clkrc); | ||
759 | if (ret) | ||
760 | return ret; | ||
761 | } | ||
762 | /* | ||
763 | * COM7 is a pain in the ass, it doesn't like to be read then | 817 | * COM7 is a pain in the ass, it doesn't like to be read then |
764 | * quickly written afterward. But we have everything we need | 818 | * quickly written afterward. But we have everything we need |
765 | * to set it absolutely here, as long as the format-specific | 819 | * to set it absolutely here, as long as the format-specific |
@@ -779,8 +833,18 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
779 | ret = ov7670_write_array(sd, wsize->regs); | 833 | ret = ov7670_write_array(sd, wsize->regs); |
780 | info->fmt = ovfmt; | 834 | info->fmt = ovfmt; |
781 | 835 | ||
782 | if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) | 836 | /* |
783 | ret = ov7670_write(sd, REG_CLKRC, clkrc); | 837 | * If we're running RGB565, we must rewrite clkrc after setting |
838 | * the other parameters or the image looks poor. If we're *not* | ||
839 | * doing RGB565, we must not rewrite clkrc or the image looks | ||
840 | * *really* poor. | ||
841 | * | ||
842 | * (Update) Now that we retain clkrc state, we should be able | ||
843 | * to write it unconditionally, and that will make the frame | ||
844 | * rate persistent too. | ||
845 | */ | ||
846 | if (ret == 0) | ||
847 | ret = ov7670_write(sd, REG_CLKRC, info->clkrc); | ||
784 | return ret; | 848 | return ret; |
785 | } | 849 | } |
786 | 850 | ||
@@ -791,20 +855,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
791 | static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | 855 | static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) |
792 | { | 856 | { |
793 | struct v4l2_captureparm *cp = &parms->parm.capture; | 857 | struct v4l2_captureparm *cp = &parms->parm.capture; |
794 | unsigned char clkrc; | 858 | struct ov7670_info *info = to_state(sd); |
795 | int ret; | ||
796 | 859 | ||
797 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 860 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
798 | return -EINVAL; | 861 | return -EINVAL; |
799 | ret = ov7670_read(sd, REG_CLKRC, &clkrc); | 862 | |
800 | if (ret < 0) | ||
801 | return ret; | ||
802 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | 863 | memset(cp, 0, sizeof(struct v4l2_captureparm)); |
803 | cp->capability = V4L2_CAP_TIMEPERFRAME; | 864 | cp->capability = V4L2_CAP_TIMEPERFRAME; |
804 | cp->timeperframe.numerator = 1; | 865 | cp->timeperframe.numerator = 1; |
805 | cp->timeperframe.denominator = OV7670_FRAME_RATE; | 866 | cp->timeperframe.denominator = OV7670_FRAME_RATE; |
806 | if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) | 867 | if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1) |
807 | cp->timeperframe.denominator /= (clkrc & CLK_SCALE); | 868 | cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE); |
808 | return 0; | 869 | return 0; |
809 | } | 870 | } |
810 | 871 | ||
@@ -812,19 +873,14 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | |||
812 | { | 873 | { |
813 | struct v4l2_captureparm *cp = &parms->parm.capture; | 874 | struct v4l2_captureparm *cp = &parms->parm.capture; |
814 | struct v4l2_fract *tpf = &cp->timeperframe; | 875 | struct v4l2_fract *tpf = &cp->timeperframe; |
815 | unsigned char clkrc; | 876 | struct ov7670_info *info = to_state(sd); |
816 | int ret, div; | 877 | int div; |
817 | 878 | ||
818 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 879 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
819 | return -EINVAL; | 880 | return -EINVAL; |
820 | if (cp->extendedmode != 0) | 881 | if (cp->extendedmode != 0) |
821 | return -EINVAL; | 882 | return -EINVAL; |
822 | /* | 883 | |
823 | * CLKRC has a reserved bit, so let's preserve it. | ||
824 | */ | ||
825 | ret = ov7670_read(sd, REG_CLKRC, &clkrc); | ||
826 | if (ret < 0) | ||
827 | return ret; | ||
828 | if (tpf->numerator == 0 || tpf->denominator == 0) | 884 | if (tpf->numerator == 0 || tpf->denominator == 0) |
829 | div = 1; /* Reset to full rate */ | 885 | div = 1; /* Reset to full rate */ |
830 | else | 886 | else |
@@ -833,10 +889,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | |||
833 | div = 1; | 889 | div = 1; |
834 | else if (div > CLK_SCALE) | 890 | else if (div > CLK_SCALE) |
835 | div = CLK_SCALE; | 891 | div = CLK_SCALE; |
836 | clkrc = (clkrc & 0x80) | div; | 892 | info->clkrc = (info->clkrc & 0x80) | div; |
837 | tpf->numerator = 1; | 893 | tpf->numerator = 1; |
838 | tpf->denominator = OV7670_FRAME_RATE/div; | 894 | tpf->denominator = OV7670_FRAME_RATE/div; |
839 | return ov7670_write(sd, REG_CLKRC, clkrc); | 895 | return ov7670_write(sd, REG_CLKRC, info->clkrc); |
840 | } | 896 | } |
841 | 897 | ||
842 | 898 | ||
@@ -1115,6 +1171,140 @@ static int ov7670_s_vflip(struct v4l2_subdev *sd, int value) | |||
1115 | return ret; | 1171 | return ret; |
1116 | } | 1172 | } |
1117 | 1173 | ||
1174 | /* | ||
1175 | * GAIN is split between REG_GAIN and REG_VREF[7:6]. If one believes | ||
1176 | * the data sheet, the VREF parts should be the most significant, but | ||
1177 | * experience shows otherwise. There seems to be little value in | ||
1178 | * messing with the VREF bits, so we leave them alone. | ||
1179 | */ | ||
1180 | static int ov7670_g_gain(struct v4l2_subdev *sd, __s32 *value) | ||
1181 | { | ||
1182 | int ret; | ||
1183 | unsigned char gain; | ||
1184 | |||
1185 | ret = ov7670_read(sd, REG_GAIN, &gain); | ||
1186 | *value = gain; | ||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | static int ov7670_s_gain(struct v4l2_subdev *sd, int value) | ||
1191 | { | ||
1192 | int ret; | ||
1193 | unsigned char com8; | ||
1194 | |||
1195 | ret = ov7670_write(sd, REG_GAIN, value & 0xff); | ||
1196 | /* Have to turn off AGC as well */ | ||
1197 | if (ret == 0) { | ||
1198 | ret = ov7670_read(sd, REG_COM8, &com8); | ||
1199 | ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AGC); | ||
1200 | } | ||
1201 | return ret; | ||
1202 | } | ||
1203 | |||
1204 | /* | ||
1205 | * Tweak autogain. | ||
1206 | */ | ||
1207 | static int ov7670_g_autogain(struct v4l2_subdev *sd, __s32 *value) | ||
1208 | { | ||
1209 | int ret; | ||
1210 | unsigned char com8; | ||
1211 | |||
1212 | ret = ov7670_read(sd, REG_COM8, &com8); | ||
1213 | *value = (com8 & COM8_AGC) != 0; | ||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1217 | static int ov7670_s_autogain(struct v4l2_subdev *sd, int value) | ||
1218 | { | ||
1219 | int ret; | ||
1220 | unsigned char com8; | ||
1221 | |||
1222 | ret = ov7670_read(sd, REG_COM8, &com8); | ||
1223 | if (ret == 0) { | ||
1224 | if (value) | ||
1225 | com8 |= COM8_AGC; | ||
1226 | else | ||
1227 | com8 &= ~COM8_AGC; | ||
1228 | ret = ov7670_write(sd, REG_COM8, com8); | ||
1229 | } | ||
1230 | return ret; | ||
1231 | } | ||
1232 | |||
1233 | /* | ||
1234 | * Exposure is spread all over the place: top 6 bits in AECHH, middle | ||
1235 | * 8 in AECH, and two stashed in COM1 just for the hell of it. | ||
1236 | */ | ||
1237 | static int ov7670_g_exp(struct v4l2_subdev *sd, __s32 *value) | ||
1238 | { | ||
1239 | int ret; | ||
1240 | unsigned char com1, aech, aechh; | ||
1241 | |||
1242 | ret = ov7670_read(sd, REG_COM1, &com1) + | ||
1243 | ov7670_read(sd, REG_AECH, &aech) + | ||
1244 | ov7670_read(sd, REG_AECHH, &aechh); | ||
1245 | *value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | static int ov7670_s_exp(struct v4l2_subdev *sd, int value) | ||
1250 | { | ||
1251 | int ret; | ||
1252 | unsigned char com1, com8, aech, aechh; | ||
1253 | |||
1254 | ret = ov7670_read(sd, REG_COM1, &com1) + | ||
1255 | ov7670_read(sd, REG_COM8, &com8); | ||
1256 | ov7670_read(sd, REG_AECHH, &aechh); | ||
1257 | if (ret) | ||
1258 | return ret; | ||
1259 | |||
1260 | com1 = (com1 & 0xfc) | (value & 0x03); | ||
1261 | aech = (value >> 2) & 0xff; | ||
1262 | aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f); | ||
1263 | ret = ov7670_write(sd, REG_COM1, com1) + | ||
1264 | ov7670_write(sd, REG_AECH, aech) + | ||
1265 | ov7670_write(sd, REG_AECHH, aechh); | ||
1266 | /* Have to turn off AEC as well */ | ||
1267 | if (ret == 0) | ||
1268 | ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AEC); | ||
1269 | return ret; | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
1273 | * Tweak autoexposure. | ||
1274 | */ | ||
1275 | static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value) | ||
1276 | { | ||
1277 | int ret; | ||
1278 | unsigned char com8; | ||
1279 | enum v4l2_exposure_auto_type *atype = (enum v4l2_exposure_auto_type *) value; | ||
1280 | |||
1281 | ret = ov7670_read(sd, REG_COM8, &com8); | ||
1282 | if (com8 & COM8_AEC) | ||
1283 | *atype = V4L2_EXPOSURE_AUTO; | ||
1284 | else | ||
1285 | *atype = V4L2_EXPOSURE_MANUAL; | ||
1286 | return ret; | ||
1287 | } | ||
1288 | |||
1289 | static int ov7670_s_autoexp(struct v4l2_subdev *sd, | ||
1290 | enum v4l2_exposure_auto_type value) | ||
1291 | { | ||
1292 | int ret; | ||
1293 | unsigned char com8; | ||
1294 | |||
1295 | ret = ov7670_read(sd, REG_COM8, &com8); | ||
1296 | if (ret == 0) { | ||
1297 | if (value == V4L2_EXPOSURE_AUTO) | ||
1298 | com8 |= COM8_AEC; | ||
1299 | else | ||
1300 | com8 &= ~COM8_AEC; | ||
1301 | ret = ov7670_write(sd, REG_COM8, com8); | ||
1302 | } | ||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1306 | |||
1307 | |||
1118 | static int ov7670_queryctrl(struct v4l2_subdev *sd, | 1308 | static int ov7670_queryctrl(struct v4l2_subdev *sd, |
1119 | struct v4l2_queryctrl *qc) | 1309 | struct v4l2_queryctrl *qc) |
1120 | { | 1310 | { |
@@ -1131,6 +1321,14 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd, | |||
1131 | return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); | 1321 | return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); |
1132 | case V4L2_CID_HUE: | 1322 | case V4L2_CID_HUE: |
1133 | return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); | 1323 | return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); |
1324 | case V4L2_CID_GAIN: | ||
1325 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); | ||
1326 | case V4L2_CID_AUTOGAIN: | ||
1327 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1328 | case V4L2_CID_EXPOSURE: | ||
1329 | return v4l2_ctrl_query_fill(qc, 0, 65535, 1, 500); | ||
1330 | case V4L2_CID_EXPOSURE_AUTO: | ||
1331 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); | ||
1134 | } | 1332 | } |
1135 | return -EINVAL; | 1333 | return -EINVAL; |
1136 | } | 1334 | } |
@@ -1150,6 +1348,14 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
1150 | return ov7670_g_vflip(sd, &ctrl->value); | 1348 | return ov7670_g_vflip(sd, &ctrl->value); |
1151 | case V4L2_CID_HFLIP: | 1349 | case V4L2_CID_HFLIP: |
1152 | return ov7670_g_hflip(sd, &ctrl->value); | 1350 | return ov7670_g_hflip(sd, &ctrl->value); |
1351 | case V4L2_CID_GAIN: | ||
1352 | return ov7670_g_gain(sd, &ctrl->value); | ||
1353 | case V4L2_CID_AUTOGAIN: | ||
1354 | return ov7670_g_autogain(sd, &ctrl->value); | ||
1355 | case V4L2_CID_EXPOSURE: | ||
1356 | return ov7670_g_exp(sd, &ctrl->value); | ||
1357 | case V4L2_CID_EXPOSURE_AUTO: | ||
1358 | return ov7670_g_autoexp(sd, &ctrl->value); | ||
1153 | } | 1359 | } |
1154 | return -EINVAL; | 1360 | return -EINVAL; |
1155 | } | 1361 | } |
@@ -1169,6 +1375,15 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
1169 | return ov7670_s_vflip(sd, ctrl->value); | 1375 | return ov7670_s_vflip(sd, ctrl->value); |
1170 | case V4L2_CID_HFLIP: | 1376 | case V4L2_CID_HFLIP: |
1171 | return ov7670_s_hflip(sd, ctrl->value); | 1377 | return ov7670_s_hflip(sd, ctrl->value); |
1378 | case V4L2_CID_GAIN: | ||
1379 | return ov7670_s_gain(sd, ctrl->value); | ||
1380 | case V4L2_CID_AUTOGAIN: | ||
1381 | return ov7670_s_autogain(sd, ctrl->value); | ||
1382 | case V4L2_CID_EXPOSURE: | ||
1383 | return ov7670_s_exp(sd, ctrl->value); | ||
1384 | case V4L2_CID_EXPOSURE_AUTO: | ||
1385 | return ov7670_s_autoexp(sd, | ||
1386 | (enum v4l2_exposure_auto_type) ctrl->value); | ||
1172 | } | 1387 | } |
1173 | return -EINVAL; | 1388 | return -EINVAL; |
1174 | } | 1389 | } |
@@ -1268,6 +1483,7 @@ static int ov7670_probe(struct i2c_client *client, | |||
1268 | 1483 | ||
1269 | info->fmt = &ov7670_formats[0]; | 1484 | info->fmt = &ov7670_formats[0]; |
1270 | info->sat = 128; /* Review this */ | 1485 | info->sat = 128; /* Review this */ |
1486 | info->clkrc = 1; /* 30fps */ | ||
1271 | 1487 | ||
1272 | return 0; | 1488 | return 0; |
1273 | } | 1489 | } |
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 47bf60ceb7a2..36599a65f548 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c | |||
@@ -59,9 +59,9 @@ static const struct ov9640_reg ov9640_regs_dflt[] = { | |||
59 | * COM12 |= OV9640_COM12_YUV_AVG | 59 | * COM12 |= OV9640_COM12_YUV_AVG |
60 | * | 60 | * |
61 | * for RGB, alter the following registers: | 61 | * for RGB, alter the following registers: |
62 | * COM7 |= OV9640_COM7_RGB | 62 | * COM7 |= OV9640_COM7_RGB |
63 | * COM13 |= OV9640_COM13_RGB_AVG | 63 | * COM13 |= OV9640_COM13_RGB_AVG |
64 | * COM15 |= proper RGB color encoding mode | 64 | * COM15 |= proper RGB color encoding mode |
65 | */ | 65 | */ |
66 | static const struct ov9640_reg ov9640_regs_qqcif[] = { | 66 | static const struct ov9640_reg ov9640_regs_qqcif[] = { |
67 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) }, | 67 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) }, |
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 0598bbd3f368..7129b50757db 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -61,7 +61,6 @@ struct pms { | |||
61 | int depth; | 61 | int depth; |
62 | int input; | 62 | int input; |
63 | s32 brightness, saturation, hue, contrast; | 63 | s32 brightness, saturation, hue, contrast; |
64 | unsigned long in_use; | ||
65 | struct mutex lock; | 64 | struct mutex lock; |
66 | int i2c_count; | 65 | int i2c_count; |
67 | struct i2c_info i2cinfo[64]; | 66 | struct i2c_info i2cinfo[64]; |
@@ -931,25 +930,8 @@ static ssize_t pms_read(struct file *file, char __user *buf, | |||
931 | return len; | 930 | return len; |
932 | } | 931 | } |
933 | 932 | ||
934 | static int pms_exclusive_open(struct file *file) | ||
935 | { | ||
936 | struct pms *dev = video_drvdata(file); | ||
937 | |||
938 | return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0; | ||
939 | } | ||
940 | |||
941 | static int pms_exclusive_release(struct file *file) | ||
942 | { | ||
943 | struct pms *dev = video_drvdata(file); | ||
944 | |||
945 | clear_bit(0, &dev->in_use); | ||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | static const struct v4l2_file_operations pms_fops = { | 933 | static const struct v4l2_file_operations pms_fops = { |
950 | .owner = THIS_MODULE, | 934 | .owner = THIS_MODULE, |
951 | .open = pms_exclusive_open, | ||
952 | .release = pms_exclusive_release, | ||
953 | .ioctl = video_ioctl2, | 935 | .ioctl = video_ioctl2, |
954 | .read = pms_read, | 936 | .read = pms_read, |
955 | }; | 937 | }; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 712b300f723f..301ef197d038 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -2028,7 +2028,7 @@ static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw) | |||
2028 | memset(&fmt, 0, sizeof(fmt)); | 2028 | memset(&fmt, 0, sizeof(fmt)); |
2029 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | 2029 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; |
2030 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, | 2030 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, |
2031 | video, s_fmt, &fmt); | 2031 | vbi, s_sliced_fmt, &fmt.fmt.sliced); |
2032 | } | 2032 | } |
2033 | 2033 | ||
2034 | 2034 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index bf1e0fe9f4d2..5ffa0d2b0b0d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -49,7 +49,7 @@ struct pvr2_v4l2_dev { | |||
49 | 49 | ||
50 | struct pvr2_v4l2_fh { | 50 | struct pvr2_v4l2_fh { |
51 | struct pvr2_channel channel; | 51 | struct pvr2_channel channel; |
52 | struct pvr2_v4l2_dev *dev_info; | 52 | struct pvr2_v4l2_dev *pdi; |
53 | enum v4l2_priority prio; | 53 | enum v4l2_priority prio; |
54 | struct pvr2_ioread *rhp; | 54 | struct pvr2_ioread *rhp; |
55 | struct file *file; | 55 | struct file *file; |
@@ -162,7 +162,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
162 | { | 162 | { |
163 | struct pvr2_v4l2_fh *fh = file->private_data; | 163 | struct pvr2_v4l2_fh *fh = file->private_data; |
164 | struct pvr2_v4l2 *vp = fh->vhead; | 164 | struct pvr2_v4l2 *vp = fh->vhead; |
165 | struct pvr2_v4l2_dev *dev_info = fh->dev_info; | 165 | struct pvr2_v4l2_dev *pdi = fh->pdi; |
166 | struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; | 166 | struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; |
167 | long ret = -EINVAL; | 167 | long ret = -EINVAL; |
168 | 168 | ||
@@ -183,7 +183,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
183 | case VIDIOC_S_INPUT: | 183 | case VIDIOC_S_INPUT: |
184 | case VIDIOC_S_TUNER: | 184 | case VIDIOC_S_TUNER: |
185 | case VIDIOC_S_FREQUENCY: | 185 | case VIDIOC_S_FREQUENCY: |
186 | ret = v4l2_prio_check(&vp->prio, &fh->prio); | 186 | ret = v4l2_prio_check(&vp->prio, fh->prio); |
187 | if (ret) | 187 | if (ret) |
188 | return ret; | 188 | return ret; |
189 | } | 189 | } |
@@ -564,14 +564,14 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
564 | 564 | ||
565 | case VIDIOC_STREAMON: | 565 | case VIDIOC_STREAMON: |
566 | { | 566 | { |
567 | if (!fh->dev_info->stream) { | 567 | if (!fh->pdi->stream) { |
568 | /* No stream defined for this node. This means | 568 | /* No stream defined for this node. This means |
569 | that we're not currently allowed to stream from | 569 | that we're not currently allowed to stream from |
570 | this node. */ | 570 | this node. */ |
571 | ret = -EPERM; | 571 | ret = -EPERM; |
572 | break; | 572 | break; |
573 | } | 573 | } |
574 | ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); | 574 | ret = pvr2_hdw_set_stream_type(hdw,pdi->config); |
575 | if (ret < 0) return ret; | 575 | if (ret < 0) return ret; |
576 | ret = pvr2_hdw_set_streaming(hdw,!0); | 576 | ret = pvr2_hdw_set_streaming(hdw,!0); |
577 | break; | 577 | break; |
@@ -579,7 +579,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
579 | 579 | ||
580 | case VIDIOC_STREAMOFF: | 580 | case VIDIOC_STREAMOFF: |
581 | { | 581 | { |
582 | if (!fh->dev_info->stream) { | 582 | if (!fh->pdi->stream) { |
583 | /* No stream defined for this node. This means | 583 | /* No stream defined for this node. This means |
584 | that we're not currently allowed to stream from | 584 | that we're not currently allowed to stream from |
585 | this node. */ | 585 | this node. */ |
@@ -972,7 +972,7 @@ static int pvr2_v4l2_release(struct file *file) | |||
972 | fhp->rhp = NULL; | 972 | fhp->rhp = NULL; |
973 | } | 973 | } |
974 | 974 | ||
975 | v4l2_prio_close(&vp->prio, &fhp->prio); | 975 | v4l2_prio_close(&vp->prio, fhp->prio); |
976 | file->private_data = NULL; | 976 | file->private_data = NULL; |
977 | 977 | ||
978 | if (fhp->vnext) { | 978 | if (fhp->vnext) { |
@@ -1032,7 +1032,7 @@ static int pvr2_v4l2_open(struct file *file) | |||
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | init_waitqueue_head(&fhp->wait_data); | 1034 | init_waitqueue_head(&fhp->wait_data); |
1035 | fhp->dev_info = dip; | 1035 | fhp->pdi = dip; |
1036 | 1036 | ||
1037 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); | 1037 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); |
1038 | pvr2_channel_init(&fhp->channel,vp->channel.mc_head); | 1038 | pvr2_channel_init(&fhp->channel,vp->channel.mc_head); |
@@ -1093,7 +1093,7 @@ static int pvr2_v4l2_open(struct file *file) | |||
1093 | 1093 | ||
1094 | fhp->file = file; | 1094 | fhp->file = file; |
1095 | file->private_data = fhp; | 1095 | file->private_data = fhp; |
1096 | v4l2_prio_open(&vp->prio,&fhp->prio); | 1096 | v4l2_prio_open(&vp->prio, &fhp->prio); |
1097 | 1097 | ||
1098 | fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); | 1098 | fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); |
1099 | 1099 | ||
@@ -1113,7 +1113,7 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) | |||
1113 | struct pvr2_hdw *hdw; | 1113 | struct pvr2_hdw *hdw; |
1114 | if (fh->rhp) return 0; | 1114 | if (fh->rhp) return 0; |
1115 | 1115 | ||
1116 | if (!fh->dev_info->stream) { | 1116 | if (!fh->pdi->stream) { |
1117 | /* No stream defined for this node. This means that we're | 1117 | /* No stream defined for this node. This means that we're |
1118 | not currently allowed to stream from this node. */ | 1118 | not currently allowed to stream from this node. */ |
1119 | return -EPERM; | 1119 | return -EPERM; |
@@ -1122,21 +1122,21 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) | |||
1122 | /* First read() attempt. Try to claim the stream and start | 1122 | /* First read() attempt. Try to claim the stream and start |
1123 | it... */ | 1123 | it... */ |
1124 | if ((ret = pvr2_channel_claim_stream(&fh->channel, | 1124 | if ((ret = pvr2_channel_claim_stream(&fh->channel, |
1125 | fh->dev_info->stream)) != 0) { | 1125 | fh->pdi->stream)) != 0) { |
1126 | /* Someone else must already have it */ | 1126 | /* Someone else must already have it */ |
1127 | return ret; | 1127 | return ret; |
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream); | 1130 | fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream); |
1131 | if (!fh->rhp) { | 1131 | if (!fh->rhp) { |
1132 | pvr2_channel_claim_stream(&fh->channel,NULL); | 1132 | pvr2_channel_claim_stream(&fh->channel,NULL); |
1133 | return -ENOMEM; | 1133 | return -ENOMEM; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | hdw = fh->channel.mc_head->hdw; | 1136 | hdw = fh->channel.mc_head->hdw; |
1137 | sp = fh->dev_info->stream->stream; | 1137 | sp = fh->pdi->stream->stream; |
1138 | pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh); | 1138 | pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh); |
1139 | pvr2_hdw_set_stream_type(hdw,fh->dev_info->config); | 1139 | pvr2_hdw_set_stream_type(hdw,fh->pdi->config); |
1140 | if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret; | 1140 | if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret; |
1141 | return pvr2_ioread_set_enabled(fh->rhp,!0); | 1141 | return pvr2_ioread_set_enabled(fh->rhp,!0); |
1142 | } | 1142 | } |
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 340f954aba34..11980db22d31 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig | |||
@@ -39,7 +39,7 @@ config USB_PWC_DEBUG | |||
39 | config USB_PWC_INPUT_EVDEV | 39 | config USB_PWC_INPUT_EVDEV |
40 | bool "USB Philips Cameras input events device support" | 40 | bool "USB Philips Cameras input events device support" |
41 | default y | 41 | default y |
42 | depends on USB_PWC=INPUT || INPUT=y | 42 | depends on USB_PWC && (USB_PWC=INPUT || INPUT=y) |
43 | ---help--- | 43 | ---help--- |
44 | This option makes USB Philips cameras register the snapshot button as | 44 | This option makes USB Philips cameras register the snapshot button as |
45 | an input device to report button events. | 45 | an input device to report button events. |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 04bf5c11308d..7fe70e718656 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -253,8 +253,8 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
253 | 253 | ||
254 | if (0 == *count) | 254 | if (0 == *count) |
255 | *count = 32; | 255 | *count = 32; |
256 | while (*size * *count > vid_limit * 1024 * 1024) | 256 | if (*size * *count > vid_limit * 1024 * 1024) |
257 | (*count)--; | 257 | *count = (vid_limit * 1024 * 1024) / *size; |
258 | 258 | ||
259 | return 0; | 259 | return 0; |
260 | } | 260 | } |
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 9277194cd821..bbd9c11e2c5a 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -555,15 +555,15 @@ static int rj54n1_commit(struct i2c_client *client) | |||
555 | return ret; | 555 | return ret; |
556 | } | 556 | } |
557 | 557 | ||
558 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | 558 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, |
559 | u32 *out_w, u32 *out_h); | 559 | s32 *out_w, s32 *out_h); |
560 | 560 | ||
561 | static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 561 | static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
562 | { | 562 | { |
563 | struct i2c_client *client = sd->priv; | 563 | struct i2c_client *client = sd->priv; |
564 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 564 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
565 | struct v4l2_rect *rect = &a->c; | 565 | struct v4l2_rect *rect = &a->c; |
566 | unsigned int dummy = 0, output_w, output_h, | 566 | int dummy = 0, output_w, output_h, |
567 | input_w = rect->width, input_h = rect->height; | 567 | input_w = rect->width, input_h = rect->height; |
568 | int ret; | 568 | int ret; |
569 | 569 | ||
@@ -577,7 +577,7 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
577 | output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize; | 577 | output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize; |
578 | output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize; | 578 | output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize; |
579 | 579 | ||
580 | dev_dbg(&client->dev, "Scaling for %ux%u : %u = %ux%u\n", | 580 | dev_dbg(&client->dev, "Scaling for %dx%d : %u = %dx%d\n", |
581 | input_w, input_h, rj54n1->resize, output_w, output_h); | 581 | input_w, input_h, rj54n1->resize, output_w, output_h); |
582 | 582 | ||
583 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); | 583 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); |
@@ -638,8 +638,8 @@ static int rj54n1_g_fmt(struct v4l2_subdev *sd, | |||
638 | * the output one, updates the window sizes and returns an error or the resize | 638 | * the output one, updates the window sizes and returns an error or the resize |
639 | * coefficient on success. Note: we only use the "Fixed Scaling" on this camera. | 639 | * coefficient on success. Note: we only use the "Fixed Scaling" on this camera. |
640 | */ | 640 | */ |
641 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | 641 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, |
642 | u32 *out_w, u32 *out_h) | 642 | s32 *out_w, s32 *out_h) |
643 | { | 643 | { |
644 | struct i2c_client *client = sd->priv; | 644 | struct i2c_client *client = sd->priv; |
645 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 645 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
@@ -749,7 +749,7 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
749 | * improve the image quality or stability for larger frames (see comment | 749 | * improve the image quality or stability for larger frames (see comment |
750 | * above), but I didn't check the framerate. | 750 | * above), but I didn't check the framerate. |
751 | */ | 751 | */ |
752 | skip = min(resize / 1024, (unsigned)15); | 752 | skip = min(resize / 1024, 15U); |
753 | 753 | ||
754 | inc_sel = 1 << skip; | 754 | inc_sel = 1 << skip; |
755 | 755 | ||
@@ -819,7 +819,7 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
819 | *out_w = output_w; | 819 | *out_w = output_w; |
820 | *out_h = output_h; | 820 | *out_h = output_h; |
821 | 821 | ||
822 | dev_dbg(&client->dev, "Scaled for %ux%u : %u = %ux%u, skip %u\n", | 822 | dev_dbg(&client->dev, "Scaled for %dx%d : %u = %ux%u, skip %u\n", |
823 | *in_w, *in_h, resize, output_w, output_h, skip); | 823 | *in_w, *in_h, resize, output_w, output_h, skip); |
824 | 824 | ||
825 | return resize; | 825 | return resize; |
@@ -1017,7 +1017,7 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, | |||
1017 | struct i2c_client *client = sd->priv; | 1017 | struct i2c_client *client = sd->priv; |
1018 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 1018 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
1019 | const struct rj54n1_datafmt *fmt; | 1019 | const struct rj54n1_datafmt *fmt; |
1020 | unsigned int output_w, output_h, max_w, max_h, | 1020 | int output_w, output_h, max_w, max_h, |
1021 | input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; | 1021 | input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; |
1022 | int ret; | 1022 | int ret; |
1023 | 1023 | ||
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 3de914deb8ee..3c7a79f3812a 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device | 2 | * s2255drv.c - a driver for the Sensoray 2255 USB video capture device |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 by Sensoray Company Inc. | 4 | * Copyright (C) 2007-2010 by Sensoray Company Inc. |
5 | * Dean Anderson | 5 | * Dean Anderson |
6 | * | 6 | * |
7 | * Some video buffer code based on vivi driver: | 7 | * Some video buffer code based on vivi driver: |
@@ -52,14 +52,19 @@ | |||
52 | #include <linux/smp_lock.h> | 52 | #include <linux/smp_lock.h> |
53 | #include <media/videobuf-vmalloc.h> | 53 | #include <media/videobuf-vmalloc.h> |
54 | #include <media/v4l2-common.h> | 54 | #include <media/v4l2-common.h> |
55 | #include <media/v4l2-device.h> | ||
55 | #include <media/v4l2-ioctl.h> | 56 | #include <media/v4l2-ioctl.h> |
56 | #include <linux/vmalloc.h> | 57 | #include <linux/vmalloc.h> |
57 | #include <linux/usb.h> | 58 | #include <linux/usb.h> |
58 | 59 | ||
60 | #define S2255_MAJOR_VERSION 1 | ||
61 | #define S2255_MINOR_VERSION 20 | ||
62 | #define S2255_RELEASE 0 | ||
63 | #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ | ||
64 | S2255_MINOR_VERSION, \ | ||
65 | S2255_RELEASE) | ||
59 | #define FIRMWARE_FILE_NAME "f2255usb.bin" | 66 | #define FIRMWARE_FILE_NAME "f2255usb.bin" |
60 | 67 | ||
61 | |||
62 | |||
63 | /* default JPEG quality */ | 68 | /* default JPEG quality */ |
64 | #define S2255_DEF_JPEG_QUAL 50 | 69 | #define S2255_DEF_JPEG_QUAL 50 |
65 | /* vendor request in */ | 70 | /* vendor request in */ |
@@ -76,14 +81,14 @@ | |||
76 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) | 81 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) |
77 | #define S2255_DEF_BUFS 16 | 82 | #define S2255_DEF_BUFS 16 |
78 | #define S2255_SETMODE_TIMEOUT 500 | 83 | #define S2255_SETMODE_TIMEOUT 500 |
79 | #define MAX_CHANNELS 4 | 84 | #define S2255_VIDSTATUS_TIMEOUT 350 |
80 | #define S2255_MARKER_FRAME 0x2255DA4AL | 85 | #define S2255_MARKER_FRAME cpu_to_le32(0x2255DA4AL) |
81 | #define S2255_MARKER_RESPONSE 0x2255ACACL | 86 | #define S2255_MARKER_RESPONSE cpu_to_le32(0x2255ACACL) |
82 | #define S2255_RESPONSE_SETMODE 0x01 | 87 | #define S2255_RESPONSE_SETMODE cpu_to_le32(0x01) |
83 | #define S2255_RESPONSE_FW 0x10 | 88 | #define S2255_RESPONSE_FW cpu_to_le32(0x10) |
89 | #define S2255_RESPONSE_STATUS cpu_to_le32(0x20) | ||
84 | #define S2255_USB_XFER_SIZE (16 * 1024) | 90 | #define S2255_USB_XFER_SIZE (16 * 1024) |
85 | #define MAX_CHANNELS 4 | 91 | #define MAX_CHANNELS 4 |
86 | #define MAX_PIPE_BUFFERS 1 | ||
87 | #define SYS_FRAMES 4 | 92 | #define SYS_FRAMES 4 |
88 | /* maximum size is PAL full size plus room for the marker header(s) */ | 93 | /* maximum size is PAL full size plus room for the marker header(s) */ |
89 | #define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) | 94 | #define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) |
@@ -118,9 +123,10 @@ | |||
118 | #define COLOR_YUVPK 2 /* YUV packed */ | 123 | #define COLOR_YUVPK 2 /* YUV packed */ |
119 | #define COLOR_Y8 4 /* monochrome */ | 124 | #define COLOR_Y8 4 /* monochrome */ |
120 | #define COLOR_JPG 5 /* JPEG */ | 125 | #define COLOR_JPG 5 /* JPEG */ |
121 | #define MASK_COLOR 0xff | ||
122 | #define MASK_JPG_QUALITY 0xff00 | ||
123 | 126 | ||
127 | #define MASK_COLOR 0x000000ff | ||
128 | #define MASK_JPG_QUALITY 0x0000ff00 | ||
129 | #define MASK_INPUT_TYPE 0x000f0000 | ||
124 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ | 130 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ |
125 | #define FDEC_1 1 /* capture every frame. default */ | 131 | #define FDEC_1 1 /* capture every frame. default */ |
126 | #define FDEC_2 2 /* capture every 2nd frame */ | 132 | #define FDEC_2 2 /* capture every 2nd frame */ |
@@ -139,12 +145,12 @@ | |||
139 | #define DEF_HUE 0 | 145 | #define DEF_HUE 0 |
140 | 146 | ||
141 | /* usb config commands */ | 147 | /* usb config commands */ |
142 | #define IN_DATA_TOKEN 0x2255c0de | 148 | #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) |
143 | #define CMD_2255 0xc2255000 | 149 | #define CMD_2255 cpu_to_le32(0xc2255000) |
144 | #define CMD_SET_MODE (CMD_2255 | 0x10) | 150 | #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) |
145 | #define CMD_START (CMD_2255 | 0x20) | 151 | #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) |
146 | #define CMD_STOP (CMD_2255 | 0x30) | 152 | #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) |
147 | #define CMD_STATUS (CMD_2255 | 0x40) | 153 | #define CMD_STATUS cpu_to_le32((CMD_2255 | 0x40)) |
148 | 154 | ||
149 | struct s2255_mode { | 155 | struct s2255_mode { |
150 | u32 format; /* input video format (NTSC, PAL) */ | 156 | u32 format; /* input video format (NTSC, PAL) */ |
@@ -194,7 +200,6 @@ struct s2255_dmaqueue { | |||
194 | #define S2255_FW_SUCCESS 2 | 200 | #define S2255_FW_SUCCESS 2 |
195 | #define S2255_FW_FAILED 3 | 201 | #define S2255_FW_FAILED 3 |
196 | #define S2255_FW_DISCONNECTING 4 | 202 | #define S2255_FW_DISCONNECTING 4 |
197 | |||
198 | #define S2255_FW_MARKER cpu_to_le32(0x22552f2f) | 203 | #define S2255_FW_MARKER cpu_to_le32(0x22552f2f) |
199 | /* 2255 read states */ | 204 | /* 2255 read states */ |
200 | #define S2255_READ_IDLE 0 | 205 | #define S2255_READ_IDLE 0 |
@@ -223,8 +228,10 @@ struct s2255_pipeinfo { | |||
223 | struct s2255_fmt; /*forward declaration */ | 228 | struct s2255_fmt; /*forward declaration */ |
224 | 229 | ||
225 | struct s2255_dev { | 230 | struct s2255_dev { |
231 | struct video_device vdev[MAX_CHANNELS]; | ||
232 | struct v4l2_device v4l2_dev; | ||
233 | atomic_t channels; /* number of channels registered */ | ||
226 | int frames; | 234 | int frames; |
227 | int users[MAX_CHANNELS]; | ||
228 | struct mutex lock; | 235 | struct mutex lock; |
229 | struct mutex open_lock; | 236 | struct mutex open_lock; |
230 | int resources[MAX_CHANNELS]; | 237 | int resources[MAX_CHANNELS]; |
@@ -233,11 +240,10 @@ struct s2255_dev { | |||
233 | u8 read_endpoint; | 240 | u8 read_endpoint; |
234 | 241 | ||
235 | struct s2255_dmaqueue vidq[MAX_CHANNELS]; | 242 | struct s2255_dmaqueue vidq[MAX_CHANNELS]; |
236 | struct video_device *vdev[MAX_CHANNELS]; | ||
237 | struct timer_list timer; | 243 | struct timer_list timer; |
238 | struct s2255_fw *fw_data; | 244 | struct s2255_fw *fw_data; |
239 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; | 245 | struct s2255_pipeinfo pipe; |
240 | struct s2255_bufferi buffer[MAX_CHANNELS]; | 246 | struct s2255_bufferi buffer[MAX_CHANNELS]; |
241 | struct s2255_mode mode[MAX_CHANNELS]; | 247 | struct s2255_mode mode[MAX_CHANNELS]; |
242 | /* jpeg compression */ | 248 | /* jpeg compression */ |
243 | struct v4l2_jpegcompression jc[MAX_CHANNELS]; | 249 | struct v4l2_jpegcompression jc[MAX_CHANNELS]; |
@@ -261,11 +267,21 @@ struct s2255_dev { | |||
261 | int chn_configured[MAX_CHANNELS]; | 267 | int chn_configured[MAX_CHANNELS]; |
262 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; | 268 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; |
263 | int setmode_ready[MAX_CHANNELS]; | 269 | int setmode_ready[MAX_CHANNELS]; |
270 | /* video status items */ | ||
271 | int vidstatus[MAX_CHANNELS]; | ||
272 | wait_queue_head_t wait_vidstatus[MAX_CHANNELS]; | ||
273 | int vidstatus_ready[MAX_CHANNELS]; | ||
264 | int chn_ready; | 274 | int chn_ready; |
265 | struct kref kref; | ||
266 | spinlock_t slock; | 275 | spinlock_t slock; |
276 | /* dsp firmware version (f2255usb.bin) */ | ||
277 | int dsp_fw_ver; | ||
278 | u16 pid; /* product id */ | ||
267 | }; | 279 | }; |
268 | #define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) | 280 | |
281 | static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) | ||
282 | { | ||
283 | return container_of(v4l2_dev, struct s2255_dev, v4l2_dev); | ||
284 | } | ||
269 | 285 | ||
270 | struct s2255_fmt { | 286 | struct s2255_fmt { |
271 | char *name; | 287 | char *name; |
@@ -296,17 +312,43 @@ struct s2255_fh { | |||
296 | 312 | ||
297 | /* current cypress EEPROM firmware version */ | 313 | /* current cypress EEPROM firmware version */ |
298 | #define S2255_CUR_USB_FWVER ((3 << 8) | 6) | 314 | #define S2255_CUR_USB_FWVER ((3 << 8) | 6) |
299 | #define S2255_MAJOR_VERSION 1 | 315 | /* current DSP FW version */ |
300 | #define S2255_MINOR_VERSION 14 | 316 | #define S2255_CUR_DSP_FWVER 8 |
301 | #define S2255_RELEASE 0 | 317 | /* Need DSP version 5+ for video status feature */ |
302 | #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ | 318 | #define S2255_MIN_DSP_STATUS 5 |
303 | S2255_MINOR_VERSION, \ | 319 | #define S2255_MIN_DSP_COLORFILTER 8 |
304 | S2255_RELEASE) | ||
305 | |||
306 | /* vendor ids */ | ||
307 | #define USB_S2255_VENDOR_ID 0x1943 | ||
308 | #define USB_S2255_PRODUCT_ID 0x2255 | ||
309 | #define S2255_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC) | 320 | #define S2255_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC) |
321 | |||
322 | /* private V4L2 controls */ | ||
323 | |||
324 | /* | ||
325 | * The following chart displays how COLORFILTER should be set | ||
326 | * ========================================================= | ||
327 | * = fourcc = COLORFILTER = | ||
328 | * = =============================== | ||
329 | * = = 0 = 1 = | ||
330 | * ========================================================= | ||
331 | * = V4L2_PIX_FMT_GREY(Y8) = monochrome from = monochrome= | ||
332 | * = = s-video or = composite = | ||
333 | * = = B/W camera = input = | ||
334 | * ========================================================= | ||
335 | * = other = color, svideo = color, = | ||
336 | * = = = composite = | ||
337 | * ========================================================= | ||
338 | * | ||
339 | * Notes: | ||
340 | * channels 0-3 on 2255 are composite | ||
341 | * channels 0-1 on 2257 are composite, 2-3 are s-video | ||
342 | * If COLORFILTER is 0 with a composite color camera connected, | ||
343 | * the output will appear monochrome but hatching | ||
344 | * will occur. | ||
345 | * COLORFILTER is different from "color killer" and "color effects" | ||
346 | * for reasons above. | ||
347 | */ | ||
348 | #define S2255_V4L2_YC_ON 1 | ||
349 | #define S2255_V4L2_YC_OFF 0 | ||
350 | #define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0) | ||
351 | |||
310 | /* frame prefix size (sent once every frame) */ | 352 | /* frame prefix size (sent once every frame) */ |
311 | #define PREFIX_SIZE 512 | 353 | #define PREFIX_SIZE 512 |
312 | 354 | ||
@@ -325,9 +367,8 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
325 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | 367 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, |
326 | struct s2255_mode *mode); | 368 | struct s2255_mode *mode); |
327 | static int s2255_board_shutdown(struct s2255_dev *dev); | 369 | static int s2255_board_shutdown(struct s2255_dev *dev); |
328 | static void s2255_exit_v4l(struct s2255_dev *dev); | ||
329 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); | 370 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); |
330 | static void s2255_destroy(struct kref *kref); | 371 | static void s2255_destroy(struct s2255_dev *dev); |
331 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, | 372 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, |
332 | u16 index, u16 value, void *buf, | 373 | u16 index, u16 value, void *buf, |
333 | s32 buf_len, int bOut); | 374 | s32 buf_len, int bOut); |
@@ -347,7 +388,6 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, | |||
347 | 388 | ||
348 | static struct usb_driver s2255_driver; | 389 | static struct usb_driver s2255_driver; |
349 | 390 | ||
350 | |||
351 | /* Declare static vars that will be used as parameters */ | 391 | /* Declare static vars that will be used as parameters */ |
352 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ | 392 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ |
353 | 393 | ||
@@ -362,58 +402,16 @@ module_param(video_nr, int, 0644); | |||
362 | MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)"); | 402 | MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)"); |
363 | 403 | ||
364 | /* USB device table */ | 404 | /* USB device table */ |
405 | #define USB_SENSORAY_VID 0x1943 | ||
365 | static struct usb_device_id s2255_table[] = { | 406 | static struct usb_device_id s2255_table[] = { |
366 | {USB_DEVICE(USB_S2255_VENDOR_ID, USB_S2255_PRODUCT_ID)}, | 407 | {USB_DEVICE(USB_SENSORAY_VID, 0x2255)}, |
408 | {USB_DEVICE(USB_SENSORAY_VID, 0x2257)}, /*same family as 2255*/ | ||
367 | { } /* Terminating entry */ | 409 | { } /* Terminating entry */ |
368 | }; | 410 | }; |
369 | MODULE_DEVICE_TABLE(usb, s2255_table); | 411 | MODULE_DEVICE_TABLE(usb, s2255_table); |
370 | 412 | ||
371 | |||
372 | #define BUFFER_TIMEOUT msecs_to_jiffies(400) | 413 | #define BUFFER_TIMEOUT msecs_to_jiffies(400) |
373 | 414 | ||
374 | /* supported controls */ | ||
375 | static struct v4l2_queryctrl s2255_qctrl[] = { | ||
376 | { | ||
377 | .id = V4L2_CID_BRIGHTNESS, | ||
378 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
379 | .name = "Brightness", | ||
380 | .minimum = -127, | ||
381 | .maximum = 128, | ||
382 | .step = 1, | ||
383 | .default_value = 0, | ||
384 | .flags = 0, | ||
385 | }, { | ||
386 | .id = V4L2_CID_CONTRAST, | ||
387 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
388 | .name = "Contrast", | ||
389 | .minimum = 0, | ||
390 | .maximum = 255, | ||
391 | .step = 0x1, | ||
392 | .default_value = DEF_CONTRAST, | ||
393 | .flags = 0, | ||
394 | }, { | ||
395 | .id = V4L2_CID_SATURATION, | ||
396 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
397 | .name = "Saturation", | ||
398 | .minimum = 0, | ||
399 | .maximum = 255, | ||
400 | .step = 0x1, | ||
401 | .default_value = DEF_SATURATION, | ||
402 | .flags = 0, | ||
403 | }, { | ||
404 | .id = V4L2_CID_HUE, | ||
405 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
406 | .name = "Hue", | ||
407 | .minimum = 0, | ||
408 | .maximum = 255, | ||
409 | .step = 0x1, | ||
410 | .default_value = DEF_HUE, | ||
411 | .flags = 0, | ||
412 | } | ||
413 | }; | ||
414 | |||
415 | static int qctl_regs[ARRAY_SIZE(s2255_qctrl)]; | ||
416 | |||
417 | /* image formats. */ | 415 | /* image formats. */ |
418 | static const struct s2255_fmt formats[] = { | 416 | static const struct s2255_fmt formats[] = { |
419 | { | 417 | { |
@@ -505,7 +503,7 @@ static void s2255_reset_dsppower(struct s2255_dev *dev) | |||
505 | static void s2255_timer(unsigned long user_data) | 503 | static void s2255_timer(unsigned long user_data) |
506 | { | 504 | { |
507 | struct s2255_fw *data = (struct s2255_fw *)user_data; | 505 | struct s2255_fw *data = (struct s2255_fw *)user_data; |
508 | dprintk(100, "s2255 timer\n"); | 506 | dprintk(100, "%s\n", __func__); |
509 | if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { | 507 | if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { |
510 | printk(KERN_ERR "s2255: can't submit urb\n"); | 508 | printk(KERN_ERR "s2255: can't submit urb\n"); |
511 | atomic_set(&data->fw_state, S2255_FW_FAILED); | 509 | atomic_set(&data->fw_state, S2255_FW_FAILED); |
@@ -527,7 +525,7 @@ static void s2255_fwchunk_complete(struct urb *urb) | |||
527 | struct s2255_fw *data = urb->context; | 525 | struct s2255_fw *data = urb->context; |
528 | struct usb_device *udev = urb->dev; | 526 | struct usb_device *udev = urb->dev; |
529 | int len; | 527 | int len; |
530 | dprintk(100, "udev %p urb %p", udev, urb); | 528 | dprintk(100, "%s: udev %p urb %p", __func__, udev, urb); |
531 | if (urb->status) { | 529 | if (urb->status) { |
532 | dev_err(&udev->dev, "URB failed with status %d\n", urb->status); | 530 | dev_err(&udev->dev, "URB failed with status %d\n", urb->status); |
533 | atomic_set(&data->fw_state, S2255_FW_FAILED); | 531 | atomic_set(&data->fw_state, S2255_FW_FAILED); |
@@ -573,8 +571,8 @@ static void s2255_fwchunk_complete(struct urb *urb) | |||
573 | data->fw_loaded += len; | 571 | data->fw_loaded += len; |
574 | } else { | 572 | } else { |
575 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); | 573 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); |
574 | dprintk(100, "%s: firmware upload complete\n", __func__); | ||
576 | } | 575 | } |
577 | dprintk(100, "2255 complete done\n"); | ||
578 | return; | 576 | return; |
579 | 577 | ||
580 | } | 578 | } |
@@ -585,9 +583,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) | |||
585 | struct s2255_buffer *buf; | 583 | struct s2255_buffer *buf; |
586 | unsigned long flags = 0; | 584 | unsigned long flags = 0; |
587 | int rc = 0; | 585 | int rc = 0; |
588 | dprintk(2, "wakeup: %p channel: %d\n", &dma_q, chn); | ||
589 | spin_lock_irqsave(&dev->slock, flags); | 586 | spin_lock_irqsave(&dev->slock, flags); |
590 | |||
591 | if (list_empty(&dma_q->active)) { | 587 | if (list_empty(&dma_q->active)) { |
592 | dprintk(1, "No active queue to serve\n"); | 588 | dprintk(1, "No active queue to serve\n"); |
593 | rc = -1; | 589 | rc = -1; |
@@ -595,23 +591,19 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) | |||
595 | } | 591 | } |
596 | buf = list_entry(dma_q->active.next, | 592 | buf = list_entry(dma_q->active.next, |
597 | struct s2255_buffer, vb.queue); | 593 | struct s2255_buffer, vb.queue); |
598 | |||
599 | list_del(&buf->vb.queue); | 594 | list_del(&buf->vb.queue); |
600 | do_gettimeofday(&buf->vb.ts); | 595 | do_gettimeofday(&buf->vb.ts); |
601 | dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); | ||
602 | s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); | 596 | s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); |
603 | wake_up(&buf->vb.done); | 597 | wake_up(&buf->vb.done); |
604 | dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); | 598 | dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i); |
605 | unlock: | 599 | unlock: |
606 | spin_unlock_irqrestore(&dev->slock, flags); | 600 | spin_unlock_irqrestore(&dev->slock, flags); |
607 | return 0; | 601 | return 0; |
608 | } | 602 | } |
609 | 603 | ||
610 | |||
611 | static const struct s2255_fmt *format_by_fourcc(int fourcc) | 604 | static const struct s2255_fmt *format_by_fourcc(int fourcc) |
612 | { | 605 | { |
613 | unsigned int i; | 606 | unsigned int i; |
614 | |||
615 | for (i = 0; i < ARRAY_SIZE(formats); i++) { | 607 | for (i = 0; i < ARRAY_SIZE(formats); i++) { |
616 | if (-1 == formats[i].fourcc) | 608 | if (-1 == formats[i].fourcc) |
617 | continue; | 609 | continue; |
@@ -621,9 +613,6 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) | |||
621 | return NULL; | 613 | return NULL; |
622 | } | 614 | } |
623 | 615 | ||
624 | |||
625 | |||
626 | |||
627 | /* video buffer vmalloc implementation based partly on VIVI driver which is | 616 | /* video buffer vmalloc implementation based partly on VIVI driver which is |
628 | * Copyright (c) 2006 by | 617 | * Copyright (c) 2006 by |
629 | * Mauro Carvalho Chehab <mchehab--a.t--infradead.org> | 618 | * Mauro Carvalho Chehab <mchehab--a.t--infradead.org> |
@@ -703,8 +692,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | |||
703 | if (0 == *count) | 692 | if (0 == *count) |
704 | *count = S2255_DEF_BUFS; | 693 | *count = S2255_DEF_BUFS; |
705 | 694 | ||
706 | while (*size * (*count) > vid_limit * 1024 * 1024) | 695 | if (*size * *count > vid_limit * 1024 * 1024) |
707 | (*count)--; | 696 | *count = (vid_limit * 1024 * 1024) / *size; |
708 | 697 | ||
709 | return 0; | 698 | return 0; |
710 | } | 699 | } |
@@ -727,10 +716,10 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
727 | if (fh->fmt == NULL) | 716 | if (fh->fmt == NULL) |
728 | return -EINVAL; | 717 | return -EINVAL; |
729 | 718 | ||
730 | if ((fh->width < norm_minw(fh->dev->vdev[fh->channel])) || | 719 | if ((fh->width < norm_minw(&fh->dev->vdev[fh->channel])) || |
731 | (fh->width > norm_maxw(fh->dev->vdev[fh->channel])) || | 720 | (fh->width > norm_maxw(&fh->dev->vdev[fh->channel])) || |
732 | (fh->height < norm_minh(fh->dev->vdev[fh->channel])) || | 721 | (fh->height < norm_minh(&fh->dev->vdev[fh->channel])) || |
733 | (fh->height > norm_maxh(fh->dev->vdev[fh->channel]))) { | 722 | (fh->height > norm_maxh(&fh->dev->vdev[fh->channel]))) { |
734 | dprintk(4, "invalid buffer prepare\n"); | 723 | dprintk(4, "invalid buffer prepare\n"); |
735 | return -EINVAL; | 724 | return -EINVAL; |
736 | } | 725 | } |
@@ -747,7 +736,6 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
747 | buf->vb.height = fh->height; | 736 | buf->vb.height = fh->height; |
748 | buf->vb.field = field; | 737 | buf->vb.field = field; |
749 | 738 | ||
750 | |||
751 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 739 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
752 | rc = videobuf_iolock(vq, &buf->vb, NULL); | 740 | rc = videobuf_iolock(vq, &buf->vb, NULL); |
753 | if (rc < 0) | 741 | if (rc < 0) |
@@ -767,9 +755,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
767 | struct s2255_fh *fh = vq->priv_data; | 755 | struct s2255_fh *fh = vq->priv_data; |
768 | struct s2255_dev *dev = fh->dev; | 756 | struct s2255_dev *dev = fh->dev; |
769 | struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel]; | 757 | struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel]; |
770 | |||
771 | dprintk(1, "%s\n", __func__); | 758 | dprintk(1, "%s\n", __func__); |
772 | |||
773 | buf->vb.state = VIDEOBUF_QUEUED; | 759 | buf->vb.state = VIDEOBUF_QUEUED; |
774 | list_add_tail(&buf->vb.queue, &vidq->active); | 760 | list_add_tail(&buf->vb.queue, &vidq->active); |
775 | } | 761 | } |
@@ -828,6 +814,27 @@ static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) | |||
828 | dprintk(1, "res: put\n"); | 814 | dprintk(1, "res: put\n"); |
829 | } | 815 | } |
830 | 816 | ||
817 | static int vidioc_querymenu(struct file *file, void *priv, | ||
818 | struct v4l2_querymenu *qmenu) | ||
819 | { | ||
820 | static const char *colorfilter[] = { | ||
821 | "Off", | ||
822 | "On", | ||
823 | NULL | ||
824 | }; | ||
825 | if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) { | ||
826 | int i; | ||
827 | const char **menu_items = colorfilter; | ||
828 | for (i = 0; i < qmenu->index && menu_items[i]; i++) | ||
829 | ; /* do nothing (from v4l2-common.c) */ | ||
830 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') | ||
831 | return -EINVAL; | ||
832 | strlcpy(qmenu->name, menu_items[qmenu->index], | ||
833 | sizeof(qmenu->name)); | ||
834 | return 0; | ||
835 | } | ||
836 | return v4l2_ctrl_query_menu(qmenu, NULL, NULL); | ||
837 | } | ||
831 | 838 | ||
832 | static int vidioc_querycap(struct file *file, void *priv, | 839 | static int vidioc_querycap(struct file *file, void *priv, |
833 | struct v4l2_capability *cap) | 840 | struct v4l2_capability *cap) |
@@ -883,7 +890,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
883 | int is_ntsc; | 890 | int is_ntsc; |
884 | 891 | ||
885 | is_ntsc = | 892 | is_ntsc = |
886 | (dev->vdev[fh->channel]->current_norm & V4L2_STD_NTSC) ? 1 : 0; | 893 | (dev->vdev[fh->channel].current_norm & V4L2_STD_NTSC) ? 1 : 0; |
887 | 894 | ||
888 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 895 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
889 | 896 | ||
@@ -894,10 +901,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
894 | if (field == V4L2_FIELD_ANY) | 901 | if (field == V4L2_FIELD_ANY) |
895 | b_any_field = 1; | 902 | b_any_field = 1; |
896 | 903 | ||
897 | dprintk(4, "try format %d \n", is_ntsc); | 904 | dprintk(50, "%s NTSC: %d suggested width: %d, height: %d\n", |
898 | /* supports 3 sizes. see s2255drv.h */ | 905 | __func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height); |
899 | dprintk(50, "width test %d, height %d\n", | ||
900 | f->fmt.pix.width, f->fmt.pix.height); | ||
901 | if (is_ntsc) { | 906 | if (is_ntsc) { |
902 | /* NTSC */ | 907 | /* NTSC */ |
903 | if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) { | 908 | if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) { |
@@ -952,29 +957,24 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
952 | } | 957 | } |
953 | } | 958 | } |
954 | if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) { | 959 | if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) { |
955 | dprintk(50, "pal 704\n"); | ||
956 | f->fmt.pix.width = LINE_SZ_4CIFS_PAL; | 960 | f->fmt.pix.width = LINE_SZ_4CIFS_PAL; |
957 | field = V4L2_FIELD_SEQ_TB; | 961 | field = V4L2_FIELD_SEQ_TB; |
958 | } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) { | 962 | } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) { |
959 | dprintk(50, "pal 352A\n"); | ||
960 | f->fmt.pix.width = LINE_SZ_2CIFS_PAL; | 963 | f->fmt.pix.width = LINE_SZ_2CIFS_PAL; |
961 | field = V4L2_FIELD_TOP; | 964 | field = V4L2_FIELD_TOP; |
962 | } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) { | 965 | } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) { |
963 | dprintk(50, "pal 352B\n"); | ||
964 | f->fmt.pix.width = LINE_SZ_1CIFS_PAL; | 966 | f->fmt.pix.width = LINE_SZ_1CIFS_PAL; |
965 | field = V4L2_FIELD_TOP; | 967 | field = V4L2_FIELD_TOP; |
966 | } else { | 968 | } else { |
967 | dprintk(50, "pal 352C\n"); | ||
968 | f->fmt.pix.width = LINE_SZ_1CIFS_PAL; | 969 | f->fmt.pix.width = LINE_SZ_1CIFS_PAL; |
969 | field = V4L2_FIELD_TOP; | 970 | field = V4L2_FIELD_TOP; |
970 | } | 971 | } |
971 | } | 972 | } |
972 | |||
973 | dprintk(50, "width %d height %d field %d \n", f->fmt.pix.width, | ||
974 | f->fmt.pix.height, f->fmt.pix.field); | ||
975 | f->fmt.pix.field = field; | 973 | f->fmt.pix.field = field; |
976 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | 974 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; |
977 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 975 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
976 | dprintk(50, "%s: set width %d height %d field %d\n", __func__, | ||
977 | f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); | ||
978 | return 0; | 978 | return 0; |
979 | } | 979 | } |
980 | 980 | ||
@@ -1006,7 +1006,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | if (res_locked(fh->dev, fh)) { | 1008 | if (res_locked(fh->dev, fh)) { |
1009 | dprintk(1, "can't change format after started\n"); | 1009 | dprintk(1, "%s: channel busy\n", __func__); |
1010 | ret = -EBUSY; | 1010 | ret = -EBUSY; |
1011 | goto out_s_fmt; | 1011 | goto out_s_fmt; |
1012 | } | 1012 | } |
@@ -1016,17 +1016,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1016 | fh->height = f->fmt.pix.height; | 1016 | fh->height = f->fmt.pix.height; |
1017 | fh->vb_vidq.field = f->fmt.pix.field; | 1017 | fh->vb_vidq.field = f->fmt.pix.field; |
1018 | fh->type = f->type; | 1018 | fh->type = f->type; |
1019 | norm = norm_minw(fh->dev->vdev[fh->channel]); | 1019 | norm = norm_minw(&fh->dev->vdev[fh->channel]); |
1020 | if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) { | 1020 | if (fh->width > norm_minw(&fh->dev->vdev[fh->channel])) { |
1021 | if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) { | 1021 | if (fh->height > norm_minh(&fh->dev->vdev[fh->channel])) { |
1022 | if (fh->dev->cap_parm[fh->channel].capturemode & | 1022 | if (fh->dev->cap_parm[fh->channel].capturemode & |
1023 | V4L2_MODE_HIGHQUALITY) { | 1023 | V4L2_MODE_HIGHQUALITY) |
1024 | fh->mode.scale = SCALE_4CIFSI; | 1024 | fh->mode.scale = SCALE_4CIFSI; |
1025 | dprintk(2, "scale 4CIFSI\n"); | 1025 | else |
1026 | } else { | ||
1027 | fh->mode.scale = SCALE_4CIFS; | 1026 | fh->mode.scale = SCALE_4CIFS; |
1028 | dprintk(2, "scale 4CIFS\n"); | ||
1029 | } | ||
1030 | } else | 1027 | } else |
1031 | fh->mode.scale = SCALE_2CIFS; | 1028 | fh->mode.scale = SCALE_2CIFS; |
1032 | 1029 | ||
@@ -1037,19 +1034,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1037 | /* color mode */ | 1034 | /* color mode */ |
1038 | switch (fh->fmt->fourcc) { | 1035 | switch (fh->fmt->fourcc) { |
1039 | case V4L2_PIX_FMT_GREY: | 1036 | case V4L2_PIX_FMT_GREY: |
1040 | fh->mode.color = COLOR_Y8; | 1037 | fh->mode.color &= ~MASK_COLOR; |
1038 | fh->mode.color |= COLOR_Y8; | ||
1041 | break; | 1039 | break; |
1042 | case V4L2_PIX_FMT_JPEG: | 1040 | case V4L2_PIX_FMT_JPEG: |
1043 | fh->mode.color = COLOR_JPG | | 1041 | fh->mode.color &= ~MASK_COLOR; |
1044 | (fh->dev->jc[fh->channel].quality << 8); | 1042 | fh->mode.color |= COLOR_JPG; |
1043 | fh->mode.color |= (fh->dev->jc[fh->channel].quality << 8); | ||
1045 | break; | 1044 | break; |
1046 | case V4L2_PIX_FMT_YUV422P: | 1045 | case V4L2_PIX_FMT_YUV422P: |
1047 | fh->mode.color = COLOR_YUVPL; | 1046 | fh->mode.color &= ~MASK_COLOR; |
1047 | fh->mode.color |= COLOR_YUVPL; | ||
1048 | break; | 1048 | break; |
1049 | case V4L2_PIX_FMT_YUYV: | 1049 | case V4L2_PIX_FMT_YUYV: |
1050 | case V4L2_PIX_FMT_UYVY: | 1050 | case V4L2_PIX_FMT_UYVY: |
1051 | default: | 1051 | default: |
1052 | fh->mode.color = COLOR_YUVPK; | 1052 | fh->mode.color &= ~MASK_COLOR; |
1053 | fh->mode.color |= COLOR_YUVPK; | ||
1053 | break; | 1054 | break; |
1054 | } | 1055 | } |
1055 | ret = 0; | 1056 | ret = 0; |
@@ -1178,19 +1179,13 @@ static u32 get_transfer_size(struct s2255_mode *mode) | |||
1178 | return usbInSize; | 1179 | return usbInSize; |
1179 | } | 1180 | } |
1180 | 1181 | ||
1181 | static void dump_verify_mode(struct s2255_dev *sdev, struct s2255_mode *mode) | 1182 | static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode) |
1182 | { | 1183 | { |
1183 | struct device *dev = &sdev->udev->dev; | 1184 | struct device *dev = &sdev->udev->dev; |
1184 | dev_info(dev, "------------------------------------------------\n"); | 1185 | dev_info(dev, "------------------------------------------------\n"); |
1185 | dev_info(dev, "verify mode\n"); | 1186 | dev_info(dev, "format: %d\nscale %d\n", mode->format, mode->scale); |
1186 | dev_info(dev, "format: %d\n", mode->format); | 1187 | dev_info(dev, "fdec: %d\ncolor %d\n", mode->fdec, mode->color); |
1187 | dev_info(dev, "scale: %d\n", mode->scale); | ||
1188 | dev_info(dev, "fdec: %d\n", mode->fdec); | ||
1189 | dev_info(dev, "color: %d\n", mode->color); | ||
1190 | dev_info(dev, "bright: 0x%x\n", mode->bright); | 1188 | dev_info(dev, "bright: 0x%x\n", mode->bright); |
1191 | dev_info(dev, "restart: 0x%x\n", mode->restart); | ||
1192 | dev_info(dev, "usb_block: 0x%x\n", mode->usb_block); | ||
1193 | dev_info(dev, "single: 0x%x\n", mode->single); | ||
1194 | dev_info(dev, "------------------------------------------------\n"); | 1189 | dev_info(dev, "------------------------------------------------\n"); |
1195 | } | 1190 | } |
1196 | 1191 | ||
@@ -1206,44 +1201,38 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1206 | struct s2255_mode *mode) | 1201 | struct s2255_mode *mode) |
1207 | { | 1202 | { |
1208 | int res; | 1203 | int res; |
1209 | u32 *buffer; | 1204 | __le32 *buffer; |
1210 | unsigned long chn_rev; | 1205 | unsigned long chn_rev; |
1211 | |||
1212 | mutex_lock(&dev->lock); | 1206 | mutex_lock(&dev->lock); |
1213 | chn_rev = G_chnmap[chn]; | 1207 | chn_rev = G_chnmap[chn]; |
1214 | dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); | 1208 | dprintk(3, "%s channel %lu\n", __func__, chn); |
1215 | dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], | ||
1216 | dev->mode[chn].scale); | ||
1217 | dprintk(2, "mode contrast %x\n", mode->contrast); | ||
1218 | |||
1219 | /* if JPEG, set the quality */ | 1209 | /* if JPEG, set the quality */ |
1220 | if ((mode->color & MASK_COLOR) == COLOR_JPG) | 1210 | if ((mode->color & MASK_COLOR) == COLOR_JPG) { |
1221 | mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG; | 1211 | mode->color &= ~MASK_COLOR; |
1222 | 1212 | mode->color |= COLOR_JPG; | |
1213 | mode->color &= ~MASK_JPG_QUALITY; | ||
1214 | mode->color |= (dev->jc[chn].quality << 8); | ||
1215 | } | ||
1223 | /* save the mode */ | 1216 | /* save the mode */ |
1224 | dev->mode[chn] = *mode; | 1217 | dev->mode[chn] = *mode; |
1225 | dev->req_image_size[chn] = get_transfer_size(mode); | 1218 | dev->req_image_size[chn] = get_transfer_size(mode); |
1226 | dprintk(1, "transfer size %ld\n", dev->req_image_size[chn]); | 1219 | dprintk(1, "%s: reqsize %ld\n", __func__, dev->req_image_size[chn]); |
1227 | |||
1228 | buffer = kzalloc(512, GFP_KERNEL); | 1220 | buffer = kzalloc(512, GFP_KERNEL); |
1229 | if (buffer == NULL) { | 1221 | if (buffer == NULL) { |
1230 | dev_err(&dev->udev->dev, "out of mem\n"); | 1222 | dev_err(&dev->udev->dev, "out of mem\n"); |
1231 | mutex_unlock(&dev->lock); | 1223 | mutex_unlock(&dev->lock); |
1232 | return -ENOMEM; | 1224 | return -ENOMEM; |
1233 | } | 1225 | } |
1234 | |||
1235 | /* set the mode */ | 1226 | /* set the mode */ |
1236 | buffer[0] = IN_DATA_TOKEN; | 1227 | buffer[0] = IN_DATA_TOKEN; |
1237 | buffer[1] = (u32) chn_rev; | 1228 | buffer[1] = (__le32) cpu_to_le32(chn_rev); |
1238 | buffer[2] = CMD_SET_MODE; | 1229 | buffer[2] = CMD_SET_MODE; |
1239 | memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); | 1230 | memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); |
1240 | dev->setmode_ready[chn] = 0; | 1231 | dev->setmode_ready[chn] = 0; |
1241 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | 1232 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); |
1242 | if (debug) | 1233 | if (debug) |
1243 | dump_verify_mode(dev, mode); | 1234 | s2255_print_cfg(dev, mode); |
1244 | kfree(buffer); | 1235 | kfree(buffer); |
1245 | dprintk(1, "set mode done chn %lu, %d\n", chn, res); | ||
1246 | |||
1247 | /* wait at least 3 frames before continuing */ | 1236 | /* wait at least 3 frames before continuing */ |
1248 | if (mode->restart) { | 1237 | if (mode->restart) { |
1249 | wait_event_timeout(dev->wait_setmode[chn], | 1238 | wait_event_timeout(dev->wait_setmode[chn], |
@@ -1254,10 +1243,46 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1254 | res = -EFAULT; | 1243 | res = -EFAULT; |
1255 | } | 1244 | } |
1256 | } | 1245 | } |
1257 | |||
1258 | /* clear the restart flag */ | 1246 | /* clear the restart flag */ |
1259 | dev->mode[chn].restart = 0; | 1247 | dev->mode[chn].restart = 0; |
1260 | mutex_unlock(&dev->lock); | 1248 | mutex_unlock(&dev->lock); |
1249 | dprintk(1, "%s chn %lu, result: %d\n", __func__, chn, res); | ||
1250 | return res; | ||
1251 | } | ||
1252 | |||
1253 | static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, | ||
1254 | u32 *pstatus) | ||
1255 | { | ||
1256 | int res; | ||
1257 | __le32 *buffer; | ||
1258 | u32 chn_rev; | ||
1259 | mutex_lock(&dev->lock); | ||
1260 | chn_rev = G_chnmap[chn]; | ||
1261 | dprintk(4, "%s chan %lu\n", __func__, chn); | ||
1262 | buffer = kzalloc(512, GFP_KERNEL); | ||
1263 | if (buffer == NULL) { | ||
1264 | dev_err(&dev->udev->dev, "out of mem\n"); | ||
1265 | mutex_unlock(&dev->lock); | ||
1266 | return -ENOMEM; | ||
1267 | } | ||
1268 | /* form the get vid status command */ | ||
1269 | buffer[0] = IN_DATA_TOKEN; | ||
1270 | buffer[1] = (__le32) cpu_to_le32(chn_rev); | ||
1271 | buffer[2] = CMD_STATUS; | ||
1272 | *pstatus = 0; | ||
1273 | dev->vidstatus_ready[chn] = 0; | ||
1274 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | ||
1275 | kfree(buffer); | ||
1276 | wait_event_timeout(dev->wait_vidstatus[chn], | ||
1277 | (dev->vidstatus_ready[chn] != 0), | ||
1278 | msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); | ||
1279 | if (dev->vidstatus_ready[chn] != 1) { | ||
1280 | printk(KERN_DEBUG "s2255: no vidstatus response\n"); | ||
1281 | res = -EFAULT; | ||
1282 | } | ||
1283 | *pstatus = dev->vidstatus[chn]; | ||
1284 | dprintk(4, "%s, vid status %d\n", __func__, *pstatus); | ||
1285 | mutex_unlock(&dev->lock); | ||
1261 | return res; | 1286 | return res; |
1262 | } | 1287 | } |
1263 | 1288 | ||
@@ -1291,7 +1316,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1291 | new_mode = &fh->mode; | 1316 | new_mode = &fh->mode; |
1292 | old_mode = &fh->dev->mode[chn]; | 1317 | old_mode = &fh->dev->mode[chn]; |
1293 | 1318 | ||
1294 | if (new_mode->color != old_mode->color) | 1319 | if ((new_mode->color & MASK_COLOR) != (old_mode->color & MASK_COLOR)) |
1295 | new_mode->restart = 1; | 1320 | new_mode->restart = 1; |
1296 | else if (new_mode->scale != old_mode->scale) | 1321 | else if (new_mode->scale != old_mode->scale) |
1297 | new_mode->restart = 1; | 1322 | new_mode->restart = 1; |
@@ -1302,7 +1327,6 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1302 | new_mode->restart = 0; | 1327 | new_mode->restart = 0; |
1303 | *old_mode = *new_mode; | 1328 | *old_mode = *new_mode; |
1304 | dev->cur_fmt[chn] = fh->fmt; | 1329 | dev->cur_fmt[chn] = fh->fmt; |
1305 | dprintk(1, "%s[%d]\n", __func__, chn); | ||
1306 | dev->last_frame[chn] = -1; | 1330 | dev->last_frame[chn] = -1; |
1307 | dev->bad_payload[chn] = 0; | 1331 | dev->bad_payload[chn] = 0; |
1308 | dev->cur_frame[chn] = 0; | 1332 | dev->cur_frame[chn] = 0; |
@@ -1325,7 +1349,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1325 | { | 1349 | { |
1326 | struct s2255_fh *fh = priv; | 1350 | struct s2255_fh *fh = priv; |
1327 | struct s2255_dev *dev = fh->dev; | 1351 | struct s2255_dev *dev = fh->dev; |
1328 | |||
1329 | dprintk(4, "%s\n, channel: %d", __func__, fh->channel); | 1352 | dprintk(4, "%s\n, channel: %d", __func__, fh->channel); |
1330 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1353 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1331 | printk(KERN_ERR "invalid fh type0\n"); | 1354 | printk(KERN_ERR "invalid fh type0\n"); |
@@ -1347,27 +1370,32 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | |||
1347 | struct s2255_mode *mode; | 1370 | struct s2255_mode *mode; |
1348 | struct videobuf_queue *q = &fh->vb_vidq; | 1371 | struct videobuf_queue *q = &fh->vb_vidq; |
1349 | int ret = 0; | 1372 | int ret = 0; |
1350 | |||
1351 | mutex_lock(&q->vb_lock); | 1373 | mutex_lock(&q->vb_lock); |
1352 | if (videobuf_queue_is_busy(q)) { | 1374 | if (videobuf_queue_is_busy(q)) { |
1353 | dprintk(1, "queue busy\n"); | 1375 | dprintk(1, "queue busy\n"); |
1354 | ret = -EBUSY; | 1376 | ret = -EBUSY; |
1355 | goto out_s_std; | 1377 | goto out_s_std; |
1356 | } | 1378 | } |
1357 | |||
1358 | if (res_locked(fh->dev, fh)) { | 1379 | if (res_locked(fh->dev, fh)) { |
1359 | dprintk(1, "can't change standard after started\n"); | 1380 | dprintk(1, "can't change standard after started\n"); |
1360 | ret = -EBUSY; | 1381 | ret = -EBUSY; |
1361 | goto out_s_std; | 1382 | goto out_s_std; |
1362 | } | 1383 | } |
1363 | mode = &fh->mode; | 1384 | mode = &fh->mode; |
1364 | |||
1365 | if (*i & V4L2_STD_NTSC) { | 1385 | if (*i & V4L2_STD_NTSC) { |
1366 | dprintk(4, "vidioc_s_std NTSC\n"); | 1386 | dprintk(4, "%s NTSC\n", __func__); |
1367 | mode->format = FORMAT_NTSC; | 1387 | /* if changing format, reset frame decimation/intervals */ |
1388 | if (mode->format != FORMAT_NTSC) { | ||
1389 | mode->format = FORMAT_NTSC; | ||
1390 | mode->fdec = FDEC_1; | ||
1391 | } | ||
1368 | } else if (*i & V4L2_STD_PAL) { | 1392 | } else if (*i & V4L2_STD_PAL) { |
1369 | dprintk(4, "vidioc_s_std PAL\n"); | 1393 | dprintk(4, "%s PAL\n", __func__); |
1370 | mode->format = FORMAT_PAL; | 1394 | mode->format = FORMAT_PAL; |
1395 | if (mode->format != FORMAT_PAL) { | ||
1396 | mode->format = FORMAT_PAL; | ||
1397 | mode->fdec = FDEC_1; | ||
1398 | } | ||
1371 | } else { | 1399 | } else { |
1372 | ret = -EINVAL; | 1400 | ret = -EINVAL; |
1373 | } | 1401 | } |
@@ -1386,12 +1414,32 @@ out_s_std: | |||
1386 | static int vidioc_enum_input(struct file *file, void *priv, | 1414 | static int vidioc_enum_input(struct file *file, void *priv, |
1387 | struct v4l2_input *inp) | 1415 | struct v4l2_input *inp) |
1388 | { | 1416 | { |
1417 | struct s2255_fh *fh = priv; | ||
1418 | struct s2255_dev *dev = fh->dev; | ||
1419 | u32 status = 0; | ||
1389 | if (inp->index != 0) | 1420 | if (inp->index != 0) |
1390 | return -EINVAL; | 1421 | return -EINVAL; |
1391 | |||
1392 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1422 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1393 | inp->std = S2255_NORMS; | 1423 | inp->std = S2255_NORMS; |
1394 | strlcpy(inp->name, "Camera", sizeof(inp->name)); | 1424 | inp->status = 0; |
1425 | if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) { | ||
1426 | int rc; | ||
1427 | rc = s2255_cmd_status(dev, fh->channel, &status); | ||
1428 | dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status); | ||
1429 | if (rc == 0) | ||
1430 | inp->status = (status & 0x01) ? 0 | ||
1431 | : V4L2_IN_ST_NO_SIGNAL; | ||
1432 | } | ||
1433 | switch (dev->pid) { | ||
1434 | case 0x2255: | ||
1435 | default: | ||
1436 | strlcpy(inp->name, "Composite", sizeof(inp->name)); | ||
1437 | break; | ||
1438 | case 0x2257: | ||
1439 | strlcpy(inp->name, (fh->channel < 2) ? "Composite" : "S-Video", | ||
1440 | sizeof(inp->name)); | ||
1441 | break; | ||
1442 | } | ||
1395 | return 0; | 1443 | return 0; |
1396 | } | 1444 | } |
1397 | 1445 | ||
@@ -1411,74 +1459,113 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1411 | static int vidioc_queryctrl(struct file *file, void *priv, | 1459 | static int vidioc_queryctrl(struct file *file, void *priv, |
1412 | struct v4l2_queryctrl *qc) | 1460 | struct v4l2_queryctrl *qc) |
1413 | { | 1461 | { |
1414 | int i; | 1462 | struct s2255_fh *fh = priv; |
1415 | 1463 | struct s2255_dev *dev = fh->dev; | |
1416 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | 1464 | switch (qc->id) { |
1417 | if (qc->id && qc->id == s2255_qctrl[i].id) { | 1465 | case V4L2_CID_BRIGHTNESS: |
1418 | memcpy(qc, &(s2255_qctrl[i]), sizeof(*qc)); | 1466 | v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT); |
1419 | return 0; | 1467 | break; |
1420 | } | 1468 | case V4L2_CID_CONTRAST: |
1421 | 1469 | v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST); | |
1422 | dprintk(4, "query_ctrl -EINVAL %d\n", qc->id); | 1470 | break; |
1423 | return -EINVAL; | 1471 | case V4L2_CID_SATURATION: |
1472 | v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION); | ||
1473 | break; | ||
1474 | case V4L2_CID_HUE: | ||
1475 | v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE); | ||
1476 | break; | ||
1477 | case V4L2_CID_PRIVATE_COLORFILTER: | ||
1478 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | ||
1479 | return -EINVAL; | ||
1480 | if ((dev->pid == 0x2257) && (fh->channel > 1)) | ||
1481 | return -EINVAL; | ||
1482 | strlcpy(qc->name, "Color Filter", sizeof(qc->name)); | ||
1483 | qc->type = V4L2_CTRL_TYPE_MENU; | ||
1484 | qc->minimum = 0; | ||
1485 | qc->maximum = 1; | ||
1486 | qc->step = 1; | ||
1487 | qc->default_value = 1; | ||
1488 | qc->flags = 0; | ||
1489 | break; | ||
1490 | default: | ||
1491 | return -EINVAL; | ||
1492 | } | ||
1493 | dprintk(4, "%s, id %d\n", __func__, qc->id); | ||
1494 | return 0; | ||
1424 | } | 1495 | } |
1425 | 1496 | ||
1426 | static int vidioc_g_ctrl(struct file *file, void *priv, | 1497 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1427 | struct v4l2_control *ctrl) | 1498 | struct v4l2_control *ctrl) |
1428 | { | 1499 | { |
1429 | int i; | 1500 | struct s2255_fh *fh = priv; |
1430 | 1501 | struct s2255_dev *dev = fh->dev; | |
1431 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | 1502 | switch (ctrl->id) { |
1432 | if (ctrl->id == s2255_qctrl[i].id) { | 1503 | case V4L2_CID_BRIGHTNESS: |
1433 | ctrl->value = qctl_regs[i]; | 1504 | ctrl->value = fh->mode.bright; |
1434 | return 0; | 1505 | break; |
1435 | } | 1506 | case V4L2_CID_CONTRAST: |
1436 | dprintk(4, "g_ctrl -EINVAL\n"); | 1507 | ctrl->value = fh->mode.contrast; |
1437 | 1508 | break; | |
1438 | return -EINVAL; | 1509 | case V4L2_CID_SATURATION: |
1510 | ctrl->value = fh->mode.saturation; | ||
1511 | break; | ||
1512 | case V4L2_CID_HUE: | ||
1513 | ctrl->value = fh->mode.hue; | ||
1514 | break; | ||
1515 | case V4L2_CID_PRIVATE_COLORFILTER: | ||
1516 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | ||
1517 | return -EINVAL; | ||
1518 | if ((dev->pid == 0x2257) && (fh->channel > 1)) | ||
1519 | return -EINVAL; | ||
1520 | ctrl->value = !((fh->mode.color & MASK_INPUT_TYPE) >> 16); | ||
1521 | break; | ||
1522 | default: | ||
1523 | return -EINVAL; | ||
1524 | } | ||
1525 | dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value); | ||
1526 | return 0; | ||
1439 | } | 1527 | } |
1440 | 1528 | ||
1441 | static int vidioc_s_ctrl(struct file *file, void *priv, | 1529 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1442 | struct v4l2_control *ctrl) | 1530 | struct v4l2_control *ctrl) |
1443 | { | 1531 | { |
1444 | int i; | ||
1445 | struct s2255_fh *fh = priv; | 1532 | struct s2255_fh *fh = priv; |
1446 | struct s2255_dev *dev = fh->dev; | 1533 | struct s2255_dev *dev = fh->dev; |
1447 | struct s2255_mode *mode; | 1534 | struct s2255_mode *mode; |
1448 | mode = &fh->mode; | 1535 | mode = &fh->mode; |
1449 | dprintk(4, "vidioc_s_ctrl\n"); | 1536 | dprintk(4, "%s\n", __func__); |
1450 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) { | 1537 | /* update the mode to the corresponding value */ |
1451 | if (ctrl->id == s2255_qctrl[i].id) { | 1538 | switch (ctrl->id) { |
1452 | if (ctrl->value < s2255_qctrl[i].minimum || | 1539 | case V4L2_CID_BRIGHTNESS: |
1453 | ctrl->value > s2255_qctrl[i].maximum) | 1540 | mode->bright = ctrl->value; |
1454 | return -ERANGE; | 1541 | break; |
1455 | 1542 | case V4L2_CID_CONTRAST: | |
1456 | qctl_regs[i] = ctrl->value; | 1543 | mode->contrast = ctrl->value; |
1457 | /* update the mode to the corresponding value */ | 1544 | break; |
1458 | switch (ctrl->id) { | 1545 | case V4L2_CID_HUE: |
1459 | case V4L2_CID_BRIGHTNESS: | 1546 | mode->hue = ctrl->value; |
1460 | mode->bright = ctrl->value; | 1547 | break; |
1461 | break; | 1548 | case V4L2_CID_SATURATION: |
1462 | case V4L2_CID_CONTRAST: | 1549 | mode->saturation = ctrl->value; |
1463 | mode->contrast = ctrl->value; | 1550 | break; |
1464 | break; | 1551 | case V4L2_CID_PRIVATE_COLORFILTER: |
1465 | case V4L2_CID_HUE: | 1552 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) |
1466 | mode->hue = ctrl->value; | 1553 | return -EINVAL; |
1467 | break; | 1554 | if ((dev->pid == 0x2257) && (fh->channel > 1)) |
1468 | case V4L2_CID_SATURATION: | 1555 | return -EINVAL; |
1469 | mode->saturation = ctrl->value; | 1556 | mode->color &= ~MASK_INPUT_TYPE; |
1470 | break; | 1557 | mode->color |= ((ctrl->value ? 0 : 1) << 16); |
1471 | } | 1558 | break; |
1472 | mode->restart = 0; | 1559 | default: |
1473 | /* set mode here. Note: stream does not need restarted. | 1560 | return -EINVAL; |
1474 | some V4L programs restart stream unnecessarily | ||
1475 | after a s_crtl. | ||
1476 | */ | ||
1477 | s2255_set_mode(dev, fh->channel, mode); | ||
1478 | return 0; | ||
1479 | } | ||
1480 | } | 1561 | } |
1481 | return -EINVAL; | 1562 | mode->restart = 0; |
1563 | /* set mode here. Note: stream does not need restarted. | ||
1564 | some V4L programs restart stream unnecessarily | ||
1565 | after a s_crtl. | ||
1566 | */ | ||
1567 | s2255_set_mode(dev, fh->channel, mode); | ||
1568 | return 0; | ||
1482 | } | 1569 | } |
1483 | 1570 | ||
1484 | static int vidioc_g_jpegcomp(struct file *file, void *priv, | 1571 | static int vidioc_g_jpegcomp(struct file *file, void *priv, |
@@ -1487,7 +1574,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, | |||
1487 | struct s2255_fh *fh = priv; | 1574 | struct s2255_fh *fh = priv; |
1488 | struct s2255_dev *dev = fh->dev; | 1575 | struct s2255_dev *dev = fh->dev; |
1489 | *jc = dev->jc[fh->channel]; | 1576 | *jc = dev->jc[fh->channel]; |
1490 | dprintk(2, "getting jpegcompression, quality %d\n", jc->quality); | 1577 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); |
1491 | return 0; | 1578 | return 0; |
1492 | } | 1579 | } |
1493 | 1580 | ||
@@ -1499,7 +1586,7 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, | |||
1499 | if (jc->quality < 0 || jc->quality > 100) | 1586 | if (jc->quality < 0 || jc->quality > 100) |
1500 | return -EINVAL; | 1587 | return -EINVAL; |
1501 | dev->jc[fh->channel].quality = jc->quality; | 1588 | dev->jc[fh->channel].quality = jc->quality; |
1502 | dprintk(2, "setting jpeg quality %d\n", jc->quality); | 1589 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); |
1503 | return 0; | 1590 | return 0; |
1504 | } | 1591 | } |
1505 | 1592 | ||
@@ -1508,10 +1595,34 @@ static int vidioc_g_parm(struct file *file, void *priv, | |||
1508 | { | 1595 | { |
1509 | struct s2255_fh *fh = priv; | 1596 | struct s2255_fh *fh = priv; |
1510 | struct s2255_dev *dev = fh->dev; | 1597 | struct s2255_dev *dev = fh->dev; |
1598 | __u32 def_num, def_dem; | ||
1511 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1599 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1512 | return -EINVAL; | 1600 | return -EINVAL; |
1601 | memset(sp, 0, sizeof(struct v4l2_streamparm)); | ||
1602 | sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
1513 | sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode; | 1603 | sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode; |
1514 | dprintk(2, "getting parm %d\n", sp->parm.capture.capturemode); | 1604 | def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; |
1605 | def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; | ||
1606 | sp->parm.capture.timeperframe.denominator = def_dem; | ||
1607 | switch (fh->mode.fdec) { | ||
1608 | default: | ||
1609 | case FDEC_1: | ||
1610 | sp->parm.capture.timeperframe.numerator = def_num; | ||
1611 | break; | ||
1612 | case FDEC_2: | ||
1613 | sp->parm.capture.timeperframe.numerator = def_num * 2; | ||
1614 | break; | ||
1615 | case FDEC_3: | ||
1616 | sp->parm.capture.timeperframe.numerator = def_num * 3; | ||
1617 | break; | ||
1618 | case FDEC_5: | ||
1619 | sp->parm.capture.timeperframe.numerator = def_num * 5; | ||
1620 | break; | ||
1621 | } | ||
1622 | dprintk(4, "%s capture mode, %d timeperframe %d/%d\n", __func__, | ||
1623 | sp->parm.capture.capturemode, | ||
1624 | sp->parm.capture.timeperframe.numerator, | ||
1625 | sp->parm.capture.timeperframe.denominator); | ||
1515 | return 0; | 1626 | return 0; |
1516 | } | 1627 | } |
1517 | 1628 | ||
@@ -1520,15 +1631,79 @@ static int vidioc_s_parm(struct file *file, void *priv, | |||
1520 | { | 1631 | { |
1521 | struct s2255_fh *fh = priv; | 1632 | struct s2255_fh *fh = priv; |
1522 | struct s2255_dev *dev = fh->dev; | 1633 | struct s2255_dev *dev = fh->dev; |
1523 | 1634 | int fdec = FDEC_1; | |
1635 | __u32 def_num, def_dem; | ||
1524 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1636 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1525 | return -EINVAL; | 1637 | return -EINVAL; |
1638 | /* high quality capture mode requires a stream restart */ | ||
1639 | if (dev->cap_parm[fh->channel].capturemode | ||
1640 | != sp->parm.capture.capturemode && res_locked(fh->dev, fh)) | ||
1641 | return -EBUSY; | ||
1642 | def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; | ||
1643 | def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; | ||
1644 | if (def_dem != sp->parm.capture.timeperframe.denominator) | ||
1645 | sp->parm.capture.timeperframe.numerator = def_num; | ||
1646 | else if (sp->parm.capture.timeperframe.numerator <= def_num) | ||
1647 | sp->parm.capture.timeperframe.numerator = def_num; | ||
1648 | else if (sp->parm.capture.timeperframe.numerator <= (def_num * 2)) { | ||
1649 | sp->parm.capture.timeperframe.numerator = def_num * 2; | ||
1650 | fdec = FDEC_2; | ||
1651 | } else if (sp->parm.capture.timeperframe.numerator <= (def_num * 3)) { | ||
1652 | sp->parm.capture.timeperframe.numerator = def_num * 3; | ||
1653 | fdec = FDEC_3; | ||
1654 | } else { | ||
1655 | sp->parm.capture.timeperframe.numerator = def_num * 5; | ||
1656 | fdec = FDEC_5; | ||
1657 | } | ||
1658 | fh->mode.fdec = fdec; | ||
1659 | sp->parm.capture.timeperframe.denominator = def_dem; | ||
1660 | s2255_set_mode(dev, fh->channel, &fh->mode); | ||
1661 | dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n", | ||
1662 | __func__, | ||
1663 | sp->parm.capture.capturemode, | ||
1664 | sp->parm.capture.timeperframe.numerator, | ||
1665 | sp->parm.capture.timeperframe.denominator, fdec); | ||
1666 | return 0; | ||
1667 | } | ||
1526 | 1668 | ||
1527 | dev->cap_parm[fh->channel].capturemode = sp->parm.capture.capturemode; | 1669 | static int vidioc_enum_frameintervals(struct file *file, void *priv, |
1528 | dprintk(2, "setting param capture mode %d\n", | 1670 | struct v4l2_frmivalenum *fe) |
1529 | sp->parm.capture.capturemode); | 1671 | { |
1672 | int is_ntsc = 0; | ||
1673 | #define NUM_FRAME_ENUMS 4 | ||
1674 | int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5}; | ||
1675 | if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS) | ||
1676 | return -EINVAL; | ||
1677 | switch (fe->width) { | ||
1678 | case 640: | ||
1679 | if (fe->height != 240 && fe->height != 480) | ||
1680 | return -EINVAL; | ||
1681 | is_ntsc = 1; | ||
1682 | break; | ||
1683 | case 320: | ||
1684 | if (fe->height != 240) | ||
1685 | return -EINVAL; | ||
1686 | is_ntsc = 1; | ||
1687 | break; | ||
1688 | case 704: | ||
1689 | if (fe->height != 288 && fe->height != 576) | ||
1690 | return -EINVAL; | ||
1691 | break; | ||
1692 | case 352: | ||
1693 | if (fe->height != 288) | ||
1694 | return -EINVAL; | ||
1695 | break; | ||
1696 | default: | ||
1697 | return -EINVAL; | ||
1698 | } | ||
1699 | fe->type = V4L2_FRMIVAL_TYPE_DISCRETE; | ||
1700 | fe->discrete.denominator = is_ntsc ? 30000 : 25000; | ||
1701 | fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index]; | ||
1702 | dprintk(4, "%s discrete %d/%d\n", __func__, fe->discrete.numerator, | ||
1703 | fe->discrete.denominator); | ||
1530 | return 0; | 1704 | return 0; |
1531 | } | 1705 | } |
1706 | |||
1532 | static int s2255_open(struct file *file) | 1707 | static int s2255_open(struct file *file) |
1533 | { | 1708 | { |
1534 | struct video_device *vdev = video_devdata(file); | 1709 | struct video_device *vdev = video_devdata(file); |
@@ -1538,31 +1713,29 @@ static int s2255_open(struct file *file) | |||
1538 | int i = 0; | 1713 | int i = 0; |
1539 | int cur_channel = -1; | 1714 | int cur_channel = -1; |
1540 | int state; | 1715 | int state; |
1541 | |||
1542 | dprintk(1, "s2255: open called (dev=%s)\n", | 1716 | dprintk(1, "s2255: open called (dev=%s)\n", |
1543 | video_device_node_name(vdev)); | 1717 | video_device_node_name(vdev)); |
1544 | 1718 | ||
1545 | lock_kernel(); | ||
1546 | |||
1547 | for (i = 0; i < MAX_CHANNELS; i++) { | 1719 | for (i = 0; i < MAX_CHANNELS; i++) { |
1548 | if (dev->vdev[i] == vdev) { | 1720 | if (&dev->vdev[i] == vdev) { |
1549 | cur_channel = i; | 1721 | cur_channel = i; |
1550 | break; | 1722 | break; |
1551 | } | 1723 | } |
1552 | } | 1724 | } |
1553 | 1725 | if (i == MAX_CHANNELS) | |
1554 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { | ||
1555 | unlock_kernel(); | ||
1556 | printk(KERN_INFO "disconnecting\n"); | ||
1557 | return -ENODEV; | 1726 | return -ENODEV; |
1558 | } | ||
1559 | kref_get(&dev->kref); | ||
1560 | mutex_lock(&dev->open_lock); | ||
1561 | |||
1562 | dev->users[cur_channel]++; | ||
1563 | dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); | ||
1564 | 1727 | ||
1565 | switch (atomic_read(&dev->fw_data->fw_state)) { | 1728 | /* |
1729 | * open lock necessary to prevent multiple instances | ||
1730 | * of v4l-conf (or other programs) from simultaneously | ||
1731 | * reloading firmware. | ||
1732 | */ | ||
1733 | mutex_lock(&dev->open_lock); | ||
1734 | state = atomic_read(&dev->fw_data->fw_state); | ||
1735 | switch (state) { | ||
1736 | case S2255_FW_DISCONNECTING: | ||
1737 | mutex_unlock(&dev->open_lock); | ||
1738 | return -ENODEV; | ||
1566 | case S2255_FW_FAILED: | 1739 | case S2255_FW_FAILED: |
1567 | s2255_dev_err(&dev->udev->dev, | 1740 | s2255_dev_err(&dev->udev->dev, |
1568 | "firmware load failed. retrying.\n"); | 1741 | "firmware load failed. retrying.\n"); |
@@ -1573,6 +1746,8 @@ static int s2255_open(struct file *file) | |||
1573 | (atomic_read(&dev->fw_data->fw_state) | 1746 | (atomic_read(&dev->fw_data->fw_state) |
1574 | == S2255_FW_DISCONNECTING)), | 1747 | == S2255_FW_DISCONNECTING)), |
1575 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1748 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
1749 | /* state may have changed, re-read */ | ||
1750 | state = atomic_read(&dev->fw_data->fw_state); | ||
1576 | break; | 1751 | break; |
1577 | case S2255_FW_NOTLOADED: | 1752 | case S2255_FW_NOTLOADED: |
1578 | case S2255_FW_LOADED_DSPWAIT: | 1753 | case S2255_FW_LOADED_DSPWAIT: |
@@ -1584,53 +1759,50 @@ static int s2255_open(struct file *file) | |||
1584 | == S2255_FW_SUCCESS) || | 1759 | == S2255_FW_SUCCESS) || |
1585 | (atomic_read(&dev->fw_data->fw_state) | 1760 | (atomic_read(&dev->fw_data->fw_state) |
1586 | == S2255_FW_DISCONNECTING)), | 1761 | == S2255_FW_DISCONNECTING)), |
1587 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1762 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
1763 | /* state may have changed, re-read */ | ||
1764 | state = atomic_read(&dev->fw_data->fw_state); | ||
1588 | break; | 1765 | break; |
1589 | case S2255_FW_SUCCESS: | 1766 | case S2255_FW_SUCCESS: |
1590 | default: | 1767 | default: |
1591 | break; | 1768 | break; |
1592 | } | 1769 | } |
1593 | state = atomic_read(&dev->fw_data->fw_state); | 1770 | /* state may have changed in above switch statement */ |
1594 | if (state != S2255_FW_SUCCESS) { | 1771 | switch (state) { |
1595 | int rc; | 1772 | case S2255_FW_SUCCESS: |
1596 | switch (state) { | 1773 | break; |
1597 | case S2255_FW_FAILED: | 1774 | case S2255_FW_FAILED: |
1598 | printk(KERN_INFO "2255 FW load failed. %d\n", state); | 1775 | printk(KERN_INFO "2255 firmware load failed.\n"); |
1599 | rc = -ENODEV; | 1776 | mutex_unlock(&dev->open_lock); |
1600 | break; | 1777 | return -ENODEV; |
1601 | case S2255_FW_DISCONNECTING: | 1778 | case S2255_FW_DISCONNECTING: |
1602 | printk(KERN_INFO "%s: disconnecting\n", __func__); | 1779 | printk(KERN_INFO "%s: disconnecting\n", __func__); |
1603 | rc = -ENODEV; | ||
1604 | break; | ||
1605 | case S2255_FW_LOADED_DSPWAIT: | ||
1606 | case S2255_FW_NOTLOADED: | ||
1607 | printk(KERN_INFO "%s: firmware not loaded yet" | ||
1608 | "please try again later\n", | ||
1609 | __func__); | ||
1610 | rc = -EAGAIN; | ||
1611 | break; | ||
1612 | default: | ||
1613 | printk(KERN_INFO "%s: unknown state\n", __func__); | ||
1614 | rc = -EFAULT; | ||
1615 | break; | ||
1616 | } | ||
1617 | dev->users[cur_channel]--; | ||
1618 | mutex_unlock(&dev->open_lock); | 1780 | mutex_unlock(&dev->open_lock); |
1619 | kref_put(&dev->kref, s2255_destroy); | 1781 | return -ENODEV; |
1620 | unlock_kernel(); | 1782 | case S2255_FW_LOADED_DSPWAIT: |
1621 | return rc; | 1783 | case S2255_FW_NOTLOADED: |
1784 | printk(KERN_INFO "%s: firmware not loaded yet" | ||
1785 | "please try again later\n", | ||
1786 | __func__); | ||
1787 | /* | ||
1788 | * Timeout on firmware load means device unusable. | ||
1789 | * Set firmware failure state. | ||
1790 | * On next s2255_open the firmware will be reloaded. | ||
1791 | */ | ||
1792 | atomic_set(&dev->fw_data->fw_state, | ||
1793 | S2255_FW_FAILED); | ||
1794 | mutex_unlock(&dev->open_lock); | ||
1795 | return -EAGAIN; | ||
1796 | default: | ||
1797 | printk(KERN_INFO "%s: unknown state\n", __func__); | ||
1798 | mutex_unlock(&dev->open_lock); | ||
1799 | return -EFAULT; | ||
1622 | } | 1800 | } |
1623 | 1801 | mutex_unlock(&dev->open_lock); | |
1624 | /* allocate + initialize per filehandle data */ | 1802 | /* allocate + initialize per filehandle data */ |
1625 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 1803 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
1626 | if (NULL == fh) { | 1804 | if (NULL == fh) |
1627 | dev->users[cur_channel]--; | ||
1628 | mutex_unlock(&dev->open_lock); | ||
1629 | kref_put(&dev->kref, s2255_destroy); | ||
1630 | unlock_kernel(); | ||
1631 | return -ENOMEM; | 1805 | return -ENOMEM; |
1632 | } | ||
1633 | |||
1634 | file->private_data = fh; | 1806 | file->private_data = fh; |
1635 | fh->dev = dev; | 1807 | fh->dev = dev; |
1636 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1808 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -1640,35 +1812,23 @@ static int s2255_open(struct file *file) | |||
1640 | fh->width = LINE_SZ_4CIFS_NTSC; | 1812 | fh->width = LINE_SZ_4CIFS_NTSC; |
1641 | fh->height = NUM_LINES_4CIFS_NTSC * 2; | 1813 | fh->height = NUM_LINES_4CIFS_NTSC * 2; |
1642 | fh->channel = cur_channel; | 1814 | fh->channel = cur_channel; |
1643 | |||
1644 | /* configure channel to default state */ | 1815 | /* configure channel to default state */ |
1645 | if (!dev->chn_configured[cur_channel]) { | 1816 | if (!dev->chn_configured[cur_channel]) { |
1646 | s2255_set_mode(dev, cur_channel, &fh->mode); | 1817 | s2255_set_mode(dev, cur_channel, &fh->mode); |
1647 | dev->chn_configured[cur_channel] = 1; | 1818 | dev->chn_configured[cur_channel] = 1; |
1648 | } | 1819 | } |
1649 | 1820 | dprintk(1, "%s: dev=%s type=%s\n", __func__, | |
1650 | 1821 | video_device_node_name(vdev), v4l2_type_names[type]); | |
1651 | /* Put all controls at a sane state */ | 1822 | dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__, |
1652 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | ||
1653 | qctl_regs[i] = s2255_qctrl[i].default_value; | ||
1654 | |||
1655 | dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n", | ||
1656 | video_device_node_name(vdev), v4l2_type_names[type], | ||
1657 | dev->users[cur_channel]); | ||
1658 | dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", | ||
1659 | (unsigned long)fh, (unsigned long)dev, | 1823 | (unsigned long)fh, (unsigned long)dev, |
1660 | (unsigned long)&dev->vidq[cur_channel]); | 1824 | (unsigned long)&dev->vidq[cur_channel]); |
1661 | dprintk(4, "s2255drv: open: list_empty active=%d\n", | 1825 | dprintk(4, "%s: list_empty active=%d\n", __func__, |
1662 | list_empty(&dev->vidq[cur_channel].active)); | 1826 | list_empty(&dev->vidq[cur_channel].active)); |
1663 | |||
1664 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops, | 1827 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops, |
1665 | NULL, &dev->slock, | 1828 | NULL, &dev->slock, |
1666 | fh->type, | 1829 | fh->type, |
1667 | V4L2_FIELD_INTERLACED, | 1830 | V4L2_FIELD_INTERLACED, |
1668 | sizeof(struct s2255_buffer), fh); | 1831 | sizeof(struct s2255_buffer), fh); |
1669 | |||
1670 | mutex_unlock(&dev->open_lock); | ||
1671 | unlock_kernel(); | ||
1672 | return 0; | 1832 | return 0; |
1673 | } | 1833 | } |
1674 | 1834 | ||
@@ -1679,39 +1839,19 @@ static unsigned int s2255_poll(struct file *file, | |||
1679 | struct s2255_fh *fh = file->private_data; | 1839 | struct s2255_fh *fh = file->private_data; |
1680 | int rc; | 1840 | int rc; |
1681 | dprintk(100, "%s\n", __func__); | 1841 | dprintk(100, "%s\n", __func__); |
1682 | |||
1683 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1842 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) |
1684 | return POLLERR; | 1843 | return POLLERR; |
1685 | |||
1686 | rc = videobuf_poll_stream(file, &fh->vb_vidq, wait); | 1844 | rc = videobuf_poll_stream(file, &fh->vb_vidq, wait); |
1687 | return rc; | 1845 | return rc; |
1688 | } | 1846 | } |
1689 | 1847 | ||
1690 | static void s2255_destroy(struct kref *kref) | 1848 | static void s2255_destroy(struct s2255_dev *dev) |
1691 | { | 1849 | { |
1692 | struct s2255_dev *dev = to_s2255_dev(kref); | ||
1693 | int i; | ||
1694 | if (!dev) { | ||
1695 | printk(KERN_ERR "s2255drv: kref problem\n"); | ||
1696 | return; | ||
1697 | } | ||
1698 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | ||
1699 | wake_up(&dev->fw_data->wait_fw); | ||
1700 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
1701 | dev->setmode_ready[i] = 1; | ||
1702 | wake_up(&dev->wait_setmode[i]); | ||
1703 | } | ||
1704 | mutex_lock(&dev->open_lock); | ||
1705 | /* reset the DSP so firmware can be reload next time */ | ||
1706 | s2255_reset_dsppower(dev); | ||
1707 | s2255_exit_v4l(dev); | ||
1708 | /* board shutdown stops the read pipe if it is running */ | 1850 | /* board shutdown stops the read pipe if it is running */ |
1709 | s2255_board_shutdown(dev); | 1851 | s2255_board_shutdown(dev); |
1710 | /* make sure firmware still not trying to load */ | 1852 | /* make sure firmware still not trying to load */ |
1711 | del_timer(&dev->timer); /* only started in .probe and .open */ | 1853 | del_timer(&dev->timer); /* only started in .probe and .open */ |
1712 | |||
1713 | if (dev->fw_data->fw_urb) { | 1854 | if (dev->fw_data->fw_urb) { |
1714 | dprintk(2, "kill fw_urb\n"); | ||
1715 | usb_kill_urb(dev->fw_data->fw_urb); | 1855 | usb_kill_urb(dev->fw_data->fw_urb); |
1716 | usb_free_urb(dev->fw_data->fw_urb); | 1856 | usb_free_urb(dev->fw_data->fw_urb); |
1717 | dev->fw_data->fw_urb = NULL; | 1857 | dev->fw_data->fw_urb = NULL; |
@@ -1720,24 +1860,22 @@ static void s2255_destroy(struct kref *kref) | |||
1720 | release_firmware(dev->fw_data->fw); | 1860 | release_firmware(dev->fw_data->fw); |
1721 | kfree(dev->fw_data->pfw_data); | 1861 | kfree(dev->fw_data->pfw_data); |
1722 | kfree(dev->fw_data); | 1862 | kfree(dev->fw_data); |
1863 | /* reset the DSP so firmware can be reloaded next time */ | ||
1864 | s2255_reset_dsppower(dev); | ||
1865 | mutex_destroy(&dev->open_lock); | ||
1866 | mutex_destroy(&dev->lock); | ||
1723 | usb_put_dev(dev->udev); | 1867 | usb_put_dev(dev->udev); |
1724 | dprintk(1, "%s", __func__); | 1868 | dprintk(1, "%s", __func__); |
1725 | |||
1726 | mutex_unlock(&dev->open_lock); | ||
1727 | kfree(dev); | 1869 | kfree(dev); |
1728 | } | 1870 | } |
1729 | 1871 | ||
1730 | static int s2255_close(struct file *file) | 1872 | static int s2255_release(struct file *file) |
1731 | { | 1873 | { |
1732 | struct s2255_fh *fh = file->private_data; | 1874 | struct s2255_fh *fh = file->private_data; |
1733 | struct s2255_dev *dev = fh->dev; | 1875 | struct s2255_dev *dev = fh->dev; |
1734 | struct video_device *vdev = video_devdata(file); | 1876 | struct video_device *vdev = video_devdata(file); |
1735 | |||
1736 | if (!dev) | 1877 | if (!dev) |
1737 | return -ENODEV; | 1878 | return -ENODEV; |
1738 | |||
1739 | mutex_lock(&dev->open_lock); | ||
1740 | |||
1741 | /* turn off stream */ | 1879 | /* turn off stream */ |
1742 | if (res_check(fh)) { | 1880 | if (res_check(fh)) { |
1743 | if (dev->b_acquire[fh->channel]) | 1881 | if (dev->b_acquire[fh->channel]) |
@@ -1745,15 +1883,8 @@ static int s2255_close(struct file *file) | |||
1745 | videobuf_streamoff(&fh->vb_vidq); | 1883 | videobuf_streamoff(&fh->vb_vidq); |
1746 | res_free(dev, fh); | 1884 | res_free(dev, fh); |
1747 | } | 1885 | } |
1748 | |||
1749 | videobuf_mmap_free(&fh->vb_vidq); | 1886 | videobuf_mmap_free(&fh->vb_vidq); |
1750 | dev->users[fh->channel]--; | 1887 | dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev)); |
1751 | |||
1752 | mutex_unlock(&dev->open_lock); | ||
1753 | |||
1754 | kref_put(&dev->kref, s2255_destroy); | ||
1755 | dprintk(1, "s2255: close called (dev=%s, users=%d)\n", | ||
1756 | video_device_node_name(vdev), dev->users[fh->channel]); | ||
1757 | kfree(fh); | 1888 | kfree(fh); |
1758 | return 0; | 1889 | return 0; |
1759 | } | 1890 | } |
@@ -1765,27 +1896,25 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma) | |||
1765 | 1896 | ||
1766 | if (!fh) | 1897 | if (!fh) |
1767 | return -ENODEV; | 1898 | return -ENODEV; |
1768 | dprintk(4, "mmap called, vma=0x%08lx\n", (unsigned long)vma); | 1899 | dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma); |
1769 | |||
1770 | ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); | 1900 | ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); |
1771 | 1901 | dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__, | |
1772 | dprintk(4, "vma start=0x%08lx, size=%ld, ret=%d\n", | ||
1773 | (unsigned long)vma->vm_start, | 1902 | (unsigned long)vma->vm_start, |
1774 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); | 1903 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); |
1775 | |||
1776 | return ret; | 1904 | return ret; |
1777 | } | 1905 | } |
1778 | 1906 | ||
1779 | static const struct v4l2_file_operations s2255_fops_v4l = { | 1907 | static const struct v4l2_file_operations s2255_fops_v4l = { |
1780 | .owner = THIS_MODULE, | 1908 | .owner = THIS_MODULE, |
1781 | .open = s2255_open, | 1909 | .open = s2255_open, |
1782 | .release = s2255_close, | 1910 | .release = s2255_release, |
1783 | .poll = s2255_poll, | 1911 | .poll = s2255_poll, |
1784 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ | 1912 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
1785 | .mmap = s2255_mmap_v4l, | 1913 | .mmap = s2255_mmap_v4l, |
1786 | }; | 1914 | }; |
1787 | 1915 | ||
1788 | static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | 1916 | static const struct v4l2_ioctl_ops s2255_ioctl_ops = { |
1917 | .vidioc_querymenu = vidioc_querymenu, | ||
1789 | .vidioc_querycap = vidioc_querycap, | 1918 | .vidioc_querycap = vidioc_querycap, |
1790 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 1919 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, |
1791 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1920 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
@@ -1811,13 +1940,23 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | |||
1811 | .vidioc_g_jpegcomp = vidioc_g_jpegcomp, | 1940 | .vidioc_g_jpegcomp = vidioc_g_jpegcomp, |
1812 | .vidioc_s_parm = vidioc_s_parm, | 1941 | .vidioc_s_parm = vidioc_s_parm, |
1813 | .vidioc_g_parm = vidioc_g_parm, | 1942 | .vidioc_g_parm = vidioc_g_parm, |
1943 | .vidioc_enum_frameintervals = vidioc_enum_frameintervals, | ||
1814 | }; | 1944 | }; |
1815 | 1945 | ||
1946 | static void s2255_video_device_release(struct video_device *vdev) | ||
1947 | { | ||
1948 | struct s2255_dev *dev = video_get_drvdata(vdev); | ||
1949 | dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels)); | ||
1950 | if (atomic_dec_and_test(&dev->channels)) | ||
1951 | s2255_destroy(dev); | ||
1952 | return; | ||
1953 | } | ||
1954 | |||
1816 | static struct video_device template = { | 1955 | static struct video_device template = { |
1817 | .name = "s2255v", | 1956 | .name = "s2255v", |
1818 | .fops = &s2255_fops_v4l, | 1957 | .fops = &s2255_fops_v4l, |
1819 | .ioctl_ops = &s2255_ioctl_ops, | 1958 | .ioctl_ops = &s2255_ioctl_ops, |
1820 | .release = video_device_release, | 1959 | .release = s2255_video_device_release, |
1821 | .tvnorms = S2255_NORMS, | 1960 | .tvnorms = S2255_NORMS, |
1822 | .current_norm = V4L2_STD_NTSC_M, | 1961 | .current_norm = V4L2_STD_NTSC_M, |
1823 | }; | 1962 | }; |
@@ -1827,7 +1966,9 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1827 | int ret; | 1966 | int ret; |
1828 | int i; | 1967 | int i; |
1829 | int cur_nr = video_nr; | 1968 | int cur_nr = video_nr; |
1830 | 1969 | ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev); | |
1970 | if (ret) | ||
1971 | return ret; | ||
1831 | /* initialize all video 4 linux */ | 1972 | /* initialize all video 4 linux */ |
1832 | /* register 4 video devices */ | 1973 | /* register 4 video devices */ |
1833 | for (i = 0; i < MAX_CHANNELS; i++) { | 1974 | for (i = 0; i < MAX_CHANNELS; i++) { |
@@ -1835,45 +1976,39 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1835 | dev->vidq[i].dev = dev; | 1976 | dev->vidq[i].dev = dev; |
1836 | dev->vidq[i].channel = i; | 1977 | dev->vidq[i].channel = i; |
1837 | /* register 4 video devices */ | 1978 | /* register 4 video devices */ |
1838 | dev->vdev[i] = video_device_alloc(); | 1979 | memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); |
1839 | memcpy(dev->vdev[i], &template, sizeof(struct video_device)); | 1980 | dev->vdev[i].v4l2_dev = &dev->v4l2_dev; |
1840 | dev->vdev[i]->parent = &dev->interface->dev; | 1981 | video_set_drvdata(&dev->vdev[i], dev); |
1841 | video_set_drvdata(dev->vdev[i], dev); | ||
1842 | if (video_nr == -1) | 1982 | if (video_nr == -1) |
1843 | ret = video_register_device(dev->vdev[i], | 1983 | ret = video_register_device(&dev->vdev[i], |
1844 | VFL_TYPE_GRABBER, | 1984 | VFL_TYPE_GRABBER, |
1845 | video_nr); | 1985 | video_nr); |
1846 | else | 1986 | else |
1847 | ret = video_register_device(dev->vdev[i], | 1987 | ret = video_register_device(&dev->vdev[i], |
1848 | VFL_TYPE_GRABBER, | 1988 | VFL_TYPE_GRABBER, |
1849 | cur_nr + i); | 1989 | cur_nr + i); |
1850 | video_set_drvdata(dev->vdev[i], dev); | 1990 | if (ret) { |
1851 | |||
1852 | if (ret != 0) { | ||
1853 | dev_err(&dev->udev->dev, | 1991 | dev_err(&dev->udev->dev, |
1854 | "failed to register video device!\n"); | 1992 | "failed to register video device!\n"); |
1855 | return ret; | 1993 | break; |
1856 | } | 1994 | } |
1995 | atomic_inc(&dev->channels); | ||
1996 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", | ||
1997 | video_device_node_name(&dev->vdev[i])); | ||
1998 | |||
1857 | } | 1999 | } |
2000 | |||
1858 | printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", | 2001 | printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", |
1859 | S2255_MAJOR_VERSION, | 2002 | S2255_MAJOR_VERSION, |
1860 | S2255_MINOR_VERSION); | 2003 | S2255_MINOR_VERSION); |
1861 | return ret; | 2004 | /* if no channels registered, return error and probe will fail*/ |
1862 | } | 2005 | if (atomic_read(&dev->channels) == 0) { |
1863 | 2006 | v4l2_device_unregister(&dev->v4l2_dev); | |
1864 | static void s2255_exit_v4l(struct s2255_dev *dev) | 2007 | return ret; |
1865 | { | ||
1866 | |||
1867 | int i; | ||
1868 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
1869 | if (video_is_registered(dev->vdev[i])) { | ||
1870 | video_unregister_device(dev->vdev[i]); | ||
1871 | printk(KERN_INFO "s2255 unregistered\n"); | ||
1872 | } else { | ||
1873 | video_device_release(dev->vdev[i]); | ||
1874 | printk(KERN_INFO "s2255 released\n"); | ||
1875 | } | ||
1876 | } | 2008 | } |
2009 | if (atomic_read(&dev->channels) != MAX_CHANNELS) | ||
2010 | printk(KERN_WARNING "s2255: Not all channels available.\n"); | ||
2011 | return 0; | ||
1877 | } | 2012 | } |
1878 | 2013 | ||
1879 | /* this function moves the usb stream read pipe data | 2014 | /* this function moves the usb stream read pipe data |
@@ -1907,14 +2042,14 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1907 | if (frm->ulState == S2255_READ_IDLE) { | 2042 | if (frm->ulState == S2255_READ_IDLE) { |
1908 | int jj; | 2043 | int jj; |
1909 | unsigned int cc; | 2044 | unsigned int cc; |
1910 | s32 *pdword; | 2045 | __le32 *pdword; /*data from dsp is little endian */ |
1911 | int payload; | 2046 | int payload; |
1912 | /* search for marker codes */ | 2047 | /* search for marker codes */ |
1913 | pdata = (unsigned char *)pipe_info->transfer_buffer; | 2048 | pdata = (unsigned char *)pipe_info->transfer_buffer; |
2049 | pdword = (__le32 *)pdata; | ||
1914 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { | 2050 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { |
1915 | switch (*(s32 *) pdata) { | 2051 | switch (*pdword) { |
1916 | case S2255_MARKER_FRAME: | 2052 | case S2255_MARKER_FRAME: |
1917 | pdword = (s32 *)pdata; | ||
1918 | dprintk(4, "found frame marker at offset:" | 2053 | dprintk(4, "found frame marker at offset:" |
1919 | " %d [%x %x]\n", jj, pdata[0], | 2054 | " %d [%x %x]\n", jj, pdata[0], |
1920 | pdata[1]); | 2055 | pdata[1]); |
@@ -1938,7 +2073,6 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1938 | dev->jpg_size[dev->cc] = pdword[4]; | 2073 | dev->jpg_size[dev->cc] = pdword[4]; |
1939 | break; | 2074 | break; |
1940 | case S2255_MARKER_RESPONSE: | 2075 | case S2255_MARKER_RESPONSE: |
1941 | pdword = (s32 *)pdata; | ||
1942 | pdata += DEF_USB_BLOCK; | 2076 | pdata += DEF_USB_BLOCK; |
1943 | jj += DEF_USB_BLOCK; | 2077 | jj += DEF_USB_BLOCK; |
1944 | if (pdword[1] >= MAX_CHANNELS) | 2078 | if (pdword[1] >= MAX_CHANNELS) |
@@ -1955,7 +2089,6 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1955 | dprintk(5, "setmode ready %d\n", cc); | 2089 | dprintk(5, "setmode ready %d\n", cc); |
1956 | break; | 2090 | break; |
1957 | case S2255_RESPONSE_FW: | 2091 | case S2255_RESPONSE_FW: |
1958 | |||
1959 | dev->chn_ready |= (1 << cc); | 2092 | dev->chn_ready |= (1 << cc); |
1960 | if ((dev->chn_ready & 0x0f) != 0x0f) | 2093 | if ((dev->chn_ready & 0x0f) != 0x0f) |
1961 | break; | 2094 | break; |
@@ -1965,6 +2098,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1965 | S2255_FW_SUCCESS); | 2098 | S2255_FW_SUCCESS); |
1966 | wake_up(&dev->fw_data->wait_fw); | 2099 | wake_up(&dev->fw_data->wait_fw); |
1967 | break; | 2100 | break; |
2101 | case S2255_RESPONSE_STATUS: | ||
2102 | dev->vidstatus[cc] = pdword[3]; | ||
2103 | dev->vidstatus_ready[cc] = 1; | ||
2104 | wake_up(&dev->wait_vidstatus[cc]); | ||
2105 | dprintk(5, "got vidstatus %x chan %d\n", | ||
2106 | pdword[3], cc); | ||
2107 | break; | ||
1968 | default: | 2108 | default: |
1969 | printk(KERN_INFO "s2255 unknown resp\n"); | 2109 | printk(KERN_INFO "s2255 unknown resp\n"); |
1970 | } | 2110 | } |
@@ -2165,28 +2305,22 @@ static int s2255_release_sys_buffers(struct s2255_dev *dev, | |||
2165 | 2305 | ||
2166 | static int s2255_board_init(struct s2255_dev *dev) | 2306 | static int s2255_board_init(struct s2255_dev *dev) |
2167 | { | 2307 | { |
2168 | int j; | ||
2169 | struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT; | 2308 | struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT; |
2170 | int fw_ver; | 2309 | int fw_ver; |
2310 | int j; | ||
2311 | struct s2255_pipeinfo *pipe = &dev->pipe; | ||
2171 | dprintk(4, "board init: %p", dev); | 2312 | dprintk(4, "board init: %p", dev); |
2172 | 2313 | memset(pipe, 0, sizeof(*pipe)); | |
2173 | for (j = 0; j < MAX_PIPE_BUFFERS; j++) { | 2314 | pipe->dev = dev; |
2174 | struct s2255_pipeinfo *pipe = &dev->pipes[j]; | 2315 | pipe->cur_transfer_size = S2255_USB_XFER_SIZE; |
2175 | 2316 | pipe->max_transfer_size = S2255_USB_XFER_SIZE; | |
2176 | memset(pipe, 0, sizeof(*pipe)); | 2317 | |
2177 | pipe->dev = dev; | 2318 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, |
2178 | pipe->cur_transfer_size = S2255_USB_XFER_SIZE; | 2319 | GFP_KERNEL); |
2179 | pipe->max_transfer_size = S2255_USB_XFER_SIZE; | 2320 | if (pipe->transfer_buffer == NULL) { |
2180 | 2321 | dprintk(1, "out of memory!\n"); | |
2181 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, | 2322 | return -ENOMEM; |
2182 | GFP_KERNEL); | ||
2183 | if (pipe->transfer_buffer == NULL) { | ||
2184 | dprintk(1, "out of memory!\n"); | ||
2185 | return -ENOMEM; | ||
2186 | } | ||
2187 | |||
2188 | } | 2323 | } |
2189 | |||
2190 | /* query the firmware */ | 2324 | /* query the firmware */ |
2191 | fw_ver = s2255_get_fx2fw(dev); | 2325 | fw_ver = s2255_get_fx2fw(dev); |
2192 | 2326 | ||
@@ -2203,6 +2337,8 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
2203 | for (j = 0; j < MAX_CHANNELS; j++) { | 2337 | for (j = 0; j < MAX_CHANNELS; j++) { |
2204 | dev->b_acquire[j] = 0; | 2338 | dev->b_acquire[j] = 0; |
2205 | dev->mode[j] = mode_def; | 2339 | dev->mode[j] = mode_def; |
2340 | if (dev->pid == 0x2257 && j > 1) | ||
2341 | dev->mode[j].color |= (1 << 16); | ||
2206 | dev->jc[j].quality = S2255_DEF_JPEG_QUAL; | 2342 | dev->jc[j].quality = S2255_DEF_JPEG_QUAL; |
2207 | dev->cur_fmt[j] = &formats[0]; | 2343 | dev->cur_fmt[j] = &formats[0]; |
2208 | dev->mode[j].restart = 1; | 2344 | dev->mode[j].restart = 1; |
@@ -2213,16 +2349,14 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
2213 | } | 2349 | } |
2214 | /* start read pipe */ | 2350 | /* start read pipe */ |
2215 | s2255_start_readpipe(dev); | 2351 | s2255_start_readpipe(dev); |
2216 | 2352 | dprintk(1, "%s: success\n", __func__); | |
2217 | dprintk(1, "S2255: board initialized\n"); | ||
2218 | return 0; | 2353 | return 0; |
2219 | } | 2354 | } |
2220 | 2355 | ||
2221 | static int s2255_board_shutdown(struct s2255_dev *dev) | 2356 | static int s2255_board_shutdown(struct s2255_dev *dev) |
2222 | { | 2357 | { |
2223 | u32 i; | 2358 | u32 i; |
2224 | 2359 | dprintk(1, "%s: dev: %p", __func__, dev); | |
2225 | dprintk(1, "S2255: board shutdown: %p", dev); | ||
2226 | 2360 | ||
2227 | for (i = 0; i < MAX_CHANNELS; i++) { | 2361 | for (i = 0; i < MAX_CHANNELS; i++) { |
2228 | if (dev->b_acquire[i]) | 2362 | if (dev->b_acquire[i]) |
@@ -2233,12 +2367,8 @@ static int s2255_board_shutdown(struct s2255_dev *dev) | |||
2233 | 2367 | ||
2234 | for (i = 0; i < MAX_CHANNELS; i++) | 2368 | for (i = 0; i < MAX_CHANNELS; i++) |
2235 | s2255_release_sys_buffers(dev, i); | 2369 | s2255_release_sys_buffers(dev, i); |
2236 | 2370 | /* release transfer buffer */ | |
2237 | /* release transfer buffers */ | 2371 | kfree(dev->pipe.transfer_buffer); |
2238 | for (i = 0; i < MAX_PIPE_BUFFERS; i++) { | ||
2239 | struct s2255_pipeinfo *pipe = &dev->pipes[i]; | ||
2240 | kfree(pipe->transfer_buffer); | ||
2241 | } | ||
2242 | return 0; | 2372 | return 0; |
2243 | } | 2373 | } |
2244 | 2374 | ||
@@ -2248,9 +2378,8 @@ static void read_pipe_completion(struct urb *purb) | |||
2248 | struct s2255_dev *dev; | 2378 | struct s2255_dev *dev; |
2249 | int status; | 2379 | int status; |
2250 | int pipe; | 2380 | int pipe; |
2251 | |||
2252 | pipe_info = purb->context; | 2381 | pipe_info = purb->context; |
2253 | dprintk(100, "read pipe completion %p, status %d\n", purb, | 2382 | dprintk(100, "%s: urb:%p, status %d\n", __func__, purb, |
2254 | purb->status); | 2383 | purb->status); |
2255 | if (pipe_info == NULL) { | 2384 | if (pipe_info == NULL) { |
2256 | dev_err(&purb->dev->dev, "no context!\n"); | 2385 | dev_err(&purb->dev->dev, "no context!\n"); |
@@ -2265,13 +2394,13 @@ static void read_pipe_completion(struct urb *purb) | |||
2265 | status = purb->status; | 2394 | status = purb->status; |
2266 | /* if shutting down, do not resubmit, exit immediately */ | 2395 | /* if shutting down, do not resubmit, exit immediately */ |
2267 | if (status == -ESHUTDOWN) { | 2396 | if (status == -ESHUTDOWN) { |
2268 | dprintk(2, "read_pipe_completion: err shutdown\n"); | 2397 | dprintk(2, "%s: err shutdown\n", __func__); |
2269 | pipe_info->err_count++; | 2398 | pipe_info->err_count++; |
2270 | return; | 2399 | return; |
2271 | } | 2400 | } |
2272 | 2401 | ||
2273 | if (pipe_info->state == 0) { | 2402 | if (pipe_info->state == 0) { |
2274 | dprintk(2, "exiting USB pipe"); | 2403 | dprintk(2, "%s: exiting USB pipe", __func__); |
2275 | return; | 2404 | return; |
2276 | } | 2405 | } |
2277 | 2406 | ||
@@ -2279,7 +2408,7 @@ static void read_pipe_completion(struct urb *purb) | |||
2279 | s2255_read_video_callback(dev, pipe_info); | 2408 | s2255_read_video_callback(dev, pipe_info); |
2280 | else { | 2409 | else { |
2281 | pipe_info->err_count++; | 2410 | pipe_info->err_count++; |
2282 | dprintk(1, "s2255drv: failed URB %d\n", status); | 2411 | dprintk(1, "%s: failed URB %d\n", __func__, status); |
2283 | } | 2412 | } |
2284 | 2413 | ||
2285 | pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); | 2414 | pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); |
@@ -2295,7 +2424,7 @@ static void read_pipe_completion(struct urb *purb) | |||
2295 | dev_err(&dev->udev->dev, "error submitting urb\n"); | 2424 | dev_err(&dev->udev->dev, "error submitting urb\n"); |
2296 | } | 2425 | } |
2297 | } else { | 2426 | } else { |
2298 | dprintk(2, "read pipe complete state 0\n"); | 2427 | dprintk(2, "%s :complete state 0\n", __func__); |
2299 | } | 2428 | } |
2300 | return; | 2429 | return; |
2301 | } | 2430 | } |
@@ -2304,35 +2433,28 @@ static int s2255_start_readpipe(struct s2255_dev *dev) | |||
2304 | { | 2433 | { |
2305 | int pipe; | 2434 | int pipe; |
2306 | int retval; | 2435 | int retval; |
2307 | int i; | 2436 | struct s2255_pipeinfo *pipe_info = &dev->pipe; |
2308 | struct s2255_pipeinfo *pipe_info = dev->pipes; | ||
2309 | pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); | 2437 | pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); |
2310 | dprintk(2, "start pipe IN %d\n", dev->read_endpoint); | 2438 | dprintk(2, "%s: IN %d\n", __func__, dev->read_endpoint); |
2311 | 2439 | pipe_info->state = 1; | |
2312 | for (i = 0; i < MAX_PIPE_BUFFERS; i++) { | 2440 | pipe_info->err_count = 0; |
2313 | pipe_info->state = 1; | 2441 | pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); |
2314 | pipe_info->err_count = 0; | 2442 | if (!pipe_info->stream_urb) { |
2315 | pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); | 2443 | dev_err(&dev->udev->dev, |
2316 | if (!pipe_info->stream_urb) { | 2444 | "ReadStream: Unable to alloc URB\n"); |
2317 | dev_err(&dev->udev->dev, | 2445 | return -ENOMEM; |
2318 | "ReadStream: Unable to alloc URB\n"); | 2446 | } |
2319 | return -ENOMEM; | 2447 | /* transfer buffer allocated in board_init */ |
2320 | } | 2448 | usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, |
2321 | /* transfer buffer allocated in board_init */ | 2449 | pipe, |
2322 | usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, | 2450 | pipe_info->transfer_buffer, |
2323 | pipe, | 2451 | pipe_info->cur_transfer_size, |
2324 | pipe_info->transfer_buffer, | 2452 | read_pipe_completion, pipe_info); |
2325 | pipe_info->cur_transfer_size, | 2453 | retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); |
2326 | read_pipe_completion, pipe_info); | 2454 | if (retval) { |
2327 | 2455 | printk(KERN_ERR "s2255: start read pipe failed\n"); | |
2328 | dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); | 2456 | return retval; |
2329 | retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); | ||
2330 | if (retval) { | ||
2331 | printk(KERN_ERR "s2255: start read pipe failed\n"); | ||
2332 | return retval; | ||
2333 | } | ||
2334 | } | 2457 | } |
2335 | |||
2336 | return 0; | 2458 | return 0; |
2337 | } | 2459 | } |
2338 | 2460 | ||
@@ -2347,10 +2469,7 @@ static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2347 | dprintk(2, "start acquire failed, bad channel %lu\n", chn); | 2469 | dprintk(2, "start acquire failed, bad channel %lu\n", chn); |
2348 | return -1; | 2470 | return -1; |
2349 | } | 2471 | } |
2350 | |||
2351 | chn_rev = G_chnmap[chn]; | 2472 | chn_rev = G_chnmap[chn]; |
2352 | dprintk(1, "S2255: start acquire %lu \n", chn); | ||
2353 | |||
2354 | buffer = kzalloc(512, GFP_KERNEL); | 2473 | buffer = kzalloc(512, GFP_KERNEL); |
2355 | if (buffer == NULL) { | 2474 | if (buffer == NULL) { |
2356 | dev_err(&dev->udev->dev, "out of mem\n"); | 2475 | dev_err(&dev->udev->dev, "out of mem\n"); |
@@ -2366,9 +2485,9 @@ static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2366 | } | 2485 | } |
2367 | 2486 | ||
2368 | /* send the start command */ | 2487 | /* send the start command */ |
2369 | *(u32 *) buffer = IN_DATA_TOKEN; | 2488 | *(__le32 *) buffer = IN_DATA_TOKEN; |
2370 | *((u32 *) buffer + 1) = (u32) chn_rev; | 2489 | *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); |
2371 | *((u32 *) buffer + 2) = (u32) CMD_START; | 2490 | *((__le32 *) buffer + 2) = CMD_START; |
2372 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | 2491 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); |
2373 | if (res != 0) | 2492 | if (res != 0) |
2374 | dev_err(&dev->udev->dev, "CMD_START error\n"); | 2493 | dev_err(&dev->udev->dev, "CMD_START error\n"); |
@@ -2383,65 +2502,41 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2383 | unsigned char *buffer; | 2502 | unsigned char *buffer; |
2384 | int res; | 2503 | int res; |
2385 | unsigned long chn_rev; | 2504 | unsigned long chn_rev; |
2386 | |||
2387 | if (chn >= MAX_CHANNELS) { | 2505 | if (chn >= MAX_CHANNELS) { |
2388 | dprintk(2, "stop acquire failed, bad channel %lu\n", chn); | 2506 | dprintk(2, "stop acquire failed, bad channel %lu\n", chn); |
2389 | return -1; | 2507 | return -1; |
2390 | } | 2508 | } |
2391 | chn_rev = G_chnmap[chn]; | 2509 | chn_rev = G_chnmap[chn]; |
2392 | |||
2393 | buffer = kzalloc(512, GFP_KERNEL); | 2510 | buffer = kzalloc(512, GFP_KERNEL); |
2394 | if (buffer == NULL) { | 2511 | if (buffer == NULL) { |
2395 | dev_err(&dev->udev->dev, "out of mem\n"); | 2512 | dev_err(&dev->udev->dev, "out of mem\n"); |
2396 | return -ENOMEM; | 2513 | return -ENOMEM; |
2397 | } | 2514 | } |
2398 | |||
2399 | /* send the stop command */ | 2515 | /* send the stop command */ |
2400 | dprintk(4, "stop acquire %lu\n", chn); | 2516 | *(__le32 *) buffer = IN_DATA_TOKEN; |
2401 | *(u32 *) buffer = IN_DATA_TOKEN; | 2517 | *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); |
2402 | *((u32 *) buffer + 1) = (u32) chn_rev; | 2518 | *((__le32 *) buffer + 2) = CMD_STOP; |
2403 | *((u32 *) buffer + 2) = CMD_STOP; | ||
2404 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | 2519 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); |
2405 | |||
2406 | if (res != 0) | 2520 | if (res != 0) |
2407 | dev_err(&dev->udev->dev, "CMD_STOP error\n"); | 2521 | dev_err(&dev->udev->dev, "CMD_STOP error\n"); |
2408 | |||
2409 | dprintk(4, "stop acquire: releasing states \n"); | ||
2410 | |||
2411 | kfree(buffer); | 2522 | kfree(buffer); |
2412 | dev->b_acquire[chn] = 0; | 2523 | dev->b_acquire[chn] = 0; |
2413 | 2524 | dprintk(4, "%s: chn %lu, res %d\n", __func__, chn, res); | |
2414 | return res; | 2525 | return res; |
2415 | } | 2526 | } |
2416 | 2527 | ||
2417 | static void s2255_stop_readpipe(struct s2255_dev *dev) | 2528 | static void s2255_stop_readpipe(struct s2255_dev *dev) |
2418 | { | 2529 | { |
2419 | int j; | 2530 | struct s2255_pipeinfo *pipe = &dev->pipe; |
2420 | |||
2421 | if (dev == NULL) { | ||
2422 | s2255_dev_err(&dev->udev->dev, "invalid device\n"); | ||
2423 | return; | ||
2424 | } | ||
2425 | dprintk(4, "stop read pipe\n"); | ||
2426 | for (j = 0; j < MAX_PIPE_BUFFERS; j++) { | ||
2427 | struct s2255_pipeinfo *pipe_info = &dev->pipes[j]; | ||
2428 | if (pipe_info) { | ||
2429 | if (pipe_info->state == 0) | ||
2430 | continue; | ||
2431 | pipe_info->state = 0; | ||
2432 | } | ||
2433 | } | ||
2434 | 2531 | ||
2435 | for (j = 0; j < MAX_PIPE_BUFFERS; j++) { | 2532 | pipe->state = 0; |
2436 | struct s2255_pipeinfo *pipe_info = &dev->pipes[j]; | 2533 | if (pipe->stream_urb) { |
2437 | if (pipe_info->stream_urb) { | 2534 | /* cancel urb */ |
2438 | /* cancel urb */ | 2535 | usb_kill_urb(pipe->stream_urb); |
2439 | usb_kill_urb(pipe_info->stream_urb); | 2536 | usb_free_urb(pipe->stream_urb); |
2440 | usb_free_urb(pipe_info->stream_urb); | 2537 | pipe->stream_urb = NULL; |
2441 | pipe_info->stream_urb = NULL; | ||
2442 | } | ||
2443 | } | 2538 | } |
2444 | dprintk(2, "s2255 stop read pipe: %d\n", j); | 2539 | dprintk(4, "%s", __func__); |
2445 | return; | 2540 | return; |
2446 | } | 2541 | } |
2447 | 2542 | ||
@@ -2473,32 +2568,28 @@ static int s2255_probe(struct usb_interface *interface, | |||
2473 | int retval = -ENOMEM; | 2568 | int retval = -ENOMEM; |
2474 | __le32 *pdata; | 2569 | __le32 *pdata; |
2475 | int fw_size; | 2570 | int fw_size; |
2476 | 2571 | dprintk(2, "%s\n", __func__); | |
2477 | dprintk(2, "s2255: probe\n"); | ||
2478 | |||
2479 | /* allocate memory for our device state and initialize it to zero */ | 2572 | /* allocate memory for our device state and initialize it to zero */ |
2480 | dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); | 2573 | dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); |
2481 | if (dev == NULL) { | 2574 | if (dev == NULL) { |
2482 | s2255_dev_err(&interface->dev, "out of memory\n"); | 2575 | s2255_dev_err(&interface->dev, "out of memory\n"); |
2483 | goto error; | 2576 | return -ENOMEM; |
2484 | } | 2577 | } |
2485 | 2578 | atomic_set(&dev->channels, 0); | |
2579 | dev->pid = id->idProduct; | ||
2486 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); | 2580 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); |
2487 | if (!dev->fw_data) | 2581 | if (!dev->fw_data) |
2488 | goto error; | 2582 | goto errorFWDATA1; |
2489 | |||
2490 | mutex_init(&dev->lock); | 2583 | mutex_init(&dev->lock); |
2491 | mutex_init(&dev->open_lock); | 2584 | mutex_init(&dev->open_lock); |
2492 | |||
2493 | /* grab usb_device and save it */ | 2585 | /* grab usb_device and save it */ |
2494 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 2586 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
2495 | if (dev->udev == NULL) { | 2587 | if (dev->udev == NULL) { |
2496 | dev_err(&interface->dev, "null usb device\n"); | 2588 | dev_err(&interface->dev, "null usb device\n"); |
2497 | retval = -ENODEV; | 2589 | retval = -ENODEV; |
2498 | goto error; | 2590 | goto errorUDEV; |
2499 | } | 2591 | } |
2500 | kref_init(&dev->kref); | 2592 | dprintk(1, "dev: %p, udev %p interface %p\n", dev, |
2501 | dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref, | ||
2502 | dev->udev, interface); | 2593 | dev->udev, interface); |
2503 | dev->interface = interface; | 2594 | dev->interface = interface; |
2504 | /* set up the endpoint information */ | 2595 | /* set up the endpoint information */ |
@@ -2514,39 +2605,33 @@ static int s2255_probe(struct usb_interface *interface, | |||
2514 | 2605 | ||
2515 | if (!dev->read_endpoint) { | 2606 | if (!dev->read_endpoint) { |
2516 | dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); | 2607 | dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); |
2517 | goto error; | 2608 | goto errorEP; |
2518 | } | 2609 | } |
2519 | |||
2520 | /* set intfdata */ | ||
2521 | usb_set_intfdata(interface, dev); | ||
2522 | |||
2523 | dprintk(100, "after intfdata %p\n", dev); | ||
2524 | |||
2525 | init_timer(&dev->timer); | 2610 | init_timer(&dev->timer); |
2526 | dev->timer.function = s2255_timer; | 2611 | dev->timer.function = s2255_timer; |
2527 | dev->timer.data = (unsigned long)dev->fw_data; | 2612 | dev->timer.data = (unsigned long)dev->fw_data; |
2528 | |||
2529 | init_waitqueue_head(&dev->fw_data->wait_fw); | 2613 | init_waitqueue_head(&dev->fw_data->wait_fw); |
2530 | for (i = 0; i < MAX_CHANNELS; i++) | 2614 | for (i = 0; i < MAX_CHANNELS; i++) { |
2531 | init_waitqueue_head(&dev->wait_setmode[i]); | 2615 | init_waitqueue_head(&dev->wait_setmode[i]); |
2532 | 2616 | init_waitqueue_head(&dev->wait_vidstatus[i]); | |
2617 | } | ||
2533 | 2618 | ||
2534 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); | 2619 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); |
2535 | |||
2536 | if (!dev->fw_data->fw_urb) { | 2620 | if (!dev->fw_data->fw_urb) { |
2537 | dev_err(&interface->dev, "out of memory!\n"); | 2621 | dev_err(&interface->dev, "out of memory!\n"); |
2538 | goto error; | 2622 | goto errorFWURB; |
2539 | } | 2623 | } |
2624 | |||
2540 | dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL); | 2625 | dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL); |
2541 | if (!dev->fw_data->pfw_data) { | 2626 | if (!dev->fw_data->pfw_data) { |
2542 | dev_err(&interface->dev, "out of memory!\n"); | 2627 | dev_err(&interface->dev, "out of memory!\n"); |
2543 | goto error; | 2628 | goto errorFWDATA2; |
2544 | } | 2629 | } |
2545 | /* load the first chunk */ | 2630 | /* load the first chunk */ |
2546 | if (request_firmware(&dev->fw_data->fw, | 2631 | if (request_firmware(&dev->fw_data->fw, |
2547 | FIRMWARE_FILE_NAME, &dev->udev->dev)) { | 2632 | FIRMWARE_FILE_NAME, &dev->udev->dev)) { |
2548 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); | 2633 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); |
2549 | goto error; | 2634 | goto errorREQFW; |
2550 | } | 2635 | } |
2551 | /* check the firmware is valid */ | 2636 | /* check the firmware is valid */ |
2552 | fw_size = dev->fw_data->fw->size; | 2637 | fw_size = dev->fw_data->fw->size; |
@@ -2555,59 +2640,80 @@ static int s2255_probe(struct usb_interface *interface, | |||
2555 | if (*pdata != S2255_FW_MARKER) { | 2640 | if (*pdata != S2255_FW_MARKER) { |
2556 | printk(KERN_INFO "Firmware invalid.\n"); | 2641 | printk(KERN_INFO "Firmware invalid.\n"); |
2557 | retval = -ENODEV; | 2642 | retval = -ENODEV; |
2558 | goto error; | 2643 | goto errorFWMARKER; |
2559 | } else { | 2644 | } else { |
2560 | /* make sure firmware is the latest */ | 2645 | /* make sure firmware is the latest */ |
2561 | __le32 *pRel; | 2646 | __le32 *pRel; |
2562 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; | 2647 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; |
2563 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); | 2648 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); |
2649 | dev->dsp_fw_ver = *pRel; | ||
2650 | if (*pRel < S2255_CUR_DSP_FWVER) | ||
2651 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); | ||
2652 | if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) | ||
2653 | printk(KERN_WARNING "s2255: 2257 requires firmware %d" | ||
2654 | "or above.\n", S2255_MIN_DSP_COLORFILTER); | ||
2564 | } | 2655 | } |
2565 | /* loads v4l specific */ | ||
2566 | s2255_probe_v4l(dev); | ||
2567 | usb_reset_device(dev->udev); | 2656 | usb_reset_device(dev->udev); |
2568 | /* load 2255 board specific */ | 2657 | /* load 2255 board specific */ |
2569 | retval = s2255_board_init(dev); | 2658 | retval = s2255_board_init(dev); |
2570 | if (retval) | 2659 | if (retval) |
2571 | goto error; | 2660 | goto errorBOARDINIT; |
2572 | |||
2573 | dprintk(4, "before probe done %p\n", dev); | ||
2574 | spin_lock_init(&dev->slock); | 2661 | spin_lock_init(&dev->slock); |
2575 | |||
2576 | s2255_fwload_start(dev, 0); | 2662 | s2255_fwload_start(dev, 0); |
2663 | /* loads v4l specific */ | ||
2664 | retval = s2255_probe_v4l(dev); | ||
2665 | if (retval) | ||
2666 | goto errorBOARDINIT; | ||
2577 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); | 2667 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); |
2578 | return 0; | 2668 | return 0; |
2579 | error: | 2669 | errorBOARDINIT: |
2670 | s2255_board_shutdown(dev); | ||
2671 | errorFWMARKER: | ||
2672 | release_firmware(dev->fw_data->fw); | ||
2673 | errorREQFW: | ||
2674 | kfree(dev->fw_data->pfw_data); | ||
2675 | errorFWDATA2: | ||
2676 | usb_free_urb(dev->fw_data->fw_urb); | ||
2677 | errorFWURB: | ||
2678 | del_timer(&dev->timer); | ||
2679 | errorEP: | ||
2680 | usb_put_dev(dev->udev); | ||
2681 | errorUDEV: | ||
2682 | kfree(dev->fw_data); | ||
2683 | mutex_destroy(&dev->open_lock); | ||
2684 | mutex_destroy(&dev->lock); | ||
2685 | errorFWDATA1: | ||
2686 | kfree(dev); | ||
2687 | printk(KERN_WARNING "Sensoray 2255 driver load failed: 0x%x\n", retval); | ||
2580 | return retval; | 2688 | return retval; |
2581 | } | 2689 | } |
2582 | 2690 | ||
2583 | /* disconnect routine. when board is removed physically or with rmmod */ | 2691 | /* disconnect routine. when board is removed physically or with rmmod */ |
2584 | static void s2255_disconnect(struct usb_interface *interface) | 2692 | static void s2255_disconnect(struct usb_interface *interface) |
2585 | { | 2693 | { |
2586 | struct s2255_dev *dev = NULL; | 2694 | struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); |
2587 | int i; | 2695 | int i; |
2588 | dprintk(1, "s2255: disconnect interface %p\n", interface); | 2696 | int channels = atomic_read(&dev->channels); |
2589 | dev = usb_get_intfdata(interface); | 2697 | v4l2_device_unregister(&dev->v4l2_dev); |
2590 | 2698 | /*see comments in the uvc_driver.c usb disconnect function */ | |
2591 | /* | 2699 | atomic_inc(&dev->channels); |
2592 | * wake up any of the timers to allow open_lock to be | 2700 | /* unregister each video device. */ |
2593 | * acquired sooner | 2701 | for (i = 0; i < channels; i++) { |
2594 | */ | 2702 | if (video_is_registered(&dev->vdev[i])) |
2703 | video_unregister_device(&dev->vdev[i]); | ||
2704 | } | ||
2705 | /* wake up any of our timers */ | ||
2595 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | 2706 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); |
2596 | wake_up(&dev->fw_data->wait_fw); | 2707 | wake_up(&dev->fw_data->wait_fw); |
2597 | for (i = 0; i < MAX_CHANNELS; i++) { | 2708 | for (i = 0; i < MAX_CHANNELS; i++) { |
2598 | dev->setmode_ready[i] = 1; | 2709 | dev->setmode_ready[i] = 1; |
2599 | wake_up(&dev->wait_setmode[i]); | 2710 | wake_up(&dev->wait_setmode[i]); |
2711 | dev->vidstatus_ready[i] = 1; | ||
2712 | wake_up(&dev->wait_vidstatus[i]); | ||
2600 | } | 2713 | } |
2601 | 2714 | if (atomic_dec_and_test(&dev->channels)) | |
2602 | mutex_lock(&dev->open_lock); | 2715 | s2255_destroy(dev); |
2603 | usb_set_intfdata(interface, NULL); | 2716 | dev_info(&interface->dev, "%s\n", __func__); |
2604 | mutex_unlock(&dev->open_lock); | ||
2605 | |||
2606 | if (dev) { | ||
2607 | kref_put(&dev->kref, s2255_destroy); | ||
2608 | dprintk(1, "s2255drv: disconnect\n"); | ||
2609 | dev_info(&interface->dev, "s2255usb now disconnected\n"); | ||
2610 | } | ||
2611 | } | 2717 | } |
2612 | 2718 | ||
2613 | static struct usb_driver s2255_driver = { | 2719 | static struct usb_driver s2255_driver = { |
@@ -2620,15 +2726,12 @@ static struct usb_driver s2255_driver = { | |||
2620 | static int __init usb_s2255_init(void) | 2726 | static int __init usb_s2255_init(void) |
2621 | { | 2727 | { |
2622 | int result; | 2728 | int result; |
2623 | |||
2624 | /* register this driver with the USB subsystem */ | 2729 | /* register this driver with the USB subsystem */ |
2625 | result = usb_register(&s2255_driver); | 2730 | result = usb_register(&s2255_driver); |
2626 | |||
2627 | if (result) | 2731 | if (result) |
2628 | pr_err(KBUILD_MODNAME | 2732 | pr_err(KBUILD_MODNAME |
2629 | ": usb_register failed. Error number %d\n", result); | 2733 | ": usb_register failed. Error number %d\n", result); |
2630 | 2734 | dprintk(2, "%s\n", __func__); | |
2631 | dprintk(2, "s2255_init: done\n"); | ||
2632 | return result; | 2735 | return result; |
2633 | } | 2736 | } |
2634 | 2737 | ||
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c0a7f8a369f4..53b6fcde3800 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -74,6 +74,7 @@ struct saa711x_state { | |||
74 | int contrast; | 74 | int contrast; |
75 | int hue; | 75 | int hue; |
76 | int sat; | 76 | int sat; |
77 | int chroma_agc; | ||
77 | int width; | 78 | int width; |
78 | int height; | 79 | int height; |
79 | u32 ident; | 80 | u32 ident; |
@@ -592,7 +593,7 @@ static const unsigned char saa7115_init_misc[] = { | |||
592 | R_5D_DID, 0xbd, | 593 | R_5D_DID, 0xbd, |
593 | R_5E_SDID, 0x35, | 594 | R_5E_SDID, 0x35, |
594 | 595 | ||
595 | R_02_INPUT_CNTL_1, 0x84, /* input tuner -> input 4, amplifier active */ | 596 | R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */ |
596 | 597 | ||
597 | R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */ | 598 | R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */ |
598 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, | 599 | R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, |
@@ -743,6 +744,7 @@ static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | |||
743 | static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 744 | static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
744 | { | 745 | { |
745 | struct saa711x_state *state = to_state(sd); | 746 | struct saa711x_state *state = to_state(sd); |
747 | u8 val; | ||
746 | 748 | ||
747 | switch (ctrl->id) { | 749 | switch (ctrl->id) { |
748 | case V4L2_CID_BRIGHTNESS: | 750 | case V4L2_CID_BRIGHTNESS: |
@@ -784,7 +786,21 @@ static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
784 | state->hue = ctrl->value; | 786 | state->hue = ctrl->value; |
785 | saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue); | 787 | saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue); |
786 | break; | 788 | break; |
787 | 789 | case V4L2_CID_CHROMA_AGC: | |
790 | val = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL); | ||
791 | state->chroma_agc = ctrl->value; | ||
792 | if (ctrl->value) | ||
793 | val &= 0x7f; | ||
794 | else | ||
795 | val |= 0x80; | ||
796 | saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, val); | ||
797 | break; | ||
798 | case V4L2_CID_CHROMA_GAIN: | ||
799 | /* Chroma gain cannot be set when AGC is enabled */ | ||
800 | if (state->chroma_agc == 1) | ||
801 | return -EINVAL; | ||
802 | saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, ctrl->value | 0x80); | ||
803 | break; | ||
788 | default: | 804 | default: |
789 | return -EINVAL; | 805 | return -EINVAL; |
790 | } | 806 | } |
@@ -809,6 +825,12 @@ static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
809 | case V4L2_CID_HUE: | 825 | case V4L2_CID_HUE: |
810 | ctrl->value = state->hue; | 826 | ctrl->value = state->hue; |
811 | break; | 827 | break; |
828 | case V4L2_CID_CHROMA_AGC: | ||
829 | ctrl->value = state->chroma_agc; | ||
830 | break; | ||
831 | case V4L2_CID_CHROMA_GAIN: | ||
832 | ctrl->value = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f; | ||
833 | break; | ||
812 | default: | 834 | default: |
813 | return -EINVAL; | 835 | return -EINVAL; |
814 | } | 836 | } |
@@ -1069,7 +1091,7 @@ static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_forma | |||
1069 | saa7115_cfg_vbi_off); | 1091 | saa7115_cfg_vbi_off); |
1070 | } | 1092 | } |
1071 | 1093 | ||
1072 | static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 1094 | static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced) |
1073 | { | 1095 | { |
1074 | static u16 lcr2vbi[] = { | 1096 | static u16 lcr2vbi[] = { |
1075 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | 1097 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ |
@@ -1078,11 +1100,8 @@ static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
1078 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ | 1100 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ |
1079 | 0, 0, 0, 0 | 1101 | 0, 0, 0, 0 |
1080 | }; | 1102 | }; |
1081 | struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced; | ||
1082 | int i; | 1103 | int i; |
1083 | 1104 | ||
1084 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
1085 | return -EINVAL; | ||
1086 | memset(sliced, 0, sizeof(*sliced)); | 1105 | memset(sliced, 0, sizeof(*sliced)); |
1087 | /* done if using raw VBI */ | 1106 | /* done if using raw VBI */ |
1088 | if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) | 1107 | if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) |
@@ -1098,16 +1117,27 @@ static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
1098 | return 0; | 1117 | return 0; |
1099 | } | 1118 | } |
1100 | 1119 | ||
1120 | static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
1121 | { | ||
1122 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
1123 | return -EINVAL; | ||
1124 | return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced); | ||
1125 | } | ||
1126 | |||
1127 | static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) | ||
1128 | { | ||
1129 | saa711x_set_lcr(sd, NULL); | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) | ||
1134 | { | ||
1135 | saa711x_set_lcr(sd, fmt); | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1101 | static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 1139 | static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
1102 | { | 1140 | { |
1103 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
1104 | saa711x_set_lcr(sd, &fmt->fmt.sliced); | ||
1105 | return 0; | ||
1106 | } | ||
1107 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1108 | saa711x_set_lcr(sd, NULL); | ||
1109 | return 0; | ||
1110 | } | ||
1111 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1141 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1112 | return -EINVAL; | 1142 | return -EINVAL; |
1113 | 1143 | ||
@@ -1209,6 +1239,10 @@ static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | |||
1209 | return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); | 1239 | return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); |
1210 | case V4L2_CID_HUE: | 1240 | case V4L2_CID_HUE: |
1211 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); | 1241 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); |
1242 | case V4L2_CID_CHROMA_AGC: | ||
1243 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1244 | case V4L2_CID_CHROMA_GAIN: | ||
1245 | return v4l2_ctrl_query_fill(qc, 0, 127, 1, 48); | ||
1212 | default: | 1246 | default: |
1213 | return -EINVAL; | 1247 | return -EINVAL; |
1214 | } | 1248 | } |
@@ -1524,18 +1558,25 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { | |||
1524 | .s_crystal_freq = saa711x_s_crystal_freq, | 1558 | .s_crystal_freq = saa711x_s_crystal_freq, |
1525 | .g_fmt = saa711x_g_fmt, | 1559 | .g_fmt = saa711x_g_fmt, |
1526 | .s_fmt = saa711x_s_fmt, | 1560 | .s_fmt = saa711x_s_fmt, |
1527 | .g_vbi_data = saa711x_g_vbi_data, | ||
1528 | .decode_vbi_line = saa711x_decode_vbi_line, | ||
1529 | .s_stream = saa711x_s_stream, | 1561 | .s_stream = saa711x_s_stream, |
1530 | .querystd = saa711x_querystd, | 1562 | .querystd = saa711x_querystd, |
1531 | .g_input_status = saa711x_g_input_status, | 1563 | .g_input_status = saa711x_g_input_status, |
1532 | }; | 1564 | }; |
1533 | 1565 | ||
1566 | static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = { | ||
1567 | .g_vbi_data = saa711x_g_vbi_data, | ||
1568 | .decode_vbi_line = saa711x_decode_vbi_line, | ||
1569 | .g_sliced_fmt = saa711x_g_sliced_fmt, | ||
1570 | .s_sliced_fmt = saa711x_s_sliced_fmt, | ||
1571 | .s_raw_fmt = saa711x_s_raw_fmt, | ||
1572 | }; | ||
1573 | |||
1534 | static const struct v4l2_subdev_ops saa711x_ops = { | 1574 | static const struct v4l2_subdev_ops saa711x_ops = { |
1535 | .core = &saa711x_core_ops, | 1575 | .core = &saa711x_core_ops, |
1536 | .tuner = &saa711x_tuner_ops, | 1576 | .tuner = &saa711x_tuner_ops, |
1537 | .audio = &saa711x_audio_ops, | 1577 | .audio = &saa711x_audio_ops, |
1538 | .video = &saa711x_video_ops, | 1578 | .video = &saa711x_video_ops, |
1579 | .vbi = &saa711x_vbi_ops, | ||
1539 | }; | 1580 | }; |
1540 | 1581 | ||
1541 | /* ----------------------------------------------------------------------- */ | 1582 | /* ----------------------------------------------------------------------- */ |
@@ -1593,6 +1634,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1593 | state->contrast = 64; | 1634 | state->contrast = 64; |
1594 | state->hue = 0; | 1635 | state->hue = 0; |
1595 | state->sat = 64; | 1636 | state->sat = 64; |
1637 | state->chroma_agc = 1; | ||
1596 | switch (chip_id) { | 1638 | switch (chip_id) { |
1597 | case '1': | 1639 | case '1': |
1598 | state->ident = V4L2_IDENT_SAA7111; | 1640 | state->ident = V4L2_IDENT_SAA7111; |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 250ef84cf5ca..87986ad62f86 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -625,29 +625,33 @@ static int saa7127_s_stream(struct v4l2_subdev *sd, int enable) | |||
625 | return saa7127_set_video_enable(sd, enable); | 625 | return saa7127_set_video_enable(sd, enable); |
626 | } | 626 | } |
627 | 627 | ||
628 | static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 628 | static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) |
629 | { | 629 | { |
630 | struct saa7127_state *state = to_state(sd); | 630 | struct saa7127_state *state = to_state(sd); |
631 | 631 | ||
632 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | 632 | memset(fmt, 0, sizeof(*fmt)); |
633 | return -EINVAL; | ||
634 | |||
635 | memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); | ||
636 | if (state->vps_enable) | 633 | if (state->vps_enable) |
637 | fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; | 634 | fmt->service_lines[0][16] = V4L2_SLICED_VPS; |
638 | if (state->wss_enable) | 635 | if (state->wss_enable) |
639 | fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; | 636 | fmt->service_lines[0][23] = V4L2_SLICED_WSS_625; |
640 | if (state->cc_enable) { | 637 | if (state->cc_enable) { |
641 | fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; | 638 | fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; |
642 | fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; | 639 | fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; |
643 | } | 640 | } |
644 | fmt->fmt.sliced.service_set = | 641 | fmt->service_set = |
645 | (state->vps_enable ? V4L2_SLICED_VPS : 0) | | 642 | (state->vps_enable ? V4L2_SLICED_VPS : 0) | |
646 | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | | 643 | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | |
647 | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); | 644 | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); |
648 | return 0; | 645 | return 0; |
649 | } | 646 | } |
650 | 647 | ||
648 | static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
649 | { | ||
650 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
651 | return -EINVAL; | ||
652 | return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced); | ||
653 | } | ||
654 | |||
651 | static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) | 655 | static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) |
652 | { | 656 | { |
653 | switch (data->id) { | 657 | switch (data->id) { |
@@ -727,16 +731,21 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = { | |||
727 | }; | 731 | }; |
728 | 732 | ||
729 | static const struct v4l2_subdev_video_ops saa7127_video_ops = { | 733 | static const struct v4l2_subdev_video_ops saa7127_video_ops = { |
730 | .s_vbi_data = saa7127_s_vbi_data, | ||
731 | .g_fmt = saa7127_g_fmt, | 734 | .g_fmt = saa7127_g_fmt, |
732 | .s_std_output = saa7127_s_std_output, | 735 | .s_std_output = saa7127_s_std_output, |
733 | .s_routing = saa7127_s_routing, | 736 | .s_routing = saa7127_s_routing, |
734 | .s_stream = saa7127_s_stream, | 737 | .s_stream = saa7127_s_stream, |
735 | }; | 738 | }; |
736 | 739 | ||
740 | static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = { | ||
741 | .s_vbi_data = saa7127_s_vbi_data, | ||
742 | .g_sliced_fmt = saa7127_g_sliced_fmt, | ||
743 | }; | ||
744 | |||
737 | static const struct v4l2_subdev_ops saa7127_ops = { | 745 | static const struct v4l2_subdev_ops saa7127_ops = { |
738 | .core = &saa7127_core_ops, | 746 | .core = &saa7127_core_ops, |
739 | .video = &saa7127_video_ops, | 747 | .video = &saa7127_video_ops, |
748 | .vbi = &saa7127_vbi_ops, | ||
740 | }; | 749 | }; |
741 | 750 | ||
742 | /* ----------------------------------------------------------------------- */ | 751 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index d48c450ed77c..d3bd82ad010a 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -1011,8 +1011,6 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | |||
1011 | unsigned int idx; | 1011 | unsigned int idx; |
1012 | int err, addr; | 1012 | int err, addr; |
1013 | 1013 | ||
1014 | if (snd_BUG_ON(!chip)) | ||
1015 | return -EINVAL; | ||
1016 | strcpy(card->mixername, "SAA7134 Mixer"); | 1014 | strcpy(card->mixername, "SAA7134 Mixer"); |
1017 | 1015 | ||
1018 | for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { | 1016 | for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 297833fb3b4a..72700d4e3941 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -5355,6 +5355,79 @@ struct saa7134_board saa7134_boards[] = { | |||
5355 | .amux = LINE2, | 5355 | .amux = LINE2, |
5356 | }, | 5356 | }, |
5357 | }, | 5357 | }, |
5358 | [SAA7134_BOARD_HAWELL_HW_404M7] = { | ||
5359 | /* Hawell HW-404M7 & Hawell HW-808M7 */ | ||
5360 | /* Bogoslovskiy Viktor <bogovic@bk.ru> */ | ||
5361 | .name = "Hawell HW-404M7", | ||
5362 | .audio_clock = 0x00200000, | ||
5363 | .tuner_type = UNSET, | ||
5364 | .radio_type = UNSET, | ||
5365 | .tuner_addr = ADDR_UNSET, | ||
5366 | .radio_addr = ADDR_UNSET, | ||
5367 | .gpiomask = 0x389c00, | ||
5368 | .inputs = {{ | ||
5369 | .name = name_comp1, | ||
5370 | .vmux = 3, | ||
5371 | .amux = LINE1, | ||
5372 | .gpio = 0x01fc00, | ||
5373 | } }, | ||
5374 | }, | ||
5375 | [SAA7134_BOARD_BEHOLD_H7] = { | ||
5376 | /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */ | ||
5377 | .name = "Beholder BeholdTV H7", | ||
5378 | .audio_clock = 0x00187de7, | ||
5379 | .tuner_type = TUNER_XC5000, | ||
5380 | .radio_type = UNSET, | ||
5381 | .tuner_addr = ADDR_UNSET, | ||
5382 | .radio_addr = ADDR_UNSET, | ||
5383 | .mpeg = SAA7134_MPEG_DVB, | ||
5384 | .ts_type = SAA7134_MPEG_TS_PARALLEL, | ||
5385 | .inputs = { { | ||
5386 | .name = name_tv, | ||
5387 | .vmux = 2, | ||
5388 | .amux = TV, | ||
5389 | .tv = 1, | ||
5390 | }, { | ||
5391 | .name = name_comp1, | ||
5392 | .vmux = 0, | ||
5393 | .amux = LINE1, | ||
5394 | }, { | ||
5395 | .name = name_svideo, | ||
5396 | .vmux = 9, | ||
5397 | .amux = LINE1, | ||
5398 | } }, | ||
5399 | .radio = { | ||
5400 | .name = name_radio, | ||
5401 | .amux = TV, | ||
5402 | }, | ||
5403 | }, | ||
5404 | [SAA7134_BOARD_BEHOLD_A7] = { | ||
5405 | /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */ | ||
5406 | .name = "Beholder BeholdTV A7", | ||
5407 | .audio_clock = 0x00187de7, | ||
5408 | .tuner_type = TUNER_XC5000, | ||
5409 | .radio_type = UNSET, | ||
5410 | .tuner_addr = ADDR_UNSET, | ||
5411 | .radio_addr = ADDR_UNSET, | ||
5412 | .inputs = { { | ||
5413 | .name = name_tv, | ||
5414 | .vmux = 2, | ||
5415 | .amux = TV, | ||
5416 | .tv = 1, | ||
5417 | }, { | ||
5418 | .name = name_comp1, | ||
5419 | .vmux = 0, | ||
5420 | .amux = LINE1, | ||
5421 | }, { | ||
5422 | .name = name_svideo, | ||
5423 | .vmux = 9, | ||
5424 | .amux = LINE1, | ||
5425 | } }, | ||
5426 | .radio = { | ||
5427 | .name = name_radio, | ||
5428 | .amux = TV, | ||
5429 | }, | ||
5430 | }, | ||
5358 | 5431 | ||
5359 | }; | 5432 | }; |
5360 | 5433 | ||
@@ -6549,6 +6622,18 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6549 | .subvendor = PCI_ANY_ID, | 6622 | .subvendor = PCI_ANY_ID, |
6550 | .subdevice = PCI_ANY_ID, | 6623 | .subdevice = PCI_ANY_ID, |
6551 | .driver_data = SAA7134_BOARD_UNKNOWN, | 6624 | .driver_data = SAA7134_BOARD_UNKNOWN, |
6625 | }, { | ||
6626 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6627 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
6628 | .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ | ||
6629 | .subdevice = 0x7190, | ||
6630 | .driver_data = SAA7134_BOARD_BEHOLD_H7, | ||
6631 | }, { | ||
6632 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6633 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
6634 | .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ | ||
6635 | .subdevice = 0x7090, | ||
6636 | .driver_data = SAA7134_BOARD_BEHOLD_A7, | ||
6552 | },{ | 6637 | },{ |
6553 | /* --- end of list --- */ | 6638 | /* --- end of list --- */ |
6554 | } | 6639 | } |
@@ -6602,6 +6687,8 @@ static int saa7134_xc5000_callback(struct saa7134_dev *dev, | |||
6602 | { | 6687 | { |
6603 | switch (dev->board) { | 6688 | switch (dev->board) { |
6604 | case SAA7134_BOARD_BEHOLD_X7: | 6689 | case SAA7134_BOARD_BEHOLD_X7: |
6690 | case SAA7134_BOARD_BEHOLD_H7: | ||
6691 | case SAA7134_BOARD_BEHOLD_A7: | ||
6605 | if (command == XC5000_TUNER_RESET) { | 6692 | if (command == XC5000_TUNER_RESET) { |
6606 | /* Down and UP pheripherial RESET pin for reset all chips */ | 6693 | /* Down and UP pheripherial RESET pin for reset all chips */ |
6607 | saa_writeb(SAA7134_SPECIAL_MODE, 0x00); | 6694 | saa_writeb(SAA7134_SPECIAL_MODE, 0x00); |
@@ -6973,6 +7060,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6973 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: | 7060 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: |
6974 | case SAA7134_BOARD_BEHOLD_H6: | 7061 | case SAA7134_BOARD_BEHOLD_H6: |
6975 | case SAA7134_BOARD_BEHOLD_X7: | 7062 | case SAA7134_BOARD_BEHOLD_X7: |
7063 | case SAA7134_BOARD_BEHOLD_H7: | ||
7064 | case SAA7134_BOARD_BEHOLD_A7: | ||
6976 | dev->has_remote = SAA7134_REMOTE_I2C; | 7065 | dev->has_remote = SAA7134_REMOTE_I2C; |
6977 | break; | 7066 | break; |
6978 | case SAA7134_BOARD_AVERMEDIA_A169_B: | 7067 | case SAA7134_BOARD_AVERMEDIA_A169_B: |
@@ -7215,6 +7304,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
7215 | printk(KERN_INFO "%s: P7131 analog only, using " | 7304 | printk(KERN_INFO "%s: P7131 analog only, using " |
7216 | "entry of %s\n", | 7305 | "entry of %s\n", |
7217 | dev->name, saa7134_boards[dev->board].name); | 7306 | dev->name, saa7134_boards[dev->board].name); |
7307 | |||
7308 | /* IR init has already happened for other cards, so | ||
7309 | * we have to catch up. */ | ||
7310 | dev->has_remote = SAA7134_REMOTE_GPIO; | ||
7311 | saa7134_input_init1(dev); | ||
7218 | } | 7312 | } |
7219 | break; | 7313 | break; |
7220 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: | 7314 | case SAA7134_BOARD_HAUPPAUGE_HVR1150: |
@@ -7344,6 +7438,23 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
7344 | } | 7438 | } |
7345 | break; | 7439 | break; |
7346 | } | 7440 | } |
7441 | case SAA7134_BOARD_BEHOLD_H6: | ||
7442 | { | ||
7443 | u8 data[] = { 0x09, 0x9f, 0x86, 0x11}; | ||
7444 | struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = data, | ||
7445 | .len = sizeof(data)}; | ||
7446 | |||
7447 | /* The tuner TUNER_PHILIPS_FMD1216MEX_MK3 after hardware */ | ||
7448 | /* start has disabled IF and enabled DVB-T. When saa7134 */ | ||
7449 | /* scan I2C devices it not detect IF tda9887 and can`t */ | ||
7450 | /* watch TV without software reboot. For solve this problem */ | ||
7451 | /* switch the tuner to analog TV mode manually. */ | ||
7452 | if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) | ||
7453 | printk(KERN_WARNING | ||
7454 | "%s: Unable to enable IF of the tuner.\n", | ||
7455 | dev->name); | ||
7456 | break; | ||
7457 | } | ||
7347 | } /* switch() */ | 7458 | } /* switch() */ |
7348 | 7459 | ||
7349 | /* initialize tuner */ | 7460 | /* initialize tuner */ |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index a7ad7810fddc..90f231881297 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -471,7 +471,7 @@ static char *irqbits[] = { | |||
471 | "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3", | 471 | "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3", |
472 | "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC", | 472 | "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC", |
473 | "TRIG_ERR", "CONF_ERR", "LOAD_ERR", | 473 | "TRIG_ERR", "CONF_ERR", "LOAD_ERR", |
474 | "GPIO16?", "GPIO18", "GPIO22", "GPIO23" | 474 | "GPIO16", "GPIO18", "GPIO22", "GPIO23" |
475 | }; | 475 | }; |
476 | #define IRQBITS ARRAY_SIZE(irqbits) | 476 | #define IRQBITS ARRAY_SIZE(irqbits) |
477 | 477 | ||
@@ -601,12 +601,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) | |||
601 | /* disable gpio16 IRQ */ | 601 | /* disable gpio16 IRQ */ |
602 | printk(KERN_WARNING "%s/irq: looping -- " | 602 | printk(KERN_WARNING "%s/irq: looping -- " |
603 | "clearing GPIO16 enable bit\n",dev->name); | 603 | "clearing GPIO16 enable bit\n",dev->name); |
604 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16); | 604 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P); |
605 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N); | ||
605 | } else if (report & SAA7134_IRQ_REPORT_GPIO18) { | 606 | } else if (report & SAA7134_IRQ_REPORT_GPIO18) { |
606 | /* disable gpio18 IRQs */ | 607 | /* disable gpio18 IRQs */ |
607 | printk(KERN_WARNING "%s/irq: looping -- " | 608 | printk(KERN_WARNING "%s/irq: looping -- " |
608 | "clearing GPIO18 enable bit\n",dev->name); | 609 | "clearing GPIO18 enable bit\n",dev->name); |
609 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | 610 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); |
611 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N); | ||
610 | } else { | 612 | } else { |
611 | /* disable all irqs */ | 613 | /* disable all irqs */ |
612 | printk(KERN_WARNING "%s/irq: looping -- " | 614 | printk(KERN_WARNING "%s/irq: looping -- " |
@@ -698,11 +700,13 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) | |||
698 | 700 | ||
699 | if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { | 701 | if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { |
700 | if (dev->remote->mask_keydown & 0x10000) | 702 | if (dev->remote->mask_keydown & 0x10000) |
701 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO16; | 703 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO16_N; |
702 | else if (dev->remote->mask_keydown & 0x40000) | 704 | else { /* Allow enabling both IRQ edge triggers */ |
703 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18; | 705 | if (dev->remote->mask_keydown & 0x40000) |
704 | else if (dev->remote->mask_keyup & 0x40000) | 706 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P; |
705 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; | 707 | if (dev->remote->mask_keyup & 0x40000) |
708 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N; | ||
709 | } | ||
706 | } | 710 | } |
707 | 711 | ||
708 | if (dev->has_remote == SAA7134_REMOTE_I2C) { | 712 | if (dev->has_remote == SAA7134_REMOTE_I2C) { |
@@ -1227,7 +1231,7 @@ static int saa7134_resume(struct pci_dev *pci_dev) | |||
1227 | if (card_has_mpeg(dev)) | 1231 | if (card_has_mpeg(dev)) |
1228 | saa7134_ts_init_hw(dev); | 1232 | saa7134_ts_init_hw(dev); |
1229 | if (dev->remote) | 1233 | if (dev->remote) |
1230 | saa7134_ir_start(dev, dev->remote); | 1234 | saa7134_ir_start(dev); |
1231 | saa7134_hw_enable1(dev); | 1235 | saa7134_hw_enable1(dev); |
1232 | 1236 | ||
1233 | msleep(100); | 1237 | msleep(100); |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 4ab4a987c9b9..31e82be1b7e7 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -1532,6 +1532,15 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1532 | &dev->i2c_adap, &behold_x7_tunerconfig); | 1532 | &dev->i2c_adap, &behold_x7_tunerconfig); |
1533 | } | 1533 | } |
1534 | break; | 1534 | break; |
1535 | case SAA7134_BOARD_BEHOLD_H7: | ||
1536 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1537 | &behold_x7_config, | ||
1538 | &dev->i2c_adap); | ||
1539 | if (fe0->dvb.frontend) { | ||
1540 | dvb_attach(xc5000_attach, fe0->dvb.frontend, | ||
1541 | &dev->i2c_adap, &behold_x7_tunerconfig); | ||
1542 | } | ||
1543 | break; | ||
1535 | case SAA7134_BOARD_AVERMEDIA_A700_PRO: | 1544 | case SAA7134_BOARD_AVERMEDIA_A700_PRO: |
1536 | case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: | 1545 | case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: |
1537 | /* Zarlink ZL10313 */ | 1546 | /* Zarlink ZL10313 */ |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 58a0cdc8414a..e5565e2fd426 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include "saa7134-reg.h" | 28 | #include "saa7134-reg.h" |
29 | #include "saa7134.h" | 29 | #include "saa7134.h" |
30 | 30 | ||
31 | #define MODULE_NAME "saa7134" | ||
32 | |||
31 | static unsigned int disable_ir; | 33 | static unsigned int disable_ir; |
32 | module_param(disable_ir, int, 0444); | 34 | module_param(disable_ir, int, 0444); |
33 | MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); | 35 | MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); |
@@ -66,6 +68,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " | |||
66 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ | 68 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ |
67 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | 69 | static int saa7134_rc5_irq(struct saa7134_dev *dev); |
68 | static int saa7134_nec_irq(struct saa7134_dev *dev); | 70 | static int saa7134_nec_irq(struct saa7134_dev *dev); |
71 | static int saa7134_raw_decode_irq(struct saa7134_dev *dev); | ||
69 | static void nec_task(unsigned long data); | 72 | static void nec_task(unsigned long data); |
70 | static void saa7134_nec_timer(unsigned long data); | 73 | static void saa7134_nec_timer(unsigned long data); |
71 | 74 | ||
@@ -397,14 +400,23 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
397 | 400 | ||
398 | void saa7134_input_irq(struct saa7134_dev *dev) | 401 | void saa7134_input_irq(struct saa7134_dev *dev) |
399 | { | 402 | { |
400 | struct card_ir *ir = dev->remote; | 403 | struct card_ir *ir; |
404 | |||
405 | if (!dev || !dev->remote) | ||
406 | return; | ||
407 | |||
408 | ir = dev->remote; | ||
409 | if (!ir->running) | ||
410 | return; | ||
401 | 411 | ||
402 | if (ir->nec_gpio) { | 412 | if (ir->nec_gpio) { |
403 | saa7134_nec_irq(dev); | 413 | saa7134_nec_irq(dev); |
404 | } else if (!ir->polling && !ir->rc5_gpio) { | 414 | } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { |
405 | build_key(dev); | 415 | build_key(dev); |
406 | } else if (ir->rc5_gpio) { | 416 | } else if (ir->rc5_gpio) { |
407 | saa7134_rc5_irq(dev); | 417 | saa7134_rc5_irq(dev); |
418 | } else if (ir->raw_decode) { | ||
419 | saa7134_raw_decode_irq(dev); | ||
408 | } | 420 | } |
409 | } | 421 | } |
410 | 422 | ||
@@ -417,8 +429,32 @@ static void saa7134_input_timer(unsigned long data) | |||
417 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 429 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
418 | } | 430 | } |
419 | 431 | ||
420 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | 432 | void ir_raw_decode_timer_end(unsigned long data) |
433 | { | ||
434 | struct saa7134_dev *dev = (struct saa7134_dev *)data; | ||
435 | struct card_ir *ir = dev->remote; | ||
436 | |||
437 | ir_raw_event_handle(dev->remote->dev); | ||
438 | |||
439 | ir->active = 0; | ||
440 | } | ||
441 | |||
442 | static int __saa7134_ir_start(void *priv) | ||
421 | { | 443 | { |
444 | struct saa7134_dev *dev = priv; | ||
445 | struct card_ir *ir; | ||
446 | |||
447 | if (!dev) | ||
448 | return -EINVAL; | ||
449 | |||
450 | ir = dev->remote; | ||
451 | if (!ir) | ||
452 | return -EINVAL; | ||
453 | |||
454 | if (ir->running) | ||
455 | return 0; | ||
456 | |||
457 | ir->running = 1; | ||
422 | if (ir->polling) { | 458 | if (ir->polling) { |
423 | setup_timer(&ir->timer, saa7134_input_timer, | 459 | setup_timer(&ir->timer, saa7134_input_timer, |
424 | (unsigned long)dev); | 460 | (unsigned long)dev); |
@@ -441,26 +477,125 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
441 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, | 477 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, |
442 | (unsigned long)dev); | 478 | (unsigned long)dev); |
443 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); | 479 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); |
480 | } else if (ir->raw_decode) { | ||
481 | /* set timer_end for code completion */ | ||
482 | init_timer(&ir->timer_end); | ||
483 | ir->timer_end.function = ir_raw_decode_timer_end; | ||
484 | ir->timer_end.data = (unsigned long)dev; | ||
485 | ir->active = 0; | ||
444 | } | 486 | } |
487 | |||
488 | return 0; | ||
445 | } | 489 | } |
446 | 490 | ||
447 | void saa7134_ir_stop(struct saa7134_dev *dev) | 491 | static void __saa7134_ir_stop(void *priv) |
448 | { | 492 | { |
493 | struct saa7134_dev *dev = priv; | ||
494 | struct card_ir *ir; | ||
495 | |||
496 | if (!dev) | ||
497 | return; | ||
498 | |||
499 | ir = dev->remote; | ||
500 | if (!ir) | ||
501 | return; | ||
502 | |||
503 | if (!ir->running) | ||
504 | return; | ||
449 | if (dev->remote->polling) | 505 | if (dev->remote->polling) |
450 | del_timer_sync(&dev->remote->timer); | 506 | del_timer_sync(&dev->remote->timer); |
507 | else if (ir->rc5_gpio) | ||
508 | del_timer_sync(&ir->timer_end); | ||
509 | else if (ir->nec_gpio) | ||
510 | tasklet_kill(&ir->tlet); | ||
511 | else if (ir->raw_decode) { | ||
512 | del_timer_sync(&ir->timer_end); | ||
513 | ir->active = 0; | ||
514 | } | ||
515 | |||
516 | ir->running = 0; | ||
517 | |||
518 | return; | ||
519 | } | ||
520 | |||
521 | int saa7134_ir_start(struct saa7134_dev *dev) | ||
522 | { | ||
523 | if (dev->remote->users) | ||
524 | return __saa7134_ir_start(dev); | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | void saa7134_ir_stop(struct saa7134_dev *dev) | ||
530 | { | ||
531 | if (dev->remote->users) | ||
532 | __saa7134_ir_stop(dev); | ||
533 | } | ||
534 | |||
535 | static int saa7134_ir_open(void *priv) | ||
536 | { | ||
537 | struct saa7134_dev *dev = priv; | ||
538 | |||
539 | dev->remote->users++; | ||
540 | return __saa7134_ir_start(dev); | ||
541 | } | ||
542 | |||
543 | static void saa7134_ir_close(void *priv) | ||
544 | { | ||
545 | struct saa7134_dev *dev = priv; | ||
546 | |||
547 | dev->remote->users--; | ||
548 | if (!dev->remote->users) | ||
549 | __saa7134_ir_stop(dev); | ||
550 | } | ||
551 | |||
552 | |||
553 | int saa7134_ir_change_protocol(void *priv, u64 ir_type) | ||
554 | { | ||
555 | struct saa7134_dev *dev = priv; | ||
556 | struct card_ir *ir = dev->remote; | ||
557 | u32 nec_gpio, rc5_gpio; | ||
558 | |||
559 | if (ir_type == IR_TYPE_RC5) { | ||
560 | dprintk("Changing protocol to RC5\n"); | ||
561 | nec_gpio = 0; | ||
562 | rc5_gpio = 1; | ||
563 | } else if (ir_type == IR_TYPE_NEC) { | ||
564 | dprintk("Changing protocol to NEC\n"); | ||
565 | nec_gpio = 1; | ||
566 | rc5_gpio = 0; | ||
567 | } else { | ||
568 | dprintk("IR protocol type %ud is not supported\n", | ||
569 | (unsigned)ir_type); | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | if (ir->running) { | ||
574 | saa7134_ir_stop(dev); | ||
575 | ir->nec_gpio = nec_gpio; | ||
576 | ir->rc5_gpio = rc5_gpio; | ||
577 | saa7134_ir_start(dev); | ||
578 | } else { | ||
579 | ir->nec_gpio = nec_gpio; | ||
580 | ir->rc5_gpio = rc5_gpio; | ||
581 | } | ||
582 | |||
583 | return 0; | ||
451 | } | 584 | } |
452 | 585 | ||
453 | int saa7134_input_init1(struct saa7134_dev *dev) | 586 | int saa7134_input_init1(struct saa7134_dev *dev) |
454 | { | 587 | { |
455 | struct card_ir *ir; | 588 | struct card_ir *ir; |
456 | struct input_dev *input_dev; | 589 | struct input_dev *input_dev; |
457 | struct ir_scancode_table *ir_codes = NULL; | 590 | char *ir_codes = NULL; |
458 | u32 mask_keycode = 0; | 591 | u32 mask_keycode = 0; |
459 | u32 mask_keydown = 0; | 592 | u32 mask_keydown = 0; |
460 | u32 mask_keyup = 0; | 593 | u32 mask_keyup = 0; |
461 | int polling = 0; | 594 | int polling = 0; |
462 | int rc5_gpio = 0; | 595 | int rc5_gpio = 0; |
463 | int nec_gpio = 0; | 596 | int nec_gpio = 0; |
597 | int raw_decode = 0; | ||
598 | int allow_protocol_change = 0; | ||
464 | u64 ir_type = IR_TYPE_OTHER; | 599 | u64 ir_type = IR_TYPE_OTHER; |
465 | int err; | 600 | int err; |
466 | 601 | ||
@@ -476,27 +611,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
476 | case SAA7134_BOARD_FLYTVPLATINUM_FM: | 611 | case SAA7134_BOARD_FLYTVPLATINUM_FM: |
477 | case SAA7134_BOARD_FLYTVPLATINUM_MINI2: | 612 | case SAA7134_BOARD_FLYTVPLATINUM_MINI2: |
478 | case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: | 613 | case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: |
479 | ir_codes = &ir_codes_flyvideo_table; | 614 | ir_codes = RC_MAP_FLYVIDEO; |
480 | mask_keycode = 0xEC00000; | 615 | mask_keycode = 0xEC00000; |
481 | mask_keydown = 0x0040000; | 616 | mask_keydown = 0x0040000; |
482 | break; | 617 | break; |
483 | case SAA7134_BOARD_CINERGY400: | 618 | case SAA7134_BOARD_CINERGY400: |
484 | case SAA7134_BOARD_CINERGY600: | 619 | case SAA7134_BOARD_CINERGY600: |
485 | case SAA7134_BOARD_CINERGY600_MK3: | 620 | case SAA7134_BOARD_CINERGY600_MK3: |
486 | ir_codes = &ir_codes_cinergy_table; | 621 | ir_codes = RC_MAP_CINERGY; |
487 | mask_keycode = 0x00003f; | 622 | mask_keycode = 0x00003f; |
488 | mask_keyup = 0x040000; | 623 | mask_keyup = 0x040000; |
489 | break; | 624 | break; |
490 | case SAA7134_BOARD_ECS_TVP3XP: | 625 | case SAA7134_BOARD_ECS_TVP3XP: |
491 | case SAA7134_BOARD_ECS_TVP3XP_4CB5: | 626 | case SAA7134_BOARD_ECS_TVP3XP_4CB5: |
492 | ir_codes = &ir_codes_eztv_table; | 627 | ir_codes = RC_MAP_EZTV; |
493 | mask_keycode = 0x00017c; | 628 | mask_keycode = 0x00017c; |
494 | mask_keyup = 0x000002; | 629 | mask_keyup = 0x000002; |
495 | polling = 50; // ms | 630 | polling = 50; // ms |
496 | break; | 631 | break; |
497 | case SAA7134_BOARD_KWORLD_XPERT: | 632 | case SAA7134_BOARD_KWORLD_XPERT: |
498 | case SAA7134_BOARD_AVACSSMARTTV: | 633 | case SAA7134_BOARD_AVACSSMARTTV: |
499 | ir_codes = &ir_codes_pixelview_table; | 634 | ir_codes = RC_MAP_PIXELVIEW; |
500 | mask_keycode = 0x00001F; | 635 | mask_keycode = 0x00001F; |
501 | mask_keyup = 0x000020; | 636 | mask_keyup = 0x000020; |
502 | polling = 50; // ms | 637 | polling = 50; // ms |
@@ -513,7 +648,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
513 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 648 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
514 | case SAA7134_BOARD_AVERMEDIA_M102: | 649 | case SAA7134_BOARD_AVERMEDIA_M102: |
515 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: | 650 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: |
516 | ir_codes = &ir_codes_avermedia_table; | 651 | ir_codes = RC_MAP_AVERMEDIA; |
517 | mask_keycode = 0x0007C8; | 652 | mask_keycode = 0x0007C8; |
518 | mask_keydown = 0x000010; | 653 | mask_keydown = 0x000010; |
519 | polling = 50; // ms | 654 | polling = 50; // ms |
@@ -522,14 +657,15 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
522 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); | 657 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); |
523 | break; | 658 | break; |
524 | case SAA7134_BOARD_AVERMEDIA_M135A: | 659 | case SAA7134_BOARD_AVERMEDIA_M135A: |
525 | ir_codes = &ir_codes_avermedia_m135a_table; | 660 | ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX; |
526 | mask_keydown = 0x0040000; | 661 | mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ |
527 | mask_keycode = 0x00013f; | 662 | mask_keyup = 0x0040000; |
528 | nec_gpio = 1; | 663 | mask_keycode = 0xffff; |
664 | raw_decode = 1; | ||
529 | break; | 665 | break; |
530 | case SAA7134_BOARD_AVERMEDIA_777: | 666 | case SAA7134_BOARD_AVERMEDIA_777: |
531 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 667 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
532 | ir_codes = &ir_codes_avermedia_table; | 668 | ir_codes = RC_MAP_AVERMEDIA; |
533 | mask_keycode = 0x02F200; | 669 | mask_keycode = 0x02F200; |
534 | mask_keydown = 0x000400; | 670 | mask_keydown = 0x000400; |
535 | polling = 50; // ms | 671 | polling = 50; // ms |
@@ -538,7 +674,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
538 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | 674 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); |
539 | break; | 675 | break; |
540 | case SAA7134_BOARD_AVERMEDIA_A16D: | 676 | case SAA7134_BOARD_AVERMEDIA_A16D: |
541 | ir_codes = &ir_codes_avermedia_a16d_table; | 677 | ir_codes = RC_MAP_AVERMEDIA_A16D; |
542 | mask_keycode = 0x02F200; | 678 | mask_keycode = 0x02F200; |
543 | mask_keydown = 0x000400; | 679 | mask_keydown = 0x000400; |
544 | polling = 50; /* ms */ | 680 | polling = 50; /* ms */ |
@@ -547,14 +683,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
547 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | 683 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); |
548 | break; | 684 | break; |
549 | case SAA7134_BOARD_KWORLD_TERMINATOR: | 685 | case SAA7134_BOARD_KWORLD_TERMINATOR: |
550 | ir_codes = &ir_codes_pixelview_table; | 686 | ir_codes = RC_MAP_PIXELVIEW; |
551 | mask_keycode = 0x00001f; | 687 | mask_keycode = 0x00001f; |
552 | mask_keyup = 0x000060; | 688 | mask_keyup = 0x000060; |
553 | polling = 50; // ms | 689 | polling = 50; // ms |
554 | break; | 690 | break; |
555 | case SAA7134_BOARD_MANLI_MTV001: | 691 | case SAA7134_BOARD_MANLI_MTV001: |
556 | case SAA7134_BOARD_MANLI_MTV002: | 692 | case SAA7134_BOARD_MANLI_MTV002: |
557 | ir_codes = &ir_codes_manli_table; | 693 | ir_codes = RC_MAP_MANLI; |
558 | mask_keycode = 0x001f00; | 694 | mask_keycode = 0x001f00; |
559 | mask_keyup = 0x004000; | 695 | mask_keyup = 0x004000; |
560 | polling = 50; /* ms */ | 696 | polling = 50; /* ms */ |
@@ -574,25 +710,25 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
574 | case SAA7134_BOARD_BEHOLD_507_9FM: | 710 | case SAA7134_BOARD_BEHOLD_507_9FM: |
575 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: | 711 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: |
576 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: | 712 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: |
577 | ir_codes = &ir_codes_manli_table; | 713 | ir_codes = RC_MAP_MANLI; |
578 | mask_keycode = 0x003f00; | 714 | mask_keycode = 0x003f00; |
579 | mask_keyup = 0x004000; | 715 | mask_keyup = 0x004000; |
580 | polling = 50; /* ms */ | 716 | polling = 50; /* ms */ |
581 | break; | 717 | break; |
582 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: | 718 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: |
583 | ir_codes = &ir_codes_behold_columbus_table; | 719 | ir_codes = RC_MAP_BEHOLD_COLUMBUS; |
584 | mask_keycode = 0x003f00; | 720 | mask_keycode = 0x003f00; |
585 | mask_keyup = 0x004000; | 721 | mask_keyup = 0x004000; |
586 | polling = 50; // ms | 722 | polling = 50; // ms |
587 | break; | 723 | break; |
588 | case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: | 724 | case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: |
589 | ir_codes = &ir_codes_pctv_sedna_table; | 725 | ir_codes = RC_MAP_PCTV_SEDNA; |
590 | mask_keycode = 0x001f00; | 726 | mask_keycode = 0x001f00; |
591 | mask_keyup = 0x004000; | 727 | mask_keyup = 0x004000; |
592 | polling = 50; // ms | 728 | polling = 50; // ms |
593 | break; | 729 | break; |
594 | case SAA7134_BOARD_GOTVIEW_7135: | 730 | case SAA7134_BOARD_GOTVIEW_7135: |
595 | ir_codes = &ir_codes_gotview7135_table; | 731 | ir_codes = RC_MAP_GOTVIEW7135; |
596 | mask_keycode = 0x0003CC; | 732 | mask_keycode = 0x0003CC; |
597 | mask_keydown = 0x000010; | 733 | mask_keydown = 0x000010; |
598 | polling = 5; /* ms */ | 734 | polling = 5; /* ms */ |
@@ -601,80 +737,80 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
601 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: | 737 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: |
602 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: | 738 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: |
603 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: | 739 | case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: |
604 | ir_codes = &ir_codes_videomate_tv_pvr_table; | 740 | ir_codes = RC_MAP_VIDEOMATE_TV_PVR; |
605 | mask_keycode = 0x00003F; | 741 | mask_keycode = 0x00003F; |
606 | mask_keyup = 0x400000; | 742 | mask_keyup = 0x400000; |
607 | polling = 50; // ms | 743 | polling = 50; // ms |
608 | break; | 744 | break; |
609 | case SAA7134_BOARD_PROTEUS_2309: | 745 | case SAA7134_BOARD_PROTEUS_2309: |
610 | ir_codes = &ir_codes_proteus_2309_table; | 746 | ir_codes = RC_MAP_PROTEUS_2309; |
611 | mask_keycode = 0x00007F; | 747 | mask_keycode = 0x00007F; |
612 | mask_keyup = 0x000080; | 748 | mask_keyup = 0x000080; |
613 | polling = 50; // ms | 749 | polling = 50; // ms |
614 | break; | 750 | break; |
615 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 751 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
616 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 752 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
617 | ir_codes = &ir_codes_videomate_tv_pvr_table; | 753 | ir_codes = RC_MAP_VIDEOMATE_TV_PVR; |
618 | mask_keycode = 0x003F00; | 754 | mask_keycode = 0x003F00; |
619 | mask_keyup = 0x040000; | 755 | mask_keyup = 0x040000; |
620 | break; | 756 | break; |
621 | case SAA7134_BOARD_FLYDVBS_LR300: | 757 | case SAA7134_BOARD_FLYDVBS_LR300: |
622 | case SAA7134_BOARD_FLYDVBT_LR301: | 758 | case SAA7134_BOARD_FLYDVBT_LR301: |
623 | case SAA7134_BOARD_FLYDVBTDUO: | 759 | case SAA7134_BOARD_FLYDVBTDUO: |
624 | ir_codes = &ir_codes_flydvb_table; | 760 | ir_codes = RC_MAP_FLYDVB; |
625 | mask_keycode = 0x0001F00; | 761 | mask_keycode = 0x0001F00; |
626 | mask_keydown = 0x0040000; | 762 | mask_keydown = 0x0040000; |
627 | break; | 763 | break; |
628 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 764 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
629 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: | 765 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: |
630 | case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: | 766 | case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: |
631 | ir_codes = &ir_codes_asus_pc39_table; | 767 | ir_codes = RC_MAP_ASUS_PC39; |
632 | mask_keydown = 0x0040000; | 768 | mask_keydown = 0x0040000; |
633 | rc5_gpio = 1; | 769 | rc5_gpio = 1; |
634 | break; | 770 | break; |
635 | case SAA7134_BOARD_ENCORE_ENLTV: | 771 | case SAA7134_BOARD_ENCORE_ENLTV: |
636 | case SAA7134_BOARD_ENCORE_ENLTV_FM: | 772 | case SAA7134_BOARD_ENCORE_ENLTV_FM: |
637 | ir_codes = &ir_codes_encore_enltv_table; | 773 | ir_codes = RC_MAP_ENCORE_ENLTV; |
638 | mask_keycode = 0x00007f; | 774 | mask_keycode = 0x00007f; |
639 | mask_keyup = 0x040000; | 775 | mask_keyup = 0x040000; |
640 | polling = 50; // ms | 776 | polling = 50; // ms |
641 | break; | 777 | break; |
642 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: | 778 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: |
643 | ir_codes = &ir_codes_encore_enltv_fm53_table; | 779 | ir_codes = RC_MAP_ENCORE_ENLTV_FM53; |
644 | mask_keydown = 0x0040000; | 780 | mask_keydown = 0x0040000; |
645 | mask_keycode = 0x00007f; | 781 | mask_keycode = 0x00007f; |
646 | nec_gpio = 1; | 782 | nec_gpio = 1; |
647 | break; | 783 | break; |
648 | case SAA7134_BOARD_10MOONSTVMASTER3: | 784 | case SAA7134_BOARD_10MOONSTVMASTER3: |
649 | ir_codes = &ir_codes_encore_enltv_table; | 785 | ir_codes = RC_MAP_ENCORE_ENLTV; |
650 | mask_keycode = 0x5f80000; | 786 | mask_keycode = 0x5f80000; |
651 | mask_keyup = 0x8000000; | 787 | mask_keyup = 0x8000000; |
652 | polling = 50; //ms | 788 | polling = 50; //ms |
653 | break; | 789 | break; |
654 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: | 790 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: |
655 | ir_codes = &ir_codes_genius_tvgo_a11mce_table; | 791 | ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; |
656 | mask_keycode = 0xff; | 792 | mask_keycode = 0xff; |
657 | mask_keydown = 0xf00000; | 793 | mask_keydown = 0xf00000; |
658 | polling = 50; /* ms */ | 794 | polling = 50; /* ms */ |
659 | break; | 795 | break; |
660 | case SAA7134_BOARD_REAL_ANGEL_220: | 796 | case SAA7134_BOARD_REAL_ANGEL_220: |
661 | ir_codes = &ir_codes_real_audio_220_32_keys_table; | 797 | ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; |
662 | mask_keycode = 0x3f00; | 798 | mask_keycode = 0x3f00; |
663 | mask_keyup = 0x4000; | 799 | mask_keyup = 0x4000; |
664 | polling = 50; /* ms */ | 800 | polling = 50; /* ms */ |
665 | break; | 801 | break; |
666 | case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: | 802 | case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: |
667 | ir_codes = &ir_codes_kworld_plus_tv_analog_table; | 803 | ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; |
668 | mask_keycode = 0x7f; | 804 | mask_keycode = 0x7f; |
669 | polling = 40; /* ms */ | 805 | polling = 40; /* ms */ |
670 | break; | 806 | break; |
671 | case SAA7134_BOARD_VIDEOMATE_S350: | 807 | case SAA7134_BOARD_VIDEOMATE_S350: |
672 | ir_codes = &ir_codes_videomate_s350_table; | 808 | ir_codes = RC_MAP_VIDEOMATE_S350; |
673 | mask_keycode = 0x003f00; | 809 | mask_keycode = 0x003f00; |
674 | mask_keydown = 0x040000; | 810 | mask_keydown = 0x040000; |
675 | break; | 811 | break; |
676 | case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: | 812 | case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: |
677 | ir_codes = &ir_codes_winfast_table; | 813 | ir_codes = RC_MAP_WINFAST; |
678 | mask_keycode = 0x5f00; | 814 | mask_keycode = 0x5f00; |
679 | mask_keyup = 0x020000; | 815 | mask_keyup = 0x020000; |
680 | polling = 50; /* ms */ | 816 | polling = 50; /* ms */ |
@@ -695,6 +831,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
695 | } | 831 | } |
696 | 832 | ||
697 | ir->dev = input_dev; | 833 | ir->dev = input_dev; |
834 | dev->remote = ir; | ||
835 | |||
836 | ir->running = 0; | ||
698 | 837 | ||
699 | /* init hardware-specific stuff */ | 838 | /* init hardware-specific stuff */ |
700 | ir->mask_keycode = mask_keycode; | 839 | ir->mask_keycode = mask_keycode; |
@@ -703,6 +842,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
703 | ir->polling = polling; | 842 | ir->polling = polling; |
704 | ir->rc5_gpio = rc5_gpio; | 843 | ir->rc5_gpio = rc5_gpio; |
705 | ir->nec_gpio = nec_gpio; | 844 | ir->nec_gpio = nec_gpio; |
845 | ir->raw_decode = raw_decode; | ||
706 | 846 | ||
707 | /* init input device */ | 847 | /* init input device */ |
708 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 848 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -710,6 +850,19 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
710 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 850 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
711 | pci_name(dev->pci)); | 851 | pci_name(dev->pci)); |
712 | 852 | ||
853 | |||
854 | ir->props.priv = dev; | ||
855 | ir->props.open = saa7134_ir_open; | ||
856 | ir->props.close = saa7134_ir_close; | ||
857 | |||
858 | if (raw_decode) | ||
859 | ir->props.driver_type = RC_DRIVER_IR_RAW; | ||
860 | |||
861 | if (!raw_decode && allow_protocol_change) { | ||
862 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | ||
863 | ir->props.change_protocol = saa7134_ir_change_protocol; | ||
864 | } | ||
865 | |||
713 | err = ir_input_init(input_dev, &ir->ir, ir_type); | 866 | err = ir_input_init(input_dev, &ir->ir, ir_type); |
714 | if (err < 0) | 867 | if (err < 0) |
715 | goto err_out_free; | 868 | goto err_out_free; |
@@ -727,12 +880,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
727 | } | 880 | } |
728 | input_dev->dev.parent = &dev->pci->dev; | 881 | input_dev->dev.parent = &dev->pci->dev; |
729 | 882 | ||
730 | dev->remote = ir; | 883 | err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); |
731 | saa7134_ir_start(dev, ir); | ||
732 | |||
733 | err = ir_input_register(ir->dev, ir_codes, NULL); | ||
734 | if (err) | 884 | if (err) |
735 | goto err_out_stop; | 885 | goto err_out_free; |
736 | 886 | ||
737 | /* the remote isn't as bouncy as a keyboard */ | 887 | /* the remote isn't as bouncy as a keyboard */ |
738 | ir->dev->rep[REP_DELAY] = repeat_delay; | 888 | ir->dev->rep[REP_DELAY] = repeat_delay; |
@@ -740,10 +890,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
740 | 890 | ||
741 | return 0; | 891 | return 0; |
742 | 892 | ||
743 | err_out_stop: | 893 | err_out_free: |
744 | saa7134_ir_stop(dev); | ||
745 | dev->remote = NULL; | 894 | dev->remote = NULL; |
746 | err_out_free: | ||
747 | kfree(ir); | 895 | kfree(ir); |
748 | return err; | 896 | return err; |
749 | } | 897 | } |
@@ -787,24 +935,24 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
787 | dev->init_data.name = "Pinnacle PCTV"; | 935 | dev->init_data.name = "Pinnacle PCTV"; |
788 | if (pinnacle_remote == 0) { | 936 | if (pinnacle_remote == 0) { |
789 | dev->init_data.get_key = get_key_pinnacle_color; | 937 | dev->init_data.get_key = get_key_pinnacle_color; |
790 | dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; | 938 | dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; |
791 | info.addr = 0x47; | 939 | info.addr = 0x47; |
792 | } else { | 940 | } else { |
793 | dev->init_data.get_key = get_key_pinnacle_grey; | 941 | dev->init_data.get_key = get_key_pinnacle_grey; |
794 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; | 942 | dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; |
795 | info.addr = 0x47; | 943 | info.addr = 0x47; |
796 | } | 944 | } |
797 | break; | 945 | break; |
798 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 946 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
799 | dev->init_data.name = "Purple TV"; | 947 | dev->init_data.name = "Purple TV"; |
800 | dev->init_data.get_key = get_key_purpletv; | 948 | dev->init_data.get_key = get_key_purpletv; |
801 | dev->init_data.ir_codes = &ir_codes_purpletv_table; | 949 | dev->init_data.ir_codes = RC_MAP_PURPLETV; |
802 | info.addr = 0x7a; | 950 | info.addr = 0x7a; |
803 | break; | 951 | break; |
804 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | 952 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: |
805 | dev->init_data.name = "MSI TV@nywhere Plus"; | 953 | dev->init_data.name = "MSI TV@nywhere Plus"; |
806 | dev->init_data.get_key = get_key_msi_tvanywhere_plus; | 954 | dev->init_data.get_key = get_key_msi_tvanywhere_plus; |
807 | dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; | 955 | dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; |
808 | info.addr = 0x30; | 956 | info.addr = 0x30; |
809 | /* MSI TV@nywhere Plus controller doesn't seem to | 957 | /* MSI TV@nywhere Plus controller doesn't seem to |
810 | respond to probes unless we read something from | 958 | respond to probes unless we read something from |
@@ -818,7 +966,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
818 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 966 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
819 | dev->init_data.name = "HVR 1110"; | 967 | dev->init_data.name = "HVR 1110"; |
820 | dev->init_data.get_key = get_key_hvr1110; | 968 | dev->init_data.get_key = get_key_hvr1110; |
821 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; | 969 | dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; |
822 | info.addr = 0x71; | 970 | info.addr = 0x71; |
823 | break; | 971 | break; |
824 | case SAA7134_BOARD_BEHOLD_607FM_MK3: | 972 | case SAA7134_BOARD_BEHOLD_607FM_MK3: |
@@ -834,9 +982,12 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
834 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: | 982 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: |
835 | case SAA7134_BOARD_BEHOLD_H6: | 983 | case SAA7134_BOARD_BEHOLD_H6: |
836 | case SAA7134_BOARD_BEHOLD_X7: | 984 | case SAA7134_BOARD_BEHOLD_X7: |
985 | case SAA7134_BOARD_BEHOLD_H7: | ||
986 | case SAA7134_BOARD_BEHOLD_A7: | ||
837 | dev->init_data.name = "BeholdTV"; | 987 | dev->init_data.name = "BeholdTV"; |
838 | dev->init_data.get_key = get_key_beholdm6xx; | 988 | dev->init_data.get_key = get_key_beholdm6xx; |
839 | dev->init_data.ir_codes = &ir_codes_behold_table; | 989 | dev->init_data.ir_codes = RC_MAP_BEHOLD; |
990 | dev->init_data.type = IR_TYPE_NEC; | ||
840 | info.addr = 0x2d; | 991 | info.addr = 0x2d; |
841 | break; | 992 | break; |
842 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: | 993 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: |
@@ -846,7 +997,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
846 | case SAA7134_BOARD_FLYDVB_TRIO: | 997 | case SAA7134_BOARD_FLYDVB_TRIO: |
847 | dev->init_data.name = "FlyDVB Trio"; | 998 | dev->init_data.name = "FlyDVB Trio"; |
848 | dev->init_data.get_key = get_key_flydvb_trio; | 999 | dev->init_data.get_key = get_key_flydvb_trio; |
849 | dev->init_data.ir_codes = &ir_codes_flydvb_table; | 1000 | dev->init_data.ir_codes = RC_MAP_FLYDVB; |
850 | info.addr = 0x0b; | 1001 | info.addr = 0x0b; |
851 | break; | 1002 | break; |
852 | default: | 1003 | default: |
@@ -859,6 +1010,33 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
859 | i2c_new_device(&dev->i2c_adap, &info); | 1010 | i2c_new_device(&dev->i2c_adap, &info); |
860 | } | 1011 | } |
861 | 1012 | ||
1013 | static int saa7134_raw_decode_irq(struct saa7134_dev *dev) | ||
1014 | { | ||
1015 | struct card_ir *ir = dev->remote; | ||
1016 | unsigned long timeout; | ||
1017 | int space; | ||
1018 | |||
1019 | /* Generate initial event */ | ||
1020 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
1021 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
1022 | space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | ||
1023 | ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); | ||
1024 | |||
1025 | |||
1026 | /* | ||
1027 | * Wait 15 ms from the start of the first IR event before processing | ||
1028 | * the event. This time is enough for NEC protocol. May need adjustments | ||
1029 | * to work with other protocols. | ||
1030 | */ | ||
1031 | if (!ir->active) { | ||
1032 | timeout = jiffies + jiffies_to_msecs(15); | ||
1033 | mod_timer(&ir->timer_end, timeout); | ||
1034 | ir->active = 1; | ||
1035 | } | ||
1036 | |||
1037 | return 1; | ||
1038 | } | ||
1039 | |||
862 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | 1040 | static int saa7134_rc5_irq(struct saa7134_dev *dev) |
863 | { | 1041 | { |
864 | struct card_ir *ir = dev->remote; | 1042 | struct card_ir *ir = dev->remote; |
@@ -901,7 +1079,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) | |||
901 | return 1; | 1079 | return 1; |
902 | } | 1080 | } |
903 | 1081 | ||
904 | |||
905 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms | 1082 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms |
906 | The first pulse (start) has 9 + 4.5 ms | 1083 | The first pulse (start) has 9 + 4.5 ms |
907 | */ | 1084 | */ |
@@ -1011,14 +1188,14 @@ static void nec_task(unsigned long data) | |||
1011 | /* Keep repeating the last key */ | 1188 | /* Keep repeating the last key */ |
1012 | mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); | 1189 | mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); |
1013 | 1190 | ||
1014 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | 1191 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); |
1015 | } | 1192 | } |
1016 | 1193 | ||
1017 | static int saa7134_nec_irq(struct saa7134_dev *dev) | 1194 | static int saa7134_nec_irq(struct saa7134_dev *dev) |
1018 | { | 1195 | { |
1019 | struct card_ir *ir = dev->remote; | 1196 | struct card_ir *ir = dev->remote; |
1020 | 1197 | ||
1021 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | 1198 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); |
1022 | tasklet_schedule(&ir->tlet); | 1199 | tasklet_schedule(&ir->tlet); |
1023 | 1200 | ||
1024 | return 1; | 1201 | return 1; |
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index cf89d96d7295..e7e0af101fa7 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h | |||
@@ -112,17 +112,17 @@ | |||
112 | #define SAA7134_IRQ1_INTE_RA0_0 (1 << 0) | 112 | #define SAA7134_IRQ1_INTE_RA0_0 (1 << 0) |
113 | 113 | ||
114 | #define SAA7134_IRQ2 (0x2c8 >> 2) | 114 | #define SAA7134_IRQ2 (0x2c8 >> 2) |
115 | #define SAA7134_IRQ2_INTE_GPIO23A (1 << 17) | 115 | #define SAA7134_IRQ2_INTE_GPIO23_N (1 << 17) /* negative edge */ |
116 | #define SAA7134_IRQ2_INTE_GPIO23 (1 << 16) | 116 | #define SAA7134_IRQ2_INTE_GPIO23_P (1 << 16) /* positive edge */ |
117 | #define SAA7134_IRQ2_INTE_GPIO22A (1 << 15) | 117 | #define SAA7134_IRQ2_INTE_GPIO22_N (1 << 15) /* negative edge */ |
118 | #define SAA7134_IRQ2_INTE_GPIO22 (1 << 14) | 118 | #define SAA7134_IRQ2_INTE_GPIO22_P (1 << 14) /* positive edge */ |
119 | #define SAA7134_IRQ2_INTE_GPIO18A (1 << 13) | 119 | #define SAA7134_IRQ2_INTE_GPIO18_N (1 << 13) /* negative edge */ |
120 | #define SAA7134_IRQ2_INTE_GPIO18 (1 << 12) | 120 | #define SAA7134_IRQ2_INTE_GPIO18_P (1 << 12) /* positive edge */ |
121 | #define SAA7134_IRQ2_INTE_GPIO16 (1 << 11) /* not certain */ | 121 | #define SAA7134_IRQ2_INTE_GPIO16_N (1 << 11) /* negative edge */ |
122 | #define SAA7134_IRQ2_INTE_SC2 (1 << 10) | 122 | #define SAA7134_IRQ2_INTE_GPIO16_P (1 << 10) /* positive edge */ |
123 | #define SAA7134_IRQ2_INTE_SC1 (1 << 9) | 123 | #define SAA7134_IRQ2_INTE_SC2 (1 << 9) |
124 | #define SAA7134_IRQ2_INTE_SC0 (1 << 8) | 124 | #define SAA7134_IRQ2_INTE_SC1 (1 << 8) |
125 | #define SAA7134_IRQ2_INTE_DEC5 (1 << 7) | 125 | #define SAA7134_IRQ2_INTE_SC0 (1 << 7) |
126 | #define SAA7134_IRQ2_INTE_DEC4 (1 << 6) | 126 | #define SAA7134_IRQ2_INTE_DEC4 (1 << 6) |
127 | #define SAA7134_IRQ2_INTE_DEC3 (1 << 5) | 127 | #define SAA7134_IRQ2_INTE_DEC3 (1 << 5) |
128 | #define SAA7134_IRQ2_INTE_DEC2 (1 << 4) | 128 | #define SAA7134_IRQ2_INTE_DEC2 (1 << 4) |
@@ -135,7 +135,7 @@ | |||
135 | #define SAA7134_IRQ_REPORT_GPIO23 (1 << 17) | 135 | #define SAA7134_IRQ_REPORT_GPIO23 (1 << 17) |
136 | #define SAA7134_IRQ_REPORT_GPIO22 (1 << 16) | 136 | #define SAA7134_IRQ_REPORT_GPIO22 (1 << 16) |
137 | #define SAA7134_IRQ_REPORT_GPIO18 (1 << 15) | 137 | #define SAA7134_IRQ_REPORT_GPIO18 (1 << 15) |
138 | #define SAA7134_IRQ_REPORT_GPIO16 (1 << 14) /* not certain */ | 138 | #define SAA7134_IRQ_REPORT_GPIO16 (1 << 14) |
139 | #define SAA7134_IRQ_REPORT_LOAD_ERR (1 << 13) | 139 | #define SAA7134_IRQ_REPORT_LOAD_ERR (1 << 13) |
140 | #define SAA7134_IRQ_REPORT_CONF_ERR (1 << 12) | 140 | #define SAA7134_IRQ_REPORT_CONF_ERR (1 << 12) |
141 | #define SAA7134_IRQ_REPORT_TRIG_ERR (1 << 11) | 141 | #define SAA7134_IRQ_REPORT_TRIG_ERR (1 << 11) |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 31138d3e51bb..45f0ac8f3c0f 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1180,7 +1180,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str | |||
1180 | That needs to be fixed somehow, but for now this is | 1180 | That needs to be fixed somehow, but for now this is |
1181 | good enough. */ | 1181 | good enough. */ |
1182 | if (fh) { | 1182 | if (fh) { |
1183 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1183 | err = v4l2_prio_check(&dev->prio, fh->prio); |
1184 | if (0 != err) | 1184 | if (0 != err) |
1185 | return err; | 1185 | return err; |
1186 | } | 1186 | } |
@@ -1359,7 +1359,7 @@ static int video_open(struct file *file) | |||
1359 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); | 1359 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); |
1360 | fh->width = 720; | 1360 | fh->width = 720; |
1361 | fh->height = 576; | 1361 | fh->height = 576; |
1362 | v4l2_prio_open(&dev->prio,&fh->prio); | 1362 | v4l2_prio_open(&dev->prio, &fh->prio); |
1363 | 1363 | ||
1364 | videobuf_queue_sg_init(&fh->cap, &video_qops, | 1364 | videobuf_queue_sg_init(&fh->cap, &video_qops, |
1365 | &dev->pci->dev, &dev->slock, | 1365 | &dev->pci->dev, &dev->slock, |
@@ -1502,7 +1502,7 @@ static int video_release(struct file *file) | |||
1502 | saa7134_pgtable_free(dev->pci,&fh->pt_cap); | 1502 | saa7134_pgtable_free(dev->pci,&fh->pt_cap); |
1503 | saa7134_pgtable_free(dev->pci,&fh->pt_vbi); | 1503 | saa7134_pgtable_free(dev->pci,&fh->pt_vbi); |
1504 | 1504 | ||
1505 | v4l2_prio_close(&dev->prio,&fh->prio); | 1505 | v4l2_prio_close(&dev->prio, fh->prio); |
1506 | file->private_data = NULL; | 1506 | file->private_data = NULL; |
1507 | kfree(fh); | 1507 | kfree(fh); |
1508 | return 0; | 1508 | return 0; |
@@ -1632,8 +1632,15 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, | |||
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | f->fmt.pix.field = field; | 1634 | f->fmt.pix.field = field; |
1635 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | 1635 | if (f->fmt.pix.width < 48) |
1636 | &f->fmt.pix.height, 32, maxh, 0, 0); | 1636 | f->fmt.pix.width = 48; |
1637 | if (f->fmt.pix.height < 32) | ||
1638 | f->fmt.pix.height = 32; | ||
1639 | if (f->fmt.pix.width > maxw) | ||
1640 | f->fmt.pix.width = maxw; | ||
1641 | if (f->fmt.pix.height > maxh) | ||
1642 | f->fmt.pix.height = maxh; | ||
1643 | f->fmt.pix.width &= ~0x03; | ||
1637 | f->fmt.pix.bytesperline = | 1644 | f->fmt.pix.bytesperline = |
1638 | (f->fmt.pix.width * fmt->depth) >> 3; | 1645 | (f->fmt.pix.width * fmt->depth) >> 3; |
1639 | f->fmt.pix.sizeimage = | 1646 | f->fmt.pix.sizeimage = |
@@ -1778,7 +1785,7 @@ static int saa7134_s_input(struct file *file, void *priv, unsigned int i) | |||
1778 | struct saa7134_dev *dev = fh->dev; | 1785 | struct saa7134_dev *dev = fh->dev; |
1779 | int err; | 1786 | int err; |
1780 | 1787 | ||
1781 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1788 | err = v4l2_prio_check(&dev->prio, fh->prio); |
1782 | if (0 != err) | 1789 | if (0 != err) |
1783 | return err; | 1790 | return err; |
1784 | 1791 | ||
@@ -1832,7 +1839,7 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_ | |||
1832 | That needs to be fixed somehow, but for now this is | 1839 | That needs to be fixed somehow, but for now this is |
1833 | good enough. */ | 1840 | good enough. */ |
1834 | if (fh) { | 1841 | if (fh) { |
1835 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1842 | err = v4l2_prio_check(&dev->prio, fh->prio); |
1836 | if (0 != err) | 1843 | if (0 != err) |
1837 | return err; | 1844 | return err; |
1838 | } else if (res_locked(dev, RESOURCE_OVERLAY)) { | 1845 | } else if (res_locked(dev, RESOURCE_OVERLAY)) { |
@@ -2016,7 +2023,7 @@ static int saa7134_s_tuner(struct file *file, void *priv, | |||
2016 | struct saa7134_dev *dev = fh->dev; | 2023 | struct saa7134_dev *dev = fh->dev; |
2017 | int rx, mode, err; | 2024 | int rx, mode, err; |
2018 | 2025 | ||
2019 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 2026 | err = v4l2_prio_check(&dev->prio, fh->prio); |
2020 | if (0 != err) | 2027 | if (0 != err) |
2021 | return err; | 2028 | return err; |
2022 | 2029 | ||
@@ -2050,7 +2057,7 @@ static int saa7134_s_frequency(struct file *file, void *priv, | |||
2050 | struct saa7134_dev *dev = fh->dev; | 2057 | struct saa7134_dev *dev = fh->dev; |
2051 | int err; | 2058 | int err; |
2052 | 2059 | ||
2053 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 2060 | err = v4l2_prio_check(&dev->prio, fh->prio); |
2054 | if (0 != err) | 2061 | if (0 != err) |
2055 | return err; | 2062 | return err; |
2056 | 2063 | ||
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index bf130967ed17..3962534267be 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/version.h> | 22 | #include <linux/version.h> |
23 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,15) | 23 | #define SAA7134_VERSION_CODE KERNEL_VERSION(0, 2, 16) |
24 | 24 | ||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
@@ -300,6 +300,9 @@ struct saa7134_format { | |||
300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 | 300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 |
301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 | 301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 |
302 | #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 | 302 | #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 |
303 | #define SAA7134_BOARD_HAWELL_HW_404M7 177 | ||
304 | #define SAA7134_BOARD_BEHOLD_H7 178 | ||
305 | #define SAA7134_BOARD_BEHOLD_A7 179 | ||
303 | 306 | ||
304 | #define SAA7134_MAXBOARDS 32 | 307 | #define SAA7134_MAXBOARDS 32 |
305 | #define SAA7134_INPUT_MAX 8 | 308 | #define SAA7134_INPUT_MAX 8 |
@@ -809,7 +812,7 @@ int saa7134_input_init1(struct saa7134_dev *dev); | |||
809 | void saa7134_input_fini(struct saa7134_dev *dev); | 812 | void saa7134_input_fini(struct saa7134_dev *dev); |
810 | void saa7134_input_irq(struct saa7134_dev *dev); | 813 | void saa7134_input_irq(struct saa7134_dev *dev); |
811 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev); | 814 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev); |
812 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); | 815 | int saa7134_ir_start(struct saa7134_dev *dev); |
813 | void saa7134_ir_stop(struct saa7134_dev *dev); | 816 | void saa7134_ir_stop(struct saa7134_dev *dev); |
814 | 817 | ||
815 | 818 | ||
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 1ad980f8e770..4ac3b482fbb4 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -115,9 +115,20 @@ struct sh_mobile_ceu_dev { | |||
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct sh_mobile_ceu_cam { | 117 | struct sh_mobile_ceu_cam { |
118 | struct v4l2_rect ceu_rect; | 118 | /* CEU offsets within scaled by the CEU camera output */ |
119 | unsigned int cam_width; | 119 | unsigned int ceu_left; |
120 | unsigned int cam_height; | 120 | unsigned int ceu_top; |
121 | /* Client output, as seen by the CEU */ | ||
122 | unsigned int width; | ||
123 | unsigned int height; | ||
124 | /* | ||
125 | * User window from S_CROP / G_CROP, produced by client cropping and | ||
126 | * scaling, CEU scaling and CEU cropping, mapped back onto the client | ||
127 | * input window | ||
128 | */ | ||
129 | struct v4l2_rect subrect; | ||
130 | /* Camera cropping rectangle */ | ||
131 | struct v4l2_rect rect; | ||
121 | const struct soc_mbus_pixelfmt *extra_fmt; | 132 | const struct soc_mbus_pixelfmt *extra_fmt; |
122 | enum v4l2_mbus_pixelcode code; | 133 | enum v4l2_mbus_pixelcode code; |
123 | }; | 134 | }; |
@@ -213,8 +224,8 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, | |||
213 | *count = 2; | 224 | *count = 2; |
214 | 225 | ||
215 | if (pcdev->video_limit) { | 226 | if (pcdev->video_limit) { |
216 | while (PAGE_ALIGN(*size) * *count > pcdev->video_limit) | 227 | if (PAGE_ALIGN(*size) * *count > pcdev->video_limit) |
217 | (*count)--; | 228 | *count = pcdev->video_limit / PAGE_ALIGN(*size); |
218 | } | 229 | } |
219 | 230 | ||
220 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); | 231 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); |
@@ -565,38 +576,36 @@ static u16 calc_scale(unsigned int src, unsigned int *dst) | |||
565 | } | 576 | } |
566 | 577 | ||
567 | /* rect is guaranteed to not exceed the scaled camera rectangle */ | 578 | /* rect is guaranteed to not exceed the scaled camera rectangle */ |
568 | static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, | 579 | static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) |
569 | unsigned int out_width, | ||
570 | unsigned int out_height) | ||
571 | { | 580 | { |
572 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 581 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
573 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 582 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
574 | struct v4l2_rect *rect = &cam->ceu_rect; | ||
575 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 583 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
576 | unsigned int height, width, cdwdr_width, in_width, in_height; | 584 | unsigned int height, width, cdwdr_width, in_width, in_height; |
577 | unsigned int left_offset, top_offset; | 585 | unsigned int left_offset, top_offset; |
578 | u32 camor; | 586 | u32 camor; |
579 | 587 | ||
580 | dev_dbg(icd->dev.parent, "Crop %ux%u@%u:%u\n", | 588 | dev_geo(icd->dev.parent, "Crop %ux%u@%u:%u\n", |
581 | rect->width, rect->height, rect->left, rect->top); | 589 | icd->user_width, icd->user_height, cam->ceu_left, cam->ceu_top); |
582 | 590 | ||
583 | left_offset = rect->left; | 591 | left_offset = cam->ceu_left; |
584 | top_offset = rect->top; | 592 | top_offset = cam->ceu_top; |
585 | 593 | ||
594 | /* CEU cropping (CFSZR) is applied _after_ the scaling filter (CFLCR) */ | ||
586 | if (pcdev->image_mode) { | 595 | if (pcdev->image_mode) { |
587 | in_width = rect->width; | 596 | in_width = cam->width; |
588 | if (!pcdev->is_16bit) { | 597 | if (!pcdev->is_16bit) { |
589 | in_width *= 2; | 598 | in_width *= 2; |
590 | left_offset *= 2; | 599 | left_offset *= 2; |
591 | } | 600 | } |
592 | width = out_width; | 601 | width = icd->user_width; |
593 | cdwdr_width = out_width; | 602 | cdwdr_width = icd->user_width; |
594 | } else { | 603 | } else { |
595 | int bytes_per_line = soc_mbus_bytes_per_line(out_width, | 604 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
596 | icd->current_fmt->host_fmt); | 605 | icd->current_fmt->host_fmt); |
597 | unsigned int w_factor; | 606 | unsigned int w_factor; |
598 | 607 | ||
599 | width = out_width; | 608 | width = icd->user_width; |
600 | 609 | ||
601 | switch (icd->current_fmt->host_fmt->packing) { | 610 | switch (icd->current_fmt->host_fmt->packing) { |
602 | case SOC_MBUS_PACKING_2X8_PADHI: | 611 | case SOC_MBUS_PACKING_2X8_PADHI: |
@@ -606,17 +615,17 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, | |||
606 | w_factor = 1; | 615 | w_factor = 1; |
607 | } | 616 | } |
608 | 617 | ||
609 | in_width = rect->width * w_factor; | 618 | in_width = cam->width * w_factor; |
610 | left_offset = left_offset * w_factor; | 619 | left_offset = left_offset * w_factor; |
611 | 620 | ||
612 | if (bytes_per_line < 0) | 621 | if (bytes_per_line < 0) |
613 | cdwdr_width = out_width; | 622 | cdwdr_width = icd->user_width; |
614 | else | 623 | else |
615 | cdwdr_width = bytes_per_line; | 624 | cdwdr_width = bytes_per_line; |
616 | } | 625 | } |
617 | 626 | ||
618 | height = out_height; | 627 | height = icd->user_height; |
619 | in_height = rect->height; | 628 | in_height = cam->height; |
620 | if (V4L2_FIELD_NONE != pcdev->field) { | 629 | if (V4L2_FIELD_NONE != pcdev->field) { |
621 | height /= 2; | 630 | height /= 2; |
622 | in_height /= 2; | 631 | in_height /= 2; |
@@ -775,9 +784,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
775 | } | 784 | } |
776 | ceu_write(pcdev, CAIFR, value); | 785 | ceu_write(pcdev, CAIFR, value); |
777 | 786 | ||
778 | sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); | 787 | sh_mobile_ceu_set_rect(icd); |
779 | mdelay(1); | 788 | mdelay(1); |
780 | 789 | ||
790 | dev_geo(icd->dev.parent, "CFLCR 0x%x\n", pcdev->cflcr); | ||
781 | ceu_write(pcdev, CFLCR, pcdev->cflcr); | 791 | ceu_write(pcdev, CFLCR, pcdev->cflcr); |
782 | 792 | ||
783 | /* | 793 | /* |
@@ -866,6 +876,8 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) | |||
866 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); | 876 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
867 | } | 877 | } |
868 | 878 | ||
879 | static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); | ||
880 | |||
869 | static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, | 881 | static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, |
870 | struct soc_camera_format_xlate *xlate) | 882 | struct soc_camera_format_xlate *xlate) |
871 | { | 883 | { |
@@ -894,10 +906,55 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, | |||
894 | return 0; | 906 | return 0; |
895 | 907 | ||
896 | if (!icd->host_priv) { | 908 | if (!icd->host_priv) { |
909 | struct v4l2_mbus_framefmt mf; | ||
910 | struct v4l2_rect rect; | ||
911 | struct device *dev = icd->dev.parent; | ||
912 | int shift = 0; | ||
913 | |||
914 | /* FIXME: subwindow is lost between close / open */ | ||
915 | |||
916 | /* Cache current client geometry */ | ||
917 | ret = client_g_rect(sd, &rect); | ||
918 | if (ret < 0) | ||
919 | return ret; | ||
920 | |||
921 | /* First time */ | ||
922 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
923 | if (ret < 0) | ||
924 | return ret; | ||
925 | |||
926 | while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { | ||
927 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ | ||
928 | mf.width = 2560 >> shift; | ||
929 | mf.height = 1920 >> shift; | ||
930 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
931 | if (ret < 0) | ||
932 | return ret; | ||
933 | shift++; | ||
934 | } | ||
935 | |||
936 | if (shift == 4) { | ||
937 | dev_err(dev, "Failed to configure the client below %ux%x\n", | ||
938 | mf.width, mf.height); | ||
939 | return -EIO; | ||
940 | } | ||
941 | |||
942 | dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); | ||
943 | |||
897 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); | 944 | cam = kzalloc(sizeof(*cam), GFP_KERNEL); |
898 | if (!cam) | 945 | if (!cam) |
899 | return -ENOMEM; | 946 | return -ENOMEM; |
900 | 947 | ||
948 | /* We are called with current camera crop, initialise subrect with it */ | ||
949 | cam->rect = rect; | ||
950 | cam->subrect = rect; | ||
951 | |||
952 | cam->width = mf.width; | ||
953 | cam->height = mf.height; | ||
954 | |||
955 | cam->width = mf.width; | ||
956 | cam->height = mf.height; | ||
957 | |||
901 | icd->host_priv = cam; | 958 | icd->host_priv = cam; |
902 | } else { | 959 | } else { |
903 | cam = icd->host_priv; | 960 | cam = icd->host_priv; |
@@ -979,16 +1036,12 @@ static unsigned int scale_down(unsigned int size, unsigned int scale) | |||
979 | return (size * 4096 + scale / 2) / scale; | 1036 | return (size * 4096 + scale / 2) / scale; |
980 | } | 1037 | } |
981 | 1038 | ||
982 | static unsigned int scale_up(unsigned int size, unsigned int scale) | ||
983 | { | ||
984 | return (size * scale + 2048) / 4096; | ||
985 | } | ||
986 | |||
987 | static unsigned int calc_generic_scale(unsigned int input, unsigned int output) | 1039 | static unsigned int calc_generic_scale(unsigned int input, unsigned int output) |
988 | { | 1040 | { |
989 | return (input * 4096 + output / 2) / output; | 1041 | return (input * 4096 + output / 2) / output; |
990 | } | 1042 | } |
991 | 1043 | ||
1044 | /* Get and store current client crop */ | ||
992 | static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) | 1045 | static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) |
993 | { | 1046 | { |
994 | struct v4l2_crop crop; | 1047 | struct v4l2_crop crop; |
@@ -1007,25 +1060,51 @@ static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) | |||
1007 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1060 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1008 | 1061 | ||
1009 | ret = v4l2_subdev_call(sd, video, cropcap, &cap); | 1062 | ret = v4l2_subdev_call(sd, video, cropcap, &cap); |
1010 | if (ret < 0) | 1063 | if (!ret) |
1011 | return ret; | 1064 | *rect = cap.defrect; |
1012 | |||
1013 | *rect = cap.defrect; | ||
1014 | 1065 | ||
1015 | return ret; | 1066 | return ret; |
1016 | } | 1067 | } |
1017 | 1068 | ||
1069 | /* Client crop has changed, update our sub-rectangle to remain within the area */ | ||
1070 | static void update_subrect(struct sh_mobile_ceu_cam *cam) | ||
1071 | { | ||
1072 | struct v4l2_rect *rect = &cam->rect, *subrect = &cam->subrect; | ||
1073 | |||
1074 | if (rect->width < subrect->width) | ||
1075 | subrect->width = rect->width; | ||
1076 | |||
1077 | if (rect->height < subrect->height) | ||
1078 | subrect->height = rect->height; | ||
1079 | |||
1080 | if (rect->left > subrect->left) | ||
1081 | subrect->left = rect->left; | ||
1082 | else if (rect->left + rect->width > | ||
1083 | subrect->left + subrect->width) | ||
1084 | subrect->left = rect->left + rect->width - | ||
1085 | subrect->width; | ||
1086 | |||
1087 | if (rect->top > subrect->top) | ||
1088 | subrect->top = rect->top; | ||
1089 | else if (rect->top + rect->height > | ||
1090 | subrect->top + subrect->height) | ||
1091 | subrect->top = rect->top + rect->height - | ||
1092 | subrect->height; | ||
1093 | } | ||
1094 | |||
1018 | /* | 1095 | /* |
1019 | * The common for both scaling and cropping iterative approach is: | 1096 | * The common for both scaling and cropping iterative approach is: |
1020 | * 1. try if the client can produce exactly what requested by the user | 1097 | * 1. try if the client can produce exactly what requested by the user |
1021 | * 2. if (1) failed, try to double the client image until we get one big enough | 1098 | * 2. if (1) failed, try to double the client image until we get one big enough |
1022 | * 3. if (2) failed, try to request the maximum image | 1099 | * 3. if (2) failed, try to request the maximum image |
1023 | */ | 1100 | */ |
1024 | static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | 1101 | static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, |
1025 | struct v4l2_crop *cam_crop) | 1102 | struct v4l2_crop *cam_crop) |
1026 | { | 1103 | { |
1104 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1027 | struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; | 1105 | struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; |
1028 | struct device *dev = sd->v4l2_dev->dev; | 1106 | struct device *dev = sd->v4l2_dev->dev; |
1107 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1029 | struct v4l2_cropcap cap; | 1108 | struct v4l2_cropcap cap; |
1030 | int ret; | 1109 | int ret; |
1031 | unsigned int width, height; | 1110 | unsigned int width, height; |
@@ -1041,13 +1120,14 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1041 | */ | 1120 | */ |
1042 | if (!memcmp(rect, cam_rect, sizeof(*rect))) { | 1121 | if (!memcmp(rect, cam_rect, sizeof(*rect))) { |
1043 | /* Even if camera S_CROP failed, but camera rectangle matches */ | 1122 | /* Even if camera S_CROP failed, but camera rectangle matches */ |
1044 | dev_dbg(dev, "Camera S_CROP successful for %ux%u@%u:%u\n", | 1123 | dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", |
1045 | rect->width, rect->height, rect->left, rect->top); | 1124 | rect->width, rect->height, rect->left, rect->top); |
1125 | cam->rect = *cam_rect; | ||
1046 | return 0; | 1126 | return 0; |
1047 | } | 1127 | } |
1048 | 1128 | ||
1049 | /* Try to fix cropping, that camera hasn't managed to set */ | 1129 | /* Try to fix cropping, that camera hasn't managed to set */ |
1050 | dev_geo(dev, "Fix camera S_CROP for %ux%u@%u:%u to %ux%u@%u:%u\n", | 1130 | dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", |
1051 | cam_rect->width, cam_rect->height, | 1131 | cam_rect->width, cam_rect->height, |
1052 | cam_rect->left, cam_rect->top, | 1132 | cam_rect->left, cam_rect->top, |
1053 | rect->width, rect->height, rect->left, rect->top); | 1133 | rect->width, rect->height, rect->left, rect->top); |
@@ -1057,6 +1137,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1057 | if (ret < 0) | 1137 | if (ret < 0) |
1058 | return ret; | 1138 | return ret; |
1059 | 1139 | ||
1140 | /* Put user requested rectangle within sensor bounds */ | ||
1060 | soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, | 1141 | soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, |
1061 | cap.bounds.width); | 1142 | cap.bounds.width); |
1062 | soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, | 1143 | soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, |
@@ -1069,6 +1150,10 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1069 | width = max(cam_rect->width, 2); | 1150 | width = max(cam_rect->width, 2); |
1070 | height = max(cam_rect->height, 2); | 1151 | height = max(cam_rect->height, 2); |
1071 | 1152 | ||
1153 | /* | ||
1154 | * Loop as long as sensor is not covering the requested rectangle and | ||
1155 | * is still within its bounds | ||
1156 | */ | ||
1072 | while (!ret && (is_smaller(cam_rect, rect) || | 1157 | while (!ret && (is_smaller(cam_rect, rect) || |
1073 | is_inside(cam_rect, rect)) && | 1158 | is_inside(cam_rect, rect)) && |
1074 | (cap.bounds.width > width || cap.bounds.height > height)) { | 1159 | (cap.bounds.width > width || cap.bounds.height > height)) { |
@@ -1086,6 +1171,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1086 | * target left, set it to the middle point between the current | 1171 | * target left, set it to the middle point between the current |
1087 | * left and minimum left. But that would add too much | 1172 | * left and minimum left. But that would add too much |
1088 | * complexity: we would have to iterate each border separately. | 1173 | * complexity: we would have to iterate each border separately. |
1174 | * Instead we just drop to the left and top bounds. | ||
1089 | */ | 1175 | */ |
1090 | if (cam_rect->left > rect->left) | 1176 | if (cam_rect->left > rect->left) |
1091 | cam_rect->left = cap.bounds.left; | 1177 | cam_rect->left = cap.bounds.left; |
@@ -1103,7 +1189,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1103 | 1189 | ||
1104 | v4l2_subdev_call(sd, video, s_crop, cam_crop); | 1190 | v4l2_subdev_call(sd, video, s_crop, cam_crop); |
1105 | ret = client_g_rect(sd, cam_rect); | 1191 | ret = client_g_rect(sd, cam_rect); |
1106 | dev_geo(dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, | 1192 | dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, |
1107 | cam_rect->width, cam_rect->height, | 1193 | cam_rect->width, cam_rect->height, |
1108 | cam_rect->left, cam_rect->top); | 1194 | cam_rect->left, cam_rect->top); |
1109 | } | 1195 | } |
@@ -1117,82 +1203,24 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1117 | *cam_rect = cap.bounds; | 1203 | *cam_rect = cap.bounds; |
1118 | v4l2_subdev_call(sd, video, s_crop, cam_crop); | 1204 | v4l2_subdev_call(sd, video, s_crop, cam_crop); |
1119 | ret = client_g_rect(sd, cam_rect); | 1205 | ret = client_g_rect(sd, cam_rect); |
1120 | dev_geo(dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, | 1206 | dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, |
1121 | cam_rect->width, cam_rect->height, | 1207 | cam_rect->width, cam_rect->height, |
1122 | cam_rect->left, cam_rect->top); | 1208 | cam_rect->left, cam_rect->top); |
1123 | } | 1209 | } |
1124 | 1210 | ||
1125 | return ret; | 1211 | if (!ret) { |
1126 | } | 1212 | cam->rect = *cam_rect; |
1127 | 1213 | update_subrect(cam); | |
1128 | static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, | ||
1129 | unsigned int *scale_h, unsigned int *scale_v) | ||
1130 | { | ||
1131 | struct v4l2_mbus_framefmt mf; | ||
1132 | int ret; | ||
1133 | |||
1134 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
1135 | if (ret < 0) | ||
1136 | return ret; | ||
1137 | |||
1138 | *scale_h = calc_generic_scale(rect->width, mf.width); | ||
1139 | *scale_v = calc_generic_scale(rect->height, mf.height); | ||
1140 | |||
1141 | return 0; | ||
1142 | } | ||
1143 | |||
1144 | static int get_camera_subwin(struct soc_camera_device *icd, | ||
1145 | struct v4l2_rect *cam_subrect, | ||
1146 | unsigned int cam_hscale, unsigned int cam_vscale) | ||
1147 | { | ||
1148 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1149 | struct v4l2_rect *ceu_rect = &cam->ceu_rect; | ||
1150 | |||
1151 | if (!ceu_rect->width) { | ||
1152 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1153 | struct device *dev = icd->dev.parent; | ||
1154 | struct v4l2_mbus_framefmt mf; | ||
1155 | int ret; | ||
1156 | /* First time */ | ||
1157 | |||
1158 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); | ||
1159 | if (ret < 0) | ||
1160 | return ret; | ||
1161 | |||
1162 | dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); | ||
1163 | |||
1164 | if (mf.width > 2560) { | ||
1165 | ceu_rect->width = 2560; | ||
1166 | ceu_rect->left = (mf.width - 2560) / 2; | ||
1167 | } else { | ||
1168 | ceu_rect->width = mf.width; | ||
1169 | ceu_rect->left = 0; | ||
1170 | } | ||
1171 | |||
1172 | if (mf.height > 1920) { | ||
1173 | ceu_rect->height = 1920; | ||
1174 | ceu_rect->top = (mf.height - 1920) / 2; | ||
1175 | } else { | ||
1176 | ceu_rect->height = mf.height; | ||
1177 | ceu_rect->top = 0; | ||
1178 | } | ||
1179 | |||
1180 | dev_geo(dev, "initialised CEU rect %ux%u@%u:%u\n", | ||
1181 | ceu_rect->width, ceu_rect->height, | ||
1182 | ceu_rect->left, ceu_rect->top); | ||
1183 | } | 1214 | } |
1184 | 1215 | ||
1185 | cam_subrect->width = scale_up(ceu_rect->width, cam_hscale); | 1216 | return ret; |
1186 | cam_subrect->left = scale_up(ceu_rect->left, cam_hscale); | ||
1187 | cam_subrect->height = scale_up(ceu_rect->height, cam_vscale); | ||
1188 | cam_subrect->top = scale_up(ceu_rect->top, cam_vscale); | ||
1189 | |||
1190 | return 0; | ||
1191 | } | 1217 | } |
1192 | 1218 | ||
1219 | /* Iterative s_mbus_fmt, also updates cached client crop on success */ | ||
1193 | static int client_s_fmt(struct soc_camera_device *icd, | 1220 | static int client_s_fmt(struct soc_camera_device *icd, |
1194 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) | 1221 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) |
1195 | { | 1222 | { |
1223 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1196 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1224 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1197 | struct device *dev = icd->dev.parent; | 1225 | struct device *dev = icd->dev.parent; |
1198 | unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; | 1226 | unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; |
@@ -1200,6 +1228,15 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1200 | struct v4l2_cropcap cap; | 1228 | struct v4l2_cropcap cap; |
1201 | int ret; | 1229 | int ret; |
1202 | 1230 | ||
1231 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); | ||
1232 | if (ret < 0) | ||
1233 | return ret; | ||
1234 | |||
1235 | dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); | ||
1236 | |||
1237 | if ((width == mf->width && height == mf->height) || !ceu_can_scale) | ||
1238 | goto update_cache; | ||
1239 | |||
1203 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1240 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1204 | 1241 | ||
1205 | ret = v4l2_subdev_call(sd, video, cropcap, &cap); | 1242 | ret = v4l2_subdev_call(sd, video, cropcap, &cap); |
@@ -1209,15 +1246,6 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1209 | max_width = min(cap.bounds.width, 2560); | 1246 | max_width = min(cap.bounds.width, 2560); |
1210 | max_height = min(cap.bounds.height, 1920); | 1247 | max_height = min(cap.bounds.height, 1920); |
1211 | 1248 | ||
1212 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); | ||
1213 | if (ret < 0) | ||
1214 | return ret; | ||
1215 | |||
1216 | dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); | ||
1217 | |||
1218 | if ((width == mf->width && height == mf->height) || !ceu_can_scale) | ||
1219 | return 0; | ||
1220 | |||
1221 | /* Camera set a format, but geometry is not precise, try to improve */ | 1249 | /* Camera set a format, but geometry is not precise, try to improve */ |
1222 | tmp_w = mf->width; | 1250 | tmp_w = mf->width; |
1223 | tmp_h = mf->height; | 1251 | tmp_h = mf->height; |
@@ -1239,26 +1267,37 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1239 | } | 1267 | } |
1240 | } | 1268 | } |
1241 | 1269 | ||
1270 | update_cache: | ||
1271 | /* Update cache */ | ||
1272 | ret = client_g_rect(sd, &cam->rect); | ||
1273 | if (ret < 0) | ||
1274 | return ret; | ||
1275 | |||
1276 | update_subrect(cam); | ||
1277 | |||
1242 | return 0; | 1278 | return 0; |
1243 | } | 1279 | } |
1244 | 1280 | ||
1245 | /** | 1281 | /** |
1246 | * @rect - camera cropped rectangle | 1282 | * @width - on output: user width, mapped back to input |
1247 | * @sub_rect - CEU cropped rectangle, mapped back to camera input area | 1283 | * @height - on output: user height, mapped back to input |
1248 | * @ceu_rect - on output calculated CEU crop rectangle | 1284 | * @mf - in- / output camera output window |
1249 | */ | 1285 | */ |
1250 | static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, | 1286 | static int client_scale(struct soc_camera_device *icd, |
1251 | struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, | 1287 | struct v4l2_mbus_framefmt *mf, |
1252 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) | 1288 | unsigned int *width, unsigned int *height, |
1289 | bool ceu_can_scale) | ||
1253 | { | 1290 | { |
1254 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1255 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1291 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1256 | struct device *dev = icd->dev.parent; | 1292 | struct device *dev = icd->dev.parent; |
1257 | struct v4l2_mbus_framefmt mf_tmp = *mf; | 1293 | struct v4l2_mbus_framefmt mf_tmp = *mf; |
1258 | unsigned int scale_h, scale_v; | 1294 | unsigned int scale_h, scale_v; |
1259 | int ret; | 1295 | int ret; |
1260 | 1296 | ||
1261 | /* 5. Apply iterative camera S_FMT for camera user window. */ | 1297 | /* |
1298 | * 5. Apply iterative camera S_FMT for camera user window (also updates | ||
1299 | * client crop cache and the imaginary sub-rectangle). | ||
1300 | */ | ||
1262 | ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); | 1301 | ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); |
1263 | if (ret < 0) | 1302 | if (ret < 0) |
1264 | return ret; | 1303 | return ret; |
@@ -1270,60 +1309,22 @@ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, | |||
1270 | 1309 | ||
1271 | /* unneeded - it is already in "mf_tmp" */ | 1310 | /* unneeded - it is already in "mf_tmp" */ |
1272 | 1311 | ||
1273 | /* 7. Calculate new camera scales. */ | 1312 | /* 7. Calculate new client scales. */ |
1274 | ret = get_camera_scales(sd, rect, &scale_h, &scale_v); | 1313 | scale_h = calc_generic_scale(cam->rect.width, mf_tmp.width); |
1275 | if (ret < 0) | 1314 | scale_v = calc_generic_scale(cam->rect.height, mf_tmp.height); |
1276 | return ret; | ||
1277 | |||
1278 | dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); | ||
1279 | 1315 | ||
1280 | cam->cam_width = mf_tmp.width; | ||
1281 | cam->cam_height = mf_tmp.height; | ||
1282 | mf->width = mf_tmp.width; | 1316 | mf->width = mf_tmp.width; |
1283 | mf->height = mf_tmp.height; | 1317 | mf->height = mf_tmp.height; |
1284 | mf->colorspace = mf_tmp.colorspace; | 1318 | mf->colorspace = mf_tmp.colorspace; |
1285 | 1319 | ||
1286 | /* | 1320 | /* |
1287 | * 8. Calculate new CEU crop - apply camera scales to previously | 1321 | * 8. Calculate new CEU crop - apply camera scales to previously |
1288 | * calculated "effective" crop. | 1322 | * updated "effective" crop. |
1289 | */ | 1323 | */ |
1290 | ceu_rect->left = scale_down(sub_rect->left, scale_h); | 1324 | *width = scale_down(cam->subrect.width, scale_h); |
1291 | ceu_rect->width = scale_down(sub_rect->width, scale_h); | 1325 | *height = scale_down(cam->subrect.height, scale_v); |
1292 | ceu_rect->top = scale_down(sub_rect->top, scale_v); | ||
1293 | ceu_rect->height = scale_down(sub_rect->height, scale_v); | ||
1294 | 1326 | ||
1295 | dev_geo(dev, "8: new CEU rect %ux%u@%u:%u\n", | 1327 | dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); |
1296 | ceu_rect->width, ceu_rect->height, | ||
1297 | ceu_rect->left, ceu_rect->top); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | /* Get combined scales */ | ||
1303 | static int get_scales(struct soc_camera_device *icd, | ||
1304 | unsigned int *scale_h, unsigned int *scale_v) | ||
1305 | { | ||
1306 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1307 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1308 | struct v4l2_crop cam_crop; | ||
1309 | unsigned int width_in, height_in; | ||
1310 | int ret; | ||
1311 | |||
1312 | cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1313 | |||
1314 | ret = client_g_rect(sd, &cam_crop.c); | ||
1315 | if (ret < 0) | ||
1316 | return ret; | ||
1317 | |||
1318 | ret = get_camera_scales(sd, &cam_crop.c, scale_h, scale_v); | ||
1319 | if (ret < 0) | ||
1320 | return ret; | ||
1321 | |||
1322 | width_in = scale_up(cam->ceu_rect.width, *scale_h); | ||
1323 | height_in = scale_up(cam->ceu_rect.height, *scale_v); | ||
1324 | |||
1325 | *scale_h = calc_generic_scale(width_in, icd->user_width); | ||
1326 | *scale_v = calc_generic_scale(height_in, icd->user_height); | ||
1327 | 1328 | ||
1328 | return 0; | 1329 | return 0; |
1329 | } | 1330 | } |
@@ -1342,115 +1343,165 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1342 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 1343 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
1343 | struct v4l2_crop cam_crop; | 1344 | struct v4l2_crop cam_crop; |
1344 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1345 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1345 | struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; | 1346 | struct v4l2_rect *cam_rect = &cam_crop.c; |
1346 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1347 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1347 | struct device *dev = icd->dev.parent; | 1348 | struct device *dev = icd->dev.parent; |
1348 | struct v4l2_mbus_framefmt mf; | 1349 | struct v4l2_mbus_framefmt mf; |
1349 | unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, | 1350 | unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v, |
1350 | out_width, out_height; | 1351 | out_width, out_height, scale_h, scale_v; |
1352 | int interm_width, interm_height; | ||
1351 | u32 capsr, cflcr; | 1353 | u32 capsr, cflcr; |
1352 | int ret; | 1354 | int ret; |
1353 | 1355 | ||
1354 | /* 1. Calculate current combined scales. */ | 1356 | dev_geo(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, |
1355 | ret = get_scales(icd, &scale_comb_h, &scale_comb_v); | 1357 | rect->left, rect->top); |
1356 | if (ret < 0) | ||
1357 | return ret; | ||
1358 | 1358 | ||
1359 | dev_geo(dev, "1: combined scales %u:%u\n", scale_comb_h, scale_comb_v); | 1359 | /* During camera cropping its output window can change too, stop CEU */ |
1360 | capsr = capture_save_reset(pcdev); | ||
1361 | dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); | ||
1360 | 1362 | ||
1361 | /* 2. Apply iterative camera S_CROP for new input window. */ | 1363 | /* 1. - 2. Apply iterative camera S_CROP for new input window. */ |
1362 | ret = client_s_crop(sd, a, &cam_crop); | 1364 | ret = client_s_crop(icd, a, &cam_crop); |
1363 | if (ret < 0) | 1365 | if (ret < 0) |
1364 | return ret; | 1366 | return ret; |
1365 | 1367 | ||
1366 | dev_geo(dev, "2: camera cropped to %ux%u@%u:%u\n", | 1368 | dev_geo(dev, "1-2: camera cropped to %ux%u@%u:%u\n", |
1367 | cam_rect->width, cam_rect->height, | 1369 | cam_rect->width, cam_rect->height, |
1368 | cam_rect->left, cam_rect->top); | 1370 | cam_rect->left, cam_rect->top); |
1369 | 1371 | ||
1370 | /* On success cam_crop contains current camera crop */ | 1372 | /* On success cam_crop contains current camera crop */ |
1371 | 1373 | ||
1372 | /* | 1374 | /* 3. Retrieve camera output window */ |
1373 | * 3. If old combined scales applied to new crop produce an impossible | 1375 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
1374 | * user window, adjust scales to produce nearest possible window. | 1376 | if (ret < 0) |
1375 | */ | 1377 | return ret; |
1376 | out_width = scale_down(rect->width, scale_comb_h); | ||
1377 | out_height = scale_down(rect->height, scale_comb_v); | ||
1378 | |||
1379 | if (out_width > 2560) | ||
1380 | out_width = 2560; | ||
1381 | else if (out_width < 2) | ||
1382 | out_width = 2; | ||
1383 | |||
1384 | if (out_height > 1920) | ||
1385 | out_height = 1920; | ||
1386 | else if (out_height < 4) | ||
1387 | out_height = 4; | ||
1388 | |||
1389 | dev_geo(dev, "3: Adjusted output %ux%u\n", out_width, out_height); | ||
1390 | |||
1391 | /* 4. Use G_CROP to retrieve actual input window: already in cam_crop */ | ||
1392 | |||
1393 | /* | ||
1394 | * 5. Using actual input window and calculated combined scales calculate | ||
1395 | * camera target output window. | ||
1396 | */ | ||
1397 | mf.width = scale_down(cam_rect->width, scale_comb_h); | ||
1398 | mf.height = scale_down(cam_rect->height, scale_comb_v); | ||
1399 | |||
1400 | dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height); | ||
1401 | |||
1402 | /* 6. - 9. */ | ||
1403 | mf.code = cam->code; | ||
1404 | mf.field = pcdev->field; | ||
1405 | |||
1406 | capsr = capture_save_reset(pcdev); | ||
1407 | dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); | ||
1408 | 1378 | ||
1409 | /* Make relative to camera rectangle */ | 1379 | if (mf.width > 2560 || mf.height > 1920) |
1410 | rect->left -= cam_rect->left; | 1380 | return -EINVAL; |
1411 | rect->top -= cam_rect->top; | ||
1412 | 1381 | ||
1413 | ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf, | 1382 | /* Cache camera output window */ |
1414 | pcdev->image_mode && | 1383 | cam->width = mf.width; |
1415 | V4L2_FIELD_NONE == pcdev->field); | 1384 | cam->height = mf.height; |
1416 | 1385 | ||
1417 | dev_geo(dev, "6-9: %d\n", ret); | 1386 | /* 4. Calculate camera scales */ |
1387 | scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); | ||
1388 | scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); | ||
1418 | 1389 | ||
1419 | /* 10. Use CEU cropping to crop to the new window. */ | 1390 | /* Calculate intermediate window */ |
1420 | sh_mobile_ceu_set_rect(icd, out_width, out_height); | 1391 | interm_width = scale_down(rect->width, scale_cam_h); |
1392 | interm_height = scale_down(rect->height, scale_cam_v); | ||
1421 | 1393 | ||
1422 | dev_geo(dev, "10: CEU cropped to %ux%u@%u:%u\n", | 1394 | if (pcdev->image_mode) { |
1423 | ceu_rect->width, ceu_rect->height, | 1395 | out_width = min(interm_width, icd->user_width); |
1424 | ceu_rect->left, ceu_rect->top); | 1396 | out_height = min(interm_height, icd->user_height); |
1397 | } else { | ||
1398 | out_width = interm_width; | ||
1399 | out_height = interm_height; | ||
1400 | } | ||
1425 | 1401 | ||
1426 | /* | 1402 | /* |
1427 | * 11. Calculate CEU scales from camera scales from results of (10) and | 1403 | * 5. Calculate CEU scales from camera scales from results of (5) and |
1428 | * user window from (3) | 1404 | * the user window |
1429 | */ | 1405 | */ |
1430 | scale_ceu_h = calc_scale(ceu_rect->width, &out_width); | 1406 | scale_ceu_h = calc_scale(interm_width, &out_width); |
1431 | scale_ceu_v = calc_scale(ceu_rect->height, &out_height); | 1407 | scale_ceu_v = calc_scale(interm_height, &out_height); |
1432 | 1408 | ||
1433 | dev_geo(dev, "11: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); | 1409 | /* Calculate camera scales */ |
1410 | scale_h = calc_generic_scale(cam_rect->width, out_width); | ||
1411 | scale_v = calc_generic_scale(cam_rect->height, out_height); | ||
1434 | 1412 | ||
1435 | /* 12. Apply CEU scales. */ | 1413 | dev_geo(dev, "5: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); |
1414 | |||
1415 | /* Apply CEU scales. */ | ||
1436 | cflcr = scale_ceu_h | (scale_ceu_v << 16); | 1416 | cflcr = scale_ceu_h | (scale_ceu_v << 16); |
1437 | if (cflcr != pcdev->cflcr) { | 1417 | if (cflcr != pcdev->cflcr) { |
1438 | pcdev->cflcr = cflcr; | 1418 | pcdev->cflcr = cflcr; |
1439 | ceu_write(pcdev, CFLCR, cflcr); | 1419 | ceu_write(pcdev, CFLCR, cflcr); |
1440 | } | 1420 | } |
1441 | 1421 | ||
1422 | icd->user_width = out_width; | ||
1423 | icd->user_height = out_height; | ||
1424 | cam->ceu_left = scale_down(rect->left - cam_rect->left, scale_h) & ~1; | ||
1425 | cam->ceu_top = scale_down(rect->top - cam_rect->top, scale_v) & ~1; | ||
1426 | |||
1427 | /* 6. Use CEU cropping to crop to the new window. */ | ||
1428 | sh_mobile_ceu_set_rect(icd); | ||
1429 | |||
1430 | cam->subrect = *rect; | ||
1431 | |||
1432 | dev_geo(dev, "6: CEU cropped to %ux%u@%u:%u\n", | ||
1433 | icd->user_width, icd->user_height, | ||
1434 | cam->ceu_left, cam->ceu_top); | ||
1435 | |||
1442 | /* Restore capture */ | 1436 | /* Restore capture */ |
1443 | if (pcdev->active) | 1437 | if (pcdev->active) |
1444 | capsr |= 1; | 1438 | capsr |= 1; |
1445 | capture_restore(pcdev, capsr); | 1439 | capture_restore(pcdev, capsr); |
1446 | 1440 | ||
1447 | icd->user_width = out_width; | ||
1448 | icd->user_height = out_height; | ||
1449 | |||
1450 | /* Even if only camera cropping succeeded */ | 1441 | /* Even if only camera cropping succeeded */ |
1451 | return ret; | 1442 | return ret; |
1452 | } | 1443 | } |
1453 | 1444 | ||
1445 | static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, | ||
1446 | struct v4l2_crop *a) | ||
1447 | { | ||
1448 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1449 | |||
1450 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1451 | a->c = cam->subrect; | ||
1452 | |||
1453 | return 0; | ||
1454 | } | ||
1455 | |||
1456 | /* | ||
1457 | * Calculate real client output window by applying new scales to the current | ||
1458 | * client crop. New scales are calculated from the requested output format and | ||
1459 | * CEU crop, mapped backed onto the client input (subrect). | ||
1460 | */ | ||
1461 | static void calculate_client_output(struct soc_camera_device *icd, | ||
1462 | struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf) | ||
1463 | { | ||
1464 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | ||
1465 | struct device *dev = icd->dev.parent; | ||
1466 | struct v4l2_rect *cam_subrect = &cam->subrect; | ||
1467 | unsigned int scale_v, scale_h; | ||
1468 | |||
1469 | if (cam_subrect->width == cam->rect.width && | ||
1470 | cam_subrect->height == cam->rect.height) { | ||
1471 | /* No sub-cropping */ | ||
1472 | mf->width = pix->width; | ||
1473 | mf->height = pix->height; | ||
1474 | return; | ||
1475 | } | ||
1476 | |||
1477 | /* 1.-2. Current camera scales and subwin - cached. */ | ||
1478 | |||
1479 | dev_geo(dev, "2: subwin %ux%u@%u:%u\n", | ||
1480 | cam_subrect->width, cam_subrect->height, | ||
1481 | cam_subrect->left, cam_subrect->top); | ||
1482 | |||
1483 | /* | ||
1484 | * 3. Calculate new combined scales from input sub-window to requested | ||
1485 | * user window. | ||
1486 | */ | ||
1487 | |||
1488 | /* | ||
1489 | * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF | ||
1490 | * (128x96) or larger than VGA | ||
1491 | */ | ||
1492 | scale_h = calc_generic_scale(cam_subrect->width, pix->width); | ||
1493 | scale_v = calc_generic_scale(cam_subrect->height, pix->height); | ||
1494 | |||
1495 | dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); | ||
1496 | |||
1497 | /* | ||
1498 | * 4. Calculate client output window by applying combined scales to real | ||
1499 | * input window. | ||
1500 | */ | ||
1501 | mf->width = scale_down(cam->rect.width, scale_h); | ||
1502 | mf->height = scale_down(cam->rect.height, scale_v); | ||
1503 | } | ||
1504 | |||
1454 | /* Similar to set_crop multistage iterative algorithm */ | 1505 | /* Similar to set_crop multistage iterative algorithm */ |
1455 | static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | 1506 | static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, |
1456 | struct v4l2_format *f) | 1507 | struct v4l2_format *f) |
@@ -1460,18 +1511,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1460 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1511 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1461 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1512 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1462 | struct v4l2_mbus_framefmt mf; | 1513 | struct v4l2_mbus_framefmt mf; |
1463 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1464 | struct device *dev = icd->dev.parent; | 1514 | struct device *dev = icd->dev.parent; |
1465 | __u32 pixfmt = pix->pixelformat; | 1515 | __u32 pixfmt = pix->pixelformat; |
1466 | const struct soc_camera_format_xlate *xlate; | 1516 | const struct soc_camera_format_xlate *xlate; |
1467 | struct v4l2_crop cam_crop; | 1517 | unsigned int ceu_sub_width, ceu_sub_height; |
1468 | struct v4l2_rect *cam_rect = &cam_crop.c, cam_subrect, ceu_rect; | ||
1469 | unsigned int scale_cam_h, scale_cam_v; | ||
1470 | u16 scale_v, scale_h; | 1518 | u16 scale_v, scale_h; |
1471 | int ret; | 1519 | int ret; |
1472 | bool image_mode; | 1520 | bool image_mode; |
1473 | enum v4l2_field field; | 1521 | enum v4l2_field field; |
1474 | 1522 | ||
1523 | dev_geo(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height); | ||
1524 | |||
1475 | switch (pix->field) { | 1525 | switch (pix->field) { |
1476 | default: | 1526 | default: |
1477 | pix->field = V4L2_FIELD_NONE; | 1527 | pix->field = V4L2_FIELD_NONE; |
@@ -1492,46 +1542,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1492 | return -EINVAL; | 1542 | return -EINVAL; |
1493 | } | 1543 | } |
1494 | 1544 | ||
1495 | /* 1. Calculate current camera scales. */ | 1545 | /* 1.-4. Calculate client output geometry */ |
1496 | cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1546 | calculate_client_output(icd, &f->fmt.pix, &mf); |
1497 | |||
1498 | ret = client_g_rect(sd, cam_rect); | ||
1499 | if (ret < 0) | ||
1500 | return ret; | ||
1501 | |||
1502 | ret = get_camera_scales(sd, cam_rect, &scale_cam_h, &scale_cam_v); | ||
1503 | if (ret < 0) | ||
1504 | return ret; | ||
1505 | |||
1506 | dev_geo(dev, "1: camera scales %u:%u\n", scale_cam_h, scale_cam_v); | ||
1507 | |||
1508 | /* | ||
1509 | * 2. Calculate "effective" input crop (sensor subwindow) - CEU crop | ||
1510 | * scaled back at current camera scales onto input window. | ||
1511 | */ | ||
1512 | ret = get_camera_subwin(icd, &cam_subrect, scale_cam_h, scale_cam_v); | ||
1513 | if (ret < 0) | ||
1514 | return ret; | ||
1515 | |||
1516 | dev_geo(dev, "2: subwin %ux%u@%u:%u\n", | ||
1517 | cam_subrect.width, cam_subrect.height, | ||
1518 | cam_subrect.left, cam_subrect.top); | ||
1519 | |||
1520 | /* | ||
1521 | * 3. Calculate new combined scales from "effective" input window to | ||
1522 | * requested user window. | ||
1523 | */ | ||
1524 | scale_h = calc_generic_scale(cam_subrect.width, pix->width); | ||
1525 | scale_v = calc_generic_scale(cam_subrect.height, pix->height); | ||
1526 | |||
1527 | dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); | ||
1528 | |||
1529 | /* | ||
1530 | * 4. Calculate camera output window by applying combined scales to real | ||
1531 | * input window. | ||
1532 | */ | ||
1533 | mf.width = scale_down(cam_rect->width, scale_h); | ||
1534 | mf.height = scale_down(cam_rect->height, scale_v); | ||
1535 | mf.field = pix->field; | 1547 | mf.field = pix->field; |
1536 | mf.colorspace = pix->colorspace; | 1548 | mf.colorspace = pix->colorspace; |
1537 | mf.code = xlate->code; | 1549 | mf.code = xlate->code; |
@@ -1547,17 +1559,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1547 | image_mode = false; | 1559 | image_mode = false; |
1548 | } | 1560 | } |
1549 | 1561 | ||
1550 | dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height); | 1562 | dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); |
1551 | 1563 | ||
1552 | /* 5. - 9. */ | 1564 | /* 5. - 9. */ |
1553 | ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf, | 1565 | ret = client_scale(icd, &mf, &ceu_sub_width, &ceu_sub_height, |
1554 | image_mode && V4L2_FIELD_NONE == field); | 1566 | image_mode && V4L2_FIELD_NONE == field); |
1555 | 1567 | ||
1556 | dev_geo(dev, "5-9: client scale %d\n", ret); | 1568 | dev_geo(dev, "5-9: client scale return %d\n", ret); |
1557 | 1569 | ||
1558 | /* Done with the camera. Now see if we can improve the result */ | 1570 | /* Done with the camera. Now see if we can improve the result */ |
1559 | 1571 | ||
1560 | dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", | 1572 | dev_geo(dev, "Camera %d fmt %ux%u, requested %ux%u\n", |
1561 | ret, mf.width, mf.height, pix->width, pix->height); | 1573 | ret, mf.width, mf.height, pix->width, pix->height); |
1562 | if (ret < 0) | 1574 | if (ret < 0) |
1563 | return ret; | 1575 | return ret; |
@@ -1565,40 +1577,44 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1565 | if (mf.code != xlate->code) | 1577 | if (mf.code != xlate->code) |
1566 | return -EINVAL; | 1578 | return -EINVAL; |
1567 | 1579 | ||
1580 | /* 9. Prepare CEU crop */ | ||
1581 | cam->width = mf.width; | ||
1582 | cam->height = mf.height; | ||
1583 | |||
1568 | /* 10. Use CEU scaling to scale to the requested user window. */ | 1584 | /* 10. Use CEU scaling to scale to the requested user window. */ |
1569 | 1585 | ||
1570 | /* We cannot scale up */ | 1586 | /* We cannot scale up */ |
1571 | if (pix->width > mf.width) | 1587 | if (pix->width > ceu_sub_width) |
1572 | pix->width = mf.width; | 1588 | ceu_sub_width = pix->width; |
1573 | if (pix->width > ceu_rect.width) | ||
1574 | pix->width = ceu_rect.width; | ||
1575 | 1589 | ||
1576 | if (pix->height > mf.height) | 1590 | if (pix->height > ceu_sub_height) |
1577 | pix->height = mf.height; | 1591 | ceu_sub_height = pix->height; |
1578 | if (pix->height > ceu_rect.height) | ||
1579 | pix->height = ceu_rect.height; | ||
1580 | 1592 | ||
1581 | pix->colorspace = mf.colorspace; | 1593 | pix->colorspace = mf.colorspace; |
1582 | 1594 | ||
1583 | if (image_mode) { | 1595 | if (image_mode) { |
1584 | /* Scale pix->{width x height} down to width x height */ | 1596 | /* Scale pix->{width x height} down to width x height */ |
1585 | scale_h = calc_scale(ceu_rect.width, &pix->width); | 1597 | scale_h = calc_scale(ceu_sub_width, &pix->width); |
1586 | scale_v = calc_scale(ceu_rect.height, &pix->height); | 1598 | scale_v = calc_scale(ceu_sub_height, &pix->height); |
1587 | |||
1588 | pcdev->cflcr = scale_h | (scale_v << 16); | ||
1589 | } else { | 1599 | } else { |
1590 | pix->width = ceu_rect.width; | 1600 | pix->width = ceu_sub_width; |
1591 | pix->height = ceu_rect.height; | 1601 | pix->height = ceu_sub_height; |
1592 | scale_h = scale_v = 0; | 1602 | scale_h = 0; |
1593 | pcdev->cflcr = 0; | 1603 | scale_v = 0; |
1594 | } | 1604 | } |
1595 | 1605 | ||
1606 | pcdev->cflcr = scale_h | (scale_v << 16); | ||
1607 | |||
1608 | /* | ||
1609 | * We have calculated CFLCR, the actual configuration will be performed | ||
1610 | * in sh_mobile_ceu_set_bus_param() | ||
1611 | */ | ||
1612 | |||
1596 | dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", | 1613 | dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", |
1597 | ceu_rect.width, scale_h, pix->width, | 1614 | ceu_sub_width, scale_h, pix->width, |
1598 | ceu_rect.height, scale_v, pix->height); | 1615 | ceu_sub_height, scale_v, pix->height); |
1599 | 1616 | ||
1600 | cam->code = xlate->code; | 1617 | cam->code = xlate->code; |
1601 | cam->ceu_rect = ceu_rect; | ||
1602 | icd->current_fmt = xlate; | 1618 | icd->current_fmt = xlate; |
1603 | 1619 | ||
1604 | pcdev->field = field; | 1620 | pcdev->field = field; |
@@ -1820,6 +1836,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1820 | .remove = sh_mobile_ceu_remove_device, | 1836 | .remove = sh_mobile_ceu_remove_device, |
1821 | .get_formats = sh_mobile_ceu_get_formats, | 1837 | .get_formats = sh_mobile_ceu_get_formats, |
1822 | .put_formats = sh_mobile_ceu_put_formats, | 1838 | .put_formats = sh_mobile_ceu_put_formats, |
1839 | .get_crop = sh_mobile_ceu_get_crop, | ||
1823 | .set_crop = sh_mobile_ceu_set_crop, | 1840 | .set_crop = sh_mobile_ceu_set_crop, |
1824 | .set_fmt = sh_mobile_ceu_set_fmt, | 1841 | .set_fmt = sh_mobile_ceu_set_fmt, |
1825 | .try_fmt = sh_mobile_ceu_try_fmt, | 1842 | .try_fmt = sh_mobile_ceu_try_fmt, |
diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c new file mode 100644 index 000000000000..f5b892a2a8ee --- /dev/null +++ b/drivers/media/video/sh_vou.c | |||
@@ -0,0 +1,1476 @@ | |||
1 | /* | ||
2 | * SuperH Video Output Unit (VOU) driver | ||
3 | * | ||
4 | * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/dma-mapping.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/version.h> | ||
22 | #include <linux/videodev2.h> | ||
23 | |||
24 | #include <media/sh_vou.h> | ||
25 | #include <media/v4l2-common.h> | ||
26 | #include <media/v4l2-device.h> | ||
27 | #include <media/v4l2-ioctl.h> | ||
28 | #include <media/v4l2-mediabus.h> | ||
29 | #include <media/videobuf-dma-contig.h> | ||
30 | |||
31 | /* Mirror addresses are not available for all registers */ | ||
32 | #define VOUER 0 | ||
33 | #define VOUCR 4 | ||
34 | #define VOUSTR 8 | ||
35 | #define VOUVCR 0xc | ||
36 | #define VOUISR 0x10 | ||
37 | #define VOUBCR 0x14 | ||
38 | #define VOUDPR 0x18 | ||
39 | #define VOUDSR 0x1c | ||
40 | #define VOUVPR 0x20 | ||
41 | #define VOUIR 0x24 | ||
42 | #define VOUSRR 0x28 | ||
43 | #define VOUMSR 0x2c | ||
44 | #define VOUHIR 0x30 | ||
45 | #define VOUDFR 0x34 | ||
46 | #define VOUAD1R 0x38 | ||
47 | #define VOUAD2R 0x3c | ||
48 | #define VOUAIR 0x40 | ||
49 | #define VOUSWR 0x44 | ||
50 | #define VOURCR 0x48 | ||
51 | #define VOURPR 0x50 | ||
52 | |||
53 | enum sh_vou_status { | ||
54 | SH_VOU_IDLE, | ||
55 | SH_VOU_INITIALISING, | ||
56 | SH_VOU_RUNNING, | ||
57 | }; | ||
58 | |||
59 | #define VOU_MAX_IMAGE_WIDTH 720 | ||
60 | #define VOU_MAX_IMAGE_HEIGHT 480 | ||
61 | |||
62 | struct sh_vou_device { | ||
63 | struct v4l2_device v4l2_dev; | ||
64 | struct video_device *vdev; | ||
65 | atomic_t use_count; | ||
66 | struct sh_vou_pdata *pdata; | ||
67 | spinlock_t lock; | ||
68 | void __iomem *base; | ||
69 | /* State information */ | ||
70 | struct v4l2_pix_format pix; | ||
71 | struct v4l2_rect rect; | ||
72 | struct list_head queue; | ||
73 | v4l2_std_id std; | ||
74 | int pix_idx; | ||
75 | struct videobuf_buffer *active; | ||
76 | enum sh_vou_status status; | ||
77 | }; | ||
78 | |||
79 | struct sh_vou_file { | ||
80 | struct videobuf_queue vbq; | ||
81 | }; | ||
82 | |||
83 | /* Register access routines for sides A, B and mirror addresses */ | ||
84 | static void sh_vou_reg_a_write(struct sh_vou_device *vou_dev, unsigned int reg, | ||
85 | u32 value) | ||
86 | { | ||
87 | __raw_writel(value, vou_dev->base + reg); | ||
88 | } | ||
89 | |||
90 | static void sh_vou_reg_ab_write(struct sh_vou_device *vou_dev, unsigned int reg, | ||
91 | u32 value) | ||
92 | { | ||
93 | __raw_writel(value, vou_dev->base + reg); | ||
94 | __raw_writel(value, vou_dev->base + reg + 0x1000); | ||
95 | } | ||
96 | |||
97 | static void sh_vou_reg_m_write(struct sh_vou_device *vou_dev, unsigned int reg, | ||
98 | u32 value) | ||
99 | { | ||
100 | __raw_writel(value, vou_dev->base + reg + 0x2000); | ||
101 | } | ||
102 | |||
103 | static u32 sh_vou_reg_a_read(struct sh_vou_device *vou_dev, unsigned int reg) | ||
104 | { | ||
105 | return __raw_readl(vou_dev->base + reg); | ||
106 | } | ||
107 | |||
108 | static void sh_vou_reg_a_set(struct sh_vou_device *vou_dev, unsigned int reg, | ||
109 | u32 value, u32 mask) | ||
110 | { | ||
111 | u32 old = __raw_readl(vou_dev->base + reg); | ||
112 | |||
113 | value = (value & mask) | (old & ~mask); | ||
114 | __raw_writel(value, vou_dev->base + reg); | ||
115 | } | ||
116 | |||
117 | static void sh_vou_reg_b_set(struct sh_vou_device *vou_dev, unsigned int reg, | ||
118 | u32 value, u32 mask) | ||
119 | { | ||
120 | sh_vou_reg_a_set(vou_dev, reg + 0x1000, value, mask); | ||
121 | } | ||
122 | |||
123 | static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg, | ||
124 | u32 value, u32 mask) | ||
125 | { | ||
126 | sh_vou_reg_a_set(vou_dev, reg, value, mask); | ||
127 | sh_vou_reg_b_set(vou_dev, reg, value, mask); | ||
128 | } | ||
129 | |||
130 | struct sh_vou_fmt { | ||
131 | u32 pfmt; | ||
132 | char *desc; | ||
133 | unsigned char bpp; | ||
134 | unsigned char rgb; | ||
135 | unsigned char yf; | ||
136 | unsigned char pkf; | ||
137 | }; | ||
138 | |||
139 | /* Further pixel formats can be added */ | ||
140 | static struct sh_vou_fmt vou_fmt[] = { | ||
141 | { | ||
142 | .pfmt = V4L2_PIX_FMT_NV12, | ||
143 | .bpp = 12, | ||
144 | .desc = "YVU420 planar", | ||
145 | .yf = 0, | ||
146 | .rgb = 0, | ||
147 | }, | ||
148 | { | ||
149 | .pfmt = V4L2_PIX_FMT_NV16, | ||
150 | .bpp = 16, | ||
151 | .desc = "YVYU planar", | ||
152 | .yf = 1, | ||
153 | .rgb = 0, | ||
154 | }, | ||
155 | { | ||
156 | .pfmt = V4L2_PIX_FMT_RGB24, | ||
157 | .bpp = 24, | ||
158 | .desc = "RGB24", | ||
159 | .pkf = 2, | ||
160 | .rgb = 1, | ||
161 | }, | ||
162 | { | ||
163 | .pfmt = V4L2_PIX_FMT_RGB565, | ||
164 | .bpp = 16, | ||
165 | .desc = "RGB565", | ||
166 | .pkf = 3, | ||
167 | .rgb = 1, | ||
168 | }, | ||
169 | { | ||
170 | .pfmt = V4L2_PIX_FMT_RGB565X, | ||
171 | .bpp = 16, | ||
172 | .desc = "RGB565 byteswapped", | ||
173 | .pkf = 3, | ||
174 | .rgb = 1, | ||
175 | }, | ||
176 | }; | ||
177 | |||
178 | static void sh_vou_schedule_next(struct sh_vou_device *vou_dev, | ||
179 | struct videobuf_buffer *vb) | ||
180 | { | ||
181 | dma_addr_t addr1, addr2; | ||
182 | |||
183 | addr1 = videobuf_to_dma_contig(vb); | ||
184 | switch (vou_dev->pix.pixelformat) { | ||
185 | case V4L2_PIX_FMT_NV12: | ||
186 | case V4L2_PIX_FMT_NV16: | ||
187 | addr2 = addr1 + vou_dev->pix.width * vou_dev->pix.height; | ||
188 | break; | ||
189 | default: | ||
190 | addr2 = 0; | ||
191 | } | ||
192 | |||
193 | sh_vou_reg_m_write(vou_dev, VOUAD1R, addr1); | ||
194 | sh_vou_reg_m_write(vou_dev, VOUAD2R, addr2); | ||
195 | } | ||
196 | |||
197 | static void sh_vou_stream_start(struct sh_vou_device *vou_dev, | ||
198 | struct videobuf_buffer *vb) | ||
199 | { | ||
200 | unsigned int row_coeff; | ||
201 | #ifdef __LITTLE_ENDIAN | ||
202 | u32 dataswap = 7; | ||
203 | #else | ||
204 | u32 dataswap = 0; | ||
205 | #endif | ||
206 | |||
207 | switch (vou_dev->pix.pixelformat) { | ||
208 | case V4L2_PIX_FMT_NV12: | ||
209 | case V4L2_PIX_FMT_NV16: | ||
210 | row_coeff = 1; | ||
211 | break; | ||
212 | case V4L2_PIX_FMT_RGB565: | ||
213 | dataswap ^= 1; | ||
214 | case V4L2_PIX_FMT_RGB565X: | ||
215 | row_coeff = 2; | ||
216 | break; | ||
217 | case V4L2_PIX_FMT_RGB24: | ||
218 | row_coeff = 3; | ||
219 | break; | ||
220 | } | ||
221 | |||
222 | sh_vou_reg_a_write(vou_dev, VOUSWR, dataswap); | ||
223 | sh_vou_reg_ab_write(vou_dev, VOUAIR, vou_dev->pix.width * row_coeff); | ||
224 | sh_vou_schedule_next(vou_dev, vb); | ||
225 | } | ||
226 | |||
227 | static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
228 | { | ||
229 | BUG_ON(in_interrupt()); | ||
230 | |||
231 | /* Wait until this buffer is no longer in STATE_QUEUED or STATE_ACTIVE */ | ||
232 | videobuf_waiton(vb, 0, 0); | ||
233 | videobuf_dma_contig_free(vq, vb); | ||
234 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
235 | } | ||
236 | |||
237 | /* Locking: caller holds vq->vb_lock mutex */ | ||
238 | static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, | ||
239 | unsigned int *size) | ||
240 | { | ||
241 | struct video_device *vdev = vq->priv_data; | ||
242 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
243 | |||
244 | *size = vou_fmt[vou_dev->pix_idx].bpp * vou_dev->pix.width * | ||
245 | vou_dev->pix.height / 8; | ||
246 | |||
247 | if (*count < 2) | ||
248 | *count = 2; | ||
249 | |||
250 | /* Taking into account maximum frame size, *count will stay >= 2 */ | ||
251 | if (PAGE_ALIGN(*size) * *count > 4 * 1024 * 1024) | ||
252 | *count = 4 * 1024 * 1024 / PAGE_ALIGN(*size); | ||
253 | |||
254 | dev_dbg(vq->dev, "%s(): count=%d, size=%d\n", __func__, *count, *size); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | /* Locking: caller holds vq->vb_lock mutex */ | ||
260 | static int sh_vou_buf_prepare(struct videobuf_queue *vq, | ||
261 | struct videobuf_buffer *vb, | ||
262 | enum v4l2_field field) | ||
263 | { | ||
264 | struct video_device *vdev = vq->priv_data; | ||
265 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
266 | struct v4l2_pix_format *pix = &vou_dev->pix; | ||
267 | int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; | ||
268 | int ret; | ||
269 | |||
270 | dev_dbg(vq->dev, "%s()\n", __func__); | ||
271 | |||
272 | if (vb->width != pix->width || | ||
273 | vb->height != pix->height || | ||
274 | vb->field != pix->field) { | ||
275 | vb->width = pix->width; | ||
276 | vb->height = pix->height; | ||
277 | vb->field = field; | ||
278 | if (vb->state != VIDEOBUF_NEEDS_INIT) | ||
279 | free_buffer(vq, vb); | ||
280 | } | ||
281 | |||
282 | vb->size = vb->height * bytes_per_line; | ||
283 | if (vb->baddr && vb->bsize < vb->size) { | ||
284 | /* User buffer too small */ | ||
285 | dev_warn(vq->dev, "User buffer too small: [%u] @ %lx\n", | ||
286 | vb->bsize, vb->baddr); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
291 | ret = videobuf_iolock(vq, vb, NULL); | ||
292 | if (ret < 0) { | ||
293 | dev_warn(vq->dev, "IOLOCK buf-type %d: %d\n", | ||
294 | vb->memory, ret); | ||
295 | return ret; | ||
296 | } | ||
297 | vb->state = VIDEOBUF_PREPARED; | ||
298 | } | ||
299 | |||
300 | dev_dbg(vq->dev, | ||
301 | "%s(): fmt #%d, %u bytes per line, phys 0x%x, type %d, state %d\n", | ||
302 | __func__, vou_dev->pix_idx, bytes_per_line, | ||
303 | videobuf_to_dma_contig(vb), vb->memory, vb->state); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | /* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ | ||
309 | static void sh_vou_buf_queue(struct videobuf_queue *vq, | ||
310 | struct videobuf_buffer *vb) | ||
311 | { | ||
312 | struct video_device *vdev = vq->priv_data; | ||
313 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
314 | |||
315 | dev_dbg(vq->dev, "%s()\n", __func__); | ||
316 | |||
317 | vb->state = VIDEOBUF_QUEUED; | ||
318 | list_add_tail(&vb->queue, &vou_dev->queue); | ||
319 | |||
320 | if (vou_dev->status == SH_VOU_RUNNING) { | ||
321 | return; | ||
322 | } else if (!vou_dev->active) { | ||
323 | vou_dev->active = vb; | ||
324 | /* Start from side A: we use mirror addresses, so, set B */ | ||
325 | sh_vou_reg_a_write(vou_dev, VOURPR, 1); | ||
326 | dev_dbg(vq->dev, "%s: first buffer status 0x%x\n", __func__, | ||
327 | sh_vou_reg_a_read(vou_dev, VOUSTR)); | ||
328 | sh_vou_schedule_next(vou_dev, vb); | ||
329 | /* Only activate VOU after the second buffer */ | ||
330 | } else if (vou_dev->active->queue.next == &vb->queue) { | ||
331 | /* Second buffer - initialise register side B */ | ||
332 | sh_vou_reg_a_write(vou_dev, VOURPR, 0); | ||
333 | sh_vou_stream_start(vou_dev, vb); | ||
334 | |||
335 | /* Register side switching with frame VSYNC */ | ||
336 | sh_vou_reg_a_write(vou_dev, VOURCR, 5); | ||
337 | dev_dbg(vq->dev, "%s: second buffer status 0x%x\n", __func__, | ||
338 | sh_vou_reg_a_read(vou_dev, VOUSTR)); | ||
339 | |||
340 | /* Enable End-of-Frame (VSYNC) interrupts */ | ||
341 | sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004); | ||
342 | /* Two buffers on the queue - activate the hardware */ | ||
343 | |||
344 | vou_dev->status = SH_VOU_RUNNING; | ||
345 | sh_vou_reg_a_write(vou_dev, VOUER, 0x107); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static void sh_vou_buf_release(struct videobuf_queue *vq, | ||
350 | struct videobuf_buffer *vb) | ||
351 | { | ||
352 | struct video_device *vdev = vq->priv_data; | ||
353 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
354 | unsigned long flags; | ||
355 | |||
356 | dev_dbg(vq->dev, "%s()\n", __func__); | ||
357 | |||
358 | spin_lock_irqsave(&vou_dev->lock, flags); | ||
359 | |||
360 | if (vou_dev->active == vb) { | ||
361 | /* disable output */ | ||
362 | sh_vou_reg_a_set(vou_dev, VOUER, 0, 1); | ||
363 | /* ...but the current frame will complete */ | ||
364 | sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000); | ||
365 | vou_dev->active = NULL; | ||
366 | } | ||
367 | |||
368 | if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED)) { | ||
369 | vb->state = VIDEOBUF_ERROR; | ||
370 | list_del(&vb->queue); | ||
371 | } | ||
372 | |||
373 | spin_unlock_irqrestore(&vou_dev->lock, flags); | ||
374 | |||
375 | free_buffer(vq, vb); | ||
376 | } | ||
377 | |||
378 | static struct videobuf_queue_ops sh_vou_video_qops = { | ||
379 | .buf_setup = sh_vou_buf_setup, | ||
380 | .buf_prepare = sh_vou_buf_prepare, | ||
381 | .buf_queue = sh_vou_buf_queue, | ||
382 | .buf_release = sh_vou_buf_release, | ||
383 | }; | ||
384 | |||
385 | /* Video IOCTLs */ | ||
386 | static int sh_vou_querycap(struct file *file, void *priv, | ||
387 | struct v4l2_capability *cap) | ||
388 | { | ||
389 | struct sh_vou_file *vou_file = priv; | ||
390 | |||
391 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
392 | |||
393 | strlcpy(cap->card, "SuperH VOU", sizeof(cap->card)); | ||
394 | cap->version = KERNEL_VERSION(0, 1, 0); | ||
395 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* Enumerate formats, that the device can accept from the user */ | ||
400 | static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, | ||
401 | struct v4l2_fmtdesc *fmt) | ||
402 | { | ||
403 | struct sh_vou_file *vou_file = priv; | ||
404 | |||
405 | if (fmt->index >= ARRAY_SIZE(vou_fmt)) | ||
406 | return -EINVAL; | ||
407 | |||
408 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
409 | |||
410 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
411 | strlcpy(fmt->description, vou_fmt[fmt->index].desc, | ||
412 | sizeof(fmt->description)); | ||
413 | fmt->pixelformat = vou_fmt[fmt->index].pfmt; | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int sh_vou_g_fmt_vid_out(struct file *file, void *priv, | ||
419 | struct v4l2_format *fmt) | ||
420 | { | ||
421 | struct video_device *vdev = video_devdata(file); | ||
422 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
423 | |||
424 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | ||
425 | |||
426 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
427 | fmt->fmt.pix = vou_dev->pix; | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static const unsigned char vou_scale_h_num[] = {1, 9, 2, 9, 4}; | ||
433 | static const unsigned char vou_scale_h_den[] = {1, 8, 1, 4, 1}; | ||
434 | static const unsigned char vou_scale_h_fld[] = {0, 2, 1, 3}; | ||
435 | static const unsigned char vou_scale_v_num[] = {1, 2, 4}; | ||
436 | static const unsigned char vou_scale_v_den[] = {1, 1, 1}; | ||
437 | static const unsigned char vou_scale_v_fld[] = {0, 1}; | ||
438 | |||
439 | static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev, | ||
440 | int pix_idx, int w_idx, int h_idx) | ||
441 | { | ||
442 | struct sh_vou_fmt *fmt = vou_fmt + pix_idx; | ||
443 | unsigned int black_left, black_top, width_max, height_max, | ||
444 | frame_in_height, frame_out_height, frame_out_top; | ||
445 | struct v4l2_rect *rect = &vou_dev->rect; | ||
446 | struct v4l2_pix_format *pix = &vou_dev->pix; | ||
447 | u32 vouvcr = 0, dsr_h, dsr_v; | ||
448 | |||
449 | if (vou_dev->std & V4L2_STD_525_60) { | ||
450 | width_max = 858; | ||
451 | height_max = 262; | ||
452 | } else { | ||
453 | width_max = 864; | ||
454 | height_max = 312; | ||
455 | } | ||
456 | |||
457 | frame_in_height = pix->height / 2; | ||
458 | frame_out_height = rect->height / 2; | ||
459 | frame_out_top = rect->top / 2; | ||
460 | |||
461 | /* | ||
462 | * Cropping scheme: max useful image is 720x480, and the total video | ||
463 | * area is 858x525 (NTSC) or 864x625 (PAL). AK8813 / 8814 starts | ||
464 | * sampling data beginning with fixed 276th (NTSC) / 288th (PAL) clock, | ||
465 | * of which the first 33 / 25 clocks HSYNC must be held active. This | ||
466 | * has to be configured in CR[HW]. 1 pixel equals 2 clock periods. | ||
467 | * This gives CR[HW] = 16 / 12, VPR[HVP] = 138 / 144, which gives | ||
468 | * exactly 858 - 138 = 864 - 144 = 720! We call the out-of-display area, | ||
469 | * beyond DSR, specified on the left and top by the VPR register "black | ||
470 | * pixels" and out-of-image area (DPR) "background pixels." We fix VPR | ||
471 | * at 138 / 144 : 20, because that's the HSYNC timing, that our first | ||
472 | * client requires, and that's exactly what leaves us 720 pixels for the | ||
473 | * image; we leave VPR[VVP] at default 20 for now, because the client | ||
474 | * doesn't seem to have any special requirements for it. Otherwise we | ||
475 | * could also set it to max - 240 = 22 / 72. Thus VPR depends only on | ||
476 | * the selected standard, and DPR and DSR are selected according to | ||
477 | * cropping. Q: how does the client detect the first valid line? Does | ||
478 | * HSYNC stay inactive during invalid (black) lines? | ||
479 | */ | ||
480 | black_left = width_max - VOU_MAX_IMAGE_WIDTH; | ||
481 | black_top = 20; | ||
482 | |||
483 | dsr_h = rect->width + rect->left; | ||
484 | dsr_v = frame_out_height + frame_out_top; | ||
485 | |||
486 | dev_dbg(vou_dev->v4l2_dev.dev, | ||
487 | "image %ux%u, black %u:%u, offset %u:%u, display %ux%u\n", | ||
488 | pix->width, frame_in_height, black_left, black_top, | ||
489 | rect->left, frame_out_top, dsr_h, dsr_v); | ||
490 | |||
491 | /* VOUISR height - half of a frame height in frame mode */ | ||
492 | sh_vou_reg_ab_write(vou_dev, VOUISR, (pix->width << 16) | frame_in_height); | ||
493 | sh_vou_reg_ab_write(vou_dev, VOUVPR, (black_left << 16) | black_top); | ||
494 | sh_vou_reg_ab_write(vou_dev, VOUDPR, (rect->left << 16) | frame_out_top); | ||
495 | sh_vou_reg_ab_write(vou_dev, VOUDSR, (dsr_h << 16) | dsr_v); | ||
496 | |||
497 | /* | ||
498 | * if necessary, we could set VOUHIR to | ||
499 | * max(black_left + dsr_h, width_max) here | ||
500 | */ | ||
501 | |||
502 | if (w_idx) | ||
503 | vouvcr |= (1 << 15) | (vou_scale_h_fld[w_idx - 1] << 4); | ||
504 | if (h_idx) | ||
505 | vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1]; | ||
506 | |||
507 | dev_dbg(vou_dev->v4l2_dev.dev, "%s: scaling 0x%x\n", fmt->desc, vouvcr); | ||
508 | |||
509 | /* To produce a colour bar for testing set bit 23 of VOUVCR */ | ||
510 | sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr); | ||
511 | sh_vou_reg_ab_write(vou_dev, VOUDFR, | ||
512 | fmt->pkf | (fmt->yf << 8) | (fmt->rgb << 16)); | ||
513 | } | ||
514 | |||
515 | struct sh_vou_geometry { | ||
516 | struct v4l2_rect output; | ||
517 | unsigned int in_width; | ||
518 | unsigned int in_height; | ||
519 | int scale_idx_h; | ||
520 | int scale_idx_v; | ||
521 | }; | ||
522 | |||
523 | /* | ||
524 | * Find input geometry, that we can use to produce output, closest to the | ||
525 | * requested rectangle, using VOU scaling | ||
526 | */ | ||
527 | static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | ||
528 | { | ||
529 | /* The compiler cannot know, that best and idx will indeed be set */ | ||
530 | unsigned int best_err = UINT_MAX, best = 0, width_max, height_max; | ||
531 | int i, idx = 0; | ||
532 | |||
533 | if (std & V4L2_STD_525_60) { | ||
534 | width_max = 858; | ||
535 | height_max = 262; | ||
536 | } else { | ||
537 | width_max = 864; | ||
538 | height_max = 312; | ||
539 | } | ||
540 | |||
541 | /* Image width must be a multiple of 4 */ | ||
542 | v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, | ||
543 | &geo->in_height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | ||
544 | |||
545 | /* Select scales to come as close as possible to the output image */ | ||
546 | for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { | ||
547 | unsigned int err; | ||
548 | unsigned int found = geo->output.width * vou_scale_h_den[i] / | ||
549 | vou_scale_h_num[i]; | ||
550 | |||
551 | if (found > VOU_MAX_IMAGE_WIDTH) | ||
552 | /* scales increase */ | ||
553 | break; | ||
554 | |||
555 | err = abs(found - geo->in_width); | ||
556 | if (err < best_err) { | ||
557 | best_err = err; | ||
558 | idx = i; | ||
559 | best = found; | ||
560 | } | ||
561 | if (!err) | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | geo->in_width = best; | ||
566 | geo->scale_idx_h = idx; | ||
567 | |||
568 | best_err = UINT_MAX; | ||
569 | |||
570 | /* This loop can be replaced with one division */ | ||
571 | for (i = ARRAY_SIZE(vou_scale_v_num) - 1; i >= 0; i--) { | ||
572 | unsigned int err; | ||
573 | unsigned int found = geo->output.height * vou_scale_v_den[i] / | ||
574 | vou_scale_v_num[i]; | ||
575 | |||
576 | if (found > VOU_MAX_IMAGE_HEIGHT) | ||
577 | /* scales increase */ | ||
578 | break; | ||
579 | |||
580 | err = abs(found - geo->in_height); | ||
581 | if (err < best_err) { | ||
582 | best_err = err; | ||
583 | idx = i; | ||
584 | best = found; | ||
585 | } | ||
586 | if (!err) | ||
587 | break; | ||
588 | } | ||
589 | |||
590 | geo->in_height = best; | ||
591 | geo->scale_idx_v = idx; | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * Find output geometry, that we can produce, using VOU scaling, closest to | ||
596 | * the requested rectangle | ||
597 | */ | ||
598 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | ||
599 | { | ||
600 | unsigned int best_err = UINT_MAX, best, width_max, height_max; | ||
601 | int i, idx; | ||
602 | |||
603 | if (std & V4L2_STD_525_60) { | ||
604 | width_max = 858; | ||
605 | height_max = 262 * 2; | ||
606 | } else { | ||
607 | width_max = 864; | ||
608 | height_max = 312 * 2; | ||
609 | } | ||
610 | |||
611 | /* Select scales to come as close as possible to the output image */ | ||
612 | for (i = 0; i < ARRAY_SIZE(vou_scale_h_num); i++) { | ||
613 | unsigned int err; | ||
614 | unsigned int found = geo->in_width * vou_scale_h_num[i] / | ||
615 | vou_scale_h_den[i]; | ||
616 | |||
617 | if (found > VOU_MAX_IMAGE_WIDTH) | ||
618 | /* scales increase */ | ||
619 | break; | ||
620 | |||
621 | err = abs(found - geo->output.width); | ||
622 | if (err < best_err) { | ||
623 | best_err = err; | ||
624 | idx = i; | ||
625 | best = found; | ||
626 | } | ||
627 | if (!err) | ||
628 | break; | ||
629 | } | ||
630 | |||
631 | geo->output.width = best; | ||
632 | geo->scale_idx_h = idx; | ||
633 | if (geo->output.left + best > width_max) | ||
634 | geo->output.left = width_max - best; | ||
635 | |||
636 | pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width, | ||
637 | vou_scale_h_num[idx], vou_scale_h_den[idx], best); | ||
638 | |||
639 | best_err = UINT_MAX; | ||
640 | |||
641 | /* This loop can be replaced with one division */ | ||
642 | for (i = 0; i < ARRAY_SIZE(vou_scale_v_num); i++) { | ||
643 | unsigned int err; | ||
644 | unsigned int found = geo->in_height * vou_scale_v_num[i] / | ||
645 | vou_scale_v_den[i]; | ||
646 | |||
647 | if (found > VOU_MAX_IMAGE_HEIGHT) | ||
648 | /* scales increase */ | ||
649 | break; | ||
650 | |||
651 | err = abs(found - geo->output.height); | ||
652 | if (err < best_err) { | ||
653 | best_err = err; | ||
654 | idx = i; | ||
655 | best = found; | ||
656 | } | ||
657 | if (!err) | ||
658 | break; | ||
659 | } | ||
660 | |||
661 | geo->output.height = best; | ||
662 | geo->scale_idx_v = idx; | ||
663 | if (geo->output.top + best > height_max) | ||
664 | geo->output.top = height_max - best; | ||
665 | |||
666 | pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height, | ||
667 | vou_scale_v_num[idx], vou_scale_v_den[idx], best); | ||
668 | } | ||
669 | |||
670 | static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | ||
671 | struct v4l2_format *fmt) | ||
672 | { | ||
673 | struct video_device *vdev = video_devdata(file); | ||
674 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
675 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
676 | int pix_idx; | ||
677 | struct sh_vou_geometry geo; | ||
678 | struct v4l2_mbus_framefmt mbfmt = { | ||
679 | /* Revisit: is this the correct code? */ | ||
680 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | ||
681 | .field = V4L2_FIELD_INTERLACED, | ||
682 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
683 | }; | ||
684 | int ret; | ||
685 | |||
686 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__, | ||
687 | vou_dev->rect.width, vou_dev->rect.height, | ||
688 | pix->width, pix->height); | ||
689 | |||
690 | if (pix->field == V4L2_FIELD_ANY) | ||
691 | pix->field = V4L2_FIELD_NONE; | ||
692 | |||
693 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || | ||
694 | pix->field != V4L2_FIELD_NONE) | ||
695 | return -EINVAL; | ||
696 | |||
697 | for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++) | ||
698 | if (vou_fmt[pix_idx].pfmt == pix->pixelformat) | ||
699 | break; | ||
700 | |||
701 | if (pix_idx == ARRAY_SIZE(vou_fmt)) | ||
702 | return -EINVAL; | ||
703 | |||
704 | /* Image width must be a multiple of 4 */ | ||
705 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, | ||
706 | &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | ||
707 | |||
708 | geo.in_width = pix->width; | ||
709 | geo.in_height = pix->height; | ||
710 | geo.output = vou_dev->rect; | ||
711 | |||
712 | vou_adjust_output(&geo, vou_dev->std); | ||
713 | |||
714 | mbfmt.width = geo.output.width; | ||
715 | mbfmt.height = geo.output.height; | ||
716 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, | ||
717 | s_mbus_fmt, &mbfmt); | ||
718 | /* Must be implemented, so, don't check for -ENOIOCTLCMD */ | ||
719 | if (ret < 0) | ||
720 | return ret; | ||
721 | |||
722 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__, | ||
723 | geo.output.width, geo.output.height, mbfmt.width, mbfmt.height); | ||
724 | |||
725 | /* Sanity checks */ | ||
726 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | ||
727 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | ||
728 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | ||
729 | return -EIO; | ||
730 | |||
731 | if (mbfmt.width != geo.output.width || | ||
732 | mbfmt.height != geo.output.height) { | ||
733 | geo.output.width = mbfmt.width; | ||
734 | geo.output.height = mbfmt.height; | ||
735 | |||
736 | vou_adjust_input(&geo, vou_dev->std); | ||
737 | } | ||
738 | |||
739 | /* We tried to preserve output rectangle, but it could have changed */ | ||
740 | vou_dev->rect = geo.output; | ||
741 | pix->width = geo.in_width; | ||
742 | pix->height = geo.in_height; | ||
743 | |||
744 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u\n", __func__, | ||
745 | pix->width, pix->height); | ||
746 | |||
747 | vou_dev->pix_idx = pix_idx; | ||
748 | |||
749 | vou_dev->pix = *pix; | ||
750 | |||
751 | sh_vou_configure_geometry(vou_dev, pix_idx, | ||
752 | geo.scale_idx_h, geo.scale_idx_v); | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, | ||
758 | struct v4l2_format *fmt) | ||
759 | { | ||
760 | struct sh_vou_file *vou_file = priv; | ||
761 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
762 | int i; | ||
763 | |||
764 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
765 | |||
766 | fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
767 | pix->field = V4L2_FIELD_NONE; | ||
768 | |||
769 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1, | ||
770 | &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | ||
771 | |||
772 | for (i = 0; ARRAY_SIZE(vou_fmt); i++) | ||
773 | if (vou_fmt[i].pfmt == pix->pixelformat) | ||
774 | return 0; | ||
775 | |||
776 | pix->pixelformat = vou_fmt[0].pfmt; | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static int sh_vou_reqbufs(struct file *file, void *priv, | ||
782 | struct v4l2_requestbuffers *req) | ||
783 | { | ||
784 | struct sh_vou_file *vou_file = priv; | ||
785 | |||
786 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
787 | |||
788 | if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
789 | return -EINVAL; | ||
790 | |||
791 | return videobuf_reqbufs(&vou_file->vbq, req); | ||
792 | } | ||
793 | |||
794 | static int sh_vou_querybuf(struct file *file, void *priv, | ||
795 | struct v4l2_buffer *b) | ||
796 | { | ||
797 | struct sh_vou_file *vou_file = priv; | ||
798 | |||
799 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
800 | |||
801 | return videobuf_querybuf(&vou_file->vbq, b); | ||
802 | } | ||
803 | |||
804 | static int sh_vou_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
805 | { | ||
806 | struct sh_vou_file *vou_file = priv; | ||
807 | |||
808 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
809 | |||
810 | return videobuf_qbuf(&vou_file->vbq, b); | ||
811 | } | ||
812 | |||
813 | static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
814 | { | ||
815 | struct sh_vou_file *vou_file = priv; | ||
816 | |||
817 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
818 | |||
819 | return videobuf_dqbuf(&vou_file->vbq, b, file->f_flags & O_NONBLOCK); | ||
820 | } | ||
821 | |||
822 | static int sh_vou_streamon(struct file *file, void *priv, | ||
823 | enum v4l2_buf_type buftype) | ||
824 | { | ||
825 | struct video_device *vdev = video_devdata(file); | ||
826 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
827 | struct sh_vou_file *vou_file = priv; | ||
828 | int ret; | ||
829 | |||
830 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
831 | |||
832 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, | ||
833 | video, s_stream, 1); | ||
834 | if (ret < 0 && ret != -ENOIOCTLCMD) | ||
835 | return ret; | ||
836 | |||
837 | /* This calls our .buf_queue() (== sh_vou_buf_queue) */ | ||
838 | return videobuf_streamon(&vou_file->vbq); | ||
839 | } | ||
840 | |||
841 | static int sh_vou_streamoff(struct file *file, void *priv, | ||
842 | enum v4l2_buf_type buftype) | ||
843 | { | ||
844 | struct video_device *vdev = video_devdata(file); | ||
845 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
846 | struct sh_vou_file *vou_file = priv; | ||
847 | |||
848 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
849 | |||
850 | /* | ||
851 | * This calls buf_release from host driver's videobuf_queue_ops for all | ||
852 | * remaining buffers. When the last buffer is freed, stop streaming | ||
853 | */ | ||
854 | videobuf_streamoff(&vou_file->vbq); | ||
855 | v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, s_stream, 0); | ||
856 | |||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) | ||
861 | { | ||
862 | switch (bus_fmt) { | ||
863 | default: | ||
864 | pr_warning("%s(): Invalid bus-format code %d, using default 8-bit\n", | ||
865 | __func__, bus_fmt); | ||
866 | case SH_VOU_BUS_8BIT: | ||
867 | return 1; | ||
868 | case SH_VOU_BUS_16BIT: | ||
869 | return 0; | ||
870 | case SH_VOU_BUS_BT656: | ||
871 | return 3; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id) | ||
876 | { | ||
877 | struct video_device *vdev = video_devdata(file); | ||
878 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
879 | int ret; | ||
880 | |||
881 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id); | ||
882 | |||
883 | if (*std_id & ~vdev->tvnorms) | ||
884 | return -EINVAL; | ||
885 | |||
886 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, | ||
887 | s_std_output, *std_id); | ||
888 | /* Shall we continue, if the subdev doesn't support .s_std_output()? */ | ||
889 | if (ret < 0 && ret != -ENOIOCTLCMD) | ||
890 | return ret; | ||
891 | |||
892 | if (*std_id & V4L2_STD_525_60) | ||
893 | sh_vou_reg_ab_set(vou_dev, VOUCR, | ||
894 | sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29); | ||
895 | else | ||
896 | sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29); | ||
897 | |||
898 | vou_dev->std = *std_id; | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) | ||
904 | { | ||
905 | struct video_device *vdev = video_devdata(file); | ||
906 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
907 | |||
908 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | ||
909 | |||
910 | *std = vou_dev->std; | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) | ||
916 | { | ||
917 | struct video_device *vdev = video_devdata(file); | ||
918 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
919 | |||
920 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | ||
921 | |||
922 | a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
923 | a->c = vou_dev->rect; | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | /* Assume a dull encoder, do all the work ourselves. */ | ||
929 | static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | ||
930 | { | ||
931 | struct video_device *vdev = video_devdata(file); | ||
932 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
933 | struct v4l2_rect *rect = &a->c; | ||
934 | struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; | ||
935 | struct v4l2_pix_format *pix = &vou_dev->pix; | ||
936 | struct sh_vou_geometry geo; | ||
937 | struct v4l2_mbus_framefmt mbfmt = { | ||
938 | /* Revisit: is this the correct code? */ | ||
939 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | ||
940 | .field = V4L2_FIELD_INTERLACED, | ||
941 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
942 | }; | ||
943 | int ret; | ||
944 | |||
945 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, | ||
946 | rect->width, rect->height, rect->left, rect->top); | ||
947 | |||
948 | if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
949 | return -EINVAL; | ||
950 | |||
951 | v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, | ||
952 | &rect->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | ||
953 | |||
954 | if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) | ||
955 | rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; | ||
956 | |||
957 | if (rect->height + rect->top > VOU_MAX_IMAGE_HEIGHT) | ||
958 | rect->top = VOU_MAX_IMAGE_HEIGHT - rect->height; | ||
959 | |||
960 | geo.output = *rect; | ||
961 | geo.in_width = pix->width; | ||
962 | geo.in_height = pix->height; | ||
963 | |||
964 | /* Configure the encoder one-to-one, position at 0, ignore errors */ | ||
965 | sd_crop.c.width = geo.output.width; | ||
966 | sd_crop.c.height = geo.output.height; | ||
967 | /* | ||
968 | * We first issue a S_CROP, so that the subsequent S_FMT delivers the | ||
969 | * final encoder configuration. | ||
970 | */ | ||
971 | v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, | ||
972 | s_crop, &sd_crop); | ||
973 | mbfmt.width = geo.output.width; | ||
974 | mbfmt.height = geo.output.height; | ||
975 | ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, | ||
976 | s_mbus_fmt, &mbfmt); | ||
977 | /* Must be implemented, so, don't check for -ENOIOCTLCMD */ | ||
978 | if (ret < 0) | ||
979 | return ret; | ||
980 | |||
981 | /* Sanity checks */ | ||
982 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | ||
983 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | ||
984 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | ||
985 | return -EIO; | ||
986 | |||
987 | geo.output.width = mbfmt.width; | ||
988 | geo.output.height = mbfmt.height; | ||
989 | |||
990 | /* | ||
991 | * No down-scaling. According to the API, current call has precedence: | ||
992 | * http://v4l2spec.bytesex.org/spec/x1904.htm#AEN1954 paragraph two. | ||
993 | */ | ||
994 | vou_adjust_input(&geo, vou_dev->std); | ||
995 | |||
996 | /* We tried to preserve output rectangle, but it could have changed */ | ||
997 | vou_dev->rect = geo.output; | ||
998 | pix->width = geo.in_width; | ||
999 | pix->height = geo.in_height; | ||
1000 | |||
1001 | sh_vou_configure_geometry(vou_dev, vou_dev->pix_idx, | ||
1002 | geo.scale_idx_h, geo.scale_idx_v); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | /* | ||
1008 | * Total field: NTSC 858 x 2 * 262/263, PAL 864 x 2 * 312/313, default rectangle | ||
1009 | * is the initial register values, height takes the interlaced format into | ||
1010 | * account. The actual image can only go up to 720 x 2 * 240, So, VOUVPR can | ||
1011 | * actually only meaningfully contain values <= 720 and <= 240 respectively, and | ||
1012 | * not <= 864 and <= 312. | ||
1013 | */ | ||
1014 | static int sh_vou_cropcap(struct file *file, void *priv, | ||
1015 | struct v4l2_cropcap *a) | ||
1016 | { | ||
1017 | struct sh_vou_file *vou_file = priv; | ||
1018 | |||
1019 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
1020 | |||
1021 | a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1022 | a->bounds.left = 0; | ||
1023 | a->bounds.top = 0; | ||
1024 | a->bounds.width = VOU_MAX_IMAGE_WIDTH; | ||
1025 | a->bounds.height = VOU_MAX_IMAGE_HEIGHT; | ||
1026 | /* Default = max, set VOUDPR = 0, which is not hardware default */ | ||
1027 | a->defrect.left = 0; | ||
1028 | a->defrect.top = 0; | ||
1029 | a->defrect.width = VOU_MAX_IMAGE_WIDTH; | ||
1030 | a->defrect.height = VOU_MAX_IMAGE_HEIGHT; | ||
1031 | a->pixelaspect.numerator = 1; | ||
1032 | a->pixelaspect.denominator = 1; | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static irqreturn_t sh_vou_isr(int irq, void *dev_id) | ||
1038 | { | ||
1039 | struct sh_vou_device *vou_dev = dev_id; | ||
1040 | static unsigned long j; | ||
1041 | struct videobuf_buffer *vb; | ||
1042 | static int cnt; | ||
1043 | static int side; | ||
1044 | u32 irq_status = sh_vou_reg_a_read(vou_dev, VOUIR), masked; | ||
1045 | u32 vou_status = sh_vou_reg_a_read(vou_dev, VOUSTR); | ||
1046 | |||
1047 | if (!(irq_status & 0x300)) { | ||
1048 | if (printk_timed_ratelimit(&j, 500)) | ||
1049 | dev_warn(vou_dev->v4l2_dev.dev, "IRQ status 0x%x!\n", | ||
1050 | irq_status); | ||
1051 | return IRQ_NONE; | ||
1052 | } | ||
1053 | |||
1054 | spin_lock(&vou_dev->lock); | ||
1055 | if (!vou_dev->active || list_empty(&vou_dev->queue)) { | ||
1056 | if (printk_timed_ratelimit(&j, 500)) | ||
1057 | dev_warn(vou_dev->v4l2_dev.dev, | ||
1058 | "IRQ without active buffer: %x!\n", irq_status); | ||
1059 | /* Just ack: buf_release will disable further interrupts */ | ||
1060 | sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x300); | ||
1061 | spin_unlock(&vou_dev->lock); | ||
1062 | return IRQ_HANDLED; | ||
1063 | } | ||
1064 | |||
1065 | masked = ~(0x300 & irq_status) & irq_status & 0x30304; | ||
1066 | dev_dbg(vou_dev->v4l2_dev.dev, | ||
1067 | "IRQ status 0x%x -> 0x%x, VOU status 0x%x, cnt %d\n", | ||
1068 | irq_status, masked, vou_status, cnt); | ||
1069 | |||
1070 | cnt++; | ||
1071 | side = vou_status & 0x10000; | ||
1072 | |||
1073 | /* Clear only set interrupts */ | ||
1074 | sh_vou_reg_a_write(vou_dev, VOUIR, masked); | ||
1075 | |||
1076 | vb = vou_dev->active; | ||
1077 | list_del(&vb->queue); | ||
1078 | |||
1079 | vb->state = VIDEOBUF_DONE; | ||
1080 | do_gettimeofday(&vb->ts); | ||
1081 | vb->field_count++; | ||
1082 | wake_up(&vb->done); | ||
1083 | |||
1084 | if (list_empty(&vou_dev->queue)) { | ||
1085 | /* Stop VOU */ | ||
1086 | dev_dbg(vou_dev->v4l2_dev.dev, "%s: queue empty after %d\n", | ||
1087 | __func__, cnt); | ||
1088 | sh_vou_reg_a_set(vou_dev, VOUER, 0, 1); | ||
1089 | vou_dev->active = NULL; | ||
1090 | vou_dev->status = SH_VOU_INITIALISING; | ||
1091 | /* Disable End-of-Frame (VSYNC) interrupts */ | ||
1092 | sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000); | ||
1093 | spin_unlock(&vou_dev->lock); | ||
1094 | return IRQ_HANDLED; | ||
1095 | } | ||
1096 | |||
1097 | vou_dev->active = list_entry(vou_dev->queue.next, | ||
1098 | struct videobuf_buffer, queue); | ||
1099 | |||
1100 | if (vou_dev->active->queue.next != &vou_dev->queue) { | ||
1101 | struct videobuf_buffer *new = list_entry(vou_dev->active->queue.next, | ||
1102 | struct videobuf_buffer, queue); | ||
1103 | sh_vou_schedule_next(vou_dev, new); | ||
1104 | } | ||
1105 | |||
1106 | spin_unlock(&vou_dev->lock); | ||
1107 | |||
1108 | return IRQ_HANDLED; | ||
1109 | } | ||
1110 | |||
1111 | static int sh_vou_hw_init(struct sh_vou_device *vou_dev) | ||
1112 | { | ||
1113 | struct sh_vou_pdata *pdata = vou_dev->pdata; | ||
1114 | u32 voucr = sh_vou_ntsc_mode(pdata->bus_fmt) << 29; | ||
1115 | int i = 100; | ||
1116 | |||
1117 | /* Disable all IRQs */ | ||
1118 | sh_vou_reg_a_write(vou_dev, VOUIR, 0); | ||
1119 | |||
1120 | /* Reset VOU interfaces - registers unaffected */ | ||
1121 | sh_vou_reg_a_write(vou_dev, VOUSRR, 0x101); | ||
1122 | while (--i && (sh_vou_reg_a_read(vou_dev, VOUSRR) & 0x101)) | ||
1123 | udelay(1); | ||
1124 | |||
1125 | if (!i) | ||
1126 | return -ETIMEDOUT; | ||
1127 | |||
1128 | dev_dbg(vou_dev->v4l2_dev.dev, "Reset took %dus\n", 100 - i); | ||
1129 | |||
1130 | if (pdata->flags & SH_VOU_PCLK_FALLING) | ||
1131 | voucr |= 1 << 28; | ||
1132 | if (pdata->flags & SH_VOU_HSYNC_LOW) | ||
1133 | voucr |= 1 << 27; | ||
1134 | if (pdata->flags & SH_VOU_VSYNC_LOW) | ||
1135 | voucr |= 1 << 26; | ||
1136 | sh_vou_reg_ab_set(vou_dev, VOUCR, voucr, 0xfc000000); | ||
1137 | |||
1138 | /* Manual register side switching at first */ | ||
1139 | sh_vou_reg_a_write(vou_dev, VOURCR, 4); | ||
1140 | /* Default - fixed HSYNC length, can be made configurable is required */ | ||
1141 | sh_vou_reg_ab_write(vou_dev, VOUMSR, 0x800000); | ||
1142 | |||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | /* File operations */ | ||
1147 | static int sh_vou_open(struct file *file) | ||
1148 | { | ||
1149 | struct video_device *vdev = video_devdata(file); | ||
1150 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1151 | struct sh_vou_file *vou_file = kzalloc(sizeof(struct sh_vou_file), | ||
1152 | GFP_KERNEL); | ||
1153 | |||
1154 | if (!vou_file) | ||
1155 | return -ENOMEM; | ||
1156 | |||
1157 | dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); | ||
1158 | |||
1159 | file->private_data = vou_file; | ||
1160 | |||
1161 | if (atomic_inc_return(&vou_dev->use_count) == 1) { | ||
1162 | int ret; | ||
1163 | /* First open */ | ||
1164 | vou_dev->status = SH_VOU_INITIALISING; | ||
1165 | pm_runtime_get_sync(vdev->v4l2_dev->dev); | ||
1166 | ret = sh_vou_hw_init(vou_dev); | ||
1167 | if (ret < 0) { | ||
1168 | atomic_dec(&vou_dev->use_count); | ||
1169 | pm_runtime_put(vdev->v4l2_dev->dev); | ||
1170 | vou_dev->status = SH_VOU_IDLE; | ||
1171 | return ret; | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | videobuf_queue_dma_contig_init(&vou_file->vbq, &sh_vou_video_qops, | ||
1176 | vou_dev->v4l2_dev.dev, &vou_dev->lock, | ||
1177 | V4L2_BUF_TYPE_VIDEO_OUTPUT, | ||
1178 | V4L2_FIELD_NONE, | ||
1179 | sizeof(struct videobuf_buffer), vdev); | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int sh_vou_release(struct file *file) | ||
1185 | { | ||
1186 | struct video_device *vdev = video_devdata(file); | ||
1187 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1188 | struct sh_vou_file *vou_file = file->private_data; | ||
1189 | |||
1190 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
1191 | |||
1192 | if (!atomic_dec_return(&vou_dev->use_count)) { | ||
1193 | /* Last close */ | ||
1194 | vou_dev->status = SH_VOU_IDLE; | ||
1195 | sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); | ||
1196 | pm_runtime_put(vdev->v4l2_dev->dev); | ||
1197 | } | ||
1198 | |||
1199 | file->private_data = NULL; | ||
1200 | kfree(vou_file); | ||
1201 | |||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) | ||
1206 | { | ||
1207 | struct sh_vou_file *vou_file = file->private_data; | ||
1208 | |||
1209 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
1210 | |||
1211 | return videobuf_mmap_mapper(&vou_file->vbq, vma); | ||
1212 | } | ||
1213 | |||
1214 | static unsigned int sh_vou_poll(struct file *file, poll_table *wait) | ||
1215 | { | ||
1216 | struct sh_vou_file *vou_file = file->private_data; | ||
1217 | |||
1218 | dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); | ||
1219 | |||
1220 | return videobuf_poll_stream(file, &vou_file->vbq, wait); | ||
1221 | } | ||
1222 | |||
1223 | static int sh_vou_g_chip_ident(struct file *file, void *fh, | ||
1224 | struct v4l2_dbg_chip_ident *id) | ||
1225 | { | ||
1226 | struct video_device *vdev = video_devdata(file); | ||
1227 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1228 | |||
1229 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); | ||
1230 | } | ||
1231 | |||
1232 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1233 | static int sh_vou_g_register(struct file *file, void *fh, | ||
1234 | struct v4l2_dbg_register *reg) | ||
1235 | { | ||
1236 | struct video_device *vdev = video_devdata(file); | ||
1237 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1238 | |||
1239 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); | ||
1240 | } | ||
1241 | |||
1242 | static int sh_vou_s_register(struct file *file, void *fh, | ||
1243 | struct v4l2_dbg_register *reg) | ||
1244 | { | ||
1245 | struct video_device *vdev = video_devdata(file); | ||
1246 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | ||
1247 | |||
1248 | return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); | ||
1249 | } | ||
1250 | #endif | ||
1251 | |||
1252 | /* sh_vou display ioctl operations */ | ||
1253 | static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { | ||
1254 | .vidioc_querycap = sh_vou_querycap, | ||
1255 | .vidioc_enum_fmt_vid_out = sh_vou_enum_fmt_vid_out, | ||
1256 | .vidioc_g_fmt_vid_out = sh_vou_g_fmt_vid_out, | ||
1257 | .vidioc_s_fmt_vid_out = sh_vou_s_fmt_vid_out, | ||
1258 | .vidioc_try_fmt_vid_out = sh_vou_try_fmt_vid_out, | ||
1259 | .vidioc_reqbufs = sh_vou_reqbufs, | ||
1260 | .vidioc_querybuf = sh_vou_querybuf, | ||
1261 | .vidioc_qbuf = sh_vou_qbuf, | ||
1262 | .vidioc_dqbuf = sh_vou_dqbuf, | ||
1263 | .vidioc_streamon = sh_vou_streamon, | ||
1264 | .vidioc_streamoff = sh_vou_streamoff, | ||
1265 | .vidioc_s_std = sh_vou_s_std, | ||
1266 | .vidioc_g_std = sh_vou_g_std, | ||
1267 | .vidioc_cropcap = sh_vou_cropcap, | ||
1268 | .vidioc_g_crop = sh_vou_g_crop, | ||
1269 | .vidioc_s_crop = sh_vou_s_crop, | ||
1270 | .vidioc_g_chip_ident = sh_vou_g_chip_ident, | ||
1271 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1272 | .vidioc_g_register = sh_vou_g_register, | ||
1273 | .vidioc_s_register = sh_vou_s_register, | ||
1274 | #endif | ||
1275 | }; | ||
1276 | |||
1277 | static const struct v4l2_file_operations sh_vou_fops = { | ||
1278 | .owner = THIS_MODULE, | ||
1279 | .open = sh_vou_open, | ||
1280 | .release = sh_vou_release, | ||
1281 | .ioctl = video_ioctl2, | ||
1282 | .mmap = sh_vou_mmap, | ||
1283 | .poll = sh_vou_poll, | ||
1284 | }; | ||
1285 | |||
1286 | static const struct video_device sh_vou_video_template = { | ||
1287 | .name = "sh_vou", | ||
1288 | .fops = &sh_vou_fops, | ||
1289 | .ioctl_ops = &sh_vou_ioctl_ops, | ||
1290 | .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ | ||
1291 | .current_norm = V4L2_STD_NTSC_M, | ||
1292 | }; | ||
1293 | |||
1294 | static int __devinit sh_vou_probe(struct platform_device *pdev) | ||
1295 | { | ||
1296 | struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data; | ||
1297 | struct v4l2_rect *rect; | ||
1298 | struct v4l2_pix_format *pix; | ||
1299 | struct i2c_adapter *i2c_adap; | ||
1300 | struct video_device *vdev; | ||
1301 | struct sh_vou_device *vou_dev; | ||
1302 | struct resource *reg_res, *region; | ||
1303 | struct v4l2_subdev *subdev; | ||
1304 | int irq, ret; | ||
1305 | |||
1306 | reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1307 | irq = platform_get_irq(pdev, 0); | ||
1308 | |||
1309 | if (!vou_pdata || !reg_res || irq <= 0) { | ||
1310 | dev_err(&pdev->dev, "Insufficient VOU platform information.\n"); | ||
1311 | return -ENODEV; | ||
1312 | } | ||
1313 | |||
1314 | vou_dev = kzalloc(sizeof(*vou_dev), GFP_KERNEL); | ||
1315 | if (!vou_dev) | ||
1316 | return -ENOMEM; | ||
1317 | |||
1318 | INIT_LIST_HEAD(&vou_dev->queue); | ||
1319 | spin_lock_init(&vou_dev->lock); | ||
1320 | atomic_set(&vou_dev->use_count, 0); | ||
1321 | vou_dev->pdata = vou_pdata; | ||
1322 | vou_dev->status = SH_VOU_IDLE; | ||
1323 | |||
1324 | rect = &vou_dev->rect; | ||
1325 | pix = &vou_dev->pix; | ||
1326 | |||
1327 | /* Fill in defaults */ | ||
1328 | vou_dev->std = sh_vou_video_template.current_norm; | ||
1329 | rect->left = 0; | ||
1330 | rect->top = 0; | ||
1331 | rect->width = VOU_MAX_IMAGE_WIDTH; | ||
1332 | rect->height = VOU_MAX_IMAGE_HEIGHT; | ||
1333 | pix->width = VOU_MAX_IMAGE_WIDTH; | ||
1334 | pix->height = VOU_MAX_IMAGE_HEIGHT; | ||
1335 | pix->pixelformat = V4L2_PIX_FMT_YVYU; | ||
1336 | pix->field = V4L2_FIELD_NONE; | ||
1337 | pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; | ||
1338 | pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * VOU_MAX_IMAGE_HEIGHT; | ||
1339 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1340 | |||
1341 | region = request_mem_region(reg_res->start, resource_size(reg_res), | ||
1342 | pdev->name); | ||
1343 | if (!region) { | ||
1344 | dev_err(&pdev->dev, "VOU region already claimed\n"); | ||
1345 | ret = -EBUSY; | ||
1346 | goto ereqmemreg; | ||
1347 | } | ||
1348 | |||
1349 | vou_dev->base = ioremap(reg_res->start, resource_size(reg_res)); | ||
1350 | if (!vou_dev->base) { | ||
1351 | ret = -ENOMEM; | ||
1352 | goto emap; | ||
1353 | } | ||
1354 | |||
1355 | ret = request_irq(irq, sh_vou_isr, 0, "vou", vou_dev); | ||
1356 | if (ret < 0) | ||
1357 | goto ereqirq; | ||
1358 | |||
1359 | ret = v4l2_device_register(&pdev->dev, &vou_dev->v4l2_dev); | ||
1360 | if (ret < 0) { | ||
1361 | dev_err(&pdev->dev, "Error registering v4l2 device\n"); | ||
1362 | goto ev4l2devreg; | ||
1363 | } | ||
1364 | |||
1365 | /* Allocate memory for video device */ | ||
1366 | vdev = video_device_alloc(); | ||
1367 | if (vdev == NULL) { | ||
1368 | ret = -ENOMEM; | ||
1369 | goto evdevalloc; | ||
1370 | } | ||
1371 | |||
1372 | *vdev = sh_vou_video_template; | ||
1373 | if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT) | ||
1374 | vdev->tvnorms |= V4L2_STD_PAL; | ||
1375 | vdev->v4l2_dev = &vou_dev->v4l2_dev; | ||
1376 | vdev->release = video_device_release; | ||
1377 | |||
1378 | vou_dev->vdev = vdev; | ||
1379 | video_set_drvdata(vdev, vou_dev); | ||
1380 | |||
1381 | pm_runtime_enable(&pdev->dev); | ||
1382 | pm_runtime_resume(&pdev->dev); | ||
1383 | |||
1384 | i2c_adap = i2c_get_adapter(vou_pdata->i2c_adap); | ||
1385 | if (!i2c_adap) { | ||
1386 | ret = -ENODEV; | ||
1387 | goto ei2cgadap; | ||
1388 | } | ||
1389 | |||
1390 | ret = sh_vou_hw_init(vou_dev); | ||
1391 | if (ret < 0) | ||
1392 | goto ereset; | ||
1393 | |||
1394 | subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap, | ||
1395 | vou_pdata->module_name, vou_pdata->board_info, NULL); | ||
1396 | if (!subdev) { | ||
1397 | ret = -ENOMEM; | ||
1398 | goto ei2cnd; | ||
1399 | } | ||
1400 | |||
1401 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | ||
1402 | if (ret < 0) | ||
1403 | goto evregdev; | ||
1404 | |||
1405 | return 0; | ||
1406 | |||
1407 | evregdev: | ||
1408 | ei2cnd: | ||
1409 | ereset: | ||
1410 | i2c_put_adapter(i2c_adap); | ||
1411 | ei2cgadap: | ||
1412 | video_device_release(vdev); | ||
1413 | pm_runtime_disable(&pdev->dev); | ||
1414 | evdevalloc: | ||
1415 | v4l2_device_unregister(&vou_dev->v4l2_dev); | ||
1416 | ev4l2devreg: | ||
1417 | free_irq(irq, vou_dev); | ||
1418 | ereqirq: | ||
1419 | iounmap(vou_dev->base); | ||
1420 | emap: | ||
1421 | release_mem_region(reg_res->start, resource_size(reg_res)); | ||
1422 | ereqmemreg: | ||
1423 | kfree(vou_dev); | ||
1424 | return ret; | ||
1425 | } | ||
1426 | |||
1427 | static int __devexit sh_vou_remove(struct platform_device *pdev) | ||
1428 | { | ||
1429 | int irq = platform_get_irq(pdev, 0); | ||
1430 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
1431 | struct sh_vou_device *vou_dev = container_of(v4l2_dev, | ||
1432 | struct sh_vou_device, v4l2_dev); | ||
1433 | struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next, | ||
1434 | struct v4l2_subdev, list); | ||
1435 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1436 | struct resource *reg_res; | ||
1437 | |||
1438 | if (irq > 0) | ||
1439 | free_irq(irq, vou_dev); | ||
1440 | pm_runtime_disable(&pdev->dev); | ||
1441 | video_unregister_device(vou_dev->vdev); | ||
1442 | i2c_put_adapter(client->adapter); | ||
1443 | v4l2_device_unregister(&vou_dev->v4l2_dev); | ||
1444 | iounmap(vou_dev->base); | ||
1445 | reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1446 | if (reg_res) | ||
1447 | release_mem_region(reg_res->start, resource_size(reg_res)); | ||
1448 | kfree(vou_dev); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | static struct platform_driver __refdata sh_vou = { | ||
1453 | .remove = __devexit_p(sh_vou_remove), | ||
1454 | .driver = { | ||
1455 | .name = "sh-vou", | ||
1456 | .owner = THIS_MODULE, | ||
1457 | }, | ||
1458 | }; | ||
1459 | |||
1460 | static int __init sh_vou_init(void) | ||
1461 | { | ||
1462 | return platform_driver_probe(&sh_vou, sh_vou_probe); | ||
1463 | } | ||
1464 | |||
1465 | static void __exit sh_vou_exit(void) | ||
1466 | { | ||
1467 | platform_driver_unregister(&sh_vou); | ||
1468 | } | ||
1469 | |||
1470 | module_init(sh_vou_init); | ||
1471 | module_exit(sh_vou_exit); | ||
1472 | |||
1473 | MODULE_DESCRIPTION("SuperH VOU driver"); | ||
1474 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
1475 | MODULE_LICENSE("GPL v2"); | ||
1476 | MODULE_ALIAS("platform:sh-vou"); | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index cbf8087b286f..28e19daadec9 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -2295,7 +2295,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) | |||
2295 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 2295 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
2296 | return -EFAULT; | 2296 | return -EFAULT; |
2297 | 2297 | ||
2298 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | 2298 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { |
2299 | if (ctrl.id == s->qctrl[i].id) { | 2299 | if (ctrl.id == s->qctrl[i].id) { |
2300 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) | 2300 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) |
2301 | return -EINVAL; | 2301 | return -EINVAL; |
@@ -2305,7 +2305,9 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) | |||
2305 | ctrl.value -= ctrl.value % s->qctrl[i].step; | 2305 | ctrl.value -= ctrl.value % s->qctrl[i].step; |
2306 | break; | 2306 | break; |
2307 | } | 2307 | } |
2308 | 2308 | } | |
2309 | if (i == ARRAY_SIZE(s->qctrl)) | ||
2310 | return -EINVAL; | ||
2309 | if ((err = s->set_ctrl(cam, &ctrl))) | 2311 | if ((err = s->set_ctrl(cam, &ctrl))) |
2310 | return err; | 2312 | return err; |
2311 | 2313 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index cc40d6ba9f22..522ba3f4c285 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
@@ -40,12 +40,12 @@ struct sn9c102_device; | |||
40 | 40 | ||
41 | static const struct usb_device_id sn9c102_id_table[] = { | 41 | static const struct usb_device_id sn9c102_id_table[] = { |
42 | /* SN9C101 and SN9C102 */ | 42 | /* SN9C101 and SN9C102 */ |
43 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 43 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
44 | { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, | 44 | { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, |
45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, | 45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, |
46 | #endif | 46 | #endif |
47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, | 47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, |
48 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 48 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
49 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, | 49 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, |
50 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, | 50 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, |
51 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ | 51 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ |
@@ -53,13 +53,13 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
53 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, | 53 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, |
54 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, | 54 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, |
55 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, | 55 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, |
56 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 56 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
57 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, | 57 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, |
58 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, | 58 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, |
59 | #endif | 59 | #endif |
60 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, | 60 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, |
61 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, | 61 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, |
62 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 62 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
63 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, | 63 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, |
64 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ | 64 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ |
65 | #endif | 65 | #endif |
@@ -74,7 +74,7 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
74 | { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, | 74 | { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, |
75 | { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, | 75 | { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, |
76 | /* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ | 76 | /* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ |
77 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 77 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
78 | { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, | 78 | { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, |
79 | #endif | 79 | #endif |
80 | { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, | 80 | { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, |
@@ -86,7 +86,7 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
86 | { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, | 86 | { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, |
87 | { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, | 87 | { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, |
88 | { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, | 88 | { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, |
89 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 89 | #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE |
90 | { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, | 90 | { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, |
91 | #endif | 91 | #endif |
92 | { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, | 92 | { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, |
@@ -97,7 +97,7 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
97 | { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, | 97 | { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, |
98 | { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, | 98 | { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, |
99 | /* SN9C105 */ | 99 | /* SN9C105 */ |
100 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 100 | #if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE |
101 | { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, | 101 | { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, |
102 | { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, | 102 | { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, |
103 | { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, | 103 | { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, |
@@ -121,11 +121,11 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
121 | { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, | 121 | { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, |
122 | { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, | 122 | { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, |
123 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ | 123 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ |
124 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 124 | #if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE |
125 | { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, | 125 | { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, |
126 | #endif | 126 | #endif |
127 | { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, | 127 | { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, |
128 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 128 | #if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE |
129 | { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, | 129 | { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, |
130 | { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, | 130 | { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, |
131 | #endif | 131 | #endif |
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index db2434948939..2dce5c908c8e 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c | |||
@@ -255,7 +255,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) | |||
255 | if (err || r0 < 0 || r1 < 0) | 255 | if (err || r0 < 0 || r1 < 0) |
256 | return -EIO; | 256 | return -EIO; |
257 | 257 | ||
258 | if (r0 != 0x00 || r1 != 0x04) | 258 | if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04) |
259 | return -ENODEV; | 259 | return -ENODEV; |
260 | 260 | ||
261 | sn9c102_attach_sensor(cam, &hv7131d); | 261 | sn9c102_attach_sensor(cam, &hv7131d); |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index a24174ddec46..db1ca0e90d76 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/pm_runtime.h> | ||
28 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
29 | 30 | ||
30 | #include <media/soc_camera.h> | 31 | #include <media/soc_camera.h> |
@@ -388,6 +389,11 @@ static int soc_camera_open(struct file *file) | |||
388 | goto eiciadd; | 389 | goto eiciadd; |
389 | } | 390 | } |
390 | 391 | ||
392 | pm_runtime_enable(&icd->vdev->dev); | ||
393 | ret = pm_runtime_resume(&icd->vdev->dev); | ||
394 | if (ret < 0 && ret != -ENOSYS) | ||
395 | goto eresume; | ||
396 | |||
391 | /* | 397 | /* |
392 | * Try to configure with default parameters. Notice: this is the | 398 | * Try to configure with default parameters. Notice: this is the |
393 | * very first open, so, we cannot race against other calls, | 399 | * very first open, so, we cannot race against other calls, |
@@ -409,10 +415,12 @@ static int soc_camera_open(struct file *file) | |||
409 | return 0; | 415 | return 0; |
410 | 416 | ||
411 | /* | 417 | /* |
412 | * First five errors are entered with the .video_lock held | 418 | * First four errors are entered with the .video_lock held |
413 | * and use_count == 1 | 419 | * and use_count == 1 |
414 | */ | 420 | */ |
415 | esfmt: | 421 | esfmt: |
422 | pm_runtime_disable(&icd->vdev->dev); | ||
423 | eresume: | ||
416 | ici->ops->remove(icd); | 424 | ici->ops->remove(icd); |
417 | eiciadd: | 425 | eiciadd: |
418 | if (icl->power) | 426 | if (icl->power) |
@@ -437,7 +445,11 @@ static int soc_camera_close(struct file *file) | |||
437 | if (!icd->use_count) { | 445 | if (!icd->use_count) { |
438 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 446 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
439 | 447 | ||
448 | pm_runtime_suspend(&icd->vdev->dev); | ||
449 | pm_runtime_disable(&icd->vdev->dev); | ||
450 | |||
440 | ici->ops->remove(icd); | 451 | ici->ops->remove(icd); |
452 | |||
441 | if (icl->power) | 453 | if (icl->power) |
442 | icl->power(icd->pdev, 0); | 454 | icl->power(icd->pdev, 0); |
443 | } | 455 | } |
@@ -741,8 +753,7 @@ static int soc_camera_g_crop(struct file *file, void *fh, | |||
741 | /* | 753 | /* |
742 | * According to the V4L2 API, drivers shall not update the struct v4l2_crop | 754 | * According to the V4L2 API, drivers shall not update the struct v4l2_crop |
743 | * argument with the actual geometry, instead, the user shall use G_CROP to | 755 | * argument with the actual geometry, instead, the user shall use G_CROP to |
744 | * retrieve it. However, we expect camera host and client drivers to update | 756 | * retrieve it. |
745 | * the argument, which we then use internally, but do not return to the user. | ||
746 | */ | 757 | */ |
747 | static int soc_camera_s_crop(struct file *file, void *fh, | 758 | static int soc_camera_s_crop(struct file *file, void *fh, |
748 | struct v4l2_crop *a) | 759 | struct v4l2_crop *a) |
@@ -1319,6 +1330,7 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1319 | */ | 1330 | */ |
1320 | static int soc_camera_video_start(struct soc_camera_device *icd) | 1331 | static int soc_camera_video_start(struct soc_camera_device *icd) |
1321 | { | 1332 | { |
1333 | struct device_type *type = icd->vdev->dev.type; | ||
1322 | int ret; | 1334 | int ret; |
1323 | 1335 | ||
1324 | if (!icd->dev.parent) | 1336 | if (!icd->dev.parent) |
@@ -1335,6 +1347,9 @@ static int soc_camera_video_start(struct soc_camera_device *icd) | |||
1335 | return ret; | 1347 | return ret; |
1336 | } | 1348 | } |
1337 | 1349 | ||
1350 | /* Restore device type, possibly set by the subdevice driver */ | ||
1351 | icd->vdev->dev.type = type; | ||
1352 | |||
1338 | return 0; | 1353 | return 0; |
1339 | } | 1354 | } |
1340 | 1355 | ||
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c index ebd9cb5bec74..edd78f8b1baa 100644 --- a/drivers/media/video/tlg2300/pd-dvb.c +++ b/drivers/media/video/tlg2300/pd-dvb.c | |||
@@ -97,15 +97,17 @@ open_out: | |||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | #ifdef CONFIG_PM | ||
100 | static void poseidon_fe_release(struct dvb_frontend *fe) | 101 | static void poseidon_fe_release(struct dvb_frontend *fe) |
101 | { | 102 | { |
102 | struct poseidon *pd = fe->demodulator_priv; | 103 | struct poseidon *pd = fe->demodulator_priv; |
103 | 104 | ||
104 | #ifdef CONFIG_PM | ||
105 | pd->pm_suspend = NULL; | 105 | pd->pm_suspend = NULL; |
106 | pd->pm_resume = NULL; | 106 | pd->pm_resume = NULL; |
107 | #endif | ||
108 | } | 107 | } |
108 | #else | ||
109 | #define poseidon_fe_release NULL | ||
110 | #endif | ||
109 | 111 | ||
110 | static s32 poseidon_fe_sleep(struct dvb_frontend *fe) | 112 | static s32 poseidon_fe_sleep(struct dvb_frontend *fe) |
111 | { | 113 | { |
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index 2cf0ebf9f28b..c267e0cfb54b 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/version.h> | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
29 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
30 | #include <linux/init.h> | 29 | #include <linux/init.h> |
@@ -55,8 +54,8 @@ int debug_mode; | |||
55 | module_param(debug_mode, int, 0644); | 54 | module_param(debug_mode, int, 0644); |
56 | MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); | 55 | MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); |
57 | 56 | ||
58 | const char *firmware_name = "tlg2300_firmware.bin"; | 57 | static const char *firmware_name = "tlg2300_firmware.bin"; |
59 | struct usb_driver poseidon_driver; | 58 | static struct usb_driver poseidon_driver; |
60 | static LIST_HEAD(pd_device_list); | 59 | static LIST_HEAD(pd_device_list); |
61 | 60 | ||
62 | /* | 61 | /* |
@@ -501,7 +500,7 @@ static void poseidon_disconnect(struct usb_interface *interface) | |||
501 | kref_put(&pd->kref, poseidon_delete); | 500 | kref_put(&pd->kref, poseidon_delete); |
502 | } | 501 | } |
503 | 502 | ||
504 | struct usb_driver poseidon_driver = { | 503 | static struct usb_driver poseidon_driver = { |
505 | .name = "poseidon", | 504 | .name = "poseidon", |
506 | .probe = poseidon_probe, | 505 | .probe = poseidon_probe, |
507 | .disconnect = poseidon_disconnect, | 506 | .disconnect = poseidon_disconnect, |
diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c index 755766b15157..fae84c2a0c39 100644 --- a/drivers/media/video/tlg2300/pd-radio.c +++ b/drivers/media/video/tlg2300/pd-radio.c | |||
@@ -161,7 +161,8 @@ static const struct v4l2_file_operations poseidon_fm_fops = { | |||
161 | .ioctl = video_ioctl2, | 161 | .ioctl = video_ioctl2, |
162 | }; | 162 | }; |
163 | 163 | ||
164 | int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | 164 | static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, |
165 | struct v4l2_tuner *vt) | ||
165 | { | 166 | { |
166 | struct tuner_fm_sig_stat_s fm_stat = {}; | 167 | struct tuner_fm_sig_stat_s fm_stat = {}; |
167 | int ret, status, count = 5; | 168 | int ret, status, count = 5; |
@@ -203,7 +204,8 @@ int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | |||
203 | return 0; | 204 | return 0; |
204 | } | 205 | } |
205 | 206 | ||
206 | int fm_get_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | 207 | static int fm_get_freq(struct file *file, void *priv, |
208 | struct v4l2_frequency *argp) | ||
207 | { | 209 | { |
208 | struct poseidon *p = file->private_data; | 210 | struct poseidon *p = file->private_data; |
209 | 211 | ||
@@ -246,7 +248,8 @@ error: | |||
246 | return ret; | 248 | return ret; |
247 | } | 249 | } |
248 | 250 | ||
249 | int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | 251 | static int fm_set_freq(struct file *file, void *priv, |
252 | struct v4l2_frequency *argp) | ||
250 | { | 253 | { |
251 | struct poseidon *p = file->private_data; | 254 | struct poseidon *p = file->private_data; |
252 | 255 | ||
@@ -258,13 +261,13 @@ int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | |||
258 | return set_frequency(p, argp->frequency); | 261 | return set_frequency(p, argp->frequency); |
259 | } | 262 | } |
260 | 263 | ||
261 | int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, | 264 | static int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, |
262 | struct v4l2_control *arg) | 265 | struct v4l2_control *arg) |
263 | { | 266 | { |
264 | return 0; | 267 | return 0; |
265 | } | 268 | } |
266 | 269 | ||
267 | int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, | 270 | static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, |
268 | struct v4l2_ext_controls *ctrls) | 271 | struct v4l2_ext_controls *ctrls) |
269 | { | 272 | { |
270 | struct poseidon *p = file->private_data; | 273 | struct poseidon *p = file->private_data; |
@@ -285,7 +288,7 @@ int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, | |||
285 | return 0; | 288 | return 0; |
286 | } | 289 | } |
287 | 290 | ||
288 | int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, | 291 | static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, |
289 | struct v4l2_ext_controls *ctrls) | 292 | struct v4l2_ext_controls *ctrls) |
290 | { | 293 | { |
291 | int i; | 294 | int i; |
@@ -312,13 +315,13 @@ int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, | |||
312 | return 0; | 315 | return 0; |
313 | } | 316 | } |
314 | 317 | ||
315 | int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, | 318 | static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, |
316 | struct v4l2_control *ctrl) | 319 | struct v4l2_control *ctrl) |
317 | { | 320 | { |
318 | return 0; | 321 | return 0; |
319 | } | 322 | } |
320 | 323 | ||
321 | int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, | 324 | static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, |
322 | struct v4l2_queryctrl *ctrl) | 325 | struct v4l2_queryctrl *ctrl) |
323 | { | 326 | { |
324 | if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) | 327 | if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) |
@@ -337,7 +340,7 @@ int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, | |||
337 | return -EINVAL; | 340 | return -EINVAL; |
338 | } | 341 | } |
339 | 342 | ||
340 | int tlg_fm_vidioc_querymenu(struct file *file, void *fh, | 343 | static int tlg_fm_vidioc_querymenu(struct file *file, void *fh, |
341 | struct v4l2_querymenu *qmenu) | 344 | struct v4l2_querymenu *qmenu) |
342 | { | 345 | { |
343 | return v4l2_ctrl_query_menu(qmenu, NULL, NULL); | 346 | return v4l2_ctrl_query_menu(qmenu, NULL, NULL); |
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c index cf8f18c007e6..c750fd115ec4 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/video/tlg2300/pd-video.c | |||
@@ -12,11 +12,13 @@ | |||
12 | #include "pd-common.h" | 12 | #include "pd-common.h" |
13 | #include "vendorcmds.h" | 13 | #include "vendorcmds.h" |
14 | 14 | ||
15 | #ifdef CONFIG_PM | ||
15 | static int pm_video_suspend(struct poseidon *pd); | 16 | static int pm_video_suspend(struct poseidon *pd); |
16 | static int pm_video_resume(struct poseidon *pd); | 17 | static int pm_video_resume(struct poseidon *pd); |
18 | #endif | ||
17 | static void iso_bubble_handler(struct work_struct *w); | 19 | static void iso_bubble_handler(struct work_struct *w); |
18 | 20 | ||
19 | int usb_transfer_mode; | 21 | static int usb_transfer_mode; |
20 | module_param(usb_transfer_mode, int, 0644); | 22 | module_param(usb_transfer_mode, int, 0644); |
21 | MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); | 23 | MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); |
22 | 24 | ||
@@ -617,7 +619,7 @@ static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
617 | return 0; | 619 | return 0; |
618 | } | 620 | } |
619 | 621 | ||
620 | int fire_all_urb(struct video_data *video) | 622 | static int fire_all_urb(struct video_data *video) |
621 | { | 623 | { |
622 | int i, ret; | 624 | int i, ret; |
623 | 625 | ||
@@ -877,7 +879,7 @@ out: | |||
877 | return ret; | 879 | return ret; |
878 | } | 880 | } |
879 | 881 | ||
880 | int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) | 882 | static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) |
881 | { | 883 | { |
882 | struct front_face *front = fh; | 884 | struct front_face *front = fh; |
883 | logs(front); | 885 | logs(front); |
@@ -1020,7 +1022,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) | |||
1020 | return 0; | 1022 | return 0; |
1021 | } | 1023 | } |
1022 | 1024 | ||
1023 | int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | 1025 | static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) |
1024 | { | 1026 | { |
1025 | a->index = 0; | 1027 | a->index = 0; |
1026 | a->capability = V4L2_AUDCAP_STEREO; | 1028 | a->capability = V4L2_AUDCAP_STEREO; |
@@ -1029,7 +1031,7 @@ int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | |||
1029 | return 0; | 1031 | return 0; |
1030 | } | 1032 | } |
1031 | 1033 | ||
1032 | int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) | 1034 | static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) |
1033 | { | 1035 | { |
1034 | return (0 == a->index) ? 0 : -EINVAL; | 1036 | return (0 == a->index) ? 0 : -EINVAL; |
1035 | } | 1037 | } |
@@ -1189,7 +1191,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) | |||
1189 | } | 1191 | } |
1190 | 1192 | ||
1191 | /* Just stop the URBs, do not free the URBs */ | 1193 | /* Just stop the URBs, do not free the URBs */ |
1192 | int usb_transfer_stop(struct video_data *video) | 1194 | static int usb_transfer_stop(struct video_data *video) |
1193 | { | 1195 | { |
1194 | if (video->is_streaming) { | 1196 | if (video->is_streaming) { |
1195 | int i; | 1197 | int i; |
@@ -1518,13 +1520,13 @@ static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) | |||
1518 | return videobuf_mmap_mapper(&front->q, vma); | 1520 | return videobuf_mmap_mapper(&front->q, vma); |
1519 | } | 1521 | } |
1520 | 1522 | ||
1521 | unsigned int pd_video_poll(struct file *file, poll_table *table) | 1523 | static unsigned int pd_video_poll(struct file *file, poll_table *table) |
1522 | { | 1524 | { |
1523 | struct front_face *front = file->private_data; | 1525 | struct front_face *front = file->private_data; |
1524 | return videobuf_poll_stream(file, &front->q, table); | 1526 | return videobuf_poll_stream(file, &front->q, table); |
1525 | } | 1527 | } |
1526 | 1528 | ||
1527 | ssize_t pd_video_read(struct file *file, char __user *buffer, | 1529 | static ssize_t pd_video_read(struct file *file, char __user *buffer, |
1528 | size_t count, loff_t *ppos) | 1530 | size_t count, loff_t *ppos) |
1529 | { | 1531 | { |
1530 | struct front_face *front = file->private_data; | 1532 | struct front_face *front = file->private_data; |
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index e4815a1806e3..e826114b7fb8 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c | |||
@@ -79,6 +79,8 @@ struct tvp514x_std_info { | |||
79 | }; | 79 | }; |
80 | 80 | ||
81 | static struct tvp514x_reg tvp514x_reg_list_default[0x40]; | 81 | static struct tvp514x_reg tvp514x_reg_list_default[0x40]; |
82 | |||
83 | static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); | ||
82 | /** | 84 | /** |
83 | * struct tvp514x_decoder - TVP5146/47 decoder object | 85 | * struct tvp514x_decoder - TVP5146/47 decoder object |
84 | * @sd: Subdevice Slave handle | 86 | * @sd: Subdevice Slave handle |
@@ -644,6 +646,17 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, | |||
644 | /* Index out of bound */ | 646 | /* Index out of bound */ |
645 | return -EINVAL; | 647 | return -EINVAL; |
646 | 648 | ||
649 | /* | ||
650 | * For the sequence streamon -> streamoff and again s_input | ||
651 | * it fails to lock the signal, since streamoff puts TVP514x | ||
652 | * into power off state which leads to failure in sub-sequent s_input. | ||
653 | * | ||
654 | * So power up the TVP514x device here, since it is important to lock | ||
655 | * the signal at this stage. | ||
656 | */ | ||
657 | if (!decoder->streaming) | ||
658 | tvp514x_s_stream(sd, 1); | ||
659 | |||
647 | input_sel = input; | 660 | input_sel = input; |
648 | output_sel = output; | 661 | output_sel = output; |
649 | 662 | ||
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 908ffb68e926..47f0582d50a5 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -891,29 +891,26 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd, | |||
891 | return 0; | 891 | return 0; |
892 | } | 892 | } |
893 | 893 | ||
894 | static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 894 | static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) |
895 | { | ||
896 | /* this is for capturing 36 raw vbi lines | ||
897 | if there's a way to cut off the beginning 2 vbi lines | ||
898 | with the tvp5150 then the vbi line count could be lowered | ||
899 | to 17 lines/field again, although I couldn't find a register | ||
900 | which could do that cropping */ | ||
901 | if (fmt->sample_format == V4L2_PIX_FMT_GREY) | ||
902 | tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); | ||
903 | if (fmt->count[0] == 18 && fmt->count[1] == 18) { | ||
904 | tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); | ||
905 | tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); | ||
906 | } | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) | ||
895 | { | 911 | { |
896 | struct v4l2_sliced_vbi_format *svbi; | ||
897 | int i; | 912 | int i; |
898 | 913 | ||
899 | /* raw vbi */ | ||
900 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
901 | /* this is for capturing 36 raw vbi lines | ||
902 | if there's a way to cut off the beginning 2 vbi lines | ||
903 | with the tvp5150 then the vbi line count could be lowered | ||
904 | to 17 lines/field again, although I couldn't find a register | ||
905 | which could do that cropping */ | ||
906 | if (fmt->fmt.vbi.sample_format == V4L2_PIX_FMT_GREY) | ||
907 | tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); | ||
908 | if (fmt->fmt.vbi.count[0] == 18 && fmt->fmt.vbi.count[1] == 18) { | ||
909 | tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); | ||
910 | tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); | ||
911 | } | ||
912 | return 0; | ||
913 | } | ||
914 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
915 | return -EINVAL; | ||
916 | svbi = &fmt->fmt.sliced; | ||
917 | if (svbi->service_set != 0) { | 914 | if (svbi->service_set != 0) { |
918 | for (i = 0; i <= 23; i++) { | 915 | for (i = 0; i <= 23; i++) { |
919 | svbi->service_lines[1][i] = 0; | 916 | svbi->service_lines[1][i] = 0; |
@@ -937,14 +934,21 @@ static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
937 | return 0; | 934 | return 0; |
938 | } | 935 | } |
939 | 936 | ||
940 | static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 937 | static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
941 | { | 938 | { |
942 | struct v4l2_sliced_vbi_format *svbi; | 939 | switch (fmt->type) { |
943 | int i, mask = 0; | 940 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: |
941 | return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced); | ||
944 | 942 | ||
945 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | 943 | default: |
946 | return -EINVAL; | 944 | return -EINVAL; |
947 | svbi = &fmt->fmt.sliced; | 945 | } |
946 | } | ||
947 | |||
948 | static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) | ||
949 | { | ||
950 | int i, mask = 0; | ||
951 | |||
948 | memset(svbi, 0, sizeof(*svbi)); | 952 | memset(svbi, 0, sizeof(*svbi)); |
949 | 953 | ||
950 | for (i = 0; i <= 23; i++) { | 954 | for (i = 0; i <= 23; i++) { |
@@ -956,6 +960,12 @@ static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | |||
956 | return 0; | 960 | return 0; |
957 | } | 961 | } |
958 | 962 | ||
963 | static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
964 | { | ||
965 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
966 | return -EINVAL; | ||
967 | return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced); | ||
968 | } | ||
959 | 969 | ||
960 | static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, | 970 | static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, |
961 | struct v4l2_dbg_chip_ident *chip) | 971 | struct v4l2_dbg_chip_ident *chip) |
@@ -1046,13 +1056,20 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { | |||
1046 | .s_routing = tvp5150_s_routing, | 1056 | .s_routing = tvp5150_s_routing, |
1047 | .g_fmt = tvp5150_g_fmt, | 1057 | .g_fmt = tvp5150_g_fmt, |
1048 | .s_fmt = tvp5150_s_fmt, | 1058 | .s_fmt = tvp5150_s_fmt, |
1059 | }; | ||
1060 | |||
1061 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { | ||
1049 | .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, | 1062 | .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, |
1063 | .g_sliced_fmt = tvp5150_g_sliced_fmt, | ||
1064 | .s_sliced_fmt = tvp5150_s_sliced_fmt, | ||
1065 | .s_raw_fmt = tvp5150_s_raw_fmt, | ||
1050 | }; | 1066 | }; |
1051 | 1067 | ||
1052 | static const struct v4l2_subdev_ops tvp5150_ops = { | 1068 | static const struct v4l2_subdev_ops tvp5150_ops = { |
1053 | .core = &tvp5150_core_ops, | 1069 | .core = &tvp5150_core_ops, |
1054 | .tuner = &tvp5150_tuner_ops, | 1070 | .tuner = &tvp5150_tuner_ops, |
1055 | .video = &tvp5150_video_ops, | 1071 | .video = &tvp5150_video_ops, |
1072 | .vbi = &tvp5150_vbi_ops, | ||
1056 | }; | 1073 | }; |
1057 | 1074 | ||
1058 | 1075 | ||
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index 4a69bcc738f3..8085ac392446 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c | |||
@@ -458,7 +458,7 @@ static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd) | |||
458 | /* | 458 | /* |
459 | * tvp7002_read - Read a value from a register in an TVP7002 | 459 | * tvp7002_read - Read a value from a register in an TVP7002 |
460 | * @sd: ptr to v4l2_subdev struct | 460 | * @sd: ptr to v4l2_subdev struct |
461 | * @reg: TVP7002 register address | 461 | * @addr: TVP7002 register address |
462 | * @dst: pointer to 8-bit destination | 462 | * @dst: pointer to 8-bit destination |
463 | * | 463 | * |
464 | * Returns value read if successful, or non-zero (-1) otherwise. | 464 | * Returns value read if successful, or non-zero (-1) otherwise. |
@@ -488,7 +488,7 @@ static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst) | |||
488 | * @sd: pointer to standard V4L2 sub-device structure | 488 | * @sd: pointer to standard V4L2 sub-device structure |
489 | * @reg: destination register | 489 | * @reg: destination register |
490 | * @val: value to be read | 490 | * @val: value to be read |
491 | * @error: pointer to error value | 491 | * @err: pointer to error value |
492 | * | 492 | * |
493 | * Read a value in a register and save error value in pointer. | 493 | * Read a value in a register and save error value in pointer. |
494 | * Also update the register table if successful | 494 | * Also update the register table if successful |
@@ -535,7 +535,7 @@ static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value) | |||
535 | * @sd: pointer to standard V4L2 sub-device structure | 535 | * @sd: pointer to standard V4L2 sub-device structure |
536 | * @reg: destination register | 536 | * @reg: destination register |
537 | * @val: value to be written | 537 | * @val: value to be written |
538 | * @error: pointer to error value | 538 | * @err: pointer to error value |
539 | * | 539 | * |
540 | * Write a value in a register and save error value in pointer. | 540 | * Write a value in a register and save error value in pointer. |
541 | * Also update the register table if successful | 541 | * Also update the register table if successful |
@@ -596,7 +596,7 @@ static int tvp7002_write_inittab(struct v4l2_subdev *sd, | |||
596 | /* | 596 | /* |
597 | * tvp7002_s_dv_preset() - Set digital video preset | 597 | * tvp7002_s_dv_preset() - Set digital video preset |
598 | * @sd: ptr to v4l2_subdev struct | 598 | * @sd: ptr to v4l2_subdev struct |
599 | * @std: ptr to v4l2_dv_preset struct | 599 | * @dv_preset: ptr to v4l2_dv_preset struct |
600 | * | 600 | * |
601 | * Set the digital video preset for a TVP7002 decoder device. | 601 | * Set the digital video preset for a TVP7002 decoder device. |
602 | * Returns zero when successful or -EINVAL if register access fails. | 602 | * Returns zero when successful or -EINVAL if register access fails. |
@@ -676,7 +676,7 @@ static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
676 | /* | 676 | /* |
677 | * tvp7002_queryctrl() - Query a control | 677 | * tvp7002_queryctrl() - Query a control |
678 | * @sd: ptr to v4l2_subdev struct | 678 | * @sd: ptr to v4l2_subdev struct |
679 | * @ctrl: ptr to v4l2_queryctrl struct | 679 | * @qc: ptr to v4l2_queryctrl struct |
680 | * | 680 | * |
681 | * Query a control of a TVP7002 decoder device. | 681 | * Query a control of a TVP7002 decoder device. |
682 | * Returns zero when successful or -EINVAL if register read fails. | 682 | * Returns zero when successful or -EINVAL if register read fails. |
@@ -776,7 +776,7 @@ static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
776 | /* | 776 | /* |
777 | * tvp7002_query_dv_preset() - query DV preset | 777 | * tvp7002_query_dv_preset() - query DV preset |
778 | * @sd: pointer to standard V4L2 sub-device structure | 778 | * @sd: pointer to standard V4L2 sub-device structure |
779 | * @std_id: standard V4L2 v4l2_dv_preset | 779 | * @qpreset: standard V4L2 v4l2_dv_preset structure |
780 | * | 780 | * |
781 | * Returns the current DV preset by TVP7002. If no active input is | 781 | * Returns the current DV preset by TVP7002. If no active input is |
782 | * detected, returns -EINVAL | 782 | * detected, returns -EINVAL |
@@ -785,7 +785,6 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | |||
785 | struct v4l2_dv_preset *qpreset) | 785 | struct v4l2_dv_preset *qpreset) |
786 | { | 786 | { |
787 | const struct tvp7002_preset_definition *presets = tvp7002_presets; | 787 | const struct tvp7002_preset_definition *presets = tvp7002_presets; |
788 | struct v4l2_dv_enum_preset e_preset; | ||
789 | struct tvp7002 *device; | 788 | struct tvp7002 *device; |
790 | u8 progressive; | 789 | u8 progressive; |
791 | u32 lpfr; | 790 | u32 lpfr; |
@@ -828,20 +827,18 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | |||
828 | } | 827 | } |
829 | 828 | ||
830 | if (index == NUM_PRESETS) { | 829 | if (index == NUM_PRESETS) { |
831 | v4l2_err(sd, "querystd error, lpf = %x, cpl = %x\n", | 830 | v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n", |
832 | lpfr, cpln); | 831 | lpfr, cpln); |
833 | return -EINVAL; | 832 | /* Could not detect a signal, so return the 'invalid' preset */ |
833 | qpreset->preset = V4L2_DV_INVALID; | ||
834 | return 0; | ||
834 | } | 835 | } |
835 | 836 | ||
836 | if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) | ||
837 | return -EINVAL; | ||
838 | |||
839 | /* Set values in found preset */ | 837 | /* Set values in found preset */ |
840 | qpreset->preset = presets->preset; | 838 | qpreset->preset = presets->preset; |
841 | 839 | ||
842 | /* Update lines per frame and clocks per line info */ | 840 | /* Update lines per frame and clocks per line info */ |
843 | v4l2_dbg(1, debug, sd, "Current preset: %d %d", | 841 | v4l2_dbg(1, debug, sd, "detected preset: %d\n", presets->preset); |
844 | e_preset.width, e_preset.height); | ||
845 | return 0; | 842 | return 0; |
846 | } | 843 | } |
847 | 844 | ||
@@ -849,7 +846,7 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | |||
849 | /* | 846 | /* |
850 | * tvp7002_g_register() - Get the value of a register | 847 | * tvp7002_g_register() - Get the value of a register |
851 | * @sd: ptr to v4l2_subdev struct | 848 | * @sd: ptr to v4l2_subdev struct |
852 | * @vreg: ptr to v4l2_dbg_register struct | 849 | * @reg: ptr to v4l2_dbg_register struct |
853 | * | 850 | * |
854 | * Get the value of a TVP7002 decoder device register. | 851 | * Get the value of a TVP7002 decoder device register. |
855 | * Returns zero when successful, -EINVAL if register read fails or | 852 | * Returns zero when successful, -EINVAL if register read fails or |
@@ -876,7 +873,7 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, | |||
876 | /* | 873 | /* |
877 | * tvp7002_s_register() - set a control | 874 | * tvp7002_s_register() - set a control |
878 | * @sd: ptr to v4l2_subdev struct | 875 | * @sd: ptr to v4l2_subdev struct |
879 | * @ctrl: ptr to v4l2_control struct | 876 | * @reg: ptr to v4l2_dbg_register struct |
880 | * | 877 | * |
881 | * Get the value of a TVP7002 decoder device register. | 878 | * Get the value of a TVP7002 decoder device register. |
882 | * Returns zero when successful, -EINVAL if register read fails or | 879 | * Returns zero when successful, -EINVAL if register read fails or |
@@ -899,7 +896,7 @@ static int tvp7002_s_register(struct v4l2_subdev *sd, | |||
899 | /* | 896 | /* |
900 | * tvp7002_enum_fmt() - Enum supported formats | 897 | * tvp7002_enum_fmt() - Enum supported formats |
901 | * @sd: pointer to standard V4L2 sub-device structure | 898 | * @sd: pointer to standard V4L2 sub-device structure |
902 | * @enable: pointer to format struct | 899 | * @fmtdesc: pointer to format struct |
903 | * | 900 | * |
904 | * Enumerate supported formats. | 901 | * Enumerate supported formats. |
905 | */ | 902 | */ |
@@ -994,6 +991,23 @@ static int tvp7002_log_status(struct v4l2_subdev *sd) | |||
994 | return 0; | 991 | return 0; |
995 | } | 992 | } |
996 | 993 | ||
994 | /* | ||
995 | * tvp7002_enum_dv_presets() - Enum supported digital video formats | ||
996 | * @sd: pointer to standard V4L2 sub-device structure | ||
997 | * @preset: pointer to format struct | ||
998 | * | ||
999 | * Enumerate supported digital video formats. | ||
1000 | */ | ||
1001 | static int tvp7002_enum_dv_presets(struct v4l2_subdev *sd, | ||
1002 | struct v4l2_dv_enum_preset *preset) | ||
1003 | { | ||
1004 | /* Check requested format index is within range */ | ||
1005 | if (preset->index >= NUM_PRESETS) | ||
1006 | return -EINVAL; | ||
1007 | |||
1008 | return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset); | ||
1009 | } | ||
1010 | |||
997 | /* V4L2 core operation handlers */ | 1011 | /* V4L2 core operation handlers */ |
998 | static const struct v4l2_subdev_core_ops tvp7002_core_ops = { | 1012 | static const struct v4l2_subdev_core_ops tvp7002_core_ops = { |
999 | .g_chip_ident = tvp7002_g_chip_ident, | 1013 | .g_chip_ident = tvp7002_g_chip_ident, |
@@ -1009,6 +1023,7 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { | |||
1009 | 1023 | ||
1010 | /* Specific video subsystem operation handlers */ | 1024 | /* Specific video subsystem operation handlers */ |
1011 | static const struct v4l2_subdev_video_ops tvp7002_video_ops = { | 1025 | static const struct v4l2_subdev_video_ops tvp7002_video_ops = { |
1026 | .enum_dv_presets = tvp7002_enum_dv_presets, | ||
1012 | .s_dv_preset = tvp7002_s_dv_preset, | 1027 | .s_dv_preset = tvp7002_s_dv_preset, |
1013 | .query_dv_preset = tvp7002_query_dv_preset, | 1028 | .query_dv_preset = tvp7002_query_dv_preset, |
1014 | .s_stream = tvp7002_s_stream, | 1029 | .s_stream = tvp7002_s_stream, |
@@ -1042,8 +1057,8 @@ static struct tvp7002 tvp7002_dev = { | |||
1042 | 1057 | ||
1043 | /* | 1058 | /* |
1044 | * tvp7002_probe - Probe a TVP7002 device | 1059 | * tvp7002_probe - Probe a TVP7002 device |
1045 | * @sd: ptr to v4l2_subdev struct | 1060 | * @c: ptr to i2c_client struct |
1046 | * @ctrl: ptr to i2c_device_id struct | 1061 | * @id: ptr to i2c_device_id struct |
1047 | * | 1062 | * |
1048 | * Initialize the TVP7002 device | 1063 | * Initialize the TVP7002 device |
1049 | * Returns zero when successful, -EINVAL if register read fails or | 1064 | * Returns zero when successful, -EINVAL if register read fails or |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index fab48ec6c0ea..fbd665fa1979 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -693,12 +693,13 @@ static int qcm_start_data(struct uvd *uvd) | |||
693 | 693 | ||
694 | static void qcm_stop_data(struct uvd *uvd) | 694 | static void qcm_stop_data(struct uvd *uvd) |
695 | { | 695 | { |
696 | struct qcm *cam = (struct qcm *) uvd->user_data; | 696 | struct qcm *cam; |
697 | int i, j; | 697 | int i, j; |
698 | int ret; | 698 | int ret; |
699 | 699 | ||
700 | if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) | 700 | if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) |
701 | return; | 701 | return; |
702 | cam = (struct qcm *) uvd->user_data; | ||
702 | 703 | ||
703 | ret = qcm_camera_off(uvd); | 704 | ret = qcm_camera_off(uvd); |
704 | if (ret) | 705 | if (ret) |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 083765238a6a..42ba28785750 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -244,6 +244,9 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) | |||
244 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | 244 | switch (usbvision_device_data[usbvision->DevModel].Codec) { |
245 | case CODEC_SAA7113: | 245 | case CODEC_SAA7113: |
246 | case CODEC_SAA7111: | 246 | case CODEC_SAA7111: |
247 | /* Without this delay the detection of the saa711x is | ||
248 | hit-and-miss. */ | ||
249 | mdelay(10); | ||
247 | v4l2_i2c_new_subdev(&usbvision->v4l2_dev, | 250 | v4l2_i2c_new_subdev(&usbvision->v4l2_dev, |
248 | &usbvision->i2c_adap, "saa7115", | 251 | &usbvision->i2c_adap, "saa7115", |
249 | "saa7115_auto", 0, saa711x_addrs); | 252 | "saa7115_auto", 0, saa711x_addrs); |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 7c17ec63c5da..6248a639ba2d 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -137,8 +137,6 @@ static int PowerOnAtOpen = 1; | |||
137 | static int video_nr = -1; | 137 | static int video_nr = -1; |
138 | /* Sequential Number of Radio Device */ | 138 | /* Sequential Number of Radio Device */ |
139 | static int radio_nr = -1; | 139 | static int radio_nr = -1; |
140 | /* Sequential Number of VBI Device */ | ||
141 | static int vbi_nr = -1; | ||
142 | 140 | ||
143 | /* Grab parameters for the device driver */ | 141 | /* Grab parameters for the device driver */ |
144 | 142 | ||
@@ -148,14 +146,12 @@ module_param(video_debug, int, 0444); | |||
148 | module_param(PowerOnAtOpen, int, 0444); | 146 | module_param(PowerOnAtOpen, int, 0444); |
149 | module_param(video_nr, int, 0444); | 147 | module_param(video_nr, int, 0444); |
150 | module_param(radio_nr, int, 0444); | 148 | module_param(radio_nr, int, 0444); |
151 | module_param(vbi_nr, int, 0444); | ||
152 | 149 | ||
153 | MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); | 150 | MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); |
154 | MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); | 151 | MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); |
155 | MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); | 152 | MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); |
156 | MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); | 153 | MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); |
157 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); | 154 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); |
158 | MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); | ||
159 | 155 | ||
160 | 156 | ||
161 | // Misc stuff | 157 | // Misc stuff |
@@ -1244,36 +1240,6 @@ static int usbvision_radio_close(struct file *file) | |||
1244 | return errCode; | 1240 | return errCode; |
1245 | } | 1241 | } |
1246 | 1242 | ||
1247 | /* | ||
1248 | * Here comes the stuff for vbi on usbvision based devices | ||
1249 | * | ||
1250 | */ | ||
1251 | static int usbvision_vbi_open(struct file *file) | ||
1252 | { | ||
1253 | /* TODO */ | ||
1254 | return -ENODEV; | ||
1255 | } | ||
1256 | |||
1257 | static int usbvision_vbi_close(struct file *file) | ||
1258 | { | ||
1259 | /* TODO */ | ||
1260 | return -ENODEV; | ||
1261 | } | ||
1262 | |||
1263 | static long usbvision_do_vbi_ioctl(struct file *file, | ||
1264 | unsigned int cmd, void *arg) | ||
1265 | { | ||
1266 | /* TODO */ | ||
1267 | return -ENOIOCTLCMD; | ||
1268 | } | ||
1269 | |||
1270 | static long usbvision_vbi_ioctl(struct file *file, | ||
1271 | unsigned int cmd, unsigned long arg) | ||
1272 | { | ||
1273 | return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl); | ||
1274 | } | ||
1275 | |||
1276 | |||
1277 | // | 1243 | // |
1278 | // Video registration stuff | 1244 | // Video registration stuff |
1279 | // | 1245 | // |
@@ -1367,21 +1333,6 @@ static struct video_device usbvision_radio_template = { | |||
1367 | .current_norm = V4L2_STD_PAL | 1333 | .current_norm = V4L2_STD_PAL |
1368 | }; | 1334 | }; |
1369 | 1335 | ||
1370 | // vbi template | ||
1371 | static const struct v4l2_file_operations usbvision_vbi_fops = { | ||
1372 | .owner = THIS_MODULE, | ||
1373 | .open = usbvision_vbi_open, | ||
1374 | .release = usbvision_vbi_close, | ||
1375 | .ioctl = usbvision_vbi_ioctl, | ||
1376 | }; | ||
1377 | |||
1378 | static struct video_device usbvision_vbi_template= | ||
1379 | { | ||
1380 | .fops = &usbvision_vbi_fops, | ||
1381 | .release = video_device_release, | ||
1382 | .name = "usbvision-vbi", | ||
1383 | }; | ||
1384 | |||
1385 | 1336 | ||
1386 | static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | 1337 | static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, |
1387 | struct video_device *vdev_template, | 1338 | struct video_device *vdev_template, |
@@ -1410,18 +1361,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | |||
1410 | // unregister video4linux devices | 1361 | // unregister video4linux devices |
1411 | static void usbvision_unregister_video(struct usb_usbvision *usbvision) | 1362 | static void usbvision_unregister_video(struct usb_usbvision *usbvision) |
1412 | { | 1363 | { |
1413 | // vbi Device: | ||
1414 | if (usbvision->vbi) { | ||
1415 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", | ||
1416 | video_device_node_name(usbvision->vbi)); | ||
1417 | if (video_is_registered(usbvision->vbi)) { | ||
1418 | video_unregister_device(usbvision->vbi); | ||
1419 | } else { | ||
1420 | video_device_release(usbvision->vbi); | ||
1421 | } | ||
1422 | usbvision->vbi = NULL; | ||
1423 | } | ||
1424 | |||
1425 | // Radio Device: | 1364 | // Radio Device: |
1426 | if (usbvision->rdev) { | 1365 | if (usbvision->rdev) { |
1427 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", | 1366 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", |
@@ -1482,22 +1421,6 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1482 | printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", | 1421 | printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", |
1483 | usbvision->nr, video_device_node_name(usbvision->rdev)); | 1422 | usbvision->nr, video_device_node_name(usbvision->rdev)); |
1484 | } | 1423 | } |
1485 | // vbi Device: | ||
1486 | if (usbvision_device_data[usbvision->DevModel].vbi) { | ||
1487 | usbvision->vbi = usbvision_vdev_init(usbvision, | ||
1488 | &usbvision_vbi_template, | ||
1489 | "USBVision VBI"); | ||
1490 | if (usbvision->vbi == NULL) { | ||
1491 | goto err_exit; | ||
1492 | } | ||
1493 | if (video_register_device(usbvision->vbi, | ||
1494 | VFL_TYPE_VBI, | ||
1495 | vbi_nr)<0) { | ||
1496 | goto err_exit; | ||
1497 | } | ||
1498 | printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device %s [v4l2] (Not Working Yet!)\n", | ||
1499 | usbvision->nr, video_device_node_name(usbvision->vbi)); | ||
1500 | } | ||
1501 | // all done | 1424 | // all done |
1502 | return 0; | 1425 | return 0; |
1503 | 1426 | ||
@@ -1726,8 +1649,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, | |||
1726 | usbvision_configure_video(usbvision); | 1649 | usbvision_configure_video(usbvision); |
1727 | mutex_unlock(&usbvision->lock); | 1650 | mutex_unlock(&usbvision->lock); |
1728 | 1651 | ||
1729 | |||
1730 | usb_set_intfdata (intf, usbvision); | ||
1731 | usbvision_create_sysfs(usbvision->vdev); | 1652 | usbvision_create_sysfs(usbvision->vdev); |
1732 | 1653 | ||
1733 | PDEBUG(DBG_PROBE, "success"); | 1654 | PDEBUG(DBG_PROBE, "success"); |
@@ -1745,7 +1666,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, | |||
1745 | */ | 1666 | */ |
1746 | static void __devexit usbvision_disconnect(struct usb_interface *intf) | 1667 | static void __devexit usbvision_disconnect(struct usb_interface *intf) |
1747 | { | 1668 | { |
1748 | struct usb_usbvision *usbvision = usb_get_intfdata(intf); | 1669 | struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); |
1749 | 1670 | ||
1750 | PDEBUG(DBG_PROBE, ""); | 1671 | PDEBUG(DBG_PROBE, ""); |
1751 | 1672 | ||
@@ -1754,7 +1675,6 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) | |||
1754 | "%s: usb_get_intfdata() failed\n", __func__); | 1675 | "%s: usb_get_intfdata() failed\n", __func__); |
1755 | return; | 1676 | return; |
1756 | } | 1677 | } |
1757 | usb_set_intfdata (intf, NULL); | ||
1758 | 1678 | ||
1759 | mutex_lock(&usbvision->lock); | 1679 | mutex_lock(&usbvision->lock); |
1760 | 1680 | ||
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index f8d7458daf3e..d1b3cc0cd87f 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -360,7 +360,6 @@ struct usb_usbvision { | |||
360 | struct v4l2_device v4l2_dev; | 360 | struct v4l2_device v4l2_dev; |
361 | struct video_device *vdev; /* Video Device */ | 361 | struct video_device *vdev; /* Video Device */ |
362 | struct video_device *rdev; /* Radio Device */ | 362 | struct video_device *rdev; /* Radio Device */ |
363 | struct video_device *vbi; /* VBI Device */ | ||
364 | 363 | ||
365 | /* i2c Declaration Section*/ | 364 | /* i2c Declaration Section*/ |
366 | struct i2c_adapter i2c_adap; | 365 | struct i2c_adapter i2c_adap; |
@@ -463,6 +462,11 @@ struct usb_usbvision { | |||
463 | int ComprBlockTypes[4]; | 462 | int ComprBlockTypes[4]; |
464 | }; | 463 | }; |
465 | 464 | ||
465 | static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev) | ||
466 | { | ||
467 | return container_of(v4l2_dev, struct usb_usbvision, v4l2_dev); | ||
468 | } | ||
469 | |||
466 | #define call_all(usbvision, o, f, args...) \ | 470 | #define call_all(usbvision, o, f, args...) \ |
467 | v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) | 471 | v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) |
468 | 472 | ||
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 6d3850b37161..aa0720af07a0 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -217,8 +217,7 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
217 | .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, | 217 | .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, |
218 | .index = 4, | 218 | .index = 4, |
219 | .size = 1, | 219 | .size = 1, |
220 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 220 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_RESTORE, |
221 | | UVC_CONTROL_RESTORE, | ||
222 | }, | 221 | }, |
223 | { | 222 | { |
224 | .entity = UVC_GUID_UVC_CAMERA, | 223 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -233,8 +232,9 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
233 | .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, | 232 | .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, |
234 | .index = 6, | 233 | .index = 6, |
235 | .size = 2, | 234 | .size = 2, |
236 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 235 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN |
237 | | UVC_CONTROL_AUTO_UPDATE, | 236 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES |
237 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | ||
238 | }, | 238 | }, |
239 | { | 239 | { |
240 | .entity = UVC_GUID_UVC_CAMERA, | 240 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -249,8 +249,7 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
249 | .selector = UVC_CT_IRIS_RELATIVE_CONTROL, | 249 | .selector = UVC_CT_IRIS_RELATIVE_CONTROL, |
250 | .index = 8, | 250 | .index = 8, |
251 | .size = 1, | 251 | .size = 1, |
252 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 252 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_AUTO_UPDATE, |
253 | | UVC_CONTROL_AUTO_UPDATE, | ||
254 | }, | 253 | }, |
255 | { | 254 | { |
256 | .entity = UVC_GUID_UVC_CAMERA, | 255 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -265,8 +264,9 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
265 | .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, | 264 | .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, |
266 | .index = 10, | 265 | .index = 10, |
267 | .size = 3, | 266 | .size = 3, |
268 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 267 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN |
269 | | UVC_CONTROL_AUTO_UPDATE, | 268 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES |
269 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | ||
270 | }, | 270 | }, |
271 | { | 271 | { |
272 | .entity = UVC_GUID_UVC_CAMERA, | 272 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -281,8 +281,9 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
281 | .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, | 281 | .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, |
282 | .index = 12, | 282 | .index = 12, |
283 | .size = 4, | 283 | .size = 4, |
284 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 284 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN |
285 | | UVC_CONTROL_AUTO_UPDATE, | 285 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES |
286 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | ||
286 | }, | 287 | }, |
287 | { | 288 | { |
288 | .entity = UVC_GUID_UVC_CAMERA, | 289 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -297,8 +298,9 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
297 | .selector = UVC_CT_ROLL_RELATIVE_CONTROL, | 298 | .selector = UVC_CT_ROLL_RELATIVE_CONTROL, |
298 | .index = 14, | 299 | .index = 14, |
299 | .size = 2, | 300 | .size = 2, |
300 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 301 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN |
301 | | UVC_CONTROL_AUTO_UPDATE, | 302 | | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES |
303 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, | ||
302 | }, | 304 | }, |
303 | { | 305 | { |
304 | .entity = UVC_GUID_UVC_CAMERA, | 306 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -562,6 +564,26 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { | |||
562 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | 564 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, |
563 | }, | 565 | }, |
564 | { | 566 | { |
567 | .id = V4L2_CID_IRIS_ABSOLUTE, | ||
568 | .name = "Iris, Absolute", | ||
569 | .entity = UVC_GUID_UVC_CAMERA, | ||
570 | .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, | ||
571 | .size = 16, | ||
572 | .offset = 0, | ||
573 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
574 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
575 | }, | ||
576 | { | ||
577 | .id = V4L2_CID_IRIS_RELATIVE, | ||
578 | .name = "Iris, Relative", | ||
579 | .entity = UVC_GUID_UVC_CAMERA, | ||
580 | .selector = UVC_CT_IRIS_RELATIVE_CONTROL, | ||
581 | .size = 8, | ||
582 | .offset = 0, | ||
583 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
584 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
585 | }, | ||
586 | { | ||
565 | .id = V4L2_CID_ZOOM_ABSOLUTE, | 587 | .id = V4L2_CID_ZOOM_ABSOLUTE, |
566 | .name = "Zoom, Absolute", | 588 | .name = "Zoom, Absolute", |
567 | .entity = UVC_GUID_UVC_CAMERA, | 589 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -822,6 +844,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
822 | strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); | 844 | strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); |
823 | v4l2_ctrl->flags = 0; | 845 | v4l2_ctrl->flags = 0; |
824 | 846 | ||
847 | if (!(ctrl->info->flags & UVC_CONTROL_GET_CUR)) | ||
848 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | ||
825 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) | 849 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) |
826 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 850 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
827 | 851 | ||
@@ -1047,6 +1071,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
1047 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); | 1071 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); |
1048 | step = mapping->get(mapping, UVC_GET_RES, | 1072 | step = mapping->get(mapping, UVC_GET_RES, |
1049 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | 1073 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); |
1074 | if (step == 0) | ||
1075 | step = 1; | ||
1050 | 1076 | ||
1051 | xctrl->value = min + (xctrl->value - min + step/2) / step * step; | 1077 | xctrl->value = min + (xctrl->value - min + step/2) / step * step; |
1052 | xctrl->value = clamp(xctrl->value, min, max); | 1078 | xctrl->value = clamp(xctrl->value, min, max); |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 86ff8c12ea58..838b56f097cf 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -91,11 +91,16 @@ static struct uvc_format_desc uvc_fmts[] = { | |||
91 | .fcc = V4L2_PIX_FMT_UYVY, | 91 | .fcc = V4L2_PIX_FMT_UYVY, |
92 | }, | 92 | }, |
93 | { | 93 | { |
94 | .name = "Greyscale", | 94 | .name = "Greyscale (8-bit)", |
95 | .guid = UVC_GUID_FORMAT_Y800, | 95 | .guid = UVC_GUID_FORMAT_Y800, |
96 | .fcc = V4L2_PIX_FMT_GREY, | 96 | .fcc = V4L2_PIX_FMT_GREY, |
97 | }, | 97 | }, |
98 | { | 98 | { |
99 | .name = "Greyscale (16-bit)", | ||
100 | .guid = UVC_GUID_FORMAT_Y16, | ||
101 | .fcc = V4L2_PIX_FMT_Y16, | ||
102 | }, | ||
103 | { | ||
99 | .name = "RGB Bayer", | 104 | .name = "RGB Bayer", |
100 | .guid = UVC_GUID_FORMAT_BY8, | 105 | .guid = UVC_GUID_FORMAT_BY8, |
101 | .fcc = V4L2_PIX_FMT_SBGGR8, | 106 | .fcc = V4L2_PIX_FMT_SBGGR8, |
@@ -2105,6 +2110,15 @@ static struct usb_device_id uvc_ids[] = { | |||
2105 | .bInterfaceSubClass = 1, | 2110 | .bInterfaceSubClass = 1, |
2106 | .bInterfaceProtocol = 0, | 2111 | .bInterfaceProtocol = 0, |
2107 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 2112 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
2113 | /* Syntek (Packard Bell EasyNote MX52 */ | ||
2114 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2115 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2116 | .idVendor = 0x174f, | ||
2117 | .idProduct = 0x8a12, | ||
2118 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2119 | .bInterfaceSubClass = 1, | ||
2120 | .bInterfaceProtocol = 0, | ||
2121 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
2108 | /* Syntek (Asus F9SG) */ | 2122 | /* Syntek (Asus F9SG) */ |
2109 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2123 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2110 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2124 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -2169,6 +2183,15 @@ static struct usb_device_id uvc_ids[] = { | |||
2169 | .bInterfaceSubClass = 1, | 2183 | .bInterfaceSubClass = 1, |
2170 | .bInterfaceProtocol = 0, | 2184 | .bInterfaceProtocol = 0, |
2171 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 2185 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
2186 | /* Arkmicro unbranded */ | ||
2187 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2188 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2189 | .idVendor = 0x18ec, | ||
2190 | .idProduct = 0x3290, | ||
2191 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2192 | .bInterfaceSubClass = 1, | ||
2193 | .bInterfaceProtocol = 0, | ||
2194 | .driver_info = UVC_QUIRK_PROBE_DEF }, | ||
2172 | /* Bodelin ProScopeHR */ | 2195 | /* Bodelin ProScopeHR */ |
2173 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2196 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2174 | | USB_DEVICE_ID_MATCH_DEV_HI | 2197 | | USB_DEVICE_ID_MATCH_DEV_HI |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 4a925a31b0e0..133c78d113ac 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -388,8 +388,12 @@ unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, | |||
388 | 388 | ||
389 | poll_wait(file, &buf->wait, wait); | 389 | poll_wait(file, &buf->wait, wait); |
390 | if (buf->state == UVC_BUF_STATE_DONE || | 390 | if (buf->state == UVC_BUF_STATE_DONE || |
391 | buf->state == UVC_BUF_STATE_ERROR) | 391 | buf->state == UVC_BUF_STATE_ERROR) { |
392 | mask |= POLLIN | POLLRDNORM; | 392 | if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
393 | mask |= POLLIN | POLLRDNORM; | ||
394 | else | ||
395 | mask |= POLLOUT | POLLWRNORM; | ||
396 | } | ||
393 | 397 | ||
394 | done: | 398 | done: |
395 | mutex_unlock(&queue->mutex); | 399 | mutex_unlock(&queue->mutex); |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 2bba059259e6..d1f88406a5e7 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -131,11 +131,13 @@ struct uvc_xu_control { | |||
131 | #define UVC_GUID_FORMAT_Y800 \ | 131 | #define UVC_GUID_FORMAT_Y800 \ |
132 | { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ | 132 | { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ |
133 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 133 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
134 | #define UVC_GUID_FORMAT_Y16 \ | ||
135 | { 'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ | ||
136 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
134 | #define UVC_GUID_FORMAT_BY8 \ | 137 | #define UVC_GUID_FORMAT_BY8 \ |
135 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ | 138 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ |
136 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 139 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
137 | 140 | ||
138 | |||
139 | /* ------------------------------------------------------------------------ | 141 | /* ------------------------------------------------------------------------ |
140 | * Driver specific constants. | 142 | * Driver specific constants. |
141 | */ | 143 | */ |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 36b5cb86fb57..4e53b0b3339c 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -51,6 +51,9 @@ | |||
51 | #include <linux/string.h> | 51 | #include <linux/string.h> |
52 | #include <linux/errno.h> | 52 | #include <linux/errno.h> |
53 | #include <linux/i2c.h> | 53 | #include <linux/i2c.h> |
54 | #if defined(CONFIG_SPI) | ||
55 | #include <linux/spi/spi.h> | ||
56 | #endif | ||
54 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
55 | #include <asm/system.h> | 58 | #include <asm/system.h> |
56 | #include <asm/pgtable.h> | 59 | #include <asm/pgtable.h> |
@@ -85,10 +88,9 @@ MODULE_LICENSE("GPL"); | |||
85 | val == V4L2_PRIORITY_INTERACTIVE || \ | 88 | val == V4L2_PRIORITY_INTERACTIVE || \ |
86 | val == V4L2_PRIORITY_RECORD) | 89 | val == V4L2_PRIORITY_RECORD) |
87 | 90 | ||
88 | int v4l2_prio_init(struct v4l2_prio_state *global) | 91 | void v4l2_prio_init(struct v4l2_prio_state *global) |
89 | { | 92 | { |
90 | memset(global,0,sizeof(*global)); | 93 | memset(global, 0, sizeof(*global)); |
91 | return 0; | ||
92 | } | 94 | } |
93 | EXPORT_SYMBOL(v4l2_prio_init); | 95 | EXPORT_SYMBOL(v4l2_prio_init); |
94 | 96 | ||
@@ -108,17 +110,16 @@ int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, | |||
108 | } | 110 | } |
109 | EXPORT_SYMBOL(v4l2_prio_change); | 111 | EXPORT_SYMBOL(v4l2_prio_change); |
110 | 112 | ||
111 | int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) | 113 | void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) |
112 | { | 114 | { |
113 | return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT); | 115 | v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT); |
114 | } | 116 | } |
115 | EXPORT_SYMBOL(v4l2_prio_open); | 117 | EXPORT_SYMBOL(v4l2_prio_open); |
116 | 118 | ||
117 | int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) | 119 | void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local) |
118 | { | 120 | { |
119 | if (V4L2_PRIO_VALID(*local)) | 121 | if (V4L2_PRIO_VALID(local)) |
120 | atomic_dec(&global->prios[*local]); | 122 | atomic_dec(&global->prios[local]); |
121 | return 0; | ||
122 | } | 123 | } |
123 | EXPORT_SYMBOL(v4l2_prio_close); | 124 | EXPORT_SYMBOL(v4l2_prio_close); |
124 | 125 | ||
@@ -134,11 +135,9 @@ enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) | |||
134 | } | 135 | } |
135 | EXPORT_SYMBOL(v4l2_prio_max); | 136 | EXPORT_SYMBOL(v4l2_prio_max); |
136 | 137 | ||
137 | int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) | 138 | int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local) |
138 | { | 139 | { |
139 | if (*local < v4l2_prio_max(global)) | 140 | return (local < v4l2_prio_max(global)) ? -EBUSY : 0; |
140 | return -EBUSY; | ||
141 | return 0; | ||
142 | } | 141 | } |
143 | EXPORT_SYMBOL(v4l2_prio_check); | 142 | EXPORT_SYMBOL(v4l2_prio_check); |
144 | 143 | ||
@@ -340,6 +339,13 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
340 | "None", | 339 | "None", |
341 | "Black & White", | 340 | "Black & White", |
342 | "Sepia", | 341 | "Sepia", |
342 | "Negative", | ||
343 | "Emboss", | ||
344 | "Sketch", | ||
345 | "Sky blue", | ||
346 | "Grass green", | ||
347 | "Skin whiten", | ||
348 | "Vivid", | ||
343 | NULL | 349 | NULL |
344 | }; | 350 | }; |
345 | static const char *tune_preemphasis[] = { | 351 | static const char *tune_preemphasis[] = { |
@@ -429,10 +435,13 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
429 | case V4L2_CID_SHARPNESS: return "Sharpness"; | 435 | case V4L2_CID_SHARPNESS: return "Sharpness"; |
430 | case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; | 436 | case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; |
431 | case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; | 437 | case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; |
438 | case V4L2_CID_CHROMA_GAIN: return "Chroma Gain"; | ||
432 | case V4L2_CID_COLOR_KILLER: return "Color Killer"; | 439 | case V4L2_CID_COLOR_KILLER: return "Color Killer"; |
433 | case V4L2_CID_COLORFX: return "Color Effects"; | 440 | case V4L2_CID_COLORFX: return "Color Effects"; |
441 | case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic"; | ||
442 | case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter"; | ||
434 | case V4L2_CID_ROTATE: return "Rotate"; | 443 | case V4L2_CID_ROTATE: return "Rotate"; |
435 | case V4L2_CID_BG_COLOR: return "Background color"; | 444 | case V4L2_CID_BG_COLOR: return "Background Color"; |
436 | 445 | ||
437 | /* MPEG controls */ | 446 | /* MPEG controls */ |
438 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; | 447 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; |
@@ -483,6 +492,8 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
483 | case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; | 492 | case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; |
484 | case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; | 493 | case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; |
485 | case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic"; | 494 | case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic"; |
495 | case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute"; | ||
496 | case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative"; | ||
486 | case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; | 497 | case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; |
487 | case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; | 498 | case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; |
488 | case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; | 499 | case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; |
@@ -620,6 +631,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
620 | case V4L2_CID_BLUE_BALANCE: | 631 | case V4L2_CID_BLUE_BALANCE: |
621 | case V4L2_CID_GAMMA: | 632 | case V4L2_CID_GAMMA: |
622 | case V4L2_CID_SHARPNESS: | 633 | case V4L2_CID_SHARPNESS: |
634 | case V4L2_CID_CHROMA_GAIN: | ||
623 | case V4L2_CID_RDS_TX_DEVIATION: | 635 | case V4L2_CID_RDS_TX_DEVIATION: |
624 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | 636 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: |
625 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | 637 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: |
@@ -636,6 +648,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
636 | case V4L2_CID_PAN_RELATIVE: | 648 | case V4L2_CID_PAN_RELATIVE: |
637 | case V4L2_CID_TILT_RELATIVE: | 649 | case V4L2_CID_TILT_RELATIVE: |
638 | case V4L2_CID_FOCUS_RELATIVE: | 650 | case V4L2_CID_FOCUS_RELATIVE: |
651 | case V4L2_CID_IRIS_RELATIVE: | ||
639 | case V4L2_CID_ZOOM_RELATIVE: | 652 | case V4L2_CID_ZOOM_RELATIVE: |
640 | qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | 653 | qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; |
641 | break; | 654 | break; |
@@ -951,6 +964,66 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); | |||
951 | 964 | ||
952 | #endif /* defined(CONFIG_I2C) */ | 965 | #endif /* defined(CONFIG_I2C) */ |
953 | 966 | ||
967 | #if defined(CONFIG_SPI) | ||
968 | |||
969 | /* Load a spi sub-device. */ | ||
970 | |||
971 | void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, | ||
972 | const struct v4l2_subdev_ops *ops) | ||
973 | { | ||
974 | v4l2_subdev_init(sd, ops); | ||
975 | sd->flags |= V4L2_SUBDEV_FL_IS_SPI; | ||
976 | /* the owner is the same as the spi_device's driver owner */ | ||
977 | sd->owner = spi->dev.driver->owner; | ||
978 | /* spi_device and v4l2_subdev point to one another */ | ||
979 | v4l2_set_subdevdata(sd, spi); | ||
980 | spi_set_drvdata(spi, sd); | ||
981 | /* initialize name */ | ||
982 | strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name)); | ||
983 | } | ||
984 | EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); | ||
985 | |||
986 | struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, | ||
987 | struct spi_master *master, struct spi_board_info *info) | ||
988 | { | ||
989 | struct v4l2_subdev *sd = NULL; | ||
990 | struct spi_device *spi = NULL; | ||
991 | |||
992 | BUG_ON(!v4l2_dev); | ||
993 | |||
994 | if (info->modalias) | ||
995 | request_module(info->modalias); | ||
996 | |||
997 | spi = spi_new_device(master, info); | ||
998 | |||
999 | if (spi == NULL || spi->dev.driver == NULL) | ||
1000 | goto error; | ||
1001 | |||
1002 | if (!try_module_get(spi->dev.driver->owner)) | ||
1003 | goto error; | ||
1004 | |||
1005 | sd = spi_get_drvdata(spi); | ||
1006 | |||
1007 | /* Register with the v4l2_device which increases the module's | ||
1008 | use count as well. */ | ||
1009 | if (v4l2_device_register_subdev(v4l2_dev, sd)) | ||
1010 | sd = NULL; | ||
1011 | |||
1012 | /* Decrease the module use count to match the first try_module_get. */ | ||
1013 | module_put(spi->dev.driver->owner); | ||
1014 | |||
1015 | error: | ||
1016 | /* If we have a client but no subdev, then something went wrong and | ||
1017 | we must unregister the client. */ | ||
1018 | if (spi && sd == NULL) | ||
1019 | spi_unregister_device(spi); | ||
1020 | |||
1021 | return sd; | ||
1022 | } | ||
1023 | EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev); | ||
1024 | |||
1025 | #endif /* defined(CONFIG_SPI) */ | ||
1026 | |||
954 | /* Clamp x to be between min and max, aligned to a multiple of 2^align. min | 1027 | /* Clamp x to be between min and max, aligned to a multiple of 2^align. min |
955 | * and max don't have to be aligned, but there must be at least one valid | 1028 | * and max don't have to be aligned, but there must be at least one valid |
956 | * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples | 1029 | * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index f77f84bfe714..9004a5fe7643 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -1086,6 +1086,9 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
1086 | case VIDIOC_QUERY_DV_PRESET: | 1086 | case VIDIOC_QUERY_DV_PRESET: |
1087 | case VIDIOC_S_DV_TIMINGS: | 1087 | case VIDIOC_S_DV_TIMINGS: |
1088 | case VIDIOC_G_DV_TIMINGS: | 1088 | case VIDIOC_G_DV_TIMINGS: |
1089 | case VIDIOC_DQEVENT: | ||
1090 | case VIDIOC_SUBSCRIBE_EVENT: | ||
1091 | case VIDIOC_UNSUBSCRIBE_EVENT: | ||
1089 | ret = do_video_ioctl(file, cmd, arg); | 1092 | ret = do_video_ioctl(file, cmd, arg); |
1090 | break; | 1093 | break; |
1091 | 1094 | ||
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 709069916068..0ca7ec9ca902 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -421,6 +421,10 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
421 | if (!vdev->release) | 421 | if (!vdev->release) |
422 | return -EINVAL; | 422 | return -EINVAL; |
423 | 423 | ||
424 | /* v4l2_fh support */ | ||
425 | spin_lock_init(&vdev->fh_lock); | ||
426 | INIT_LIST_HEAD(&vdev->fh_list); | ||
427 | |||
424 | /* Part 1: check device type */ | 428 | /* Part 1: check device type */ |
425 | switch (type) { | 429 | switch (type) { |
426 | case VFL_TYPE_GRABBER: | 430 | case VFL_TYPE_GRABBER: |
@@ -596,9 +600,7 @@ void video_unregister_device(struct video_device *vdev) | |||
596 | if (!vdev || !video_is_registered(vdev)) | 600 | if (!vdev || !video_is_registered(vdev)) |
597 | return; | 601 | return; |
598 | 602 | ||
599 | mutex_lock(&videodev_lock); | ||
600 | clear_bit(V4L2_FL_REGISTERED, &vdev->flags); | 603 | clear_bit(V4L2_FL_REGISTERED, &vdev->flags); |
601 | mutex_unlock(&videodev_lock); | ||
602 | device_unregister(&vdev->dev); | 604 | device_unregister(&vdev->dev); |
603 | } | 605 | } |
604 | EXPORT_SYMBOL(video_unregister_device); | 606 | EXPORT_SYMBOL(video_unregister_device); |
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0d06e7cbd5b3..5a7dc4afe92a 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/ioctl.h> | 22 | #include <linux/ioctl.h> |
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #if defined(CONFIG_SPI) | ||
25 | #include <linux/spi/spi.h> | ||
26 | #endif | ||
24 | #include <linux/videodev2.h> | 27 | #include <linux/videodev2.h> |
25 | #include <media/v4l2-device.h> | 28 | #include <media/v4l2-device.h> |
26 | 29 | ||
@@ -97,6 +100,14 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) | |||
97 | i2c_unregister_device(client); | 100 | i2c_unregister_device(client); |
98 | } | 101 | } |
99 | #endif | 102 | #endif |
103 | #if defined(CONFIG_SPI) | ||
104 | if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) { | ||
105 | struct spi_device *spi = v4l2_get_subdevdata(sd); | ||
106 | |||
107 | if (spi) | ||
108 | spi_unregister_device(spi); | ||
109 | } | ||
110 | #endif | ||
100 | } | 111 | } |
101 | } | 112 | } |
102 | EXPORT_SYMBOL_GPL(v4l2_device_unregister); | 113 | EXPORT_SYMBOL_GPL(v4l2_device_unregister); |
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c new file mode 100644 index 000000000000..de74ce07b5e2 --- /dev/null +++ b/drivers/media/video/v4l2-event.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * v4l2-event.c | ||
3 | * | ||
4 | * V4L2 events. | ||
5 | * | ||
6 | * Copyright (C) 2009--2010 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <media/v4l2-dev.h> | ||
26 | #include <media/v4l2-fh.h> | ||
27 | #include <media/v4l2-event.h> | ||
28 | |||
29 | #include <linux/sched.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | int v4l2_event_init(struct v4l2_fh *fh) | ||
33 | { | ||
34 | fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL); | ||
35 | if (fh->events == NULL) | ||
36 | return -ENOMEM; | ||
37 | |||
38 | init_waitqueue_head(&fh->events->wait); | ||
39 | |||
40 | INIT_LIST_HEAD(&fh->events->free); | ||
41 | INIT_LIST_HEAD(&fh->events->available); | ||
42 | INIT_LIST_HEAD(&fh->events->subscribed); | ||
43 | |||
44 | fh->events->sequence = -1; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | EXPORT_SYMBOL_GPL(v4l2_event_init); | ||
49 | |||
50 | int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n) | ||
51 | { | ||
52 | struct v4l2_events *events = fh->events; | ||
53 | unsigned long flags; | ||
54 | |||
55 | if (!events) { | ||
56 | WARN_ON(1); | ||
57 | return -ENOMEM; | ||
58 | } | ||
59 | |||
60 | while (events->nallocated < n) { | ||
61 | struct v4l2_kevent *kev; | ||
62 | |||
63 | kev = kzalloc(sizeof(*kev), GFP_KERNEL); | ||
64 | if (kev == NULL) | ||
65 | return -ENOMEM; | ||
66 | |||
67 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
68 | list_add_tail(&kev->list, &events->free); | ||
69 | events->nallocated++; | ||
70 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
71 | } | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(v4l2_event_alloc); | ||
76 | |||
77 | #define list_kfree(list, type, member) \ | ||
78 | while (!list_empty(list)) { \ | ||
79 | type *hi; \ | ||
80 | hi = list_first_entry(list, type, member); \ | ||
81 | list_del(&hi->member); \ | ||
82 | kfree(hi); \ | ||
83 | } | ||
84 | |||
85 | void v4l2_event_free(struct v4l2_fh *fh) | ||
86 | { | ||
87 | struct v4l2_events *events = fh->events; | ||
88 | |||
89 | if (!events) | ||
90 | return; | ||
91 | |||
92 | list_kfree(&events->free, struct v4l2_kevent, list); | ||
93 | list_kfree(&events->available, struct v4l2_kevent, list); | ||
94 | list_kfree(&events->subscribed, struct v4l2_subscribed_event, list); | ||
95 | |||
96 | kfree(events); | ||
97 | fh->events = NULL; | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(v4l2_event_free); | ||
100 | |||
101 | static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) | ||
102 | { | ||
103 | struct v4l2_events *events = fh->events; | ||
104 | struct v4l2_kevent *kev; | ||
105 | unsigned long flags; | ||
106 | |||
107 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
108 | |||
109 | if (list_empty(&events->available)) { | ||
110 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
111 | return -ENOENT; | ||
112 | } | ||
113 | |||
114 | WARN_ON(events->navailable == 0); | ||
115 | |||
116 | kev = list_first_entry(&events->available, struct v4l2_kevent, list); | ||
117 | list_move(&kev->list, &events->free); | ||
118 | events->navailable--; | ||
119 | |||
120 | kev->event.pending = events->navailable; | ||
121 | *event = kev->event; | ||
122 | |||
123 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, | ||
129 | int nonblocking) | ||
130 | { | ||
131 | struct v4l2_events *events = fh->events; | ||
132 | int ret; | ||
133 | |||
134 | if (nonblocking) | ||
135 | return __v4l2_event_dequeue(fh, event); | ||
136 | |||
137 | do { | ||
138 | ret = wait_event_interruptible(events->wait, | ||
139 | events->navailable != 0); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | |||
143 | ret = __v4l2_event_dequeue(fh, event); | ||
144 | } while (ret == -ENOENT); | ||
145 | |||
146 | return ret; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(v4l2_event_dequeue); | ||
149 | |||
150 | /* Caller must hold fh->event->lock! */ | ||
151 | static struct v4l2_subscribed_event *v4l2_event_subscribed( | ||
152 | struct v4l2_fh *fh, u32 type) | ||
153 | { | ||
154 | struct v4l2_events *events = fh->events; | ||
155 | struct v4l2_subscribed_event *sev; | ||
156 | |||
157 | assert_spin_locked(&fh->vdev->fh_lock); | ||
158 | |||
159 | list_for_each_entry(sev, &events->subscribed, list) { | ||
160 | if (sev->type == type) | ||
161 | return sev; | ||
162 | } | ||
163 | |||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev) | ||
168 | { | ||
169 | struct v4l2_fh *fh; | ||
170 | unsigned long flags; | ||
171 | struct timespec timestamp; | ||
172 | |||
173 | ktime_get_ts(×tamp); | ||
174 | |||
175 | spin_lock_irqsave(&vdev->fh_lock, flags); | ||
176 | |||
177 | list_for_each_entry(fh, &vdev->fh_list, list) { | ||
178 | struct v4l2_events *events = fh->events; | ||
179 | struct v4l2_kevent *kev; | ||
180 | |||
181 | /* Are we subscribed? */ | ||
182 | if (!v4l2_event_subscribed(fh, ev->type)) | ||
183 | continue; | ||
184 | |||
185 | /* Increase event sequence number on fh. */ | ||
186 | events->sequence++; | ||
187 | |||
188 | /* Do we have any free events? */ | ||
189 | if (list_empty(&events->free)) | ||
190 | continue; | ||
191 | |||
192 | /* Take one and fill it. */ | ||
193 | kev = list_first_entry(&events->free, struct v4l2_kevent, list); | ||
194 | kev->event.type = ev->type; | ||
195 | kev->event.u = ev->u; | ||
196 | kev->event.timestamp = timestamp; | ||
197 | kev->event.sequence = events->sequence; | ||
198 | list_move_tail(&kev->list, &events->available); | ||
199 | |||
200 | events->navailable++; | ||
201 | |||
202 | wake_up_all(&events->wait); | ||
203 | } | ||
204 | |||
205 | spin_unlock_irqrestore(&vdev->fh_lock, flags); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(v4l2_event_queue); | ||
208 | |||
209 | int v4l2_event_pending(struct v4l2_fh *fh) | ||
210 | { | ||
211 | return fh->events->navailable; | ||
212 | } | ||
213 | EXPORT_SYMBOL_GPL(v4l2_event_pending); | ||
214 | |||
215 | int v4l2_event_subscribe(struct v4l2_fh *fh, | ||
216 | struct v4l2_event_subscription *sub) | ||
217 | { | ||
218 | struct v4l2_events *events = fh->events; | ||
219 | struct v4l2_subscribed_event *sev; | ||
220 | unsigned long flags; | ||
221 | |||
222 | if (fh->events == NULL) { | ||
223 | WARN_ON(1); | ||
224 | return -ENOMEM; | ||
225 | } | ||
226 | |||
227 | sev = kmalloc(sizeof(*sev), GFP_KERNEL); | ||
228 | if (!sev) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
232 | |||
233 | if (v4l2_event_subscribed(fh, sub->type) == NULL) { | ||
234 | INIT_LIST_HEAD(&sev->list); | ||
235 | sev->type = sub->type; | ||
236 | |||
237 | list_add(&sev->list, &events->subscribed); | ||
238 | sev = NULL; | ||
239 | } | ||
240 | |||
241 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
242 | |||
243 | kfree(sev); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | EXPORT_SYMBOL_GPL(v4l2_event_subscribe); | ||
248 | |||
249 | static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh) | ||
250 | { | ||
251 | struct v4l2_events *events = fh->events; | ||
252 | struct v4l2_subscribed_event *sev; | ||
253 | unsigned long flags; | ||
254 | |||
255 | do { | ||
256 | sev = NULL; | ||
257 | |||
258 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
259 | if (!list_empty(&events->subscribed)) { | ||
260 | sev = list_first_entry(&events->subscribed, | ||
261 | struct v4l2_subscribed_event, list); | ||
262 | list_del(&sev->list); | ||
263 | } | ||
264 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
265 | kfree(sev); | ||
266 | } while (sev); | ||
267 | } | ||
268 | |||
269 | int v4l2_event_unsubscribe(struct v4l2_fh *fh, | ||
270 | struct v4l2_event_subscription *sub) | ||
271 | { | ||
272 | struct v4l2_subscribed_event *sev; | ||
273 | unsigned long flags; | ||
274 | |||
275 | if (sub->type == V4L2_EVENT_ALL) { | ||
276 | v4l2_event_unsubscribe_all(fh); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
281 | |||
282 | sev = v4l2_event_subscribed(fh, sub->type); | ||
283 | if (sev != NULL) | ||
284 | list_del(&sev->list); | ||
285 | |||
286 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
287 | |||
288 | kfree(sev); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe); | ||
diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c new file mode 100644 index 000000000000..d78f184f40c5 --- /dev/null +++ b/drivers/media/video/v4l2-fh.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * v4l2-fh.c | ||
3 | * | ||
4 | * V4L2 file handles. | ||
5 | * | ||
6 | * Copyright (C) 2009--2010 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/bitops.h> | ||
26 | #include <media/v4l2-dev.h> | ||
27 | #include <media/v4l2-fh.h> | ||
28 | #include <media/v4l2-event.h> | ||
29 | #include <media/v4l2-ioctl.h> | ||
30 | |||
31 | int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) | ||
32 | { | ||
33 | fh->vdev = vdev; | ||
34 | INIT_LIST_HEAD(&fh->list); | ||
35 | set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); | ||
36 | |||
37 | /* | ||
38 | * fh->events only needs to be initialized if the driver | ||
39 | * supports the VIDIOC_SUBSCRIBE_EVENT ioctl. | ||
40 | */ | ||
41 | if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event) | ||
42 | return v4l2_event_init(fh); | ||
43 | |||
44 | fh->events = NULL; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | EXPORT_SYMBOL_GPL(v4l2_fh_init); | ||
49 | |||
50 | void v4l2_fh_add(struct v4l2_fh *fh) | ||
51 | { | ||
52 | unsigned long flags; | ||
53 | |||
54 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
55 | list_add(&fh->list, &fh->vdev->fh_list); | ||
56 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(v4l2_fh_add); | ||
59 | |||
60 | void v4l2_fh_del(struct v4l2_fh *fh) | ||
61 | { | ||
62 | unsigned long flags; | ||
63 | |||
64 | spin_lock_irqsave(&fh->vdev->fh_lock, flags); | ||
65 | list_del_init(&fh->list); | ||
66 | spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); | ||
67 | } | ||
68 | EXPORT_SYMBOL_GPL(v4l2_fh_del); | ||
69 | |||
70 | void v4l2_fh_exit(struct v4l2_fh *fh) | ||
71 | { | ||
72 | if (fh->vdev == NULL) | ||
73 | return; | ||
74 | |||
75 | fh->vdev = NULL; | ||
76 | |||
77 | v4l2_event_free(fh); | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(v4l2_fh_exit); | ||
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7d59c107f13b..0eeceae50329 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #endif | 26 | #endif |
27 | #include <media/v4l2-common.h> | 27 | #include <media/v4l2-common.h> |
28 | #include <media/v4l2-ioctl.h> | 28 | #include <media/v4l2-ioctl.h> |
29 | #include <media/v4l2-fh.h> | ||
30 | #include <media/v4l2-event.h> | ||
29 | #include <media/v4l2-chip-ident.h> | 31 | #include <media/v4l2-chip-ident.h> |
30 | 32 | ||
31 | #define dbgarg(cmd, fmt, arg...) \ | 33 | #define dbgarg(cmd, fmt, arg...) \ |
@@ -291,6 +293,9 @@ static const char *v4l2_ioctls[] = { | |||
291 | [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", | 293 | [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", |
292 | [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", | 294 | [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", |
293 | [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", | 295 | [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", |
296 | [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT", | ||
297 | [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT", | ||
298 | [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT", | ||
294 | }; | 299 | }; |
295 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) | 300 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) |
296 | 301 | ||
@@ -610,17 +615,33 @@ static long __video_do_ioctl(struct file *file, | |||
610 | void *fh = file->private_data; | 615 | void *fh = file->private_data; |
611 | long ret = -EINVAL; | 616 | long ret = -EINVAL; |
612 | 617 | ||
618 | if (ops == NULL) { | ||
619 | printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", | ||
620 | vfd->name); | ||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
625 | /******************************************************** | ||
626 | All other V4L1 calls are handled by v4l1_compat module. | ||
627 | Those calls will be translated into V4L2 calls, and | ||
628 | __video_do_ioctl will be called again, with one or more | ||
629 | V4L2 ioctls. | ||
630 | ********************************************************/ | ||
631 | if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF && | ||
632 | _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) { | ||
633 | return v4l_compat_translate_ioctl(file, cmd, arg, | ||
634 | __video_do_ioctl); | ||
635 | } | ||
636 | #endif | ||
637 | |||
613 | if ((vfd->debug & V4L2_DEBUG_IOCTL) && | 638 | if ((vfd->debug & V4L2_DEBUG_IOCTL) && |
614 | !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { | 639 | !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { |
615 | v4l_print_ioctl(vfd->name, cmd); | 640 | v4l_print_ioctl(vfd->name, cmd); |
616 | printk(KERN_CONT "\n"); | 641 | printk(KERN_CONT "\n"); |
617 | } | 642 | } |
618 | 643 | ||
619 | if (ops == NULL) { | 644 | switch (cmd) { |
620 | printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", | ||
621 | vfd->name); | ||
622 | return -EINVAL; | ||
623 | } | ||
624 | 645 | ||
625 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 646 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
626 | /*********************************************************** | 647 | /*********************************************************** |
@@ -630,31 +651,21 @@ static long __video_do_ioctl(struct file *file, | |||
630 | ***********************************************************/ | 651 | ***********************************************************/ |
631 | 652 | ||
632 | /* --- streaming capture ------------------------------------- */ | 653 | /* --- streaming capture ------------------------------------- */ |
633 | if (cmd == VIDIOCGMBUF) { | 654 | case VIDIOCGMBUF: |
655 | { | ||
634 | struct video_mbuf *p = arg; | 656 | struct video_mbuf *p = arg; |
635 | 657 | ||
636 | if (!ops->vidiocgmbuf) | 658 | if (!ops->vidiocgmbuf) |
637 | return ret; | 659 | break; |
638 | ret = ops->vidiocgmbuf(file, fh, p); | 660 | ret = ops->vidiocgmbuf(file, fh, p); |
639 | if (!ret) | 661 | if (!ret) |
640 | dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", | 662 | dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", |
641 | p->size, p->frames, | 663 | p->size, p->frames, |
642 | (unsigned long)p->offsets); | 664 | (unsigned long)p->offsets); |
643 | return ret; | 665 | break; |
644 | } | 666 | } |
645 | |||
646 | /******************************************************** | ||
647 | All other V4L1 calls are handled by v4l1_compat module. | ||
648 | Those calls will be translated into V4L2 calls, and | ||
649 | __video_do_ioctl will be called again, with one or more | ||
650 | V4L2 ioctls. | ||
651 | ********************************************************/ | ||
652 | if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) | ||
653 | return v4l_compat_translate_ioctl(file, cmd, arg, | ||
654 | __video_do_ioctl); | ||
655 | #endif | 667 | #endif |
656 | 668 | ||
657 | switch (cmd) { | ||
658 | /* --- capabilities ------------------------------------------ */ | 669 | /* --- capabilities ------------------------------------------ */ |
659 | case VIDIOC_QUERYCAP: | 670 | case VIDIOC_QUERYCAP: |
660 | { | 671 | { |
@@ -1072,7 +1083,7 @@ static long __video_do_ioctl(struct file *file, | |||
1072 | id &= ~curr_id; | 1083 | id &= ~curr_id; |
1073 | } | 1084 | } |
1074 | if (i <= index) | 1085 | if (i <= index) |
1075 | return -EINVAL; | 1086 | break; |
1076 | 1087 | ||
1077 | v4l2_video_std_construct(p, curr_id, descr); | 1088 | v4l2_video_std_construct(p, curr_id, descr); |
1078 | 1089 | ||
@@ -1597,7 +1608,7 @@ static long __video_do_ioctl(struct file *file, | |||
1597 | v4l2_std_id std = vfd->current_norm; | 1608 | v4l2_std_id std = vfd->current_norm; |
1598 | 1609 | ||
1599 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1610 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1600 | return -EINVAL; | 1611 | break; |
1601 | 1612 | ||
1602 | ret = 0; | 1613 | ret = 0; |
1603 | if (ops->vidioc_g_std) | 1614 | if (ops->vidioc_g_std) |
@@ -1942,7 +1953,55 @@ static long __video_do_ioctl(struct file *file, | |||
1942 | } | 1953 | } |
1943 | break; | 1954 | break; |
1944 | } | 1955 | } |
1956 | case VIDIOC_DQEVENT: | ||
1957 | { | ||
1958 | struct v4l2_event *ev = arg; | ||
1959 | |||
1960 | if (!ops->vidioc_subscribe_event) | ||
1961 | break; | ||
1945 | 1962 | ||
1963 | ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); | ||
1964 | if (ret < 0) { | ||
1965 | dbgarg(cmd, "no pending events?"); | ||
1966 | break; | ||
1967 | } | ||
1968 | dbgarg(cmd, | ||
1969 | "pending=%d, type=0x%8.8x, sequence=%d, " | ||
1970 | "timestamp=%lu.%9.9lu ", | ||
1971 | ev->pending, ev->type, ev->sequence, | ||
1972 | ev->timestamp.tv_sec, ev->timestamp.tv_nsec); | ||
1973 | break; | ||
1974 | } | ||
1975 | case VIDIOC_SUBSCRIBE_EVENT: | ||
1976 | { | ||
1977 | struct v4l2_event_subscription *sub = arg; | ||
1978 | |||
1979 | if (!ops->vidioc_subscribe_event) | ||
1980 | break; | ||
1981 | |||
1982 | ret = ops->vidioc_subscribe_event(fh, sub); | ||
1983 | if (ret < 0) { | ||
1984 | dbgarg(cmd, "failed, ret=%ld", ret); | ||
1985 | break; | ||
1986 | } | ||
1987 | dbgarg(cmd, "type=0x%8.8x", sub->type); | ||
1988 | break; | ||
1989 | } | ||
1990 | case VIDIOC_UNSUBSCRIBE_EVENT: | ||
1991 | { | ||
1992 | struct v4l2_event_subscription *sub = arg; | ||
1993 | |||
1994 | if (!ops->vidioc_unsubscribe_event) | ||
1995 | break; | ||
1996 | |||
1997 | ret = ops->vidioc_unsubscribe_event(fh, sub); | ||
1998 | if (ret < 0) { | ||
1999 | dbgarg(cmd, "failed, ret=%ld", ret); | ||
2000 | break; | ||
2001 | } | ||
2002 | dbgarg(cmd, "type=0x%8.8x", sub->type); | ||
2003 | break; | ||
2004 | } | ||
1946 | default: | 2005 | default: |
1947 | { | 2006 | { |
1948 | if (!ops->vidioc_default) | 2007 | if (!ops->vidioc_default) |
@@ -2006,7 +2065,7 @@ long video_ioctl2(struct file *file, | |||
2006 | { | 2065 | { |
2007 | char sbuf[128]; | 2066 | char sbuf[128]; |
2008 | void *mbuf = NULL; | 2067 | void *mbuf = NULL; |
2009 | void *parg = NULL; | 2068 | void *parg = (void *)arg; |
2010 | long err = -EINVAL; | 2069 | long err = -EINVAL; |
2011 | int is_ext_ctrl; | 2070 | int is_ext_ctrl; |
2012 | size_t ctrls_size = 0; | 2071 | size_t ctrls_size = 0; |
diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/video/v4l2-mem2mem.c new file mode 100644 index 000000000000..f45f9405ea39 --- /dev/null +++ b/drivers/media/video/v4l2-mem2mem.c | |||
@@ -0,0 +1,633 @@ | |||
1 | /* | ||
2 | * Memory-to-memory device framework for Video for Linux 2 and videobuf. | ||
3 | * | ||
4 | * Helper functions for devices that use videobuf buffers for both their | ||
5 | * source and destination. | ||
6 | * | ||
7 | * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. | ||
8 | * Pawel Osciak, <p.osciak@samsung.com> | ||
9 | * Marek Szyprowski, <m.szyprowski@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | #include <media/videobuf-core.h> | ||
21 | #include <media/v4l2-mem2mem.h> | ||
22 | |||
23 | MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); | ||
24 | MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>"); | ||
25 | MODULE_LICENSE("GPL"); | ||
26 | |||
27 | static bool debug; | ||
28 | module_param(debug, bool, 0644); | ||
29 | |||
30 | #define dprintk(fmt, arg...) \ | ||
31 | do { \ | ||
32 | if (debug) \ | ||
33 | printk(KERN_DEBUG "%s: " fmt, __func__, ## arg);\ | ||
34 | } while (0) | ||
35 | |||
36 | |||
37 | /* Instance is already queued on the job_queue */ | ||
38 | #define TRANS_QUEUED (1 << 0) | ||
39 | /* Instance is currently running in hardware */ | ||
40 | #define TRANS_RUNNING (1 << 1) | ||
41 | |||
42 | |||
43 | /* Offset base for buffers on the destination queue - used to distinguish | ||
44 | * between source and destination buffers when mmapping - they receive the same | ||
45 | * offsets but for different queues */ | ||
46 | #define DST_QUEUE_OFF_BASE (1 << 30) | ||
47 | |||
48 | |||
49 | /** | ||
50 | * struct v4l2_m2m_dev - per-device context | ||
51 | * @curr_ctx: currently running instance | ||
52 | * @job_queue: instances queued to run | ||
53 | * @job_spinlock: protects job_queue | ||
54 | * @m2m_ops: driver callbacks | ||
55 | */ | ||
56 | struct v4l2_m2m_dev { | ||
57 | struct v4l2_m2m_ctx *curr_ctx; | ||
58 | |||
59 | struct list_head job_queue; | ||
60 | spinlock_t job_spinlock; | ||
61 | |||
62 | struct v4l2_m2m_ops *m2m_ops; | ||
63 | }; | ||
64 | |||
65 | static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx, | ||
66 | enum v4l2_buf_type type) | ||
67 | { | ||
68 | switch (type) { | ||
69 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
70 | return &m2m_ctx->cap_q_ctx; | ||
71 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
72 | return &m2m_ctx->out_q_ctx; | ||
73 | default: | ||
74 | printk(KERN_ERR "Invalid buffer type\n"); | ||
75 | return NULL; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * v4l2_m2m_get_vq() - return videobuf_queue for the given type | ||
81 | */ | ||
82 | struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, | ||
83 | enum v4l2_buf_type type) | ||
84 | { | ||
85 | struct v4l2_m2m_queue_ctx *q_ctx; | ||
86 | |||
87 | q_ctx = get_queue_ctx(m2m_ctx, type); | ||
88 | if (!q_ctx) | ||
89 | return NULL; | ||
90 | |||
91 | return &q_ctx->q; | ||
92 | } | ||
93 | EXPORT_SYMBOL(v4l2_m2m_get_vq); | ||
94 | |||
95 | /** | ||
96 | * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers | ||
97 | */ | ||
98 | void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) | ||
99 | { | ||
100 | struct v4l2_m2m_queue_ctx *q_ctx; | ||
101 | struct videobuf_buffer *vb = NULL; | ||
102 | unsigned long flags; | ||
103 | |||
104 | q_ctx = get_queue_ctx(m2m_ctx, type); | ||
105 | if (!q_ctx) | ||
106 | return NULL; | ||
107 | |||
108 | spin_lock_irqsave(q_ctx->q.irqlock, flags); | ||
109 | |||
110 | if (list_empty(&q_ctx->rdy_queue)) | ||
111 | goto end; | ||
112 | |||
113 | vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, queue); | ||
114 | vb->state = VIDEOBUF_ACTIVE; | ||
115 | |||
116 | end: | ||
117 | spin_unlock_irqrestore(q_ctx->q.irqlock, flags); | ||
118 | return vb; | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf); | ||
121 | |||
122 | /** | ||
123 | * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and | ||
124 | * return it | ||
125 | */ | ||
126 | void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) | ||
127 | { | ||
128 | struct v4l2_m2m_queue_ctx *q_ctx; | ||
129 | struct videobuf_buffer *vb = NULL; | ||
130 | unsigned long flags; | ||
131 | |||
132 | q_ctx = get_queue_ctx(m2m_ctx, type); | ||
133 | if (!q_ctx) | ||
134 | return NULL; | ||
135 | |||
136 | spin_lock_irqsave(q_ctx->q.irqlock, flags); | ||
137 | if (!list_empty(&q_ctx->rdy_queue)) { | ||
138 | vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, | ||
139 | queue); | ||
140 | list_del(&vb->queue); | ||
141 | q_ctx->num_rdy--; | ||
142 | } | ||
143 | spin_unlock_irqrestore(q_ctx->q.irqlock, flags); | ||
144 | |||
145 | return vb; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove); | ||
148 | |||
149 | /* | ||
150 | * Scheduling handlers | ||
151 | */ | ||
152 | |||
153 | /** | ||
154 | * v4l2_m2m_get_curr_priv() - return driver private data for the currently | ||
155 | * running instance or NULL if no instance is running | ||
156 | */ | ||
157 | void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | void *ret = NULL; | ||
161 | |||
162 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
163 | if (m2m_dev->curr_ctx) | ||
164 | ret = m2m_dev->curr_ctx->priv; | ||
165 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | EXPORT_SYMBOL(v4l2_m2m_get_curr_priv); | ||
170 | |||
171 | /** | ||
172 | * v4l2_m2m_try_run() - select next job to perform and run it if possible | ||
173 | * | ||
174 | * Get next transaction (if present) from the waiting jobs list and run it. | ||
175 | */ | ||
176 | static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) | ||
177 | { | ||
178 | unsigned long flags; | ||
179 | |||
180 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
181 | if (NULL != m2m_dev->curr_ctx) { | ||
182 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
183 | dprintk("Another instance is running, won't run now\n"); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | if (list_empty(&m2m_dev->job_queue)) { | ||
188 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
189 | dprintk("No job pending\n"); | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | m2m_dev->curr_ctx = list_entry(m2m_dev->job_queue.next, | ||
194 | struct v4l2_m2m_ctx, queue); | ||
195 | m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING; | ||
196 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
197 | |||
198 | m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv); | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * v4l2_m2m_try_schedule() - check whether an instance is ready to be added to | ||
203 | * the pending job queue and add it if so. | ||
204 | * @m2m_ctx: m2m context assigned to the instance to be checked | ||
205 | * | ||
206 | * There are three basic requirements an instance has to meet to be able to run: | ||
207 | * 1) at least one source buffer has to be queued, | ||
208 | * 2) at least one destination buffer has to be queued, | ||
209 | * 3) streaming has to be on. | ||
210 | * | ||
211 | * There may also be additional, custom requirements. In such case the driver | ||
212 | * should supply a custom callback (job_ready in v4l2_m2m_ops) that should | ||
213 | * return 1 if the instance is ready. | ||
214 | * An example of the above could be an instance that requires more than one | ||
215 | * src/dst buffer per transaction. | ||
216 | */ | ||
217 | static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) | ||
218 | { | ||
219 | struct v4l2_m2m_dev *m2m_dev; | ||
220 | unsigned long flags_job, flags; | ||
221 | |||
222 | m2m_dev = m2m_ctx->m2m_dev; | ||
223 | dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); | ||
224 | |||
225 | if (!m2m_ctx->out_q_ctx.q.streaming | ||
226 | || !m2m_ctx->cap_q_ctx.q.streaming) { | ||
227 | dprintk("Streaming needs to be on for both queues\n"); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job); | ||
232 | if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
233 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||
234 | dprintk("On job queue already\n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | spin_lock_irqsave(m2m_ctx->out_q_ctx.q.irqlock, flags); | ||
239 | if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { | ||
240 | spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); | ||
241 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||
242 | dprintk("No input buffers available\n"); | ||
243 | return; | ||
244 | } | ||
245 | if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { | ||
246 | spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); | ||
247 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||
248 | dprintk("No output buffers available\n"); | ||
249 | return; | ||
250 | } | ||
251 | spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); | ||
252 | |||
253 | if (m2m_dev->m2m_ops->job_ready | ||
254 | && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { | ||
255 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||
256 | dprintk("Driver not ready\n"); | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue); | ||
261 | m2m_ctx->job_flags |= TRANS_QUEUED; | ||
262 | |||
263 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||
264 | |||
265 | v4l2_m2m_try_run(m2m_dev); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * v4l2_m2m_job_finish() - inform the framework that a job has been finished | ||
270 | * and have it clean up | ||
271 | * | ||
272 | * Called by a driver to yield back the device after it has finished with it. | ||
273 | * Should be called as soon as possible after reaching a state which allows | ||
274 | * other instances to take control of the device. | ||
275 | * | ||
276 | * This function has to be called only after device_run() callback has been | ||
277 | * called on the driver. To prevent recursion, it should not be called directly | ||
278 | * from the device_run() callback though. | ||
279 | */ | ||
280 | void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||
281 | struct v4l2_m2m_ctx *m2m_ctx) | ||
282 | { | ||
283 | unsigned long flags; | ||
284 | |||
285 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
286 | if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { | ||
287 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
288 | dprintk("Called by an instance not currently running\n"); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | list_del(&m2m_dev->curr_ctx->queue); | ||
293 | m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
294 | m2m_dev->curr_ctx = NULL; | ||
295 | |||
296 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
297 | |||
298 | /* This instance might have more buffers ready, but since we do not | ||
299 | * allow more than one job on the job_queue per instance, each has | ||
300 | * to be scheduled separately after the previous one finishes. */ | ||
301 | v4l2_m2m_try_schedule(m2m_ctx); | ||
302 | v4l2_m2m_try_run(m2m_dev); | ||
303 | } | ||
304 | EXPORT_SYMBOL(v4l2_m2m_job_finish); | ||
305 | |||
306 | /** | ||
307 | * v4l2_m2m_reqbufs() - multi-queue-aware REQBUFS multiplexer | ||
308 | */ | ||
309 | int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
310 | struct v4l2_requestbuffers *reqbufs) | ||
311 | { | ||
312 | struct videobuf_queue *vq; | ||
313 | |||
314 | vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type); | ||
315 | return videobuf_reqbufs(vq, reqbufs); | ||
316 | } | ||
317 | EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs); | ||
318 | |||
319 | /** | ||
320 | * v4l2_m2m_querybuf() - multi-queue-aware QUERYBUF multiplexer | ||
321 | * | ||
322 | * See v4l2_m2m_mmap() documentation for details. | ||
323 | */ | ||
324 | int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
325 | struct v4l2_buffer *buf) | ||
326 | { | ||
327 | struct videobuf_queue *vq; | ||
328 | int ret; | ||
329 | |||
330 | vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); | ||
331 | ret = videobuf_querybuf(vq, buf); | ||
332 | |||
333 | if (buf->memory == V4L2_MEMORY_MMAP | ||
334 | && vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
335 | buf->m.offset += DST_QUEUE_OFF_BASE; | ||
336 | } | ||
337 | |||
338 | return ret; | ||
339 | } | ||
340 | EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf); | ||
341 | |||
342 | /** | ||
343 | * v4l2_m2m_qbuf() - enqueue a source or destination buffer, depending on | ||
344 | * the type | ||
345 | */ | ||
346 | int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
347 | struct v4l2_buffer *buf) | ||
348 | { | ||
349 | struct videobuf_queue *vq; | ||
350 | int ret; | ||
351 | |||
352 | vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); | ||
353 | ret = videobuf_qbuf(vq, buf); | ||
354 | if (!ret) | ||
355 | v4l2_m2m_try_schedule(m2m_ctx); | ||
356 | |||
357 | return ret; | ||
358 | } | ||
359 | EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf); | ||
360 | |||
361 | /** | ||
362 | * v4l2_m2m_dqbuf() - dequeue a source or destination buffer, depending on | ||
363 | * the type | ||
364 | */ | ||
365 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
366 | struct v4l2_buffer *buf) | ||
367 | { | ||
368 | struct videobuf_queue *vq; | ||
369 | |||
370 | vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); | ||
371 | return videobuf_dqbuf(vq, buf, file->f_flags & O_NONBLOCK); | ||
372 | } | ||
373 | EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); | ||
374 | |||
375 | /** | ||
376 | * v4l2_m2m_streamon() - turn on streaming for a video queue | ||
377 | */ | ||
378 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
379 | enum v4l2_buf_type type) | ||
380 | { | ||
381 | struct videobuf_queue *vq; | ||
382 | int ret; | ||
383 | |||
384 | vq = v4l2_m2m_get_vq(m2m_ctx, type); | ||
385 | ret = videobuf_streamon(vq); | ||
386 | if (!ret) | ||
387 | v4l2_m2m_try_schedule(m2m_ctx); | ||
388 | |||
389 | return ret; | ||
390 | } | ||
391 | EXPORT_SYMBOL_GPL(v4l2_m2m_streamon); | ||
392 | |||
393 | /** | ||
394 | * v4l2_m2m_streamoff() - turn off streaming for a video queue | ||
395 | */ | ||
396 | int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
397 | enum v4l2_buf_type type) | ||
398 | { | ||
399 | struct videobuf_queue *vq; | ||
400 | |||
401 | vq = v4l2_m2m_get_vq(m2m_ctx, type); | ||
402 | return videobuf_streamoff(vq); | ||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); | ||
405 | |||
406 | /** | ||
407 | * v4l2_m2m_poll() - poll replacement, for destination buffers only | ||
408 | * | ||
409 | * Call from the driver's poll() function. Will poll both queues. If a buffer | ||
410 | * is available to dequeue (with dqbuf) from the source queue, this will | ||
411 | * indicate that a non-blocking write can be performed, while read will be | ||
412 | * returned in case of the destination queue. | ||
413 | */ | ||
414 | unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
415 | struct poll_table_struct *wait) | ||
416 | { | ||
417 | struct videobuf_queue *src_q, *dst_q; | ||
418 | struct videobuf_buffer *src_vb = NULL, *dst_vb = NULL; | ||
419 | unsigned int rc = 0; | ||
420 | |||
421 | src_q = v4l2_m2m_get_src_vq(m2m_ctx); | ||
422 | dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); | ||
423 | |||
424 | mutex_lock(&src_q->vb_lock); | ||
425 | mutex_lock(&dst_q->vb_lock); | ||
426 | |||
427 | if (src_q->streaming && !list_empty(&src_q->stream)) | ||
428 | src_vb = list_first_entry(&src_q->stream, | ||
429 | struct videobuf_buffer, stream); | ||
430 | if (dst_q->streaming && !list_empty(&dst_q->stream)) | ||
431 | dst_vb = list_first_entry(&dst_q->stream, | ||
432 | struct videobuf_buffer, stream); | ||
433 | |||
434 | if (!src_vb && !dst_vb) { | ||
435 | rc = POLLERR; | ||
436 | goto end; | ||
437 | } | ||
438 | |||
439 | if (src_vb) { | ||
440 | poll_wait(file, &src_vb->done, wait); | ||
441 | if (src_vb->state == VIDEOBUF_DONE | ||
442 | || src_vb->state == VIDEOBUF_ERROR) | ||
443 | rc |= POLLOUT | POLLWRNORM; | ||
444 | } | ||
445 | if (dst_vb) { | ||
446 | poll_wait(file, &dst_vb->done, wait); | ||
447 | if (dst_vb->state == VIDEOBUF_DONE | ||
448 | || dst_vb->state == VIDEOBUF_ERROR) | ||
449 | rc |= POLLIN | POLLRDNORM; | ||
450 | } | ||
451 | |||
452 | end: | ||
453 | mutex_unlock(&dst_q->vb_lock); | ||
454 | mutex_unlock(&src_q->vb_lock); | ||
455 | return rc; | ||
456 | } | ||
457 | EXPORT_SYMBOL_GPL(v4l2_m2m_poll); | ||
458 | |||
459 | /** | ||
460 | * v4l2_m2m_mmap() - source and destination queues-aware mmap multiplexer | ||
461 | * | ||
462 | * Call from driver's mmap() function. Will handle mmap() for both queues | ||
463 | * seamlessly for videobuffer, which will receive normal per-queue offsets and | ||
464 | * proper videobuf queue pointers. The differentiation is made outside videobuf | ||
465 | * by adding a predefined offset to buffers from one of the queues and | ||
466 | * subtracting it before passing it back to videobuf. Only drivers (and | ||
467 | * thus applications) receive modified offsets. | ||
468 | */ | ||
469 | int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
470 | struct vm_area_struct *vma) | ||
471 | { | ||
472 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
473 | struct videobuf_queue *vq; | ||
474 | |||
475 | if (offset < DST_QUEUE_OFF_BASE) { | ||
476 | vq = v4l2_m2m_get_src_vq(m2m_ctx); | ||
477 | } else { | ||
478 | vq = v4l2_m2m_get_dst_vq(m2m_ctx); | ||
479 | vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); | ||
480 | } | ||
481 | |||
482 | return videobuf_mmap_mapper(vq, vma); | ||
483 | } | ||
484 | EXPORT_SYMBOL(v4l2_m2m_mmap); | ||
485 | |||
486 | /** | ||
487 | * v4l2_m2m_init() - initialize per-driver m2m data | ||
488 | * | ||
489 | * Usually called from driver's probe() function. | ||
490 | */ | ||
491 | struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops) | ||
492 | { | ||
493 | struct v4l2_m2m_dev *m2m_dev; | ||
494 | |||
495 | if (!m2m_ops) | ||
496 | return ERR_PTR(-EINVAL); | ||
497 | |||
498 | BUG_ON(!m2m_ops->device_run); | ||
499 | BUG_ON(!m2m_ops->job_abort); | ||
500 | |||
501 | m2m_dev = kzalloc(sizeof *m2m_dev, GFP_KERNEL); | ||
502 | if (!m2m_dev) | ||
503 | return ERR_PTR(-ENOMEM); | ||
504 | |||
505 | m2m_dev->curr_ctx = NULL; | ||
506 | m2m_dev->m2m_ops = m2m_ops; | ||
507 | INIT_LIST_HEAD(&m2m_dev->job_queue); | ||
508 | spin_lock_init(&m2m_dev->job_spinlock); | ||
509 | |||
510 | return m2m_dev; | ||
511 | } | ||
512 | EXPORT_SYMBOL_GPL(v4l2_m2m_init); | ||
513 | |||
514 | /** | ||
515 | * v4l2_m2m_release() - cleans up and frees a m2m_dev structure | ||
516 | * | ||
517 | * Usually called from driver's remove() function. | ||
518 | */ | ||
519 | void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev) | ||
520 | { | ||
521 | kfree(m2m_dev); | ||
522 | } | ||
523 | EXPORT_SYMBOL_GPL(v4l2_m2m_release); | ||
524 | |||
525 | /** | ||
526 | * v4l2_m2m_ctx_init() - allocate and initialize a m2m context | ||
527 | * @priv - driver's instance private data | ||
528 | * @m2m_dev - a previously initialized m2m_dev struct | ||
529 | * @vq_init - a callback for queue type-specific initialization function to be | ||
530 | * used for initializing videobuf_queues | ||
531 | * | ||
532 | * Usually called from driver's open() function. | ||
533 | */ | ||
534 | struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, | ||
535 | void (*vq_init)(void *priv, struct videobuf_queue *, | ||
536 | enum v4l2_buf_type)) | ||
537 | { | ||
538 | struct v4l2_m2m_ctx *m2m_ctx; | ||
539 | struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx; | ||
540 | |||
541 | if (!vq_init) | ||
542 | return ERR_PTR(-EINVAL); | ||
543 | |||
544 | m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL); | ||
545 | if (!m2m_ctx) | ||
546 | return ERR_PTR(-ENOMEM); | ||
547 | |||
548 | m2m_ctx->priv = priv; | ||
549 | m2m_ctx->m2m_dev = m2m_dev; | ||
550 | |||
551 | out_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
552 | cap_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
553 | |||
554 | INIT_LIST_HEAD(&out_q_ctx->rdy_queue); | ||
555 | INIT_LIST_HEAD(&cap_q_ctx->rdy_queue); | ||
556 | |||
557 | INIT_LIST_HEAD(&m2m_ctx->queue); | ||
558 | |||
559 | vq_init(priv, &out_q_ctx->q, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
560 | vq_init(priv, &cap_q_ctx->q, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
561 | out_q_ctx->q.priv_data = cap_q_ctx->q.priv_data = priv; | ||
562 | |||
563 | return m2m_ctx; | ||
564 | } | ||
565 | EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); | ||
566 | |||
567 | /** | ||
568 | * v4l2_m2m_ctx_release() - release m2m context | ||
569 | * | ||
570 | * Usually called from driver's release() function. | ||
571 | */ | ||
572 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) | ||
573 | { | ||
574 | struct v4l2_m2m_dev *m2m_dev; | ||
575 | struct videobuf_buffer *vb; | ||
576 | unsigned long flags; | ||
577 | |||
578 | m2m_dev = m2m_ctx->m2m_dev; | ||
579 | |||
580 | spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||
581 | if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||
582 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
583 | m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||
584 | dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); | ||
585 | vb = v4l2_m2m_next_dst_buf(m2m_ctx); | ||
586 | BUG_ON(NULL == vb); | ||
587 | wait_event(vb->done, vb->state != VIDEOBUF_ACTIVE | ||
588 | && vb->state != VIDEOBUF_QUEUED); | ||
589 | } else if (m2m_ctx->job_flags & TRANS_QUEUED) { | ||
590 | list_del(&m2m_ctx->queue); | ||
591 | m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||
592 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
593 | dprintk("m2m_ctx: %p had been on queue and was removed\n", | ||
594 | m2m_ctx); | ||
595 | } else { | ||
596 | /* Do nothing, was not on queue/running */ | ||
597 | spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||
598 | } | ||
599 | |||
600 | videobuf_stop(&m2m_ctx->cap_q_ctx.q); | ||
601 | videobuf_stop(&m2m_ctx->out_q_ctx.q); | ||
602 | |||
603 | videobuf_mmap_free(&m2m_ctx->cap_q_ctx.q); | ||
604 | videobuf_mmap_free(&m2m_ctx->out_q_ctx.q); | ||
605 | |||
606 | kfree(m2m_ctx); | ||
607 | } | ||
608 | EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release); | ||
609 | |||
610 | /** | ||
611 | * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list. | ||
612 | * | ||
613 | * Call from buf_queue(), videobuf_queue_ops callback. | ||
614 | * | ||
615 | * Locking: Caller holds q->irqlock (taken by videobuf before calling buf_queue | ||
616 | * callback in the driver). | ||
617 | */ | ||
618 | void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, | ||
619 | struct videobuf_buffer *vb) | ||
620 | { | ||
621 | struct v4l2_m2m_queue_ctx *q_ctx; | ||
622 | |||
623 | q_ctx = get_queue_ctx(m2m_ctx, vq->type); | ||
624 | if (!q_ctx) | ||
625 | return; | ||
626 | |||
627 | list_add_tail(&vb->queue, &q_ctx->rdy_queue); | ||
628 | q_ctx->num_rdy++; | ||
629 | |||
630 | vb->state = VIDEOBUF_QUEUED; | ||
631 | } | ||
632 | EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); | ||
633 | |||
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index bb0a1c8de414..7d3378437ded 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -24,10 +24,15 @@ | |||
24 | #include <media/videobuf-core.h> | 24 | #include <media/videobuf-core.h> |
25 | 25 | ||
26 | #define MAGIC_BUFFER 0x20070728 | 26 | #define MAGIC_BUFFER 0x20070728 |
27 | #define MAGIC_CHECK(is, should) do { \ | 27 | #define MAGIC_CHECK(is, should) \ |
28 | if (unlikely((is) != (should))) { \ | 28 | do { \ |
29 | printk(KERN_ERR "magic mismatch: %x (expected %x)\n", is, should); \ | 29 | if (unlikely((is) != (should))) { \ |
30 | BUG(); } } while (0) | 30 | printk(KERN_ERR \ |
31 | "magic mismatch: %x (expected %x)\n", \ | ||
32 | is, should); \ | ||
33 | BUG(); \ | ||
34 | } \ | ||
35 | } while (0) | ||
31 | 36 | ||
32 | static int debug; | 37 | static int debug; |
33 | module_param(debug, int, 0644); | 38 | module_param(debug, int, 0644); |
@@ -36,16 +41,18 @@ MODULE_DESCRIPTION("helper module to manage video4linux buffers"); | |||
36 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 41 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
37 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
38 | 43 | ||
39 | #define dprintk(level, fmt, arg...) do { \ | 44 | #define dprintk(level, fmt, arg...) \ |
40 | if (debug >= level) \ | 45 | do { \ |
41 | printk(KERN_DEBUG "vbuf: " fmt , ## arg); } while (0) | 46 | if (debug >= level) \ |
47 | printk(KERN_DEBUG "vbuf: " fmt, ## arg); \ | ||
48 | } while (0) | ||
42 | 49 | ||
43 | /* --------------------------------------------------------------------- */ | 50 | /* --------------------------------------------------------------------- */ |
44 | 51 | ||
45 | #define CALL(q, f, arg...) \ | 52 | #define CALL(q, f, arg...) \ |
46 | ((q->int_ops->f) ? q->int_ops->f(arg) : 0) | 53 | ((q->int_ops->f) ? q->int_ops->f(arg) : 0) |
47 | 54 | ||
48 | void *videobuf_alloc(struct videobuf_queue *q) | 55 | struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q) |
49 | { | 56 | { |
50 | struct videobuf_buffer *vb; | 57 | struct videobuf_buffer *vb; |
51 | 58 | ||
@@ -57,14 +64,14 @@ void *videobuf_alloc(struct videobuf_queue *q) | |||
57 | } | 64 | } |
58 | 65 | ||
59 | vb = q->int_ops->alloc(q->msize); | 66 | vb = q->int_ops->alloc(q->msize); |
60 | |||
61 | if (NULL != vb) { | 67 | if (NULL != vb) { |
62 | init_waitqueue_head(&vb->done); | 68 | init_waitqueue_head(&vb->done); |
63 | vb->magic = MAGIC_BUFFER; | 69 | vb->magic = MAGIC_BUFFER; |
64 | } | 70 | } |
65 | 71 | ||
66 | return vb; | 72 | return vb; |
67 | } | 73 | } |
74 | EXPORT_SYMBOL_GPL(videobuf_alloc); | ||
68 | 75 | ||
69 | #define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ | 76 | #define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ |
70 | vb->state != VIDEOBUF_QUEUED) | 77 | vb->state != VIDEOBUF_QUEUED) |
@@ -86,6 +93,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) | |||
86 | 93 | ||
87 | return 0; | 94 | return 0; |
88 | } | 95 | } |
96 | EXPORT_SYMBOL_GPL(videobuf_waiton); | ||
89 | 97 | ||
90 | int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, | 98 | int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, |
91 | struct v4l2_framebuffer *fbuf) | 99 | struct v4l2_framebuffer *fbuf) |
@@ -95,16 +103,16 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
95 | 103 | ||
96 | return CALL(q, iolock, q, vb, fbuf); | 104 | return CALL(q, iolock, q, vb, fbuf); |
97 | } | 105 | } |
106 | EXPORT_SYMBOL_GPL(videobuf_iolock); | ||
98 | 107 | ||
99 | void *videobuf_queue_to_vmalloc (struct videobuf_queue *q, | 108 | void *videobuf_queue_to_vaddr(struct videobuf_queue *q, |
100 | struct videobuf_buffer *buf) | 109 | struct videobuf_buffer *buf) |
101 | { | 110 | { |
102 | if (q->int_ops->vmalloc) | 111 | if (q->int_ops->vaddr) |
103 | return q->int_ops->vmalloc(buf); | 112 | return q->int_ops->vaddr(buf); |
104 | else | 113 | return NULL; |
105 | return NULL; | ||
106 | } | 114 | } |
107 | EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); | 115 | EXPORT_SYMBOL_GPL(videobuf_queue_to_vaddr); |
108 | 116 | ||
109 | /* --------------------------------------------------------------------- */ | 117 | /* --------------------------------------------------------------------- */ |
110 | 118 | ||
@@ -146,6 +154,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, | |||
146 | init_waitqueue_head(&q->wait); | 154 | init_waitqueue_head(&q->wait); |
147 | INIT_LIST_HEAD(&q->stream); | 155 | INIT_LIST_HEAD(&q->stream); |
148 | } | 156 | } |
157 | EXPORT_SYMBOL_GPL(videobuf_queue_core_init); | ||
149 | 158 | ||
150 | /* Locking: Only usage in bttv unsafe find way to remove */ | 159 | /* Locking: Only usage in bttv unsafe find way to remove */ |
151 | int videobuf_queue_is_busy(struct videobuf_queue *q) | 160 | int videobuf_queue_is_busy(struct videobuf_queue *q) |
@@ -184,6 +193,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) | |||
184 | } | 193 | } |
185 | return 0; | 194 | return 0; |
186 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); | ||
187 | 197 | ||
188 | /* Locking: Caller holds q->vb_lock */ | 198 | /* Locking: Caller holds q->vb_lock */ |
189 | void videobuf_queue_cancel(struct videobuf_queue *q) | 199 | void videobuf_queue_cancel(struct videobuf_queue *q) |
@@ -216,6 +226,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) | |||
216 | } | 226 | } |
217 | INIT_LIST_HEAD(&q->stream); | 227 | INIT_LIST_HEAD(&q->stream); |
218 | } | 228 | } |
229 | EXPORT_SYMBOL_GPL(videobuf_queue_cancel); | ||
219 | 230 | ||
220 | /* --------------------------------------------------------------------- */ | 231 | /* --------------------------------------------------------------------- */ |
221 | 232 | ||
@@ -237,6 +248,7 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) | |||
237 | } | 248 | } |
238 | return field; | 249 | return field; |
239 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(videobuf_next_field); | ||
240 | 252 | ||
241 | /* Locking: Caller holds q->vb_lock */ | 253 | /* Locking: Caller holds q->vb_lock */ |
242 | static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, | 254 | static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, |
@@ -273,8 +285,10 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, | |||
273 | case VIDEOBUF_ACTIVE: | 285 | case VIDEOBUF_ACTIVE: |
274 | b->flags |= V4L2_BUF_FLAG_QUEUED; | 286 | b->flags |= V4L2_BUF_FLAG_QUEUED; |
275 | break; | 287 | break; |
276 | case VIDEOBUF_DONE: | ||
277 | case VIDEOBUF_ERROR: | 288 | case VIDEOBUF_ERROR: |
289 | b->flags |= V4L2_BUF_FLAG_ERROR; | ||
290 | /* fall through */ | ||
291 | case VIDEOBUF_DONE: | ||
278 | b->flags |= V4L2_BUF_FLAG_DONE; | 292 | b->flags |= V4L2_BUF_FLAG_DONE; |
279 | break; | 293 | break; |
280 | case VIDEOBUF_NEEDS_INIT: | 294 | case VIDEOBUF_NEEDS_INIT: |
@@ -298,20 +312,15 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, | |||
298 | static int __videobuf_mmap_free(struct videobuf_queue *q) | 312 | static int __videobuf_mmap_free(struct videobuf_queue *q) |
299 | { | 313 | { |
300 | int i; | 314 | int i; |
301 | int rc; | ||
302 | 315 | ||
303 | if (!q) | 316 | if (!q) |
304 | return 0; | 317 | return 0; |
305 | 318 | ||
306 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | 319 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); |
307 | 320 | ||
308 | 321 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | |
309 | rc = CALL(q, mmap_free, q); | 322 | if (q->bufs[i] && q->bufs[i]->map) |
310 | 323 | return -EBUSY; | |
311 | q->is_mmapped = 0; | ||
312 | |||
313 | if (rc < 0) | ||
314 | return rc; | ||
315 | 324 | ||
316 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 325 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
317 | if (NULL == q->bufs[i]) | 326 | if (NULL == q->bufs[i]) |
@@ -321,7 +330,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) | |||
321 | q->bufs[i] = NULL; | 330 | q->bufs[i] = NULL; |
322 | } | 331 | } |
323 | 332 | ||
324 | return rc; | 333 | return 0; |
325 | } | 334 | } |
326 | 335 | ||
327 | int videobuf_mmap_free(struct videobuf_queue *q) | 336 | int videobuf_mmap_free(struct videobuf_queue *q) |
@@ -332,6 +341,7 @@ int videobuf_mmap_free(struct videobuf_queue *q) | |||
332 | mutex_unlock(&q->vb_lock); | 341 | mutex_unlock(&q->vb_lock); |
333 | return ret; | 342 | return ret; |
334 | } | 343 | } |
344 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); | ||
335 | 345 | ||
336 | /* Locking: Caller holds q->vb_lock */ | 346 | /* Locking: Caller holds q->vb_lock */ |
337 | int __videobuf_mmap_setup(struct videobuf_queue *q, | 347 | int __videobuf_mmap_setup(struct videobuf_queue *q, |
@@ -351,7 +361,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, | |||
351 | for (i = 0; i < bcount; i++) { | 361 | for (i = 0; i < bcount; i++) { |
352 | q->bufs[i] = videobuf_alloc(q); | 362 | q->bufs[i] = videobuf_alloc(q); |
353 | 363 | ||
354 | if (q->bufs[i] == NULL) | 364 | if (NULL == q->bufs[i]) |
355 | break; | 365 | break; |
356 | 366 | ||
357 | q->bufs[i]->i = i; | 367 | q->bufs[i]->i = i; |
@@ -372,11 +382,11 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, | |||
372 | if (!i) | 382 | if (!i) |
373 | return -ENOMEM; | 383 | return -ENOMEM; |
374 | 384 | ||
375 | dprintk(1, "mmap setup: %d buffers, %d bytes each\n", | 385 | dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize); |
376 | i, bsize); | ||
377 | 386 | ||
378 | return i; | 387 | return i; |
379 | } | 388 | } |
389 | EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); | ||
380 | 390 | ||
381 | int videobuf_mmap_setup(struct videobuf_queue *q, | 391 | int videobuf_mmap_setup(struct videobuf_queue *q, |
382 | unsigned int bcount, unsigned int bsize, | 392 | unsigned int bcount, unsigned int bsize, |
@@ -388,6 +398,7 @@ int videobuf_mmap_setup(struct videobuf_queue *q, | |||
388 | mutex_unlock(&q->vb_lock); | 398 | mutex_unlock(&q->vb_lock); |
389 | return ret; | 399 | return ret; |
390 | } | 400 | } |
401 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); | ||
391 | 402 | ||
392 | int videobuf_reqbufs(struct videobuf_queue *q, | 403 | int videobuf_reqbufs(struct videobuf_queue *q, |
393 | struct v4l2_requestbuffers *req) | 404 | struct v4l2_requestbuffers *req) |
@@ -432,7 +443,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, | |||
432 | q->ops->buf_setup(q, &count, &size); | 443 | q->ops->buf_setup(q, &count, &size); |
433 | dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", | 444 | dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", |
434 | count, size, | 445 | count, size, |
435 | (unsigned int)((count*PAGE_ALIGN(size))>>PAGE_SHIFT) ); | 446 | (unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT)); |
436 | 447 | ||
437 | retval = __videobuf_mmap_setup(q, count, size, req->memory); | 448 | retval = __videobuf_mmap_setup(q, count, size, req->memory); |
438 | if (retval < 0) { | 449 | if (retval < 0) { |
@@ -447,6 +458,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, | |||
447 | mutex_unlock(&q->vb_lock); | 458 | mutex_unlock(&q->vb_lock); |
448 | return retval; | 459 | return retval; |
449 | } | 460 | } |
461 | EXPORT_SYMBOL_GPL(videobuf_reqbufs); | ||
450 | 462 | ||
451 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) | 463 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) |
452 | { | 464 | { |
@@ -473,9 +485,9 @@ done: | |||
473 | mutex_unlock(&q->vb_lock); | 485 | mutex_unlock(&q->vb_lock); |
474 | return ret; | 486 | return ret; |
475 | } | 487 | } |
488 | EXPORT_SYMBOL_GPL(videobuf_querybuf); | ||
476 | 489 | ||
477 | int videobuf_qbuf(struct videobuf_queue *q, | 490 | int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) |
478 | struct v4l2_buffer *b) | ||
479 | { | 491 | { |
480 | struct videobuf_buffer *buf; | 492 | struct videobuf_buffer *buf; |
481 | enum v4l2_field field; | 493 | enum v4l2_field field; |
@@ -534,6 +546,13 @@ int videobuf_qbuf(struct videobuf_queue *q, | |||
534 | "but buffer addr is zero!\n"); | 546 | "but buffer addr is zero!\n"); |
535 | goto done; | 547 | goto done; |
536 | } | 548 | } |
549 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT | ||
550 | || q->type == V4L2_BUF_TYPE_VBI_OUTPUT | ||
551 | || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | ||
552 | buf->size = b->bytesused; | ||
553 | buf->field = b->field; | ||
554 | buf->ts = b->timestamp; | ||
555 | } | ||
537 | break; | 556 | break; |
538 | case V4L2_MEMORY_USERPTR: | 557 | case V4L2_MEMORY_USERPTR: |
539 | if (b->length < buf->bsize) { | 558 | if (b->length < buf->bsize) { |
@@ -567,11 +586,11 @@ int videobuf_qbuf(struct videobuf_queue *q, | |||
567 | q->ops->buf_queue(q, buf); | 586 | q->ops->buf_queue(q, buf); |
568 | spin_unlock_irqrestore(q->irqlock, flags); | 587 | spin_unlock_irqrestore(q->irqlock, flags); |
569 | } | 588 | } |
570 | dprintk(1, "qbuf: succeded\n"); | 589 | dprintk(1, "qbuf: succeeded\n"); |
571 | retval = 0; | 590 | retval = 0; |
572 | wake_up_interruptible_sync(&q->wait); | 591 | wake_up_interruptible_sync(&q->wait); |
573 | 592 | ||
574 | done: | 593 | done: |
575 | mutex_unlock(&q->vb_lock); | 594 | mutex_unlock(&q->vb_lock); |
576 | 595 | ||
577 | if (b->memory == V4L2_MEMORY_MMAP) | 596 | if (b->memory == V4L2_MEMORY_MMAP) |
@@ -579,7 +598,7 @@ int videobuf_qbuf(struct videobuf_queue *q, | |||
579 | 598 | ||
580 | return retval; | 599 | return retval; |
581 | } | 600 | } |
582 | 601 | EXPORT_SYMBOL_GPL(videobuf_qbuf); | |
583 | 602 | ||
584 | /* Locking: Caller holds q->vb_lock */ | 603 | /* Locking: Caller holds q->vb_lock */ |
585 | static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) | 604 | static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) |
@@ -624,7 +643,6 @@ done: | |||
624 | return retval; | 643 | return retval; |
625 | } | 644 | } |
626 | 645 | ||
627 | |||
628 | /* Locking: Caller holds q->vb_lock */ | 646 | /* Locking: Caller holds q->vb_lock */ |
629 | static int stream_next_buffer(struct videobuf_queue *q, | 647 | static int stream_next_buffer(struct videobuf_queue *q, |
630 | struct videobuf_buffer **vb, int nonblocking) | 648 | struct videobuf_buffer **vb, int nonblocking) |
@@ -647,13 +665,14 @@ done: | |||
647 | } | 665 | } |
648 | 666 | ||
649 | int videobuf_dqbuf(struct videobuf_queue *q, | 667 | int videobuf_dqbuf(struct videobuf_queue *q, |
650 | struct v4l2_buffer *b, int nonblocking) | 668 | struct v4l2_buffer *b, int nonblocking) |
651 | { | 669 | { |
652 | struct videobuf_buffer *buf = NULL; | 670 | struct videobuf_buffer *buf = NULL; |
653 | int retval; | 671 | int retval; |
654 | 672 | ||
655 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | 673 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); |
656 | 674 | ||
675 | memset(b, 0, sizeof(*b)); | ||
657 | mutex_lock(&q->vb_lock); | 676 | mutex_lock(&q->vb_lock); |
658 | 677 | ||
659 | retval = stream_next_buffer(q, &buf, nonblocking); | 678 | retval = stream_next_buffer(q, &buf, nonblocking); |
@@ -665,28 +684,25 @@ int videobuf_dqbuf(struct videobuf_queue *q, | |||
665 | switch (buf->state) { | 684 | switch (buf->state) { |
666 | case VIDEOBUF_ERROR: | 685 | case VIDEOBUF_ERROR: |
667 | dprintk(1, "dqbuf: state is error\n"); | 686 | dprintk(1, "dqbuf: state is error\n"); |
668 | retval = -EIO; | ||
669 | CALL(q, sync, q, buf); | ||
670 | buf->state = VIDEOBUF_IDLE; | ||
671 | break; | 687 | break; |
672 | case VIDEOBUF_DONE: | 688 | case VIDEOBUF_DONE: |
673 | dprintk(1, "dqbuf: state is done\n"); | 689 | dprintk(1, "dqbuf: state is done\n"); |
674 | CALL(q, sync, q, buf); | ||
675 | buf->state = VIDEOBUF_IDLE; | ||
676 | break; | 690 | break; |
677 | default: | 691 | default: |
678 | dprintk(1, "dqbuf: state invalid\n"); | 692 | dprintk(1, "dqbuf: state invalid\n"); |
679 | retval = -EINVAL; | 693 | retval = -EINVAL; |
680 | goto done; | 694 | goto done; |
681 | } | 695 | } |
682 | list_del(&buf->stream); | 696 | CALL(q, sync, q, buf); |
683 | memset(b, 0, sizeof(*b)); | ||
684 | videobuf_status(q, b, buf, q->type); | 697 | videobuf_status(q, b, buf, q->type); |
685 | 698 | list_del(&buf->stream); | |
686 | done: | 699 | buf->state = VIDEOBUF_IDLE; |
700 | b->flags &= ~V4L2_BUF_FLAG_DONE; | ||
701 | done: | ||
687 | mutex_unlock(&q->vb_lock); | 702 | mutex_unlock(&q->vb_lock); |
688 | return retval; | 703 | return retval; |
689 | } | 704 | } |
705 | EXPORT_SYMBOL_GPL(videobuf_dqbuf); | ||
690 | 706 | ||
691 | int videobuf_streamon(struct videobuf_queue *q) | 707 | int videobuf_streamon(struct videobuf_queue *q) |
692 | { | 708 | { |
@@ -709,10 +725,11 @@ int videobuf_streamon(struct videobuf_queue *q) | |||
709 | spin_unlock_irqrestore(q->irqlock, flags); | 725 | spin_unlock_irqrestore(q->irqlock, flags); |
710 | 726 | ||
711 | wake_up_interruptible_sync(&q->wait); | 727 | wake_up_interruptible_sync(&q->wait); |
712 | done: | 728 | done: |
713 | mutex_unlock(&q->vb_lock); | 729 | mutex_unlock(&q->vb_lock); |
714 | return retval; | 730 | return retval; |
715 | } | 731 | } |
732 | EXPORT_SYMBOL_GPL(videobuf_streamon); | ||
716 | 733 | ||
717 | /* Locking: Caller holds q->vb_lock */ | 734 | /* Locking: Caller holds q->vb_lock */ |
718 | static int __videobuf_streamoff(struct videobuf_queue *q) | 735 | static int __videobuf_streamoff(struct videobuf_queue *q) |
@@ -735,6 +752,7 @@ int videobuf_streamoff(struct videobuf_queue *q) | |||
735 | 752 | ||
736 | return retval; | 753 | return retval; |
737 | } | 754 | } |
755 | EXPORT_SYMBOL_GPL(videobuf_streamoff); | ||
738 | 756 | ||
739 | /* Locking: Caller holds q->vb_lock */ | 757 | /* Locking: Caller holds q->vb_lock */ |
740 | static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, | 758 | static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, |
@@ -774,7 +792,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, | |||
774 | retval = q->read_buf->size; | 792 | retval = q->read_buf->size; |
775 | } | 793 | } |
776 | 794 | ||
777 | done: | 795 | done: |
778 | /* cleanup */ | 796 | /* cleanup */ |
779 | q->ops->buf_release(q, q->read_buf); | 797 | q->ops->buf_release(q, q->read_buf); |
780 | kfree(q->read_buf); | 798 | kfree(q->read_buf); |
@@ -782,6 +800,49 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, | |||
782 | return retval; | 800 | return retval; |
783 | } | 801 | } |
784 | 802 | ||
803 | static int __videobuf_copy_to_user(struct videobuf_queue *q, | ||
804 | struct videobuf_buffer *buf, | ||
805 | char __user *data, size_t count, | ||
806 | int nonblocking) | ||
807 | { | ||
808 | void *vaddr = CALL(q, vaddr, buf); | ||
809 | |||
810 | /* copy to userspace */ | ||
811 | if (count > buf->size - q->read_off) | ||
812 | count = buf->size - q->read_off; | ||
813 | |||
814 | if (copy_to_user(data, vaddr + q->read_off, count)) | ||
815 | return -EFAULT; | ||
816 | |||
817 | return count; | ||
818 | } | ||
819 | |||
820 | static int __videobuf_copy_stream(struct videobuf_queue *q, | ||
821 | struct videobuf_buffer *buf, | ||
822 | char __user *data, size_t count, size_t pos, | ||
823 | int vbihack, int nonblocking) | ||
824 | { | ||
825 | unsigned int *fc = CALL(q, vaddr, buf); | ||
826 | |||
827 | if (vbihack) { | ||
828 | /* dirty, undocumented hack -- pass the frame counter | ||
829 | * within the last four bytes of each vbi data block. | ||
830 | * We need that one to maintain backward compatibility | ||
831 | * to all vbi decoding software out there ... */ | ||
832 | fc += (buf->size >> 2) - 1; | ||
833 | *fc = buf->field_count >> 1; | ||
834 | dprintk(1, "vbihack: %d\n", *fc); | ||
835 | } | ||
836 | |||
837 | /* copy stuff using the common method */ | ||
838 | count = __videobuf_copy_to_user(q, buf, data, count, nonblocking); | ||
839 | |||
840 | if ((count == -EFAULT) && (pos == 0)) | ||
841 | return -EFAULT; | ||
842 | |||
843 | return count; | ||
844 | } | ||
845 | |||
785 | ssize_t videobuf_read_one(struct videobuf_queue *q, | 846 | ssize_t videobuf_read_one(struct videobuf_queue *q, |
786 | char __user *data, size_t count, loff_t *ppos, | 847 | char __user *data, size_t count, loff_t *ppos, |
787 | int nonblocking) | 848 | int nonblocking) |
@@ -850,7 +911,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
850 | } | 911 | } |
851 | 912 | ||
852 | /* Copy to userspace */ | 913 | /* Copy to userspace */ |
853 | retval = CALL(q, video_copy_to_user, q, data, count, nonblocking); | 914 | retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking); |
854 | if (retval < 0) | 915 | if (retval < 0) |
855 | goto done; | 916 | goto done; |
856 | 917 | ||
@@ -862,10 +923,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
862 | q->read_buf = NULL; | 923 | q->read_buf = NULL; |
863 | } | 924 | } |
864 | 925 | ||
865 | done: | 926 | done: |
866 | mutex_unlock(&q->vb_lock); | 927 | mutex_unlock(&q->vb_lock); |
867 | return retval; | 928 | return retval; |
868 | } | 929 | } |
930 | EXPORT_SYMBOL_GPL(videobuf_read_one); | ||
869 | 931 | ||
870 | /* Locking: Caller holds q->vb_lock */ | 932 | /* Locking: Caller holds q->vb_lock */ |
871 | static int __videobuf_read_start(struct videobuf_queue *q) | 933 | static int __videobuf_read_start(struct videobuf_queue *q) |
@@ -917,7 +979,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) | |||
917 | q->bufs[i] = NULL; | 979 | q->bufs[i] = NULL; |
918 | } | 980 | } |
919 | q->read_buf = NULL; | 981 | q->read_buf = NULL; |
920 | |||
921 | } | 982 | } |
922 | 983 | ||
923 | int videobuf_read_start(struct videobuf_queue *q) | 984 | int videobuf_read_start(struct videobuf_queue *q) |
@@ -930,6 +991,7 @@ int videobuf_read_start(struct videobuf_queue *q) | |||
930 | 991 | ||
931 | return rc; | 992 | return rc; |
932 | } | 993 | } |
994 | EXPORT_SYMBOL_GPL(videobuf_read_start); | ||
933 | 995 | ||
934 | void videobuf_read_stop(struct videobuf_queue *q) | 996 | void videobuf_read_stop(struct videobuf_queue *q) |
935 | { | 997 | { |
@@ -937,6 +999,7 @@ void videobuf_read_stop(struct videobuf_queue *q) | |||
937 | __videobuf_read_stop(q); | 999 | __videobuf_read_stop(q); |
938 | mutex_unlock(&q->vb_lock); | 1000 | mutex_unlock(&q->vb_lock); |
939 | } | 1001 | } |
1002 | EXPORT_SYMBOL_GPL(videobuf_read_stop); | ||
940 | 1003 | ||
941 | void videobuf_stop(struct videobuf_queue *q) | 1004 | void videobuf_stop(struct videobuf_queue *q) |
942 | { | 1005 | { |
@@ -950,7 +1013,7 @@ void videobuf_stop(struct videobuf_queue *q) | |||
950 | 1013 | ||
951 | mutex_unlock(&q->vb_lock); | 1014 | mutex_unlock(&q->vb_lock); |
952 | } | 1015 | } |
953 | 1016 | EXPORT_SYMBOL_GPL(videobuf_stop); | |
954 | 1017 | ||
955 | ssize_t videobuf_read_stream(struct videobuf_queue *q, | 1018 | ssize_t videobuf_read_stream(struct videobuf_queue *q, |
956 | char __user *data, size_t count, loff_t *ppos, | 1019 | char __user *data, size_t count, loff_t *ppos, |
@@ -990,7 +1053,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, | |||
990 | } | 1053 | } |
991 | 1054 | ||
992 | if (q->read_buf->state == VIDEOBUF_DONE) { | 1055 | if (q->read_buf->state == VIDEOBUF_DONE) { |
993 | rc = CALL(q, copy_stream, q, data + retval, count, | 1056 | rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count, |
994 | retval, vbihack, nonblocking); | 1057 | retval, vbihack, nonblocking); |
995 | if (rc < 0) { | 1058 | if (rc < 0) { |
996 | retval = rc; | 1059 | retval = rc; |
@@ -1019,10 +1082,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, | |||
1019 | break; | 1082 | break; |
1020 | } | 1083 | } |
1021 | 1084 | ||
1022 | done: | 1085 | done: |
1023 | mutex_unlock(&q->vb_lock); | 1086 | mutex_unlock(&q->vb_lock); |
1024 | return retval; | 1087 | return retval; |
1025 | } | 1088 | } |
1089 | EXPORT_SYMBOL_GPL(videobuf_read_stream); | ||
1026 | 1090 | ||
1027 | unsigned int videobuf_poll_stream(struct file *file, | 1091 | unsigned int videobuf_poll_stream(struct file *file, |
1028 | struct videobuf_queue *q, | 1092 | struct videobuf_queue *q, |
@@ -1056,27 +1120,51 @@ unsigned int videobuf_poll_stream(struct file *file, | |||
1056 | if (0 == rc) { | 1120 | if (0 == rc) { |
1057 | poll_wait(file, &buf->done, wait); | 1121 | poll_wait(file, &buf->done, wait); |
1058 | if (buf->state == VIDEOBUF_DONE || | 1122 | if (buf->state == VIDEOBUF_DONE || |
1059 | buf->state == VIDEOBUF_ERROR) | 1123 | buf->state == VIDEOBUF_ERROR) { |
1060 | rc = POLLIN|POLLRDNORM; | 1124 | switch (q->type) { |
1125 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
1126 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
1127 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
1128 | rc = POLLOUT | POLLWRNORM; | ||
1129 | break; | ||
1130 | default: | ||
1131 | rc = POLLIN | POLLRDNORM; | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1061 | } | 1135 | } |
1062 | mutex_unlock(&q->vb_lock); | 1136 | mutex_unlock(&q->vb_lock); |
1063 | return rc; | 1137 | return rc; |
1064 | } | 1138 | } |
1139 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); | ||
1065 | 1140 | ||
1066 | int videobuf_mmap_mapper(struct videobuf_queue *q, | 1141 | int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) |
1067 | struct vm_area_struct *vma) | ||
1068 | { | 1142 | { |
1069 | int retval; | 1143 | int rc = -EINVAL; |
1144 | int i; | ||
1070 | 1145 | ||
1071 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | 1146 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); |
1072 | 1147 | ||
1148 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) { | ||
1149 | dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n"); | ||
1150 | return -EINVAL; | ||
1151 | } | ||
1152 | |||
1073 | mutex_lock(&q->vb_lock); | 1153 | mutex_lock(&q->vb_lock); |
1074 | retval = CALL(q, mmap_mapper, q, vma); | 1154 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
1075 | q->is_mmapped = 1; | 1155 | struct videobuf_buffer *buf = q->bufs[i]; |
1156 | |||
1157 | if (buf && buf->memory == V4L2_MEMORY_MMAP && | ||
1158 | buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) { | ||
1159 | rc = CALL(q, mmap_mapper, q, buf, vma); | ||
1160 | break; | ||
1161 | } | ||
1162 | } | ||
1076 | mutex_unlock(&q->vb_lock); | 1163 | mutex_unlock(&q->vb_lock); |
1077 | 1164 | ||
1078 | return retval; | 1165 | return rc; |
1079 | } | 1166 | } |
1167 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); | ||
1080 | 1168 | ||
1081 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1169 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1082 | int videobuf_cgmbuf(struct videobuf_queue *q, | 1170 | int videobuf_cgmbuf(struct videobuf_queue *q, |
@@ -1107,33 +1195,3 @@ int videobuf_cgmbuf(struct videobuf_queue *q, | |||
1107 | EXPORT_SYMBOL_GPL(videobuf_cgmbuf); | 1195 | EXPORT_SYMBOL_GPL(videobuf_cgmbuf); |
1108 | #endif | 1196 | #endif |
1109 | 1197 | ||
1110 | /* --------------------------------------------------------------------- */ | ||
1111 | |||
1112 | EXPORT_SYMBOL_GPL(videobuf_waiton); | ||
1113 | EXPORT_SYMBOL_GPL(videobuf_iolock); | ||
1114 | |||
1115 | EXPORT_SYMBOL_GPL(videobuf_alloc); | ||
1116 | |||
1117 | EXPORT_SYMBOL_GPL(videobuf_queue_core_init); | ||
1118 | EXPORT_SYMBOL_GPL(videobuf_queue_cancel); | ||
1119 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); | ||
1120 | |||
1121 | EXPORT_SYMBOL_GPL(videobuf_next_field); | ||
1122 | EXPORT_SYMBOL_GPL(videobuf_reqbufs); | ||
1123 | EXPORT_SYMBOL_GPL(videobuf_querybuf); | ||
1124 | EXPORT_SYMBOL_GPL(videobuf_qbuf); | ||
1125 | EXPORT_SYMBOL_GPL(videobuf_dqbuf); | ||
1126 | EXPORT_SYMBOL_GPL(videobuf_streamon); | ||
1127 | EXPORT_SYMBOL_GPL(videobuf_streamoff); | ||
1128 | |||
1129 | EXPORT_SYMBOL_GPL(videobuf_read_start); | ||
1130 | EXPORT_SYMBOL_GPL(videobuf_read_stop); | ||
1131 | EXPORT_SYMBOL_GPL(videobuf_stop); | ||
1132 | EXPORT_SYMBOL_GPL(videobuf_read_stream); | ||
1133 | EXPORT_SYMBOL_GPL(videobuf_read_one); | ||
1134 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); | ||
1135 | |||
1136 | EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); | ||
1137 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); | ||
1138 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); | ||
1139 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); | ||
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index dce4f3aa4af1..74730c624cfc 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c | |||
@@ -55,14 +55,14 @@ static void videobuf_vm_close(struct vm_area_struct *vma) | |||
55 | struct videobuf_queue *q = map->q; | 55 | struct videobuf_queue *q = map->q; |
56 | int i; | 56 | int i; |
57 | 57 | ||
58 | dev_dbg(map->q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", | 58 | dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", |
59 | map, map->count, vma->vm_start, vma->vm_end); | 59 | map, map->count, vma->vm_start, vma->vm_end); |
60 | 60 | ||
61 | map->count--; | 61 | map->count--; |
62 | if (0 == map->count) { | 62 | if (0 == map->count) { |
63 | struct videobuf_dma_contig_memory *mem; | 63 | struct videobuf_dma_contig_memory *mem; |
64 | 64 | ||
65 | dev_dbg(map->q->dev, "munmap %p q=%p\n", map, q); | 65 | dev_dbg(q->dev, "munmap %p q=%p\n", map, q); |
66 | mutex_lock(&q->vb_lock); | 66 | mutex_lock(&q->vb_lock); |
67 | 67 | ||
68 | /* We need first to cancel streams, before unmapping */ | 68 | /* We need first to cancel streams, before unmapping */ |
@@ -89,7 +89,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) | |||
89 | /* vfree is not atomic - can't be | 89 | /* vfree is not atomic - can't be |
90 | called with IRQ's disabled | 90 | called with IRQ's disabled |
91 | */ | 91 | */ |
92 | dev_dbg(map->q->dev, "buf[%d] freeing %p\n", | 92 | dev_dbg(q->dev, "buf[%d] freeing %p\n", |
93 | i, mem->vaddr); | 93 | i, mem->vaddr); |
94 | 94 | ||
95 | dma_free_coherent(q->dev, mem->size, | 95 | dma_free_coherent(q->dev, mem->size, |
@@ -190,7 +190,7 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, | |||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | static void *__videobuf_alloc(size_t size) | 193 | static struct videobuf_buffer *__videobuf_alloc(size_t size) |
194 | { | 194 | { |
195 | struct videobuf_dma_contig_memory *mem; | 195 | struct videobuf_dma_contig_memory *mem; |
196 | struct videobuf_buffer *vb; | 196 | struct videobuf_buffer *vb; |
@@ -204,7 +204,7 @@ static void *__videobuf_alloc(size_t size) | |||
204 | return vb; | 204 | return vb; |
205 | } | 205 | } |
206 | 206 | ||
207 | static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf) | 207 | static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) |
208 | { | 208 | { |
209 | struct videobuf_dma_contig_memory *mem = buf->priv; | 209 | struct videobuf_dma_contig_memory *mem = buf->priv; |
210 | 210 | ||
@@ -263,65 +263,34 @@ static int __videobuf_iolock(struct videobuf_queue *q, | |||
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | 265 | ||
266 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
267 | { | ||
268 | unsigned int i; | ||
269 | |||
270 | dev_dbg(q->dev, "%s\n", __func__); | ||
271 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
272 | if (q->bufs[i] && q->bufs[i]->map) | ||
273 | return -EBUSY; | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, | 266 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, |
267 | struct videobuf_buffer *buf, | ||
280 | struct vm_area_struct *vma) | 268 | struct vm_area_struct *vma) |
281 | { | 269 | { |
282 | struct videobuf_dma_contig_memory *mem; | 270 | struct videobuf_dma_contig_memory *mem; |
283 | struct videobuf_mapping *map; | 271 | struct videobuf_mapping *map; |
284 | unsigned int first; | ||
285 | int retval; | 272 | int retval; |
286 | unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT; | 273 | unsigned long size; |
287 | 274 | ||
288 | dev_dbg(q->dev, "%s\n", __func__); | 275 | dev_dbg(q->dev, "%s\n", __func__); |
289 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | ||
290 | return -EINVAL; | ||
291 | |||
292 | /* look for first buffer to map */ | ||
293 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | ||
294 | if (!q->bufs[first]) | ||
295 | continue; | ||
296 | |||
297 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
298 | continue; | ||
299 | if (q->bufs[first]->boff == offset) | ||
300 | break; | ||
301 | } | ||
302 | if (VIDEO_MAX_FRAME == first) { | ||
303 | dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n", | ||
304 | offset); | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | 276 | ||
308 | /* create mapping + update buffer list */ | 277 | /* create mapping + update buffer list */ |
309 | map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); | 278 | map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); |
310 | if (!map) | 279 | if (!map) |
311 | return -ENOMEM; | 280 | return -ENOMEM; |
312 | 281 | ||
313 | q->bufs[first]->map = map; | 282 | buf->map = map; |
314 | map->start = vma->vm_start; | 283 | map->start = vma->vm_start; |
315 | map->end = vma->vm_end; | 284 | map->end = vma->vm_end; |
316 | map->q = q; | 285 | map->q = q; |
317 | 286 | ||
318 | q->bufs[first]->baddr = vma->vm_start; | 287 | buf->baddr = vma->vm_start; |
319 | 288 | ||
320 | mem = q->bufs[first]->priv; | 289 | mem = buf->priv; |
321 | BUG_ON(!mem); | 290 | BUG_ON(!mem); |
322 | MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); | 291 | MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); |
323 | 292 | ||
324 | mem->size = PAGE_ALIGN(q->bufs[first]->bsize); | 293 | mem->size = PAGE_ALIGN(buf->bsize); |
325 | mem->vaddr = dma_alloc_coherent(q->dev, mem->size, | 294 | mem->vaddr = dma_alloc_coherent(q->dev, mem->size, |
326 | &mem->dma_handle, GFP_KERNEL); | 295 | &mem->dma_handle, GFP_KERNEL); |
327 | if (!mem->vaddr) { | 296 | if (!mem->vaddr) { |
@@ -354,8 +323,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
354 | 323 | ||
355 | dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", | 324 | dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", |
356 | map, q, vma->vm_start, vma->vm_end, | 325 | map, q, vma->vm_start, vma->vm_end, |
357 | (long int) q->bufs[first]->bsize, | 326 | (long int)buf->bsize, |
358 | vma->vm_pgoff, first); | 327 | vma->vm_pgoff, buf->i); |
359 | 328 | ||
360 | videobuf_vm_open(vma); | 329 | videobuf_vm_open(vma); |
361 | 330 | ||
@@ -366,69 +335,13 @@ error: | |||
366 | return -ENOMEM; | 335 | return -ENOMEM; |
367 | } | 336 | } |
368 | 337 | ||
369 | static int __videobuf_copy_to_user(struct videobuf_queue *q, | ||
370 | char __user *data, size_t count, | ||
371 | int nonblocking) | ||
372 | { | ||
373 | struct videobuf_dma_contig_memory *mem = q->read_buf->priv; | ||
374 | void *vaddr; | ||
375 | |||
376 | BUG_ON(!mem); | ||
377 | MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); | ||
378 | BUG_ON(!mem->vaddr); | ||
379 | |||
380 | /* copy to userspace */ | ||
381 | if (count > q->read_buf->size - q->read_off) | ||
382 | count = q->read_buf->size - q->read_off; | ||
383 | |||
384 | vaddr = mem->vaddr; | ||
385 | |||
386 | if (copy_to_user(data, vaddr + q->read_off, count)) | ||
387 | return -EFAULT; | ||
388 | |||
389 | return count; | ||
390 | } | ||
391 | |||
392 | static int __videobuf_copy_stream(struct videobuf_queue *q, | ||
393 | char __user *data, size_t count, size_t pos, | ||
394 | int vbihack, int nonblocking) | ||
395 | { | ||
396 | unsigned int *fc; | ||
397 | struct videobuf_dma_contig_memory *mem = q->read_buf->priv; | ||
398 | |||
399 | BUG_ON(!mem); | ||
400 | MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); | ||
401 | |||
402 | if (vbihack) { | ||
403 | /* dirty, undocumented hack -- pass the frame counter | ||
404 | * within the last four bytes of each vbi data block. | ||
405 | * We need that one to maintain backward compatibility | ||
406 | * to all vbi decoding software out there ... */ | ||
407 | fc = (unsigned int *)mem->vaddr; | ||
408 | fc += (q->read_buf->size >> 2) - 1; | ||
409 | *fc = q->read_buf->field_count >> 1; | ||
410 | dev_dbg(q->dev, "vbihack: %d\n", *fc); | ||
411 | } | ||
412 | |||
413 | /* copy stuff using the common method */ | ||
414 | count = __videobuf_copy_to_user(q, data, count, nonblocking); | ||
415 | |||
416 | if ((count == -EFAULT) && (pos == 0)) | ||
417 | return -EFAULT; | ||
418 | |||
419 | return count; | ||
420 | } | ||
421 | |||
422 | static struct videobuf_qtype_ops qops = { | 338 | static struct videobuf_qtype_ops qops = { |
423 | .magic = MAGIC_QTYPE_OPS, | 339 | .magic = MAGIC_QTYPE_OPS, |
424 | 340 | ||
425 | .alloc = __videobuf_alloc, | 341 | .alloc = __videobuf_alloc, |
426 | .iolock = __videobuf_iolock, | 342 | .iolock = __videobuf_iolock, |
427 | .mmap_free = __videobuf_mmap_free, | ||
428 | .mmap_mapper = __videobuf_mmap_mapper, | 343 | .mmap_mapper = __videobuf_mmap_mapper, |
429 | .video_copy_to_user = __videobuf_copy_to_user, | 344 | .vaddr = __videobuf_to_vaddr, |
430 | .copy_stream = __videobuf_copy_stream, | ||
431 | .vmalloc = __videobuf_to_vmalloc, | ||
432 | }; | 345 | }; |
433 | 346 | ||
434 | void videobuf_queue_dma_contig_init(struct videobuf_queue *q, | 347 | void videobuf_queue_dma_contig_init(struct videobuf_queue *q, |
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index fcd045e7a1c1..8359e6badd36 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -37,8 +37,12 @@ | |||
37 | #define MAGIC_DMABUF 0x19721112 | 37 | #define MAGIC_DMABUF 0x19721112 |
38 | #define MAGIC_SG_MEM 0x17890714 | 38 | #define MAGIC_SG_MEM 0x17890714 |
39 | 39 | ||
40 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ | 40 | #define MAGIC_CHECK(is, should) \ |
41 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } | 41 | if (unlikely((is) != (should))) { \ |
42 | printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ | ||
43 | is, should); \ | ||
44 | BUG(); \ | ||
45 | } | ||
42 | 46 | ||
43 | static int debug; | 47 | static int debug; |
44 | module_param(debug, int, 0644); | 48 | module_param(debug, int, 0644); |
@@ -47,13 +51,13 @@ MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); | |||
47 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 51 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
48 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
49 | 53 | ||
50 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | 54 | #define dprintk(level, fmt, arg...) \ |
51 | printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) | 55 | if (debug >= level) \ |
56 | printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) | ||
52 | 57 | ||
53 | /* --------------------------------------------------------------------- */ | 58 | /* --------------------------------------------------------------------- */ |
54 | 59 | ||
55 | struct scatterlist* | 60 | struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) |
56 | videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) | ||
57 | { | 61 | { |
58 | struct scatterlist *sglist; | 62 | struct scatterlist *sglist; |
59 | struct page *pg; | 63 | struct page *pg; |
@@ -73,13 +77,14 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) | |||
73 | } | 77 | } |
74 | return sglist; | 78 | return sglist; |
75 | 79 | ||
76 | err: | 80 | err: |
77 | vfree(sglist); | 81 | vfree(sglist); |
78 | return NULL; | 82 | return NULL; |
79 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); | ||
80 | 85 | ||
81 | struct scatterlist* | 86 | struct scatterlist *videobuf_pages_to_sg(struct page **pages, int nr_pages, |
82 | videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) | 87 | int offset) |
83 | { | 88 | { |
84 | struct scatterlist *sglist; | 89 | struct scatterlist *sglist; |
85 | int i; | 90 | int i; |
@@ -104,20 +109,20 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) | |||
104 | } | 109 | } |
105 | return sglist; | 110 | return sglist; |
106 | 111 | ||
107 | nopage: | 112 | nopage: |
108 | dprintk(2,"sgl: oops - no page\n"); | 113 | dprintk(2, "sgl: oops - no page\n"); |
109 | vfree(sglist); | 114 | vfree(sglist); |
110 | return NULL; | 115 | return NULL; |
111 | 116 | ||
112 | highmem: | 117 | highmem: |
113 | dprintk(2,"sgl: oops - highmem page\n"); | 118 | dprintk(2, "sgl: oops - highmem page\n"); |
114 | vfree(sglist); | 119 | vfree(sglist); |
115 | return NULL; | 120 | return NULL; |
116 | } | 121 | } |
117 | 122 | ||
118 | /* --------------------------------------------------------------------- */ | 123 | /* --------------------------------------------------------------------- */ |
119 | 124 | ||
120 | struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) | 125 | struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf) |
121 | { | 126 | { |
122 | struct videobuf_dma_sg_memory *mem = buf->priv; | 127 | struct videobuf_dma_sg_memory *mem = buf->priv; |
123 | BUG_ON(!mem); | 128 | BUG_ON(!mem); |
@@ -126,17 +131,19 @@ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) | |||
126 | 131 | ||
127 | return &mem->dma; | 132 | return &mem->dma; |
128 | } | 133 | } |
134 | EXPORT_SYMBOL_GPL(videobuf_to_dma); | ||
129 | 135 | ||
130 | void videobuf_dma_init(struct videobuf_dmabuf *dma) | 136 | void videobuf_dma_init(struct videobuf_dmabuf *dma) |
131 | { | 137 | { |
132 | memset(dma,0,sizeof(*dma)); | 138 | memset(dma, 0, sizeof(*dma)); |
133 | dma->magic = MAGIC_DMABUF; | 139 | dma->magic = MAGIC_DMABUF; |
134 | } | 140 | } |
141 | EXPORT_SYMBOL_GPL(videobuf_dma_init); | ||
135 | 142 | ||
136 | static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, | 143 | static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, |
137 | int direction, unsigned long data, unsigned long size) | 144 | int direction, unsigned long data, unsigned long size) |
138 | { | 145 | { |
139 | unsigned long first,last; | 146 | unsigned long first, last; |
140 | int err, rw = 0; | 147 | int err, rw = 0; |
141 | 148 | ||
142 | dma->direction = direction; | 149 | dma->direction = direction; |
@@ -155,21 +162,21 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, | |||
155 | last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; | 162 | last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; |
156 | dma->offset = data & ~PAGE_MASK; | 163 | dma->offset = data & ~PAGE_MASK; |
157 | dma->nr_pages = last-first+1; | 164 | dma->nr_pages = last-first+1; |
158 | dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*), | 165 | dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL); |
159 | GFP_KERNEL); | ||
160 | if (NULL == dma->pages) | 166 | if (NULL == dma->pages) |
161 | return -ENOMEM; | 167 | return -ENOMEM; |
162 | dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", | ||
163 | data,size,dma->nr_pages); | ||
164 | 168 | ||
165 | err = get_user_pages(current,current->mm, | 169 | dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", |
170 | data, size, dma->nr_pages); | ||
171 | |||
172 | err = get_user_pages(current, current->mm, | ||
166 | data & PAGE_MASK, dma->nr_pages, | 173 | data & PAGE_MASK, dma->nr_pages, |
167 | rw == READ, 1, /* force */ | 174 | rw == READ, 1, /* force */ |
168 | dma->pages, NULL); | 175 | dma->pages, NULL); |
169 | 176 | ||
170 | if (err != dma->nr_pages) { | 177 | if (err != dma->nr_pages) { |
171 | dma->nr_pages = (err >= 0) ? err : 0; | 178 | dma->nr_pages = (err >= 0) ? err : 0; |
172 | dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages); | 179 | dprintk(1, "get_user_pages: err=%d [%d]\n", err, dma->nr_pages); |
173 | return err < 0 ? err : -EINVAL; | 180 | return err < 0 ? err : -EINVAL; |
174 | } | 181 | } |
175 | return 0; | 182 | return 0; |
@@ -179,48 +186,58 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, | |||
179 | unsigned long data, unsigned long size) | 186 | unsigned long data, unsigned long size) |
180 | { | 187 | { |
181 | int ret; | 188 | int ret; |
189 | |||
182 | down_read(¤t->mm->mmap_sem); | 190 | down_read(¤t->mm->mmap_sem); |
183 | ret = videobuf_dma_init_user_locked(dma, direction, data, size); | 191 | ret = videobuf_dma_init_user_locked(dma, direction, data, size); |
184 | up_read(¤t->mm->mmap_sem); | 192 | up_read(¤t->mm->mmap_sem); |
185 | 193 | ||
186 | return ret; | 194 | return ret; |
187 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); | ||
188 | 197 | ||
189 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | 198 | int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, |
190 | int nr_pages) | 199 | int nr_pages) |
191 | { | 200 | { |
192 | dprintk(1,"init kernel [%d pages]\n",nr_pages); | 201 | dprintk(1, "init kernel [%d pages]\n", nr_pages); |
202 | |||
193 | dma->direction = direction; | 203 | dma->direction = direction; |
194 | dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); | 204 | dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); |
195 | if (NULL == dma->vmalloc) { | 205 | if (NULL == dma->vmalloc) { |
196 | dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); | 206 | dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); |
197 | return -ENOMEM; | 207 | return -ENOMEM; |
198 | } | 208 | } |
199 | dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", | 209 | |
210 | dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", | ||
200 | (unsigned long)dma->vmalloc, | 211 | (unsigned long)dma->vmalloc, |
201 | nr_pages << PAGE_SHIFT); | 212 | nr_pages << PAGE_SHIFT); |
202 | memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); | 213 | |
214 | memset(dma->vmalloc, 0, nr_pages << PAGE_SHIFT); | ||
203 | dma->nr_pages = nr_pages; | 215 | dma->nr_pages = nr_pages; |
216 | |||
204 | return 0; | 217 | return 0; |
205 | } | 218 | } |
219 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); | ||
206 | 220 | ||
207 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | 221 | int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, |
208 | dma_addr_t addr, int nr_pages) | 222 | dma_addr_t addr, int nr_pages) |
209 | { | 223 | { |
210 | dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n", | 224 | dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n", |
211 | nr_pages,(unsigned long)addr); | 225 | nr_pages, (unsigned long)addr); |
212 | dma->direction = direction; | 226 | dma->direction = direction; |
227 | |||
213 | if (0 == addr) | 228 | if (0 == addr) |
214 | return -EINVAL; | 229 | return -EINVAL; |
215 | 230 | ||
216 | dma->bus_addr = addr; | 231 | dma->bus_addr = addr; |
217 | dma->nr_pages = nr_pages; | 232 | dma->nr_pages = nr_pages; |
233 | |||
218 | return 0; | 234 | return 0; |
219 | } | 235 | } |
236 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | ||
220 | 237 | ||
221 | int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) | 238 | int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) |
222 | { | 239 | { |
223 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | 240 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); |
224 | BUG_ON(0 == dma->nr_pages); | 241 | BUG_ON(0 == dma->nr_pages); |
225 | 242 | ||
226 | if (dma->pages) { | 243 | if (dma->pages) { |
@@ -228,20 +245,21 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) | |||
228 | dma->offset); | 245 | dma->offset); |
229 | } | 246 | } |
230 | if (dma->vmalloc) { | 247 | if (dma->vmalloc) { |
231 | dma->sglist = videobuf_vmalloc_to_sg | 248 | dma->sglist = videobuf_vmalloc_to_sg(dma->vmalloc, |
232 | (dma->vmalloc,dma->nr_pages); | 249 | dma->nr_pages); |
233 | } | 250 | } |
234 | if (dma->bus_addr) { | 251 | if (dma->bus_addr) { |
235 | dma->sglist = vmalloc(sizeof(*dma->sglist)); | 252 | dma->sglist = vmalloc(sizeof(*dma->sglist)); |
236 | if (NULL != dma->sglist) { | 253 | if (NULL != dma->sglist) { |
237 | dma->sglen = 1; | 254 | dma->sglen = 1; |
238 | sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK; | 255 | sg_dma_address(&dma->sglist[0]) = dma->bus_addr |
239 | dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; | 256 | & PAGE_MASK; |
240 | sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; | 257 | dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; |
258 | sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; | ||
241 | } | 259 | } |
242 | } | 260 | } |
243 | if (NULL == dma->sglist) { | 261 | if (NULL == dma->sglist) { |
244 | dprintk(1,"scatterlist is NULL\n"); | 262 | dprintk(1, "scatterlist is NULL\n"); |
245 | return -ENOMEM; | 263 | return -ENOMEM; |
246 | } | 264 | } |
247 | if (!dma->bus_addr) { | 265 | if (!dma->bus_addr) { |
@@ -249,47 +267,43 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) | |||
249 | dma->nr_pages, dma->direction); | 267 | dma->nr_pages, dma->direction); |
250 | if (0 == dma->sglen) { | 268 | if (0 == dma->sglen) { |
251 | printk(KERN_WARNING | 269 | printk(KERN_WARNING |
252 | "%s: videobuf_map_sg failed\n",__func__); | 270 | "%s: videobuf_map_sg failed\n", __func__); |
253 | vfree(dma->sglist); | 271 | vfree(dma->sglist); |
254 | dma->sglist = NULL; | 272 | dma->sglist = NULL; |
255 | dma->sglen = 0; | 273 | dma->sglen = 0; |
256 | return -ENOMEM; | 274 | return -ENOMEM; |
257 | } | 275 | } |
258 | } | 276 | } |
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | ||
263 | { | ||
264 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); | ||
265 | BUG_ON(!dma->sglen); | ||
266 | 277 | ||
267 | dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); | ||
268 | return 0; | 278 | return 0; |
269 | } | 279 | } |
280 | EXPORT_SYMBOL_GPL(videobuf_dma_map); | ||
270 | 281 | ||
271 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) | 282 | int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma) |
272 | { | 283 | { |
273 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); | 284 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); |
285 | |||
274 | if (!dma->sglen) | 286 | if (!dma->sglen) |
275 | return 0; | 287 | return 0; |
276 | 288 | ||
277 | dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); | 289 | dma_unmap_sg(q->dev, dma->sglist, dma->sglen, dma->direction); |
278 | 290 | ||
279 | vfree(dma->sglist); | 291 | vfree(dma->sglist); |
280 | dma->sglist = NULL; | 292 | dma->sglist = NULL; |
281 | dma->sglen = 0; | 293 | dma->sglen = 0; |
294 | |||
282 | return 0; | 295 | return 0; |
283 | } | 296 | } |
297 | EXPORT_SYMBOL_GPL(videobuf_dma_unmap); | ||
284 | 298 | ||
285 | int videobuf_dma_free(struct videobuf_dmabuf *dma) | 299 | int videobuf_dma_free(struct videobuf_dmabuf *dma) |
286 | { | 300 | { |
287 | MAGIC_CHECK(dma->magic,MAGIC_DMABUF); | 301 | int i; |
302 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); | ||
288 | BUG_ON(dma->sglen); | 303 | BUG_ON(dma->sglen); |
289 | 304 | ||
290 | if (dma->pages) { | 305 | if (dma->pages) { |
291 | int i; | 306 | for (i = 0; i < dma->nr_pages; i++) |
292 | for (i=0; i < dma->nr_pages; i++) | ||
293 | page_cache_release(dma->pages[i]); | 307 | page_cache_release(dma->pages[i]); |
294 | kfree(dma->pages); | 308 | kfree(dma->pages); |
295 | dma->pages = NULL; | 309 | dma->pages = NULL; |
@@ -298,12 +312,13 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) | |||
298 | vfree(dma->vmalloc); | 312 | vfree(dma->vmalloc); |
299 | dma->vmalloc = NULL; | 313 | dma->vmalloc = NULL; |
300 | 314 | ||
301 | if (dma->bus_addr) { | 315 | if (dma->bus_addr) |
302 | dma->bus_addr = 0; | 316 | dma->bus_addr = 0; |
303 | } | ||
304 | dma->direction = DMA_NONE; | 317 | dma->direction = DMA_NONE; |
318 | |||
305 | return 0; | 319 | return 0; |
306 | } | 320 | } |
321 | EXPORT_SYMBOL_GPL(videobuf_dma_free); | ||
307 | 322 | ||
308 | /* --------------------------------------------------------------------- */ | 323 | /* --------------------------------------------------------------------- */ |
309 | 324 | ||
@@ -315,6 +330,7 @@ int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) | |||
315 | 330 | ||
316 | return videobuf_dma_map(&q, dma); | 331 | return videobuf_dma_map(&q, dma); |
317 | } | 332 | } |
333 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); | ||
318 | 334 | ||
319 | int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) | 335 | int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) |
320 | { | 336 | { |
@@ -324,49 +340,48 @@ int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) | |||
324 | 340 | ||
325 | return videobuf_dma_unmap(&q, dma); | 341 | return videobuf_dma_unmap(&q, dma); |
326 | } | 342 | } |
343 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); | ||
327 | 344 | ||
328 | /* --------------------------------------------------------------------- */ | 345 | /* --------------------------------------------------------------------- */ |
329 | 346 | ||
330 | static void | 347 | static void videobuf_vm_open(struct vm_area_struct *vma) |
331 | videobuf_vm_open(struct vm_area_struct *vma) | ||
332 | { | 348 | { |
333 | struct videobuf_mapping *map = vma->vm_private_data; | 349 | struct videobuf_mapping *map = vma->vm_private_data; |
334 | 350 | ||
335 | dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, | 351 | dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map, |
336 | map->count,vma->vm_start,vma->vm_end); | 352 | map->count, vma->vm_start, vma->vm_end); |
353 | |||
337 | map->count++; | 354 | map->count++; |
338 | } | 355 | } |
339 | 356 | ||
340 | static void | 357 | static void videobuf_vm_close(struct vm_area_struct *vma) |
341 | videobuf_vm_close(struct vm_area_struct *vma) | ||
342 | { | 358 | { |
343 | struct videobuf_mapping *map = vma->vm_private_data; | 359 | struct videobuf_mapping *map = vma->vm_private_data; |
344 | struct videobuf_queue *q = map->q; | 360 | struct videobuf_queue *q = map->q; |
345 | struct videobuf_dma_sg_memory *mem; | 361 | struct videobuf_dma_sg_memory *mem; |
346 | int i; | 362 | int i; |
347 | 363 | ||
348 | dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, | 364 | dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map, |
349 | map->count,vma->vm_start,vma->vm_end); | 365 | map->count, vma->vm_start, vma->vm_end); |
350 | 366 | ||
351 | map->count--; | 367 | map->count--; |
352 | if (0 == map->count) { | 368 | if (0 == map->count) { |
353 | dprintk(1,"munmap %p q=%p\n",map,q); | 369 | dprintk(1, "munmap %p q=%p\n", map, q); |
354 | mutex_lock(&q->vb_lock); | 370 | mutex_lock(&q->vb_lock); |
355 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 371 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
356 | if (NULL == q->bufs[i]) | 372 | if (NULL == q->bufs[i]) |
357 | continue; | 373 | continue; |
358 | mem=q->bufs[i]->priv; | 374 | mem = q->bufs[i]->priv; |
359 | |||
360 | if (!mem) | 375 | if (!mem) |
361 | continue; | 376 | continue; |
362 | 377 | ||
363 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | 378 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); |
364 | 379 | ||
365 | if (q->bufs[i]->map != map) | 380 | if (q->bufs[i]->map != map) |
366 | continue; | 381 | continue; |
367 | q->bufs[i]->map = NULL; | 382 | q->bufs[i]->map = NULL; |
368 | q->bufs[i]->baddr = 0; | 383 | q->bufs[i]->baddr = 0; |
369 | q->ops->buf_release(q,q->bufs[i]); | 384 | q->ops->buf_release(q, q->bufs[i]); |
370 | } | 385 | } |
371 | mutex_unlock(&q->vb_lock); | 386 | mutex_unlock(&q->vb_lock); |
372 | kfree(map); | 387 | kfree(map); |
@@ -380,26 +395,27 @@ videobuf_vm_close(struct vm_area_struct *vma) | |||
380 | * now ...). Bounce buffers don't work very well for the data rates | 395 | * now ...). Bounce buffers don't work very well for the data rates |
381 | * video capture has. | 396 | * video capture has. |
382 | */ | 397 | */ |
383 | static int | 398 | static int videobuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
384 | videobuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
385 | { | 399 | { |
386 | struct page *page; | 400 | struct page *page; |
387 | 401 | ||
388 | dprintk(3,"fault: fault @ %08lx [vma %08lx-%08lx]\n", | 402 | dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n", |
389 | (unsigned long)vmf->virtual_address,vma->vm_start,vma->vm_end); | 403 | (unsigned long)vmf->virtual_address, |
404 | vma->vm_start, vma->vm_end); | ||
405 | |||
390 | page = alloc_page(GFP_USER | __GFP_DMA32); | 406 | page = alloc_page(GFP_USER | __GFP_DMA32); |
391 | if (!page) | 407 | if (!page) |
392 | return VM_FAULT_OOM; | 408 | return VM_FAULT_OOM; |
393 | clear_user_highpage(page, (unsigned long)vmf->virtual_address); | 409 | clear_user_highpage(page, (unsigned long)vmf->virtual_address); |
394 | vmf->page = page; | 410 | vmf->page = page; |
411 | |||
395 | return 0; | 412 | return 0; |
396 | } | 413 | } |
397 | 414 | ||
398 | static const struct vm_operations_struct videobuf_vm_ops = | 415 | static const struct vm_operations_struct videobuf_vm_ops = { |
399 | { | 416 | .open = videobuf_vm_open, |
400 | .open = videobuf_vm_open, | 417 | .close = videobuf_vm_close, |
401 | .close = videobuf_vm_close, | 418 | .fault = videobuf_vm_fault, |
402 | .fault = videobuf_vm_fault, | ||
403 | }; | 419 | }; |
404 | 420 | ||
405 | /* --------------------------------------------------------------------- | 421 | /* --------------------------------------------------------------------- |
@@ -412,28 +428,28 @@ static const struct vm_operations_struct videobuf_vm_ops = | |||
412 | struct videobuf_dma_sg_memory | 428 | struct videobuf_dma_sg_memory |
413 | */ | 429 | */ |
414 | 430 | ||
415 | static void *__videobuf_alloc(size_t size) | 431 | static struct videobuf_buffer *__videobuf_alloc(size_t size) |
416 | { | 432 | { |
417 | struct videobuf_dma_sg_memory *mem; | 433 | struct videobuf_dma_sg_memory *mem; |
418 | struct videobuf_buffer *vb; | 434 | struct videobuf_buffer *vb; |
419 | 435 | ||
420 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 436 | vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); |
421 | if (!vb) | 437 | if (!vb) |
422 | return vb; | 438 | return vb; |
423 | 439 | ||
424 | mem = vb->priv = ((char *)vb)+size; | 440 | mem = vb->priv = ((char *)vb) + size; |
425 | mem->magic=MAGIC_SG_MEM; | 441 | mem->magic = MAGIC_SG_MEM; |
426 | 442 | ||
427 | videobuf_dma_init(&mem->dma); | 443 | videobuf_dma_init(&mem->dma); |
428 | 444 | ||
429 | dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", | 445 | dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", |
430 | __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), | 446 | __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), |
431 | mem,(long)sizeof(*mem)); | 447 | mem, (long)sizeof(*mem)); |
432 | 448 | ||
433 | return vb; | 449 | return vb; |
434 | } | 450 | } |
435 | 451 | ||
436 | static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) | 452 | static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) |
437 | { | 453 | { |
438 | struct videobuf_dma_sg_memory *mem = buf->priv; | 454 | struct videobuf_dma_sg_memory *mem = buf->priv; |
439 | BUG_ON(!mem); | 455 | BUG_ON(!mem); |
@@ -443,11 +459,11 @@ static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) | |||
443 | return mem->dma.vmalloc; | 459 | return mem->dma.vmalloc; |
444 | } | 460 | } |
445 | 461 | ||
446 | static int __videobuf_iolock (struct videobuf_queue* q, | 462 | static int __videobuf_iolock(struct videobuf_queue *q, |
447 | struct videobuf_buffer *vb, | 463 | struct videobuf_buffer *vb, |
448 | struct v4l2_framebuffer *fbuf) | 464 | struct v4l2_framebuffer *fbuf) |
449 | { | 465 | { |
450 | int err,pages; | 466 | int err, pages; |
451 | dma_addr_t bus; | 467 | dma_addr_t bus; |
452 | struct videobuf_dma_sg_memory *mem = vb->priv; | 468 | struct videobuf_dma_sg_memory *mem = vb->priv; |
453 | BUG_ON(!mem); | 469 | BUG_ON(!mem); |
@@ -460,16 +476,16 @@ static int __videobuf_iolock (struct videobuf_queue* q, | |||
460 | if (0 == vb->baddr) { | 476 | if (0 == vb->baddr) { |
461 | /* no userspace addr -- kernel bounce buffer */ | 477 | /* no userspace addr -- kernel bounce buffer */ |
462 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; | 478 | pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; |
463 | err = videobuf_dma_init_kernel( &mem->dma, | 479 | err = videobuf_dma_init_kernel(&mem->dma, |
464 | DMA_FROM_DEVICE, | 480 | DMA_FROM_DEVICE, |
465 | pages ); | 481 | pages); |
466 | if (0 != err) | 482 | if (0 != err) |
467 | return err; | 483 | return err; |
468 | } else if (vb->memory == V4L2_MEMORY_USERPTR) { | 484 | } else if (vb->memory == V4L2_MEMORY_USERPTR) { |
469 | /* dma directly to userspace */ | 485 | /* dma directly to userspace */ |
470 | err = videobuf_dma_init_user( &mem->dma, | 486 | err = videobuf_dma_init_user(&mem->dma, |
471 | DMA_FROM_DEVICE, | 487 | DMA_FROM_DEVICE, |
472 | vb->baddr,vb->bsize ); | 488 | vb->baddr, vb->bsize); |
473 | if (0 != err) | 489 | if (0 != err) |
474 | return err; | 490 | return err; |
475 | } else { | 491 | } else { |
@@ -515,43 +531,27 @@ static int __videobuf_sync(struct videobuf_queue *q, | |||
515 | struct videobuf_buffer *buf) | 531 | struct videobuf_buffer *buf) |
516 | { | 532 | { |
517 | struct videobuf_dma_sg_memory *mem = buf->priv; | 533 | struct videobuf_dma_sg_memory *mem = buf->priv; |
518 | BUG_ON(!mem); | 534 | BUG_ON(!mem || !mem->dma.sglen); |
519 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
520 | 535 | ||
521 | return videobuf_dma_sync(q,&mem->dma); | 536 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); |
522 | } | 537 | MAGIC_CHECK(mem->dma.magic, MAGIC_DMABUF); |
523 | |||
524 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
525 | { | ||
526 | int i; | ||
527 | 538 | ||
528 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 539 | dma_sync_sg_for_cpu(q->dev, mem->dma.sglist, |
529 | if (q->bufs[i]) { | 540 | mem->dma.sglen, mem->dma.direction); |
530 | if (q->bufs[i]->map) | ||
531 | return -EBUSY; | ||
532 | } | ||
533 | } | ||
534 | 541 | ||
535 | return 0; | 542 | return 0; |
536 | } | 543 | } |
537 | 544 | ||
538 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, | 545 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, |
539 | struct vm_area_struct *vma) | 546 | struct videobuf_buffer *buf, |
547 | struct vm_area_struct *vma) | ||
540 | { | 548 | { |
541 | struct videobuf_dma_sg_memory *mem; | 549 | struct videobuf_dma_sg_memory *mem = buf->priv; |
542 | struct videobuf_mapping *map; | 550 | struct videobuf_mapping *map; |
543 | unsigned int first,last,size,i; | 551 | unsigned int first, last, size = 0, i; |
544 | int retval; | 552 | int retval; |
545 | 553 | ||
546 | retval = -EINVAL; | 554 | retval = -EINVAL; |
547 | if (!(vma->vm_flags & VM_WRITE)) { | ||
548 | dprintk(1,"mmap app bug: PROT_WRITE please\n"); | ||
549 | goto done; | ||
550 | } | ||
551 | if (!(vma->vm_flags & VM_SHARED)) { | ||
552 | dprintk(1,"mmap app bug: MAP_SHARED please\n"); | ||
553 | goto done; | ||
554 | } | ||
555 | 555 | ||
556 | /* This function maintains backwards compatibility with V4L1 and will | 556 | /* This function maintains backwards compatibility with V4L1 and will |
557 | * map more than one buffer if the vma length is equal to the combined | 557 | * map more than one buffer if the vma length is equal to the combined |
@@ -561,48 +561,52 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
561 | * TODO: Allow drivers to specify if they support this mode | 561 | * TODO: Allow drivers to specify if they support this mode |
562 | */ | 562 | */ |
563 | 563 | ||
564 | BUG_ON(!mem); | ||
565 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); | ||
566 | |||
564 | /* look for first buffer to map */ | 567 | /* look for first buffer to map */ |
565 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | 568 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { |
566 | if (NULL == q->bufs[first]) | 569 | if (buf == q->bufs[first]) { |
567 | continue; | 570 | size = PAGE_ALIGN(q->bufs[first]->bsize); |
568 | mem=q->bufs[first]->priv; | ||
569 | BUG_ON(!mem); | ||
570 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
571 | |||
572 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
573 | continue; | ||
574 | if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) | ||
575 | break; | 571 | break; |
572 | } | ||
576 | } | 573 | } |
577 | if (VIDEO_MAX_FRAME == first) { | 574 | |
578 | dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", | 575 | /* paranoia, should never happen since buf is always valid. */ |
579 | (vma->vm_pgoff << PAGE_SHIFT)); | 576 | if (!size) { |
577 | dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", | ||
578 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
580 | goto done; | 579 | goto done; |
581 | } | 580 | } |
582 | 581 | ||
583 | /* look for last buffer to map */ | 582 | last = first; |
584 | for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { | 583 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
585 | if (NULL == q->bufs[last]) | 584 | if (size != (vma->vm_end - vma->vm_start)) { |
586 | continue; | 585 | /* look for last buffer to map */ |
587 | if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) | 586 | for (last = first + 1; last < VIDEO_MAX_FRAME; last++) { |
588 | continue; | 587 | if (NULL == q->bufs[last]) |
589 | if (q->bufs[last]->map) { | 588 | continue; |
590 | retval = -EBUSY; | 589 | if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) |
590 | continue; | ||
591 | if (q->bufs[last]->map) { | ||
592 | retval = -EBUSY; | ||
593 | goto done; | ||
594 | } | ||
595 | size += PAGE_ALIGN(q->bufs[last]->bsize); | ||
596 | if (size == (vma->vm_end - vma->vm_start)) | ||
597 | break; | ||
598 | } | ||
599 | if (VIDEO_MAX_FRAME == last) { | ||
600 | dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", | ||
601 | (vma->vm_end - vma->vm_start)); | ||
591 | goto done; | 602 | goto done; |
592 | } | 603 | } |
593 | size += PAGE_ALIGN(q->bufs[last]->bsize); | ||
594 | if (size == (vma->vm_end - vma->vm_start)) | ||
595 | break; | ||
596 | } | ||
597 | if (VIDEO_MAX_FRAME == last) { | ||
598 | dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n", | ||
599 | (vma->vm_end - vma->vm_start)); | ||
600 | goto done; | ||
601 | } | 604 | } |
605 | #endif | ||
602 | 606 | ||
603 | /* create mapping + update buffer list */ | 607 | /* create mapping + update buffer list */ |
604 | retval = -ENOMEM; | 608 | retval = -ENOMEM; |
605 | map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); | 609 | map = kmalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); |
606 | if (NULL == map) | 610 | if (NULL == map) |
607 | goto done; | 611 | goto done; |
608 | 612 | ||
@@ -623,72 +627,22 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
623 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | 627 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; |
624 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ | 628 | vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ |
625 | vma->vm_private_data = map; | 629 | vma->vm_private_data = map; |
626 | dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", | 630 | dprintk(1, "mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", |
627 | map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); | 631 | map, q, vma->vm_start, vma->vm_end, vma->vm_pgoff, first, last); |
628 | retval = 0; | 632 | retval = 0; |
629 | 633 | ||
630 | done: | 634 | done: |
631 | return retval; | 635 | return retval; |
632 | } | 636 | } |
633 | 637 | ||
634 | static int __videobuf_copy_to_user ( struct videobuf_queue *q, | ||
635 | char __user *data, size_t count, | ||
636 | int nonblocking ) | ||
637 | { | ||
638 | struct videobuf_dma_sg_memory *mem = q->read_buf->priv; | ||
639 | BUG_ON(!mem); | ||
640 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
641 | |||
642 | /* copy to userspace */ | ||
643 | if (count > q->read_buf->size - q->read_off) | ||
644 | count = q->read_buf->size - q->read_off; | ||
645 | |||
646 | if (copy_to_user(data, mem->dma.vmalloc+q->read_off, count)) | ||
647 | return -EFAULT; | ||
648 | |||
649 | return count; | ||
650 | } | ||
651 | |||
652 | static int __videobuf_copy_stream ( struct videobuf_queue *q, | ||
653 | char __user *data, size_t count, size_t pos, | ||
654 | int vbihack, int nonblocking ) | ||
655 | { | ||
656 | unsigned int *fc; | ||
657 | struct videobuf_dma_sg_memory *mem = q->read_buf->priv; | ||
658 | BUG_ON(!mem); | ||
659 | MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); | ||
660 | |||
661 | if (vbihack) { | ||
662 | /* dirty, undocumented hack -- pass the frame counter | ||
663 | * within the last four bytes of each vbi data block. | ||
664 | * We need that one to maintain backward compatibility | ||
665 | * to all vbi decoding software out there ... */ | ||
666 | fc = (unsigned int*)mem->dma.vmalloc; | ||
667 | fc += (q->read_buf->size>>2) -1; | ||
668 | *fc = q->read_buf->field_count >> 1; | ||
669 | dprintk(1,"vbihack: %d\n",*fc); | ||
670 | } | ||
671 | |||
672 | /* copy stuff using the common method */ | ||
673 | count = __videobuf_copy_to_user (q,data,count,nonblocking); | ||
674 | |||
675 | if ( (count==-EFAULT) && (0 == pos) ) | ||
676 | return -EFAULT; | ||
677 | |||
678 | return count; | ||
679 | } | ||
680 | |||
681 | static struct videobuf_qtype_ops sg_ops = { | 638 | static struct videobuf_qtype_ops sg_ops = { |
682 | .magic = MAGIC_QTYPE_OPS, | 639 | .magic = MAGIC_QTYPE_OPS, |
683 | 640 | ||
684 | .alloc = __videobuf_alloc, | 641 | .alloc = __videobuf_alloc, |
685 | .iolock = __videobuf_iolock, | 642 | .iolock = __videobuf_iolock, |
686 | .sync = __videobuf_sync, | 643 | .sync = __videobuf_sync, |
687 | .mmap_free = __videobuf_mmap_free, | ||
688 | .mmap_mapper = __videobuf_mmap_mapper, | 644 | .mmap_mapper = __videobuf_mmap_mapper, |
689 | .video_copy_to_user = __videobuf_copy_to_user, | 645 | .vaddr = __videobuf_to_vaddr, |
690 | .copy_stream = __videobuf_copy_stream, | ||
691 | .vmalloc = __videobuf_to_vmalloc, | ||
692 | }; | 646 | }; |
693 | 647 | ||
694 | void *videobuf_sg_alloc(size_t size) | 648 | void *videobuf_sg_alloc(size_t size) |
@@ -702,8 +656,9 @@ void *videobuf_sg_alloc(size_t size) | |||
702 | 656 | ||
703 | return videobuf_alloc(&q); | 657 | return videobuf_alloc(&q); |
704 | } | 658 | } |
659 | EXPORT_SYMBOL_GPL(videobuf_sg_alloc); | ||
705 | 660 | ||
706 | void videobuf_queue_sg_init(struct videobuf_queue* q, | 661 | void videobuf_queue_sg_init(struct videobuf_queue *q, |
707 | const struct videobuf_queue_ops *ops, | 662 | const struct videobuf_queue_ops *ops, |
708 | struct device *dev, | 663 | struct device *dev, |
709 | spinlock_t *irqlock, | 664 | spinlock_t *irqlock, |
@@ -715,29 +670,5 @@ void videobuf_queue_sg_init(struct videobuf_queue* q, | |||
715 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, | 670 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, |
716 | priv, &sg_ops); | 671 | priv, &sg_ops); |
717 | } | 672 | } |
718 | |||
719 | /* --------------------------------------------------------------------- */ | ||
720 | |||
721 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); | ||
722 | |||
723 | EXPORT_SYMBOL_GPL(videobuf_to_dma); | ||
724 | EXPORT_SYMBOL_GPL(videobuf_dma_init); | ||
725 | EXPORT_SYMBOL_GPL(videobuf_dma_init_user); | ||
726 | EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); | ||
727 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | ||
728 | EXPORT_SYMBOL_GPL(videobuf_dma_map); | ||
729 | EXPORT_SYMBOL_GPL(videobuf_dma_sync); | ||
730 | EXPORT_SYMBOL_GPL(videobuf_dma_unmap); | ||
731 | EXPORT_SYMBOL_GPL(videobuf_dma_free); | ||
732 | |||
733 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); | ||
734 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); | ||
735 | EXPORT_SYMBOL_GPL(videobuf_sg_alloc); | ||
736 | |||
737 | EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); | 673 | EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); |
738 | 674 | ||
739 | /* | ||
740 | * Local variables: | ||
741 | * c-basic-offset: 8 | ||
742 | * End: | ||
743 | */ | ||
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0afb62e63d99..3f76398968b8 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c | |||
@@ -67,7 +67,7 @@ static int videobuf_dvb_thread(void *data) | |||
67 | try_to_freeze(); | 67 | try_to_freeze(); |
68 | 68 | ||
69 | /* feed buffer data to demux */ | 69 | /* feed buffer data to demux */ |
70 | outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf); | 70 | outp = videobuf_queue_to_vaddr(&dvb->dvbq, buf); |
71 | 71 | ||
72 | if (buf->state == VIDEOBUF_DONE) | 72 | if (buf->state == VIDEOBUF_DONE) |
73 | dvb_dmx_swfilter(&dvb->demux, outp, | 73 | dvb_dmx_swfilter(&dvb->demux, outp, |
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 136e09383c06..583728f4c221 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -30,8 +30,12 @@ | |||
30 | #define MAGIC_DMABUF 0x17760309 | 30 | #define MAGIC_DMABUF 0x17760309 |
31 | #define MAGIC_VMAL_MEM 0x18221223 | 31 | #define MAGIC_VMAL_MEM 0x18221223 |
32 | 32 | ||
33 | #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ | 33 | #define MAGIC_CHECK(is, should) \ |
34 | { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } | 34 | if (unlikely((is) != (should))) { \ |
35 | printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ | ||
36 | is, should); \ | ||
37 | BUG(); \ | ||
38 | } | ||
35 | 39 | ||
36 | static int debug; | 40 | static int debug; |
37 | module_param(debug, int, 0644); | 41 | module_param(debug, int, 0644); |
@@ -40,19 +44,19 @@ MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); | |||
40 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 44 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
41 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
42 | 46 | ||
43 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | 47 | #define dprintk(level, fmt, arg...) \ |
44 | printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) | 48 | if (debug >= level) \ |
49 | printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) | ||
45 | 50 | ||
46 | 51 | ||
47 | /***************************************************************************/ | 52 | /***************************************************************************/ |
48 | 53 | ||
49 | static void | 54 | static void videobuf_vm_open(struct vm_area_struct *vma) |
50 | videobuf_vm_open(struct vm_area_struct *vma) | ||
51 | { | 55 | { |
52 | struct videobuf_mapping *map = vma->vm_private_data; | 56 | struct videobuf_mapping *map = vma->vm_private_data; |
53 | 57 | ||
54 | dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map, | 58 | dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, |
55 | map->count,vma->vm_start,vma->vm_end); | 59 | map->count, vma->vm_start, vma->vm_end); |
56 | 60 | ||
57 | map->count++; | 61 | map->count++; |
58 | } | 62 | } |
@@ -63,7 +67,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) | |||
63 | struct videobuf_queue *q = map->q; | 67 | struct videobuf_queue *q = map->q; |
64 | int i; | 68 | int i; |
65 | 69 | ||
66 | dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, | 70 | dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, |
67 | map->count, vma->vm_start, vma->vm_end); | 71 | map->count, vma->vm_start, vma->vm_end); |
68 | 72 | ||
69 | map->count--; | 73 | map->count--; |
@@ -116,8 +120,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) | |||
116 | return; | 120 | return; |
117 | } | 121 | } |
118 | 122 | ||
119 | static const struct vm_operations_struct videobuf_vm_ops = | 123 | static const struct vm_operations_struct videobuf_vm_ops = { |
120 | { | ||
121 | .open = videobuf_vm_open, | 124 | .open = videobuf_vm_open, |
122 | .close = videobuf_vm_close, | 125 | .close = videobuf_vm_close, |
123 | }; | 126 | }; |
@@ -132,28 +135,28 @@ static const struct vm_operations_struct videobuf_vm_ops = | |||
132 | struct videobuf_dma_sg_memory | 135 | struct videobuf_dma_sg_memory |
133 | */ | 136 | */ |
134 | 137 | ||
135 | static void *__videobuf_alloc(size_t size) | 138 | static struct videobuf_buffer *__videobuf_alloc(size_t size) |
136 | { | 139 | { |
137 | struct videobuf_vmalloc_memory *mem; | 140 | struct videobuf_vmalloc_memory *mem; |
138 | struct videobuf_buffer *vb; | 141 | struct videobuf_buffer *vb; |
139 | 142 | ||
140 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 143 | vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); |
141 | if (!vb) | 144 | if (!vb) |
142 | return vb; | 145 | return vb; |
143 | 146 | ||
144 | mem = vb->priv = ((char *)vb)+size; | 147 | mem = vb->priv = ((char *)vb) + size; |
145 | mem->magic=MAGIC_VMAL_MEM; | 148 | mem->magic = MAGIC_VMAL_MEM; |
146 | 149 | ||
147 | dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", | 150 | dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", |
148 | __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), | 151 | __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), |
149 | mem,(long)sizeof(*mem)); | 152 | mem, (long)sizeof(*mem)); |
150 | 153 | ||
151 | return vb; | 154 | return vb; |
152 | } | 155 | } |
153 | 156 | ||
154 | static int __videobuf_iolock (struct videobuf_queue* q, | 157 | static int __videobuf_iolock(struct videobuf_queue *q, |
155 | struct videobuf_buffer *vb, | 158 | struct videobuf_buffer *vb, |
156 | struct v4l2_framebuffer *fbuf) | 159 | struct v4l2_framebuffer *fbuf) |
157 | { | 160 | { |
158 | struct videobuf_vmalloc_memory *mem = vb->priv; | 161 | struct videobuf_vmalloc_memory *mem = vb->priv; |
159 | int pages; | 162 | int pages; |
@@ -177,15 +180,13 @@ static int __videobuf_iolock (struct videobuf_queue* q, | |||
177 | 180 | ||
178 | dprintk(1, "%s memory method USERPTR\n", __func__); | 181 | dprintk(1, "%s memory method USERPTR\n", __func__); |
179 | 182 | ||
180 | #if 1 | ||
181 | if (vb->baddr) { | 183 | if (vb->baddr) { |
182 | printk(KERN_ERR "USERPTR is currently not supported\n"); | 184 | printk(KERN_ERR "USERPTR is currently not supported\n"); |
183 | return -EINVAL; | 185 | return -EINVAL; |
184 | } | 186 | } |
185 | #endif | ||
186 | 187 | ||
187 | /* The only USERPTR currently supported is the one needed for | 188 | /* The only USERPTR currently supported is the one needed for |
188 | read() method. | 189 | * read() method. |
189 | */ | 190 | */ |
190 | 191 | ||
191 | mem->vmalloc = vmalloc_user(pages); | 192 | mem->vmalloc = vmalloc_user(pages); |
@@ -210,7 +211,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, | |||
210 | /* Try to remap memory */ | 211 | /* Try to remap memory */ |
211 | rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); | 212 | rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); |
212 | if (rc < 0) { | 213 | if (rc < 0) { |
213 | printk(KERN_ERR "mmap: remap failed with error %d. ", rc); | 214 | printk(KERN_ERR "mmap: remap failed with error %d", rc); |
214 | return -ENOMEM; | 215 | return -ENOMEM; |
215 | } | 216 | } |
216 | #endif | 217 | #endif |
@@ -228,69 +229,29 @@ static int __videobuf_iolock (struct videobuf_queue* q, | |||
228 | return 0; | 229 | return 0; |
229 | } | 230 | } |
230 | 231 | ||
231 | static int __videobuf_sync(struct videobuf_queue *q, | ||
232 | struct videobuf_buffer *buf) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
238 | { | ||
239 | unsigned int i; | ||
240 | |||
241 | dprintk(1, "%s\n", __func__); | ||
242 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
243 | if (q->bufs[i]) { | ||
244 | if (q->bufs[i]->map) | ||
245 | return -EBUSY; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, | 232 | static int __videobuf_mmap_mapper(struct videobuf_queue *q, |
253 | struct vm_area_struct *vma) | 233 | struct videobuf_buffer *buf, |
234 | struct vm_area_struct *vma) | ||
254 | { | 235 | { |
255 | struct videobuf_vmalloc_memory *mem; | 236 | struct videobuf_vmalloc_memory *mem; |
256 | struct videobuf_mapping *map; | 237 | struct videobuf_mapping *map; |
257 | unsigned int first; | ||
258 | int retval, pages; | 238 | int retval, pages; |
259 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
260 | 239 | ||
261 | dprintk(1, "%s\n", __func__); | 240 | dprintk(1, "%s\n", __func__); |
262 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | ||
263 | return -EINVAL; | ||
264 | |||
265 | /* look for first buffer to map */ | ||
266 | for (first = 0; first < VIDEO_MAX_FRAME; first++) { | ||
267 | if (NULL == q->bufs[first]) | ||
268 | continue; | ||
269 | |||
270 | if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) | ||
271 | continue; | ||
272 | if (q->bufs[first]->boff == offset) | ||
273 | break; | ||
274 | } | ||
275 | if (VIDEO_MAX_FRAME == first) { | ||
276 | dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", | ||
277 | (vma->vm_pgoff << PAGE_SHIFT)); | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | 241 | ||
281 | /* create mapping + update buffer list */ | 242 | /* create mapping + update buffer list */ |
282 | map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); | 243 | map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); |
283 | if (NULL == map) | 244 | if (NULL == map) |
284 | return -ENOMEM; | 245 | return -ENOMEM; |
285 | 246 | ||
286 | q->bufs[first]->map = map; | 247 | buf->map = map; |
287 | map->start = vma->vm_start; | 248 | map->start = vma->vm_start; |
288 | map->end = vma->vm_end; | 249 | map->end = vma->vm_end; |
289 | map->q = q; | 250 | map->q = q; |
290 | 251 | ||
291 | q->bufs[first]->baddr = vma->vm_start; | 252 | buf->baddr = vma->vm_start; |
292 | 253 | ||
293 | mem = q->bufs[first]->priv; | 254 | mem = buf->priv; |
294 | BUG_ON(!mem); | 255 | BUG_ON(!mem); |
295 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); | 256 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); |
296 | 257 | ||
@@ -300,8 +261,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
300 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); | 261 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); |
301 | goto error; | 262 | goto error; |
302 | } | 263 | } |
303 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", | 264 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages); |
304 | mem->vmalloc, pages); | ||
305 | 265 | ||
306 | /* Try to remap memory */ | 266 | /* Try to remap memory */ |
307 | retval = remap_vmalloc_range(vma, mem->vmalloc, 0); | 267 | retval = remap_vmalloc_range(vma, mem->vmalloc, 0); |
@@ -315,10 +275,10 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
315 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | 275 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; |
316 | vma->vm_private_data = map; | 276 | vma->vm_private_data = map; |
317 | 277 | ||
318 | dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", | 278 | dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", |
319 | map, q, vma->vm_start, vma->vm_end, | 279 | map, q, vma->vm_start, vma->vm_end, |
320 | (long int) q->bufs[first]->bsize, | 280 | (long int)buf->bsize, |
321 | vma->vm_pgoff, first); | 281 | vma->vm_pgoff, buf->i); |
322 | 282 | ||
323 | videobuf_vm_open(vma); | 283 | videobuf_vm_open(vma); |
324 | 284 | ||
@@ -330,69 +290,16 @@ error: | |||
330 | return -ENOMEM; | 290 | return -ENOMEM; |
331 | } | 291 | } |
332 | 292 | ||
333 | static int __videobuf_copy_to_user ( struct videobuf_queue *q, | ||
334 | char __user *data, size_t count, | ||
335 | int nonblocking ) | ||
336 | { | ||
337 | struct videobuf_vmalloc_memory *mem=q->read_buf->priv; | ||
338 | BUG_ON (!mem); | ||
339 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
340 | |||
341 | BUG_ON (!mem->vmalloc); | ||
342 | |||
343 | /* copy to userspace */ | ||
344 | if (count > q->read_buf->size - q->read_off) | ||
345 | count = q->read_buf->size - q->read_off; | ||
346 | |||
347 | if (copy_to_user(data, mem->vmalloc+q->read_off, count)) | ||
348 | return -EFAULT; | ||
349 | |||
350 | return count; | ||
351 | } | ||
352 | |||
353 | static int __videobuf_copy_stream ( struct videobuf_queue *q, | ||
354 | char __user *data, size_t count, size_t pos, | ||
355 | int vbihack, int nonblocking ) | ||
356 | { | ||
357 | unsigned int *fc; | ||
358 | struct videobuf_vmalloc_memory *mem=q->read_buf->priv; | ||
359 | BUG_ON (!mem); | ||
360 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | ||
361 | |||
362 | if (vbihack) { | ||
363 | /* dirty, undocumented hack -- pass the frame counter | ||
364 | * within the last four bytes of each vbi data block. | ||
365 | * We need that one to maintain backward compatibility | ||
366 | * to all vbi decoding software out there ... */ | ||
367 | fc = (unsigned int*)mem->vmalloc; | ||
368 | fc += (q->read_buf->size>>2) -1; | ||
369 | *fc = q->read_buf->field_count >> 1; | ||
370 | dprintk(1,"vbihack: %d\n",*fc); | ||
371 | } | ||
372 | |||
373 | /* copy stuff using the common method */ | ||
374 | count = __videobuf_copy_to_user (q,data,count,nonblocking); | ||
375 | |||
376 | if ( (count==-EFAULT) && (0 == pos) ) | ||
377 | return -EFAULT; | ||
378 | |||
379 | return count; | ||
380 | } | ||
381 | |||
382 | static struct videobuf_qtype_ops qops = { | 293 | static struct videobuf_qtype_ops qops = { |
383 | .magic = MAGIC_QTYPE_OPS, | 294 | .magic = MAGIC_QTYPE_OPS, |
384 | 295 | ||
385 | .alloc = __videobuf_alloc, | 296 | .alloc = __videobuf_alloc, |
386 | .iolock = __videobuf_iolock, | 297 | .iolock = __videobuf_iolock, |
387 | .sync = __videobuf_sync, | ||
388 | .mmap_free = __videobuf_mmap_free, | ||
389 | .mmap_mapper = __videobuf_mmap_mapper, | 298 | .mmap_mapper = __videobuf_mmap_mapper, |
390 | .video_copy_to_user = __videobuf_copy_to_user, | 299 | .vaddr = videobuf_to_vmalloc, |
391 | .copy_stream = __videobuf_copy_stream, | ||
392 | .vmalloc = videobuf_to_vmalloc, | ||
393 | }; | 300 | }; |
394 | 301 | ||
395 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | 302 | void videobuf_queue_vmalloc_init(struct videobuf_queue *q, |
396 | const struct videobuf_queue_ops *ops, | 303 | const struct videobuf_queue_ops *ops, |
397 | struct device *dev, | 304 | struct device *dev, |
398 | spinlock_t *irqlock, | 305 | spinlock_t *irqlock, |
@@ -404,20 +311,19 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | |||
404 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, | 311 | videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, |
405 | priv, &qops); | 312 | priv, &qops); |
406 | } | 313 | } |
407 | |||
408 | EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); | 314 | EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); |
409 | 315 | ||
410 | void *videobuf_to_vmalloc (struct videobuf_buffer *buf) | 316 | void *videobuf_to_vmalloc(struct videobuf_buffer *buf) |
411 | { | 317 | { |
412 | struct videobuf_vmalloc_memory *mem=buf->priv; | 318 | struct videobuf_vmalloc_memory *mem = buf->priv; |
413 | BUG_ON (!mem); | 319 | BUG_ON(!mem); |
414 | MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); | 320 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); |
415 | 321 | ||
416 | return mem->vmalloc; | 322 | return mem->vmalloc; |
417 | } | 323 | } |
418 | EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); | 324 | EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); |
419 | 325 | ||
420 | void videobuf_vmalloc_free (struct videobuf_buffer *buf) | 326 | void videobuf_vmalloc_free(struct videobuf_buffer *buf) |
421 | { | 327 | { |
422 | struct videobuf_vmalloc_memory *mem = buf->priv; | 328 | struct videobuf_vmalloc_memory *mem = buf->priv; |
423 | 329 | ||
@@ -442,8 +348,3 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf) | |||
442 | } | 348 | } |
443 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); | 349 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); |
444 | 350 | ||
445 | /* | ||
446 | * Local variables: | ||
447 | * c-basic-offset: 8 | ||
448 | * End: | ||
449 | */ | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cdbe70385c12..e17b6fee046b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -13,29 +13,23 @@ | |||
13 | * License, or (at your option) any later version | 13 | * License, or (at your option) any later version |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/delay.h> | ||
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
18 | #include <linux/fs.h> | ||
19 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
20 | #include <linux/slab.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/init.h> | 18 | #include <linux/init.h> |
24 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
25 | #include <linux/pci.h> | 20 | #include <linux/slab.h> |
26 | #include <linux/random.h> | 21 | #include <linux/font.h> |
27 | #include <linux/version.h> | 22 | #include <linux/version.h> |
28 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
29 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
30 | #include <linux/dma-mapping.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
33 | #include <linux/highmem.h> | 26 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) |
34 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
28 | #endif | ||
35 | #include <media/videobuf-vmalloc.h> | 29 | #include <media/videobuf-vmalloc.h> |
36 | #include <media/v4l2-device.h> | 30 | #include <media/v4l2-device.h> |
37 | #include <media/v4l2-ioctl.h> | 31 | #include <media/v4l2-ioctl.h> |
38 | #include "font.h" | 32 | #include <media/v4l2-common.h> |
39 | 33 | ||
40 | #define VIVI_MODULE_NAME "vivi" | 34 | #define VIVI_MODULE_NAME "vivi" |
41 | 35 | ||
@@ -44,8 +38,11 @@ | |||
44 | #define WAKE_DENOMINATOR 1001 | 38 | #define WAKE_DENOMINATOR 1001 |
45 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ | 39 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ |
46 | 40 | ||
41 | #define MAX_WIDTH 1920 | ||
42 | #define MAX_HEIGHT 1200 | ||
43 | |||
47 | #define VIVI_MAJOR_VERSION 0 | 44 | #define VIVI_MAJOR_VERSION 0 |
48 | #define VIVI_MINOR_VERSION 6 | 45 | #define VIVI_MINOR_VERSION 7 |
49 | #define VIVI_RELEASE 0 | 46 | #define VIVI_RELEASE 0 |
50 | #define VIVI_VERSION \ | 47 | #define VIVI_VERSION \ |
51 | KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) | 48 | KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) |
@@ -70,56 +67,8 @@ static unsigned int vid_limit = 16; | |||
70 | module_param(vid_limit, uint, 0644); | 67 | module_param(vid_limit, uint, 0644); |
71 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | 68 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); |
72 | 69 | ||
73 | 70 | /* Global font descriptor */ | |
74 | /* supported controls */ | 71 | static const u8 *font8x16; |
75 | static struct v4l2_queryctrl vivi_qctrl[] = { | ||
76 | { | ||
77 | .id = V4L2_CID_AUDIO_VOLUME, | ||
78 | .name = "Volume", | ||
79 | .minimum = 0, | ||
80 | .maximum = 65535, | ||
81 | .step = 65535/100, | ||
82 | .default_value = 65535, | ||
83 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
84 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
85 | }, { | ||
86 | .id = V4L2_CID_BRIGHTNESS, | ||
87 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
88 | .name = "Brightness", | ||
89 | .minimum = 0, | ||
90 | .maximum = 255, | ||
91 | .step = 1, | ||
92 | .default_value = 127, | ||
93 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
94 | }, { | ||
95 | .id = V4L2_CID_CONTRAST, | ||
96 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
97 | .name = "Contrast", | ||
98 | .minimum = 0, | ||
99 | .maximum = 255, | ||
100 | .step = 0x1, | ||
101 | .default_value = 0x10, | ||
102 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
103 | }, { | ||
104 | .id = V4L2_CID_SATURATION, | ||
105 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
106 | .name = "Saturation", | ||
107 | .minimum = 0, | ||
108 | .maximum = 255, | ||
109 | .step = 0x1, | ||
110 | .default_value = 127, | ||
111 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
112 | }, { | ||
113 | .id = V4L2_CID_HUE, | ||
114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
115 | .name = "Hue", | ||
116 | .minimum = -128, | ||
117 | .maximum = 127, | ||
118 | .step = 0x1, | ||
119 | .default_value = 0, | ||
120 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
121 | } | ||
122 | }; | ||
123 | 72 | ||
124 | #define dprintk(dev, level, fmt, arg...) \ | 73 | #define dprintk(dev, level, fmt, arg...) \ |
125 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) | 74 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) |
@@ -214,41 +163,38 @@ struct vivi_dev { | |||
214 | struct list_head vivi_devlist; | 163 | struct list_head vivi_devlist; |
215 | struct v4l2_device v4l2_dev; | 164 | struct v4l2_device v4l2_dev; |
216 | 165 | ||
166 | /* controls */ | ||
167 | int brightness; | ||
168 | int contrast; | ||
169 | int saturation; | ||
170 | int hue; | ||
171 | int volume; | ||
172 | |||
217 | spinlock_t slock; | 173 | spinlock_t slock; |
218 | struct mutex mutex; | 174 | struct mutex mutex; |
219 | 175 | ||
220 | int users; | ||
221 | |||
222 | /* various device info */ | 176 | /* various device info */ |
223 | struct video_device *vfd; | 177 | struct video_device *vfd; |
224 | 178 | ||
225 | struct vivi_dmaqueue vidq; | 179 | struct vivi_dmaqueue vidq; |
226 | 180 | ||
227 | /* Several counters */ | 181 | /* Several counters */ |
228 | int h, m, s, ms; | 182 | unsigned ms; |
229 | unsigned long jiffies; | 183 | unsigned long jiffies; |
230 | char timestr[13]; | ||
231 | 184 | ||
232 | int mv_count; /* Controls bars movement */ | 185 | int mv_count; /* Controls bars movement */ |
233 | 186 | ||
234 | /* Input Number */ | 187 | /* Input Number */ |
235 | int input; | 188 | int input; |
236 | 189 | ||
237 | /* Control 'registers' */ | ||
238 | int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; | ||
239 | }; | ||
240 | |||
241 | struct vivi_fh { | ||
242 | struct vivi_dev *dev; | ||
243 | |||
244 | /* video capture */ | 190 | /* video capture */ |
245 | struct vivi_fmt *fmt; | 191 | struct vivi_fmt *fmt; |
246 | unsigned int width, height; | 192 | unsigned int width, height; |
247 | struct videobuf_queue vb_vidq; | 193 | struct videobuf_queue vb_vidq; |
248 | 194 | ||
249 | enum v4l2_buf_type type; | 195 | unsigned long generating; |
250 | unsigned char bars[8][3]; | 196 | u8 bars[9][3]; |
251 | int input; /* Input Number on bars */ | 197 | u8 line[MAX_WIDTH * 4]; |
252 | }; | 198 | }; |
253 | 199 | ||
254 | /* ------------------------------------------------------------------ | 200 | /* ------------------------------------------------------------------ |
@@ -259,19 +205,20 @@ struct vivi_fh { | |||
259 | 205 | ||
260 | enum colors { | 206 | enum colors { |
261 | WHITE, | 207 | WHITE, |
262 | AMBAR, | 208 | AMBER, |
263 | CYAN, | 209 | CYAN, |
264 | GREEN, | 210 | GREEN, |
265 | MAGENTA, | 211 | MAGENTA, |
266 | RED, | 212 | RED, |
267 | BLUE, | 213 | BLUE, |
268 | BLACK, | 214 | BLACK, |
215 | TEXT_BLACK, | ||
269 | }; | 216 | }; |
270 | 217 | ||
271 | /* R G B */ | 218 | /* R G B */ |
272 | #define COLOR_WHITE {204, 204, 204} | 219 | #define COLOR_WHITE {204, 204, 204} |
273 | #define COLOR_AMBAR {208, 208, 0} | 220 | #define COLOR_AMBER {208, 208, 0} |
274 | #define COLOR_CIAN { 0, 206, 206} | 221 | #define COLOR_CYAN { 0, 206, 206} |
275 | #define COLOR_GREEN { 0, 239, 0} | 222 | #define COLOR_GREEN { 0, 239, 0} |
276 | #define COLOR_MAGENTA {239, 0, 239} | 223 | #define COLOR_MAGENTA {239, 0, 239} |
277 | #define COLOR_RED {205, 0, 0} | 224 | #define COLOR_RED {205, 0, 0} |
@@ -279,56 +226,24 @@ enum colors { | |||
279 | #define COLOR_BLACK { 0, 0, 0} | 226 | #define COLOR_BLACK { 0, 0, 0} |
280 | 227 | ||
281 | struct bar_std { | 228 | struct bar_std { |
282 | u8 bar[8][3]; | 229 | u8 bar[9][3]; |
283 | }; | 230 | }; |
284 | 231 | ||
285 | /* Maximum number of bars are 10 - otherwise, the input print code | 232 | /* Maximum number of bars are 10 - otherwise, the input print code |
286 | should be modified */ | 233 | should be modified */ |
287 | static struct bar_std bars[] = { | 234 | static struct bar_std bars[] = { |
288 | { /* Standard ITU-R color bar sequence */ | 235 | { /* Standard ITU-R color bar sequence */ |
289 | { | 236 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, |
290 | COLOR_WHITE, | 237 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } |
291 | COLOR_AMBAR, | ||
292 | COLOR_CIAN, | ||
293 | COLOR_GREEN, | ||
294 | COLOR_MAGENTA, | ||
295 | COLOR_RED, | ||
296 | COLOR_BLUE, | ||
297 | COLOR_BLACK, | ||
298 | } | ||
299 | }, { | 238 | }, { |
300 | { | 239 | { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, |
301 | COLOR_WHITE, | 240 | COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK } |
302 | COLOR_AMBAR, | ||
303 | COLOR_BLACK, | ||
304 | COLOR_WHITE, | ||
305 | COLOR_AMBAR, | ||
306 | COLOR_BLACK, | ||
307 | COLOR_WHITE, | ||
308 | COLOR_AMBAR, | ||
309 | } | ||
310 | }, { | 241 | }, { |
311 | { | 242 | { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, |
312 | COLOR_WHITE, | 243 | COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK } |
313 | COLOR_CIAN, | ||
314 | COLOR_BLACK, | ||
315 | COLOR_WHITE, | ||
316 | COLOR_CIAN, | ||
317 | COLOR_BLACK, | ||
318 | COLOR_WHITE, | ||
319 | COLOR_CIAN, | ||
320 | } | ||
321 | }, { | 244 | }, { |
322 | { | 245 | { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, |
323 | COLOR_WHITE, | 246 | COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK } |
324 | COLOR_GREEN, | ||
325 | COLOR_BLACK, | ||
326 | COLOR_WHITE, | ||
327 | COLOR_GREEN, | ||
328 | COLOR_BLACK, | ||
329 | COLOR_WHITE, | ||
330 | COLOR_GREEN, | ||
331 | } | ||
332 | }, | 247 | }, |
333 | }; | 248 | }; |
334 | 249 | ||
@@ -344,21 +259,18 @@ static struct bar_std bars[] = { | |||
344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) | 259 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) |
345 | 260 | ||
346 | /* precalculate color bar values to speed up rendering */ | 261 | /* precalculate color bar values to speed up rendering */ |
347 | static void precalculate_bars(struct vivi_fh *fh) | 262 | static void precalculate_bars(struct vivi_dev *dev) |
348 | { | 263 | { |
349 | struct vivi_dev *dev = fh->dev; | 264 | u8 r, g, b; |
350 | unsigned char r, g, b; | ||
351 | int k, is_yuv; | 265 | int k, is_yuv; |
352 | 266 | ||
353 | fh->input = dev->input; | 267 | for (k = 0; k < 9; k++) { |
354 | 268 | r = bars[dev->input].bar[k][0]; | |
355 | for (k = 0; k < 8; k++) { | 269 | g = bars[dev->input].bar[k][1]; |
356 | r = bars[fh->input].bar[k][0]; | 270 | b = bars[dev->input].bar[k][2]; |
357 | g = bars[fh->input].bar[k][1]; | ||
358 | b = bars[fh->input].bar[k][2]; | ||
359 | is_yuv = 0; | 271 | is_yuv = 0; |
360 | 272 | ||
361 | switch (fh->fmt->fourcc) { | 273 | switch (dev->fmt->fourcc) { |
362 | case V4L2_PIX_FMT_YUYV: | 274 | case V4L2_PIX_FMT_YUYV: |
363 | case V4L2_PIX_FMT_UYVY: | 275 | case V4L2_PIX_FMT_UYVY: |
364 | is_yuv = 1; | 276 | is_yuv = 1; |
@@ -378,16 +290,15 @@ static void precalculate_bars(struct vivi_fh *fh) | |||
378 | } | 290 | } |
379 | 291 | ||
380 | if (is_yuv) { | 292 | if (is_yuv) { |
381 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | 293 | dev->bars[k][0] = TO_Y(r, g, b); /* Luma */ |
382 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | 294 | dev->bars[k][1] = TO_U(r, g, b); /* Cb */ |
383 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | 295 | dev->bars[k][2] = TO_V(r, g, b); /* Cr */ |
384 | } else { | 296 | } else { |
385 | fh->bars[k][0] = r; | 297 | dev->bars[k][0] = r; |
386 | fh->bars[k][1] = g; | 298 | dev->bars[k][1] = g; |
387 | fh->bars[k][2] = b; | 299 | dev->bars[k][2] = b; |
388 | } | 300 | } |
389 | } | 301 | } |
390 | |||
391 | } | 302 | } |
392 | 303 | ||
393 | #define TSTAMP_MIN_Y 24 | 304 | #define TSTAMP_MIN_Y 24 |
@@ -395,20 +306,20 @@ static void precalculate_bars(struct vivi_fh *fh) | |||
395 | #define TSTAMP_INPUT_X 10 | 306 | #define TSTAMP_INPUT_X 10 |
396 | #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) | 307 | #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) |
397 | 308 | ||
398 | static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) | 309 | static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) |
399 | { | 310 | { |
400 | unsigned char r_y, g_u, b_v; | 311 | u8 r_y, g_u, b_v; |
401 | unsigned char *p; | ||
402 | int color; | 312 | int color; |
313 | u8 *p; | ||
403 | 314 | ||
404 | r_y = fh->bars[colorpos][0]; /* R or precalculated Y */ | 315 | r_y = dev->bars[colorpos][0]; /* R or precalculated Y */ |
405 | g_u = fh->bars[colorpos][1]; /* G or precalculated U */ | 316 | g_u = dev->bars[colorpos][1]; /* G or precalculated U */ |
406 | b_v = fh->bars[colorpos][2]; /* B or precalculated V */ | 317 | b_v = dev->bars[colorpos][2]; /* B or precalculated V */ |
407 | 318 | ||
408 | for (color = 0; color < 4; color++) { | 319 | for (color = 0; color < 4; color++) { |
409 | p = buf + color; | 320 | p = buf + color; |
410 | 321 | ||
411 | switch (fh->fmt->fourcc) { | 322 | switch (dev->fmt->fourcc) { |
412 | case V4L2_PIX_FMT_YUYV: | 323 | case V4L2_PIX_FMT_YUYV: |
413 | switch (color) { | 324 | switch (color) { |
414 | case 0: | 325 | case 0: |
@@ -489,123 +400,88 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) | |||
489 | } | 400 | } |
490 | } | 401 | } |
491 | 402 | ||
492 | static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax, | 403 | static void precalculate_line(struct vivi_dev *dev) |
493 | int hmax, int line, int count, char *timestr) | ||
494 | { | 404 | { |
495 | int w, i, j; | 405 | int w; |
496 | int pos = inipos; | ||
497 | char *s; | ||
498 | u8 chr; | ||
499 | |||
500 | /* We will just duplicate the second pixel at the packet */ | ||
501 | wmax /= 2; | ||
502 | 406 | ||
503 | /* Generate a standard color bar pattern */ | 407 | for (w = 0; w < dev->width * 2; w += 2) { |
504 | for (w = 0; w < wmax; w++) { | 408 | int colorpos = (w / (dev->width / 8) % 8); |
505 | int colorpos = ((w + count) * 8/(wmax + 1)) % 8; | ||
506 | 409 | ||
507 | gen_twopix(fh, basep + pos, colorpos); | 410 | gen_twopix(dev, dev->line + w * 2, colorpos); |
508 | pos += 4; /* only 16 bpp supported for now */ | ||
509 | } | 411 | } |
412 | } | ||
510 | 413 | ||
511 | /* Prints input entry number */ | 414 | static void gen_text(struct vivi_dev *dev, char *basep, |
512 | 415 | int y, int x, char *text) | |
513 | /* Checks if it is possible to input number */ | 416 | { |
514 | if (TSTAMP_MAX_Y >= hmax) | 417 | int line; |
515 | goto end; | ||
516 | |||
517 | if (TSTAMP_INPUT_X + strlen(timestr) >= wmax) | ||
518 | goto end; | ||
519 | |||
520 | if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { | ||
521 | chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y]; | ||
522 | pos = TSTAMP_INPUT_X; | ||
523 | for (i = 0; i < 7; i++) { | ||
524 | /* Draw white font on black background */ | ||
525 | if (chr & 1 << (7 - i)) | ||
526 | gen_twopix(fh, basep + pos, WHITE); | ||
527 | else | ||
528 | gen_twopix(fh, basep + pos, BLACK); | ||
529 | pos += 2; | ||
530 | } | ||
531 | } | ||
532 | 418 | ||
533 | /* Checks if it is possible to show timestamp */ | 419 | /* Checks if it is possible to show string */ |
534 | if (TSTAMP_MIN_X + strlen(timestr) >= wmax) | 420 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width) |
535 | goto end; | 421 | return; |
536 | 422 | ||
537 | /* Print stream time */ | 423 | /* Print stream time */ |
538 | if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { | 424 | for (line = y; line < y + 16; line++) { |
539 | j = TSTAMP_MIN_X; | 425 | int j = 0; |
540 | for (s = timestr; *s; s++) { | 426 | char *pos = basep + line * dev->width * 2 + x * 2; |
541 | chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y]; | 427 | char *s; |
542 | for (i = 0; i < 7; i++) { | 428 | |
543 | pos = inipos + j * 2; | 429 | for (s = text; *s; s++) { |
430 | u8 chr = font8x16[*s * 16 + line - y]; | ||
431 | int i; | ||
432 | |||
433 | for (i = 0; i < 7; i++, j++) { | ||
544 | /* Draw white font on black background */ | 434 | /* Draw white font on black background */ |
545 | if (chr & 1 << (7 - i)) | 435 | if (chr & (1 << (7 - i))) |
546 | gen_twopix(fh, basep + pos, WHITE); | 436 | gen_twopix(dev, pos + j * 2, WHITE); |
547 | else | 437 | else |
548 | gen_twopix(fh, basep + pos, BLACK); | 438 | gen_twopix(dev, pos + j * 2, TEXT_BLACK); |
549 | j++; | ||
550 | } | 439 | } |
551 | } | 440 | } |
552 | } | 441 | } |
553 | |||
554 | end: | ||
555 | return; | ||
556 | } | 442 | } |
557 | 443 | ||
558 | static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) | 444 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) |
559 | { | 445 | { |
560 | struct vivi_dev *dev = fh->dev; | 446 | int hmax = buf->vb.height; |
561 | int h , pos = 0; | 447 | int wmax = buf->vb.width; |
562 | int hmax = buf->vb.height; | ||
563 | int wmax = buf->vb.width; | ||
564 | struct timeval ts; | 448 | struct timeval ts; |
565 | char *tmpbuf; | ||
566 | void *vbuf = videobuf_to_vmalloc(&buf->vb); | 449 | void *vbuf = videobuf_to_vmalloc(&buf->vb); |
450 | unsigned ms; | ||
451 | char str[100]; | ||
452 | int h, line = 1; | ||
567 | 453 | ||
568 | if (!vbuf) | 454 | if (!vbuf) |
569 | return; | 455 | return; |
570 | 456 | ||
571 | tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); | 457 | for (h = 0; h < hmax; h++) |
572 | if (!tmpbuf) | 458 | memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2); |
573 | return; | ||
574 | |||
575 | for (h = 0; h < hmax; h++) { | ||
576 | gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count, | ||
577 | dev->timestr); | ||
578 | memcpy(vbuf + pos, tmpbuf, wmax * 2); | ||
579 | pos += wmax*2; | ||
580 | } | ||
581 | |||
582 | dev->mv_count++; | ||
583 | |||
584 | kfree(tmpbuf); | ||
585 | 459 | ||
586 | /* Updates stream time */ | 460 | /* Updates stream time */ |
587 | 461 | ||
588 | dev->ms += jiffies_to_msecs(jiffies-dev->jiffies); | 462 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); |
589 | dev->jiffies = jiffies; | 463 | dev->jiffies = jiffies; |
590 | if (dev->ms >= 1000) { | 464 | ms = dev->ms; |
591 | dev->ms -= 1000; | 465 | snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ", |
592 | dev->s++; | 466 | (ms / (60 * 60 * 1000)) % 24, |
593 | if (dev->s >= 60) { | 467 | (ms / (60 * 1000)) % 60, |
594 | dev->s -= 60; | 468 | (ms / 1000) % 60, |
595 | dev->m++; | 469 | ms % 1000); |
596 | if (dev->m > 60) { | 470 | gen_text(dev, vbuf, line++ * 16, 16, str); |
597 | dev->m -= 60; | 471 | snprintf(str, sizeof(str), " %dx%d, input %d ", |
598 | dev->h++; | 472 | dev->width, dev->height, dev->input); |
599 | if (dev->h > 24) | 473 | gen_text(dev, vbuf, line++ * 16, 16, str); |
600 | dev->h -= 24; | 474 | |
601 | } | 475 | snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", |
602 | } | 476 | dev->brightness, |
603 | } | 477 | dev->contrast, |
604 | sprintf(dev->timestr, "%02d:%02d:%02d:%03d", | 478 | dev->saturation, |
605 | dev->h, dev->m, dev->s, dev->ms); | 479 | dev->hue); |
606 | 480 | gen_text(dev, vbuf, line++ * 16, 16, str); | |
607 | dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", | 481 | snprintf(str, sizeof(str), " volume %3d ", dev->volume); |
608 | dev->timestr, (unsigned long)tmpbuf, pos); | 482 | gen_text(dev, vbuf, line++ * 16, 16, str); |
483 | |||
484 | dev->mv_count += 2; | ||
609 | 485 | ||
610 | /* Advice that buffer was filled */ | 486 | /* Advice that buffer was filled */ |
611 | buf->vb.field_count++; | 487 | buf->vb.field_count++; |
@@ -614,12 +490,10 @@ static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) | |||
614 | buf->vb.state = VIDEOBUF_DONE; | 490 | buf->vb.state = VIDEOBUF_DONE; |
615 | } | 491 | } |
616 | 492 | ||
617 | static void vivi_thread_tick(struct vivi_fh *fh) | 493 | static void vivi_thread_tick(struct vivi_dev *dev) |
618 | { | 494 | { |
619 | struct vivi_buffer *buf; | ||
620 | struct vivi_dev *dev = fh->dev; | ||
621 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 495 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
622 | 496 | struct vivi_buffer *buf; | |
623 | unsigned long flags = 0; | 497 | unsigned long flags = 0; |
624 | 498 | ||
625 | dprintk(dev, 1, "Thread tick\n"); | 499 | dprintk(dev, 1, "Thread tick\n"); |
@@ -642,22 +516,20 @@ static void vivi_thread_tick(struct vivi_fh *fh) | |||
642 | do_gettimeofday(&buf->vb.ts); | 516 | do_gettimeofday(&buf->vb.ts); |
643 | 517 | ||
644 | /* Fill buffer */ | 518 | /* Fill buffer */ |
645 | vivi_fillbuff(fh, buf); | 519 | vivi_fillbuff(dev, buf); |
646 | dprintk(dev, 1, "filled buffer %p\n", buf); | 520 | dprintk(dev, 1, "filled buffer %p\n", buf); |
647 | 521 | ||
648 | wake_up(&buf->vb.done); | 522 | wake_up(&buf->vb.done); |
649 | dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); | 523 | dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); |
650 | unlock: | 524 | unlock: |
651 | spin_unlock_irqrestore(&dev->slock, flags); | 525 | spin_unlock_irqrestore(&dev->slock, flags); |
652 | return; | ||
653 | } | 526 | } |
654 | 527 | ||
655 | #define frames_to_ms(frames) \ | 528 | #define frames_to_ms(frames) \ |
656 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) | 529 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) |
657 | 530 | ||
658 | static void vivi_sleep(struct vivi_fh *fh) | 531 | static void vivi_sleep(struct vivi_dev *dev) |
659 | { | 532 | { |
660 | struct vivi_dev *dev = fh->dev; | ||
661 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 533 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
662 | int timeout; | 534 | int timeout; |
663 | DECLARE_WAITQUEUE(wait, current); | 535 | DECLARE_WAITQUEUE(wait, current); |
@@ -672,7 +544,7 @@ static void vivi_sleep(struct vivi_fh *fh) | |||
672 | /* Calculate time to wake up */ | 544 | /* Calculate time to wake up */ |
673 | timeout = msecs_to_jiffies(frames_to_ms(1)); | 545 | timeout = msecs_to_jiffies(frames_to_ms(1)); |
674 | 546 | ||
675 | vivi_thread_tick(fh); | 547 | vivi_thread_tick(dev); |
676 | 548 | ||
677 | schedule_timeout_interruptible(timeout); | 549 | schedule_timeout_interruptible(timeout); |
678 | 550 | ||
@@ -683,15 +555,14 @@ stop_task: | |||
683 | 555 | ||
684 | static int vivi_thread(void *data) | 556 | static int vivi_thread(void *data) |
685 | { | 557 | { |
686 | struct vivi_fh *fh = data; | 558 | struct vivi_dev *dev = data; |
687 | struct vivi_dev *dev = fh->dev; | ||
688 | 559 | ||
689 | dprintk(dev, 1, "thread started\n"); | 560 | dprintk(dev, 1, "thread started\n"); |
690 | 561 | ||
691 | set_freezable(); | 562 | set_freezable(); |
692 | 563 | ||
693 | for (;;) { | 564 | for (;;) { |
694 | vivi_sleep(fh); | 565 | vivi_sleep(dev); |
695 | 566 | ||
696 | if (kthread_should_stop()) | 567 | if (kthread_should_stop()) |
697 | break; | 568 | break; |
@@ -700,39 +571,61 @@ static int vivi_thread(void *data) | |||
700 | return 0; | 571 | return 0; |
701 | } | 572 | } |
702 | 573 | ||
703 | static int vivi_start_thread(struct vivi_fh *fh) | 574 | static void vivi_start_generating(struct file *file) |
704 | { | 575 | { |
705 | struct vivi_dev *dev = fh->dev; | 576 | struct vivi_dev *dev = video_drvdata(file); |
706 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 577 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
707 | 578 | ||
708 | dma_q->frame = 0; | ||
709 | dma_q->ini_jiffies = jiffies; | ||
710 | |||
711 | dprintk(dev, 1, "%s\n", __func__); | 579 | dprintk(dev, 1, "%s\n", __func__); |
712 | 580 | ||
713 | dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); | 581 | if (test_and_set_bit(0, &dev->generating)) |
582 | return; | ||
583 | file->private_data = dev; | ||
584 | |||
585 | /* Resets frame counters */ | ||
586 | dev->ms = 0; | ||
587 | dev->mv_count = 0; | ||
588 | dev->jiffies = jiffies; | ||
589 | |||
590 | dma_q->frame = 0; | ||
591 | dma_q->ini_jiffies = jiffies; | ||
592 | dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name); | ||
714 | 593 | ||
715 | if (IS_ERR(dma_q->kthread)) { | 594 | if (IS_ERR(dma_q->kthread)) { |
716 | v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); | 595 | v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); |
717 | return PTR_ERR(dma_q->kthread); | 596 | clear_bit(0, &dev->generating); |
597 | return; | ||
718 | } | 598 | } |
719 | /* Wakes thread */ | 599 | /* Wakes thread */ |
720 | wake_up_interruptible(&dma_q->wq); | 600 | wake_up_interruptible(&dma_q->wq); |
721 | 601 | ||
722 | dprintk(dev, 1, "returning from %s\n", __func__); | 602 | dprintk(dev, 1, "returning from %s\n", __func__); |
723 | return 0; | ||
724 | } | 603 | } |
725 | 604 | ||
726 | static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | 605 | static void vivi_stop_generating(struct file *file) |
727 | { | 606 | { |
728 | struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); | 607 | struct vivi_dev *dev = video_drvdata(file); |
608 | struct vivi_dmaqueue *dma_q = &dev->vidq; | ||
729 | 609 | ||
730 | dprintk(dev, 1, "%s\n", __func__); | 610 | dprintk(dev, 1, "%s\n", __func__); |
611 | |||
612 | if (!file->private_data) | ||
613 | return; | ||
614 | if (!test_and_clear_bit(0, &dev->generating)) | ||
615 | return; | ||
616 | |||
731 | /* shutdown control thread */ | 617 | /* shutdown control thread */ |
732 | if (dma_q->kthread) { | 618 | if (dma_q->kthread) { |
733 | kthread_stop(dma_q->kthread); | 619 | kthread_stop(dma_q->kthread); |
734 | dma_q->kthread = NULL; | 620 | dma_q->kthread = NULL; |
735 | } | 621 | } |
622 | videobuf_stop(&dev->vb_vidq); | ||
623 | videobuf_mmap_free(&dev->vb_vidq); | ||
624 | } | ||
625 | |||
626 | static int vivi_is_generating(struct vivi_dev *dev) | ||
627 | { | ||
628 | return test_bit(0, &dev->generating); | ||
736 | } | 629 | } |
737 | 630 | ||
738 | /* ------------------------------------------------------------------ | 631 | /* ------------------------------------------------------------------ |
@@ -741,10 +634,9 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | |||
741 | static int | 634 | static int |
742 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | 635 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) |
743 | { | 636 | { |
744 | struct vivi_fh *fh = vq->priv_data; | 637 | struct vivi_dev *dev = vq->priv_data; |
745 | struct vivi_dev *dev = fh->dev; | ||
746 | 638 | ||
747 | *size = fh->width*fh->height*2; | 639 | *size = dev->width * dev->height * 2; |
748 | 640 | ||
749 | if (0 == *count) | 641 | if (0 == *count) |
750 | *count = 32; | 642 | *count = 32; |
@@ -760,49 +652,43 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | |||
760 | 652 | ||
761 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | 653 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) |
762 | { | 654 | { |
763 | struct vivi_fh *fh = vq->priv_data; | 655 | struct vivi_dev *dev = vq->priv_data; |
764 | struct vivi_dev *dev = fh->dev; | ||
765 | 656 | ||
766 | dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); | 657 | dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); |
767 | 658 | ||
768 | if (in_interrupt()) | ||
769 | BUG(); | ||
770 | |||
771 | videobuf_vmalloc_free(&buf->vb); | 659 | videobuf_vmalloc_free(&buf->vb); |
772 | dprintk(dev, 1, "free_buffer: freed\n"); | 660 | dprintk(dev, 1, "free_buffer: freed\n"); |
773 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 661 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
774 | } | 662 | } |
775 | 663 | ||
776 | #define norm_maxw() 1024 | ||
777 | #define norm_maxh() 768 | ||
778 | static int | 664 | static int |
779 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | 665 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
780 | enum v4l2_field field) | 666 | enum v4l2_field field) |
781 | { | 667 | { |
782 | struct vivi_fh *fh = vq->priv_data; | 668 | struct vivi_dev *dev = vq->priv_data; |
783 | struct vivi_dev *dev = fh->dev; | ||
784 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 669 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
785 | int rc; | 670 | int rc; |
786 | 671 | ||
787 | dprintk(dev, 1, "%s, field=%d\n", __func__, field); | 672 | dprintk(dev, 1, "%s, field=%d\n", __func__, field); |
788 | 673 | ||
789 | BUG_ON(NULL == fh->fmt); | 674 | BUG_ON(NULL == dev->fmt); |
790 | 675 | ||
791 | if (fh->width < 48 || fh->width > norm_maxw() || | 676 | if (dev->width < 48 || dev->width > MAX_WIDTH || |
792 | fh->height < 32 || fh->height > norm_maxh()) | 677 | dev->height < 32 || dev->height > MAX_HEIGHT) |
793 | return -EINVAL; | 678 | return -EINVAL; |
794 | 679 | ||
795 | buf->vb.size = fh->width*fh->height*2; | 680 | buf->vb.size = dev->width * dev->height * 2; |
796 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 681 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
797 | return -EINVAL; | 682 | return -EINVAL; |
798 | 683 | ||
799 | /* These properties only change when queue is idle, see s_fmt */ | 684 | /* These properties only change when queue is idle, see s_fmt */ |
800 | buf->fmt = fh->fmt; | 685 | buf->fmt = dev->fmt; |
801 | buf->vb.width = fh->width; | 686 | buf->vb.width = dev->width; |
802 | buf->vb.height = fh->height; | 687 | buf->vb.height = dev->height; |
803 | buf->vb.field = field; | 688 | buf->vb.field = field; |
804 | 689 | ||
805 | precalculate_bars(fh); | 690 | precalculate_bars(dev); |
691 | precalculate_line(dev); | ||
806 | 692 | ||
807 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 693 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
808 | rc = videobuf_iolock(vq, &buf->vb, NULL); | 694 | rc = videobuf_iolock(vq, &buf->vb, NULL); |
@@ -811,7 +697,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
811 | } | 697 | } |
812 | 698 | ||
813 | buf->vb.state = VIDEOBUF_PREPARED; | 699 | buf->vb.state = VIDEOBUF_PREPARED; |
814 | |||
815 | return 0; | 700 | return 0; |
816 | 701 | ||
817 | fail: | 702 | fail: |
@@ -822,9 +707,8 @@ fail: | |||
822 | static void | 707 | static void |
823 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | 708 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
824 | { | 709 | { |
825 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 710 | struct vivi_dev *dev = vq->priv_data; |
826 | struct vivi_fh *fh = vq->priv_data; | 711 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
827 | struct vivi_dev *dev = fh->dev; | ||
828 | struct vivi_dmaqueue *vidq = &dev->vidq; | 712 | struct vivi_dmaqueue *vidq = &dev->vidq; |
829 | 713 | ||
830 | dprintk(dev, 1, "%s\n", __func__); | 714 | dprintk(dev, 1, "%s\n", __func__); |
@@ -836,9 +720,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
836 | static void buffer_release(struct videobuf_queue *vq, | 720 | static void buffer_release(struct videobuf_queue *vq, |
837 | struct videobuf_buffer *vb) | 721 | struct videobuf_buffer *vb) |
838 | { | 722 | { |
839 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 723 | struct vivi_dev *dev = vq->priv_data; |
840 | struct vivi_fh *fh = vq->priv_data; | 724 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
841 | struct vivi_dev *dev = (struct vivi_dev *)fh->dev; | ||
842 | 725 | ||
843 | dprintk(dev, 1, "%s\n", __func__); | 726 | dprintk(dev, 1, "%s\n", __func__); |
844 | 727 | ||
@@ -858,16 +741,14 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
858 | static int vidioc_querycap(struct file *file, void *priv, | 741 | static int vidioc_querycap(struct file *file, void *priv, |
859 | struct v4l2_capability *cap) | 742 | struct v4l2_capability *cap) |
860 | { | 743 | { |
861 | struct vivi_fh *fh = priv; | 744 | struct vivi_dev *dev = video_drvdata(file); |
862 | struct vivi_dev *dev = fh->dev; | ||
863 | 745 | ||
864 | strcpy(cap->driver, "vivi"); | 746 | strcpy(cap->driver, "vivi"); |
865 | strcpy(cap->card, "vivi"); | 747 | strcpy(cap->card, "vivi"); |
866 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); | 748 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); |
867 | cap->version = VIVI_VERSION; | 749 | cap->version = VIVI_VERSION; |
868 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 750 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ |
869 | V4L2_CAP_STREAMING | | 751 | V4L2_CAP_READWRITE; |
870 | V4L2_CAP_READWRITE; | ||
871 | return 0; | 752 | return 0; |
872 | } | 753 | } |
873 | 754 | ||
@@ -889,28 +770,25 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
889 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 770 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
890 | struct v4l2_format *f) | 771 | struct v4l2_format *f) |
891 | { | 772 | { |
892 | struct vivi_fh *fh = priv; | 773 | struct vivi_dev *dev = video_drvdata(file); |
893 | 774 | ||
894 | f->fmt.pix.width = fh->width; | 775 | f->fmt.pix.width = dev->width; |
895 | f->fmt.pix.height = fh->height; | 776 | f->fmt.pix.height = dev->height; |
896 | f->fmt.pix.field = fh->vb_vidq.field; | 777 | f->fmt.pix.field = dev->vb_vidq.field; |
897 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | 778 | f->fmt.pix.pixelformat = dev->fmt->fourcc; |
898 | f->fmt.pix.bytesperline = | 779 | f->fmt.pix.bytesperline = |
899 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | 780 | (f->fmt.pix.width * dev->fmt->depth) >> 3; |
900 | f->fmt.pix.sizeimage = | 781 | f->fmt.pix.sizeimage = |
901 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 782 | f->fmt.pix.height * f->fmt.pix.bytesperline; |
902 | 783 | return 0; | |
903 | return (0); | ||
904 | } | 784 | } |
905 | 785 | ||
906 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 786 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
907 | struct v4l2_format *f) | 787 | struct v4l2_format *f) |
908 | { | 788 | { |
909 | struct vivi_fh *fh = priv; | 789 | struct vivi_dev *dev = video_drvdata(file); |
910 | struct vivi_dev *dev = fh->dev; | ||
911 | struct vivi_fmt *fmt; | 790 | struct vivi_fmt *fmt; |
912 | enum v4l2_field field; | 791 | enum v4l2_field field; |
913 | unsigned int maxw, maxh; | ||
914 | 792 | ||
915 | fmt = get_format(f); | 793 | fmt = get_format(f); |
916 | if (!fmt) { | 794 | if (!fmt) { |
@@ -928,113 +806,109 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
928 | return -EINVAL; | 806 | return -EINVAL; |
929 | } | 807 | } |
930 | 808 | ||
931 | maxw = norm_maxw(); | ||
932 | maxh = norm_maxh(); | ||
933 | |||
934 | f->fmt.pix.field = field; | 809 | f->fmt.pix.field = field; |
935 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | 810 | v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, |
936 | &f->fmt.pix.height, 32, maxh, 0, 0); | 811 | &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); |
937 | f->fmt.pix.bytesperline = | 812 | f->fmt.pix.bytesperline = |
938 | (f->fmt.pix.width * fmt->depth) >> 3; | 813 | (f->fmt.pix.width * fmt->depth) >> 3; |
939 | f->fmt.pix.sizeimage = | 814 | f->fmt.pix.sizeimage = |
940 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 815 | f->fmt.pix.height * f->fmt.pix.bytesperline; |
941 | |||
942 | return 0; | 816 | return 0; |
943 | } | 817 | } |
944 | 818 | ||
945 | /*FIXME: This seems to be generic enough to be at videodev2 */ | ||
946 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 819 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
947 | struct v4l2_format *f) | 820 | struct v4l2_format *f) |
948 | { | 821 | { |
949 | struct vivi_fh *fh = priv; | 822 | struct vivi_dev *dev = video_drvdata(file); |
950 | struct videobuf_queue *q = &fh->vb_vidq; | 823 | struct videobuf_queue *q = &dev->vb_vidq; |
951 | 824 | ||
952 | int ret = vidioc_try_fmt_vid_cap(file, fh, f); | 825 | int ret = vidioc_try_fmt_vid_cap(file, priv, f); |
953 | if (ret < 0) | 826 | if (ret < 0) |
954 | return ret; | 827 | return ret; |
955 | 828 | ||
956 | mutex_lock(&q->vb_lock); | 829 | mutex_lock(&q->vb_lock); |
957 | 830 | ||
958 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 831 | if (vivi_is_generating(dev)) { |
959 | dprintk(fh->dev, 1, "%s queue busy\n", __func__); | 832 | dprintk(dev, 1, "%s device busy\n", __func__); |
960 | ret = -EBUSY; | 833 | ret = -EBUSY; |
961 | goto out; | 834 | goto out; |
962 | } | 835 | } |
963 | 836 | ||
964 | fh->fmt = get_format(f); | 837 | dev->fmt = get_format(f); |
965 | fh->width = f->fmt.pix.width; | 838 | dev->width = f->fmt.pix.width; |
966 | fh->height = f->fmt.pix.height; | 839 | dev->height = f->fmt.pix.height; |
967 | fh->vb_vidq.field = f->fmt.pix.field; | 840 | dev->vb_vidq.field = f->fmt.pix.field; |
968 | fh->type = f->type; | ||
969 | |||
970 | ret = 0; | 841 | ret = 0; |
971 | out: | 842 | out: |
972 | mutex_unlock(&q->vb_lock); | 843 | mutex_unlock(&q->vb_lock); |
973 | |||
974 | return ret; | 844 | return ret; |
975 | } | 845 | } |
976 | 846 | ||
977 | static int vidioc_reqbufs(struct file *file, void *priv, | 847 | static int vidioc_reqbufs(struct file *file, void *priv, |
978 | struct v4l2_requestbuffers *p) | 848 | struct v4l2_requestbuffers *p) |
979 | { | 849 | { |
980 | struct vivi_fh *fh = priv; | 850 | struct vivi_dev *dev = video_drvdata(file); |
981 | 851 | ||
982 | return (videobuf_reqbufs(&fh->vb_vidq, p)); | 852 | return videobuf_reqbufs(&dev->vb_vidq, p); |
983 | } | 853 | } |
984 | 854 | ||
985 | static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | 855 | static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) |
986 | { | 856 | { |
987 | struct vivi_fh *fh = priv; | 857 | struct vivi_dev *dev = video_drvdata(file); |
988 | 858 | ||
989 | return (videobuf_querybuf(&fh->vb_vidq, p)); | 859 | return videobuf_querybuf(&dev->vb_vidq, p); |
990 | } | 860 | } |
991 | 861 | ||
992 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 862 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
993 | { | 863 | { |
994 | struct vivi_fh *fh = priv; | 864 | struct vivi_dev *dev = video_drvdata(file); |
995 | 865 | ||
996 | return (videobuf_qbuf(&fh->vb_vidq, p)); | 866 | return videobuf_qbuf(&dev->vb_vidq, p); |
997 | } | 867 | } |
998 | 868 | ||
999 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 869 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1000 | { | 870 | { |
1001 | struct vivi_fh *fh = priv; | 871 | struct vivi_dev *dev = video_drvdata(file); |
1002 | 872 | ||
1003 | return (videobuf_dqbuf(&fh->vb_vidq, p, | 873 | return videobuf_dqbuf(&dev->vb_vidq, p, |
1004 | file->f_flags & O_NONBLOCK)); | 874 | file->f_flags & O_NONBLOCK); |
1005 | } | 875 | } |
1006 | 876 | ||
1007 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 877 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1008 | static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | 878 | static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) |
1009 | { | 879 | { |
1010 | struct vivi_fh *fh = priv; | 880 | struct vivi_dev *dev = video_drvdata(file); |
1011 | 881 | ||
1012 | return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); | 882 | return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8); |
1013 | } | 883 | } |
1014 | #endif | 884 | #endif |
1015 | 885 | ||
1016 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 886 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
1017 | { | 887 | { |
1018 | struct vivi_fh *fh = priv; | 888 | struct vivi_dev *dev = video_drvdata(file); |
889 | int ret; | ||
1019 | 890 | ||
1020 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 891 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1021 | return -EINVAL; | ||
1022 | if (i != fh->type) | ||
1023 | return -EINVAL; | 892 | return -EINVAL; |
893 | ret = videobuf_streamon(&dev->vb_vidq); | ||
894 | if (ret) | ||
895 | return ret; | ||
1024 | 896 | ||
1025 | return videobuf_streamon(&fh->vb_vidq); | 897 | vivi_start_generating(file); |
898 | return 0; | ||
1026 | } | 899 | } |
1027 | 900 | ||
1028 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 901 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1029 | { | 902 | { |
1030 | struct vivi_fh *fh = priv; | 903 | struct vivi_dev *dev = video_drvdata(file); |
904 | int ret; | ||
1031 | 905 | ||
1032 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 906 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1033 | return -EINVAL; | ||
1034 | if (i != fh->type) | ||
1035 | return -EINVAL; | 907 | return -EINVAL; |
1036 | 908 | ret = videobuf_streamoff(&dev->vb_vidq); | |
1037 | return videobuf_streamoff(&fh->vb_vidq); | 909 | if (!ret) |
910 | vivi_stop_generating(file); | ||
911 | return ret; | ||
1038 | } | 912 | } |
1039 | 913 | ||
1040 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | 914 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) |
@@ -1052,80 +926,104 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1052 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 926 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1053 | inp->std = V4L2_STD_525_60; | 927 | inp->std = V4L2_STD_525_60; |
1054 | sprintf(inp->name, "Camera %u", inp->index); | 928 | sprintf(inp->name, "Camera %u", inp->index); |
1055 | 929 | return 0; | |
1056 | return (0); | ||
1057 | } | 930 | } |
1058 | 931 | ||
1059 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 932 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1060 | { | 933 | { |
1061 | struct vivi_fh *fh = priv; | 934 | struct vivi_dev *dev = video_drvdata(file); |
1062 | struct vivi_dev *dev = fh->dev; | ||
1063 | 935 | ||
1064 | *i = dev->input; | 936 | *i = dev->input; |
1065 | 937 | return 0; | |
1066 | return (0); | ||
1067 | } | 938 | } |
939 | |||
1068 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 940 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1069 | { | 941 | { |
1070 | struct vivi_fh *fh = priv; | 942 | struct vivi_dev *dev = video_drvdata(file); |
1071 | struct vivi_dev *dev = fh->dev; | ||
1072 | 943 | ||
1073 | if (i >= NUM_INPUTS) | 944 | if (i >= NUM_INPUTS) |
1074 | return -EINVAL; | 945 | return -EINVAL; |
1075 | 946 | ||
1076 | dev->input = i; | 947 | dev->input = i; |
1077 | precalculate_bars(fh); | 948 | precalculate_bars(dev); |
1078 | 949 | precalculate_line(dev); | |
1079 | return (0); | 950 | return 0; |
1080 | } | 951 | } |
1081 | 952 | ||
1082 | /* --- controls ---------------------------------------------- */ | 953 | /* --- controls ---------------------------------------------- */ |
1083 | static int vidioc_queryctrl(struct file *file, void *priv, | 954 | static int vidioc_queryctrl(struct file *file, void *priv, |
1084 | struct v4l2_queryctrl *qc) | 955 | struct v4l2_queryctrl *qc) |
1085 | { | 956 | { |
1086 | int i; | 957 | switch (qc->id) { |
1087 | 958 | case V4L2_CID_AUDIO_VOLUME: | |
1088 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 959 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200); |
1089 | if (qc->id && qc->id == vivi_qctrl[i].id) { | 960 | case V4L2_CID_BRIGHTNESS: |
1090 | memcpy(qc, &(vivi_qctrl[i]), | 961 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); |
1091 | sizeof(*qc)); | 962 | case V4L2_CID_CONTRAST: |
1092 | return (0); | 963 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16); |
1093 | } | 964 | case V4L2_CID_SATURATION: |
1094 | 965 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); | |
966 | case V4L2_CID_HUE: | ||
967 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); | ||
968 | } | ||
1095 | return -EINVAL; | 969 | return -EINVAL; |
1096 | } | 970 | } |
1097 | 971 | ||
1098 | static int vidioc_g_ctrl(struct file *file, void *priv, | 972 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1099 | struct v4l2_control *ctrl) | 973 | struct v4l2_control *ctrl) |
1100 | { | 974 | { |
1101 | struct vivi_fh *fh = priv; | 975 | struct vivi_dev *dev = video_drvdata(file); |
1102 | struct vivi_dev *dev = fh->dev; | ||
1103 | int i; | ||
1104 | |||
1105 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1106 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1107 | ctrl->value = dev->qctl_regs[i]; | ||
1108 | return 0; | ||
1109 | } | ||
1110 | 976 | ||
977 | switch (ctrl->id) { | ||
978 | case V4L2_CID_AUDIO_VOLUME: | ||
979 | ctrl->value = dev->volume; | ||
980 | return 0; | ||
981 | case V4L2_CID_BRIGHTNESS: | ||
982 | ctrl->value = dev->brightness; | ||
983 | return 0; | ||
984 | case V4L2_CID_CONTRAST: | ||
985 | ctrl->value = dev->contrast; | ||
986 | return 0; | ||
987 | case V4L2_CID_SATURATION: | ||
988 | ctrl->value = dev->saturation; | ||
989 | return 0; | ||
990 | case V4L2_CID_HUE: | ||
991 | ctrl->value = dev->hue; | ||
992 | return 0; | ||
993 | } | ||
1111 | return -EINVAL; | 994 | return -EINVAL; |
1112 | } | 995 | } |
996 | |||
1113 | static int vidioc_s_ctrl(struct file *file, void *priv, | 997 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1114 | struct v4l2_control *ctrl) | 998 | struct v4l2_control *ctrl) |
1115 | { | 999 | { |
1116 | struct vivi_fh *fh = priv; | 1000 | struct vivi_dev *dev = video_drvdata(file); |
1117 | struct vivi_dev *dev = fh->dev; | 1001 | struct v4l2_queryctrl qc; |
1118 | int i; | 1002 | int err; |
1119 | 1003 | ||
1120 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 1004 | qc.id = ctrl->id; |
1121 | if (ctrl->id == vivi_qctrl[i].id) { | 1005 | err = vidioc_queryctrl(file, priv, &qc); |
1122 | if (ctrl->value < vivi_qctrl[i].minimum || | 1006 | if (err < 0) |
1123 | ctrl->value > vivi_qctrl[i].maximum) { | 1007 | return err; |
1124 | return -ERANGE; | 1008 | if (ctrl->value < qc.minimum || ctrl->value > qc.maximum) |
1125 | } | 1009 | return -ERANGE; |
1126 | dev->qctl_regs[i] = ctrl->value; | 1010 | switch (ctrl->id) { |
1127 | return 0; | 1011 | case V4L2_CID_AUDIO_VOLUME: |
1128 | } | 1012 | dev->volume = ctrl->value; |
1013 | return 0; | ||
1014 | case V4L2_CID_BRIGHTNESS: | ||
1015 | dev->brightness = ctrl->value; | ||
1016 | return 0; | ||
1017 | case V4L2_CID_CONTRAST: | ||
1018 | dev->contrast = ctrl->value; | ||
1019 | return 0; | ||
1020 | case V4L2_CID_SATURATION: | ||
1021 | dev->saturation = ctrl->value; | ||
1022 | return 0; | ||
1023 | case V4L2_CID_HUE: | ||
1024 | dev->hue = ctrl->value; | ||
1025 | return 0; | ||
1026 | } | ||
1129 | return -EINVAL; | 1027 | return -EINVAL; |
1130 | } | 1028 | } |
1131 | 1029 | ||
@@ -1133,134 +1031,58 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1133 | File operations for the device | 1031 | File operations for the device |
1134 | ------------------------------------------------------------------*/ | 1032 | ------------------------------------------------------------------*/ |
1135 | 1033 | ||
1136 | static int vivi_open(struct file *file) | ||
1137 | { | ||
1138 | struct vivi_dev *dev = video_drvdata(file); | ||
1139 | struct vivi_fh *fh = NULL; | ||
1140 | int retval = 0; | ||
1141 | |||
1142 | mutex_lock(&dev->mutex); | ||
1143 | dev->users++; | ||
1144 | |||
1145 | if (dev->users > 1) { | ||
1146 | dev->users--; | ||
1147 | mutex_unlock(&dev->mutex); | ||
1148 | return -EBUSY; | ||
1149 | } | ||
1150 | |||
1151 | dprintk(dev, 1, "open %s type=%s users=%d\n", | ||
1152 | video_device_node_name(dev->vfd), | ||
1153 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); | ||
1154 | |||
1155 | /* allocate + initialize per filehandle data */ | ||
1156 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
1157 | if (NULL == fh) { | ||
1158 | dev->users--; | ||
1159 | retval = -ENOMEM; | ||
1160 | } | ||
1161 | mutex_unlock(&dev->mutex); | ||
1162 | |||
1163 | if (retval) | ||
1164 | return retval; | ||
1165 | |||
1166 | file->private_data = fh; | ||
1167 | fh->dev = dev; | ||
1168 | |||
1169 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1170 | fh->fmt = &formats[0]; | ||
1171 | fh->width = 640; | ||
1172 | fh->height = 480; | ||
1173 | |||
1174 | /* Resets frame counters */ | ||
1175 | dev->h = 0; | ||
1176 | dev->m = 0; | ||
1177 | dev->s = 0; | ||
1178 | dev->ms = 0; | ||
1179 | dev->mv_count = 0; | ||
1180 | dev->jiffies = jiffies; | ||
1181 | sprintf(dev->timestr, "%02d:%02d:%02d:%03d", | ||
1182 | dev->h, dev->m, dev->s, dev->ms); | ||
1183 | |||
1184 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, | ||
1185 | NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, | ||
1186 | sizeof(struct vivi_buffer), fh); | ||
1187 | |||
1188 | vivi_start_thread(fh); | ||
1189 | |||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1193 | static ssize_t | 1034 | static ssize_t |
1194 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | 1035 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
1195 | { | 1036 | { |
1196 | struct vivi_fh *fh = file->private_data; | 1037 | struct vivi_dev *dev = video_drvdata(file); |
1197 | 1038 | ||
1198 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1039 | vivi_start_generating(file); |
1199 | return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, | 1040 | return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0, |
1200 | file->f_flags & O_NONBLOCK); | 1041 | file->f_flags & O_NONBLOCK); |
1201 | } | ||
1202 | return 0; | ||
1203 | } | 1042 | } |
1204 | 1043 | ||
1205 | static unsigned int | 1044 | static unsigned int |
1206 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1045 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1207 | { | 1046 | { |
1208 | struct vivi_fh *fh = file->private_data; | 1047 | struct vivi_dev *dev = video_drvdata(file); |
1209 | struct vivi_dev *dev = fh->dev; | 1048 | struct videobuf_queue *q = &dev->vb_vidq; |
1210 | struct videobuf_queue *q = &fh->vb_vidq; | ||
1211 | 1049 | ||
1212 | dprintk(dev, 1, "%s\n", __func__); | 1050 | dprintk(dev, 1, "%s\n", __func__); |
1213 | 1051 | ||
1214 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1052 | vivi_start_generating(file); |
1215 | return POLLERR; | ||
1216 | |||
1217 | return videobuf_poll_stream(file, q, wait); | 1053 | return videobuf_poll_stream(file, q, wait); |
1218 | } | 1054 | } |
1219 | 1055 | ||
1220 | static int vivi_close(struct file *file) | 1056 | static int vivi_close(struct file *file) |
1221 | { | 1057 | { |
1222 | struct vivi_fh *fh = file->private_data; | ||
1223 | struct vivi_dev *dev = fh->dev; | ||
1224 | struct vivi_dmaqueue *vidq = &dev->vidq; | ||
1225 | struct video_device *vdev = video_devdata(file); | 1058 | struct video_device *vdev = video_devdata(file); |
1059 | struct vivi_dev *dev = video_drvdata(file); | ||
1226 | 1060 | ||
1227 | vivi_stop_thread(vidq); | 1061 | vivi_stop_generating(file); |
1228 | videobuf_stop(&fh->vb_vidq); | ||
1229 | videobuf_mmap_free(&fh->vb_vidq); | ||
1230 | |||
1231 | kfree(fh); | ||
1232 | |||
1233 | mutex_lock(&dev->mutex); | ||
1234 | dev->users--; | ||
1235 | mutex_unlock(&dev->mutex); | ||
1236 | |||
1237 | dprintk(dev, 1, "close called (dev=%s, users=%d)\n", | ||
1238 | video_device_node_name(vdev), dev->users); | ||
1239 | 1062 | ||
1063 | dprintk(dev, 1, "close called (dev=%s)\n", | ||
1064 | video_device_node_name(vdev)); | ||
1240 | return 0; | 1065 | return 0; |
1241 | } | 1066 | } |
1242 | 1067 | ||
1243 | static int vivi_mmap(struct file *file, struct vm_area_struct *vma) | 1068 | static int vivi_mmap(struct file *file, struct vm_area_struct *vma) |
1244 | { | 1069 | { |
1245 | struct vivi_fh *fh = file->private_data; | 1070 | struct vivi_dev *dev = video_drvdata(file); |
1246 | struct vivi_dev *dev = fh->dev; | ||
1247 | int ret; | 1071 | int ret; |
1248 | 1072 | ||
1249 | dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); | 1073 | dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); |
1250 | 1074 | ||
1251 | ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); | 1075 | ret = videobuf_mmap_mapper(&dev->vb_vidq, vma); |
1252 | 1076 | ||
1253 | dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", | 1077 | dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", |
1254 | (unsigned long)vma->vm_start, | 1078 | (unsigned long)vma->vm_start, |
1255 | (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, | 1079 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, |
1256 | ret); | 1080 | ret); |
1257 | |||
1258 | return ret; | 1081 | return ret; |
1259 | } | 1082 | } |
1260 | 1083 | ||
1261 | static const struct v4l2_file_operations vivi_fops = { | 1084 | static const struct v4l2_file_operations vivi_fops = { |
1262 | .owner = THIS_MODULE, | 1085 | .owner = THIS_MODULE, |
1263 | .open = vivi_open, | ||
1264 | .release = vivi_close, | 1086 | .release = vivi_close, |
1265 | .read = vivi_read, | 1087 | .read = vivi_read, |
1266 | .poll = vivi_poll, | 1088 | .poll = vivi_poll, |
@@ -1282,11 +1104,11 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1282 | .vidioc_enum_input = vidioc_enum_input, | 1104 | .vidioc_enum_input = vidioc_enum_input, |
1283 | .vidioc_g_input = vidioc_g_input, | 1105 | .vidioc_g_input = vidioc_g_input, |
1284 | .vidioc_s_input = vidioc_s_input, | 1106 | .vidioc_s_input = vidioc_s_input, |
1107 | .vidioc_streamon = vidioc_streamon, | ||
1108 | .vidioc_streamoff = vidioc_streamoff, | ||
1285 | .vidioc_queryctrl = vidioc_queryctrl, | 1109 | .vidioc_queryctrl = vidioc_queryctrl, |
1286 | .vidioc_g_ctrl = vidioc_g_ctrl, | 1110 | .vidioc_g_ctrl = vidioc_g_ctrl, |
1287 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1111 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1288 | .vidioc_streamon = vidioc_streamon, | ||
1289 | .vidioc_streamoff = vidioc_streamoff, | ||
1290 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1112 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1291 | .vidiocgmbuf = vidiocgmbuf, | 1113 | .vidiocgmbuf = vidiocgmbuf, |
1292 | #endif | 1114 | #endif |
@@ -1330,7 +1152,7 @@ static int __init vivi_create_instance(int inst) | |||
1330 | { | 1152 | { |
1331 | struct vivi_dev *dev; | 1153 | struct vivi_dev *dev; |
1332 | struct video_device *vfd; | 1154 | struct video_device *vfd; |
1333 | int ret, i; | 1155 | int ret; |
1334 | 1156 | ||
1335 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1157 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1336 | if (!dev) | 1158 | if (!dev) |
@@ -1342,6 +1164,20 @@ static int __init vivi_create_instance(int inst) | |||
1342 | if (ret) | 1164 | if (ret) |
1343 | goto free_dev; | 1165 | goto free_dev; |
1344 | 1166 | ||
1167 | dev->fmt = &formats[0]; | ||
1168 | dev->width = 640; | ||
1169 | dev->height = 480; | ||
1170 | dev->volume = 200; | ||
1171 | dev->brightness = 127; | ||
1172 | dev->contrast = 16; | ||
1173 | dev->saturation = 127; | ||
1174 | dev->hue = 0; | ||
1175 | |||
1176 | videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops, | ||
1177 | NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1178 | V4L2_FIELD_INTERLACED, | ||
1179 | sizeof(struct vivi_buffer), dev); | ||
1180 | |||
1345 | /* init video dma queues */ | 1181 | /* init video dma queues */ |
1346 | INIT_LIST_HEAD(&dev->vidq.active); | 1182 | INIT_LIST_HEAD(&dev->vidq.active); |
1347 | init_waitqueue_head(&dev->vidq.wq); | 1183 | init_waitqueue_head(&dev->vidq.wq); |
@@ -1357,6 +1193,7 @@ static int __init vivi_create_instance(int inst) | |||
1357 | 1193 | ||
1358 | *vfd = vivi_template; | 1194 | *vfd = vivi_template; |
1359 | vfd->debug = debug; | 1195 | vfd->debug = debug; |
1196 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
1360 | 1197 | ||
1361 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); | 1198 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); |
1362 | if (ret < 0) | 1199 | if (ret < 0) |
@@ -1364,10 +1201,6 @@ static int __init vivi_create_instance(int inst) | |||
1364 | 1201 | ||
1365 | video_set_drvdata(vfd, dev); | 1202 | video_set_drvdata(vfd, dev); |
1366 | 1203 | ||
1367 | /* Set all controls to their default value. */ | ||
1368 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1369 | dev->qctl_regs[i] = vivi_qctrl[i].default_value; | ||
1370 | |||
1371 | /* Now that everything is fine, let's add it to device list */ | 1204 | /* Now that everything is fine, let's add it to device list */ |
1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); | 1205 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); |
1373 | 1206 | ||
@@ -1396,8 +1229,15 @@ free_dev: | |||
1396 | */ | 1229 | */ |
1397 | static int __init vivi_init(void) | 1230 | static int __init vivi_init(void) |
1398 | { | 1231 | { |
1232 | const struct font_desc *font = find_font("VGA8x16"); | ||
1399 | int ret = 0, i; | 1233 | int ret = 0, i; |
1400 | 1234 | ||
1235 | if (font == NULL) { | ||
1236 | printk(KERN_ERR "vivi: could not find font\n"); | ||
1237 | return -ENODEV; | ||
1238 | } | ||
1239 | font8x16 = font->data; | ||
1240 | |||
1401 | if (n_devs <= 0) | 1241 | if (n_devs <= 0) |
1402 | n_devs = 1; | 1242 | n_devs = 1; |
1403 | 1243 | ||
@@ -1412,7 +1252,7 @@ static int __init vivi_init(void) | |||
1412 | } | 1252 | } |
1413 | 1253 | ||
1414 | if (ret < 0) { | 1254 | if (ret < 0) { |
1415 | printk(KERN_INFO "Error %d while loading vivi driver\n", ret); | 1255 | printk(KERN_ERR "vivi: error %d while loading driver\n", ret); |
1416 | return ret; | 1256 | return ret; |
1417 | } | 1257 | } |
1418 | 1258 | ||
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index bf9bf650a317..635420d8d84a 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | Winbond w9966cf Webcam parport driver. | 2 | Winbond w9966cf Webcam parport driver. |
3 | 3 | ||
4 | Version 0.32 | 4 | Version 0.33 |
5 | 5 | ||
6 | Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se> | 6 | Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se> |
7 | 7 | ||
@@ -57,10 +57,12 @@ | |||
57 | #include <linux/module.h> | 57 | #include <linux/module.h> |
58 | #include <linux/init.h> | 58 | #include <linux/init.h> |
59 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
60 | #include <linux/videodev.h> | 60 | #include <linux/version.h> |
61 | #include <linux/videodev2.h> | ||
61 | #include <linux/slab.h> | 62 | #include <linux/slab.h> |
62 | #include <media/v4l2-common.h> | 63 | #include <media/v4l2-common.h> |
63 | #include <media/v4l2-ioctl.h> | 64 | #include <media/v4l2-ioctl.h> |
65 | #include <media/v4l2-device.h> | ||
64 | #include <linux/parport.h> | 66 | #include <linux/parport.h> |
65 | 67 | ||
66 | /*#define DEBUG*/ /* Undef me for production */ | 68 | /*#define DEBUG*/ /* Undef me for production */ |
@@ -76,12 +78,12 @@ | |||
76 | */ | 78 | */ |
77 | 79 | ||
78 | #define W9966_DRIVERNAME "W9966CF Webcam" | 80 | #define W9966_DRIVERNAME "W9966CF Webcam" |
79 | #define W9966_MAXCAMS 4 // Maximum number of cameras | 81 | #define W9966_MAXCAMS 4 /* Maximum number of cameras */ |
80 | #define W9966_RBUFFER 2048 // Read buffer (must be an even number) | 82 | #define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */ |
81 | #define W9966_SRAMSIZE 131072 // 128kb | 83 | #define W9966_SRAMSIZE 131072 /* 128kb */ |
82 | #define W9966_SRAMID 0x02 // check w9966cf.pdf | 84 | #define W9966_SRAMID 0x02 /* check w9966cf.pdf */ |
83 | 85 | ||
84 | // Empirically determined window limits | 86 | /* Empirically determined window limits */ |
85 | #define W9966_WND_MIN_X 16 | 87 | #define W9966_WND_MIN_X 16 |
86 | #define W9966_WND_MIN_Y 14 | 88 | #define W9966_WND_MIN_Y 14 |
87 | #define W9966_WND_MAX_X 705 | 89 | #define W9966_WND_MAX_X 705 |
@@ -89,7 +91,7 @@ | |||
89 | #define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X) | 91 | #define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X) |
90 | #define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y) | 92 | #define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y) |
91 | 93 | ||
92 | // Keep track of our current state | 94 | /* Keep track of our current state */ |
93 | #define W9966_STATE_PDEV 0x01 | 95 | #define W9966_STATE_PDEV 0x01 |
94 | #define W9966_STATE_CLAIMED 0x02 | 96 | #define W9966_STATE_CLAIMED 0x02 |
95 | #define W9966_STATE_VDEV 0x04 | 97 | #define W9966_STATE_VDEV 0x04 |
@@ -101,12 +103,13 @@ | |||
101 | #define W9966_I2C_W_DATA 0x02 | 103 | #define W9966_I2C_W_DATA 0x02 |
102 | #define W9966_I2C_W_CLOCK 0x01 | 104 | #define W9966_I2C_W_CLOCK 0x01 |
103 | 105 | ||
104 | struct w9966_dev { | 106 | struct w9966 { |
107 | struct v4l2_device v4l2_dev; | ||
105 | unsigned char dev_state; | 108 | unsigned char dev_state; |
106 | unsigned char i2c_state; | 109 | unsigned char i2c_state; |
107 | unsigned short ppmode; | 110 | unsigned short ppmode; |
108 | struct parport* pport; | 111 | struct parport *pport; |
109 | struct pardevice* pdev; | 112 | struct pardevice *pdev; |
110 | struct video_device vdev; | 113 | struct video_device vdev; |
111 | unsigned short width; | 114 | unsigned short width; |
112 | unsigned short height; | 115 | unsigned short height; |
@@ -114,7 +117,7 @@ struct w9966_dev { | |||
114 | signed char contrast; | 117 | signed char contrast; |
115 | signed char color; | 118 | signed char color; |
116 | signed char hue; | 119 | signed char hue; |
117 | unsigned long in_use; | 120 | struct mutex lock; |
118 | }; | 121 | }; |
119 | 122 | ||
120 | /* | 123 | /* |
@@ -127,15 +130,15 @@ MODULE_LICENSE("GPL"); | |||
127 | 130 | ||
128 | 131 | ||
129 | #ifdef MODULE | 132 | #ifdef MODULE |
130 | static const char* pardev[] = {[0 ... W9966_MAXCAMS] = ""}; | 133 | static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; |
131 | #else | 134 | #else |
132 | static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; | 135 | static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; |
133 | #endif | 136 | #endif |
134 | module_param_array(pardev, charp, NULL, 0); | 137 | module_param_array(pardev, charp, NULL, 0); |
135 | MODULE_PARM_DESC(pardev, "pardev: where to search for\n\ | 138 | MODULE_PARM_DESC(pardev, "pardev: where to search for\n" |
136 | \teach camera. 'aggressive' means brute-force search.\n\ | 139 | "\teach camera. 'aggressive' means brute-force search.\n" |
137 | \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\ | 140 | "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n" |
138 | \tcam 1 to parport3 and search every parport for cam 2 etc..."); | 141 | "\tcam 1 to parport3 and search every parport for cam 2 etc..."); |
139 | 142 | ||
140 | static int parmode; | 143 | static int parmode; |
141 | module_param(parmode, int, 0); | 144 | module_param(parmode, int, 0); |
@@ -144,117 +147,49 @@ MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); | |||
144 | static int video_nr = -1; | 147 | static int video_nr = -1; |
145 | module_param(video_nr, int, 0); | 148 | module_param(video_nr, int, 0); |
146 | 149 | ||
147 | /* | 150 | static struct w9966 w9966_cams[W9966_MAXCAMS]; |
148 | * Private data | ||
149 | */ | ||
150 | |||
151 | static struct w9966_dev w9966_cams[W9966_MAXCAMS]; | ||
152 | |||
153 | /* | ||
154 | * Private function declares | ||
155 | */ | ||
156 | |||
157 | static inline void w9966_setState(struct w9966_dev* cam, int mask, int val); | ||
158 | static inline int w9966_getState(struct w9966_dev* cam, int mask, int val); | ||
159 | static inline void w9966_pdev_claim(struct w9966_dev *vdev); | ||
160 | static inline void w9966_pdev_release(struct w9966_dev *vdev); | ||
161 | |||
162 | static int w9966_rReg(struct w9966_dev* cam, int reg); | ||
163 | static int w9966_wReg(struct w9966_dev* cam, int reg, int data); | ||
164 | #if 0 | ||
165 | static int w9966_rReg_i2c(struct w9966_dev* cam, int reg); | ||
166 | #endif | ||
167 | static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data); | ||
168 | static int w9966_findlen(int near, int size, int maxlen); | ||
169 | static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor); | ||
170 | static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h); | ||
171 | |||
172 | static int w9966_init(struct w9966_dev* cam, struct parport* port); | ||
173 | static void w9966_term(struct w9966_dev* cam); | ||
174 | |||
175 | static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state); | ||
176 | static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state); | ||
177 | static inline int w9966_i2c_getsda(struct w9966_dev* cam); | ||
178 | static inline int w9966_i2c_getscl(struct w9966_dev* cam); | ||
179 | static int w9966_i2c_wbyte(struct w9966_dev* cam, int data); | ||
180 | #if 0 | ||
181 | static int w9966_i2c_rbyte(struct w9966_dev* cam); | ||
182 | #endif | ||
183 | |||
184 | static long w9966_v4l_ioctl(struct file *file, | ||
185 | unsigned int cmd, unsigned long arg); | ||
186 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | ||
187 | size_t count, loff_t *ppos); | ||
188 | |||
189 | static int w9966_exclusive_open(struct file *file) | ||
190 | { | ||
191 | struct w9966_dev *cam = video_drvdata(file); | ||
192 | |||
193 | return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; | ||
194 | } | ||
195 | |||
196 | static int w9966_exclusive_release(struct file *file) | ||
197 | { | ||
198 | struct w9966_dev *cam = video_drvdata(file); | ||
199 | |||
200 | clear_bit(0, &cam->in_use); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static const struct v4l2_file_operations w9966_fops = { | ||
205 | .owner = THIS_MODULE, | ||
206 | .open = w9966_exclusive_open, | ||
207 | .release = w9966_exclusive_release, | ||
208 | .ioctl = w9966_v4l_ioctl, | ||
209 | .read = w9966_v4l_read, | ||
210 | }; | ||
211 | static struct video_device w9966_template = { | ||
212 | .name = W9966_DRIVERNAME, | ||
213 | .fops = &w9966_fops, | ||
214 | .release = video_device_release_empty, | ||
215 | }; | ||
216 | 151 | ||
217 | /* | 152 | /* |
218 | * Private function defines | 153 | * Private function defines |
219 | */ | 154 | */ |
220 | 155 | ||
221 | 156 | ||
222 | // Set camera phase flags, so we know what to uninit when terminating | 157 | /* Set camera phase flags, so we know what to uninit when terminating */ |
223 | static inline void w9966_setState(struct w9966_dev* cam, int mask, int val) | 158 | static inline void w9966_set_state(struct w9966 *cam, int mask, int val) |
224 | { | 159 | { |
225 | cam->dev_state = (cam->dev_state & ~mask) ^ val; | 160 | cam->dev_state = (cam->dev_state & ~mask) ^ val; |
226 | } | 161 | } |
227 | 162 | ||
228 | // Get camera phase flags | 163 | /* Get camera phase flags */ |
229 | static inline int w9966_getState(struct w9966_dev* cam, int mask, int val) | 164 | static inline int w9966_get_state(struct w9966 *cam, int mask, int val) |
230 | { | 165 | { |
231 | return ((cam->dev_state & mask) == val); | 166 | return ((cam->dev_state & mask) == val); |
232 | } | 167 | } |
233 | 168 | ||
234 | // Claim parport for ourself | 169 | /* Claim parport for ourself */ |
235 | static inline void w9966_pdev_claim(struct w9966_dev* cam) | 170 | static void w9966_pdev_claim(struct w9966 *cam) |
236 | { | 171 | { |
237 | if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) | 172 | if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) |
238 | return; | 173 | return; |
239 | parport_claim_or_block(cam->pdev); | 174 | parport_claim_or_block(cam->pdev); |
240 | w9966_setState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); | 175 | w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); |
241 | } | 176 | } |
242 | 177 | ||
243 | // Release parport for others to use | 178 | /* Release parport for others to use */ |
244 | static inline void w9966_pdev_release(struct w9966_dev* cam) | 179 | static void w9966_pdev_release(struct w9966 *cam) |
245 | { | 180 | { |
246 | if (w9966_getState(cam, W9966_STATE_CLAIMED, 0)) | 181 | if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0)) |
247 | return; | 182 | return; |
248 | parport_release(cam->pdev); | 183 | parport_release(cam->pdev); |
249 | w9966_setState(cam, W9966_STATE_CLAIMED, 0); | 184 | w9966_set_state(cam, W9966_STATE_CLAIMED, 0); |
250 | } | 185 | } |
251 | 186 | ||
252 | // Read register from W9966 interface-chip | 187 | /* Read register from W9966 interface-chip |
253 | // Expects a claimed pdev | 188 | Expects a claimed pdev |
254 | // -1 on error, else register data (byte) | 189 | -1 on error, else register data (byte) */ |
255 | static int w9966_rReg(struct w9966_dev* cam, int reg) | 190 | static int w9966_read_reg(struct w9966 *cam, int reg) |
256 | { | 191 | { |
257 | // ECP, read, regtransfer, REG, REG, REG, REG, REG | 192 | /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ |
258 | const unsigned char addr = 0x80 | (reg & 0x1f); | 193 | const unsigned char addr = 0x80 | (reg & 0x1f); |
259 | unsigned char val; | 194 | unsigned char val; |
260 | 195 | ||
@@ -270,12 +205,12 @@ static int w9966_rReg(struct w9966_dev* cam, int reg) | |||
270 | return val; | 205 | return val; |
271 | } | 206 | } |
272 | 207 | ||
273 | // Write register to W9966 interface-chip | 208 | /* Write register to W9966 interface-chip |
274 | // Expects a claimed pdev | 209 | Expects a claimed pdev |
275 | // -1 on error | 210 | -1 on error */ |
276 | static int w9966_wReg(struct w9966_dev* cam, int reg, int data) | 211 | static int w9966_write_reg(struct w9966 *cam, int reg, int data) |
277 | { | 212 | { |
278 | // ECP, write, regtransfer, REG, REG, REG, REG, REG | 213 | /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ |
279 | const unsigned char addr = 0xc0 | (reg & 0x1f); | 214 | const unsigned char addr = 0xc0 | (reg & 0x1f); |
280 | const unsigned char val = data; | 215 | const unsigned char val = data; |
281 | 216 | ||
@@ -291,119 +226,186 @@ static int w9966_wReg(struct w9966_dev* cam, int reg, int data) | |||
291 | return 0; | 226 | return 0; |
292 | } | 227 | } |
293 | 228 | ||
294 | // Initialize camera device. Setup all internal flags, set a | 229 | /* |
295 | // default video mode, setup ccd-chip, register v4l device etc.. | 230 | * Ugly and primitive i2c protocol functions |
296 | // Also used for 'probing' of hardware. | 231 | */ |
297 | // -1 on error | 232 | |
298 | static int w9966_init(struct w9966_dev* cam, struct parport* port) | 233 | /* Sets the data line on the i2c bus. |
234 | Expects a claimed pdev. */ | ||
235 | static void w9966_i2c_setsda(struct w9966 *cam, int state) | ||
299 | { | 236 | { |
300 | if (cam->dev_state != 0) | 237 | if (state) |
301 | return -1; | 238 | cam->i2c_state |= W9966_I2C_W_DATA; |
239 | else | ||
240 | cam->i2c_state &= ~W9966_I2C_W_DATA; | ||
302 | 241 | ||
303 | cam->pport = port; | 242 | w9966_write_reg(cam, 0x18, cam->i2c_state); |
304 | cam->brightness = 128; | 243 | udelay(5); |
305 | cam->contrast = 64; | 244 | } |
306 | cam->color = 64; | ||
307 | cam->hue = 0; | ||
308 | 245 | ||
309 | // Select requested transfer mode | 246 | /* Get peripheral clock line |
310 | switch(parmode) | 247 | Expects a claimed pdev. */ |
311 | { | 248 | static int w9966_i2c_getscl(struct w9966 *cam) |
312 | default: // Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) | 249 | { |
313 | case 0: | 250 | const unsigned char state = w9966_read_reg(cam, 0x18); |
314 | if (port->modes & PARPORT_MODE_ECP) | 251 | return ((state & W9966_I2C_R_CLOCK) > 0); |
315 | cam->ppmode = IEEE1284_MODE_ECP; | 252 | } |
316 | else if (port->modes & PARPORT_MODE_EPP) | 253 | |
317 | cam->ppmode = IEEE1284_MODE_EPP; | 254 | /* Sets the clock line on the i2c bus. |
318 | else | 255 | Expects a claimed pdev. -1 on error */ |
319 | cam->ppmode = IEEE1284_MODE_ECP; | 256 | static int w9966_i2c_setscl(struct w9966 *cam, int state) |
320 | break; | 257 | { |
321 | case 1: // hw- or sw-ecp | 258 | unsigned long timeout; |
322 | cam->ppmode = IEEE1284_MODE_ECP; | 259 | |
323 | break; | 260 | if (state) |
324 | case 2: // hw- or sw-epp | 261 | cam->i2c_state |= W9966_I2C_W_CLOCK; |
325 | cam->ppmode = IEEE1284_MODE_EPP; | 262 | else |
326 | break; | 263 | cam->i2c_state &= ~W9966_I2C_W_CLOCK; |
264 | |||
265 | w9966_write_reg(cam, 0x18, cam->i2c_state); | ||
266 | udelay(5); | ||
267 | |||
268 | /* we go to high, we also expect the peripheral to ack. */ | ||
269 | if (state) { | ||
270 | timeout = jiffies + 100; | ||
271 | while (!w9966_i2c_getscl(cam)) { | ||
272 | if (time_after(jiffies, timeout)) | ||
273 | return -1; | ||
274 | } | ||
327 | } | 275 | } |
276 | return 0; | ||
277 | } | ||
328 | 278 | ||
329 | // Tell the parport driver that we exists | 279 | #if 0 |
330 | cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); | 280 | /* Get peripheral data line |
331 | if (cam->pdev == NULL) { | 281 | Expects a claimed pdev. */ |
332 | DPRINTF("parport_register_device() failed\n"); | 282 | static int w9966_i2c_getsda(struct w9966 *cam) |
333 | return -1; | 283 | { |
284 | const unsigned char state = w9966_read_reg(cam, 0x18); | ||
285 | return ((state & W9966_I2C_R_DATA) > 0); | ||
286 | } | ||
287 | #endif | ||
288 | |||
289 | /* Write a byte with ack to the i2c bus. | ||
290 | Expects a claimed pdev. -1 on error */ | ||
291 | static int w9966_i2c_wbyte(struct w9966 *cam, int data) | ||
292 | { | ||
293 | int i; | ||
294 | |||
295 | for (i = 7; i >= 0; i--) { | ||
296 | w9966_i2c_setsda(cam, (data >> i) & 0x01); | ||
297 | |||
298 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
299 | return -1; | ||
300 | w9966_i2c_setscl(cam, 0); | ||
334 | } | 301 | } |
335 | w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); | ||
336 | 302 | ||
337 | w9966_pdev_claim(cam); | 303 | w9966_i2c_setsda(cam, 1); |
338 | 304 | ||
339 | // Setup a default capture mode | 305 | if (w9966_i2c_setscl(cam, 1) == -1) |
340 | if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { | ||
341 | DPRINTF("w9966_setup() failed.\n"); | ||
342 | return -1; | 306 | return -1; |
307 | w9966_i2c_setscl(cam, 0); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | /* Read a data byte with ack from the i2c-bus | ||
313 | Expects a claimed pdev. -1 on error */ | ||
314 | #if 0 | ||
315 | static int w9966_i2c_rbyte(struct w9966 *cam) | ||
316 | { | ||
317 | unsigned char data = 0x00; | ||
318 | int i; | ||
319 | |||
320 | w9966_i2c_setsda(cam, 1); | ||
321 | |||
322 | for (i = 0; i < 8; i++) { | ||
323 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
324 | return -1; | ||
325 | data = data << 1; | ||
326 | if (w9966_i2c_getsda(cam)) | ||
327 | data |= 0x01; | ||
328 | |||
329 | w9966_i2c_setscl(cam, 0); | ||
343 | } | 330 | } |
331 | return data; | ||
332 | } | ||
333 | #endif | ||
344 | 334 | ||
345 | w9966_pdev_release(cam); | 335 | /* Read a register from the i2c device. |
336 | Expects claimed pdev. -1 on error */ | ||
337 | #if 0 | ||
338 | static int w9966_read_reg_i2c(struct w9966 *cam, int reg) | ||
339 | { | ||
340 | int data; | ||
346 | 341 | ||
347 | // Fill in the video_device struct and register us to v4l | 342 | w9966_i2c_setsda(cam, 0); |
348 | memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); | 343 | w9966_i2c_setscl(cam, 0); |
349 | video_set_drvdata(&cam->vdev, cam); | ||
350 | 344 | ||
351 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) | 345 | if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || |
346 | w9966_i2c_wbyte(cam, reg) == -1) | ||
347 | return -1; | ||
348 | |||
349 | w9966_i2c_setsda(cam, 1); | ||
350 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
352 | return -1; | 351 | return -1; |
352 | w9966_i2c_setsda(cam, 0); | ||
353 | w9966_i2c_setscl(cam, 0); | ||
353 | 354 | ||
354 | w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); | 355 | if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1) |
356 | return -1; | ||
357 | data = w9966_i2c_rbyte(cam); | ||
358 | if (data == -1) | ||
359 | return -1; | ||
355 | 360 | ||
356 | // All ok | 361 | w9966_i2c_setsda(cam, 0); |
357 | printk( | ||
358 | "w9966cf: Found and initialized a webcam on %s.\n", | ||
359 | cam->pport->name | ||
360 | ); | ||
361 | return 0; | ||
362 | } | ||
363 | 362 | ||
363 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
364 | return -1; | ||
365 | w9966_i2c_setsda(cam, 1); | ||
364 | 366 | ||
365 | // Terminate everything gracefully | 367 | return data; |
366 | static void w9966_term(struct w9966_dev* cam) | 368 | } |
369 | #endif | ||
370 | |||
371 | /* Write a register to the i2c device. | ||
372 | Expects claimed pdev. -1 on error */ | ||
373 | static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data) | ||
367 | { | 374 | { |
368 | // Unregister from v4l | 375 | w9966_i2c_setsda(cam, 0); |
369 | if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { | 376 | w9966_i2c_setscl(cam, 0); |
370 | video_unregister_device(&cam->vdev); | ||
371 | w9966_setState(cam, W9966_STATE_VDEV, 0); | ||
372 | } | ||
373 | 377 | ||
374 | // Terminate from IEEE1284 mode and release pdev block | 378 | if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || |
375 | if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { | 379 | w9966_i2c_wbyte(cam, reg) == -1 || |
376 | w9966_pdev_claim(cam); | 380 | w9966_i2c_wbyte(cam, data) == -1) |
377 | parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); | 381 | return -1; |
378 | w9966_pdev_release(cam); | ||
379 | } | ||
380 | 382 | ||
381 | // Unregister from parport | 383 | w9966_i2c_setsda(cam, 0); |
382 | if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { | 384 | if (w9966_i2c_setscl(cam, 1) == -1) |
383 | parport_unregister_device(cam->pdev); | 385 | return -1; |
384 | w9966_setState(cam, W9966_STATE_PDEV, 0); | 386 | |
385 | } | 387 | w9966_i2c_setsda(cam, 1); |
386 | } | ||
387 | 388 | ||
389 | return 0; | ||
390 | } | ||
388 | 391 | ||
389 | // Find a good length for capture window (used both for W and H) | 392 | /* Find a good length for capture window (used both for W and H) |
390 | // A bit ugly but pretty functional. The capture length | 393 | A bit ugly but pretty functional. The capture length |
391 | // have to match the downscale | 394 | have to match the downscale */ |
392 | static int w9966_findlen(int near, int size, int maxlen) | 395 | static int w9966_findlen(int near, int size, int maxlen) |
393 | { | 396 | { |
394 | int bestlen = size; | 397 | int bestlen = size; |
395 | int besterr = abs(near - bestlen); | 398 | int besterr = abs(near - bestlen); |
396 | int len; | 399 | int len; |
397 | 400 | ||
398 | for(len = size+1;len < maxlen;len++) | 401 | for (len = size + 1; len < maxlen; len++) { |
399 | { | ||
400 | int err; | 402 | int err; |
401 | if ( ((64*size) %len) != 0) | 403 | if (((64 * size) % len) != 0) |
402 | continue; | 404 | continue; |
403 | 405 | ||
404 | err = abs(near - len); | 406 | err = abs(near - len); |
405 | 407 | ||
406 | // Only continue as long as we keep getting better values | 408 | /* Only continue as long as we keep getting better values */ |
407 | if (err > besterr) | 409 | if (err > besterr) |
408 | break; | 410 | break; |
409 | 411 | ||
@@ -414,32 +416,32 @@ static int w9966_findlen(int near, int size, int maxlen) | |||
414 | return bestlen; | 416 | return bestlen; |
415 | } | 417 | } |
416 | 418 | ||
417 | // Modify capture window (if necessary) | 419 | /* Modify capture window (if necessary) |
418 | // and calculate downscaling | 420 | and calculate downscaling |
419 | // Return -1 on error | 421 | Return -1 on error */ |
420 | static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor) | 422 | static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor) |
421 | { | 423 | { |
422 | int maxlen = max - min; | 424 | int maxlen = max - min; |
423 | int len = *end - *beg + 1; | 425 | int len = *end - *beg + 1; |
424 | int newlen = w9966_findlen(len, size, maxlen); | 426 | int newlen = w9966_findlen(len, size, maxlen); |
425 | int err = newlen - len; | 427 | int err = newlen - len; |
426 | 428 | ||
427 | // Check for bad format | 429 | /* Check for bad format */ |
428 | if (newlen > maxlen || newlen < size) | 430 | if (newlen > maxlen || newlen < size) |
429 | return -1; | 431 | return -1; |
430 | 432 | ||
431 | // Set factor (6 bit fixed) | 433 | /* Set factor (6 bit fixed) */ |
432 | *factor = (64*size) / newlen; | 434 | *factor = (64 * size) / newlen; |
433 | if (*factor == 64) | 435 | if (*factor == 64) |
434 | *factor = 0x00; // downscale is disabled | 436 | *factor = 0x00; /* downscale is disabled */ |
435 | else | 437 | else |
436 | *factor |= 0x80; // set downscale-enable bit | 438 | *factor |= 0x80; /* set downscale-enable bit */ |
437 | 439 | ||
438 | // Modify old beginning and end | 440 | /* Modify old beginning and end */ |
439 | *beg -= err / 2; | 441 | *beg -= err / 2; |
440 | *end += err - (err / 2); | 442 | *end += err - (err / 2); |
441 | 443 | ||
442 | // Move window if outside borders | 444 | /* Move window if outside borders */ |
443 | if (*beg < min) { | 445 | if (*beg < min) { |
444 | *end += min - *beg; | 446 | *end += min - *beg; |
445 | *beg += min - *beg; | 447 | *beg += min - *beg; |
@@ -452,10 +454,10 @@ static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsig | |||
452 | return 0; | 454 | return 0; |
453 | } | 455 | } |
454 | 456 | ||
455 | // Setup the cameras capture window etc. | 457 | /* Setup the cameras capture window etc. |
456 | // Expects a claimed pdev | 458 | Expects a claimed pdev |
457 | // return -1 on error | 459 | return -1 on error */ |
458 | static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h) | 460 | static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h) |
459 | { | 461 | { |
460 | unsigned int i; | 462 | unsigned int i; |
461 | unsigned int enh_s, enh_e; | 463 | unsigned int enh_s, enh_e; |
@@ -469,443 +471,314 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in | |||
469 | }; | 471 | }; |
470 | 472 | ||
471 | 473 | ||
472 | if (w*h*2 > W9966_SRAMSIZE) | 474 | if (w * h * 2 > W9966_SRAMSIZE) { |
473 | { | ||
474 | DPRINTF("capture window exceeds SRAM size!.\n"); | 475 | DPRINTF("capture window exceeds SRAM size!.\n"); |
475 | w = 200; h = 160; // Pick default values | 476 | w = 200; h = 160; /* Pick default values */ |
476 | } | 477 | } |
477 | 478 | ||
478 | w &= ~0x1; | 479 | w &= ~0x1; |
479 | if (w < 2) w = 2; | 480 | if (w < 2) |
480 | if (h < 1) h = 1; | 481 | w = 2; |
481 | if (w > W9966_WND_MAX_W) w = W9966_WND_MAX_W; | 482 | if (h < 1) |
482 | if (h > W9966_WND_MAX_H) h = W9966_WND_MAX_H; | 483 | h = 1; |
484 | if (w > W9966_WND_MAX_W) | ||
485 | w = W9966_WND_MAX_W; | ||
486 | if (h > W9966_WND_MAX_H) | ||
487 | h = W9966_WND_MAX_H; | ||
483 | 488 | ||
484 | cam->width = w; | 489 | cam->width = w; |
485 | cam->height = h; | 490 | cam->height = h; |
486 | 491 | ||
487 | enh_s = 0; | 492 | enh_s = 0; |
488 | enh_e = w*h*2; | 493 | enh_e = w * h * 2; |
489 | 494 | ||
490 | // Modify capture window if necessary and calculate downscaling | 495 | /* Modify capture window if necessary and calculate downscaling */ |
491 | if ( | 496 | if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || |
492 | w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || | 497 | w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0) |
493 | w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0 | 498 | return -1; |
494 | ) return -1; | 499 | |
495 | 500 | DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", | |
496 | DPRINTF( | 501 | w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80); |
497 | "%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", | 502 | |
498 | w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80 | 503 | /* Setup registers */ |
499 | ); | 504 | regs[0x00] = 0x00; /* Set normal operation */ |
500 | 505 | regs[0x01] = 0x18; /* Capture mode */ | |
501 | // Setup registers | 506 | regs[0x02] = scale_y; /* V-scaling */ |
502 | regs[0x00] = 0x00; // Set normal operation | 507 | regs[0x03] = scale_x; /* H-scaling */ |
503 | regs[0x01] = 0x18; // Capture mode | 508 | |
504 | regs[0x02] = scale_y; // V-scaling | 509 | /* Capture window */ |
505 | regs[0x03] = scale_x; // H-scaling | 510 | regs[0x04] = (x1 & 0x0ff); /* X-start (8 low bits) */ |
506 | 511 | regs[0x05] = (x1 & 0x300)>>8; /* X-start (2 high bits) */ | |
507 | // Capture window | 512 | regs[0x06] = (y1 & 0x0ff); /* Y-start (8 low bits) */ |
508 | regs[0x04] = (x1 & 0x0ff); // X-start (8 low bits) | 513 | regs[0x07] = (y1 & 0x300)>>8; /* Y-start (2 high bits) */ |
509 | regs[0x05] = (x1 & 0x300)>>8; // X-start (2 high bits) | 514 | regs[0x08] = (x2 & 0x0ff); /* X-end (8 low bits) */ |
510 | regs[0x06] = (y1 & 0x0ff); // Y-start (8 low bits) | 515 | regs[0x09] = (x2 & 0x300)>>8; /* X-end (2 high bits) */ |
511 | regs[0x07] = (y1 & 0x300)>>8; // Y-start (2 high bits) | 516 | regs[0x0a] = (y2 & 0x0ff); /* Y-end (8 low bits) */ |
512 | regs[0x08] = (x2 & 0x0ff); // X-end (8 low bits) | 517 | |
513 | regs[0x09] = (x2 & 0x300)>>8; // X-end (2 high bits) | 518 | regs[0x0c] = W9966_SRAMID; /* SRAM-banks (1x 128kb) */ |
514 | regs[0x0a] = (y2 & 0x0ff); // Y-end (8 low bits) | 519 | |
515 | 520 | /* Enhancement layer */ | |
516 | regs[0x0c] = W9966_SRAMID; // SRAM-banks (1x 128kb) | 521 | regs[0x0d] = (enh_s & 0x000ff); /* Enh. start (0-7) */ |
517 | 522 | regs[0x0e] = (enh_s & 0x0ff00) >> 8; /* Enh. start (8-15) */ | |
518 | // Enhancement layer | 523 | regs[0x0f] = (enh_s & 0x70000) >> 16; /* Enh. start (16-17/18??) */ |
519 | regs[0x0d] = (enh_s& 0x000ff); // Enh. start (0-7) | 524 | regs[0x10] = (enh_e & 0x000ff); /* Enh. end (0-7) */ |
520 | regs[0x0e] = (enh_s& 0x0ff00)>>8; // Enh. start (8-15) | 525 | regs[0x11] = (enh_e & 0x0ff00) >> 8; /* Enh. end (8-15) */ |
521 | regs[0x0f] = (enh_s& 0x70000)>>16; // Enh. start (16-17/18??) | 526 | regs[0x12] = (enh_e & 0x70000) >> 16; /* Enh. end (16-17/18??) */ |
522 | regs[0x10] = (enh_e& 0x000ff); // Enh. end (0-7) | 527 | |
523 | regs[0x11] = (enh_e& 0x0ff00)>>8; // Enh. end (8-15) | 528 | /* Misc */ |
524 | regs[0x12] = (enh_e& 0x70000)>>16; // Enh. end (16-17/18??) | 529 | regs[0x13] = 0x40; /* VEE control (raw 4:2:2) */ |
525 | 530 | regs[0x17] = 0x00; /* ??? */ | |
526 | // Misc | 531 | regs[0x18] = cam->i2c_state = 0x00; /* Serial bus */ |
527 | regs[0x13] = 0x40; // VEE control (raw 4:2:2) | 532 | regs[0x19] = 0xff; /* I/O port direction control */ |
528 | regs[0x17] = 0x00; // ??? | 533 | regs[0x1a] = 0xff; /* I/O port data register */ |
529 | regs[0x18] = cam->i2c_state = 0x00; // Serial bus | 534 | regs[0x1b] = 0x10; /* ??? */ |
530 | regs[0x19] = 0xff; // I/O port direction control | 535 | |
531 | regs[0x1a] = 0xff; // I/O port data register | 536 | /* SAA7111 chip settings */ |
532 | regs[0x1b] = 0x10; // ??? | ||
533 | |||
534 | // SAA7111 chip settings | ||
535 | saa7111_regs[0x0a] = cam->brightness; | 537 | saa7111_regs[0x0a] = cam->brightness; |
536 | saa7111_regs[0x0b] = cam->contrast; | 538 | saa7111_regs[0x0b] = cam->contrast; |
537 | saa7111_regs[0x0c] = cam->color; | 539 | saa7111_regs[0x0c] = cam->color; |
538 | saa7111_regs[0x0d] = cam->hue; | 540 | saa7111_regs[0x0d] = cam->hue; |
539 | 541 | ||
540 | // Reset (ECP-fifo & serial-bus) | 542 | /* Reset (ECP-fifo & serial-bus) */ |
541 | if (w9966_wReg(cam, 0x00, 0x03) == -1) | 543 | if (w9966_write_reg(cam, 0x00, 0x03) == -1) |
542 | return -1; | 544 | return -1; |
543 | 545 | ||
544 | // Write regs to w9966cf chip | 546 | /* Write regs to w9966cf chip */ |
545 | for (i = 0; i < 0x1c; i++) | 547 | for (i = 0; i < 0x1c; i++) |
546 | if (w9966_wReg(cam, i, regs[i]) == -1) | 548 | if (w9966_write_reg(cam, i, regs[i]) == -1) |
547 | return -1; | 549 | return -1; |
548 | 550 | ||
549 | // Write regs to saa7111 chip | 551 | /* Write regs to saa7111 chip */ |
550 | for (i = 0; i < 0x20; i++) | 552 | for (i = 0; i < 0x20; i++) |
551 | if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1) | 553 | if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1) |
552 | return -1; | 554 | return -1; |
553 | 555 | ||
554 | return 0; | 556 | return 0; |
555 | } | 557 | } |
556 | 558 | ||
557 | /* | 559 | /* |
558 | * Ugly and primitive i2c protocol functions | 560 | * Video4linux interfacing |
559 | */ | 561 | */ |
560 | 562 | ||
561 | // Sets the data line on the i2c bus. | 563 | static int cam_querycap(struct file *file, void *priv, |
562 | // Expects a claimed pdev. | 564 | struct v4l2_capability *vcap) |
563 | static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state) | ||
564 | { | 565 | { |
565 | if (state) | 566 | struct w9966 *cam = video_drvdata(file); |
566 | cam->i2c_state |= W9966_I2C_W_DATA; | ||
567 | else | ||
568 | cam->i2c_state &= ~W9966_I2C_W_DATA; | ||
569 | 567 | ||
570 | w9966_wReg(cam, 0x18, cam->i2c_state); | 568 | strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver)); |
571 | udelay(5); | 569 | strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card)); |
570 | strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); | ||
571 | vcap->version = KERNEL_VERSION(0, 33, 0); | ||
572 | vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; | ||
573 | return 0; | ||
572 | } | 574 | } |
573 | 575 | ||
574 | // Get peripheral clock line | 576 | static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
575 | // Expects a claimed pdev. | ||
576 | static inline int w9966_i2c_getscl(struct w9966_dev* cam) | ||
577 | { | 577 | { |
578 | const unsigned char state = w9966_rReg(cam, 0x18); | 578 | if (vin->index > 0) |
579 | return ((state & W9966_I2C_R_CLOCK) > 0); | 579 | return -EINVAL; |
580 | strlcpy(vin->name, "Camera", sizeof(vin->name)); | ||
581 | vin->type = V4L2_INPUT_TYPE_CAMERA; | ||
582 | vin->audioset = 0; | ||
583 | vin->tuner = 0; | ||
584 | vin->std = 0; | ||
585 | vin->status = 0; | ||
586 | return 0; | ||
580 | } | 587 | } |
581 | 588 | ||
582 | // Sets the clock line on the i2c bus. | 589 | static int cam_g_input(struct file *file, void *fh, unsigned int *inp) |
583 | // Expects a claimed pdev. -1 on error | ||
584 | static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) | ||
585 | { | 590 | { |
586 | unsigned long timeout; | 591 | *inp = 0; |
587 | |||
588 | if (state) | ||
589 | cam->i2c_state |= W9966_I2C_W_CLOCK; | ||
590 | else | ||
591 | cam->i2c_state &= ~W9966_I2C_W_CLOCK; | ||
592 | |||
593 | w9966_wReg(cam, 0x18, cam->i2c_state); | ||
594 | udelay(5); | ||
595 | |||
596 | // we go to high, we also expect the peripheral to ack. | ||
597 | if (state) { | ||
598 | timeout = jiffies + 100; | ||
599 | while (!w9966_i2c_getscl(cam)) { | ||
600 | if (time_after(jiffies, timeout)) | ||
601 | return -1; | ||
602 | } | ||
603 | } | ||
604 | return 0; | 592 | return 0; |
605 | } | 593 | } |
606 | 594 | ||
607 | // Get peripheral data line | 595 | static int cam_s_input(struct file *file, void *fh, unsigned int inp) |
608 | // Expects a claimed pdev. | ||
609 | static inline int w9966_i2c_getsda(struct w9966_dev* cam) | ||
610 | { | 596 | { |
611 | const unsigned char state = w9966_rReg(cam, 0x18); | 597 | return (inp > 0) ? -EINVAL : 0; |
612 | return ((state & W9966_I2C_R_DATA) > 0); | ||
613 | } | 598 | } |
614 | 599 | ||
615 | // Write a byte with ack to the i2c bus. | 600 | static int cam_queryctrl(struct file *file, void *priv, |
616 | // Expects a claimed pdev. -1 on error | 601 | struct v4l2_queryctrl *qc) |
617 | static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) | ||
618 | { | 602 | { |
619 | int i; | 603 | switch (qc->id) { |
620 | for (i = 7; i >= 0; i--) | 604 | case V4L2_CID_BRIGHTNESS: |
621 | { | 605 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); |
622 | w9966_i2c_setsda(cam, (data >> i) & 0x01); | 606 | case V4L2_CID_CONTRAST: |
623 | 607 | return v4l2_ctrl_query_fill(qc, -64, 64, 1, 64); | |
624 | if (w9966_i2c_setscl(cam, 1) == -1) | 608 | case V4L2_CID_SATURATION: |
625 | return -1; | 609 | return v4l2_ctrl_query_fill(qc, -64, 64, 1, 64); |
626 | w9966_i2c_setscl(cam, 0); | 610 | case V4L2_CID_HUE: |
611 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); | ||
627 | } | 612 | } |
628 | 613 | return -EINVAL; | |
629 | w9966_i2c_setsda(cam, 1); | ||
630 | |||
631 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
632 | return -1; | ||
633 | w9966_i2c_setscl(cam, 0); | ||
634 | |||
635 | return 0; | ||
636 | } | 614 | } |
637 | 615 | ||
638 | // Read a data byte with ack from the i2c-bus | 616 | static int cam_g_ctrl(struct file *file, void *priv, |
639 | // Expects a claimed pdev. -1 on error | 617 | struct v4l2_control *ctrl) |
640 | #if 0 | ||
641 | static int w9966_i2c_rbyte(struct w9966_dev* cam) | ||
642 | { | 618 | { |
643 | unsigned char data = 0x00; | 619 | struct w9966 *cam = video_drvdata(file); |
644 | int i; | 620 | int ret = 0; |
645 | |||
646 | w9966_i2c_setsda(cam, 1); | ||
647 | 621 | ||
648 | for (i = 0; i < 8; i++) | 622 | switch (ctrl->id) { |
649 | { | 623 | case V4L2_CID_BRIGHTNESS: |
650 | if (w9966_i2c_setscl(cam, 1) == -1) | 624 | ctrl->value = cam->brightness; |
651 | return -1; | 625 | break; |
652 | data = data << 1; | 626 | case V4L2_CID_CONTRAST: |
653 | if (w9966_i2c_getsda(cam)) | 627 | ctrl->value = cam->contrast; |
654 | data |= 0x01; | 628 | break; |
655 | 629 | case V4L2_CID_SATURATION: | |
656 | w9966_i2c_setscl(cam, 0); | 630 | ctrl->value = cam->color; |
631 | break; | ||
632 | case V4L2_CID_HUE: | ||
633 | ctrl->value = cam->hue; | ||
634 | break; | ||
635 | default: | ||
636 | ret = -EINVAL; | ||
637 | break; | ||
657 | } | 638 | } |
658 | return data; | 639 | return ret; |
659 | } | 640 | } |
660 | #endif | ||
661 | 641 | ||
662 | // Read a register from the i2c device. | 642 | static int cam_s_ctrl(struct file *file, void *priv, |
663 | // Expects claimed pdev. -1 on error | 643 | struct v4l2_control *ctrl) |
664 | #if 0 | ||
665 | static int w9966_rReg_i2c(struct w9966_dev* cam, int reg) | ||
666 | { | 644 | { |
667 | int data; | 645 | struct w9966 *cam = video_drvdata(file); |
668 | 646 | int ret = 0; | |
669 | w9966_i2c_setsda(cam, 0); | ||
670 | w9966_i2c_setscl(cam, 0); | ||
671 | |||
672 | if ( | ||
673 | w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || | ||
674 | w9966_i2c_wbyte(cam, reg) == -1 | ||
675 | ) | ||
676 | return -1; | ||
677 | |||
678 | w9966_i2c_setsda(cam, 1); | ||
679 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
680 | return -1; | ||
681 | w9966_i2c_setsda(cam, 0); | ||
682 | w9966_i2c_setscl(cam, 0); | ||
683 | 647 | ||
684 | if ( | 648 | mutex_lock(&cam->lock); |
685 | w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1 || | 649 | switch (ctrl->id) { |
686 | (data = w9966_i2c_rbyte(cam)) == -1 | 650 | case V4L2_CID_BRIGHTNESS: |
687 | ) | 651 | cam->brightness = ctrl->value; |
688 | return -1; | 652 | break; |
653 | case V4L2_CID_CONTRAST: | ||
654 | cam->contrast = ctrl->value; | ||
655 | break; | ||
656 | case V4L2_CID_SATURATION: | ||
657 | cam->color = ctrl->value; | ||
658 | break; | ||
659 | case V4L2_CID_HUE: | ||
660 | cam->hue = ctrl->value; | ||
661 | break; | ||
662 | default: | ||
663 | ret = -EINVAL; | ||
664 | break; | ||
665 | } | ||
689 | 666 | ||
690 | w9966_i2c_setsda(cam, 0); | 667 | if (ret == 0) { |
668 | w9966_pdev_claim(cam); | ||
691 | 669 | ||
692 | if (w9966_i2c_setscl(cam, 1) == -1) | 670 | if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 || |
693 | return -1; | 671 | w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 || |
694 | w9966_i2c_setsda(cam, 1); | 672 | w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 || |
673 | w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) { | ||
674 | ret = -EIO; | ||
675 | } | ||
695 | 676 | ||
696 | return data; | 677 | w9966_pdev_release(cam); |
678 | } | ||
679 | mutex_unlock(&cam->lock); | ||
680 | return ret; | ||
697 | } | 681 | } |
698 | #endif | ||
699 | 682 | ||
700 | // Write a register to the i2c device. | 683 | static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
701 | // Expects claimed pdev. -1 on error | ||
702 | static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) | ||
703 | { | 684 | { |
704 | w9966_i2c_setsda(cam, 0); | 685 | struct w9966 *cam = video_drvdata(file); |
705 | w9966_i2c_setscl(cam, 0); | 686 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
706 | 687 | ||
707 | if ( | 688 | pix->width = cam->width; |
708 | w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || | 689 | pix->height = cam->height; |
709 | w9966_i2c_wbyte(cam, reg) == -1 || | 690 | pix->pixelformat = V4L2_PIX_FMT_YUYV; |
710 | w9966_i2c_wbyte(cam, data) == -1 | 691 | pix->field = V4L2_FIELD_NONE; |
711 | ) | 692 | pix->bytesperline = 2 * cam->width; |
712 | return -1; | 693 | pix->sizeimage = 2 * cam->width * cam->height; |
713 | 694 | /* Just a guess */ | |
714 | w9966_i2c_setsda(cam, 0); | 695 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; |
715 | if (w9966_i2c_setscl(cam, 1) == -1) | ||
716 | return -1; | ||
717 | |||
718 | w9966_i2c_setsda(cam, 1); | ||
719 | |||
720 | return 0; | 696 | return 0; |
721 | } | 697 | } |
722 | 698 | ||
723 | /* | 699 | static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
724 | * Video4linux interfacing | 700 | { |
725 | */ | 701 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
726 | 702 | ||
727 | static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 703 | if (pix->width < 2) |
728 | { | 704 | pix->width = 2; |
729 | struct w9966_dev *cam = video_drvdata(file); | 705 | if (pix->height < 1) |
730 | 706 | pix->height = 1; | |
731 | switch(cmd) | 707 | if (pix->width > W9966_WND_MAX_W) |
732 | { | 708 | pix->width = W9966_WND_MAX_W; |
733 | case VIDIOCGCAP: | 709 | if (pix->height > W9966_WND_MAX_H) |
734 | { | 710 | pix->height = W9966_WND_MAX_H; |
735 | static struct video_capability vcap = { | 711 | pix->pixelformat = V4L2_PIX_FMT_YUYV; |
736 | .name = W9966_DRIVERNAME, | 712 | pix->field = V4L2_FIELD_NONE; |
737 | .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, | 713 | pix->bytesperline = 2 * pix->width; |
738 | .channels = 1, | 714 | pix->sizeimage = 2 * pix->width * pix->height; |
739 | .maxwidth = W9966_WND_MAX_W, | 715 | /* Just a guess */ |
740 | .maxheight = W9966_WND_MAX_H, | 716 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; |
741 | .minwidth = 2, | 717 | return 0; |
742 | .minheight = 1, | 718 | } |
743 | }; | ||
744 | struct video_capability *cap = arg; | ||
745 | *cap = vcap; | ||
746 | return 0; | ||
747 | } | ||
748 | case VIDIOCGCHAN: | ||
749 | { | ||
750 | struct video_channel *vch = arg; | ||
751 | if(vch->channel != 0) // We only support one channel (#0) | ||
752 | return -EINVAL; | ||
753 | memset(vch,0,sizeof(*vch)); | ||
754 | strcpy(vch->name, "CCD-input"); | ||
755 | vch->type = VIDEO_TYPE_CAMERA; | ||
756 | return 0; | ||
757 | } | ||
758 | case VIDIOCSCHAN: | ||
759 | { | ||
760 | struct video_channel *vch = arg; | ||
761 | if(vch->channel != 0) | ||
762 | return -EINVAL; | ||
763 | return 0; | ||
764 | } | ||
765 | case VIDIOCGTUNER: | ||
766 | { | ||
767 | struct video_tuner *vtune = arg; | ||
768 | if(vtune->tuner != 0) | ||
769 | return -EINVAL; | ||
770 | strcpy(vtune->name, "no tuner"); | ||
771 | vtune->rangelow = 0; | ||
772 | vtune->rangehigh = 0; | ||
773 | vtune->flags = VIDEO_TUNER_NORM; | ||
774 | vtune->mode = VIDEO_MODE_AUTO; | ||
775 | vtune->signal = 0xffff; | ||
776 | return 0; | ||
777 | } | ||
778 | case VIDIOCSTUNER: | ||
779 | { | ||
780 | struct video_tuner *vtune = arg; | ||
781 | if (vtune->tuner != 0) | ||
782 | return -EINVAL; | ||
783 | if (vtune->mode != VIDEO_MODE_AUTO) | ||
784 | return -EINVAL; | ||
785 | return 0; | ||
786 | } | ||
787 | case VIDIOCGPICT: | ||
788 | { | ||
789 | struct video_picture vpic = { | ||
790 | cam->brightness << 8, // brightness | ||
791 | (cam->hue + 128) << 8, // hue | ||
792 | cam->color << 9, // color | ||
793 | cam->contrast << 9, // contrast | ||
794 | 0x8000, // whiteness | ||
795 | 16, VIDEO_PALETTE_YUV422// bpp, palette format | ||
796 | }; | ||
797 | struct video_picture *pic = arg; | ||
798 | *pic = vpic; | ||
799 | return 0; | ||
800 | } | ||
801 | case VIDIOCSPICT: | ||
802 | { | ||
803 | struct video_picture *vpic = arg; | ||
804 | if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV)) | ||
805 | return -EINVAL; | ||
806 | |||
807 | cam->brightness = vpic->brightness >> 8; | ||
808 | cam->hue = (vpic->hue >> 8) - 128; | ||
809 | cam->color = vpic->colour >> 9; | ||
810 | cam->contrast = vpic->contrast >> 9; | ||
811 | 719 | ||
812 | w9966_pdev_claim(cam); | 720 | static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
721 | { | ||
722 | struct w9966 *cam = video_drvdata(file); | ||
723 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
724 | int ret = cam_try_fmt_vid_cap(file, fh, fmt); | ||
813 | 725 | ||
814 | if ( | 726 | if (ret) |
815 | w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 || | 727 | return ret; |
816 | w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 || | ||
817 | w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 || | ||
818 | w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1 | ||
819 | ) { | ||
820 | w9966_pdev_release(cam); | ||
821 | return -EIO; | ||
822 | } | ||
823 | 728 | ||
824 | w9966_pdev_release(cam); | 729 | mutex_lock(&cam->lock); |
825 | return 0; | 730 | /* Update camera regs */ |
826 | } | 731 | w9966_pdev_claim(cam); |
827 | case VIDIOCSWIN: | 732 | ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height); |
828 | { | 733 | w9966_pdev_release(cam); |
829 | int ret; | 734 | mutex_unlock(&cam->lock); |
830 | struct video_window *vwin = arg; | 735 | return ret; |
831 | 736 | } | |
832 | if (vwin->flags != 0) | ||
833 | return -EINVAL; | ||
834 | if (vwin->clipcount != 0) | ||
835 | return -EINVAL; | ||
836 | if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) | ||
837 | return -EINVAL; | ||
838 | if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) | ||
839 | return -EINVAL; | ||
840 | |||
841 | // Update camera regs | ||
842 | w9966_pdev_claim(cam); | ||
843 | ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); | ||
844 | w9966_pdev_release(cam); | ||
845 | 737 | ||
846 | if (ret != 0) { | 738 | static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) |
847 | DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); | 739 | { |
848 | return -EIO; | 740 | static struct v4l2_fmtdesc formats[] = { |
849 | } | 741 | { 0, 0, 0, |
742 | "YUV 4:2:2", V4L2_PIX_FMT_YUYV, | ||
743 | { 0, 0, 0, 0 } | ||
744 | }, | ||
745 | }; | ||
746 | enum v4l2_buf_type type = fmt->type; | ||
850 | 747 | ||
851 | return 0; | 748 | if (fmt->index > 0) |
852 | } | ||
853 | case VIDIOCGWIN: | ||
854 | { | ||
855 | struct video_window *vwin = arg; | ||
856 | memset(vwin, 0, sizeof(*vwin)); | ||
857 | vwin->width = cam->width; | ||
858 | vwin->height = cam->height; | ||
859 | return 0; | ||
860 | } | ||
861 | // Unimplemented | ||
862 | case VIDIOCCAPTURE: | ||
863 | case VIDIOCGFBUF: | ||
864 | case VIDIOCSFBUF: | ||
865 | case VIDIOCKEY: | ||
866 | case VIDIOCGFREQ: | ||
867 | case VIDIOCSFREQ: | ||
868 | case VIDIOCGAUDIO: | ||
869 | case VIDIOCSAUDIO: | ||
870 | return -EINVAL; | 749 | return -EINVAL; |
871 | default: | ||
872 | return -ENOIOCTLCMD; | ||
873 | } | ||
874 | return 0; | ||
875 | } | ||
876 | 750 | ||
877 | static long w9966_v4l_ioctl(struct file *file, | 751 | *fmt = formats[fmt->index]; |
878 | unsigned int cmd, unsigned long arg) | 752 | fmt->type = type; |
879 | { | 753 | return 0; |
880 | return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); | ||
881 | } | 754 | } |
882 | 755 | ||
883 | // Capture data | 756 | /* Capture data */ |
884 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | 757 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, |
885 | size_t count, loff_t *ppos) | 758 | size_t count, loff_t *ppos) |
886 | { | 759 | { |
887 | struct w9966_dev *cam = video_drvdata(file); | 760 | struct w9966 *cam = video_drvdata(file); |
888 | unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 | 761 | unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ |
889 | unsigned char __user *dest = (unsigned char __user *)buf; | 762 | unsigned char __user *dest = (unsigned char __user *)buf; |
890 | unsigned long dleft = count; | 763 | unsigned long dleft = count; |
891 | unsigned char *tbuf; | 764 | unsigned char *tbuf; |
892 | 765 | ||
893 | // Why would anyone want more than this?? | 766 | /* Why would anyone want more than this?? */ |
894 | if (count > cam->width * cam->height * 2) | 767 | if (count > cam->width * cam->height * 2) |
895 | return -EINVAL; | 768 | return -EINVAL; |
896 | 769 | ||
770 | mutex_lock(&cam->lock); | ||
897 | w9966_pdev_claim(cam); | 771 | w9966_pdev_claim(cam); |
898 | w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer | 772 | w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ |
899 | w9966_wReg(cam, 0x00, 0x00); // Return to normal operation | 773 | w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */ |
900 | w9966_wReg(cam, 0x01, 0x98); // Enable capture | 774 | w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */ |
901 | 775 | ||
902 | // write special capture-addr and negotiate into data transfer | 776 | /* write special capture-addr and negotiate into data transfer */ |
903 | if ( | 777 | if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) || |
904 | (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )|| | 778 | (parport_write(cam->pport, &addr, 1) != 1) || |
905 | (parport_write(cam->pport, &addr, 1) != 1 )|| | 779 | (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { |
906 | (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0 ) | ||
907 | ) { | ||
908 | w9966_pdev_release(cam); | 780 | w9966_pdev_release(cam); |
781 | mutex_unlock(&cam->lock); | ||
909 | return -EFAULT; | 782 | return -EFAULT; |
910 | } | 783 | } |
911 | 784 | ||
@@ -915,8 +788,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | |||
915 | goto out; | 788 | goto out; |
916 | } | 789 | } |
917 | 790 | ||
918 | while(dleft > 0) | 791 | while (dleft > 0) { |
919 | { | ||
920 | unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; | 792 | unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; |
921 | 793 | ||
922 | if (parport_read(cam->pport, tbuf, tsize) < tsize) { | 794 | if (parport_read(cam->pport, tbuf, tsize) < tsize) { |
@@ -931,43 +803,167 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | |||
931 | dleft -= tsize; | 803 | dleft -= tsize; |
932 | } | 804 | } |
933 | 805 | ||
934 | w9966_wReg(cam, 0x01, 0x18); // Disable capture | 806 | w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */ |
935 | 807 | ||
936 | out: | 808 | out: |
937 | kfree(tbuf); | 809 | kfree(tbuf); |
938 | w9966_pdev_release(cam); | 810 | w9966_pdev_release(cam); |
811 | mutex_unlock(&cam->lock); | ||
939 | 812 | ||
940 | return count; | 813 | return count; |
941 | } | 814 | } |
942 | 815 | ||
816 | static const struct v4l2_file_operations w9966_fops = { | ||
817 | .owner = THIS_MODULE, | ||
818 | .ioctl = video_ioctl2, | ||
819 | .read = w9966_v4l_read, | ||
820 | }; | ||
821 | |||
822 | static const struct v4l2_ioctl_ops w9966_ioctl_ops = { | ||
823 | .vidioc_querycap = cam_querycap, | ||
824 | .vidioc_g_input = cam_g_input, | ||
825 | .vidioc_s_input = cam_s_input, | ||
826 | .vidioc_enum_input = cam_enum_input, | ||
827 | .vidioc_queryctrl = cam_queryctrl, | ||
828 | .vidioc_g_ctrl = cam_g_ctrl, | ||
829 | .vidioc_s_ctrl = cam_s_ctrl, | ||
830 | .vidioc_enum_fmt_vid_cap = cam_enum_fmt_vid_cap, | ||
831 | .vidioc_g_fmt_vid_cap = cam_g_fmt_vid_cap, | ||
832 | .vidioc_s_fmt_vid_cap = cam_s_fmt_vid_cap, | ||
833 | .vidioc_try_fmt_vid_cap = cam_try_fmt_vid_cap, | ||
834 | }; | ||
835 | |||
943 | 836 | ||
944 | // Called once for every parport on init | 837 | /* Initialize camera device. Setup all internal flags, set a |
838 | default video mode, setup ccd-chip, register v4l device etc.. | ||
839 | Also used for 'probing' of hardware. | ||
840 | -1 on error */ | ||
841 | static int w9966_init(struct w9966 *cam, struct parport *port) | ||
842 | { | ||
843 | struct v4l2_device *v4l2_dev = &cam->v4l2_dev; | ||
844 | |||
845 | if (cam->dev_state != 0) | ||
846 | return -1; | ||
847 | |||
848 | strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name)); | ||
849 | |||
850 | if (v4l2_device_register(NULL, v4l2_dev) < 0) { | ||
851 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
852 | return -1; | ||
853 | } | ||
854 | cam->pport = port; | ||
855 | cam->brightness = 128; | ||
856 | cam->contrast = 64; | ||
857 | cam->color = 64; | ||
858 | cam->hue = 0; | ||
859 | |||
860 | /* Select requested transfer mode */ | ||
861 | switch (parmode) { | ||
862 | default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ | ||
863 | case 0: | ||
864 | if (port->modes & PARPORT_MODE_ECP) | ||
865 | cam->ppmode = IEEE1284_MODE_ECP; | ||
866 | else if (port->modes & PARPORT_MODE_EPP) | ||
867 | cam->ppmode = IEEE1284_MODE_EPP; | ||
868 | else | ||
869 | cam->ppmode = IEEE1284_MODE_ECP; | ||
870 | break; | ||
871 | case 1: /* hw- or sw-ecp */ | ||
872 | cam->ppmode = IEEE1284_MODE_ECP; | ||
873 | break; | ||
874 | case 2: /* hw- or sw-epp */ | ||
875 | cam->ppmode = IEEE1284_MODE_EPP; | ||
876 | break; | ||
877 | } | ||
878 | |||
879 | /* Tell the parport driver that we exists */ | ||
880 | cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); | ||
881 | if (cam->pdev == NULL) { | ||
882 | DPRINTF("parport_register_device() failed\n"); | ||
883 | return -1; | ||
884 | } | ||
885 | w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); | ||
886 | |||
887 | w9966_pdev_claim(cam); | ||
888 | |||
889 | /* Setup a default capture mode */ | ||
890 | if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { | ||
891 | DPRINTF("w9966_setup() failed.\n"); | ||
892 | return -1; | ||
893 | } | ||
894 | |||
895 | w9966_pdev_release(cam); | ||
896 | |||
897 | /* Fill in the video_device struct and register us to v4l */ | ||
898 | strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name)); | ||
899 | cam->vdev.v4l2_dev = v4l2_dev; | ||
900 | cam->vdev.fops = &w9966_fops; | ||
901 | cam->vdev.ioctl_ops = &w9966_ioctl_ops; | ||
902 | cam->vdev.release = video_device_release_empty; | ||
903 | video_set_drvdata(&cam->vdev, cam); | ||
904 | |||
905 | mutex_init(&cam->lock); | ||
906 | |||
907 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) | ||
908 | return -1; | ||
909 | |||
910 | w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); | ||
911 | |||
912 | /* All ok */ | ||
913 | v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n", | ||
914 | cam->pport->name); | ||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | |||
919 | /* Terminate everything gracefully */ | ||
920 | static void w9966_term(struct w9966 *cam) | ||
921 | { | ||
922 | /* Unregister from v4l */ | ||
923 | if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { | ||
924 | video_unregister_device(&cam->vdev); | ||
925 | w9966_set_state(cam, W9966_STATE_VDEV, 0); | ||
926 | } | ||
927 | |||
928 | /* Terminate from IEEE1284 mode and release pdev block */ | ||
929 | if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { | ||
930 | w9966_pdev_claim(cam); | ||
931 | parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); | ||
932 | w9966_pdev_release(cam); | ||
933 | } | ||
934 | |||
935 | /* Unregister from parport */ | ||
936 | if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { | ||
937 | parport_unregister_device(cam->pdev); | ||
938 | w9966_set_state(cam, W9966_STATE_PDEV, 0); | ||
939 | } | ||
940 | } | ||
941 | |||
942 | |||
943 | /* Called once for every parport on init */ | ||
945 | static void w9966_attach(struct parport *port) | 944 | static void w9966_attach(struct parport *port) |
946 | { | 945 | { |
947 | int i; | 946 | int i; |
948 | 947 | ||
949 | for (i = 0; i < W9966_MAXCAMS; i++) | 948 | for (i = 0; i < W9966_MAXCAMS; i++) { |
950 | { | 949 | if (w9966_cams[i].dev_state != 0) /* Cam is already assigned */ |
951 | if (w9966_cams[i].dev_state != 0) // Cam is already assigned | ||
952 | continue; | 950 | continue; |
953 | if ( | 951 | if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) { |
954 | strcmp(pardev[i], "aggressive") == 0 || | ||
955 | strcmp(pardev[i], port->name) == 0 | ||
956 | ) { | ||
957 | if (w9966_init(&w9966_cams[i], port) != 0) | 952 | if (w9966_init(&w9966_cams[i], port) != 0) |
958 | w9966_term(&w9966_cams[i]); | 953 | w9966_term(&w9966_cams[i]); |
959 | break; // return | 954 | break; /* return */ |
960 | } | 955 | } |
961 | } | 956 | } |
962 | } | 957 | } |
963 | 958 | ||
964 | // Called once for every parport on termination | 959 | /* Called once for every parport on termination */ |
965 | static void w9966_detach(struct parport *port) | 960 | static void w9966_detach(struct parport *port) |
966 | { | 961 | { |
967 | int i; | 962 | int i; |
963 | |||
968 | for (i = 0; i < W9966_MAXCAMS; i++) | 964 | for (i = 0; i < W9966_MAXCAMS; i++) |
969 | if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) | 965 | if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) |
970 | w9966_term(&w9966_cams[i]); | 966 | w9966_term(&w9966_cams[i]); |
971 | } | 967 | } |
972 | 968 | ||
973 | 969 | ||
@@ -977,17 +973,18 @@ static struct parport_driver w9966_ppd = { | |||
977 | .detach = w9966_detach, | 973 | .detach = w9966_detach, |
978 | }; | 974 | }; |
979 | 975 | ||
980 | // Module entry point | 976 | /* Module entry point */ |
981 | static int __init w9966_mod_init(void) | 977 | static int __init w9966_mod_init(void) |
982 | { | 978 | { |
983 | int i; | 979 | int i; |
980 | |||
984 | for (i = 0; i < W9966_MAXCAMS; i++) | 981 | for (i = 0; i < W9966_MAXCAMS; i++) |
985 | w9966_cams[i].dev_state = 0; | 982 | w9966_cams[i].dev_state = 0; |
986 | 983 | ||
987 | return parport_register_driver(&w9966_ppd); | 984 | return parport_register_driver(&w9966_ppd); |
988 | } | 985 | } |
989 | 986 | ||
990 | // Module cleanup | 987 | /* Module cleanup */ |
991 | static void __exit w9966_mod_term(void) | 988 | static void __exit w9966_mod_term(void) |
992 | { | 989 | { |
993 | parport_unregister_driver(&w9966_ppd); | 990 | parport_unregister_driver(&w9966_ppd); |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index e44e4b5f3e50..bb51cfb0c647 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -1153,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) | |||
1153 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 1153 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
1154 | return -EFAULT; | 1154 | return -EFAULT; |
1155 | 1155 | ||
1156 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | 1156 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { |
1157 | if (ctrl.id == s->qctrl[i].id) { | 1157 | if (ctrl.id == s->qctrl[i].id) { |
1158 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) | 1158 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) |
1159 | return -EINVAL; | 1159 | return -EINVAL; |
@@ -1163,7 +1163,9 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) | |||
1163 | ctrl.value -= ctrl.value % s->qctrl[i].step; | 1163 | ctrl.value -= ctrl.value % s->qctrl[i].step; |
1164 | break; | 1164 | break; |
1165 | } | 1165 | } |
1166 | 1166 | } | |
1167 | if (i == ARRAY_SIZE(s->qctrl)) | ||
1168 | return -EINVAL; | ||
1167 | if ((err = s->set_ctrl(cam, &ctrl))) | 1169 | if ((err = s->set_ctrl(cam, &ctrl))) |
1168 | return err; | 1170 | return err; |
1169 | 1171 | ||
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 3a408de91b9c..0be783c203f7 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h | |||
@@ -58,7 +58,7 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); | |||
58 | .idProduct = (prod), \ | 58 | .idProduct = (prod), \ |
59 | .bInterfaceClass = (intclass) | 59 | .bInterfaceClass = (intclass) |
60 | 60 | ||
61 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 61 | #if !defined CONFIG_USB_GSPCA_ZC3XX && !defined CONFIG_USB_GSPCA_ZC3XX_MODULE |
62 | #define ZC0301_ID_TABLE \ | 62 | #define ZC0301_ID_TABLE \ |
63 | static const struct usb_device_id zc0301_id_table[] = { \ | 63 | static const struct usb_device_id zc0301_id_table[] = { \ |
64 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | 64 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ |
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index cb1de7ea197a..8997add1248e 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h | |||
@@ -33,6 +33,10 @@ | |||
33 | 33 | ||
34 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
35 | 35 | ||
36 | #define ZORAN_VIDMODE_PAL 0 | ||
37 | #define ZORAN_VIDMODE_NTSC 1 | ||
38 | #define ZORAN_VIDMODE_SECAM 2 | ||
39 | |||
36 | struct zoran_requestbuffers { | 40 | struct zoran_requestbuffers { |
37 | unsigned long count; /* Number of buffers for MJPEG grabbing */ | 41 | unsigned long count; /* Number of buffers for MJPEG grabbing */ |
38 | unsigned long size; /* Size PER BUFFER in bytes */ | 42 | unsigned long size; /* Size PER BUFFER in bytes */ |
@@ -48,7 +52,7 @@ struct zoran_sync { | |||
48 | struct zoran_status { | 52 | struct zoran_status { |
49 | int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ | 53 | int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ |
50 | int signal; /* Returned: 1 if valid video signal detected */ | 54 | int signal; /* Returned: 1 if valid video signal detected */ |
51 | int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ | 55 | int norm; /* Returned: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ |
52 | int color; /* Returned: 1 if color signal detected */ | 56 | int color; /* Returned: 1 if color signal detected */ |
53 | }; | 57 | }; |
54 | 58 | ||
@@ -62,7 +66,7 @@ struct zoran_params { | |||
62 | /* Main control parameters */ | 66 | /* Main control parameters */ |
63 | 67 | ||
64 | int input; /* Input channel: 0 = Composite, 1 = S-VHS */ | 68 | int input; /* Input channel: 0 = Composite, 1 = S-VHS */ |
65 | int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ | 69 | int norm; /* Norm: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ |
66 | int decimation; /* decimation of captured video, | 70 | int decimation; /* decimation of captured video, |
67 | * enlargement of video played back. | 71 | * enlargement of video played back. |
68 | * Valid values are 1, 2, 4 or 0. | 72 | * Valid values are 1, 2, 4 or 0. |
@@ -131,13 +135,13 @@ struct zoran_params { | |||
131 | /* | 135 | /* |
132 | Private IOCTL to set up for displaying MJPEG | 136 | Private IOCTL to set up for displaying MJPEG |
133 | */ | 137 | */ |
134 | #define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct zoran_params) | 138 | #define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct zoran_params) |
135 | #define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct zoran_params) | 139 | #define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOC_PRIVATE+1, struct zoran_params) |
136 | #define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct zoran_requestbuffers) | 140 | #define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOC_PRIVATE+2, struct zoran_requestbuffers) |
137 | #define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) | 141 | #define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+3, int) |
138 | #define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) | 142 | #define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOC_PRIVATE+4, int) |
139 | #define BUZIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct zoran_sync) | 143 | #define BUZIOC_SYNC _IOR ('v', BASE_VIDIOC_PRIVATE+5, struct zoran_sync) |
140 | #define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct zoran_status) | 144 | #define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOC_PRIVATE+6, struct zoran_status) |
141 | 145 | ||
142 | 146 | ||
143 | #ifdef __KERNEL__ | 147 | #ifdef __KERNEL__ |
@@ -401,7 +405,7 @@ struct zoran { | |||
401 | spinlock_t spinlock; /* Spinlock */ | 405 | spinlock_t spinlock; /* Spinlock */ |
402 | 406 | ||
403 | /* Video for Linux parameters */ | 407 | /* Video for Linux parameters */ |
404 | int input; /* card's norm and input - norm=VIDEO_MODE_* */ | 408 | int input; /* card's norm and input */ |
405 | v4l2_std_id norm; | 409 | v4l2_std_id norm; |
406 | 410 | ||
407 | /* Current buffer params */ | 411 | /* Current buffer params */ |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index ec41303544e5..6f89d0a096ea 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -60,7 +60,7 @@ | |||
60 | 60 | ||
61 | #include <linux/spinlock.h> | 61 | #include <linux/spinlock.h> |
62 | 62 | ||
63 | #include <linux/videodev.h> | 63 | #include <linux/videodev2.h> |
64 | #include <media/v4l2-common.h> | 64 | #include <media/v4l2-common.h> |
65 | #include <media/v4l2-ioctl.h> | 65 | #include <media/v4l2-ioctl.h> |
66 | #include "videocodec.h" | 66 | #include "videocodec.h" |
@@ -1549,11 +1549,11 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) | |||
1549 | mutex_lock(&zr->resource_lock); | 1549 | mutex_lock(&zr->resource_lock); |
1550 | 1550 | ||
1551 | if (zr->norm & V4L2_STD_NTSC) | 1551 | if (zr->norm & V4L2_STD_NTSC) |
1552 | bparams->norm = VIDEO_MODE_NTSC; | 1552 | bparams->norm = ZORAN_VIDMODE_NTSC; |
1553 | else if (zr->norm & V4L2_STD_PAL) | 1553 | else if (zr->norm & V4L2_STD_SECAM) |
1554 | bparams->norm = VIDEO_MODE_PAL; | 1554 | bparams->norm = ZORAN_VIDMODE_SECAM; |
1555 | else | 1555 | else |
1556 | bparams->norm = VIDEO_MODE_SECAM; | 1556 | bparams->norm = ZORAN_VIDMODE_PAL; |
1557 | 1557 | ||
1558 | bparams->input = zr->input; | 1558 | bparams->input = zr->input; |
1559 | 1559 | ||
@@ -1789,11 +1789,11 @@ gstat_unlock_and_return: | |||
1789 | bstat->signal = | 1789 | bstat->signal = |
1790 | (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; | 1790 | (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; |
1791 | if (norm & V4L2_STD_NTSC) | 1791 | if (norm & V4L2_STD_NTSC) |
1792 | bstat->norm = VIDEO_MODE_NTSC; | 1792 | bstat->norm = ZORAN_VIDMODE_NTSC; |
1793 | else if (norm & V4L2_STD_SECAM) | 1793 | else if (norm & V4L2_STD_SECAM) |
1794 | bstat->norm = VIDEO_MODE_SECAM; | 1794 | bstat->norm = ZORAN_VIDMODE_SECAM; |
1795 | else | 1795 | else |
1796 | bstat->norm = VIDEO_MODE_PAL; | 1796 | bstat->norm = ZORAN_VIDMODE_PAL; |
1797 | 1797 | ||
1798 | bstat->color = | 1798 | bstat->color = |
1799 | (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; | 1799 | (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; |
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 3d4bac252902..a82b5bd18d26 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -376,8 +376,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | |||
376 | if (*count == 0) | 376 | if (*count == 0) |
377 | *count = ZR364XX_DEF_BUFS; | 377 | *count = ZR364XX_DEF_BUFS; |
378 | 378 | ||
379 | while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024) | 379 | if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024) |
380 | (*count)--; | 380 | *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size; |
381 | 381 | ||
382 | return 0; | 382 | return 0; |
383 | } | 383 | } |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7696a664f8a5..5589616082e7 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -49,6 +49,8 @@ source "drivers/staging/go7007/Kconfig" | |||
49 | 49 | ||
50 | source "drivers/staging/cx25821/Kconfig" | 50 | source "drivers/staging/cx25821/Kconfig" |
51 | 51 | ||
52 | source "drivers/staging/tm6000/Kconfig" | ||
53 | |||
52 | source "drivers/staging/usbip/Kconfig" | 54 | source "drivers/staging/usbip/Kconfig" |
53 | 55 | ||
54 | source "drivers/staging/winbond/Kconfig" | 56 | source "drivers/staging/winbond/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ea2e70e2fed4..ec45d4bb8c11 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_ET131X) += et131x/ | |||
7 | obj-$(CONFIG_SLICOSS) += slicoss/ | 7 | obj-$(CONFIG_SLICOSS) += slicoss/ |
8 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | 8 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
9 | obj-$(CONFIG_VIDEO_CX25821) += cx25821/ | 9 | obj-$(CONFIG_VIDEO_CX25821) += cx25821/ |
10 | obj-$(CONFIG_VIDEO_TM6000) += tm6000/ | ||
10 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ | 11 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ |
11 | obj-$(CONFIG_W35UND) += winbond/ | 12 | obj-$(CONFIG_W35UND) += winbond/ |
12 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ | 13 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ |
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c index 061add30ba8a..1798975a69bd 100644 --- a/drivers/staging/cx25821/cx25821-alsa.c +++ b/drivers/staging/cx25821/cx25821-alsa.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | 31 | ||
32 | #include <asm/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/pcm.h> | 34 | #include <sound/pcm.h> |
35 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
@@ -42,10 +42,10 @@ | |||
42 | 42 | ||
43 | #define AUDIO_SRAM_CHANNEL SRAM_CH08 | 43 | #define AUDIO_SRAM_CHANNEL SRAM_CH08 |
44 | 44 | ||
45 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 45 | #define dprintk(level, fmt, arg...) if (debug >= level) \ |
46 | printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) | 46 | printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) |
47 | 47 | ||
48 | #define dprintk_core(level,fmt, arg...) if (debug >= level) \ | 48 | #define dprintk_core(level, fmt, arg...) if (debug >= level) \ |
49 | printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) | 49 | printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) |
50 | 50 | ||
51 | /**************************************************************************** | 51 | /**************************************************************************** |
@@ -81,7 +81,6 @@ struct cx25821_audio_dev { | |||
81 | 81 | ||
82 | struct snd_pcm_substream *substream; | 82 | struct snd_pcm_substream *substream; |
83 | }; | 83 | }; |
84 | typedef struct cx25821_audio_dev snd_cx25821_card_t; | ||
85 | 84 | ||
86 | 85 | ||
87 | /**************************************************************************** | 86 | /**************************************************************************** |
@@ -90,7 +89,7 @@ typedef struct cx25821_audio_dev snd_cx25821_card_t; | |||
90 | 89 | ||
91 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 90 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
92 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 91 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
93 | static int enable[SNDRV_CARDS] = { 1,[1 ... (SNDRV_CARDS - 1)] = 1 }; | 92 | static int enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 }; |
94 | 93 | ||
95 | module_param_array(enable, bool, NULL, 0444); | 94 | module_param_array(enable, bool, NULL, 0444); |
96 | MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); | 95 | MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); |
@@ -105,7 +104,7 @@ MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); | |||
105 | MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); | 104 | MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); |
106 | MODULE_AUTHOR("Hiep Huynh"); | 105 | MODULE_AUTHOR("Hiep Huynh"); |
107 | MODULE_LICENSE("GPL"); | 106 | MODULE_LICENSE("GPL"); |
108 | MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); //"{{Conexant,23881}," | 107 | MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); /* "{{Conexant,23881}," */ |
109 | 108 | ||
110 | static unsigned int debug; | 109 | static unsigned int debug; |
111 | module_param(debug, int, 0644); | 110 | module_param(debug, int, 0644); |
@@ -135,7 +134,7 @@ MODULE_PARM_DESC(debug, "enable debug messages"); | |||
135 | * BOARD Specific: Sets audio DMA | 134 | * BOARD Specific: Sets audio DMA |
136 | */ | 135 | */ |
137 | 136 | ||
138 | static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | 137 | static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) |
139 | { | 138 | { |
140 | struct cx25821_buffer *buf = chip->buf; | 139 | struct cx25821_buffer *buf = chip->buf; |
141 | struct cx25821_dev *dev = chip->dev; | 140 | struct cx25821_dev *dev = chip->dev; |
@@ -143,7 +142,7 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | |||
143 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; | 142 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; |
144 | u32 tmp = 0; | 143 | u32 tmp = 0; |
145 | 144 | ||
146 | // enable output on the GPIO 0 for the MCLK ADC (Audio) | 145 | /* enable output on the GPIO 0 for the MCLK ADC (Audio) */ |
147 | cx25821_set_gpiopin_direction(chip->dev, 0, 0); | 146 | cx25821_set_gpiopin_direction(chip->dev, 0, 0); |
148 | 147 | ||
149 | /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ | 148 | /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ |
@@ -158,18 +157,23 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | |||
158 | cx_write(AUD_A_LNGTH, buf->bpl); | 157 | cx_write(AUD_A_LNGTH, buf->bpl); |
159 | 158 | ||
160 | /* reset counter */ | 159 | /* reset counter */ |
161 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 | 160 | /* GP_COUNT_CONTROL_RESET = 0x3 */ |
161 | cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); | ||
162 | atomic_set(&chip->count, 0); | 162 | atomic_set(&chip->count, 0); |
163 | 163 | ||
164 | //Set the input mode to 16-bit | 164 | /* Set the input mode to 16-bit */ |
165 | tmp = cx_read(AUD_A_CFG); | 165 | tmp = cx_read(AUD_A_CFG); |
166 | cx_write(AUD_A_CFG, | 166 | cx_write(AUD_A_CFG, |
167 | tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | | 167 | tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | |
168 | FLD_AUD_CLK_ENABLE); | 168 | FLD_AUD_CLK_ENABLE); |
169 | 169 | ||
170 | //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d " | 170 | /* printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line," |
171 | // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, | 171 | "cmds_start(0x%x)= %d lines/FIFO, %d periods, " |
172 | // chip->num_periods, buf->bpl * chip->num_periods); | 172 | "%d byte buffer\n", buf->bpl, |
173 | audio_ch->cmds_start, | ||
174 | cx_read(audio_ch->cmds_start + 12)>>1, | ||
175 | chip->num_periods, buf->bpl *chip->num_periods); | ||
176 | */ | ||
173 | 177 | ||
174 | /* Enables corresponding bits at AUD_INT_STAT */ | 178 | /* Enables corresponding bits at AUD_INT_STAT */ |
175 | cx_write(AUD_A_INT_MSK, | 179 | cx_write(AUD_A_INT_MSK, |
@@ -182,7 +186,7 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | |||
182 | /* enable audio irqs */ | 186 | /* enable audio irqs */ |
183 | cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); | 187 | cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); |
184 | 188 | ||
185 | // Turn on audio downstream fifo and risc enable 0x101 | 189 | /* Turn on audio downstream fifo and risc enable 0x101 */ |
186 | tmp = cx_read(AUD_INT_DMA_CTL); | 190 | tmp = cx_read(AUD_INT_DMA_CTL); |
187 | cx_set(AUD_INT_DMA_CTL, | 191 | cx_set(AUD_INT_DMA_CTL, |
188 | tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); | 192 | tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); |
@@ -194,7 +198,7 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) | |||
194 | /* | 198 | /* |
195 | * BOARD Specific: Resets audio DMA | 199 | * BOARD Specific: Resets audio DMA |
196 | */ | 200 | */ |
197 | static int _cx25821_stop_audio_dma(snd_cx25821_card_t * chip) | 201 | static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip) |
198 | { | 202 | { |
199 | struct cx25821_dev *dev = chip->dev; | 203 | struct cx25821_dev *dev = chip->dev; |
200 | 204 | ||
@@ -232,13 +236,13 @@ static char *cx25821_aud_irqs[32] = { | |||
232 | /* | 236 | /* |
233 | * BOARD Specific: Threats IRQ audio specific calls | 237 | * BOARD Specific: Threats IRQ audio specific calls |
234 | */ | 238 | */ |
235 | static void cx25821_aud_irq(snd_cx25821_card_t * chip, u32 status, u32 mask) | 239 | static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, |
240 | u32 mask) | ||
236 | { | 241 | { |
237 | struct cx25821_dev *dev = chip->dev; | 242 | struct cx25821_dev *dev = chip->dev; |
238 | 243 | ||
239 | if (0 == (status & mask)) { | 244 | if (0 == (status & mask)) |
240 | return; | 245 | return; |
241 | } | ||
242 | 246 | ||
243 | cx_write(AUD_A_INT_STAT, status); | 247 | cx_write(AUD_A_INT_STAT, status); |
244 | if (debug > 1 || (status & mask & ~0xff)) | 248 | if (debug > 1 || (status & mask & ~0xff)) |
@@ -277,7 +281,7 @@ static void cx25821_aud_irq(snd_cx25821_card_t * chip, u32 status, u32 mask) | |||
277 | */ | 281 | */ |
278 | static irqreturn_t cx25821_irq(int irq, void *dev_id) | 282 | static irqreturn_t cx25821_irq(int irq, void *dev_id) |
279 | { | 283 | { |
280 | snd_cx25821_card_t *chip = dev_id; | 284 | struct cx25821_audio_dev *chip = dev_id; |
281 | struct cx25821_dev *dev = chip->dev; | 285 | struct cx25821_dev *dev = chip->dev; |
282 | u32 status, pci_status; | 286 | u32 status, pci_status; |
283 | u32 audint_status, audint_mask; | 287 | u32 audint_status, audint_mask; |
@@ -318,11 +322,11 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) | |||
318 | if (handled) | 322 | if (handled) |
319 | cx_write(PCI_INT_STAT, pci_status); | 323 | cx_write(PCI_INT_STAT, pci_status); |
320 | 324 | ||
321 | out: | 325 | out: |
322 | return IRQ_RETVAL(handled); | 326 | return IRQ_RETVAL(handled); |
323 | } | 327 | } |
324 | 328 | ||
325 | static int dsp_buffer_free(snd_cx25821_card_t * chip) | 329 | static int dsp_buffer_free(struct cx25821_audio_dev *chip) |
326 | { | 330 | { |
327 | BUG_ON(!chip->dma_size); | 331 | BUG_ON(!chip->dma_size); |
328 | 332 | ||
@@ -363,7 +367,8 @@ static struct snd_pcm_hardware snd_cx25821_digital_hw = { | |||
363 | .period_bytes_max = DEFAULT_FIFO_SIZE / 3, | 367 | .period_bytes_max = DEFAULT_FIFO_SIZE / 3, |
364 | .periods_min = 1, | 368 | .periods_min = 1, |
365 | .periods_max = AUDIO_LINE_SIZE, | 369 | .periods_max = AUDIO_LINE_SIZE, |
366 | .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 | 370 | /* 128 * 128 = 16384 = 1024 * 16 */ |
371 | .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE), | ||
367 | }; | 372 | }; |
368 | 373 | ||
369 | /* | 374 | /* |
@@ -371,7 +376,7 @@ static struct snd_pcm_hardware snd_cx25821_digital_hw = { | |||
371 | */ | 376 | */ |
372 | static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) | 377 | static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) |
373 | { | 378 | { |
374 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | 379 | struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); |
375 | struct snd_pcm_runtime *runtime = substream->runtime; | 380 | struct snd_pcm_runtime *runtime = substream->runtime; |
376 | int err; | 381 | int err; |
377 | unsigned int bpl = 0; | 382 | unsigned int bpl = 0; |
@@ -393,18 +398,19 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) | |||
393 | 398 | ||
394 | if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != | 399 | if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != |
395 | DEFAULT_FIFO_SIZE) { | 400 | DEFAULT_FIFO_SIZE) { |
396 | bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters | 401 | /* since there are 3 audio Clusters */ |
402 | bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; | ||
397 | bpl &= ~7; /* must be multiple of 8 */ | 403 | bpl &= ~7; /* must be multiple of 8 */ |
398 | 404 | ||
399 | if (bpl > AUDIO_LINE_SIZE) { | 405 | if (bpl > AUDIO_LINE_SIZE) |
400 | bpl = AUDIO_LINE_SIZE; | 406 | bpl = AUDIO_LINE_SIZE; |
401 | } | 407 | |
402 | runtime->hw.period_bytes_min = bpl; | 408 | runtime->hw.period_bytes_min = bpl; |
403 | runtime->hw.period_bytes_max = bpl; | 409 | runtime->hw.period_bytes_max = bpl; |
404 | } | 410 | } |
405 | 411 | ||
406 | return 0; | 412 | return 0; |
407 | _error: | 413 | _error: |
408 | dprintk(1, "Error opening PCM!\n"); | 414 | dprintk(1, "Error opening PCM!\n"); |
409 | return err; | 415 | return err; |
410 | } | 416 | } |
@@ -423,7 +429,7 @@ static int snd_cx25821_close(struct snd_pcm_substream *substream) | |||
423 | static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | 429 | static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, |
424 | struct snd_pcm_hw_params *hw_params) | 430 | struct snd_pcm_hw_params *hw_params) |
425 | { | 431 | { |
426 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | 432 | struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); |
427 | struct videobuf_dmabuf *dma; | 433 | struct videobuf_dmabuf *dma; |
428 | 434 | ||
429 | struct cx25821_buffer *buf; | 435 | struct cx25821_buffer *buf; |
@@ -445,9 +451,8 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
445 | if (NULL == buf) | 451 | if (NULL == buf) |
446 | return -ENOMEM; | 452 | return -ENOMEM; |
447 | 453 | ||
448 | if (chip->period_size > AUDIO_LINE_SIZE) { | 454 | if (chip->period_size > AUDIO_LINE_SIZE) |
449 | chip->period_size = AUDIO_LINE_SIZE; | 455 | chip->period_size = AUDIO_LINE_SIZE; |
450 | } | ||
451 | 456 | ||
452 | buf->vb.memory = V4L2_MEMORY_MMAP; | 457 | buf->vb.memory = V4L2_MEMORY_MMAP; |
453 | buf->vb.field = V4L2_FIELD_NONE; | 458 | buf->vb.field = V4L2_FIELD_NONE; |
@@ -474,7 +479,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
474 | buf->vb.width, buf->vb.height, 1); | 479 | buf->vb.width, buf->vb.height, 1); |
475 | if (ret < 0) { | 480 | if (ret < 0) { |
476 | printk(KERN_INFO | 481 | printk(KERN_INFO |
477 | "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); | 482 | "DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); |
478 | goto error; | 483 | goto error; |
479 | } | 484 | } |
480 | 485 | ||
@@ -494,7 +499,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
494 | 499 | ||
495 | return 0; | 500 | return 0; |
496 | 501 | ||
497 | error: | 502 | error: |
498 | kfree(buf); | 503 | kfree(buf); |
499 | return ret; | 504 | return ret; |
500 | } | 505 | } |
@@ -504,7 +509,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
504 | */ | 509 | */ |
505 | static int snd_cx25821_hw_free(struct snd_pcm_substream *substream) | 510 | static int snd_cx25821_hw_free(struct snd_pcm_substream *substream) |
506 | { | 511 | { |
507 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | 512 | struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); |
508 | 513 | ||
509 | if (substream->runtime->dma_area) { | 514 | if (substream->runtime->dma_area) { |
510 | dsp_buffer_free(chip); | 515 | dsp_buffer_free(chip); |
@@ -528,7 +533,7 @@ static int snd_cx25821_prepare(struct snd_pcm_substream *substream) | |||
528 | static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, | 533 | static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, |
529 | int cmd) | 534 | int cmd) |
530 | { | 535 | { |
531 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | 536 | struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); |
532 | int err = 0; | 537 | int err = 0; |
533 | 538 | ||
534 | /* Local interrupts are already disabled by ALSA */ | 539 | /* Local interrupts are already disabled by ALSA */ |
@@ -557,7 +562,7 @@ static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, | |||
557 | static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream | 562 | static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream |
558 | *substream) | 563 | *substream) |
559 | { | 564 | { |
560 | snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); | 565 | struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); |
561 | struct snd_pcm_runtime *runtime = substream->runtime; | 566 | struct snd_pcm_runtime *runtime = substream->runtime; |
562 | u16 count; | 567 | u16 count; |
563 | 568 | ||
@@ -593,10 +598,11 @@ static struct snd_pcm_ops snd_cx25821_pcm_ops = { | |||
593 | }; | 598 | }; |
594 | 599 | ||
595 | /* | 600 | /* |
596 | * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up | 601 | * ALSA create a PCM device: Called when initializing the board. |
597 | * the callbacks | 602 | * Sets up the name and hooks up the callbacks |
598 | */ | 603 | */ |
599 | static int snd_cx25821_pcm(snd_cx25821_card_t * chip, int device, char *name) | 604 | static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device, |
605 | char *name) | ||
600 | { | 606 | { |
601 | struct snd_pcm *pcm; | 607 | struct snd_pcm *pcm; |
602 | int err; | 608 | int err; |
@@ -636,7 +642,7 @@ MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); | |||
636 | * from the file. | 642 | * from the file. |
637 | */ | 643 | */ |
638 | /* | 644 | /* |
639 | static int snd_cx25821_free(snd_cx25821_card_t *chip) | 645 | static int snd_cx25821_free(struct cx25821_audio_dev *chip) |
640 | { | 646 | { |
641 | if (chip->irq >= 0) | 647 | if (chip->irq >= 0) |
642 | free_irq(chip->irq, chip); | 648 | free_irq(chip->irq, chip); |
@@ -653,9 +659,9 @@ static int snd_cx25821_free(snd_cx25821_card_t *chip) | |||
653 | */ | 659 | */ |
654 | static void snd_cx25821_dev_free(struct snd_card *card) | 660 | static void snd_cx25821_dev_free(struct snd_card *card) |
655 | { | 661 | { |
656 | snd_cx25821_card_t *chip = card->private_data; | 662 | struct cx25821_audio_dev *chip = card->private_data; |
657 | 663 | ||
658 | //snd_cx25821_free(chip); | 664 | /* snd_cx25821_free(chip); */ |
659 | snd_card_free(chip->card); | 665 | snd_card_free(chip->card); |
660 | } | 666 | } |
661 | 667 | ||
@@ -665,23 +671,23 @@ static void snd_cx25821_dev_free(struct snd_card *card) | |||
665 | static int cx25821_audio_initdev(struct cx25821_dev *dev) | 671 | static int cx25821_audio_initdev(struct cx25821_dev *dev) |
666 | { | 672 | { |
667 | struct snd_card *card; | 673 | struct snd_card *card; |
668 | snd_cx25821_card_t *chip; | 674 | struct cx25821_audio_dev *chip; |
669 | int err; | 675 | int err; |
670 | 676 | ||
671 | if (devno >= SNDRV_CARDS) { | 677 | if (devno >= SNDRV_CARDS) { |
672 | printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", | 678 | printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", |
673 | __func__); | 679 | __func__); |
674 | return (-ENODEV); | 680 | return -ENODEV; |
675 | } | 681 | } |
676 | 682 | ||
677 | if (!enable[devno]) { | 683 | if (!enable[devno]) { |
678 | ++devno; | 684 | ++devno; |
679 | printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); | 685 | printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); |
680 | return (-ENOENT); | 686 | return -ENOENT; |
681 | } | 687 | } |
682 | 688 | ||
683 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, | 689 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, |
684 | sizeof(snd_cx25821_card_t), &card); | 690 | sizeof(struct cx25821_audio_dev), &card); |
685 | if (err < 0) { | 691 | if (err < 0) { |
686 | printk(KERN_INFO | 692 | printk(KERN_INFO |
687 | "DEBUG ERROR: cannot create snd_card_new in %s\n", | 693 | "DEBUG ERROR: cannot create snd_card_new in %s\n", |
@@ -693,7 +699,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
693 | 699 | ||
694 | /* Card "creation" */ | 700 | /* Card "creation" */ |
695 | card->private_free = snd_cx25821_dev_free; | 701 | card->private_free = snd_cx25821_dev_free; |
696 | chip = (snd_cx25821_card_t *) card->private_data; | 702 | chip = (struct cx25821_audio_dev *) card->private_data; |
697 | spin_lock_init(&chip->reg_lock); | 703 | spin_lock_init(&chip->reg_lock); |
698 | 704 | ||
699 | chip->dev = dev; | 705 | chip->dev = dev; |
@@ -712,7 +718,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
712 | goto error; | 718 | goto error; |
713 | } | 719 | } |
714 | 720 | ||
715 | if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) { | 721 | err = snd_cx25821_pcm(chip, 0, "cx25821 Digital"); |
722 | if (err < 0) { | ||
716 | printk(KERN_INFO | 723 | printk(KERN_INFO |
717 | "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", | 724 | "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", |
718 | __func__); | 725 | __func__); |
@@ -741,7 +748,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
741 | devno++; | 748 | devno++; |
742 | return 0; | 749 | return 0; |
743 | 750 | ||
744 | error: | 751 | error: |
745 | snd_card_free(card); | 752 | snd_card_free(card); |
746 | return err; | 753 | return err; |
747 | } | 754 | } |
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c index 11c56bdb0ceb..6a4e8720b478 100644 --- a/drivers/staging/cx25821/cx25821-audio-upstream.c +++ b/drivers/staging/cx25821/cx25821-audio-upstream.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/fcntl.h> | 33 | #include <linux/fcntl.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <asm/uaccess.h> | 36 | #include <linux/uaccess.h> |
37 | 37 | ||
38 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | 38 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); |
39 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | 39 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); |
@@ -62,9 +62,8 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, | |||
62 | cdt = ch->cdt; | 62 | cdt = ch->cdt; |
63 | lines = ch->fifo_size / bpl; | 63 | lines = ch->fifo_size / bpl; |
64 | 64 | ||
65 | if (lines > 3) { | 65 | if (lines > 3) |
66 | lines = 3; | 66 | lines = 3; |
67 | } | ||
68 | 67 | ||
69 | BUG_ON(lines < 2); | 68 | BUG_ON(lines < 2); |
70 | 69 | ||
@@ -84,7 +83,7 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, | |||
84 | cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); | 83 | cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); |
85 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | 84 | cx_write(ch->cmds_start + 16, ch->ctrl_start); |
86 | 85 | ||
87 | //IQ size | 86 | /* IQ size */ |
88 | cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); | 87 | cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); |
89 | 88 | ||
90 | for (i = 24; i < 80; i += 4) | 89 | for (i = 24; i < 80; i += 4) |
@@ -100,7 +99,7 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, | |||
100 | } | 99 | } |
101 | 100 | ||
102 | static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, | 101 | static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, |
103 | __le32 * rp, | 102 | __le32 *rp, |
104 | dma_addr_t databuf_phys_addr, | 103 | dma_addr_t databuf_phys_addr, |
105 | unsigned int bpl, | 104 | unsigned int bpl, |
106 | int fifo_enable) | 105 | int fifo_enable) |
@@ -116,8 +115,10 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, | |||
116 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | 115 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); |
117 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 116 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
118 | 117 | ||
119 | // Check if we need to enable the FIFO after the first 3 lines | 118 | /* Check if we need to enable the FIFO |
120 | // For the upstream audio channel, the risc engine will enable the FIFO. | 119 | * after the first 3 lines. |
120 | * For the upstream audio channel, | ||
121 | * the risc engine will enable the FIFO */ | ||
121 | if (fifo_enable && line == 2) { | 122 | if (fifo_enable && line == 2) { |
122 | *(rp++) = RISC_WRITECR; | 123 | *(rp++) = RISC_WRITECR; |
123 | *(rp++) = sram_ch->dma_ctl; | 124 | *(rp++) = sram_ch->dma_ctl; |
@@ -160,7 +161,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, | |||
160 | risc_flag = RISC_CNT_INC; | 161 | risc_flag = RISC_CNT_INC; |
161 | } | 162 | } |
162 | 163 | ||
163 | //Calculate physical jump address | 164 | /* Calculate physical jump address */ |
164 | if ((frame + 1) == NUM_AUDIO_FRAMES) { | 165 | if ((frame + 1) == NUM_AUDIO_FRAMES) { |
165 | risc_phys_jump_addr = | 166 | risc_phys_jump_addr = |
166 | dev->_risc_phys_start_addr + | 167 | dev->_risc_phys_start_addr + |
@@ -179,17 +180,17 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, | |||
179 | fifo_enable); | 180 | fifo_enable); |
180 | 181 | ||
181 | if (USE_RISC_NOOP_AUDIO) { | 182 | if (USE_RISC_NOOP_AUDIO) { |
182 | for (i = 0; i < NUM_NO_OPS; i++) { | 183 | for (i = 0; i < NUM_NO_OPS; i++) |
183 | *(rp++) = cpu_to_le32(RISC_NOOP); | 184 | *(rp++) = cpu_to_le32(RISC_NOOP); |
184 | } | ||
185 | } | 185 | } |
186 | 186 | ||
187 | // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ | 187 | /* Loop to (Nth)FrameRISC or to Start of Risc program & |
188 | * generate IRQ */ | ||
188 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | 189 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); |
189 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | 190 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); |
190 | *(rp++) = cpu_to_le32(0); | 191 | *(rp++) = cpu_to_le32(0); |
191 | 192 | ||
192 | //Recalculate virtual address based on frame index | 193 | /* Recalculate virtual address based on frame index */ |
193 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + | 194 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + |
194 | (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); | 195 | (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); |
195 | } | 196 | } |
@@ -220,19 +221,19 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | |||
220 | u32 tmp = 0; | 221 | u32 tmp = 0; |
221 | 222 | ||
222 | if (!dev->_audio_is_running) { | 223 | if (!dev->_audio_is_running) { |
223 | printk | 224 | printk(KERN_DEBUG |
224 | ("cx25821: No audio file is currently running so return!\n"); | 225 | "cx25821: No audio file is currently running so return!\n"); |
225 | return; | 226 | return; |
226 | } | 227 | } |
227 | //Disable RISC interrupts | 228 | /* Disable RISC interrupts */ |
228 | cx_write(sram_ch->int_msk, 0); | 229 | cx_write(sram_ch->int_msk, 0); |
229 | 230 | ||
230 | //Turn OFF risc and fifo enable in AUD_DMA_CNTRL | 231 | /* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */ |
231 | tmp = cx_read(sram_ch->dma_ctl); | 232 | tmp = cx_read(sram_ch->dma_ctl); |
232 | cx_write(sram_ch->dma_ctl, | 233 | cx_write(sram_ch->dma_ctl, |
233 | tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en)); | 234 | tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en)); |
234 | 235 | ||
235 | //Clear data buffer memory | 236 | /* Clear data buffer memory */ |
236 | if (dev->_audiodata_buf_virt_addr) | 237 | if (dev->_audiodata_buf_virt_addr) |
237 | memset(dev->_audiodata_buf_virt_addr, 0, | 238 | memset(dev->_audiodata_buf_virt_addr, 0, |
238 | dev->_audiodata_buf_size); | 239 | dev->_audiodata_buf_size); |
@@ -253,9 +254,8 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | |||
253 | 254 | ||
254 | void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) | 255 | void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) |
255 | { | 256 | { |
256 | if (dev->_audio_is_running) { | 257 | if (dev->_audio_is_running) |
257 | cx25821_stop_upstream_audio(dev); | 258 | cx25821_stop_upstream_audio(dev); |
258 | } | ||
259 | 259 | ||
260 | cx25821_free_memory_audio(dev); | 260 | cx25821_free_memory_audio(dev); |
261 | } | 261 | } |
@@ -282,7 +282,7 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
282 | 282 | ||
283 | if (IS_ERR(myfile)) { | 283 | if (IS_ERR(myfile)) { |
284 | const int open_errno = -PTR_ERR(myfile); | 284 | const int open_errno = -PTR_ERR(myfile); |
285 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | 285 | printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", |
286 | __func__, dev->_audiofilename, open_errno); | 286 | __func__, dev->_audiofilename, open_errno); |
287 | return PTR_ERR(myfile); | 287 | return PTR_ERR(myfile); |
288 | } else { | 288 | } else { |
@@ -294,7 +294,7 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
294 | } | 294 | } |
295 | 295 | ||
296 | if (!myfile->f_op->read) { | 296 | if (!myfile->f_op->read) { |
297 | printk("%s: File has no READ operations registered! \n", | 297 | printk("%s: File has no READ operations registered!\n", |
298 | __func__); | 298 | __func__); |
299 | filp_close(myfile, NULL); | 299 | filp_close(myfile, NULL); |
300 | return -EIO; | 300 | return -EIO; |
@@ -347,7 +347,7 @@ static void cx25821_audioups_handler(struct work_struct *work) | |||
347 | container_of(work, struct cx25821_dev, _audio_work_entry); | 347 | container_of(work, struct cx25821_dev, _audio_work_entry); |
348 | 348 | ||
349 | if (!dev) { | 349 | if (!dev) { |
350 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", | 350 | printk(KERN_ERR "ERROR %s(): since container_of(work_struct) FAILED!\n", |
351 | __func__); | 351 | __func__); |
352 | return; | 352 | return; |
353 | } | 353 | } |
@@ -373,19 +373,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
373 | 373 | ||
374 | if (IS_ERR(myfile)) { | 374 | if (IS_ERR(myfile)) { |
375 | const int open_errno = -PTR_ERR(myfile); | 375 | const int open_errno = -PTR_ERR(myfile); |
376 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | 376 | printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", |
377 | __func__, dev->_audiofilename, open_errno); | 377 | __func__, dev->_audiofilename, open_errno); |
378 | return PTR_ERR(myfile); | 378 | return PTR_ERR(myfile); |
379 | } else { | 379 | } else { |
380 | if (!(myfile->f_op)) { | 380 | if (!(myfile->f_op)) { |
381 | printk("%s: File has no file operations registered! \n", | 381 | printk("%s: File has no file operations registered!\n", |
382 | __func__); | 382 | __func__); |
383 | filp_close(myfile, NULL); | 383 | filp_close(myfile, NULL); |
384 | return -EIO; | 384 | return -EIO; |
385 | } | 385 | } |
386 | 386 | ||
387 | if (!myfile->f_op->read) { | 387 | if (!myfile->f_op->read) { |
388 | printk("%s: File has no READ operations registered! \n", | 388 | printk("%s: File has no READ operations registered!\n", |
389 | __func__); | 389 | __func__); |
390 | filp_close(myfile, NULL); | 390 | filp_close(myfile, NULL); |
391 | return -EIO; | 391 | return -EIO; |
@@ -421,13 +421,11 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
421 | } | 421 | } |
422 | } | 422 | } |
423 | 423 | ||
424 | if (i > 0) { | 424 | if (i > 0) |
425 | dev->_audioframe_count++; | 425 | dev->_audioframe_count++; |
426 | } | ||
427 | 426 | ||
428 | if (vfs_read_retval < line_size) { | 427 | if (vfs_read_retval < line_size) |
429 | break; | 428 | break; |
430 | } | ||
431 | } | 429 | } |
432 | 430 | ||
433 | dev->_audiofile_status = | 431 | dev->_audiofile_status = |
@@ -460,14 +458,14 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
460 | dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; | 458 | dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; |
461 | 459 | ||
462 | if (!dev->_risc_virt_addr) { | 460 | if (!dev->_risc_virt_addr) { |
463 | printk | 461 | printk(KERN_DEBUG |
464 | ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); | 462 | "cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); |
465 | return -ENOMEM; | 463 | return -ENOMEM; |
466 | } | 464 | } |
467 | //Clear out memory at address | 465 | /* Clear out memory at address */ |
468 | memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); | 466 | memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); |
469 | 467 | ||
470 | //For Audio Data buffer allocation | 468 | /* For Audio Data buffer allocation */ |
471 | dev->_audiodata_buf_virt_addr = | 469 | dev->_audiodata_buf_virt_addr = |
472 | pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, | 470 | pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, |
473 | &data_dma_addr); | 471 | &data_dma_addr); |
@@ -475,30 +473,30 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
475 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; | 473 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; |
476 | 474 | ||
477 | if (!dev->_audiodata_buf_virt_addr) { | 475 | if (!dev->_audiodata_buf_virt_addr) { |
478 | printk | 476 | printk(KERN_DEBUG |
479 | ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); | 477 | "cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning.\n"); |
480 | return -ENOMEM; | 478 | return -ENOMEM; |
481 | } | 479 | } |
482 | //Clear out memory at address | 480 | /* Clear out memory at address */ |
483 | memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size); | 481 | memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size); |
484 | 482 | ||
485 | ret = cx25821_openfile_audio(dev, sram_ch); | 483 | ret = cx25821_openfile_audio(dev, sram_ch); |
486 | if (ret < 0) | 484 | if (ret < 0) |
487 | return ret; | 485 | return ret; |
488 | 486 | ||
489 | //Creating RISC programs | 487 | /* Creating RISC programs */ |
490 | ret = | 488 | ret = |
491 | cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, | 489 | cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, |
492 | dev->_audio_lines_count); | 490 | dev->_audio_lines_count); |
493 | if (ret < 0) { | 491 | if (ret < 0) { |
494 | printk(KERN_DEBUG | 492 | printk(KERN_DEBUG |
495 | "cx25821 ERROR creating audio upstream RISC programs! \n"); | 493 | "cx25821 ERROR creating audio upstream RISC programs!\n"); |
496 | goto error; | 494 | goto error; |
497 | } | 495 | } |
498 | 496 | ||
499 | return 0; | 497 | return 0; |
500 | 498 | ||
501 | error: | 499 | error: |
502 | return ret; | 500 | return ret; |
503 | } | 501 | } |
504 | 502 | ||
@@ -512,22 +510,22 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
512 | __le32 *rp; | 510 | __le32 *rp; |
513 | 511 | ||
514 | if (status & FLD_AUD_SRC_RISCI1) { | 512 | if (status & FLD_AUD_SRC_RISCI1) { |
515 | //Get interrupt_index of the program that interrupted | 513 | /* Get interrupt_index of the program that interrupted */ |
516 | u32 prog_cnt = cx_read(channel->gpcnt); | 514 | u32 prog_cnt = cx_read(channel->gpcnt); |
517 | 515 | ||
518 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | 516 | /* Since we've identified our IRQ, clear our bits from the |
517 | * interrupt mask and interrupt status registers */ | ||
519 | cx_write(channel->int_msk, 0); | 518 | cx_write(channel->int_msk, 0); |
520 | cx_write(channel->int_stat, cx_read(channel->int_stat)); | 519 | cx_write(channel->int_stat, cx_read(channel->int_stat)); |
521 | 520 | ||
522 | spin_lock(&dev->slock); | 521 | spin_lock(&dev->slock); |
523 | 522 | ||
524 | while (prog_cnt != dev->_last_index_irq) { | 523 | while (prog_cnt != dev->_last_index_irq) { |
525 | //Update _last_index_irq | 524 | /* Update _last_index_irq */ |
526 | if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) { | 525 | if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) |
527 | dev->_last_index_irq++; | 526 | dev->_last_index_irq++; |
528 | } else { | 527 | else |
529 | dev->_last_index_irq = 0; | 528 | dev->_last_index_irq = 0; |
530 | } | ||
531 | 529 | ||
532 | dev->_audioframe_index = dev->_last_index_irq; | 530 | dev->_audioframe_index = dev->_last_index_irq; |
533 | 531 | ||
@@ -559,7 +557,7 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
559 | cpu_to_le32(RISC_NOOP); | 557 | cpu_to_le32(RISC_NOOP); |
560 | } | 558 | } |
561 | } | 559 | } |
562 | // Jump to 2nd Audio Frame | 560 | /* Jump to 2nd Audio Frame */ |
563 | *(rp++) = | 561 | *(rp++) = |
564 | cpu_to_le32(RISC_JUMP | RISC_IRQ1 | | 562 | cpu_to_le32(RISC_JUMP | RISC_IRQ1 | |
565 | RISC_CNT_RESET); | 563 | RISC_CNT_RESET); |
@@ -582,7 +580,8 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
582 | printk("%s: Audio Received OpCode Error Interrupt!\n", | 580 | printk("%s: Audio Received OpCode Error Interrupt!\n", |
583 | __func__); | 581 | __func__); |
584 | 582 | ||
585 | // Read and write back the interrupt status register to clear our bits | 583 | /* Read and write back the interrupt status register to clear |
584 | * our bits */ | ||
586 | cx_write(channel->int_stat, cx_read(channel->int_stat)); | 585 | cx_write(channel->int_stat, cx_read(channel->int_stat)); |
587 | } | 586 | } |
588 | 587 | ||
@@ -591,7 +590,7 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
591 | dev->_audioframe_count); | 590 | dev->_audioframe_count); |
592 | return -1; | 591 | return -1; |
593 | } | 592 | } |
594 | //ElSE, set the interrupt mask register, re-enable irq. | 593 | /* ElSE, set the interrupt mask register, re-enable irq. */ |
595 | int_msk_tmp = cx_read(channel->int_msk); | 594 | int_msk_tmp = cx_read(channel->int_msk); |
596 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | 595 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); |
597 | 596 | ||
@@ -613,7 +612,7 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | |||
613 | msk_stat = cx_read(sram_ch->int_mstat); | 612 | msk_stat = cx_read(sram_ch->int_mstat); |
614 | audio_status = cx_read(sram_ch->int_stat); | 613 | audio_status = cx_read(sram_ch->int_stat); |
615 | 614 | ||
616 | // Only deal with our interrupt | 615 | /* Only deal with our interrupt */ |
617 | if (audio_status) { | 616 | if (audio_status) { |
618 | handled = | 617 | handled = |
619 | cx25821_audio_upstream_irq(dev, | 618 | cx25821_audio_upstream_irq(dev, |
@@ -622,11 +621,10 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | |||
622 | audio_status); | 621 | audio_status); |
623 | } | 622 | } |
624 | 623 | ||
625 | if (handled < 0) { | 624 | if (handled < 0) |
626 | cx25821_stop_upstream_audio(dev); | 625 | cx25821_stop_upstream_audio(dev); |
627 | } else { | 626 | else |
628 | handled += handled; | 627 | handled += handled; |
629 | } | ||
630 | 628 | ||
631 | return IRQ_RETVAL(handled); | 629 | return IRQ_RETVAL(handled); |
632 | } | 630 | } |
@@ -638,13 +636,14 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, | |||
638 | u32 tmp; | 636 | u32 tmp; |
639 | 637 | ||
640 | do { | 638 | do { |
641 | //Wait 10 microsecond before checking to see if the FIFO is turned ON. | 639 | /* Wait 10 microsecond before checking to see if the FIFO is |
640 | * turned ON. */ | ||
642 | udelay(10); | 641 | udelay(10); |
643 | 642 | ||
644 | tmp = cx_read(sram_ch->dma_ctl); | 643 | tmp = cx_read(sram_ch->dma_ctl); |
645 | 644 | ||
646 | if (count++ > 1000) //10 millisecond timeout | 645 | /* 10 millisecond timeout */ |
647 | { | 646 | if (count++ > 1000) { |
648 | printk | 647 | printk |
649 | ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", | 648 | ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", |
650 | __func__); | 649 | __func__); |
@@ -661,31 +660,34 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | |||
661 | u32 tmp = 0; | 660 | u32 tmp = 0; |
662 | int err = 0; | 661 | int err = 0; |
663 | 662 | ||
664 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. | 663 | /* Set the physical start address of the RISC program in the initial |
664 | * program counter(IPC) member of the CMDS. */ | ||
665 | cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); | 665 | cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); |
666 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | 666 | /* Risc IPC High 64 bits 63-32 */ |
667 | cx_write(sram_ch->cmds_start + 4, 0); | ||
667 | 668 | ||
668 | /* reset counter */ | 669 | /* reset counter */ |
669 | cx_write(sram_ch->gpcnt_ctl, 3); | 670 | cx_write(sram_ch->gpcnt_ctl, 3); |
670 | 671 | ||
671 | //Set the line length (It looks like we do not need to set the line length) | 672 | /* Set the line length (It looks like we do not need to set the |
673 | * line length) */ | ||
672 | cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); | 674 | cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); |
673 | 675 | ||
674 | //Set the input mode to 16-bit | 676 | /* Set the input mode to 16-bit */ |
675 | tmp = cx_read(sram_ch->aud_cfg); | 677 | tmp = cx_read(sram_ch->aud_cfg); |
676 | tmp |= | 678 | tmp |= |
677 | FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | | 679 | FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | |
678 | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; | 680 | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; |
679 | cx_write(sram_ch->aud_cfg, tmp); | 681 | cx_write(sram_ch->aud_cfg, tmp); |
680 | 682 | ||
681 | // Read and write back the interrupt status register to clear it | 683 | /* Read and write back the interrupt status register to clear it */ |
682 | tmp = cx_read(sram_ch->int_stat); | 684 | tmp = cx_read(sram_ch->int_stat); |
683 | cx_write(sram_ch->int_stat, tmp); | 685 | cx_write(sram_ch->int_stat, tmp); |
684 | 686 | ||
685 | // Clear our bits from the interrupt status register. | 687 | /* Clear our bits from the interrupt status register. */ |
686 | cx_write(sram_ch->int_stat, _intr_msk); | 688 | cx_write(sram_ch->int_stat, _intr_msk); |
687 | 689 | ||
688 | //Set the interrupt mask register, enable irq. | 690 | /* Set the interrupt mask register, enable irq. */ |
689 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | 691 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); |
690 | tmp = cx_read(sram_ch->int_msk); | 692 | tmp = cx_read(sram_ch->int_msk); |
691 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 693 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
@@ -699,19 +701,19 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | |||
699 | goto fail_irq; | 701 | goto fail_irq; |
700 | } | 702 | } |
701 | 703 | ||
702 | // Start the DMA engine | 704 | /* Start the DMA engine */ |
703 | tmp = cx_read(sram_ch->dma_ctl); | 705 | tmp = cx_read(sram_ch->dma_ctl); |
704 | cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en); | 706 | cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en); |
705 | 707 | ||
706 | dev->_audio_is_running = 1; | 708 | dev->_audio_is_running = 1; |
707 | dev->_is_first_audio_frame = 1; | 709 | dev->_is_first_audio_frame = 1; |
708 | 710 | ||
709 | // The fifo_en bit turns on by the first Risc program | 711 | /* The fifo_en bit turns on by the first Risc program */ |
710 | cx25821_wait_fifo_enable(dev, sram_ch); | 712 | cx25821_wait_fifo_enable(dev, sram_ch); |
711 | 713 | ||
712 | return 0; | 714 | return 0; |
713 | 715 | ||
714 | fail_irq: | 716 | fail_irq: |
715 | cx25821_dev_unregister(dev); | 717 | cx25821_dev_unregister(dev); |
716 | return err; | 718 | return err; |
717 | } | 719 | } |
@@ -731,14 +733,14 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
731 | dev->_audio_upstream_channel_select = channel_select; | 733 | dev->_audio_upstream_channel_select = channel_select; |
732 | sram_ch = &dev->sram_channels[channel_select]; | 734 | sram_ch = &dev->sram_channels[channel_select]; |
733 | 735 | ||
734 | //Work queue | 736 | /* Work queue */ |
735 | INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); | 737 | INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); |
736 | dev->_irq_audio_queues = | 738 | dev->_irq_audio_queues = |
737 | create_singlethread_workqueue("cx25821_audioworkqueue"); | 739 | create_singlethread_workqueue("cx25821_audioworkqueue"); |
738 | 740 | ||
739 | if (!dev->_irq_audio_queues) { | 741 | if (!dev->_irq_audio_queues) { |
740 | printk | 742 | printk(KERN_DEBUG |
741 | ("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); | 743 | "cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); |
742 | return -ENOMEM; | 744 | return -ENOMEM; |
743 | } | 745 | } |
744 | 746 | ||
@@ -760,7 +762,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
760 | memcpy(dev->_audiofilename, dev->input_audiofilename, | 762 | memcpy(dev->_audiofilename, dev->input_audiofilename, |
761 | str_length + 1); | 763 | str_length + 1); |
762 | 764 | ||
763 | //Default if filename is empty string | 765 | /* Default if filename is empty string */ |
764 | if (strcmp(dev->input_audiofilename, "") == 0) { | 766 | if (strcmp(dev->input_audiofilename, "") == 0) { |
765 | dev->_audiofilename = "/root/audioGOOD.wav"; | 767 | dev->_audiofilename = "/root/audioGOOD.wav"; |
766 | } | 768 | } |
@@ -784,7 +786,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
784 | RISC_SYNC_INSTRUCTION_SIZE; | 786 | RISC_SYNC_INSTRUCTION_SIZE; |
785 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; | 787 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; |
786 | 788 | ||
787 | //Allocating buffers and prepare RISC program | 789 | /* Allocating buffers and prepare RISC program */ |
788 | retval = | 790 | retval = |
789 | cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); | 791 | cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); |
790 | if (retval < 0) { | 792 | if (retval < 0) { |
@@ -793,12 +795,12 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
793 | dev->name); | 795 | dev->name); |
794 | goto error; | 796 | goto error; |
795 | } | 797 | } |
796 | //Start RISC engine | 798 | /* Start RISC engine */ |
797 | cx25821_start_audio_dma_upstream(dev, sram_ch); | 799 | cx25821_start_audio_dma_upstream(dev, sram_ch); |
798 | 800 | ||
799 | return 0; | 801 | return 0; |
800 | 802 | ||
801 | error: | 803 | error: |
802 | cx25821_dev_unregister(dev); | 804 | cx25821_dev_unregister(dev); |
803 | 805 | ||
804 | return err; | 806 | return err; |
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index e76451c309f1..e49ead982f39 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c | |||
@@ -88,10 +88,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | static struct videobuf_queue_ops cx25821_video_qops = { | 90 | static struct videobuf_queue_ops cx25821_video_qops = { |
91 | .buf_setup = buffer_setup, | 91 | .buf_setup = cx25821_buffer_setup, |
92 | .buf_prepare = buffer_prepare, | 92 | .buf_prepare = cx25821_buffer_prepare, |
93 | .buf_queue = buffer_queue, | 93 | .buf_queue = buffer_queue, |
94 | .buf_release = buffer_release, | 94 | .buf_release = cx25821_buffer_release, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static int video_open(struct file *file) | 97 | static int video_open(struct file *file) |
@@ -145,7 +145,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
145 | 145 | ||
146 | switch (fh->type) { | 146 | switch (fh->type) { |
147 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 147 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
148 | if (res_locked(fh->dev, RESOURCE_VIDEO11)) | 148 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO11)) |
149 | return -EBUSY; | 149 | return -EBUSY; |
150 | 150 | ||
151 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 151 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -163,7 +163,7 @@ static unsigned int video_poll(struct file *file, | |||
163 | struct cx25821_fh *fh = file->private_data; | 163 | struct cx25821_fh *fh = file->private_data; |
164 | struct cx25821_buffer *buf; | 164 | struct cx25821_buffer *buf; |
165 | 165 | ||
166 | if (res_check(fh, RESOURCE_VIDEO11)) { | 166 | if (cx25821_res_check(fh, RESOURCE_VIDEO11)) { |
167 | /* streaming capture */ | 167 | /* streaming capture */ |
168 | if (list_empty(&fh->vidq.stream)) | 168 | if (list_empty(&fh->vidq.stream)) |
169 | return POLLERR; | 169 | return POLLERR; |
@@ -191,19 +191,19 @@ static int video_release(struct file *file) | |||
191 | //cx_write(channel11->dma_ctl, 0); | 191 | //cx_write(channel11->dma_ctl, 0); |
192 | 192 | ||
193 | /* stop video capture */ | 193 | /* stop video capture */ |
194 | if (res_check(fh, RESOURCE_VIDEO11)) { | 194 | if (cx25821_res_check(fh, RESOURCE_VIDEO11)) { |
195 | videobuf_queue_cancel(&fh->vidq); | 195 | videobuf_queue_cancel(&fh->vidq); |
196 | res_free(dev, fh, RESOURCE_VIDEO11); | 196 | cx25821_res_free(dev, fh, RESOURCE_VIDEO11); |
197 | } | 197 | } |
198 | 198 | ||
199 | if (fh->vidq.read_buf) { | 199 | if (fh->vidq.read_buf) { |
200 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 200 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
201 | kfree(fh->vidq.read_buf); | 201 | kfree(fh->vidq.read_buf); |
202 | } | 202 | } |
203 | 203 | ||
204 | videobuf_mmap_free(&fh->vidq); | 204 | videobuf_mmap_free(&fh->vidq); |
205 | 205 | ||
206 | v4l2_prio_close(&dev->prio, &fh->prio); | 206 | v4l2_prio_close(&dev->prio, fh->prio); |
207 | 207 | ||
208 | file->private_data = NULL; | 208 | file->private_data = NULL; |
209 | kfree(fh); | 209 | kfree(fh); |
@@ -224,7 +224,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
224 | return -EINVAL; | 224 | return -EINVAL; |
225 | } | 225 | } |
226 | 226 | ||
227 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) { | 227 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO11)))) { |
228 | return -EBUSY; | 228 | return -EBUSY; |
229 | } | 229 | } |
230 | 230 | ||
@@ -242,11 +242,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
242 | if (i != fh->type) | 242 | if (i != fh->type) |
243 | return -EINVAL; | 243 | return -EINVAL; |
244 | 244 | ||
245 | res = get_resource(fh, RESOURCE_VIDEO11); | 245 | res = cx25821_get_resource(fh, RESOURCE_VIDEO11); |
246 | err = videobuf_streamoff(get_queue(fh)); | 246 | err = videobuf_streamoff(get_queue(fh)); |
247 | if (err < 0) | 247 | if (err < 0) |
248 | return err; | 248 | return err; |
249 | res_free(dev, fh, res); | 249 | cx25821_res_free(dev, fh, res); |
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | 252 | ||
@@ -258,13 +258,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
258 | int err; | 258 | int err; |
259 | 259 | ||
260 | if (fh) { | 260 | if (fh) { |
261 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 261 | err = v4l2_prio_check(&dev->prio, fh->prio); |
262 | if (0 != err) | 262 | if (0 != err) |
263 | return err; | 263 | return err; |
264 | } | 264 | } |
265 | 265 | ||
266 | dprintk(2, "%s()\n", __func__); | 266 | dprintk(2, "%s()\n", __func__); |
267 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 267 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
268 | 268 | ||
269 | if (0 != err) | 269 | if (0 != err) |
270 | return err; | 270 | return err; |
@@ -350,7 +350,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
350 | 350 | ||
351 | if (fh) { | 351 | if (fh) { |
352 | dev = fh->dev; | 352 | dev = fh->dev; |
353 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 353 | err = v4l2_prio_check(&dev->prio, fh->prio); |
354 | if (0 != err) | 354 | if (0 != err) |
355 | return err; | 355 | return err; |
356 | } | 356 | } |
@@ -364,50 +364,50 @@ static const struct v4l2_file_operations video_fops = { | |||
364 | .release = video_release, | 364 | .release = video_release, |
365 | .read = video_read, | 365 | .read = video_read, |
366 | .poll = video_poll, | 366 | .poll = video_poll, |
367 | .mmap = video_mmap, | 367 | .mmap = cx25821_video_mmap, |
368 | .ioctl = video_ioctl_upstream11, | 368 | .ioctl = video_ioctl_upstream11, |
369 | }; | 369 | }; |
370 | 370 | ||
371 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 371 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
372 | .vidioc_querycap = vidioc_querycap, | 372 | .vidioc_querycap = cx25821_vidioc_querycap, |
373 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 373 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
374 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 374 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
375 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 375 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
376 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 376 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
377 | .vidioc_reqbufs = vidioc_reqbufs, | 377 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
378 | .vidioc_querybuf = vidioc_querybuf, | 378 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
379 | .vidioc_qbuf = vidioc_qbuf, | 379 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
380 | .vidioc_dqbuf = vidioc_dqbuf, | 380 | .vidioc_dqbuf = vidioc_dqbuf, |
381 | #ifdef TUNER_FLAG | 381 | #ifdef TUNER_FLAG |
382 | .vidioc_s_std = vidioc_s_std, | 382 | .vidioc_s_std = cx25821_vidioc_s_std, |
383 | .vidioc_querystd = vidioc_querystd, | 383 | .vidioc_querystd = cx25821_vidioc_querystd, |
384 | #endif | 384 | #endif |
385 | .vidioc_cropcap = vidioc_cropcap, | 385 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
386 | .vidioc_s_crop = vidioc_s_crop, | 386 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
387 | .vidioc_g_crop = vidioc_g_crop, | 387 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
388 | .vidioc_enum_input = vidioc_enum_input, | 388 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
389 | .vidioc_g_input = vidioc_g_input, | 389 | .vidioc_g_input = cx25821_vidioc_g_input, |
390 | .vidioc_s_input = vidioc_s_input, | 390 | .vidioc_s_input = cx25821_vidioc_s_input, |
391 | .vidioc_g_ctrl = vidioc_g_ctrl, | 391 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
392 | .vidioc_s_ctrl = vidioc_s_ctrl, | 392 | .vidioc_s_ctrl = vidioc_s_ctrl, |
393 | .vidioc_queryctrl = vidioc_queryctrl, | 393 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
394 | .vidioc_streamon = vidioc_streamon, | 394 | .vidioc_streamon = vidioc_streamon, |
395 | .vidioc_streamoff = vidioc_streamoff, | 395 | .vidioc_streamoff = vidioc_streamoff, |
396 | .vidioc_log_status = vidioc_log_status, | 396 | .vidioc_log_status = vidioc_log_status, |
397 | .vidioc_g_priority = vidioc_g_priority, | 397 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
398 | .vidioc_s_priority = vidioc_s_priority, | 398 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
399 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 399 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
400 | .vidiocgmbuf = vidiocgmbuf, | 400 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
401 | #endif | 401 | #endif |
402 | #ifdef TUNER_FLAG | 402 | #ifdef TUNER_FLAG |
403 | .vidioc_g_tuner = vidioc_g_tuner, | 403 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
404 | .vidioc_s_tuner = vidioc_s_tuner, | 404 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
405 | .vidioc_g_frequency = vidioc_g_frequency, | 405 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
406 | .vidioc_s_frequency = vidioc_s_frequency, | 406 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
407 | #endif | 407 | #endif |
408 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 408 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
409 | .vidioc_g_register = vidioc_g_register, | 409 | .vidioc_g_register = cx25821_vidioc_g_register, |
410 | .vidioc_s_register = vidioc_s_register, | 410 | .vidioc_s_register = cx25821_vidioc_s_register, |
411 | #endif | 411 | #endif |
412 | }; | 412 | }; |
413 | 413 | ||
diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c index 4d0b9eac3e49..da0f56d50e27 100644 --- a/drivers/staging/cx25821/cx25821-cards.c +++ b/drivers/staging/cx25821/cx25821-cards.c | |||
@@ -30,12 +30,12 @@ | |||
30 | #include "cx25821.h" | 30 | #include "cx25821.h" |
31 | #include "tuner-xc2028.h" | 31 | #include "tuner-xc2028.h" |
32 | 32 | ||
33 | // board config info | 33 | /* board config info */ |
34 | 34 | ||
35 | struct cx25821_board cx25821_boards[] = { | 35 | struct cx25821_board cx25821_boards[] = { |
36 | [UNKNOWN_BOARD] = { | 36 | [UNKNOWN_BOARD] = { |
37 | .name = "UNKNOWN/GENERIC", | 37 | .name = "UNKNOWN/GENERIC", |
38 | // Ensure safe default for unknown boards | 38 | /* Ensure safe default for unknown boards */ |
39 | .clk_freq = 0, | 39 | .clk_freq = 0, |
40 | }, | 40 | }, |
41 | 41 | ||
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c index 9e9b8c3c9311..d90abb383fc8 100644 --- a/drivers/staging/cx25821/cx25821-core.c +++ b/drivers/staging/cx25821/cx25821-core.c | |||
@@ -32,6 +32,7 @@ MODULE_AUTHOR("Shu Lin - Hiep Huynh"); | |||
32 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
33 | 33 | ||
34 | struct list_head cx25821_devlist; | 34 | struct list_head cx25821_devlist; |
35 | EXPORT_SYMBOL(cx25821_devlist); | ||
35 | 36 | ||
36 | static unsigned int debug; | 37 | static unsigned int debug; |
37 | module_param(debug, int, 0644); | 38 | module_param(debug, int, 0644); |
@@ -313,6 +314,7 @@ struct sram_channel cx25821_sram_channels[] = { | |||
313 | .irq_bit = 11, | 314 | .irq_bit = 11, |
314 | }, | 315 | }, |
315 | }; | 316 | }; |
317 | EXPORT_SYMBOL(cx25821_sram_channels); | ||
316 | 318 | ||
317 | struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; | 319 | struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; |
318 | struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; | 320 | struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; |
@@ -388,70 +390,74 @@ static void cx25821_registers_init(struct cx25821_dev *dev) | |||
388 | { | 390 | { |
389 | u32 tmp; | 391 | u32 tmp; |
390 | 392 | ||
391 | // enable RUN_RISC in Pecos | 393 | /* enable RUN_RISC in Pecos */ |
392 | cx_write(DEV_CNTRL2, 0x20); | 394 | cx_write(DEV_CNTRL2, 0x20); |
393 | 395 | ||
394 | // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts | 396 | /* Set the master PCI interrupt masks to enable video, audio, MBIF, |
395 | // I2C interrupt masking is handled by the I2C objects themselves. | 397 | * and GPIO interrupts |
398 | * I2C interrupt masking is handled by the I2C objects themselves. */ | ||
396 | cx_write(PCI_INT_MSK, 0x2001FFFF); | 399 | cx_write(PCI_INT_MSK, 0x2001FFFF); |
397 | 400 | ||
398 | tmp = cx_read(RDR_TLCTL0); | 401 | tmp = cx_read(RDR_TLCTL0); |
399 | tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit | 402 | tmp &= ~FLD_CFG_RCB_CK_EN; /* Clear the RCB_CK_EN bit */ |
400 | cx_write(RDR_TLCTL0, tmp); | 403 | cx_write(RDR_TLCTL0, tmp); |
401 | 404 | ||
402 | // PLL-A setting for the Audio Master Clock | 405 | /* PLL-A setting for the Audio Master Clock */ |
403 | cx_write(PLL_A_INT_FRAC, 0x9807A58B); | 406 | cx_write(PLL_A_INT_FRAC, 0x9807A58B); |
404 | 407 | ||
405 | // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 | 408 | /* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */ |
406 | cx_write(PLL_A_POST_STAT_BIST, 0x8000019C); | 409 | cx_write(PLL_A_POST_STAT_BIST, 0x8000019C); |
407 | 410 | ||
408 | // clear reset bit [31] | 411 | /* clear reset bit [31] */ |
409 | tmp = cx_read(PLL_A_INT_FRAC); | 412 | tmp = cx_read(PLL_A_INT_FRAC); |
410 | cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); | 413 | cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); |
411 | 414 | ||
412 | // PLL-B setting for Mobilygen Host Bus Interface | 415 | /* PLL-B setting for Mobilygen Host Bus Interface */ |
413 | cx_write(PLL_B_INT_FRAC, 0x9883A86F); | 416 | cx_write(PLL_B_INT_FRAC, 0x9883A86F); |
414 | 417 | ||
415 | // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 | 418 | /* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */ |
416 | cx_write(PLL_B_POST_STAT_BIST, 0x8000018D); | 419 | cx_write(PLL_B_POST_STAT_BIST, 0x8000018D); |
417 | 420 | ||
418 | // clear reset bit [31] | 421 | /* clear reset bit [31] */ |
419 | tmp = cx_read(PLL_B_INT_FRAC); | 422 | tmp = cx_read(PLL_B_INT_FRAC); |
420 | cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); | 423 | cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); |
421 | 424 | ||
422 | // PLL-C setting for video upstream channel | 425 | /* PLL-C setting for video upstream channel */ |
423 | cx_write(PLL_C_INT_FRAC, 0x96A0EA3F); | 426 | cx_write(PLL_C_INT_FRAC, 0x96A0EA3F); |
424 | 427 | ||
425 | // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 | 428 | /* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */ |
426 | cx_write(PLL_C_POST_STAT_BIST, 0x80000103); | 429 | cx_write(PLL_C_POST_STAT_BIST, 0x80000103); |
427 | 430 | ||
428 | // clear reset bit [31] | 431 | /* clear reset bit [31] */ |
429 | tmp = cx_read(PLL_C_INT_FRAC); | 432 | tmp = cx_read(PLL_C_INT_FRAC); |
430 | cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); | 433 | cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); |
431 | 434 | ||
432 | // PLL-D setting for audio upstream channel | 435 | /* PLL-D setting for audio upstream channel */ |
433 | cx_write(PLL_D_INT_FRAC, 0x98757F5B); | 436 | cx_write(PLL_D_INT_FRAC, 0x98757F5B); |
434 | 437 | ||
435 | // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 | 438 | /* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */ |
436 | cx_write(PLL_D_POST_STAT_BIST, 0x80000113); | 439 | cx_write(PLL_D_POST_STAT_BIST, 0x80000113); |
437 | 440 | ||
438 | // clear reset bit [31] | 441 | /* clear reset bit [31] */ |
439 | tmp = cx_read(PLL_D_INT_FRAC); | 442 | tmp = cx_read(PLL_D_INT_FRAC); |
440 | cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); | 443 | cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); |
441 | 444 | ||
442 | // This selects the PLL C clock source for the video upstream channel I and J | 445 | /* This selects the PLL C clock source for the video upstream channel |
446 | * I and J */ | ||
443 | tmp = cx_read(VID_CH_CLK_SEL); | 447 | tmp = cx_read(VID_CH_CLK_SEL); |
444 | cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); | 448 | cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); |
445 | 449 | ||
446 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | 450 | /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for |
447 | //select 656/VIP DST for downstream Channel A - C | 451 | * channel A-C |
452 | * select 656/VIP DST for downstream Channel A - C */ | ||
448 | tmp = cx_read(VID_CH_MODE_SEL); | 453 | tmp = cx_read(VID_CH_MODE_SEL); |
449 | //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); | 454 | /* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */ |
450 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | 455 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); |
451 | 456 | ||
452 | // enables 656 port I and J as output | 457 | /* enables 656 port I and J as output */ |
453 | tmp = cx_read(CLK_RST); | 458 | tmp = cx_read(CLK_RST); |
454 | tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead | 459 | /* use external ALT_PLL_REF pin as its reference clock instead */ |
460 | tmp |= FLD_USE_ALT_PLL_REF; | ||
455 | cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE)); | 461 | cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE)); |
456 | 462 | ||
457 | mdelay(100); | 463 | mdelay(100); |
@@ -476,9 +482,8 @@ int cx25821_sram_channel_setup(struct cx25821_dev *dev, | |||
476 | cdt = ch->cdt; | 482 | cdt = ch->cdt; |
477 | lines = ch->fifo_size / bpl; | 483 | lines = ch->fifo_size / bpl; |
478 | 484 | ||
479 | if (lines > 4) { | 485 | if (lines > 4) |
480 | lines = 4; | 486 | lines = 4; |
481 | } | ||
482 | 487 | ||
483 | BUG_ON(lines < 2); | 488 | BUG_ON(lines < 2); |
484 | 489 | ||
@@ -494,16 +499,15 @@ int cx25821_sram_channel_setup(struct cx25821_dev *dev, | |||
494 | cx_write(cdt + 16 * i + 12, 0); | 499 | cx_write(cdt + 16 * i + 12, 0); |
495 | } | 500 | } |
496 | 501 | ||
497 | //init the first cdt buffer | 502 | /* init the first cdt buffer */ |
498 | for (i = 0; i < 128; i++) | 503 | for (i = 0; i < 128; i++) |
499 | cx_write(ch->fifo_start + 4 * i, i); | 504 | cx_write(ch->fifo_start + 4 * i, i); |
500 | 505 | ||
501 | /* write CMDS */ | 506 | /* write CMDS */ |
502 | if (ch->jumponly) { | 507 | if (ch->jumponly) |
503 | cx_write(ch->cmds_start + 0, 8); | 508 | cx_write(ch->cmds_start + 0, 8); |
504 | } else { | 509 | else |
505 | cx_write(ch->cmds_start + 0, risc); | 510 | cx_write(ch->cmds_start + 0, risc); |
506 | } | ||
507 | 511 | ||
508 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | 512 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ |
509 | cx_write(ch->cmds_start + 8, cdt); | 513 | cx_write(ch->cmds_start + 8, cdt); |
@@ -526,6 +530,7 @@ int cx25821_sram_channel_setup(struct cx25821_dev *dev, | |||
526 | 530 | ||
527 | return 0; | 531 | return 0; |
528 | } | 532 | } |
533 | EXPORT_SYMBOL(cx25821_sram_channel_setup); | ||
529 | 534 | ||
530 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | 535 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, |
531 | struct sram_channel *ch, | 536 | struct sram_channel *ch, |
@@ -546,9 +551,8 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | |||
546 | cdt = ch->cdt; | 551 | cdt = ch->cdt; |
547 | lines = ch->fifo_size / bpl; | 552 | lines = ch->fifo_size / bpl; |
548 | 553 | ||
549 | if (lines > 3) { | 554 | if (lines > 3) |
550 | lines = 3; //for AUDIO | 555 | lines = 3; /* for AUDIO */ |
551 | } | ||
552 | 556 | ||
553 | BUG_ON(lines < 2); | 557 | BUG_ON(lines < 2); |
554 | 558 | ||
@@ -565,25 +569,23 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | |||
565 | } | 569 | } |
566 | 570 | ||
567 | /* write CMDS */ | 571 | /* write CMDS */ |
568 | if (ch->jumponly) { | 572 | if (ch->jumponly) |
569 | cx_write(ch->cmds_start + 0, 8); | 573 | cx_write(ch->cmds_start + 0, 8); |
570 | } else { | 574 | else |
571 | cx_write(ch->cmds_start + 0, risc); | 575 | cx_write(ch->cmds_start + 0, risc); |
572 | } | ||
573 | 576 | ||
574 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ | 577 | cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ |
575 | cx_write(ch->cmds_start + 8, cdt); | 578 | cx_write(ch->cmds_start + 8, cdt); |
576 | cx_write(ch->cmds_start + 12, (lines * 16) >> 3); | 579 | cx_write(ch->cmds_start + 12, (lines * 16) >> 3); |
577 | cx_write(ch->cmds_start + 16, ch->ctrl_start); | 580 | cx_write(ch->cmds_start + 16, ch->ctrl_start); |
578 | 581 | ||
579 | //IQ size | 582 | /* IQ size */ |
580 | if (ch->jumponly) { | 583 | if (ch->jumponly) |
581 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); | 584 | cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); |
582 | } else { | 585 | else |
583 | cx_write(ch->cmds_start + 20, 64 >> 2); | 586 | cx_write(ch->cmds_start + 20, 64 >> 2); |
584 | } | ||
585 | 587 | ||
586 | //zero out | 588 | /* zero out */ |
587 | for (i = 24; i < 80; i += 4) | 589 | for (i = 24; i < 80; i += 4) |
588 | cx_write(ch->cmds_start + i, 0); | 590 | cx_write(ch->cmds_start + i, 0); |
589 | 591 | ||
@@ -595,6 +597,7 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | |||
595 | 597 | ||
596 | return 0; | 598 | return 0; |
597 | } | 599 | } |
600 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); | ||
598 | 601 | ||
599 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | 602 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) |
600 | { | 603 | { |
@@ -658,6 +661,7 @@ void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | |||
658 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", | 661 | printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", |
659 | cx_read(ch->cnt2_reg)); | 662 | cx_read(ch->cnt2_reg)); |
660 | } | 663 | } |
664 | EXPORT_SYMBOL(cx25821_sram_channel_dump); | ||
661 | 665 | ||
662 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | 666 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, |
663 | struct sram_channel *ch) | 667 | struct sram_channel *ch) |
@@ -731,7 +735,7 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | |||
731 | printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); | 735 | printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); |
732 | } | 736 | } |
733 | 737 | ||
734 | //read data from the first cdt buffer | 738 | /* read data from the first cdt buffer */ |
735 | risc = cx_read(AUD_A_CDT); | 739 | risc = cx_read(AUD_A_CDT); |
736 | printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); | 740 | printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); |
737 | for (i = 0; i < 8; i++) { | 741 | for (i = 0; i < 8; i++) { |
@@ -741,31 +745,32 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | |||
741 | printk(KERN_WARNING "\n\n"); | 745 | printk(KERN_WARNING "\n\n"); |
742 | 746 | ||
743 | value = cx_read(CLK_RST); | 747 | value = cx_read(CLK_RST); |
744 | CX25821_INFO(" CLK_RST = 0x%x \n\n", value); | 748 | CX25821_INFO(" CLK_RST = 0x%x\n\n", value); |
745 | 749 | ||
746 | value = cx_read(PLL_A_POST_STAT_BIST); | 750 | value = cx_read(PLL_A_POST_STAT_BIST); |
747 | CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); | 751 | CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value); |
748 | value = cx_read(PLL_A_INT_FRAC); | 752 | value = cx_read(PLL_A_INT_FRAC); |
749 | CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); | 753 | CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value); |
750 | 754 | ||
751 | value = cx_read(PLL_B_POST_STAT_BIST); | 755 | value = cx_read(PLL_B_POST_STAT_BIST); |
752 | CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); | 756 | CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value); |
753 | value = cx_read(PLL_B_INT_FRAC); | 757 | value = cx_read(PLL_B_INT_FRAC); |
754 | CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); | 758 | CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value); |
755 | 759 | ||
756 | value = cx_read(PLL_C_POST_STAT_BIST); | 760 | value = cx_read(PLL_C_POST_STAT_BIST); |
757 | CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); | 761 | CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value); |
758 | value = cx_read(PLL_C_INT_FRAC); | 762 | value = cx_read(PLL_C_INT_FRAC); |
759 | CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); | 763 | CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value); |
760 | 764 | ||
761 | value = cx_read(PLL_D_POST_STAT_BIST); | 765 | value = cx_read(PLL_D_POST_STAT_BIST); |
762 | CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); | 766 | CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value); |
763 | value = cx_read(PLL_D_INT_FRAC); | 767 | value = cx_read(PLL_D_INT_FRAC); |
764 | CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); | 768 | CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value); |
765 | 769 | ||
766 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | 770 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); |
767 | CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); | 771 | CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value); |
768 | } | 772 | } |
773 | EXPORT_SYMBOL(cx25821_sram_channel_dump_audio); | ||
769 | 774 | ||
770 | static void cx25821_shutdown(struct cx25821_dev *dev) | 775 | static void cx25821_shutdown(struct cx25821_dev *dev) |
771 | { | 776 | { |
@@ -835,8 +840,8 @@ static void cx25821_initialize(struct cx25821_dev *dev) | |||
835 | cx_write(AUD_E_INT_STAT, 0xffffffff); | 840 | cx_write(AUD_E_INT_STAT, 0xffffffff); |
836 | 841 | ||
837 | cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); | 842 | cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); |
838 | cx_write(PAD_CTRL, 0x12); //for I2C | 843 | cx_write(PAD_CTRL, 0x12); /* for I2C */ |
839 | cx25821_registers_init(dev); //init Pecos registers | 844 | cx25821_registers_init(dev); /* init Pecos registers */ |
840 | mdelay(100); | 845 | mdelay(100); |
841 | 846 | ||
842 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | 847 | for (i = 0; i < VID_CHANNEL_NUM; i++) { |
@@ -847,7 +852,7 @@ static void cx25821_initialize(struct cx25821_dev *dev) | |||
847 | dev->use_cif_resolution[i] = FALSE; | 852 | dev->use_cif_resolution[i] = FALSE; |
848 | } | 853 | } |
849 | 854 | ||
850 | //Probably only affect Downstream | 855 | /* Probably only affect Downstream */ |
851 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; | 856 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; |
852 | i++) { | 857 | i++) { |
853 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); | 858 | cx25821_set_vip_mode(dev, &dev->sram_channels[i]); |
@@ -859,7 +864,7 @@ static void cx25821_initialize(struct cx25821_dev *dev) | |||
859 | cx25821_gpio_init(dev); | 864 | cx25821_gpio_init(dev); |
860 | } | 865 | } |
861 | 866 | ||
862 | static int get_resources(struct cx25821_dev *dev) | 867 | static int cx25821_get_resources(struct cx25821_dev *dev) |
863 | { | 868 | { |
864 | if (request_mem_region | 869 | if (request_mem_region |
865 | (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), | 870 | (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), |
@@ -944,12 +949,11 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
944 | dev->clk_freq = 28000000; | 949 | dev->clk_freq = 28000000; |
945 | dev->sram_channels = cx25821_sram_channels; | 950 | dev->sram_channels = cx25821_sram_channels; |
946 | 951 | ||
947 | if (dev->nr > 1) { | 952 | if (dev->nr > 1) |
948 | CX25821_INFO("dev->nr > 1!"); | 953 | CX25821_INFO("dev->nr > 1!"); |
949 | } | ||
950 | 954 | ||
951 | /* board config */ | 955 | /* board config */ |
952 | dev->board = 1; //card[dev->nr]; | 956 | dev->board = 1; /* card[dev->nr]; */ |
953 | dev->_max_num_decoders = MAX_DECODERS; | 957 | dev->_max_num_decoders = MAX_DECODERS; |
954 | 958 | ||
955 | dev->pci_bus = dev->pci->bus->number; | 959 | dev->pci_bus = dev->pci->bus->number; |
@@ -967,7 +971,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
967 | dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ | 971 | dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ |
968 | 972 | ||
969 | 973 | ||
970 | if (get_resources(dev) < 0) { | 974 | if (cx25821_get_resources(dev) < 0) { |
971 | printk(KERN_ERR "%s No more PCIe resources for " | 975 | printk(KERN_ERR "%s No more PCIe resources for " |
972 | "subsystem: %04x:%04x\n", | 976 | "subsystem: %04x:%04x\n", |
973 | dev->name, dev->pci->subsystem_vendor, | 977 | dev->name, dev->pci->subsystem_vendor, |
@@ -1007,8 +1011,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
1007 | cx25821_initialize(dev); | 1011 | cx25821_initialize(dev); |
1008 | 1012 | ||
1009 | cx25821_i2c_register(&dev->i2c_bus[0]); | 1013 | cx25821_i2c_register(&dev->i2c_bus[0]); |
1010 | // cx25821_i2c_register(&dev->i2c_bus[1]); | 1014 | /* cx25821_i2c_register(&dev->i2c_bus[1]); |
1011 | // cx25821_i2c_register(&dev->i2c_bus[2]); | 1015 | * cx25821_i2c_register(&dev->i2c_bus[2]); */ |
1012 | 1016 | ||
1013 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", | 1017 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", |
1014 | dev->i2c_bus[0].i2c_rc); | 1018 | dev->i2c_bus[0].i2c_rc); |
@@ -1026,7 +1030,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
1026 | 1030 | ||
1027 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; | 1031 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; |
1028 | i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { | 1032 | i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { |
1029 | //Since we don't have template8 for Audio Downstream | 1033 | /* Since we don't have template8 for Audio Downstream */ |
1030 | if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) { | 1034 | if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) { |
1031 | printk(KERN_ERR | 1035 | printk(KERN_ERR |
1032 | "%s() Failed to register analog video adapters for Upstream channel %d.\n", | 1036 | "%s() Failed to register analog video adapters for Upstream channel %d.\n", |
@@ -1034,7 +1038,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
1034 | } | 1038 | } |
1035 | } | 1039 | } |
1036 | 1040 | ||
1037 | // register IOCTL device | 1041 | /* register IOCTL device */ |
1038 | dev->ioctl_dev = | 1042 | dev->ioctl_dev = |
1039 | cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], | 1043 | cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], |
1040 | "video"); | 1044 | "video"); |
@@ -1112,6 +1116,7 @@ void cx25821_dev_unregister(struct cx25821_dev *dev) | |||
1112 | cx25821_i2c_unregister(&dev->i2c_bus[0]); | 1116 | cx25821_i2c_unregister(&dev->i2c_bus[0]); |
1113 | cx25821_iounmap(dev); | 1117 | cx25821_iounmap(dev); |
1114 | } | 1118 | } |
1119 | EXPORT_SYMBOL(cx25821_dev_unregister); | ||
1115 | 1120 | ||
1116 | static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, | 1121 | static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, |
1117 | unsigned int offset, u32 sync_line, | 1122 | unsigned int offset, u32 sync_line, |
@@ -1122,9 +1127,8 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, | |||
1122 | unsigned int line, todo; | 1127 | unsigned int line, todo; |
1123 | 1128 | ||
1124 | /* sync instruction */ | 1129 | /* sync instruction */ |
1125 | if (sync_line != NO_SYNC_LINE) { | 1130 | if (sync_line != NO_SYNC_LINE) |
1126 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | 1131 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); |
1127 | } | ||
1128 | 1132 | ||
1129 | /* scan lines */ | 1133 | /* scan lines */ |
1130 | sg = sglist; | 1134 | sg = sglist; |
@@ -1299,7 +1303,8 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, | |||
1299 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; | 1303 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; |
1300 | instructions += 1; | 1304 | instructions += 1; |
1301 | 1305 | ||
1302 | if ((rc = btcx_riscmem_alloc(pci, risc, instructions * 12)) < 0) | 1306 | rc = btcx_riscmem_alloc(pci, risc, instructions * 12); |
1307 | if (rc < 0) | ||
1303 | return rc; | 1308 | return rc; |
1304 | 1309 | ||
1305 | /* write risc instructions */ | 1310 | /* write risc instructions */ |
@@ -1312,6 +1317,7 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, | |||
1312 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); | 1317 | BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); |
1313 | return 0; | 1318 | return 0; |
1314 | } | 1319 | } |
1320 | EXPORT_SYMBOL(cx25821_risc_databuffer_audio); | ||
1315 | 1321 | ||
1316 | int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | 1322 | int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, |
1317 | u32 reg, u32 mask, u32 value) | 1323 | u32 reg, u32 mask, u32 value) |
@@ -1375,7 +1381,7 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) | |||
1375 | } | 1381 | } |
1376 | } | 1382 | } |
1377 | 1383 | ||
1378 | out: | 1384 | out: |
1379 | return IRQ_RETVAL(handled); | 1385 | return IRQ_RETVAL(handled); |
1380 | } | 1386 | } |
1381 | 1387 | ||
@@ -1399,12 +1405,14 @@ void cx25821_print_irqbits(char *name, char *tag, char **strings, | |||
1399 | } | 1405 | } |
1400 | printk("\n"); | 1406 | printk("\n"); |
1401 | } | 1407 | } |
1408 | EXPORT_SYMBOL(cx25821_print_irqbits); | ||
1402 | 1409 | ||
1403 | struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci) | 1410 | struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci) |
1404 | { | 1411 | { |
1405 | struct cx25821_dev *dev = pci_get_drvdata(pci); | 1412 | struct cx25821_dev *dev = pci_get_drvdata(pci); |
1406 | return dev; | 1413 | return dev; |
1407 | } | 1414 | } |
1415 | EXPORT_SYMBOL(cx25821_dev_get); | ||
1408 | 1416 | ||
1409 | static int __devinit cx25821_initdev(struct pci_dev *pci_dev, | 1417 | static int __devinit cx25821_initdev(struct pci_dev *pci_dev, |
1410 | const struct pci_device_id *pci_id) | 1418 | const struct pci_device_id *pci_id) |
@@ -1430,7 +1438,7 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, | |||
1430 | goto fail_unregister_device; | 1438 | goto fail_unregister_device; |
1431 | } | 1439 | } |
1432 | 1440 | ||
1433 | printk(KERN_INFO "cx25821 Athena pci enable ! \n"); | 1441 | printk(KERN_INFO "cx25821 Athena pci enable !\n"); |
1434 | 1442 | ||
1435 | if (cx25821_dev_setup(dev) < 0) { | 1443 | if (cx25821_dev_setup(dev) < 0) { |
1436 | err = -EINVAL; | 1444 | err = -EINVAL; |
@@ -1464,14 +1472,14 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, | |||
1464 | 1472 | ||
1465 | return 0; | 1473 | return 0; |
1466 | 1474 | ||
1467 | fail_irq: | 1475 | fail_irq: |
1468 | printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); | 1476 | printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ !\n"); |
1469 | cx25821_dev_unregister(dev); | 1477 | cx25821_dev_unregister(dev); |
1470 | 1478 | ||
1471 | fail_unregister_device: | 1479 | fail_unregister_device: |
1472 | v4l2_device_unregister(&dev->v4l2_dev); | 1480 | v4l2_device_unregister(&dev->v4l2_dev); |
1473 | 1481 | ||
1474 | fail_free: | 1482 | fail_free: |
1475 | kfree(dev); | 1483 | kfree(dev); |
1476 | return err; | 1484 | return err; |
1477 | } | 1485 | } |
@@ -1536,16 +1544,6 @@ static void __exit cx25821_fini(void) | |||
1536 | pci_unregister_driver(&cx25821_pci_driver); | 1544 | pci_unregister_driver(&cx25821_pci_driver); |
1537 | } | 1545 | } |
1538 | 1546 | ||
1539 | EXPORT_SYMBOL(cx25821_devlist); | ||
1540 | EXPORT_SYMBOL(cx25821_sram_channels); | ||
1541 | EXPORT_SYMBOL(cx25821_print_irqbits); | ||
1542 | EXPORT_SYMBOL(cx25821_dev_get); | ||
1543 | EXPORT_SYMBOL(cx25821_dev_unregister); | ||
1544 | EXPORT_SYMBOL(cx25821_sram_channel_setup); | ||
1545 | EXPORT_SYMBOL(cx25821_sram_channel_dump); | ||
1546 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); | ||
1547 | EXPORT_SYMBOL(cx25821_sram_channel_dump_audio); | ||
1548 | EXPORT_SYMBOL(cx25821_risc_databuffer_audio); | ||
1549 | EXPORT_SYMBOL(cx25821_set_gpiopin_direction); | 1547 | EXPORT_SYMBOL(cx25821_set_gpiopin_direction); |
1550 | 1548 | ||
1551 | module_init(cx25821_init); | 1549 | module_init(cx25821_init); |
diff --git a/drivers/staging/cx25821/cx25821-gpio.c b/drivers/staging/cx25821/cx25821-gpio.c index e8a37b47e437..2f154b3658a1 100644 --- a/drivers/staging/cx25821/cx25821-gpio.c +++ b/drivers/staging/cx25821/cx25821-gpio.c | |||
@@ -31,7 +31,7 @@ void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, | |||
31 | u32 gpio_register = 0; | 31 | u32 gpio_register = 0; |
32 | u32 value = 0; | 32 | u32 value = 0; |
33 | 33 | ||
34 | // Check for valid pinNumber | 34 | /* Check for valid pinNumber */ |
35 | if (pin_number >= 47) | 35 | if (pin_number >= 47) |
36 | return; | 36 | return; |
37 | 37 | ||
@@ -39,14 +39,14 @@ void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, | |||
39 | bit = pin_number - 31; | 39 | bit = pin_number - 31; |
40 | gpio_oe_reg = GPIO_HI_OE; | 40 | gpio_oe_reg = GPIO_HI_OE; |
41 | } | 41 | } |
42 | // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is | 42 | /* Here we will make sure that the GPIOs 0 and 1 are output. keep the |
43 | * rest as is */ | ||
43 | gpio_register = cx_read(gpio_oe_reg); | 44 | gpio_register = cx_read(gpio_oe_reg); |
44 | 45 | ||
45 | if (pin_logic_value == 1) { | 46 | if (pin_logic_value == 1) |
46 | value = gpio_register | Set_GPIO_Bit(bit); | 47 | value = gpio_register | Set_GPIO_Bit(bit); |
47 | } else { | 48 | else |
48 | value = gpio_register & Clear_GPIO_Bit(bit); | 49 | value = gpio_register & Clear_GPIO_Bit(bit); |
49 | } | ||
50 | 50 | ||
51 | cx_write(gpio_oe_reg, value); | 51 | cx_write(gpio_oe_reg, value); |
52 | } | 52 | } |
@@ -58,11 +58,12 @@ static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev, | |||
58 | u32 gpio_reg = GPIO_LO; | 58 | u32 gpio_reg = GPIO_LO; |
59 | u32 value = 0; | 59 | u32 value = 0; |
60 | 60 | ||
61 | // Check for valid pinNumber | 61 | /* Check for valid pinNumber */ |
62 | if (pin_number >= 47) | 62 | if (pin_number >= 47) |
63 | return; | 63 | return; |
64 | 64 | ||
65 | cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction | 65 | /* change to output direction */ |
66 | cx25821_set_gpiopin_direction(dev, pin_number, 0); | ||
66 | 67 | ||
67 | if (pin_number > 31) { | 68 | if (pin_number > 31) { |
68 | bit = pin_number - 31; | 69 | bit = pin_number - 31; |
@@ -71,25 +72,23 @@ static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev, | |||
71 | 72 | ||
72 | value = cx_read(gpio_reg); | 73 | value = cx_read(gpio_reg); |
73 | 74 | ||
74 | if (pin_logic_value == 0) { | 75 | if (pin_logic_value == 0) |
75 | value &= Clear_GPIO_Bit(bit); | 76 | value &= Clear_GPIO_Bit(bit); |
76 | } else { | 77 | else |
77 | value |= Set_GPIO_Bit(bit); | 78 | value |= Set_GPIO_Bit(bit); |
78 | } | ||
79 | 79 | ||
80 | cx_write(gpio_reg, value); | 80 | cx_write(gpio_reg, value); |
81 | } | 81 | } |
82 | 82 | ||
83 | void cx25821_gpio_init(struct cx25821_dev *dev) | 83 | void cx25821_gpio_init(struct cx25821_dev *dev) |
84 | { | 84 | { |
85 | if (dev == NULL) { | 85 | if (dev == NULL) |
86 | return; | 86 | return; |
87 | } | ||
88 | 87 | ||
89 | switch (dev->board) { | 88 | switch (dev->board) { |
90 | case CX25821_BOARD_CONEXANT_ATHENA10: | 89 | case CX25821_BOARD_CONEXANT_ATHENA10: |
91 | default: | 90 | default: |
92 | //set GPIO 5 to select the path for Medusa/Athena | 91 | /* set GPIO 5 to select the path for Medusa/Athena */ |
93 | cx25821_set_gpiopin_logicvalue(dev, 5, 1); | 92 | cx25821_set_gpiopin_logicvalue(dev, 5, 1); |
94 | mdelay(20); | 93 | mdelay(20); |
95 | break; | 94 | break; |
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c index f4f2681d8f1c..08f45b52df6a 100644 --- a/drivers/staging/cx25821/cx25821-i2c.c +++ b/drivers/staging/cx25821/cx25821-i2c.c | |||
@@ -28,7 +28,7 @@ static unsigned int i2c_debug; | |||
28 | module_param(i2c_debug, int, 0644); | 28 | module_param(i2c_debug, int, 0644); |
29 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | 29 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); |
30 | 30 | ||
31 | static unsigned int i2c_scan = 0; | 31 | static unsigned int i2c_scan; |
32 | module_param(i2c_scan, int, 0444); | 32 | module_param(i2c_scan, int, 0444); |
33 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | 33 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); |
34 | 34 | ||
@@ -159,9 +159,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, | |||
159 | 159 | ||
160 | return msg->len; | 160 | return msg->len; |
161 | 161 | ||
162 | eio: | 162 | eio: |
163 | retval = -EIO; | 163 | retval = -EIO; |
164 | err: | 164 | err: |
165 | if (i2c_debug) | 165 | if (i2c_debug) |
166 | printk(KERN_ERR " ERR: %d\n", retval); | 166 | printk(KERN_ERR " ERR: %d\n", retval); |
167 | return retval; | 167 | return retval; |
@@ -223,9 +223,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, | |||
223 | } | 223 | } |
224 | 224 | ||
225 | return msg->len; | 225 | return msg->len; |
226 | eio: | 226 | eio: |
227 | retval = -EIO; | 227 | retval = -EIO; |
228 | err: | 228 | err: |
229 | if (i2c_debug) | 229 | if (i2c_debug) |
230 | printk(KERN_ERR " ERR: %d\n", retval); | 230 | printk(KERN_ERR " ERR: %d\n", retval); |
231 | return retval; | 231 | return retval; |
@@ -266,7 +266,7 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | |||
266 | } | 266 | } |
267 | return num; | 267 | return num; |
268 | 268 | ||
269 | err: | 269 | err: |
270 | return retval; | 270 | return retval; |
271 | } | 271 | } |
272 | 272 | ||
@@ -319,7 +319,7 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) | |||
319 | 319 | ||
320 | bus->i2c_client.adapter = &bus->i2c_adap; | 320 | bus->i2c_client.adapter = &bus->i2c_adap; |
321 | 321 | ||
322 | //set up the I2c | 322 | /* set up the I2c */ |
323 | bus->i2c_client.addr = (0x88 >> 1); | 323 | bus->i2c_client.addr = (0x88 >> 1); |
324 | 324 | ||
325 | return bus->i2c_rc; | 325 | return bus->i2c_rc; |
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c index d6016200d699..34616dc507f9 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/drivers/staging/cx25821/cx25821-medusa-video.c | |||
@@ -24,11 +24,12 @@ | |||
24 | #include "cx25821-medusa-video.h" | 24 | #include "cx25821-medusa-video.h" |
25 | #include "cx25821-biffuncs.h" | 25 | #include "cx25821-biffuncs.h" |
26 | 26 | ||
27 | ///////////////////////////////////////////////////////////////////////////////////////// | 27 | /* |
28 | //medusa_enable_bluefield_output() | 28 | * medusa_enable_bluefield_output() |
29 | // | 29 | * |
30 | // Enable the generation of blue filed output if no video | 30 | * Enable the generation of blue filed output if no video |
31 | // | 31 | * |
32 | */ | ||
32 | static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, | 33 | static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, |
33 | int enable) | 34 | int enable) |
34 | { | 35 | { |
@@ -73,15 +74,15 @@ static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, | |||
73 | } | 74 | } |
74 | 75 | ||
75 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); | 76 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); |
76 | value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN | 77 | value &= 0xFFFFFF7F; /* clear BLUE_FIELD_EN */ |
77 | if (enable) | 78 | if (enable) |
78 | value |= 0x00000080; // set BLUE_FIELD_EN | 79 | value |= 0x00000080; /* set BLUE_FIELD_EN */ |
79 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); | 80 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); |
80 | 81 | ||
81 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); | 82 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); |
82 | value &= 0xFFFFFF7F; | 83 | value &= 0xFFFFFF7F; |
83 | if (enable) | 84 | if (enable) |
84 | value |= 0x00000080; // set BLUE_FIELD_EN | 85 | value |= 0x00000080; /* set BLUE_FIELD_EN */ |
85 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); | 86 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); |
86 | } | 87 | } |
87 | 88 | ||
@@ -95,17 +96,18 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
95 | mutex_lock(&dev->lock); | 96 | mutex_lock(&dev->lock); |
96 | 97 | ||
97 | for (i = 0; i < MAX_DECODERS; i++) { | 98 | for (i = 0; i < MAX_DECODERS; i++) { |
98 | // set video format NTSC-M | 99 | /* set video format NTSC-M */ |
99 | value = | 100 | value = |
100 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 101 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), |
101 | &tmp); | 102 | &tmp); |
102 | value &= 0xFFFFFFF0; | 103 | value &= 0xFFFFFFF0; |
103 | value |= 0x10001; // enable the fast locking mode bit[16] | 104 | /* enable the fast locking mode bit[16] */ |
105 | value |= 0x10001; | ||
104 | ret_val = | 106 | ret_val = |
105 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 107 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), |
106 | value); | 108 | value); |
107 | 109 | ||
108 | // resolution NTSC 720x480 | 110 | /* resolution NTSC 720x480 */ |
109 | value = | 111 | value = |
110 | cx25821_i2c_read(&dev->i2c_bus[0], | 112 | cx25821_i2c_read(&dev->i2c_bus[0], |
111 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | 113 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); |
@@ -119,17 +121,17 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
119 | cx25821_i2c_read(&dev->i2c_bus[0], | 121 | cx25821_i2c_read(&dev->i2c_bus[0], |
120 | VERT_TIM_CTRL + (0x200 * i), &tmp); | 122 | VERT_TIM_CTRL + (0x200 * i), &tmp); |
121 | value &= 0x00C00C00; | 123 | value &= 0x00C00C00; |
122 | value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID | 124 | value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */ |
123 | ret_val = | 125 | ret_val = |
124 | cx25821_i2c_write(&dev->i2c_bus[0], | 126 | cx25821_i2c_write(&dev->i2c_bus[0], |
125 | VERT_TIM_CTRL + (0x200 * i), value); | 127 | VERT_TIM_CTRL + (0x200 * i), value); |
126 | 128 | ||
127 | // chroma subcarrier step size | 129 | /* chroma subcarrier step size */ |
128 | ret_val = | 130 | ret_val = |
129 | cx25821_i2c_write(&dev->i2c_bus[0], | 131 | cx25821_i2c_write(&dev->i2c_bus[0], |
130 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); | 132 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); |
131 | 133 | ||
132 | // enable VIP optional active | 134 | /* enable VIP optional active */ |
133 | value = | 135 | value = |
134 | cx25821_i2c_read(&dev->i2c_bus[0], | 136 | cx25821_i2c_read(&dev->i2c_bus[0], |
135 | OUT_CTRL_NS + (0x200 * i), &tmp); | 137 | OUT_CTRL_NS + (0x200 * i), &tmp); |
@@ -139,7 +141,7 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
139 | cx25821_i2c_write(&dev->i2c_bus[0], | 141 | cx25821_i2c_write(&dev->i2c_bus[0], |
140 | OUT_CTRL_NS + (0x200 * i), value); | 142 | OUT_CTRL_NS + (0x200 * i), value); |
141 | 143 | ||
142 | // enable VIP optional active (VIP_OPT_AL) for direct output. | 144 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
143 | value = | 145 | value = |
144 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 146 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), |
145 | &tmp); | 147 | &tmp); |
@@ -149,19 +151,21 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
149 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 151 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), |
150 | value); | 152 | value); |
151 | 153 | ||
152 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | 154 | /* |
153 | // when the input switching rate < 16 fields | 155 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem |
154 | // | 156 | * when the input switching rate < 16 fields |
157 | */ | ||
155 | value = | 158 | value = |
156 | cx25821_i2c_read(&dev->i2c_bus[0], | 159 | cx25821_i2c_read(&dev->i2c_bus[0], |
157 | MISC_TIM_CTRL + (0x200 * i), &tmp); | 160 | MISC_TIM_CTRL + (0x200 * i), &tmp); |
158 | value = setBitAtPos(value, 14); // disable special play detection | 161 | /* disable special play detection */ |
162 | value = setBitAtPos(value, 14); | ||
159 | value = clearBitAtPos(value, 15); | 163 | value = clearBitAtPos(value, 15); |
160 | ret_val = | 164 | ret_val = |
161 | cx25821_i2c_write(&dev->i2c_bus[0], | 165 | cx25821_i2c_write(&dev->i2c_bus[0], |
162 | MISC_TIM_CTRL + (0x200 * i), value); | 166 | MISC_TIM_CTRL + (0x200 * i), value); |
163 | 167 | ||
164 | // set vbi_gate_en to 0 | 168 | /* set vbi_gate_en to 0 */ |
165 | value = | 169 | value = |
166 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 170 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), |
167 | &tmp); | 171 | &tmp); |
@@ -170,12 +174,12 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
170 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 174 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), |
171 | value); | 175 | value); |
172 | 176 | ||
173 | // Enable the generation of blue field output if no video | 177 | /* Enable the generation of blue field output if no video */ |
174 | medusa_enable_bluefield_output(dev, i, 1); | 178 | medusa_enable_bluefield_output(dev, i, 1); |
175 | } | 179 | } |
176 | 180 | ||
177 | for (i = 0; i < MAX_ENCODERS; i++) { | 181 | for (i = 0; i < MAX_ENCODERS; i++) { |
178 | // NTSC hclock | 182 | /* NTSC hclock */ |
179 | value = | 183 | value = |
180 | cx25821_i2c_read(&dev->i2c_bus[0], | 184 | cx25821_i2c_read(&dev->i2c_bus[0], |
181 | DENC_A_REG_1 + (0x100 * i), &tmp); | 185 | DENC_A_REG_1 + (0x100 * i), &tmp); |
@@ -185,7 +189,7 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
185 | cx25821_i2c_write(&dev->i2c_bus[0], | 189 | cx25821_i2c_write(&dev->i2c_bus[0], |
186 | DENC_A_REG_1 + (0x100 * i), value); | 190 | DENC_A_REG_1 + (0x100 * i), value); |
187 | 191 | ||
188 | // burst begin and burst end | 192 | /* burst begin and burst end */ |
189 | value = | 193 | value = |
190 | cx25821_i2c_read(&dev->i2c_bus[0], | 194 | cx25821_i2c_read(&dev->i2c_bus[0], |
191 | DENC_A_REG_2 + (0x100 * i), &tmp); | 195 | DENC_A_REG_2 + (0x100 * i), &tmp); |
@@ -204,7 +208,7 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
204 | cx25821_i2c_write(&dev->i2c_bus[0], | 208 | cx25821_i2c_write(&dev->i2c_bus[0], |
205 | DENC_A_REG_3 + (0x100 * i), value); | 209 | DENC_A_REG_3 + (0x100 * i), value); |
206 | 210 | ||
207 | // set NTSC vblank, no phase alternation, 7.5 IRE pedestal | 211 | /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */ |
208 | value = | 212 | value = |
209 | cx25821_i2c_read(&dev->i2c_bus[0], | 213 | cx25821_i2c_read(&dev->i2c_bus[0], |
210 | DENC_A_REG_4 + (0x100 * i), &tmp); | 214 | DENC_A_REG_4 + (0x100 * i), &tmp); |
@@ -227,17 +231,19 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
227 | cx25821_i2c_write(&dev->i2c_bus[0], | 231 | cx25821_i2c_write(&dev->i2c_bus[0], |
228 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); | 232 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); |
229 | 233 | ||
230 | // Subcarrier Increment | 234 | /* Subcarrier Increment */ |
231 | ret_val = | 235 | ret_val = |
232 | cx25821_i2c_write(&dev->i2c_bus[0], | 236 | cx25821_i2c_write(&dev->i2c_bus[0], |
233 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); | 237 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); |
234 | } | 238 | } |
235 | 239 | ||
236 | //set picture resolutions | 240 | /* set picture resolutions */ |
237 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | 241 | /* 0 - 720 */ |
238 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 | 242 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); |
243 | /* 0 - 480 */ | ||
244 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); | ||
239 | 245 | ||
240 | // set Bypass input format to NTSC 525 lines | 246 | /* set Bypass input format to NTSC 525 lines */ |
241 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | 247 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
242 | value |= 0x00080200; | 248 | value |= 0x00080200; |
243 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | 249 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
@@ -252,7 +258,7 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | |||
252 | int ret_val = -1; | 258 | int ret_val = -1; |
253 | u32 value = 0, tmp = 0; | 259 | u32 value = 0, tmp = 0; |
254 | 260 | ||
255 | // Setup for 2D threshold | 261 | /* Setup for 2D threshold */ |
256 | ret_val = | 262 | ret_val = |
257 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), | 263 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), |
258 | 0x20002861); | 264 | 0x20002861); |
@@ -263,7 +269,7 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | |||
263 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), | 269 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), |
264 | 0x200A1023); | 270 | 0x200A1023); |
265 | 271 | ||
266 | // Setup flat chroma and luma thresholds | 272 | /* Setup flat chroma and luma thresholds */ |
267 | value = | 273 | value = |
268 | cx25821_i2c_read(&dev->i2c_bus[0], | 274 | cx25821_i2c_read(&dev->i2c_bus[0], |
269 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); | 275 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); |
@@ -272,12 +278,12 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | |||
272 | cx25821_i2c_write(&dev->i2c_bus[0], | 278 | cx25821_i2c_write(&dev->i2c_bus[0], |
273 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); | 279 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); |
274 | 280 | ||
275 | // set comb 2D blend | 281 | /* set comb 2D blend */ |
276 | ret_val = | 282 | ret_val = |
277 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), | 283 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), |
278 | 0x210F0F0F); | 284 | 0x210F0F0F); |
279 | 285 | ||
280 | // COMB MISC CONTROL | 286 | /* COMB MISC CONTROL */ |
281 | ret_val = | 287 | ret_val = |
282 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), | 288 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), |
283 | 0x41120A7F); | 289 | 0x41120A7F); |
@@ -295,17 +301,18 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
295 | mutex_lock(&dev->lock); | 301 | mutex_lock(&dev->lock); |
296 | 302 | ||
297 | for (i = 0; i < MAX_DECODERS; i++) { | 303 | for (i = 0; i < MAX_DECODERS; i++) { |
298 | // set video format PAL-BDGHI | 304 | /* set video format PAL-BDGHI */ |
299 | value = | 305 | value = |
300 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 306 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), |
301 | &tmp); | 307 | &tmp); |
302 | value &= 0xFFFFFFF0; | 308 | value &= 0xFFFFFFF0; |
303 | value |= 0x10004; // enable the fast locking mode bit[16] | 309 | /* enable the fast locking mode bit[16] */ |
310 | value |= 0x10004; | ||
304 | ret_val = | 311 | ret_val = |
305 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 312 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), |
306 | value); | 313 | value); |
307 | 314 | ||
308 | // resolution PAL 720x576 | 315 | /* resolution PAL 720x576 */ |
309 | value = | 316 | value = |
310 | cx25821_i2c_read(&dev->i2c_bus[0], | 317 | cx25821_i2c_read(&dev->i2c_bus[0], |
311 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | 318 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); |
@@ -315,22 +322,22 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
315 | cx25821_i2c_write(&dev->i2c_bus[0], | 322 | cx25821_i2c_write(&dev->i2c_bus[0], |
316 | HORIZ_TIM_CTRL + (0x200 * i), value); | 323 | HORIZ_TIM_CTRL + (0x200 * i), value); |
317 | 324 | ||
318 | // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 | 325 | /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */ |
319 | value = | 326 | value = |
320 | cx25821_i2c_read(&dev->i2c_bus[0], | 327 | cx25821_i2c_read(&dev->i2c_bus[0], |
321 | VERT_TIM_CTRL + (0x200 * i), &tmp); | 328 | VERT_TIM_CTRL + (0x200 * i), &tmp); |
322 | value &= 0x00C00C00; | 329 | value &= 0x00C00C00; |
323 | value |= 0x28240026; // vblank_cnt + 2 to get camera ID | 330 | value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */ |
324 | ret_val = | 331 | ret_val = |
325 | cx25821_i2c_write(&dev->i2c_bus[0], | 332 | cx25821_i2c_write(&dev->i2c_bus[0], |
326 | VERT_TIM_CTRL + (0x200 * i), value); | 333 | VERT_TIM_CTRL + (0x200 * i), value); |
327 | 334 | ||
328 | // chroma subcarrier step size | 335 | /* chroma subcarrier step size */ |
329 | ret_val = | 336 | ret_val = |
330 | cx25821_i2c_write(&dev->i2c_bus[0], | 337 | cx25821_i2c_write(&dev->i2c_bus[0], |
331 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); | 338 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); |
332 | 339 | ||
333 | // enable VIP optional active | 340 | /* enable VIP optional active */ |
334 | value = | 341 | value = |
335 | cx25821_i2c_read(&dev->i2c_bus[0], | 342 | cx25821_i2c_read(&dev->i2c_bus[0], |
336 | OUT_CTRL_NS + (0x200 * i), &tmp); | 343 | OUT_CTRL_NS + (0x200 * i), &tmp); |
@@ -340,7 +347,7 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
340 | cx25821_i2c_write(&dev->i2c_bus[0], | 347 | cx25821_i2c_write(&dev->i2c_bus[0], |
341 | OUT_CTRL_NS + (0x200 * i), value); | 348 | OUT_CTRL_NS + (0x200 * i), value); |
342 | 349 | ||
343 | // enable VIP optional active (VIP_OPT_AL) for direct output. | 350 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
344 | value = | 351 | value = |
345 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 352 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), |
346 | &tmp); | 353 | &tmp); |
@@ -350,18 +357,21 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
350 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 357 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), |
351 | value); | 358 | value); |
352 | 359 | ||
353 | // clear VPRES_VERT_EN bit, fixes the chroma run away problem | 360 | /* |
354 | // when the input switching rate < 16 fields | 361 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem |
362 | * when the input switching rate < 16 fields | ||
363 | */ | ||
355 | value = | 364 | value = |
356 | cx25821_i2c_read(&dev->i2c_bus[0], | 365 | cx25821_i2c_read(&dev->i2c_bus[0], |
357 | MISC_TIM_CTRL + (0x200 * i), &tmp); | 366 | MISC_TIM_CTRL + (0x200 * i), &tmp); |
358 | value = setBitAtPos(value, 14); // disable special play detection | 367 | /* disable special play detection */ |
368 | value = setBitAtPos(value, 14); | ||
359 | value = clearBitAtPos(value, 15); | 369 | value = clearBitAtPos(value, 15); |
360 | ret_val = | 370 | ret_val = |
361 | cx25821_i2c_write(&dev->i2c_bus[0], | 371 | cx25821_i2c_write(&dev->i2c_bus[0], |
362 | MISC_TIM_CTRL + (0x200 * i), value); | 372 | MISC_TIM_CTRL + (0x200 * i), value); |
363 | 373 | ||
364 | // set vbi_gate_en to 0 | 374 | /* set vbi_gate_en to 0 */ |
365 | value = | 375 | value = |
366 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 376 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), |
367 | &tmp); | 377 | &tmp); |
@@ -372,12 +382,12 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
372 | 382 | ||
373 | medusa_PALCombInit(dev, i); | 383 | medusa_PALCombInit(dev, i); |
374 | 384 | ||
375 | // Enable the generation of blue field output if no video | 385 | /* Enable the generation of blue field output if no video */ |
376 | medusa_enable_bluefield_output(dev, i, 1); | 386 | medusa_enable_bluefield_output(dev, i, 1); |
377 | } | 387 | } |
378 | 388 | ||
379 | for (i = 0; i < MAX_ENCODERS; i++) { | 389 | for (i = 0; i < MAX_ENCODERS; i++) { |
380 | // PAL hclock | 390 | /* PAL hclock */ |
381 | value = | 391 | value = |
382 | cx25821_i2c_read(&dev->i2c_bus[0], | 392 | cx25821_i2c_read(&dev->i2c_bus[0], |
383 | DENC_A_REG_1 + (0x100 * i), &tmp); | 393 | DENC_A_REG_1 + (0x100 * i), &tmp); |
@@ -387,7 +397,7 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
387 | cx25821_i2c_write(&dev->i2c_bus[0], | 397 | cx25821_i2c_write(&dev->i2c_bus[0], |
388 | DENC_A_REG_1 + (0x100 * i), value); | 398 | DENC_A_REG_1 + (0x100 * i), value); |
389 | 399 | ||
390 | // burst begin and burst end | 400 | /* burst begin and burst end */ |
391 | value = | 401 | value = |
392 | cx25821_i2c_read(&dev->i2c_bus[0], | 402 | cx25821_i2c_read(&dev->i2c_bus[0], |
393 | DENC_A_REG_2 + (0x100 * i), &tmp); | 403 | DENC_A_REG_2 + (0x100 * i), &tmp); |
@@ -397,7 +407,7 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
397 | cx25821_i2c_write(&dev->i2c_bus[0], | 407 | cx25821_i2c_write(&dev->i2c_bus[0], |
398 | DENC_A_REG_2 + (0x100 * i), value); | 408 | DENC_A_REG_2 + (0x100 * i), value); |
399 | 409 | ||
400 | // hblank and vactive | 410 | /* hblank and vactive */ |
401 | value = | 411 | value = |
402 | cx25821_i2c_read(&dev->i2c_bus[0], | 412 | cx25821_i2c_read(&dev->i2c_bus[0], |
403 | DENC_A_REG_3 + (0x100 * i), &tmp); | 413 | DENC_A_REG_3 + (0x100 * i), &tmp); |
@@ -407,7 +417,7 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
407 | cx25821_i2c_write(&dev->i2c_bus[0], | 417 | cx25821_i2c_write(&dev->i2c_bus[0], |
408 | DENC_A_REG_3 + (0x100 * i), value); | 418 | DENC_A_REG_3 + (0x100 * i), value); |
409 | 419 | ||
410 | // set PAL vblank, phase alternation, 0 IRE pedestal | 420 | /* set PAL vblank, phase alternation, 0 IRE pedestal */ |
411 | value = | 421 | value = |
412 | cx25821_i2c_read(&dev->i2c_bus[0], | 422 | cx25821_i2c_read(&dev->i2c_bus[0], |
413 | DENC_A_REG_4 + (0x100 * i), &tmp); | 423 | DENC_A_REG_4 + (0x100 * i), &tmp); |
@@ -430,17 +440,19 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
430 | cx25821_i2c_write(&dev->i2c_bus[0], | 440 | cx25821_i2c_write(&dev->i2c_bus[0], |
431 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); | 441 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); |
432 | 442 | ||
433 | // Subcarrier Increment | 443 | /* Subcarrier Increment */ |
434 | ret_val = | 444 | ret_val = |
435 | cx25821_i2c_write(&dev->i2c_bus[0], | 445 | cx25821_i2c_write(&dev->i2c_bus[0], |
436 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); | 446 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); |
437 | } | 447 | } |
438 | 448 | ||
439 | //set picture resolutions | 449 | /* set picture resolutions */ |
440 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 | 450 | /* 0 - 720 */ |
441 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 | 451 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); |
452 | /* 0 - 576 */ | ||
453 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); | ||
442 | 454 | ||
443 | // set Bypass input format to PAL 625 lines | 455 | /* set Bypass input format to PAL 625 lines */ |
444 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | 456 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
445 | value &= 0xFFF7FDFF; | 457 | value &= 0xFFF7FDFF; |
446 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | 458 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
@@ -455,18 +467,17 @@ int medusa_set_videostandard(struct cx25821_dev *dev) | |||
455 | int status = STATUS_SUCCESS; | 467 | int status = STATUS_SUCCESS; |
456 | u32 value = 0, tmp = 0; | 468 | u32 value = 0, tmp = 0; |
457 | 469 | ||
458 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) { | 470 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) |
459 | status = medusa_initialize_pal(dev); | 471 | status = medusa_initialize_pal(dev); |
460 | } else { | 472 | else |
461 | status = medusa_initialize_ntsc(dev); | 473 | status = medusa_initialize_ntsc(dev); |
462 | } | ||
463 | 474 | ||
464 | // Enable DENC_A output | 475 | /* Enable DENC_A output */ |
465 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); | 476 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); |
466 | value = setBitAtPos(value, 4); | 477 | value = setBitAtPos(value, 4); |
467 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); | 478 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); |
468 | 479 | ||
469 | // Enable DENC_B output | 480 | /* Enable DENC_B output */ |
470 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); | 481 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); |
471 | value = setBitAtPos(value, 4); | 482 | value = setBitAtPos(value, 4); |
472 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); | 483 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); |
@@ -486,10 +497,10 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
486 | 497 | ||
487 | mutex_lock(&dev->lock); | 498 | mutex_lock(&dev->lock); |
488 | 499 | ||
489 | // validate the width - cannot be negative | 500 | /* validate the width - cannot be negative */ |
490 | if (width > MAX_WIDTH) { | 501 | if (width > MAX_WIDTH) { |
491 | printk | 502 | printk |
492 | ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", | 503 | ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", |
493 | __func__, width, MAX_WIDTH); | 504 | __func__, width, MAX_WIDTH); |
494 | width = MAX_WIDTH; | 505 | width = MAX_WIDTH; |
495 | } | 506 | } |
@@ -523,14 +534,14 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
523 | vscale = 0x1E00; | 534 | vscale = 0x1E00; |
524 | break; | 535 | break; |
525 | 536 | ||
526 | default: //720 | 537 | default: /* 720 */ |
527 | hscale = 0x0; | 538 | hscale = 0x0; |
528 | vscale = 0x0; | 539 | vscale = 0x0; |
529 | break; | 540 | break; |
530 | } | 541 | } |
531 | 542 | ||
532 | for (; decoder < decoder_count; decoder++) { | 543 | for (; decoder < decoder_count; decoder++) { |
533 | // write scaling values for each decoder | 544 | /* write scaling values for each decoder */ |
534 | ret_val = | 545 | ret_val = |
535 | cx25821_i2c_write(&dev->i2c_bus[0], | 546 | cx25821_i2c_write(&dev->i2c_bus[0], |
536 | HSCALE_CTRL + (0x200 * decoder), hscale); | 547 | HSCALE_CTRL + (0x200 * decoder), hscale); |
@@ -552,7 +563,7 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
552 | 563 | ||
553 | mutex_lock(&dev->lock); | 564 | mutex_lock(&dev->lock); |
554 | 565 | ||
555 | // no support | 566 | /* no support */ |
556 | if (decoder < VDEC_A && decoder > VDEC_H) { | 567 | if (decoder < VDEC_A && decoder > VDEC_H) { |
557 | mutex_unlock(&dev->lock); | 568 | mutex_unlock(&dev->lock); |
558 | return; | 569 | return; |
@@ -577,11 +588,10 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
577 | 588 | ||
578 | _display_field_cnt[decoder] = duration; | 589 | _display_field_cnt[decoder] = duration; |
579 | 590 | ||
580 | // update hardware | 591 | /* update hardware */ |
581 | fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); | 592 | fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); |
582 | 593 | ||
583 | if (!(decoder % 2)) // EVEN decoder | 594 | if (!(decoder % 2)) { /* EVEN decoder */ |
584 | { | ||
585 | fld_cnt &= 0xFFFF0000; | 595 | fld_cnt &= 0xFFFF0000; |
586 | fld_cnt |= duration; | 596 | fld_cnt |= duration; |
587 | } else { | 597 | } else { |
@@ -594,8 +604,7 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
594 | mutex_unlock(&dev->lock); | 604 | mutex_unlock(&dev->lock); |
595 | } | 605 | } |
596 | 606 | ||
597 | ///////////////////////////////////////////////////////////////////////////////////////// | 607 | /* Map to Medusa register setting */ |
598 | // Map to Medusa register setting | ||
599 | static int mapM(int srcMin, | 608 | static int mapM(int srcMin, |
600 | int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) | 609 | int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) |
601 | { | 610 | { |
@@ -603,20 +612,21 @@ static int mapM(int srcMin, | |||
603 | int denominator; | 612 | int denominator; |
604 | int quotient; | 613 | int quotient; |
605 | 614 | ||
606 | if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) { | 615 | if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) |
607 | return -1; | 616 | return -1; |
608 | } | 617 | /* |
609 | // This is the overall expression used: | 618 | * This is the overall expression used: |
610 | // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; | 619 | * *dstVal = |
611 | // but we need to account for rounding so below we use the modulus | 620 | * (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; |
612 | // operator to find the remainder and increment if necessary. | 621 | * but we need to account for rounding so below we use the modulus |
622 | * operator to find the remainder and increment if necessary. | ||
623 | */ | ||
613 | numerator = (srcVal - srcMin) * (dstMax - dstMin); | 624 | numerator = (srcVal - srcMin) * (dstMax - dstMin); |
614 | denominator = srcMax - srcMin; | 625 | denominator = srcMax - srcMin; |
615 | quotient = numerator / denominator; | 626 | quotient = numerator / denominator; |
616 | 627 | ||
617 | if (2 * (numerator % denominator) >= denominator) { | 628 | if (2 * (numerator % denominator) >= denominator) |
618 | quotient++; | 629 | quotient++; |
619 | } | ||
620 | 630 | ||
621 | *dstVal = quotient + dstMin; | 631 | *dstVal = quotient + dstMin; |
622 | 632 | ||
@@ -636,7 +646,6 @@ static unsigned long convert_to_twos(long numeric, unsigned long bits_len) | |||
636 | } | 646 | } |
637 | } | 647 | } |
638 | 648 | ||
639 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
640 | int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | 649 | int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) |
641 | { | 650 | { |
642 | int ret_val = 0; | 651 | int ret_val = 0; |
@@ -665,7 +674,6 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | |||
665 | return ret_val; | 674 | return ret_val; |
666 | } | 675 | } |
667 | 676 | ||
668 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
669 | int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | 677 | int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) |
670 | { | 678 | { |
671 | int ret_val = 0; | 679 | int ret_val = 0; |
@@ -695,7 +703,6 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | |||
695 | return ret_val; | 703 | return ret_val; |
696 | } | 704 | } |
697 | 705 | ||
698 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
699 | int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | 706 | int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) |
700 | { | 707 | { |
701 | int ret_val = 0; | 708 | int ret_val = 0; |
@@ -727,7 +734,6 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | |||
727 | return ret_val; | 734 | return ret_val; |
728 | } | 735 | } |
729 | 736 | ||
730 | ///////////////////////////////////////////////////////////////////////////////////////// | ||
731 | int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | 737 | int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) |
732 | { | 738 | { |
733 | int ret_val = 0; | 739 | int ret_val = 0; |
@@ -768,98 +774,90 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | |||
768 | return ret_val; | 774 | return ret_val; |
769 | } | 775 | } |
770 | 776 | ||
771 | ///////////////////////////////////////////////////////////////////////////////////////// | 777 | /* Program the display sequence and monitor output. */ |
772 | // Program the display sequence and monitor output. | 778 | |
773 | // | ||
774 | int medusa_video_init(struct cx25821_dev *dev) | 779 | int medusa_video_init(struct cx25821_dev *dev) |
775 | { | 780 | { |
776 | u32 value = 0, tmp = 0; | 781 | u32 value, tmp = 0; |
777 | int ret_val = 0; | 782 | int ret_val; |
778 | int i = 0; | 783 | int i; |
779 | 784 | ||
780 | mutex_lock(&dev->lock); | 785 | mutex_lock(&dev->lock); |
781 | 786 | ||
782 | _num_decoders = dev->_max_num_decoders; | 787 | _num_decoders = dev->_max_num_decoders; |
783 | 788 | ||
784 | // disable Auto source selection on all video decoders | 789 | /* disable Auto source selection on all video decoders */ |
785 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | 790 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); |
786 | value &= 0xFFFFF0FF; | 791 | value &= 0xFFFFF0FF; |
787 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | 792 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); |
793 | if (ret_val < 0) | ||
794 | goto error; | ||
788 | 795 | ||
789 | if (ret_val < 0) { | 796 | /* Turn off Master source switch enable */ |
790 | mutex_unlock(&dev->lock); | ||
791 | return -EINVAL; | ||
792 | } | ||
793 | // Turn off Master source switch enable | ||
794 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); | 797 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); |
795 | value &= 0xFFFFFFDF; | 798 | value &= 0xFFFFFFDF; |
796 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | 799 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); |
797 | |||
798 | if (ret_val < 0) | 800 | if (ret_val < 0) |
799 | return -EINVAL; | 801 | goto error; |
800 | 802 | ||
801 | mutex_unlock(&dev->lock); | 803 | mutex_unlock(&dev->lock); |
802 | 804 | ||
803 | for (i = 0; i < _num_decoders; i++) { | 805 | for (i = 0; i < _num_decoders; i++) |
804 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); | 806 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); |
805 | } | ||
806 | 807 | ||
807 | mutex_lock(&dev->lock); | 808 | mutex_lock(&dev->lock); |
808 | 809 | ||
809 | // Select monitor as DENC A input, power up the DAC | 810 | /* Select monitor as DENC A input, power up the DAC */ |
810 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); | 811 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); |
811 | value &= 0xFF70FF70; | 812 | value &= 0xFF70FF70; |
812 | value |= 0x00090008; // set en_active | 813 | value |= 0x00090008; /* set en_active */ |
813 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); | 814 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); |
815 | if (ret_val < 0) | ||
816 | goto error; | ||
814 | 817 | ||
815 | if (ret_val < 0) { | 818 | /* enable input is VIP/656 */ |
816 | mutex_unlock(&dev->lock); | ||
817 | return -EINVAL; | ||
818 | } | ||
819 | // enable input is VIP/656 | ||
820 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); | 819 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
821 | value |= 0x00040100; // enable VIP | 820 | value |= 0x00040100; /* enable VIP */ |
822 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | 821 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
823 | 822 | ||
824 | if (ret_val < 0) { | 823 | if (ret_val < 0) |
825 | mutex_unlock(&dev->lock); | 824 | goto error; |
826 | return -EINVAL; | 825 | |
827 | } | 826 | /* select AFE clock to output mode */ |
828 | // select AFE clock to output mode | ||
829 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | 827 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); |
830 | value &= 0x83FFFFFF; | 828 | value &= 0x83FFFFFF; |
831 | ret_val = | 829 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, |
832 | cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, | 830 | value | 0x10000000); |
833 | value | 0x10000000); | 831 | if (ret_val < 0) |
832 | goto error; | ||
834 | 833 | ||
835 | if (ret_val < 0) { | 834 | /* Turn on all of the data out and control output pins. */ |
836 | mutex_unlock(&dev->lock); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | // Turn on all of the data out and control output pins. | ||
840 | value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); | 835 | value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); |
841 | value &= 0xFEF0FE00; | 836 | value &= 0xFEF0FE00; |
842 | if (_num_decoders == MAX_DECODERS) { | 837 | if (_num_decoders == MAX_DECODERS) { |
843 | // Note: The octal board does not support control pins(bit16-19). | 838 | /* |
844 | // These bits are ignored in the octal board. | 839 | * Note: The octal board does not support control pins(bit16-19) |
845 | value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface | 840 | * These bits are ignored in the octal board. |
841 | * | ||
842 | * disable VDEC A-C port, default to Mobilygen Interface | ||
843 | */ | ||
844 | value |= 0x010001F8; | ||
846 | } else { | 845 | } else { |
847 | value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface | 846 | /* disable VDEC A-C port, default to Mobilygen Interface */ |
847 | value |= 0x010F0108; | ||
848 | } | 848 | } |
849 | 849 | ||
850 | value |= 7; | 850 | value |= 7; |
851 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); | 851 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); |
852 | if (ret_val < 0) { | 852 | if (ret_val < 0) |
853 | mutex_unlock(&dev->lock); | 853 | goto error; |
854 | return -EINVAL; | ||
855 | } | ||
856 | 854 | ||
857 | mutex_unlock(&dev->lock); | 855 | mutex_unlock(&dev->lock); |
858 | 856 | ||
859 | ret_val = medusa_set_videostandard(dev); | 857 | ret_val = medusa_set_videostandard(dev); |
858 | return ret_val; | ||
860 | 859 | ||
861 | if (ret_val < 0) | 860 | error: |
862 | return -EINVAL; | 861 | mutex_unlock(&dev->lock); |
863 | 862 | return ret_val; | |
864 | return 1; | ||
865 | } | 863 | } |
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c index 6d48a1e26d1b..c842d8f3d692 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream.c +++ b/drivers/staging/cx25821/cx25821-video-upstream.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <linux/file.h> | 32 | #include <linux/file.h> |
33 | #include <linux/fcntl.h> | 33 | #include <linux/fcntl.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <asm/uaccess.h> | 35 | #include <linux/uaccess.h> |
36 | 36 | ||
37 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | 37 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); |
38 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | 38 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); |
@@ -60,9 +60,8 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | |||
60 | cdt = ch->cdt; | 60 | cdt = ch->cdt; |
61 | lines = ch->fifo_size / bpl; | 61 | lines = ch->fifo_size / bpl; |
62 | 62 | ||
63 | if (lines > 4) { | 63 | if (lines > 4) |
64 | lines = 4; | 64 | lines = 4; |
65 | } | ||
66 | 65 | ||
67 | BUG_ON(lines < 2); | 66 | BUG_ON(lines < 2); |
68 | 67 | ||
@@ -97,7 +96,7 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | |||
97 | } | 96 | } |
98 | 97 | ||
99 | static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | 98 | static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, |
100 | __le32 * rp, unsigned int offset, | 99 | __le32 *rp, unsigned int offset, |
101 | unsigned int bpl, u32 sync_line, | 100 | unsigned int bpl, u32 sync_line, |
102 | unsigned int lines, int fifo_enable, | 101 | unsigned int lines, int fifo_enable, |
103 | int field_type) | 102 | int field_type) |
@@ -108,9 +107,8 @@ static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | |||
108 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | 107 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); |
109 | 108 | ||
110 | if (USE_RISC_NOOP_VIDEO) { | 109 | if (USE_RISC_NOOP_VIDEO) { |
111 | for (i = 0; i < NUM_NO_OPS; i++) { | 110 | for (i = 0; i < NUM_NO_OPS; i++) |
112 | *(rp++) = cpu_to_le32(RISC_NOOP); | 111 | *(rp++) = cpu_to_le32(RISC_NOOP); |
113 | } | ||
114 | } | 112 | } |
115 | 113 | ||
116 | /* scan lines */ | 114 | /* scan lines */ |
@@ -140,14 +138,12 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | |||
140 | int dist_betwn_starts = bpl * 2; | 138 | int dist_betwn_starts = bpl * 2; |
141 | 139 | ||
142 | /* sync instruction */ | 140 | /* sync instruction */ |
143 | if (sync_line != NO_SYNC_LINE) { | 141 | if (sync_line != NO_SYNC_LINE) |
144 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | 142 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); |
145 | } | ||
146 | 143 | ||
147 | if (USE_RISC_NOOP_VIDEO) { | 144 | if (USE_RISC_NOOP_VIDEO) { |
148 | for (i = 0; i < NUM_NO_OPS; i++) { | 145 | for (i = 0; i < NUM_NO_OPS; i++) |
149 | *(rp++) = cpu_to_le32(RISC_NOOP); | 146 | *(rp++) = cpu_to_le32(RISC_NOOP); |
150 | } | ||
151 | } | 147 | } |
152 | 148 | ||
153 | /* scan lines */ | 149 | /* scan lines */ |
@@ -157,12 +153,13 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | |||
157 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 153 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
158 | 154 | ||
159 | if ((lines <= NTSC_FIELD_HEIGHT) | 155 | if ((lines <= NTSC_FIELD_HEIGHT) |
160 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { | 156 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) |
161 | offset += dist_betwn_starts; //to skip the other field line | 157 | /* to skip the other field line */ |
162 | } | 158 | offset += dist_betwn_starts; |
163 | 159 | ||
164 | // check if we need to enable the FIFO after the first 4 lines | 160 | /* check if we need to enable the FIFO after the first 4 lines |
165 | // For the upstream video channel, the risc engine will enable the FIFO. | 161 | * For the upstream video channel, the risc engine will enable |
162 | * the FIFO. */ | ||
166 | if (fifo_enable && line == 3) { | 163 | if (fifo_enable && line == 3) { |
167 | *(rp++) = RISC_WRITECR; | 164 | *(rp++) = RISC_WRITECR; |
168 | *(rp++) = sram_ch->dma_ctl; | 165 | *(rp++) = sram_ch->dma_ctl; |
@@ -181,7 +178,8 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
181 | { | 178 | { |
182 | __le32 *rp; | 179 | __le32 *rp; |
183 | int fifo_enable = 0; | 180 | int fifo_enable = 0; |
184 | int singlefield_lines = lines >> 1; //get line count for single field | 181 | /* get line count for single field */ |
182 | int singlefield_lines = lines >> 1; | ||
185 | int odd_num_lines = singlefield_lines; | 183 | int odd_num_lines = singlefield_lines; |
186 | int frame = 0; | 184 | int frame = 0; |
187 | int frame_size = 0; | 185 | int frame_size = 0; |
@@ -225,7 +223,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
225 | 223 | ||
226 | fifo_enable = FIFO_DISABLE; | 224 | fifo_enable = FIFO_DISABLE; |
227 | 225 | ||
228 | //Even Field | 226 | /* Even Field */ |
229 | rp = cx25821_risc_field_upstream(dev, rp, | 227 | rp = cx25821_risc_field_upstream(dev, rp, |
230 | dev->_data_buf_phys_addr + | 228 | dev->_data_buf_phys_addr + |
231 | databuf_offset, bottom_offset, | 229 | databuf_offset, bottom_offset, |
@@ -241,7 +239,9 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
241 | risc_flag = RISC_CNT_INC; | 239 | risc_flag = RISC_CNT_INC; |
242 | } | 240 | } |
243 | 241 | ||
244 | // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ | 242 | /* Loop to 2ndFrameRISC or to Start of Risc |
243 | * program & generate IRQ | ||
244 | */ | ||
245 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | 245 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); |
246 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | 246 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); |
247 | *(rp++) = cpu_to_le32(0); | 247 | *(rp++) = cpu_to_le32(0); |
@@ -258,18 +258,18 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | |||
258 | 258 | ||
259 | if (!dev->_is_running) { | 259 | if (!dev->_is_running) { |
260 | printk | 260 | printk |
261 | ("cx25821: No video file is currently running so return!\n"); | 261 | (KERN_INFO "cx25821: No video file is currently running so return!\n"); |
262 | return; | 262 | return; |
263 | } | 263 | } |
264 | //Disable RISC interrupts | 264 | /* Disable RISC interrupts */ |
265 | tmp = cx_read(sram_ch->int_msk); | 265 | tmp = cx_read(sram_ch->int_msk); |
266 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); | 266 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); |
267 | 267 | ||
268 | //Turn OFF risc and fifo enable | 268 | /* Turn OFF risc and fifo enable */ |
269 | tmp = cx_read(sram_ch->dma_ctl); | 269 | tmp = cx_read(sram_ch->dma_ctl); |
270 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); | 270 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); |
271 | 271 | ||
272 | //Clear data buffer memory | 272 | /* Clear data buffer memory */ |
273 | if (dev->_data_buf_virt_addr) | 273 | if (dev->_data_buf_virt_addr) |
274 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | 274 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); |
275 | 275 | ||
@@ -292,9 +292,8 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | |||
292 | 292 | ||
293 | void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) | 293 | void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) |
294 | { | 294 | { |
295 | if (dev->_is_running) { | 295 | if (dev->_is_running) |
296 | cx25821_stop_upstream_video_ch1(dev); | 296 | cx25821_stop_upstream_video_ch1(dev); |
297 | } | ||
298 | 297 | ||
299 | if (dev->_dma_virt_addr) { | 298 | if (dev->_dma_virt_addr) { |
300 | pci_free_consistent(dev->pci, dev->_risc_size, | 299 | pci_free_consistent(dev->pci, dev->_risc_size, |
@@ -347,19 +346,19 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
347 | 346 | ||
348 | if (IS_ERR(myfile)) { | 347 | if (IS_ERR(myfile)) { |
349 | const int open_errno = -PTR_ERR(myfile); | 348 | const int open_errno = -PTR_ERR(myfile); |
350 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | 349 | printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", |
351 | __func__, dev->_filename, open_errno); | 350 | __func__, dev->_filename, open_errno); |
352 | return PTR_ERR(myfile); | 351 | return PTR_ERR(myfile); |
353 | } else { | 352 | } else { |
354 | if (!(myfile->f_op)) { | 353 | if (!(myfile->f_op)) { |
355 | printk("%s: File has no file operations registered!", | 354 | printk(KERN_ERR "%s: File has no file operations registered!", |
356 | __func__); | 355 | __func__); |
357 | filp_close(myfile, NULL); | 356 | filp_close(myfile, NULL); |
358 | return -EIO; | 357 | return -EIO; |
359 | } | 358 | } |
360 | 359 | ||
361 | if (!myfile->f_op->read) { | 360 | if (!myfile->f_op->read) { |
362 | printk("%s: File has no READ operations registered!", | 361 | printk(KERN_ERR "%s: File has no READ operations registered!", |
363 | __func__); | 362 | __func__); |
364 | filp_close(myfile, NULL); | 363 | filp_close(myfile, NULL); |
365 | return -EIO; | 364 | return -EIO; |
@@ -412,7 +411,7 @@ static void cx25821_vidups_handler(struct work_struct *work) | |||
412 | container_of(work, struct cx25821_dev, _irq_work_entry); | 411 | container_of(work, struct cx25821_dev, _irq_work_entry); |
413 | 412 | ||
414 | if (!dev) { | 413 | if (!dev) { |
415 | printk("ERROR %s(): since container_of(work_struct) FAILED! \n", | 414 | printk(KERN_ERR "ERROR %s(): since container_of(work_struct) FAILED!\n", |
416 | __func__); | 415 | __func__); |
417 | return; | 416 | return; |
418 | } | 417 | } |
@@ -438,12 +437,12 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
438 | 437 | ||
439 | if (IS_ERR(myfile)) { | 438 | if (IS_ERR(myfile)) { |
440 | const int open_errno = -PTR_ERR(myfile); | 439 | const int open_errno = -PTR_ERR(myfile); |
441 | printk("%s(): ERROR opening file(%s) with errno = %d! \n", | 440 | printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", |
442 | __func__, dev->_filename, open_errno); | 441 | __func__, dev->_filename, open_errno); |
443 | return PTR_ERR(myfile); | 442 | return PTR_ERR(myfile); |
444 | } else { | 443 | } else { |
445 | if (!(myfile->f_op)) { | 444 | if (!(myfile->f_op)) { |
446 | printk("%s: File has no file operations registered!", | 445 | printk(KERN_ERR "%s: File has no file operations registered!", |
447 | __func__); | 446 | __func__); |
448 | filp_close(myfile, NULL); | 447 | filp_close(myfile, NULL); |
449 | return -EIO; | 448 | return -EIO; |
@@ -451,7 +450,7 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
451 | 450 | ||
452 | if (!myfile->f_op->read) { | 451 | if (!myfile->f_op->read) { |
453 | printk | 452 | printk |
454 | ("%s: File has no READ operations registered! Returning.", | 453 | (KERN_ERR "%s: File has no READ operations registered! Returning.", |
455 | __func__); | 454 | __func__); |
456 | filp_close(myfile, NULL); | 455 | filp_close(myfile, NULL); |
457 | return -EIO; | 456 | return -EIO; |
@@ -490,9 +489,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
490 | if (i > 0) | 489 | if (i > 0) |
491 | dev->_frame_count++; | 490 | dev->_frame_count++; |
492 | 491 | ||
493 | if (vfs_read_retval < line_size) { | 492 | if (vfs_read_retval < line_size) |
494 | break; | 493 | break; |
495 | } | ||
496 | } | 494 | } |
497 | 495 | ||
498 | dev->_file_status = | 496 | dev->_file_status = |
@@ -528,11 +526,11 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
528 | 526 | ||
529 | if (!dev->_dma_virt_addr) { | 527 | if (!dev->_dma_virt_addr) { |
530 | printk | 528 | printk |
531 | ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); | 529 | (KERN_ERR "cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); |
532 | return -ENOMEM; | 530 | return -ENOMEM; |
533 | } | 531 | } |
534 | 532 | ||
535 | //Clear memory at address | 533 | /* Clear memory at address */ |
536 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); | 534 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); |
537 | 535 | ||
538 | if (dev->_data_buf_virt_addr != NULL) { | 536 | if (dev->_data_buf_virt_addr != NULL) { |
@@ -540,7 +538,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
540 | dev->_data_buf_virt_addr, | 538 | dev->_data_buf_virt_addr, |
541 | dev->_data_buf_phys_addr); | 539 | dev->_data_buf_phys_addr); |
542 | } | 540 | } |
543 | //For Video Data buffer allocation | 541 | /* For Video Data buffer allocation */ |
544 | dev->_data_buf_virt_addr = | 542 | dev->_data_buf_virt_addr = |
545 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, | 543 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, |
546 | &data_dma_addr); | 544 | &data_dma_addr); |
@@ -549,30 +547,30 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
549 | 547 | ||
550 | if (!dev->_data_buf_virt_addr) { | 548 | if (!dev->_data_buf_virt_addr) { |
551 | printk | 549 | printk |
552 | ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); | 550 | (KERN_ERR "cx25821: FAILED to allocate memory for data buffer! Returning.\n"); |
553 | return -ENOMEM; | 551 | return -ENOMEM; |
554 | } | 552 | } |
555 | 553 | ||
556 | //Clear memory at address | 554 | /* Clear memory at address */ |
557 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | 555 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); |
558 | 556 | ||
559 | ret = cx25821_openfile(dev, sram_ch); | 557 | ret = cx25821_openfile(dev, sram_ch); |
560 | if (ret < 0) | 558 | if (ret < 0) |
561 | return ret; | 559 | return ret; |
562 | 560 | ||
563 | //Create RISC programs | 561 | /* Create RISC programs */ |
564 | ret = | 562 | ret = |
565 | cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, | 563 | cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, |
566 | dev->_lines_count); | 564 | dev->_lines_count); |
567 | if (ret < 0) { | 565 | if (ret < 0) { |
568 | printk(KERN_INFO | 566 | printk(KERN_INFO |
569 | "cx25821: Failed creating Video Upstream Risc programs! \n"); | 567 | "cx25821: Failed creating Video Upstream Risc programs!\n"); |
570 | goto error; | 568 | goto error; |
571 | } | 569 | } |
572 | 570 | ||
573 | return 0; | 571 | return 0; |
574 | 572 | ||
575 | error: | 573 | error: |
576 | return ret; | 574 | return ret; |
577 | } | 575 | } |
578 | 576 | ||
@@ -588,10 +586,11 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
588 | __le32 *rp; | 586 | __le32 *rp; |
589 | 587 | ||
590 | if (status & FLD_VID_SRC_RISC1) { | 588 | if (status & FLD_VID_SRC_RISC1) { |
591 | // We should only process one program per call | 589 | /* We should only process one program per call */ |
592 | u32 prog_cnt = cx_read(channel->gpcnt); | 590 | u32 prog_cnt = cx_read(channel->gpcnt); |
593 | 591 | ||
594 | //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers | 592 | /* Since we've identified our IRQ, clear our bits from the |
593 | * interrupt mask and interrupt status registers */ | ||
595 | int_msk_tmp = cx_read(channel->int_msk); | 594 | int_msk_tmp = cx_read(channel->int_msk); |
596 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | 595 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); |
597 | cx_write(channel->int_stat, _intr_msk); | 596 | cx_write(channel->int_stat, _intr_msk); |
@@ -632,7 +631,7 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
632 | FIFO_DISABLE, | 631 | FIFO_DISABLE, |
633 | ODD_FIELD); | 632 | ODD_FIELD); |
634 | 633 | ||
635 | // Jump to Even Risc program of 1st Frame | 634 | /* Jump to Even Risc program of 1st Frame */ |
636 | *(rp++) = cpu_to_le32(RISC_JUMP); | 635 | *(rp++) = cpu_to_le32(RISC_JUMP); |
637 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | 636 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); |
638 | *(rp++) = cpu_to_le32(0); | 637 | *(rp++) = cpu_to_le32(0); |
@@ -643,24 +642,24 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
643 | } else { | 642 | } else { |
644 | if (status & FLD_VID_SRC_UF) | 643 | if (status & FLD_VID_SRC_UF) |
645 | printk | 644 | printk |
646 | ("%s: Video Received Underflow Error Interrupt!\n", | 645 | (KERN_ERR "%s: Video Received Underflow Error Interrupt!\n", |
647 | __func__); | 646 | __func__); |
648 | 647 | ||
649 | if (status & FLD_VID_SRC_SYNC) | 648 | if (status & FLD_VID_SRC_SYNC) |
650 | printk("%s: Video Received Sync Error Interrupt!\n", | 649 | printk(KERN_ERR "%s: Video Received Sync Error Interrupt!\n", |
651 | __func__); | 650 | __func__); |
652 | 651 | ||
653 | if (status & FLD_VID_SRC_OPC_ERR) | 652 | if (status & FLD_VID_SRC_OPC_ERR) |
654 | printk("%s: Video Received OpCode Error Interrupt!\n", | 653 | printk(KERN_ERR "%s: Video Received OpCode Error Interrupt!\n", |
655 | __func__); | 654 | __func__); |
656 | } | 655 | } |
657 | 656 | ||
658 | if (dev->_file_status == END_OF_FILE) { | 657 | if (dev->_file_status == END_OF_FILE) { |
659 | printk("cx25821: EOF Channel 1 Framecount = %d\n", | 658 | printk(KERN_ERR "cx25821: EOF Channel 1 Framecount = %d\n", |
660 | dev->_frame_count); | 659 | dev->_frame_count); |
661 | return -1; | 660 | return -1; |
662 | } | 661 | } |
663 | //ElSE, set the interrupt mask register, re-enable irq. | 662 | /* ElSE, set the interrupt mask register, re-enable irq. */ |
664 | int_msk_tmp = cx_read(channel->int_msk); | 663 | int_msk_tmp = cx_read(channel->int_msk); |
665 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | 664 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); |
666 | 665 | ||
@@ -685,17 +684,16 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) | |||
685 | msk_stat = cx_read(sram_ch->int_mstat); | 684 | msk_stat = cx_read(sram_ch->int_mstat); |
686 | vid_status = cx_read(sram_ch->int_stat); | 685 | vid_status = cx_read(sram_ch->int_stat); |
687 | 686 | ||
688 | // Only deal with our interrupt | 687 | /* Only deal with our interrupt */ |
689 | if (vid_status) { | 688 | if (vid_status) { |
690 | handled = | 689 | handled = |
691 | cx25821_video_upstream_irq(dev, channel_num, vid_status); | 690 | cx25821_video_upstream_irq(dev, channel_num, vid_status); |
692 | } | 691 | } |
693 | 692 | ||
694 | if (handled < 0) { | 693 | if (handled < 0) |
695 | cx25821_stop_upstream_video_ch1(dev); | 694 | cx25821_stop_upstream_video_ch1(dev); |
696 | } else { | 695 | else |
697 | handled += handled; | 696 | handled += handled; |
698 | } | ||
699 | 697 | ||
700 | return IRQ_RETVAL(handled); | 698 | return IRQ_RETVAL(handled); |
701 | } | 699 | } |
@@ -714,19 +712,19 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, | |||
714 | value |= dev->_isNTSC ? 0 : 0x10; | 712 | value |= dev->_isNTSC ? 0 : 0x10; |
715 | cx_write(ch->vid_fmt_ctl, value); | 713 | cx_write(ch->vid_fmt_ctl, value); |
716 | 714 | ||
717 | // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format | 715 | /* set number of active pixels in each line. |
716 | * Default is 720 pixels in both NTSC and PAL format */ | ||
718 | cx_write(ch->vid_active_ctl1, width); | 717 | cx_write(ch->vid_active_ctl1, width); |
719 | 718 | ||
720 | num_lines = (height / 2) & 0x3FF; | 719 | num_lines = (height / 2) & 0x3FF; |
721 | odd_num_lines = num_lines; | 720 | odd_num_lines = num_lines; |
722 | 721 | ||
723 | if (dev->_isNTSC) { | 722 | if (dev->_isNTSC) |
724 | odd_num_lines += 1; | 723 | odd_num_lines += 1; |
725 | } | ||
726 | 724 | ||
727 | value = (num_lines << 16) | odd_num_lines; | 725 | value = (num_lines << 16) | odd_num_lines; |
728 | 726 | ||
729 | // set number of active lines in field 0 (top) and field 1 (bottom) | 727 | /* set number of active lines in field 0 (top) and field 1 (bottom) */ |
730 | cx_write(ch->vid_active_ctl2, value); | 728 | cx_write(ch->vid_active_ctl2, value); |
731 | 729 | ||
732 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); | 730 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); |
@@ -738,21 +736,26 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
738 | u32 tmp = 0; | 736 | u32 tmp = 0; |
739 | int err = 0; | 737 | int err = 0; |
740 | 738 | ||
741 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | 739 | /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for |
740 | * channel A-C | ||
741 | */ | ||
742 | tmp = cx_read(VID_CH_MODE_SEL); | 742 | tmp = cx_read(VID_CH_MODE_SEL); |
743 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | 743 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); |
744 | 744 | ||
745 | // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. | 745 | /* Set the physical start address of the RISC program in the initial |
746 | * program counter(IPC) member of the cmds. | ||
747 | */ | ||
746 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); | 748 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); |
747 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | 749 | /* Risc IPC High 64 bits 63-32 */ |
750 | cx_write(sram_ch->cmds_start + 4, 0); | ||
748 | 751 | ||
749 | /* reset counter */ | 752 | /* reset counter */ |
750 | cx_write(sram_ch->gpcnt_ctl, 3); | 753 | cx_write(sram_ch->gpcnt_ctl, 3); |
751 | 754 | ||
752 | // Clear our bits from the interrupt status register. | 755 | /* Clear our bits from the interrupt status register. */ |
753 | cx_write(sram_ch->int_stat, _intr_msk); | 756 | cx_write(sram_ch->int_stat, _intr_msk); |
754 | 757 | ||
755 | //Set the interrupt mask register, enable irq. | 758 | /* Set the interrupt mask register, enable irq. */ |
756 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | 759 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); |
757 | tmp = cx_read(sram_ch->int_msk); | 760 | tmp = cx_read(sram_ch->int_msk); |
758 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 761 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
@@ -766,7 +769,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
766 | goto fail_irq; | 769 | goto fail_irq; |
767 | } | 770 | } |
768 | 771 | ||
769 | // Start the DMA engine | 772 | /* Start the DMA engine */ |
770 | tmp = cx_read(sram_ch->dma_ctl); | 773 | tmp = cx_read(sram_ch->dma_ctl); |
771 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); | 774 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); |
772 | 775 | ||
@@ -775,7 +778,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
775 | 778 | ||
776 | return 0; | 779 | return 0; |
777 | 780 | ||
778 | fail_irq: | 781 | fail_irq: |
779 | cx25821_dev_unregister(dev); | 782 | cx25821_dev_unregister(dev); |
780 | return err; | 783 | return err; |
781 | } | 784 | } |
@@ -792,7 +795,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
792 | int str_length = 0; | 795 | int str_length = 0; |
793 | 796 | ||
794 | if (dev->_is_running) { | 797 | if (dev->_is_running) { |
795 | printk("Video Channel is still running so return!\n"); | 798 | printk(KERN_INFO "Video Channel is still running so return!\n"); |
796 | return 0; | 799 | return 0; |
797 | } | 800 | } |
798 | 801 | ||
@@ -804,10 +807,12 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
804 | 807 | ||
805 | if (!dev->_irq_queues) { | 808 | if (!dev->_irq_queues) { |
806 | printk | 809 | printk |
807 | ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); | 810 | (KERN_ERR "cx25821: create_singlethread_workqueue() for Video FAILED!\n"); |
808 | return -ENOMEM; | 811 | return -ENOMEM; |
809 | } | 812 | } |
810 | // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C | 813 | /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for |
814 | * channel A-C | ||
815 | */ | ||
811 | tmp = cx_read(VID_CH_MODE_SEL); | 816 | tmp = cx_read(VID_CH_MODE_SEL); |
812 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | 817 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); |
813 | 818 | ||
@@ -841,7 +846,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
841 | memcpy(dev->_filename, dev->_defaultname, str_length + 1); | 846 | memcpy(dev->_filename, dev->_defaultname, str_length + 1); |
842 | } | 847 | } |
843 | 848 | ||
844 | //Default if filename is empty string | 849 | /* Default if filename is empty string */ |
845 | if (strcmp(dev->input_filename, "") == 0) { | 850 | if (strcmp(dev->input_filename, "") == 0) { |
846 | if (dev->_isNTSC) { | 851 | if (dev->_isNTSC) { |
847 | dev->_filename = | 852 | dev->_filename = |
@@ -875,7 +880,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
875 | dev->upstream_riscbuf_size = risc_buffer_size * 2; | 880 | dev->upstream_riscbuf_size = risc_buffer_size * 2; |
876 | dev->upstream_databuf_size = data_frame_size * 2; | 881 | dev->upstream_databuf_size = data_frame_size * 2; |
877 | 882 | ||
878 | //Allocating buffers and prepare RISC program | 883 | /* Allocating buffers and prepare RISC program */ |
879 | retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); | 884 | retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); |
880 | if (retval < 0) { | 885 | if (retval < 0) { |
881 | printk(KERN_ERR | 886 | printk(KERN_ERR |
@@ -888,7 +893,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
888 | 893 | ||
889 | return 0; | 894 | return 0; |
890 | 895 | ||
891 | error: | 896 | error: |
892 | cx25821_dev_unregister(dev); | 897 | cx25821_dev_unregister(dev); |
893 | 898 | ||
894 | return err; | 899 | return err; |
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 8cd3986d2e5c..791212c1a661 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c | |||
@@ -54,34 +54,34 @@ static void init_controls(struct cx25821_dev *dev, int chan_num); | |||
54 | 54 | ||
55 | struct cx25821_fmt formats[] = { | 55 | struct cx25821_fmt formats[] = { |
56 | { | 56 | { |
57 | .name = "8 bpp, gray", | 57 | .name = "8 bpp, gray", |
58 | .fourcc = V4L2_PIX_FMT_GREY, | 58 | .fourcc = V4L2_PIX_FMT_GREY, |
59 | .depth = 8, | 59 | .depth = 8, |
60 | .flags = FORMAT_FLAGS_PACKED, | 60 | .flags = FORMAT_FLAGS_PACKED, |
61 | }, { | 61 | }, { |
62 | .name = "4:1:1, packed, Y41P", | 62 | .name = "4:1:1, packed, Y41P", |
63 | .fourcc = V4L2_PIX_FMT_Y41P, | 63 | .fourcc = V4L2_PIX_FMT_Y41P, |
64 | .depth = 12, | 64 | .depth = 12, |
65 | .flags = FORMAT_FLAGS_PACKED, | 65 | .flags = FORMAT_FLAGS_PACKED, |
66 | }, { | 66 | }, { |
67 | .name = "4:2:2, packed, YUYV", | 67 | .name = "4:2:2, packed, YUYV", |
68 | .fourcc = V4L2_PIX_FMT_YUYV, | 68 | .fourcc = V4L2_PIX_FMT_YUYV, |
69 | .depth = 16, | 69 | .depth = 16, |
70 | .flags = FORMAT_FLAGS_PACKED, | 70 | .flags = FORMAT_FLAGS_PACKED, |
71 | }, { | 71 | }, { |
72 | .name = "4:2:2, packed, UYVY", | 72 | .name = "4:2:2, packed, UYVY", |
73 | .fourcc = V4L2_PIX_FMT_UYVY, | 73 | .fourcc = V4L2_PIX_FMT_UYVY, |
74 | .depth = 16, | 74 | .depth = 16, |
75 | .flags = FORMAT_FLAGS_PACKED, | 75 | .flags = FORMAT_FLAGS_PACKED, |
76 | }, { | 76 | }, { |
77 | .name = "4:2:0, YUV", | 77 | .name = "4:2:0, YUV", |
78 | .fourcc = V4L2_PIX_FMT_YUV420, | 78 | .fourcc = V4L2_PIX_FMT_YUV420, |
79 | .depth = 12, | 79 | .depth = 12, |
80 | .flags = FORMAT_FLAGS_PACKED, | 80 | .flags = FORMAT_FLAGS_PACKED, |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | int get_format_size(void) | 84 | int cx25821_get_format_size(void) |
85 | { | 85 | { |
86 | return ARRAY_SIZE(formats); | 86 | return ARRAY_SIZE(formats); |
87 | } | 87 | } |
@@ -102,7 +102,7 @@ struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) | |||
102 | return NULL; | 102 | return NULL; |
103 | } | 103 | } |
104 | 104 | ||
105 | void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) | 105 | void cx25821_dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) |
106 | { | 106 | { |
107 | struct cx25821_buffer *buf; | 107 | struct cx25821_buffer *buf; |
108 | struct list_head *item; | 108 | struct list_head *item; |
@@ -212,7 +212,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | |||
212 | */ | 212 | */ |
213 | 213 | ||
214 | // resource management | 214 | // resource management |
215 | int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) | 215 | int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) |
216 | { | 216 | { |
217 | dprintk(1, "%s()\n", __func__); | 217 | dprintk(1, "%s()\n", __func__); |
218 | if (fh->resources & bit) | 218 | if (fh->resources & bit) |
@@ -234,17 +234,17 @@ int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) | |||
234 | return 1; | 234 | return 1; |
235 | } | 235 | } |
236 | 236 | ||
237 | int res_check(struct cx25821_fh *fh, unsigned int bit) | 237 | int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit) |
238 | { | 238 | { |
239 | return fh->resources & bit; | 239 | return fh->resources & bit; |
240 | } | 240 | } |
241 | 241 | ||
242 | int res_locked(struct cx25821_dev *dev, unsigned int bit) | 242 | int cx25821_res_locked(struct cx25821_dev *dev, unsigned int bit) |
243 | { | 243 | { |
244 | return dev->resources & bit; | 244 | return dev->resources & bit; |
245 | } | 245 | } |
246 | 246 | ||
247 | void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) | 247 | void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) |
248 | { | 248 | { |
249 | BUG_ON((fh->resources & bits) != bits); | 249 | BUG_ON((fh->resources & bits) != bits); |
250 | dprintk(1, "%s()\n", __func__); | 250 | dprintk(1, "%s()\n", __func__); |
@@ -506,7 +506,7 @@ int cx25821_video_register(struct cx25821_dev *dev, int chan_num, | |||
506 | return err; | 506 | return err; |
507 | } | 507 | } |
508 | 508 | ||
509 | int buffer_setup(struct videobuf_queue *q, unsigned int *count, | 509 | int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, |
510 | unsigned int *size) | 510 | unsigned int *size) |
511 | { | 511 | { |
512 | struct cx25821_fh *fh = q->priv_data; | 512 | struct cx25821_fh *fh = q->priv_data; |
@@ -516,13 +516,13 @@ int buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
516 | if (0 == *count) | 516 | if (0 == *count) |
517 | *count = 32; | 517 | *count = 32; |
518 | 518 | ||
519 | while (*size * *count > vid_limit * 1024 * 1024) | 519 | if (*size * *count > vid_limit * 1024 * 1024) |
520 | (*count)--; | 520 | *count = (vid_limit * 1024 * 1024) / *size; |
521 | 521 | ||
522 | return 0; | 522 | return 0; |
523 | } | 523 | } |
524 | 524 | ||
525 | int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 525 | int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
526 | enum v4l2_field field) | 526 | enum v4l2_field field) |
527 | { | 527 | { |
528 | struct cx25821_fh *fh = q->priv_data; | 528 | struct cx25821_fh *fh = q->priv_data; |
@@ -648,7 +648,7 @@ int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
648 | return rc; | 648 | return rc; |
649 | } | 649 | } |
650 | 650 | ||
651 | void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 651 | void cx25821_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) |
652 | { | 652 | { |
653 | struct cx25821_buffer *buf = | 653 | struct cx25821_buffer *buf = |
654 | container_of(vb, struct cx25821_buffer, vb); | 654 | container_of(vb, struct cx25821_buffer, vb); |
@@ -667,7 +667,7 @@ struct videobuf_queue *get_queue(struct cx25821_fh *fh) | |||
667 | } | 667 | } |
668 | } | 668 | } |
669 | 669 | ||
670 | int get_resource(struct cx25821_fh *fh, int resource) | 670 | int cx25821_get_resource(struct cx25821_fh *fh, int resource) |
671 | { | 671 | { |
672 | switch (fh->type) { | 672 | switch (fh->type) { |
673 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 673 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
@@ -678,7 +678,7 @@ int get_resource(struct cx25821_fh *fh, int resource) | |||
678 | } | 678 | } |
679 | } | 679 | } |
680 | 680 | ||
681 | int video_mmap(struct file *file, struct vm_area_struct *vma) | 681 | int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) |
682 | { | 682 | { |
683 | struct cx25821_fh *fh = file->private_data; | 683 | struct cx25821_fh *fh = file->private_data; |
684 | 684 | ||
@@ -686,7 +686,7 @@ int video_mmap(struct file *file, struct vm_area_struct *vma) | |||
686 | } | 686 | } |
687 | 687 | ||
688 | /* VIDEO IOCTLS */ | 688 | /* VIDEO IOCTLS */ |
689 | int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | 689 | int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) |
690 | { | 690 | { |
691 | struct cx25821_fh *fh = priv; | 691 | struct cx25821_fh *fh = priv; |
692 | 692 | ||
@@ -700,7 +700,7 @@ int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | |||
700 | return 0; | 700 | return 0; |
701 | } | 701 | } |
702 | 702 | ||
703 | int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | 703 | int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) |
704 | { | 704 | { |
705 | struct cx25821_fmt *fmt; | 705 | struct cx25821_fmt *fmt; |
706 | enum v4l2_field field; | 706 | enum v4l2_field field; |
@@ -746,7 +746,7 @@ int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) | |||
746 | return 0; | 746 | return 0; |
747 | } | 747 | } |
748 | 748 | ||
749 | int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) | 749 | int cx25821_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) |
750 | { | 750 | { |
751 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 751 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
752 | 752 | ||
@@ -761,7 +761,7 @@ int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) | |||
761 | return 0; | 761 | return 0; |
762 | } | 762 | } |
763 | 763 | ||
764 | int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 764 | int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
765 | struct v4l2_fmtdesc *f) | 765 | struct v4l2_fmtdesc *f) |
766 | { | 766 | { |
767 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | 767 | if (unlikely(f->index >= ARRAY_SIZE(formats))) |
@@ -774,7 +774,7 @@ int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
774 | } | 774 | } |
775 | 775 | ||
776 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 776 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
777 | int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | 777 | int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) |
778 | { | 778 | { |
779 | struct cx25821_fh *fh = priv; | 779 | struct cx25821_fh *fh = priv; |
780 | struct videobuf_queue *q; | 780 | struct videobuf_queue *q; |
@@ -801,25 +801,25 @@ int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | |||
801 | } | 801 | } |
802 | #endif | 802 | #endif |
803 | 803 | ||
804 | int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) | 804 | int cx25821_vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) |
805 | { | 805 | { |
806 | struct cx25821_fh *fh = priv; | 806 | struct cx25821_fh *fh = priv; |
807 | return videobuf_reqbufs(get_queue(fh), p); | 807 | return videobuf_reqbufs(get_queue(fh), p); |
808 | } | 808 | } |
809 | 809 | ||
810 | int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | 810 | int cx25821_vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) |
811 | { | 811 | { |
812 | struct cx25821_fh *fh = priv; | 812 | struct cx25821_fh *fh = priv; |
813 | return videobuf_querybuf(get_queue(fh), p); | 813 | return videobuf_querybuf(get_queue(fh), p); |
814 | } | 814 | } |
815 | 815 | ||
816 | int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 816 | int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
817 | { | 817 | { |
818 | struct cx25821_fh *fh = priv; | 818 | struct cx25821_fh *fh = priv; |
819 | return videobuf_qbuf(get_queue(fh), p); | 819 | return videobuf_qbuf(get_queue(fh), p); |
820 | } | 820 | } |
821 | 821 | ||
822 | int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | 822 | int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) |
823 | { | 823 | { |
824 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | 824 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; |
825 | 825 | ||
@@ -828,7 +828,7 @@ int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | |||
828 | return 0; | 828 | return 0; |
829 | } | 829 | } |
830 | 830 | ||
831 | int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio) | 831 | int cx25821_vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio) |
832 | { | 832 | { |
833 | struct cx25821_fh *fh = f; | 833 | struct cx25821_fh *fh = f; |
834 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | 834 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; |
@@ -837,7 +837,7 @@ int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio) | |||
837 | } | 837 | } |
838 | 838 | ||
839 | #ifdef TUNER_FLAG | 839 | #ifdef TUNER_FLAG |
840 | int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) | 840 | int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) |
841 | { | 841 | { |
842 | struct cx25821_fh *fh = priv; | 842 | struct cx25821_fh *fh = priv; |
843 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 843 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
@@ -846,7 +846,7 @@ int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) | |||
846 | dprintk(1, "%s()\n", __func__); | 846 | dprintk(1, "%s()\n", __func__); |
847 | 847 | ||
848 | if (fh) { | 848 | if (fh) { |
849 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 849 | err = v4l2_prio_check(&dev->prio, fh->prio); |
850 | if (0 != err) | 850 | if (0 != err) |
851 | return err; | 851 | return err; |
852 | } | 852 | } |
@@ -891,14 +891,14 @@ int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) | |||
891 | return 0; | 891 | return 0; |
892 | } | 892 | } |
893 | 893 | ||
894 | int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) | 894 | int cx25821_vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) |
895 | { | 895 | { |
896 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 896 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
897 | dprintk(1, "%s()\n", __func__); | 897 | dprintk(1, "%s()\n", __func__); |
898 | return cx25821_enum_input(dev, i); | 898 | return cx25821_enum_input(dev, i); |
899 | } | 899 | } |
900 | 900 | ||
901 | int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 901 | int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
902 | { | 902 | { |
903 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 903 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
904 | 904 | ||
@@ -907,7 +907,7 @@ int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | |||
907 | return 0; | 907 | return 0; |
908 | } | 908 | } |
909 | 909 | ||
910 | int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 910 | int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) |
911 | { | 911 | { |
912 | struct cx25821_fh *fh = priv; | 912 | struct cx25821_fh *fh = priv; |
913 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 913 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
@@ -916,7 +916,7 @@ int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
916 | dprintk(1, "%s(%d)\n", __func__, i); | 916 | dprintk(1, "%s(%d)\n", __func__, i); |
917 | 917 | ||
918 | if (fh) { | 918 | if (fh) { |
919 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 919 | err = v4l2_prio_check(&dev->prio, fh->prio); |
920 | if (0 != err) | 920 | if (0 != err) |
921 | return err; | 921 | return err; |
922 | } | 922 | } |
@@ -933,7 +933,7 @@ int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
933 | } | 933 | } |
934 | 934 | ||
935 | #ifdef TUNER_FLAG | 935 | #ifdef TUNER_FLAG |
936 | int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | 936 | int cx25821_vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) |
937 | { | 937 | { |
938 | struct cx25821_fh *fh = priv; | 938 | struct cx25821_fh *fh = priv; |
939 | struct cx25821_dev *dev = fh->dev; | 939 | struct cx25821_dev *dev = fh->dev; |
@@ -960,15 +960,14 @@ int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) | |||
960 | return 0; | 960 | return 0; |
961 | } | 961 | } |
962 | 962 | ||
963 | int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | 963 | int cx25821_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) |
964 | { | 964 | { |
965 | struct cx25821_fh *fh = priv; | 965 | struct cx25821_fh *fh = priv; |
966 | struct cx25821_dev *dev; | 966 | struct cx25821_dev *dev; |
967 | int err; | 967 | int err; |
968 | 968 | ||
969 | if (fh) { | 969 | if (fh) { |
970 | dev = fh->dev; | 970 | err = v4l2_prio_check(&dev->prio, fh->prio); |
971 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
972 | if (0 != err) | 971 | if (0 != err) |
973 | return err; | 972 | return err; |
974 | } | 973 | } |
@@ -978,7 +977,7 @@ int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) | |||
978 | #endif | 977 | #endif |
979 | 978 | ||
980 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 979 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
981 | int vidioc_g_register(struct file *file, void *fh, | 980 | int cx25821_vidioc_g_register(struct file *file, void *fh, |
982 | struct v4l2_dbg_register *reg) | 981 | struct v4l2_dbg_register *reg) |
983 | { | 982 | { |
984 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | 983 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; |
@@ -991,7 +990,7 @@ int vidioc_g_register(struct file *file, void *fh, | |||
991 | return 0; | 990 | return 0; |
992 | } | 991 | } |
993 | 992 | ||
994 | int vidioc_s_register(struct file *file, void *fh, | 993 | int cx25821_vidioc_s_register(struct file *file, void *fh, |
995 | struct v4l2_dbg_register *reg) | 994 | struct v4l2_dbg_register *reg) |
996 | { | 995 | { |
997 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | 996 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; |
@@ -1007,7 +1006,7 @@ int vidioc_s_register(struct file *file, void *fh, | |||
1007 | #endif | 1006 | #endif |
1008 | 1007 | ||
1009 | #ifdef TUNER_FLAG | 1008 | #ifdef TUNER_FLAG |
1010 | int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | 1009 | int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
1011 | { | 1010 | { |
1012 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1011 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1013 | 1012 | ||
@@ -1025,14 +1024,14 @@ int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | |||
1025 | return 0; | 1024 | return 0; |
1026 | } | 1025 | } |
1027 | 1026 | ||
1028 | int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | 1027 | int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
1029 | { | 1028 | { |
1030 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1029 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1031 | struct cx25821_fh *fh = priv; | 1030 | struct cx25821_fh *fh = priv; |
1032 | int err; | 1031 | int err; |
1033 | 1032 | ||
1034 | if (fh) { | 1033 | if (fh) { |
1035 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1034 | err = v4l2_prio_check(&dev->prio, fh->prio); |
1036 | if (0 != err) | 1035 | if (0 != err) |
1037 | return err; | 1036 | return err; |
1038 | } | 1037 | } |
@@ -1108,7 +1107,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | |||
1108 | return 0; | 1107 | return 0; |
1109 | } | 1108 | } |
1110 | 1109 | ||
1111 | int vidioc_queryctrl(struct file *file, void *priv, | 1110 | int cx25821_vidioc_queryctrl(struct file *file, void *priv, |
1112 | struct v4l2_queryctrl *qctrl) | 1111 | struct v4l2_queryctrl *qctrl) |
1113 | { | 1112 | { |
1114 | return cx25821_ctrl_query(qctrl); | 1113 | return cx25821_ctrl_query(qctrl); |
@@ -1127,7 +1126,7 @@ static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) | |||
1127 | return NULL; | 1126 | return NULL; |
1128 | } | 1127 | } |
1129 | 1128 | ||
1130 | int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) | 1129 | int cx25821_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) |
1131 | { | 1130 | { |
1132 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1131 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1133 | 1132 | ||
@@ -1216,7 +1215,7 @@ static void init_controls(struct cx25821_dev *dev, int chan_num) | |||
1216 | } | 1215 | } |
1217 | } | 1216 | } |
1218 | 1217 | ||
1219 | int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap) | 1218 | int cx25821_vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap) |
1220 | { | 1219 | { |
1221 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1220 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1222 | 1221 | ||
@@ -1233,28 +1232,28 @@ int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap) | |||
1233 | return 0; | 1232 | return 0; |
1234 | } | 1233 | } |
1235 | 1234 | ||
1236 | int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) | 1235 | int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) |
1237 | { | 1236 | { |
1238 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1237 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1239 | struct cx25821_fh *fh = priv; | 1238 | struct cx25821_fh *fh = priv; |
1240 | int err; | 1239 | int err; |
1241 | 1240 | ||
1242 | if (fh) { | 1241 | if (fh) { |
1243 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1242 | err = v4l2_prio_check(&dev->prio, fh->prio); |
1244 | if (0 != err) | 1243 | if (0 != err) |
1245 | return err; | 1244 | return err; |
1246 | } | 1245 | } |
1247 | // vidioc_s_crop not supported | 1246 | // cx25821_vidioc_s_crop not supported |
1248 | return -EINVAL; | 1247 | return -EINVAL; |
1249 | } | 1248 | } |
1250 | 1249 | ||
1251 | int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) | 1250 | int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) |
1252 | { | 1251 | { |
1253 | // vidioc_g_crop not supported | 1252 | // cx25821_vidioc_g_crop not supported |
1254 | return -EINVAL; | 1253 | return -EINVAL; |
1255 | } | 1254 | } |
1256 | 1255 | ||
1257 | int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) | 1256 | int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) |
1258 | { | 1257 | { |
1259 | // medusa does not support video standard sensing of current input | 1258 | // medusa does not support video standard sensing of current input |
1260 | *norm = CX25821_NORMS; | 1259 | *norm = CX25821_NORMS; |
@@ -1262,7 +1261,7 @@ int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) | |||
1262 | return 0; | 1261 | return 0; |
1263 | } | 1262 | } |
1264 | 1263 | ||
1265 | int is_valid_width(u32 width, v4l2_std_id tvnorm) | 1264 | int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm) |
1266 | { | 1265 | { |
1267 | if (tvnorm == V4L2_STD_PAL_BG) { | 1266 | if (tvnorm == V4L2_STD_PAL_BG) { |
1268 | if (width == 352 || width == 720) | 1267 | if (width == 352 || width == 720) |
@@ -1280,7 +1279,7 @@ int is_valid_width(u32 width, v4l2_std_id tvnorm) | |||
1280 | return 0; | 1279 | return 0; |
1281 | } | 1280 | } |
1282 | 1281 | ||
1283 | int is_valid_height(u32 height, v4l2_std_id tvnorm) | 1282 | int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm) |
1284 | { | 1283 | { |
1285 | if (tvnorm == V4L2_STD_PAL_BG) { | 1284 | if (tvnorm == V4L2_STD_PAL_BG) { |
1286 | if (height == 576 || height == 288) | 1285 | if (height == 576 || height == 288) |
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index 4417ff5d90d4..0bddc02be57d 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h | |||
@@ -101,7 +101,7 @@ extern struct cx25821_fmt formats[]; | |||
101 | extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); | 101 | extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); |
102 | extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | 102 | extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; |
103 | 103 | ||
104 | extern void dump_video_queue(struct cx25821_dev *dev, | 104 | extern void cx25821_dump_video_queue(struct cx25821_dev *dev, |
105 | struct cx25821_dmaqueue *q); | 105 | struct cx25821_dmaqueue *q); |
106 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, | 106 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, |
107 | struct cx25821_dmaqueue *q, u32 count); | 107 | struct cx25821_dmaqueue *q, u32 count); |
@@ -110,11 +110,11 @@ extern void cx25821_video_wakeup(struct cx25821_dev *dev, | |||
110 | extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); | 110 | extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, | 113 | extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, |
114 | unsigned int bit); | 114 | unsigned int bit); |
115 | extern int res_check(struct cx25821_fh *fh, unsigned int bit); | 115 | extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit); |
116 | extern int res_locked(struct cx25821_dev *dev, unsigned int bit); | 116 | extern int cx25821_res_locked(struct cx25821_dev *dev, unsigned int bit); |
117 | extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, | 117 | extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, |
118 | unsigned int bits); | 118 | unsigned int bits); |
119 | extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); | 119 | extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); |
120 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, | 120 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, |
@@ -128,67 +128,67 @@ extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); | |||
128 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); | 128 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); |
129 | extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, | 129 | extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, |
130 | struct video_device *video_template); | 130 | struct video_device *video_template); |
131 | extern int get_format_size(void); | 131 | extern int cx25821_get_format_size(void); |
132 | 132 | ||
133 | extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, | 133 | extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, |
134 | unsigned int *size); | 134 | unsigned int *size); |
135 | extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 135 | extern int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
136 | enum v4l2_field field); | 136 | enum v4l2_field field); |
137 | extern void buffer_release(struct videobuf_queue *q, | 137 | extern void cx25821_buffer_release(struct videobuf_queue *q, |
138 | struct videobuf_buffer *vb); | 138 | struct videobuf_buffer *vb); |
139 | extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); | 139 | extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); |
140 | extern int get_resource(struct cx25821_fh *fh, int resource); | 140 | extern int cx25821_get_resource(struct cx25821_fh *fh, int resource); |
141 | extern int video_mmap(struct file *file, struct vm_area_struct *vma); | 141 | extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma); |
142 | extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 142 | extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
143 | struct v4l2_format *f); | 143 | struct v4l2_format *f); |
144 | extern int vidioc_querycap(struct file *file, void *priv, | 144 | extern int cx25821_vidioc_querycap(struct file *file, void *priv, |
145 | struct v4l2_capability *cap); | 145 | struct v4l2_capability *cap); |
146 | extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 146 | extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
147 | struct v4l2_fmtdesc *f); | 147 | struct v4l2_fmtdesc *f); |
148 | extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); | 148 | extern int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); |
149 | extern int vidioc_reqbufs(struct file *file, void *priv, | 149 | extern int cx25821_vidioc_reqbufs(struct file *file, void *priv, |
150 | struct v4l2_requestbuffers *p); | 150 | struct v4l2_requestbuffers *p); |
151 | extern int vidioc_querybuf(struct file *file, void *priv, | 151 | extern int cx25821_vidioc_querybuf(struct file *file, void *priv, |
152 | struct v4l2_buffer *p); | 152 | struct v4l2_buffer *p); |
153 | extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); | 153 | extern int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); |
154 | extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms); | 154 | extern int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms); |
155 | extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); | 155 | extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); |
156 | extern int vidioc_enum_input(struct file *file, void *priv, | 156 | extern int cx25821_vidioc_enum_input(struct file *file, void *priv, |
157 | struct v4l2_input *i); | 157 | struct v4l2_input *i); |
158 | extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i); | 158 | extern int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i); |
159 | extern int vidioc_s_input(struct file *file, void *priv, unsigned int i); | 159 | extern int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i); |
160 | extern int vidioc_g_ctrl(struct file *file, void *priv, | 160 | extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv, |
161 | struct v4l2_control *ctl); | 161 | struct v4l2_control *ctl); |
162 | extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 162 | extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
163 | struct v4l2_format *f); | 163 | struct v4l2_format *f); |
164 | extern int vidioc_g_frequency(struct file *file, void *priv, | 164 | extern int cx25821_vidioc_g_frequency(struct file *file, void *priv, |
165 | struct v4l2_frequency *f); | 165 | struct v4l2_frequency *f); |
166 | extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); | 166 | extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); |
167 | extern int vidioc_s_frequency(struct file *file, void *priv, | 167 | extern int cx25821_vidioc_s_frequency(struct file *file, void *priv, |
168 | struct v4l2_frequency *f); | 168 | struct v4l2_frequency *f); |
169 | extern int vidioc_g_register(struct file *file, void *fh, | 169 | extern int cx25821_vidioc_g_register(struct file *file, void *fh, |
170 | struct v4l2_dbg_register *reg); | 170 | struct v4l2_dbg_register *reg); |
171 | extern int vidioc_s_register(struct file *file, void *fh, | 171 | extern int cx25821_vidioc_s_register(struct file *file, void *fh, |
172 | struct v4l2_dbg_register *reg); | 172 | struct v4l2_dbg_register *reg); |
173 | extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | 173 | extern int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); |
174 | extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); | 174 | extern int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); |
175 | 175 | ||
176 | extern int is_valid_width(u32 width, v4l2_std_id tvnorm); | 176 | extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm); |
177 | extern int is_valid_height(u32 height, v4l2_std_id tvnorm); | 177 | extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm); |
178 | 178 | ||
179 | extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); | 179 | extern int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); |
180 | extern int vidioc_s_priority(struct file *file, void *f, | 180 | extern int cx25821_vidioc_s_priority(struct file *file, void *f, |
181 | enum v4l2_priority prio); | 181 | enum v4l2_priority prio); |
182 | 182 | ||
183 | extern int vidioc_queryctrl(struct file *file, void *priv, | 183 | extern int cx25821_vidioc_queryctrl(struct file *file, void *priv, |
184 | struct v4l2_queryctrl *qctrl); | 184 | struct v4l2_queryctrl *qctrl); |
185 | extern int cx25821_set_control(struct cx25821_dev *dev, | 185 | extern int cx25821_set_control(struct cx25821_dev *dev, |
186 | struct v4l2_control *ctrl, int chan_num); | 186 | struct v4l2_control *ctrl, int chan_num); |
187 | 187 | ||
188 | extern int vidioc_cropcap(struct file *file, void *fh, | 188 | extern int cx25821_vidioc_cropcap(struct file *file, void *fh, |
189 | struct v4l2_cropcap *cropcap); | 189 | struct v4l2_cropcap *cropcap); |
190 | extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); | 190 | extern int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); |
191 | extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); | 191 | extern int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); |
192 | 192 | ||
193 | extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm); | 193 | extern int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm); |
194 | #endif | 194 | #endif |
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c index ad7a69129118..0be2cc15d856 100644 --- a/drivers/staging/cx25821/cx25821-video0.c +++ b/drivers/staging/cx25821/cx25821-video0.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO0)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO0)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO0)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,19 +207,19 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO0)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO0); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO0); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (fh->vidq.read_buf) { | 215 | if (fh->vidq.read_buf) { |
216 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 216 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
217 | kfree(fh->vidq.read_buf); | 217 | kfree(fh->vidq.read_buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | videobuf_mmap_free(&fh->vidq); | 220 | videobuf_mmap_free(&fh->vidq); |
221 | 221 | ||
222 | v4l2_prio_close(&dev->prio, &fh->prio); | 222 | v4l2_prio_close(&dev->prio, fh->prio); |
223 | file->private_data = NULL; | 223 | file->private_data = NULL; |
224 | kfree(fh); | 224 | kfree(fh); |
225 | 225 | ||
@@ -239,7 +239,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) { | 242 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO0)))) { |
243 | return -EBUSY; | 243 | return -EBUSY; |
244 | } | 244 | } |
245 | 245 | ||
@@ -257,11 +257,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
257 | if (i != fh->type) | 257 | if (i != fh->type) |
258 | return -EINVAL; | 258 | return -EINVAL; |
259 | 259 | ||
260 | res = get_resource(fh, RESOURCE_VIDEO0); | 260 | res = cx25821_get_resource(fh, RESOURCE_VIDEO0); |
261 | err = videobuf_streamoff(get_queue(fh)); | 261 | err = videobuf_streamoff(get_queue(fh)); |
262 | if (err < 0) | 262 | if (err < 0) |
263 | return err; | 263 | return err; |
264 | res_free(dev, fh, res); | 264 | cx25821_res_free(dev, fh, res); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -274,13 +274,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | int pix_format = PIXEL_FRMT_422; | 274 | int pix_format = PIXEL_FRMT_422; |
275 | 275 | ||
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | 281 | ||
282 | dprintk(2, "%s()\n", __func__); | 282 | dprintk(2, "%s()\n", __func__); |
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 283 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
284 | 284 | ||
285 | if (0 != err) | 285 | if (0 != err) |
286 | return err; | 286 | return err; |
@@ -289,11 +289,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
289 | fh->vidq.field = f->fmt.pix.field; | 289 | fh->vidq.field = f->fmt.pix.field; |
290 | 290 | ||
291 | // check if width and height is valid based on set standard | 291 | // check if width and height is valid based on set standard |
292 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 292 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
293 | fh->width = f->fmt.pix.width; | 293 | fh->width = f->fmt.pix.width; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 296 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
297 | fh->height = f->fmt.pix.height; | 297 | fh->height = f->fmt.pix.height; |
298 | } | 298 | } |
299 | 299 | ||
@@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | if (fh) { | 365 | if (fh) { |
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 366 | err = v4l2_prio_check(&dev->prio, fh->prio); |
367 | if (0 != err) | 367 | if (0 != err) |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
@@ -378,50 +378,50 @@ static const struct v4l2_file_operations video_fops = { | |||
378 | .release = video_release, | 378 | .release = video_release, |
379 | .read = video_read, | 379 | .read = video_read, |
380 | .poll = video_poll, | 380 | .poll = video_poll, |
381 | .mmap = video_mmap, | 381 | .mmap = cx25821_video_mmap, |
382 | .ioctl = video_ioctl2, | 382 | .ioctl = video_ioctl2, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
386 | .vidioc_querycap = vidioc_querycap, | 386 | .vidioc_querycap = cx25821_vidioc_querycap, |
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 387 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 388 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 389 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
391 | .vidioc_reqbufs = vidioc_reqbufs, | 391 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
392 | .vidioc_querybuf = vidioc_querybuf, | 392 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
393 | .vidioc_qbuf = vidioc_qbuf, | 393 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
394 | .vidioc_dqbuf = vidioc_dqbuf, | 394 | .vidioc_dqbuf = vidioc_dqbuf, |
395 | #ifdef TUNER_FLAG | 395 | #ifdef TUNER_FLAG |
396 | .vidioc_s_std = vidioc_s_std, | 396 | .vidioc_s_std = cx25821_vidioc_s_std, |
397 | .vidioc_querystd = vidioc_querystd, | 397 | .vidioc_querystd = cx25821_vidioc_querystd, |
398 | #endif | 398 | #endif |
399 | .vidioc_cropcap = vidioc_cropcap, | 399 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
400 | .vidioc_s_crop = vidioc_s_crop, | 400 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
401 | .vidioc_g_crop = vidioc_g_crop, | 401 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
402 | .vidioc_enum_input = vidioc_enum_input, | 402 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
403 | .vidioc_g_input = vidioc_g_input, | 403 | .vidioc_g_input = cx25821_vidioc_g_input, |
404 | .vidioc_s_input = vidioc_s_input, | 404 | .vidioc_s_input = cx25821_vidioc_s_input, |
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | 405 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | 406 | .vidioc_s_ctrl = vidioc_s_ctrl, |
407 | .vidioc_queryctrl = vidioc_queryctrl, | 407 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
408 | .vidioc_streamon = vidioc_streamon, | 408 | .vidioc_streamon = vidioc_streamon, |
409 | .vidioc_streamoff = vidioc_streamoff, | 409 | .vidioc_streamoff = vidioc_streamoff, |
410 | .vidioc_log_status = vidioc_log_status, | 410 | .vidioc_log_status = vidioc_log_status, |
411 | .vidioc_g_priority = vidioc_g_priority, | 411 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
412 | .vidioc_s_priority = vidioc_s_priority, | 412 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
414 | .vidiocgmbuf = vidiocgmbuf, | 414 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
415 | #endif | 415 | #endif |
416 | #ifdef TUNER_FLAG | 416 | #ifdef TUNER_FLAG |
417 | .vidioc_g_tuner = vidioc_g_tuner, | 417 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
418 | .vidioc_s_tuner = vidioc_s_tuner, | 418 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
419 | .vidioc_g_frequency = vidioc_g_frequency, | 419 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
420 | .vidioc_s_frequency = vidioc_s_frequency, | 420 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
421 | #endif | 421 | #endif |
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
423 | .vidioc_g_register = vidioc_g_register, | 423 | .vidioc_g_register = cx25821_vidioc_g_register, |
424 | .vidioc_s_register = vidioc_s_register, | 424 | .vidioc_s_register = cx25821_vidioc_s_register, |
425 | #endif | 425 | #endif |
426 | }; | 426 | }; |
427 | 427 | ||
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c index e3f3c4ac7908..b0bae627bfb1 100644 --- a/drivers/staging/cx25821/cx25821-video1.c +++ b/drivers/staging/cx25821/cx25821-video1.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO1)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO1)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO1)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO1)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,19 +207,19 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO1)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO1)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO1); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO1); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (fh->vidq.read_buf) { | 215 | if (fh->vidq.read_buf) { |
216 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 216 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
217 | kfree(fh->vidq.read_buf); | 217 | kfree(fh->vidq.read_buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | videobuf_mmap_free(&fh->vidq); | 220 | videobuf_mmap_free(&fh->vidq); |
221 | 221 | ||
222 | v4l2_prio_close(&dev->prio, &fh->prio); | 222 | v4l2_prio_close(&dev->prio, fh->prio); |
223 | file->private_data = NULL; | 223 | file->private_data = NULL; |
224 | kfree(fh); | 224 | kfree(fh); |
225 | 225 | ||
@@ -239,7 +239,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) { | 242 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO1)))) { |
243 | return -EBUSY; | 243 | return -EBUSY; |
244 | } | 244 | } |
245 | 245 | ||
@@ -257,11 +257,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
257 | if (i != fh->type) | 257 | if (i != fh->type) |
258 | return -EINVAL; | 258 | return -EINVAL; |
259 | 259 | ||
260 | res = get_resource(fh, RESOURCE_VIDEO1); | 260 | res = cx25821_get_resource(fh, RESOURCE_VIDEO1); |
261 | err = videobuf_streamoff(get_queue(fh)); | 261 | err = videobuf_streamoff(get_queue(fh)); |
262 | if (err < 0) | 262 | if (err < 0) |
263 | return err; | 263 | return err; |
264 | res_free(dev, fh, res); | 264 | cx25821_res_free(dev, fh, res); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -274,13 +274,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | int pix_format = 0; | 274 | int pix_format = 0; |
275 | 275 | ||
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | 281 | ||
282 | dprintk(2, "%s()\n", __func__); | 282 | dprintk(2, "%s()\n", __func__); |
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 283 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
284 | 284 | ||
285 | if (0 != err) | 285 | if (0 != err) |
286 | return err; | 286 | return err; |
@@ -289,11 +289,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
289 | fh->vidq.field = f->fmt.pix.field; | 289 | fh->vidq.field = f->fmt.pix.field; |
290 | 290 | ||
291 | // check if width and height is valid based on set standard | 291 | // check if width and height is valid based on set standard |
292 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 292 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
293 | fh->width = f->fmt.pix.width; | 293 | fh->width = f->fmt.pix.width; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 296 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
297 | fh->height = f->fmt.pix.height; | 297 | fh->height = f->fmt.pix.height; |
298 | } | 298 | } |
299 | 299 | ||
@@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | if (fh) { | 365 | if (fh) { |
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 366 | err = v4l2_prio_check(&dev->prio, fh->prio); |
367 | if (0 != err) | 367 | if (0 != err) |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
@@ -378,50 +378,50 @@ static const struct v4l2_file_operations video_fops = { | |||
378 | .release = video_release, | 378 | .release = video_release, |
379 | .read = video_read, | 379 | .read = video_read, |
380 | .poll = video_poll, | 380 | .poll = video_poll, |
381 | .mmap = video_mmap, | 381 | .mmap = cx25821_video_mmap, |
382 | .ioctl = video_ioctl2, | 382 | .ioctl = video_ioctl2, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
386 | .vidioc_querycap = vidioc_querycap, | 386 | .vidioc_querycap = cx25821_vidioc_querycap, |
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 387 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 388 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 389 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
391 | .vidioc_reqbufs = vidioc_reqbufs, | 391 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
392 | .vidioc_querybuf = vidioc_querybuf, | 392 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
393 | .vidioc_qbuf = vidioc_qbuf, | 393 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
394 | .vidioc_dqbuf = vidioc_dqbuf, | 394 | .vidioc_dqbuf = vidioc_dqbuf, |
395 | #ifdef TUNER_FLAG | 395 | #ifdef TUNER_FLAG |
396 | .vidioc_s_std = vidioc_s_std, | 396 | .vidioc_s_std = cx25821_vidioc_s_std, |
397 | .vidioc_querystd = vidioc_querystd, | 397 | .vidioc_querystd = cx25821_vidioc_querystd, |
398 | #endif | 398 | #endif |
399 | .vidioc_cropcap = vidioc_cropcap, | 399 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
400 | .vidioc_s_crop = vidioc_s_crop, | 400 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
401 | .vidioc_g_crop = vidioc_g_crop, | 401 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
402 | .vidioc_enum_input = vidioc_enum_input, | 402 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
403 | .vidioc_g_input = vidioc_g_input, | 403 | .vidioc_g_input = cx25821_vidioc_g_input, |
404 | .vidioc_s_input = vidioc_s_input, | 404 | .vidioc_s_input = cx25821_vidioc_s_input, |
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | 405 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | 406 | .vidioc_s_ctrl = vidioc_s_ctrl, |
407 | .vidioc_queryctrl = vidioc_queryctrl, | 407 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
408 | .vidioc_streamon = vidioc_streamon, | 408 | .vidioc_streamon = vidioc_streamon, |
409 | .vidioc_streamoff = vidioc_streamoff, | 409 | .vidioc_streamoff = vidioc_streamoff, |
410 | .vidioc_log_status = vidioc_log_status, | 410 | .vidioc_log_status = vidioc_log_status, |
411 | .vidioc_g_priority = vidioc_g_priority, | 411 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
412 | .vidioc_s_priority = vidioc_s_priority, | 412 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
414 | .vidiocgmbuf = vidiocgmbuf, | 414 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
415 | #endif | 415 | #endif |
416 | #ifdef TUNER_FLAG | 416 | #ifdef TUNER_FLAG |
417 | .vidioc_g_tuner = vidioc_g_tuner, | 417 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
418 | .vidioc_s_tuner = vidioc_s_tuner, | 418 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
419 | .vidioc_g_frequency = vidioc_g_frequency, | 419 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
420 | .vidioc_s_frequency = vidioc_s_frequency, | 420 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
421 | #endif | 421 | #endif |
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
423 | .vidioc_g_register = vidioc_g_register, | 423 | .vidioc_g_register = cx25821_vidioc_g_register, |
424 | .vidioc_s_register = vidioc_s_register, | 424 | .vidioc_s_register = cx25821_vidioc_s_register, |
425 | #endif | 425 | #endif |
426 | }; | 426 | }; |
427 | 427 | ||
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c index 36fb855a497e..400cdb80674e 100644 --- a/drivers/staging/cx25821/cx25821-video2.c +++ b/drivers/staging/cx25821/cx25821-video2.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO2)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO2)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO2)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO2)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,19 +207,19 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO2)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO2)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO2); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO2); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (fh->vidq.read_buf) { | 215 | if (fh->vidq.read_buf) { |
216 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 216 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
217 | kfree(fh->vidq.read_buf); | 217 | kfree(fh->vidq.read_buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | videobuf_mmap_free(&fh->vidq); | 220 | videobuf_mmap_free(&fh->vidq); |
221 | 221 | ||
222 | v4l2_prio_close(&dev->prio, &fh->prio); | 222 | v4l2_prio_close(&dev->prio, fh->prio); |
223 | file->private_data = NULL; | 223 | file->private_data = NULL; |
224 | kfree(fh); | 224 | kfree(fh); |
225 | 225 | ||
@@ -239,7 +239,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) { | 242 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO2)))) { |
243 | return -EBUSY; | 243 | return -EBUSY; |
244 | } | 244 | } |
245 | 245 | ||
@@ -257,11 +257,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
257 | if (i != fh->type) | 257 | if (i != fh->type) |
258 | return -EINVAL; | 258 | return -EINVAL; |
259 | 259 | ||
260 | res = get_resource(fh, RESOURCE_VIDEO2); | 260 | res = cx25821_get_resource(fh, RESOURCE_VIDEO2); |
261 | err = videobuf_streamoff(get_queue(fh)); | 261 | err = videobuf_streamoff(get_queue(fh)); |
262 | if (err < 0) | 262 | if (err < 0) |
263 | return err; | 263 | return err; |
264 | res_free(dev, fh, res); | 264 | cx25821_res_free(dev, fh, res); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -274,13 +274,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | int pix_format = 0; | 274 | int pix_format = 0; |
275 | 275 | ||
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | 281 | ||
282 | dprintk(2, "%s()\n", __func__); | 282 | dprintk(2, "%s()\n", __func__); |
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 283 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
284 | 284 | ||
285 | if (0 != err) | 285 | if (0 != err) |
286 | return err; | 286 | return err; |
@@ -289,11 +289,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
289 | fh->vidq.field = f->fmt.pix.field; | 289 | fh->vidq.field = f->fmt.pix.field; |
290 | 290 | ||
291 | // check if width and height is valid based on set standard | 291 | // check if width and height is valid based on set standard |
292 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 292 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
293 | fh->width = f->fmt.pix.width; | 293 | fh->width = f->fmt.pix.width; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 296 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
297 | fh->height = f->fmt.pix.height; | 297 | fh->height = f->fmt.pix.height; |
298 | } | 298 | } |
299 | 299 | ||
@@ -365,7 +365,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
365 | int err; | 365 | int err; |
366 | 366 | ||
367 | if (fh) { | 367 | if (fh) { |
368 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 368 | err = v4l2_prio_check(&dev->prio, fh->prio); |
369 | if (0 != err) | 369 | if (0 != err) |
370 | return err; | 370 | return err; |
371 | } | 371 | } |
@@ -380,50 +380,50 @@ static const struct v4l2_file_operations video_fops = { | |||
380 | .release = video_release, | 380 | .release = video_release, |
381 | .read = video_read, | 381 | .read = video_read, |
382 | .poll = video_poll, | 382 | .poll = video_poll, |
383 | .mmap = video_mmap, | 383 | .mmap = cx25821_video_mmap, |
384 | .ioctl = video_ioctl2, | 384 | .ioctl = video_ioctl2, |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 387 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
388 | .vidioc_querycap = vidioc_querycap, | 388 | .vidioc_querycap = cx25821_vidioc_querycap, |
389 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 389 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
390 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 390 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
391 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 391 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
392 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 392 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
393 | .vidioc_reqbufs = vidioc_reqbufs, | 393 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
394 | .vidioc_querybuf = vidioc_querybuf, | 394 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
395 | .vidioc_qbuf = vidioc_qbuf, | 395 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
396 | .vidioc_dqbuf = vidioc_dqbuf, | 396 | .vidioc_dqbuf = vidioc_dqbuf, |
397 | #ifdef TUNER_FLAG | 397 | #ifdef TUNER_FLAG |
398 | .vidioc_s_std = vidioc_s_std, | 398 | .vidioc_s_std = cx25821_vidioc_s_std, |
399 | .vidioc_querystd = vidioc_querystd, | 399 | .vidioc_querystd = cx25821_vidioc_querystd, |
400 | #endif | 400 | #endif |
401 | .vidioc_cropcap = vidioc_cropcap, | 401 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
402 | .vidioc_s_crop = vidioc_s_crop, | 402 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
403 | .vidioc_g_crop = vidioc_g_crop, | 403 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
404 | .vidioc_enum_input = vidioc_enum_input, | 404 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
405 | .vidioc_g_input = vidioc_g_input, | 405 | .vidioc_g_input = cx25821_vidioc_g_input, |
406 | .vidioc_s_input = vidioc_s_input, | 406 | .vidioc_s_input = cx25821_vidioc_s_input, |
407 | .vidioc_g_ctrl = vidioc_g_ctrl, | 407 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
408 | .vidioc_s_ctrl = vidioc_s_ctrl, | 408 | .vidioc_s_ctrl = vidioc_s_ctrl, |
409 | .vidioc_queryctrl = vidioc_queryctrl, | 409 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
410 | .vidioc_streamon = vidioc_streamon, | 410 | .vidioc_streamon = vidioc_streamon, |
411 | .vidioc_streamoff = vidioc_streamoff, | 411 | .vidioc_streamoff = vidioc_streamoff, |
412 | .vidioc_log_status = vidioc_log_status, | 412 | .vidioc_log_status = vidioc_log_status, |
413 | .vidioc_g_priority = vidioc_g_priority, | 413 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
414 | .vidioc_s_priority = vidioc_s_priority, | 414 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
415 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 415 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
416 | .vidiocgmbuf = vidiocgmbuf, | 416 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
417 | #endif | 417 | #endif |
418 | #ifdef TUNER_FLAG | 418 | #ifdef TUNER_FLAG |
419 | .vidioc_g_tuner = vidioc_g_tuner, | 419 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
420 | .vidioc_s_tuner = vidioc_s_tuner, | 420 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
421 | .vidioc_g_frequency = vidioc_g_frequency, | 421 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
422 | .vidioc_s_frequency = vidioc_s_frequency, | 422 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
423 | #endif | 423 | #endif |
424 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 424 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
425 | .vidioc_g_register = vidioc_g_register, | 425 | .vidioc_g_register = cx25821_vidioc_g_register, |
426 | .vidioc_s_register = vidioc_s_register, | 426 | .vidioc_s_register = cx25821_vidioc_s_register, |
427 | #endif | 427 | #endif |
428 | }; | 428 | }; |
429 | 429 | ||
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c index 1e0f10abdbcd..3b216ed0906e 100644 --- a/drivers/staging/cx25821/cx25821-video3.c +++ b/drivers/staging/cx25821/cx25821-video3.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO3)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO3)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO3)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO3)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,19 +207,19 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO3)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO3)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO3); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO3); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (fh->vidq.read_buf) { | 215 | if (fh->vidq.read_buf) { |
216 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 216 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
217 | kfree(fh->vidq.read_buf); | 217 | kfree(fh->vidq.read_buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | videobuf_mmap_free(&fh->vidq); | 220 | videobuf_mmap_free(&fh->vidq); |
221 | 221 | ||
222 | v4l2_prio_close(&dev->prio, &fh->prio); | 222 | v4l2_prio_close(&dev->prio, fh->prio); |
223 | file->private_data = NULL; | 223 | file->private_data = NULL; |
224 | kfree(fh); | 224 | kfree(fh); |
225 | 225 | ||
@@ -239,7 +239,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) { | 242 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO3)))) { |
243 | return -EBUSY; | 243 | return -EBUSY; |
244 | } | 244 | } |
245 | 245 | ||
@@ -257,11 +257,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
257 | if (i != fh->type) | 257 | if (i != fh->type) |
258 | return -EINVAL; | 258 | return -EINVAL; |
259 | 259 | ||
260 | res = get_resource(fh, RESOURCE_VIDEO3); | 260 | res = cx25821_get_resource(fh, RESOURCE_VIDEO3); |
261 | err = videobuf_streamoff(get_queue(fh)); | 261 | err = videobuf_streamoff(get_queue(fh)); |
262 | if (err < 0) | 262 | if (err < 0) |
263 | return err; | 263 | return err; |
264 | res_free(dev, fh, res); | 264 | cx25821_res_free(dev, fh, res); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -274,13 +274,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | int pix_format = 0; | 274 | int pix_format = 0; |
275 | 275 | ||
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | 281 | ||
282 | dprintk(2, "%s()\n", __func__); | 282 | dprintk(2, "%s()\n", __func__); |
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 283 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
284 | 284 | ||
285 | if (0 != err) | 285 | if (0 != err) |
286 | return err; | 286 | return err; |
@@ -289,11 +289,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
289 | fh->vidq.field = f->fmt.pix.field; | 289 | fh->vidq.field = f->fmt.pix.field; |
290 | 290 | ||
291 | // check if width and height is valid based on set standard | 291 | // check if width and height is valid based on set standard |
292 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 292 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
293 | fh->width = f->fmt.pix.width; | 293 | fh->width = f->fmt.pix.width; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 296 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
297 | fh->height = f->fmt.pix.height; | 297 | fh->height = f->fmt.pix.height; |
298 | } | 298 | } |
299 | 299 | ||
@@ -364,7 +364,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
364 | int err; | 364 | int err; |
365 | 365 | ||
366 | if (fh) { | 366 | if (fh) { |
367 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 367 | err = v4l2_prio_check(&dev->prio, fh->prio); |
368 | if (0 != err) | 368 | if (0 != err) |
369 | return err; | 369 | return err; |
370 | } | 370 | } |
@@ -379,50 +379,50 @@ static const struct v4l2_file_operations video_fops = { | |||
379 | .release = video_release, | 379 | .release = video_release, |
380 | .read = video_read, | 380 | .read = video_read, |
381 | .poll = video_poll, | 381 | .poll = video_poll, |
382 | .mmap = video_mmap, | 382 | .mmap = cx25821_video_mmap, |
383 | .ioctl = video_ioctl2, | 383 | .ioctl = video_ioctl2, |
384 | }; | 384 | }; |
385 | 385 | ||
386 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 386 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
387 | .vidioc_querycap = vidioc_querycap, | 387 | .vidioc_querycap = cx25821_vidioc_querycap, |
388 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 388 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
389 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 389 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
390 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 390 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
391 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 391 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
392 | .vidioc_reqbufs = vidioc_reqbufs, | 392 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
393 | .vidioc_querybuf = vidioc_querybuf, | 393 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
394 | .vidioc_qbuf = vidioc_qbuf, | 394 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
395 | .vidioc_dqbuf = vidioc_dqbuf, | 395 | .vidioc_dqbuf = vidioc_dqbuf, |
396 | #ifdef TUNER_FLAG | 396 | #ifdef TUNER_FLAG |
397 | .vidioc_s_std = vidioc_s_std, | 397 | .vidioc_s_std = cx25821_vidioc_s_std, |
398 | .vidioc_querystd = vidioc_querystd, | 398 | .vidioc_querystd = cx25821_vidioc_querystd, |
399 | #endif | 399 | #endif |
400 | .vidioc_cropcap = vidioc_cropcap, | 400 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
401 | .vidioc_s_crop = vidioc_s_crop, | 401 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
402 | .vidioc_g_crop = vidioc_g_crop, | 402 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
403 | .vidioc_enum_input = vidioc_enum_input, | 403 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
404 | .vidioc_g_input = vidioc_g_input, | 404 | .vidioc_g_input = cx25821_vidioc_g_input, |
405 | .vidioc_s_input = vidioc_s_input, | 405 | .vidioc_s_input = cx25821_vidioc_s_input, |
406 | .vidioc_g_ctrl = vidioc_g_ctrl, | 406 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
407 | .vidioc_s_ctrl = vidioc_s_ctrl, | 407 | .vidioc_s_ctrl = vidioc_s_ctrl, |
408 | .vidioc_queryctrl = vidioc_queryctrl, | 408 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
409 | .vidioc_streamon = vidioc_streamon, | 409 | .vidioc_streamon = vidioc_streamon, |
410 | .vidioc_streamoff = vidioc_streamoff, | 410 | .vidioc_streamoff = vidioc_streamoff, |
411 | .vidioc_log_status = vidioc_log_status, | 411 | .vidioc_log_status = vidioc_log_status, |
412 | .vidioc_g_priority = vidioc_g_priority, | 412 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
413 | .vidioc_s_priority = vidioc_s_priority, | 413 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
414 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 414 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
415 | .vidiocgmbuf = vidiocgmbuf, | 415 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
416 | #endif | 416 | #endif |
417 | #ifdef TUNER_FLAG | 417 | #ifdef TUNER_FLAG |
418 | .vidioc_g_tuner = vidioc_g_tuner, | 418 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
419 | .vidioc_s_tuner = vidioc_s_tuner, | 419 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
420 | .vidioc_g_frequency = vidioc_g_frequency, | 420 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
421 | .vidioc_s_frequency = vidioc_s_frequency, | 421 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
422 | #endif | 422 | #endif |
423 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 423 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
424 | .vidioc_g_register = vidioc_g_register, | 424 | .vidioc_g_register = cx25821_vidioc_g_register, |
425 | .vidioc_s_register = vidioc_s_register, | 425 | .vidioc_s_register = cx25821_vidioc_s_register, |
426 | #endif | 426 | #endif |
427 | }; | 427 | }; |
428 | 428 | ||
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c index 0cbe7a79d8c0..f7b08c51868a 100644 --- a/drivers/staging/cx25821/cx25821-video4.c +++ b/drivers/staging/cx25821/cx25821-video4.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -146,7 +146,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
146 | 146 | ||
147 | switch (fh->type) { | 147 | switch (fh->type) { |
148 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 148 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
149 | if (res_locked(fh->dev, RESOURCE_VIDEO4)) | 149 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO4)) |
150 | return -EBUSY; | 150 | return -EBUSY; |
151 | 151 | ||
152 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 152 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -164,7 +164,7 @@ static unsigned int video_poll(struct file *file, | |||
164 | struct cx25821_fh *fh = file->private_data; | 164 | struct cx25821_fh *fh = file->private_data; |
165 | struct cx25821_buffer *buf; | 165 | struct cx25821_buffer *buf; |
166 | 166 | ||
167 | if (res_check(fh, RESOURCE_VIDEO4)) { | 167 | if (cx25821_res_check(fh, RESOURCE_VIDEO4)) { |
168 | /* streaming capture */ | 168 | /* streaming capture */ |
169 | if (list_empty(&fh->vidq.stream)) | 169 | if (list_empty(&fh->vidq.stream)) |
170 | return POLLERR; | 170 | return POLLERR; |
@@ -206,19 +206,19 @@ static int video_release(struct file *file) | |||
206 | cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ | 206 | cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ |
207 | 207 | ||
208 | /* stop video capture */ | 208 | /* stop video capture */ |
209 | if (res_check(fh, RESOURCE_VIDEO4)) { | 209 | if (cx25821_res_check(fh, RESOURCE_VIDEO4)) { |
210 | videobuf_queue_cancel(&fh->vidq); | 210 | videobuf_queue_cancel(&fh->vidq); |
211 | res_free(dev, fh, RESOURCE_VIDEO4); | 211 | cx25821_res_free(dev, fh, RESOURCE_VIDEO4); |
212 | } | 212 | } |
213 | 213 | ||
214 | if (fh->vidq.read_buf) { | 214 | if (fh->vidq.read_buf) { |
215 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 215 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
216 | kfree(fh->vidq.read_buf); | 216 | kfree(fh->vidq.read_buf); |
217 | } | 217 | } |
218 | 218 | ||
219 | videobuf_mmap_free(&fh->vidq); | 219 | videobuf_mmap_free(&fh->vidq); |
220 | 220 | ||
221 | v4l2_prio_close(&dev->prio, &fh->prio); | 221 | v4l2_prio_close(&dev->prio, fh->prio); |
222 | file->private_data = NULL; | 222 | file->private_data = NULL; |
223 | kfree(fh); | 223 | kfree(fh); |
224 | 224 | ||
@@ -238,7 +238,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
238 | return -EINVAL; | 238 | return -EINVAL; |
239 | } | 239 | } |
240 | 240 | ||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) { | 241 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO4)))) { |
242 | return -EBUSY; | 242 | return -EBUSY; |
243 | } | 243 | } |
244 | 244 | ||
@@ -256,11 +256,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
256 | if (i != fh->type) | 256 | if (i != fh->type) |
257 | return -EINVAL; | 257 | return -EINVAL; |
258 | 258 | ||
259 | res = get_resource(fh, RESOURCE_VIDEO4); | 259 | res = cx25821_get_resource(fh, RESOURCE_VIDEO4); |
260 | err = videobuf_streamoff(get_queue(fh)); | 260 | err = videobuf_streamoff(get_queue(fh)); |
261 | if (err < 0) | 261 | if (err < 0) |
262 | return err; | 262 | return err; |
263 | res_free(dev, fh, res); | 263 | cx25821_res_free(dev, fh, res); |
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
@@ -274,12 +274,12 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | 274 | ||
275 | // check priority | 275 | // check priority |
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | dprintk(2, "%s()\n", __func__); | 281 | dprintk(2, "%s()\n", __func__); |
282 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 282 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
283 | 283 | ||
284 | if (0 != err) | 284 | if (0 != err) |
285 | return err; | 285 | return err; |
@@ -288,11 +288,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
288 | fh->vidq.field = f->fmt.pix.field; | 288 | fh->vidq.field = f->fmt.pix.field; |
289 | 289 | ||
290 | // check if width and height is valid based on set standard | 290 | // check if width and height is valid based on set standard |
291 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 291 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
292 | fh->width = f->fmt.pix.width; | 292 | fh->width = f->fmt.pix.width; |
293 | } | 293 | } |
294 | 294 | ||
295 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 295 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
296 | fh->height = f->fmt.pix.height; | 296 | fh->height = f->fmt.pix.height; |
297 | } | 297 | } |
298 | 298 | ||
@@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | if (fh) { | 365 | if (fh) { |
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 366 | err = v4l2_prio_check(&dev->prio, fh->prio); |
367 | if (0 != err) | 367 | if (0 != err) |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
@@ -378,50 +378,50 @@ static const struct v4l2_file_operations video_fops = { | |||
378 | .release = video_release, | 378 | .release = video_release, |
379 | .read = video_read, | 379 | .read = video_read, |
380 | .poll = video_poll, | 380 | .poll = video_poll, |
381 | .mmap = video_mmap, | 381 | .mmap = cx25821_video_mmap, |
382 | .ioctl = video_ioctl2, | 382 | .ioctl = video_ioctl2, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
386 | .vidioc_querycap = vidioc_querycap, | 386 | .vidioc_querycap = cx25821_vidioc_querycap, |
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 387 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 388 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 389 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
391 | .vidioc_reqbufs = vidioc_reqbufs, | 391 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
392 | .vidioc_querybuf = vidioc_querybuf, | 392 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
393 | .vidioc_qbuf = vidioc_qbuf, | 393 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
394 | .vidioc_dqbuf = vidioc_dqbuf, | 394 | .vidioc_dqbuf = vidioc_dqbuf, |
395 | #ifdef TUNER_FLAG | 395 | #ifdef TUNER_FLAG |
396 | .vidioc_s_std = vidioc_s_std, | 396 | .vidioc_s_std = cx25821_vidioc_s_std, |
397 | .vidioc_querystd = vidioc_querystd, | 397 | .vidioc_querystd = cx25821_vidioc_querystd, |
398 | #endif | 398 | #endif |
399 | .vidioc_cropcap = vidioc_cropcap, | 399 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
400 | .vidioc_s_crop = vidioc_s_crop, | 400 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
401 | .vidioc_g_crop = vidioc_g_crop, | 401 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
402 | .vidioc_enum_input = vidioc_enum_input, | 402 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
403 | .vidioc_g_input = vidioc_g_input, | 403 | .vidioc_g_input = cx25821_vidioc_g_input, |
404 | .vidioc_s_input = vidioc_s_input, | 404 | .vidioc_s_input = cx25821_vidioc_s_input, |
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | 405 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | 406 | .vidioc_s_ctrl = vidioc_s_ctrl, |
407 | .vidioc_queryctrl = vidioc_queryctrl, | 407 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
408 | .vidioc_streamon = vidioc_streamon, | 408 | .vidioc_streamon = vidioc_streamon, |
409 | .vidioc_streamoff = vidioc_streamoff, | 409 | .vidioc_streamoff = vidioc_streamoff, |
410 | .vidioc_log_status = vidioc_log_status, | 410 | .vidioc_log_status = vidioc_log_status, |
411 | .vidioc_g_priority = vidioc_g_priority, | 411 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
412 | .vidioc_s_priority = vidioc_s_priority, | 412 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
414 | .vidiocgmbuf = vidiocgmbuf, | 414 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
415 | #endif | 415 | #endif |
416 | #ifdef TUNER_FLAG | 416 | #ifdef TUNER_FLAG |
417 | .vidioc_g_tuner = vidioc_g_tuner, | 417 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
418 | .vidioc_s_tuner = vidioc_s_tuner, | 418 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
419 | .vidioc_g_frequency = vidioc_g_frequency, | 419 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
420 | .vidioc_s_frequency = vidioc_s_frequency, | 420 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
421 | #endif | 421 | #endif |
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
423 | .vidioc_g_register = vidioc_g_register, | 423 | .vidioc_g_register = cx25821_vidioc_g_register, |
424 | .vidioc_s_register = vidioc_s_register, | 424 | .vidioc_s_register = cx25821_vidioc_s_register, |
425 | #endif | 425 | #endif |
426 | }; | 426 | }; |
427 | 427 | ||
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c index 5dc08adc12e8..59370337b076 100644 --- a/drivers/staging/cx25821/cx25821-video5.c +++ b/drivers/staging/cx25821/cx25821-video5.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO5)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO5)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO5)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO5)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,19 +207,19 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO5)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO5)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO5); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO5); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (fh->vidq.read_buf) { | 215 | if (fh->vidq.read_buf) { |
216 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 216 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
217 | kfree(fh->vidq.read_buf); | 217 | kfree(fh->vidq.read_buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | videobuf_mmap_free(&fh->vidq); | 220 | videobuf_mmap_free(&fh->vidq); |
221 | 221 | ||
222 | v4l2_prio_close(&dev->prio, &fh->prio); | 222 | v4l2_prio_close(&dev->prio, fh->prio); |
223 | file->private_data = NULL; | 223 | file->private_data = NULL; |
224 | kfree(fh); | 224 | kfree(fh); |
225 | 225 | ||
@@ -239,7 +239,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) { | 242 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO5)))) { |
243 | return -EBUSY; | 243 | return -EBUSY; |
244 | } | 244 | } |
245 | 245 | ||
@@ -257,11 +257,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
257 | if (i != fh->type) | 257 | if (i != fh->type) |
258 | return -EINVAL; | 258 | return -EINVAL; |
259 | 259 | ||
260 | res = get_resource(fh, RESOURCE_VIDEO5); | 260 | res = cx25821_get_resource(fh, RESOURCE_VIDEO5); |
261 | err = videobuf_streamoff(get_queue(fh)); | 261 | err = videobuf_streamoff(get_queue(fh)); |
262 | if (err < 0) | 262 | if (err < 0) |
263 | return err; | 263 | return err; |
264 | res_free(dev, fh, res); | 264 | cx25821_res_free(dev, fh, res); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -274,13 +274,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
274 | int pix_format = 0; | 274 | int pix_format = 0; |
275 | 275 | ||
276 | if (fh) { | 276 | if (fh) { |
277 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 277 | err = v4l2_prio_check(&dev->prio, fh->prio); |
278 | if (0 != err) | 278 | if (0 != err) |
279 | return err; | 279 | return err; |
280 | } | 280 | } |
281 | 281 | ||
282 | dprintk(2, "%s()\n", __func__); | 282 | dprintk(2, "%s()\n", __func__); |
283 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 283 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
284 | 284 | ||
285 | if (0 != err) | 285 | if (0 != err) |
286 | return err; | 286 | return err; |
@@ -289,11 +289,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
289 | fh->vidq.field = f->fmt.pix.field; | 289 | fh->vidq.field = f->fmt.pix.field; |
290 | 290 | ||
291 | // check if width and height is valid based on set standard | 291 | // check if width and height is valid based on set standard |
292 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 292 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
293 | fh->width = f->fmt.pix.width; | 293 | fh->width = f->fmt.pix.width; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 296 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
297 | fh->height = f->fmt.pix.height; | 297 | fh->height = f->fmt.pix.height; |
298 | } | 298 | } |
299 | 299 | ||
@@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | if (fh) { | 365 | if (fh) { |
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 366 | err = v4l2_prio_check(&dev->prio, fh->prio); |
367 | if (0 != err) | 367 | if (0 != err) |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
@@ -378,50 +378,50 @@ static const struct v4l2_file_operations video_fops = { | |||
378 | .release = video_release, | 378 | .release = video_release, |
379 | .read = video_read, | 379 | .read = video_read, |
380 | .poll = video_poll, | 380 | .poll = video_poll, |
381 | .mmap = video_mmap, | 381 | .mmap = cx25821_video_mmap, |
382 | .ioctl = video_ioctl2, | 382 | .ioctl = video_ioctl2, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
386 | .vidioc_querycap = vidioc_querycap, | 386 | .vidioc_querycap = cx25821_vidioc_querycap, |
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 387 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 388 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 389 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
391 | .vidioc_reqbufs = vidioc_reqbufs, | 391 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
392 | .vidioc_querybuf = vidioc_querybuf, | 392 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
393 | .vidioc_qbuf = vidioc_qbuf, | 393 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
394 | .vidioc_dqbuf = vidioc_dqbuf, | 394 | .vidioc_dqbuf = vidioc_dqbuf, |
395 | #ifdef TUNER_FLAG | 395 | #ifdef TUNER_FLAG |
396 | .vidioc_s_std = vidioc_s_std, | 396 | .vidioc_s_std = cx25821_vidioc_s_std, |
397 | .vidioc_querystd = vidioc_querystd, | 397 | .vidioc_querystd = cx25821_vidioc_querystd, |
398 | #endif | 398 | #endif |
399 | .vidioc_cropcap = vidioc_cropcap, | 399 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
400 | .vidioc_s_crop = vidioc_s_crop, | 400 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
401 | .vidioc_g_crop = vidioc_g_crop, | 401 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
402 | .vidioc_enum_input = vidioc_enum_input, | 402 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
403 | .vidioc_g_input = vidioc_g_input, | 403 | .vidioc_g_input = cx25821_vidioc_g_input, |
404 | .vidioc_s_input = vidioc_s_input, | 404 | .vidioc_s_input = cx25821_vidioc_s_input, |
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | 405 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | 406 | .vidioc_s_ctrl = vidioc_s_ctrl, |
407 | .vidioc_queryctrl = vidioc_queryctrl, | 407 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
408 | .vidioc_streamon = vidioc_streamon, | 408 | .vidioc_streamon = vidioc_streamon, |
409 | .vidioc_streamoff = vidioc_streamoff, | 409 | .vidioc_streamoff = vidioc_streamoff, |
410 | .vidioc_log_status = vidioc_log_status, | 410 | .vidioc_log_status = vidioc_log_status, |
411 | .vidioc_g_priority = vidioc_g_priority, | 411 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
412 | .vidioc_s_priority = vidioc_s_priority, | 412 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
414 | .vidiocgmbuf = vidiocgmbuf, | 414 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
415 | #endif | 415 | #endif |
416 | #ifdef TUNER_FLAG | 416 | #ifdef TUNER_FLAG |
417 | .vidioc_g_tuner = vidioc_g_tuner, | 417 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
418 | .vidioc_s_tuner = vidioc_s_tuner, | 418 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
419 | .vidioc_g_frequency = vidioc_g_frequency, | 419 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
420 | .vidioc_s_frequency = vidioc_s_frequency, | 420 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
421 | #endif | 421 | #endif |
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
423 | .vidioc_g_register = vidioc_g_register, | 423 | .vidioc_g_register = cx25821_vidioc_g_register, |
424 | .vidioc_s_register = vidioc_s_register, | 424 | .vidioc_s_register = cx25821_vidioc_s_register, |
425 | #endif | 425 | #endif |
426 | }; | 426 | }; |
427 | 427 | ||
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c index 2938ad3ad3c5..4db2eb83d35a 100644 --- a/drivers/staging/cx25821/cx25821-video6.c +++ b/drivers/staging/cx25821/cx25821-video6.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -147,7 +147,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
147 | 147 | ||
148 | switch (fh->type) { | 148 | switch (fh->type) { |
149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 149 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
150 | if (res_locked(fh->dev, RESOURCE_VIDEO6)) | 150 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO6)) |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | 152 | ||
153 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 153 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -165,7 +165,7 @@ static unsigned int video_poll(struct file *file, | |||
165 | struct cx25821_fh *fh = file->private_data; | 165 | struct cx25821_fh *fh = file->private_data; |
166 | struct cx25821_buffer *buf; | 166 | struct cx25821_buffer *buf; |
167 | 167 | ||
168 | if (res_check(fh, RESOURCE_VIDEO6)) { | 168 | if (cx25821_res_check(fh, RESOURCE_VIDEO6)) { |
169 | /* streaming capture */ | 169 | /* streaming capture */ |
170 | if (list_empty(&fh->vidq.stream)) | 170 | if (list_empty(&fh->vidq.stream)) |
171 | return POLLERR; | 171 | return POLLERR; |
@@ -207,18 +207,18 @@ static int video_release(struct file *file) | |||
207 | cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ | 207 | cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ |
208 | 208 | ||
209 | /* stop video capture */ | 209 | /* stop video capture */ |
210 | if (res_check(fh, RESOURCE_VIDEO6)) { | 210 | if (cx25821_res_check(fh, RESOURCE_VIDEO6)) { |
211 | videobuf_queue_cancel(&fh->vidq); | 211 | videobuf_queue_cancel(&fh->vidq); |
212 | res_free(dev, fh, RESOURCE_VIDEO6); | 212 | cx25821_res_free(dev, fh, RESOURCE_VIDEO6); |
213 | } | 213 | } |
214 | if (fh->vidq.read_buf) { | 214 | if (fh->vidq.read_buf) { |
215 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 215 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
216 | kfree(fh->vidq.read_buf); | 216 | kfree(fh->vidq.read_buf); |
217 | } | 217 | } |
218 | 218 | ||
219 | videobuf_mmap_free(&fh->vidq); | 219 | videobuf_mmap_free(&fh->vidq); |
220 | 220 | ||
221 | v4l2_prio_close(&dev->prio, &fh->prio); | 221 | v4l2_prio_close(&dev->prio, fh->prio); |
222 | file->private_data = NULL; | 222 | file->private_data = NULL; |
223 | kfree(fh); | 223 | kfree(fh); |
224 | 224 | ||
@@ -238,7 +238,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
238 | return -EINVAL; | 238 | return -EINVAL; |
239 | } | 239 | } |
240 | 240 | ||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) { | 241 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO6)))) { |
242 | return -EBUSY; | 242 | return -EBUSY; |
243 | } | 243 | } |
244 | 244 | ||
@@ -256,11 +256,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
256 | if (i != fh->type) | 256 | if (i != fh->type) |
257 | return -EINVAL; | 257 | return -EINVAL; |
258 | 258 | ||
259 | res = get_resource(fh, RESOURCE_VIDEO6); | 259 | res = cx25821_get_resource(fh, RESOURCE_VIDEO6); |
260 | err = videobuf_streamoff(get_queue(fh)); | 260 | err = videobuf_streamoff(get_queue(fh)); |
261 | if (err < 0) | 261 | if (err < 0) |
262 | return err; | 262 | return err; |
263 | res_free(dev, fh, res); | 263 | cx25821_res_free(dev, fh, res); |
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
@@ -273,13 +273,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
273 | int pix_format = 0; | 273 | int pix_format = 0; |
274 | 274 | ||
275 | if (fh) { | 275 | if (fh) { |
276 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 276 | err = v4l2_prio_check(&dev->prio, fh->prio); |
277 | if (0 != err) | 277 | if (0 != err) |
278 | return err; | 278 | return err; |
279 | } | 279 | } |
280 | 280 | ||
281 | dprintk(2, "%s()\n", __func__); | 281 | dprintk(2, "%s()\n", __func__); |
282 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 282 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
283 | 283 | ||
284 | if (0 != err) | 284 | if (0 != err) |
285 | return err; | 285 | return err; |
@@ -288,11 +288,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
288 | fh->vidq.field = f->fmt.pix.field; | 288 | fh->vidq.field = f->fmt.pix.field; |
289 | 289 | ||
290 | // check if width and height is valid based on set standard | 290 | // check if width and height is valid based on set standard |
291 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 291 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
292 | fh->width = f->fmt.pix.width; | 292 | fh->width = f->fmt.pix.width; |
293 | } | 293 | } |
294 | 294 | ||
295 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 295 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
296 | fh->height = f->fmt.pix.height; | 296 | fh->height = f->fmt.pix.height; |
297 | } | 297 | } |
298 | 298 | ||
@@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | if (fh) { | 365 | if (fh) { |
366 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 366 | err = v4l2_prio_check(&dev->prio, fh->prio); |
367 | if (0 != err) | 367 | if (0 != err) |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
@@ -378,50 +378,50 @@ static const struct v4l2_file_operations video_fops = { | |||
378 | .release = video_release, | 378 | .release = video_release, |
379 | .read = video_read, | 379 | .read = video_read, |
380 | .poll = video_poll, | 380 | .poll = video_poll, |
381 | .mmap = video_mmap, | 381 | .mmap = cx25821_video_mmap, |
382 | .ioctl = video_ioctl2, | 382 | .ioctl = video_ioctl2, |
383 | }; | 383 | }; |
384 | 384 | ||
385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 385 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
386 | .vidioc_querycap = vidioc_querycap, | 386 | .vidioc_querycap = cx25821_vidioc_querycap, |
387 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 387 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
388 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 388 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
389 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 389 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 390 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
391 | .vidioc_reqbufs = vidioc_reqbufs, | 391 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
392 | .vidioc_querybuf = vidioc_querybuf, | 392 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
393 | .vidioc_qbuf = vidioc_qbuf, | 393 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
394 | .vidioc_dqbuf = vidioc_dqbuf, | 394 | .vidioc_dqbuf = vidioc_dqbuf, |
395 | #ifdef TUNER_FLAG | 395 | #ifdef TUNER_FLAG |
396 | .vidioc_s_std = vidioc_s_std, | 396 | .vidioc_s_std = cx25821_vidioc_s_std, |
397 | .vidioc_querystd = vidioc_querystd, | 397 | .vidioc_querystd = cx25821_vidioc_querystd, |
398 | #endif | 398 | #endif |
399 | .vidioc_cropcap = vidioc_cropcap, | 399 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
400 | .vidioc_s_crop = vidioc_s_crop, | 400 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
401 | .vidioc_g_crop = vidioc_g_crop, | 401 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
402 | .vidioc_enum_input = vidioc_enum_input, | 402 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
403 | .vidioc_g_input = vidioc_g_input, | 403 | .vidioc_g_input = cx25821_vidioc_g_input, |
404 | .vidioc_s_input = vidioc_s_input, | 404 | .vidioc_s_input = cx25821_vidioc_s_input, |
405 | .vidioc_g_ctrl = vidioc_g_ctrl, | 405 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
406 | .vidioc_s_ctrl = vidioc_s_ctrl, | 406 | .vidioc_s_ctrl = vidioc_s_ctrl, |
407 | .vidioc_queryctrl = vidioc_queryctrl, | 407 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
408 | .vidioc_streamon = vidioc_streamon, | 408 | .vidioc_streamon = vidioc_streamon, |
409 | .vidioc_streamoff = vidioc_streamoff, | 409 | .vidioc_streamoff = vidioc_streamoff, |
410 | .vidioc_log_status = vidioc_log_status, | 410 | .vidioc_log_status = vidioc_log_status, |
411 | .vidioc_g_priority = vidioc_g_priority, | 411 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
412 | .vidioc_s_priority = vidioc_s_priority, | 412 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 413 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
414 | .vidiocgmbuf = vidiocgmbuf, | 414 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
415 | #endif | 415 | #endif |
416 | #ifdef TUNER_FLAG | 416 | #ifdef TUNER_FLAG |
417 | .vidioc_g_tuner = vidioc_g_tuner, | 417 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
418 | .vidioc_s_tuner = vidioc_s_tuner, | 418 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
419 | .vidioc_g_frequency = vidioc_g_frequency, | 419 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
420 | .vidioc_s_frequency = vidioc_s_frequency, | 420 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
421 | #endif | 421 | #endif |
422 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
423 | .vidioc_g_register = vidioc_g_register, | 423 | .vidioc_g_register = cx25821_vidioc_g_register, |
424 | .vidioc_s_register = vidioc_s_register, | 424 | .vidioc_s_register = cx25821_vidioc_s_register, |
425 | #endif | 425 | #endif |
426 | }; | 426 | }; |
427 | 427 | ||
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c index 458e525d72af..5e4a769badad 100644 --- a/drivers/staging/cx25821/cx25821-video7.c +++ b/drivers/staging/cx25821/cx25821-video7.c | |||
@@ -85,10 +85,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | static struct videobuf_queue_ops cx25821_video_qops = { | 87 | static struct videobuf_queue_ops cx25821_video_qops = { |
88 | .buf_setup = buffer_setup, | 88 | .buf_setup = cx25821_buffer_setup, |
89 | .buf_prepare = buffer_prepare, | 89 | .buf_prepare = cx25821_buffer_prepare, |
90 | .buf_queue = buffer_queue, | 90 | .buf_queue = buffer_queue, |
91 | .buf_release = buffer_release, | 91 | .buf_release = cx25821_buffer_release, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static int video_open(struct file *file) | 94 | static int video_open(struct file *file) |
@@ -146,7 +146,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
146 | 146 | ||
147 | switch (fh->type) { | 147 | switch (fh->type) { |
148 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 148 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
149 | if (res_locked(fh->dev, RESOURCE_VIDEO7)) | 149 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO7)) |
150 | return -EBUSY; | 150 | return -EBUSY; |
151 | 151 | ||
152 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 152 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -164,7 +164,7 @@ static unsigned int video_poll(struct file *file, | |||
164 | struct cx25821_fh *fh = file->private_data; | 164 | struct cx25821_fh *fh = file->private_data; |
165 | struct cx25821_buffer *buf; | 165 | struct cx25821_buffer *buf; |
166 | 166 | ||
167 | if (res_check(fh, RESOURCE_VIDEO7)) { | 167 | if (cx25821_res_check(fh, RESOURCE_VIDEO7)) { |
168 | /* streaming capture */ | 168 | /* streaming capture */ |
169 | if (list_empty(&fh->vidq.stream)) | 169 | if (list_empty(&fh->vidq.stream)) |
170 | return POLLERR; | 170 | return POLLERR; |
@@ -206,19 +206,19 @@ static int video_release(struct file *file) | |||
206 | cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ | 206 | cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ |
207 | 207 | ||
208 | /* stop video capture */ | 208 | /* stop video capture */ |
209 | if (res_check(fh, RESOURCE_VIDEO7)) { | 209 | if (cx25821_res_check(fh, RESOURCE_VIDEO7)) { |
210 | videobuf_queue_cancel(&fh->vidq); | 210 | videobuf_queue_cancel(&fh->vidq); |
211 | res_free(dev, fh, RESOURCE_VIDEO7); | 211 | cx25821_res_free(dev, fh, RESOURCE_VIDEO7); |
212 | } | 212 | } |
213 | 213 | ||
214 | if (fh->vidq.read_buf) { | 214 | if (fh->vidq.read_buf) { |
215 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 215 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
216 | kfree(fh->vidq.read_buf); | 216 | kfree(fh->vidq.read_buf); |
217 | } | 217 | } |
218 | 218 | ||
219 | videobuf_mmap_free(&fh->vidq); | 219 | videobuf_mmap_free(&fh->vidq); |
220 | 220 | ||
221 | v4l2_prio_close(&dev->prio, &fh->prio); | 221 | v4l2_prio_close(&dev->prio, fh->prio); |
222 | file->private_data = NULL; | 222 | file->private_data = NULL; |
223 | kfree(fh); | 223 | kfree(fh); |
224 | 224 | ||
@@ -238,7 +238,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
238 | return -EINVAL; | 238 | return -EINVAL; |
239 | } | 239 | } |
240 | 240 | ||
241 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) { | 241 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO7)))) { |
242 | return -EBUSY; | 242 | return -EBUSY; |
243 | } | 243 | } |
244 | 244 | ||
@@ -256,11 +256,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
256 | if (i != fh->type) | 256 | if (i != fh->type) |
257 | return -EINVAL; | 257 | return -EINVAL; |
258 | 258 | ||
259 | res = get_resource(fh, RESOURCE_VIDEO7); | 259 | res = cx25821_get_resource(fh, RESOURCE_VIDEO7); |
260 | err = videobuf_streamoff(get_queue(fh)); | 260 | err = videobuf_streamoff(get_queue(fh)); |
261 | if (err < 0) | 261 | if (err < 0) |
262 | return err; | 262 | return err; |
263 | res_free(dev, fh, res); | 263 | cx25821_res_free(dev, fh, res); |
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
@@ -273,13 +273,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
273 | int pix_format = 0; | 273 | int pix_format = 0; |
274 | 274 | ||
275 | if (fh) { | 275 | if (fh) { |
276 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 276 | err = v4l2_prio_check(&dev->prio, fh->prio); |
277 | if (0 != err) | 277 | if (0 != err) |
278 | return err; | 278 | return err; |
279 | } | 279 | } |
280 | 280 | ||
281 | dprintk(2, "%s()\n", __func__); | 281 | dprintk(2, "%s()\n", __func__); |
282 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 282 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
283 | 283 | ||
284 | if (0 != err) | 284 | if (0 != err) |
285 | return err; | 285 | return err; |
@@ -288,11 +288,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
288 | fh->vidq.field = f->fmt.pix.field; | 288 | fh->vidq.field = f->fmt.pix.field; |
289 | 289 | ||
290 | // check if width and height is valid based on set standard | 290 | // check if width and height is valid based on set standard |
291 | if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { | 291 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { |
292 | fh->width = f->fmt.pix.width; | 292 | fh->width = f->fmt.pix.width; |
293 | } | 293 | } |
294 | 294 | ||
295 | if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { | 295 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { |
296 | fh->height = f->fmt.pix.height; | 296 | fh->height = f->fmt.pix.height; |
297 | } | 297 | } |
298 | 298 | ||
@@ -362,7 +362,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
362 | int err; | 362 | int err; |
363 | 363 | ||
364 | if (fh) { | 364 | if (fh) { |
365 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 365 | err = v4l2_prio_check(&dev->prio, fh->prio); |
366 | if (0 != err) | 366 | if (0 != err) |
367 | return err; | 367 | return err; |
368 | } | 368 | } |
@@ -377,50 +377,50 @@ static const struct v4l2_file_operations video_fops = { | |||
377 | .release = video_release, | 377 | .release = video_release, |
378 | .read = video_read, | 378 | .read = video_read, |
379 | .poll = video_poll, | 379 | .poll = video_poll, |
380 | .mmap = video_mmap, | 380 | .mmap = cx25821_video_mmap, |
381 | .ioctl = video_ioctl2, | 381 | .ioctl = video_ioctl2, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 384 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
385 | .vidioc_querycap = vidioc_querycap, | 385 | .vidioc_querycap = cx25821_vidioc_querycap, |
386 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 386 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
387 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 387 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
388 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 388 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
389 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 389 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
390 | .vidioc_reqbufs = vidioc_reqbufs, | 390 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
391 | .vidioc_querybuf = vidioc_querybuf, | 391 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
392 | .vidioc_qbuf = vidioc_qbuf, | 392 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
393 | .vidioc_dqbuf = vidioc_dqbuf, | 393 | .vidioc_dqbuf = vidioc_dqbuf, |
394 | #ifdef TUNER_FLAG | 394 | #ifdef TUNER_FLAG |
395 | .vidioc_s_std = vidioc_s_std, | 395 | .vidioc_s_std = cx25821_vidioc_s_std, |
396 | .vidioc_querystd = vidioc_querystd, | 396 | .vidioc_querystd = cx25821_vidioc_querystd, |
397 | #endif | 397 | #endif |
398 | .vidioc_cropcap = vidioc_cropcap, | 398 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
399 | .vidioc_s_crop = vidioc_s_crop, | 399 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
400 | .vidioc_g_crop = vidioc_g_crop, | 400 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
401 | .vidioc_enum_input = vidioc_enum_input, | 401 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
402 | .vidioc_g_input = vidioc_g_input, | 402 | .vidioc_g_input = cx25821_vidioc_g_input, |
403 | .vidioc_s_input = vidioc_s_input, | 403 | .vidioc_s_input = cx25821_vidioc_s_input, |
404 | .vidioc_g_ctrl = vidioc_g_ctrl, | 404 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
405 | .vidioc_s_ctrl = vidioc_s_ctrl, | 405 | .vidioc_s_ctrl = vidioc_s_ctrl, |
406 | .vidioc_queryctrl = vidioc_queryctrl, | 406 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
407 | .vidioc_streamon = vidioc_streamon, | 407 | .vidioc_streamon = vidioc_streamon, |
408 | .vidioc_streamoff = vidioc_streamoff, | 408 | .vidioc_streamoff = vidioc_streamoff, |
409 | .vidioc_log_status = vidioc_log_status, | 409 | .vidioc_log_status = vidioc_log_status, |
410 | .vidioc_g_priority = vidioc_g_priority, | 410 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
411 | .vidioc_s_priority = vidioc_s_priority, | 411 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
412 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 412 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
413 | .vidiocgmbuf = vidiocgmbuf, | 413 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
414 | #endif | 414 | #endif |
415 | #ifdef TUNER_FLAG | 415 | #ifdef TUNER_FLAG |
416 | .vidioc_g_tuner = vidioc_g_tuner, | 416 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
417 | .vidioc_s_tuner = vidioc_s_tuner, | 417 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
418 | .vidioc_g_frequency = vidioc_g_frequency, | 418 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
419 | .vidioc_s_frequency = vidioc_s_frequency, | 419 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
420 | #endif | 420 | #endif |
421 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 421 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
422 | .vidioc_g_register = vidioc_g_register, | 422 | .vidioc_g_register = cx25821_vidioc_g_register, |
423 | .vidioc_s_register = vidioc_s_register, | 423 | .vidioc_s_register = cx25821_vidioc_s_register, |
424 | #endif | 424 | #endif |
425 | }; | 425 | }; |
426 | 426 | ||
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c index 1da52b54a454..d16807d88be0 100644 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/drivers/staging/cx25821/cx25821-videoioctl.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -145,7 +145,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
145 | 145 | ||
146 | switch (fh->type) { | 146 | switch (fh->type) { |
147 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 147 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
148 | if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) | 148 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) |
149 | return -EBUSY; | 149 | return -EBUSY; |
150 | 150 | ||
151 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 151 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -163,7 +163,7 @@ static unsigned int video_poll(struct file *file, | |||
163 | struct cx25821_fh *fh = file->private_data; | 163 | struct cx25821_fh *fh = file->private_data; |
164 | struct cx25821_buffer *buf; | 164 | struct cx25821_buffer *buf; |
165 | 165 | ||
166 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | 166 | if (cx25821_res_check(fh, RESOURCE_VIDEO_IOCTL)) { |
167 | /* streaming capture */ | 167 | /* streaming capture */ |
168 | if (list_empty(&fh->vidq.stream)) | 168 | if (list_empty(&fh->vidq.stream)) |
169 | return POLLERR; | 169 | return POLLERR; |
@@ -189,19 +189,19 @@ static int video_release(struct file *file) | |||
189 | struct cx25821_dev *dev = fh->dev; | 189 | struct cx25821_dev *dev = fh->dev; |
190 | 190 | ||
191 | /* stop video capture */ | 191 | /* stop video capture */ |
192 | if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { | 192 | if (cx25821_res_check(fh, RESOURCE_VIDEO_IOCTL)) { |
193 | videobuf_queue_cancel(&fh->vidq); | 193 | videobuf_queue_cancel(&fh->vidq); |
194 | res_free(dev, fh, RESOURCE_VIDEO_IOCTL); | 194 | cx25821_res_free(dev, fh, RESOURCE_VIDEO_IOCTL); |
195 | } | 195 | } |
196 | 196 | ||
197 | if (fh->vidq.read_buf) { | 197 | if (fh->vidq.read_buf) { |
198 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 198 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
199 | kfree(fh->vidq.read_buf); | 199 | kfree(fh->vidq.read_buf); |
200 | } | 200 | } |
201 | 201 | ||
202 | videobuf_mmap_free(&fh->vidq); | 202 | videobuf_mmap_free(&fh->vidq); |
203 | 203 | ||
204 | v4l2_prio_close(&dev->prio, &fh->prio); | 204 | v4l2_prio_close(&dev->prio, fh->prio); |
205 | 205 | ||
206 | file->private_data = NULL; | 206 | file->private_data = NULL; |
207 | kfree(fh); | 207 | kfree(fh); |
@@ -222,7 +222,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
222 | return -EINVAL; | 222 | return -EINVAL; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { | 225 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { |
226 | return -EBUSY; | 226 | return -EBUSY; |
227 | } | 227 | } |
228 | 228 | ||
@@ -240,11 +240,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
240 | if (i != fh->type) | 240 | if (i != fh->type) |
241 | return -EINVAL; | 241 | return -EINVAL; |
242 | 242 | ||
243 | res = get_resource(fh, RESOURCE_VIDEO_IOCTL); | 243 | res = cx25821_get_resource(fh, RESOURCE_VIDEO_IOCTL); |
244 | err = videobuf_streamoff(get_queue(fh)); | 244 | err = videobuf_streamoff(get_queue(fh)); |
245 | if (err < 0) | 245 | if (err < 0) |
246 | return err; | 246 | return err; |
247 | res_free(dev, fh, res); | 247 | cx25821_res_free(dev, fh, res); |
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
@@ -256,13 +256,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
256 | int err; | 256 | int err; |
257 | 257 | ||
258 | if (fh) { | 258 | if (fh) { |
259 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 259 | err = v4l2_prio_check(&dev->prio, fh->prio); |
260 | if (0 != err) | 260 | if (0 != err) |
261 | return err; | 261 | return err; |
262 | } | 262 | } |
263 | 263 | ||
264 | dprintk(2, "%s()\n", __func__); | 264 | dprintk(2, "%s()\n", __func__); |
265 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 265 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
266 | 266 | ||
267 | if (0 != err) | 267 | if (0 != err) |
268 | return err; | 268 | return err; |
@@ -409,7 +409,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
409 | int err; | 409 | int err; |
410 | 410 | ||
411 | if (fh) { | 411 | if (fh) { |
412 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 412 | err = v4l2_prio_check(&dev->prio, fh->prio); |
413 | if (0 != err) | 413 | if (0 != err) |
414 | return err; | 414 | return err; |
415 | } | 415 | } |
@@ -424,50 +424,50 @@ static const struct v4l2_file_operations video_fops = { | |||
424 | .release = video_release, | 424 | .release = video_release, |
425 | .read = video_read, | 425 | .read = video_read, |
426 | .poll = video_poll, | 426 | .poll = video_poll, |
427 | .mmap = video_mmap, | 427 | .mmap = cx25821_video_mmap, |
428 | .ioctl = video_ioctl_set, | 428 | .ioctl = video_ioctl_set, |
429 | }; | 429 | }; |
430 | 430 | ||
431 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 431 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
432 | .vidioc_querycap = vidioc_querycap, | 432 | .vidioc_querycap = cx25821_vidioc_querycap, |
433 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 433 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
434 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 434 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
435 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 435 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
436 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 436 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
437 | .vidioc_reqbufs = vidioc_reqbufs, | 437 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
438 | .vidioc_querybuf = vidioc_querybuf, | 438 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
439 | .vidioc_qbuf = vidioc_qbuf, | 439 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
440 | .vidioc_dqbuf = vidioc_dqbuf, | 440 | .vidioc_dqbuf = vidioc_dqbuf, |
441 | #ifdef TUNER_FLAG | 441 | #ifdef TUNER_FLAG |
442 | .vidioc_s_std = vidioc_s_std, | 442 | .vidioc_s_std = cx25821_vidioc_s_std, |
443 | .vidioc_querystd = vidioc_querystd, | 443 | .vidioc_querystd = cx25821_vidioc_querystd, |
444 | #endif | 444 | #endif |
445 | .vidioc_cropcap = vidioc_cropcap, | 445 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
446 | .vidioc_s_crop = vidioc_s_crop, | 446 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
447 | .vidioc_g_crop = vidioc_g_crop, | 447 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
448 | .vidioc_enum_input = vidioc_enum_input, | 448 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
449 | .vidioc_g_input = vidioc_g_input, | 449 | .vidioc_g_input = cx25821_vidioc_g_input, |
450 | .vidioc_s_input = vidioc_s_input, | 450 | .vidioc_s_input = cx25821_vidioc_s_input, |
451 | .vidioc_g_ctrl = vidioc_g_ctrl, | 451 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
452 | .vidioc_s_ctrl = vidioc_s_ctrl, | 452 | .vidioc_s_ctrl = vidioc_s_ctrl, |
453 | .vidioc_queryctrl = vidioc_queryctrl, | 453 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
454 | .vidioc_streamon = vidioc_streamon, | 454 | .vidioc_streamon = vidioc_streamon, |
455 | .vidioc_streamoff = vidioc_streamoff, | 455 | .vidioc_streamoff = vidioc_streamoff, |
456 | .vidioc_log_status = vidioc_log_status, | 456 | .vidioc_log_status = vidioc_log_status, |
457 | .vidioc_g_priority = vidioc_g_priority, | 457 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
458 | .vidioc_s_priority = vidioc_s_priority, | 458 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
459 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 459 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
460 | .vidiocgmbuf = vidiocgmbuf, | 460 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
461 | #endif | 461 | #endif |
462 | #ifdef TUNER_FLAG | 462 | #ifdef TUNER_FLAG |
463 | .vidioc_g_tuner = vidioc_g_tuner, | 463 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
464 | .vidioc_s_tuner = vidioc_s_tuner, | 464 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
465 | .vidioc_g_frequency = vidioc_g_frequency, | 465 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
466 | .vidioc_s_frequency = vidioc_s_frequency, | 466 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
467 | #endif | 467 | #endif |
468 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 468 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
469 | .vidioc_g_register = vidioc_g_register, | 469 | .vidioc_g_register = cx25821_vidioc_g_register, |
470 | .vidioc_s_register = vidioc_s_register, | 470 | .vidioc_s_register = cx25821_vidioc_s_register, |
471 | #endif | 471 | #endif |
472 | }; | 472 | }; |
473 | 473 | ||
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c index b76d9f62c3d1..c746a17ccbd2 100644 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ b/drivers/staging/cx25821/cx25821-vidups10.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -143,7 +143,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
143 | 143 | ||
144 | switch (fh->type) { | 144 | switch (fh->type) { |
145 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 145 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
146 | if (res_locked(fh->dev, RESOURCE_VIDEO10)) | 146 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO10)) |
147 | return -EBUSY; | 147 | return -EBUSY; |
148 | 148 | ||
149 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 149 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -161,7 +161,7 @@ static unsigned int video_poll(struct file *file, | |||
161 | struct cx25821_fh *fh = file->private_data; | 161 | struct cx25821_fh *fh = file->private_data; |
162 | struct cx25821_buffer *buf; | 162 | struct cx25821_buffer *buf; |
163 | 163 | ||
164 | if (res_check(fh, RESOURCE_VIDEO10)) { | 164 | if (cx25821_res_check(fh, RESOURCE_VIDEO10)) { |
165 | /* streaming capture */ | 165 | /* streaming capture */ |
166 | if (list_empty(&fh->vidq.stream)) | 166 | if (list_empty(&fh->vidq.stream)) |
167 | return POLLERR; | 167 | return POLLERR; |
@@ -189,19 +189,19 @@ static int video_release(struct file *file) | |||
189 | //cx_write(channel10->dma_ctl, 0); | 189 | //cx_write(channel10->dma_ctl, 0); |
190 | 190 | ||
191 | /* stop video capture */ | 191 | /* stop video capture */ |
192 | if (res_check(fh, RESOURCE_VIDEO10)) { | 192 | if (cx25821_res_check(fh, RESOURCE_VIDEO10)) { |
193 | videobuf_queue_cancel(&fh->vidq); | 193 | videobuf_queue_cancel(&fh->vidq); |
194 | res_free(dev, fh, RESOURCE_VIDEO10); | 194 | cx25821_res_free(dev, fh, RESOURCE_VIDEO10); |
195 | } | 195 | } |
196 | 196 | ||
197 | if (fh->vidq.read_buf) { | 197 | if (fh->vidq.read_buf) { |
198 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 198 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
199 | kfree(fh->vidq.read_buf); | 199 | kfree(fh->vidq.read_buf); |
200 | } | 200 | } |
201 | 201 | ||
202 | videobuf_mmap_free(&fh->vidq); | 202 | videobuf_mmap_free(&fh->vidq); |
203 | 203 | ||
204 | v4l2_prio_close(&dev->prio, &fh->prio); | 204 | v4l2_prio_close(&dev->prio, fh->prio); |
205 | 205 | ||
206 | file->private_data = NULL; | 206 | file->private_data = NULL; |
207 | kfree(fh); | 207 | kfree(fh); |
@@ -222,7 +222,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
222 | return -EINVAL; | 222 | return -EINVAL; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) { | 225 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO10)))) { |
226 | return -EBUSY; | 226 | return -EBUSY; |
227 | } | 227 | } |
228 | 228 | ||
@@ -240,11 +240,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
240 | if (i != fh->type) | 240 | if (i != fh->type) |
241 | return -EINVAL; | 241 | return -EINVAL; |
242 | 242 | ||
243 | res = get_resource(fh, RESOURCE_VIDEO10); | 243 | res = cx25821_get_resource(fh, RESOURCE_VIDEO10); |
244 | err = videobuf_streamoff(get_queue(fh)); | 244 | err = videobuf_streamoff(get_queue(fh)); |
245 | if (err < 0) | 245 | if (err < 0) |
246 | return err; | 246 | return err; |
247 | res_free(dev, fh, res); | 247 | cx25821_res_free(dev, fh, res); |
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
@@ -299,13 +299,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
299 | int err; | 299 | int err; |
300 | 300 | ||
301 | if (fh) { | 301 | if (fh) { |
302 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 302 | err = v4l2_prio_check(&dev->prio, fh->prio); |
303 | if (0 != err) | 303 | if (0 != err) |
304 | return err; | 304 | return err; |
305 | } | 305 | } |
306 | 306 | ||
307 | dprintk(2, "%s()\n", __func__); | 307 | dprintk(2, "%s()\n", __func__); |
308 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 308 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
309 | 309 | ||
310 | if (0 != err) | 310 | if (0 != err) |
311 | return err; | 311 | return err; |
@@ -347,7 +347,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
347 | int err; | 347 | int err; |
348 | 348 | ||
349 | if (fh) { | 349 | if (fh) { |
350 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 350 | err = v4l2_prio_check(&dev->prio, fh->prio); |
351 | if (0 != err) | 351 | if (0 != err) |
352 | return err; | 352 | return err; |
353 | } | 353 | } |
@@ -362,50 +362,50 @@ static const struct v4l2_file_operations video_fops = { | |||
362 | .release = video_release, | 362 | .release = video_release, |
363 | .read = video_read, | 363 | .read = video_read, |
364 | .poll = video_poll, | 364 | .poll = video_poll, |
365 | .mmap = video_mmap, | 365 | .mmap = cx25821_video_mmap, |
366 | .ioctl = video_ioctl_upstream10, | 366 | .ioctl = video_ioctl_upstream10, |
367 | }; | 367 | }; |
368 | 368 | ||
369 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 369 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
370 | .vidioc_querycap = vidioc_querycap, | 370 | .vidioc_querycap = cx25821_vidioc_querycap, |
371 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 371 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
372 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 372 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
373 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 373 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
374 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 374 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
375 | .vidioc_reqbufs = vidioc_reqbufs, | 375 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
376 | .vidioc_querybuf = vidioc_querybuf, | 376 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
377 | .vidioc_qbuf = vidioc_qbuf, | 377 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
378 | .vidioc_dqbuf = vidioc_dqbuf, | 378 | .vidioc_dqbuf = vidioc_dqbuf, |
379 | #ifdef TUNER_FLAG | 379 | #ifdef TUNER_FLAG |
380 | .vidioc_s_std = vidioc_s_std, | 380 | .vidioc_s_std = cx25821_vidioc_s_std, |
381 | .vidioc_querystd = vidioc_querystd, | 381 | .vidioc_querystd = cx25821_vidioc_querystd, |
382 | #endif | 382 | #endif |
383 | .vidioc_cropcap = vidioc_cropcap, | 383 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
384 | .vidioc_s_crop = vidioc_s_crop, | 384 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
385 | .vidioc_g_crop = vidioc_g_crop, | 385 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
386 | .vidioc_enum_input = vidioc_enum_input, | 386 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
387 | .vidioc_g_input = vidioc_g_input, | 387 | .vidioc_g_input = cx25821_vidioc_g_input, |
388 | .vidioc_s_input = vidioc_s_input, | 388 | .vidioc_s_input = cx25821_vidioc_s_input, |
389 | .vidioc_g_ctrl = vidioc_g_ctrl, | 389 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
390 | .vidioc_s_ctrl = vidioc_s_ctrl, | 390 | .vidioc_s_ctrl = vidioc_s_ctrl, |
391 | .vidioc_queryctrl = vidioc_queryctrl, | 391 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
392 | .vidioc_streamon = vidioc_streamon, | 392 | .vidioc_streamon = vidioc_streamon, |
393 | .vidioc_streamoff = vidioc_streamoff, | 393 | .vidioc_streamoff = vidioc_streamoff, |
394 | .vidioc_log_status = vidioc_log_status, | 394 | .vidioc_log_status = vidioc_log_status, |
395 | .vidioc_g_priority = vidioc_g_priority, | 395 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
396 | .vidioc_s_priority = vidioc_s_priority, | 396 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
397 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 397 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
398 | .vidiocgmbuf = vidiocgmbuf, | 398 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
399 | #endif | 399 | #endif |
400 | #ifdef TUNER_FLAG | 400 | #ifdef TUNER_FLAG |
401 | .vidioc_g_tuner = vidioc_g_tuner, | 401 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
402 | .vidioc_s_tuner = vidioc_s_tuner, | 402 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
403 | .vidioc_g_frequency = vidioc_g_frequency, | 403 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
404 | .vidioc_s_frequency = vidioc_s_frequency, | 404 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
405 | #endif | 405 | #endif |
406 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 406 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
407 | .vidioc_g_register = vidioc_g_register, | 407 | .vidioc_g_register = cx25821_vidioc_g_register, |
408 | .vidioc_s_register = vidioc_s_register, | 408 | .vidioc_s_register = cx25821_vidioc_s_register, |
409 | #endif | 409 | #endif |
410 | }; | 410 | }; |
411 | 411 | ||
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c index 1580da3b29aa..466e0f34ae34 100644 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ b/drivers/staging/cx25821/cx25821-vidups9.c | |||
@@ -86,10 +86,10 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | static struct videobuf_queue_ops cx25821_video_qops = { | 88 | static struct videobuf_queue_ops cx25821_video_qops = { |
89 | .buf_setup = buffer_setup, | 89 | .buf_setup = cx25821_buffer_setup, |
90 | .buf_prepare = buffer_prepare, | 90 | .buf_prepare = cx25821_buffer_prepare, |
91 | .buf_queue = buffer_queue, | 91 | .buf_queue = buffer_queue, |
92 | .buf_release = buffer_release, | 92 | .buf_release = cx25821_buffer_release, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static int video_open(struct file *file) | 95 | static int video_open(struct file *file) |
@@ -143,7 +143,7 @@ static ssize_t video_read(struct file *file, char __user * data, size_t count, | |||
143 | 143 | ||
144 | switch (fh->type) { | 144 | switch (fh->type) { |
145 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 145 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
146 | if (res_locked(fh->dev, RESOURCE_VIDEO9)) | 146 | if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO9)) |
147 | return -EBUSY; | 147 | return -EBUSY; |
148 | 148 | ||
149 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 149 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
@@ -161,7 +161,7 @@ static unsigned int video_poll(struct file *file, | |||
161 | struct cx25821_fh *fh = file->private_data; | 161 | struct cx25821_fh *fh = file->private_data; |
162 | struct cx25821_buffer *buf; | 162 | struct cx25821_buffer *buf; |
163 | 163 | ||
164 | if (res_check(fh, RESOURCE_VIDEO9)) { | 164 | if (cx25821_res_check(fh, RESOURCE_VIDEO9)) { |
165 | /* streaming capture */ | 165 | /* streaming capture */ |
166 | if (list_empty(&fh->vidq.stream)) | 166 | if (list_empty(&fh->vidq.stream)) |
167 | return POLLERR; | 167 | return POLLERR; |
@@ -189,19 +189,19 @@ static int video_release(struct file *file) | |||
189 | //cx_write(channel9->dma_ctl, 0); | 189 | //cx_write(channel9->dma_ctl, 0); |
190 | 190 | ||
191 | /* stop video capture */ | 191 | /* stop video capture */ |
192 | if (res_check(fh, RESOURCE_VIDEO9)) { | 192 | if (cx25821_res_check(fh, RESOURCE_VIDEO9)) { |
193 | videobuf_queue_cancel(&fh->vidq); | 193 | videobuf_queue_cancel(&fh->vidq); |
194 | res_free(dev, fh, RESOURCE_VIDEO9); | 194 | cx25821_res_free(dev, fh, RESOURCE_VIDEO9); |
195 | } | 195 | } |
196 | 196 | ||
197 | if (fh->vidq.read_buf) { | 197 | if (fh->vidq.read_buf) { |
198 | buffer_release(&fh->vidq, fh->vidq.read_buf); | 198 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
199 | kfree(fh->vidq.read_buf); | 199 | kfree(fh->vidq.read_buf); |
200 | } | 200 | } |
201 | 201 | ||
202 | videobuf_mmap_free(&fh->vidq); | 202 | videobuf_mmap_free(&fh->vidq); |
203 | 203 | ||
204 | v4l2_prio_close(&dev->prio, &fh->prio); | 204 | v4l2_prio_close(&dev->prio, fh->prio); |
205 | 205 | ||
206 | file->private_data = NULL; | 206 | file->private_data = NULL; |
207 | kfree(fh); | 207 | kfree(fh); |
@@ -222,7 +222,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
222 | return -EINVAL; | 222 | return -EINVAL; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) { | 225 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO9)))) { |
226 | return -EBUSY; | 226 | return -EBUSY; |
227 | } | 227 | } |
228 | 228 | ||
@@ -240,11 +240,11 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
240 | if (i != fh->type) | 240 | if (i != fh->type) |
241 | return -EINVAL; | 241 | return -EINVAL; |
242 | 242 | ||
243 | res = get_resource(fh, RESOURCE_VIDEO9); | 243 | res = cx25821_get_resource(fh, RESOURCE_VIDEO9); |
244 | err = videobuf_streamoff(get_queue(fh)); | 244 | err = videobuf_streamoff(get_queue(fh)); |
245 | if (err < 0) | 245 | if (err < 0) |
246 | return err; | 246 | return err; |
247 | res_free(dev, fh, res); | 247 | cx25821_res_free(dev, fh, res); |
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
@@ -299,13 +299,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
299 | int err; | 299 | int err; |
300 | 300 | ||
301 | if (fh) { | 301 | if (fh) { |
302 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 302 | err = v4l2_prio_check(&dev->prio, fh->prio); |
303 | if (0 != err) | 303 | if (0 != err) |
304 | return err; | 304 | return err; |
305 | } | 305 | } |
306 | 306 | ||
307 | dprintk(2, "%s()\n", __func__); | 307 | dprintk(2, "%s()\n", __func__); |
308 | err = vidioc_try_fmt_vid_cap(file, priv, f); | 308 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
309 | 309 | ||
310 | if (0 != err) | 310 | if (0 != err) |
311 | return err; | 311 | return err; |
@@ -345,7 +345,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
345 | struct cx25821_fh *fh = priv; | 345 | struct cx25821_fh *fh = priv; |
346 | int err; | 346 | int err; |
347 | if (fh) { | 347 | if (fh) { |
348 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 348 | err = v4l2_prio_check(&dev->prio, fh->prio); |
349 | if (0 != err) | 349 | if (0 != err) |
350 | return err; | 350 | return err; |
351 | } | 351 | } |
@@ -360,50 +360,50 @@ static const struct v4l2_file_operations video_fops = { | |||
360 | .release = video_release, | 360 | .release = video_release, |
361 | .read = video_read, | 361 | .read = video_read, |
362 | .poll = video_poll, | 362 | .poll = video_poll, |
363 | .mmap = video_mmap, | 363 | .mmap = cx25821_video_mmap, |
364 | .ioctl = video_ioctl_upstream9, | 364 | .ioctl = video_ioctl_upstream9, |
365 | }; | 365 | }; |
366 | 366 | ||
367 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 367 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
368 | .vidioc_querycap = vidioc_querycap, | 368 | .vidioc_querycap = cx25821_vidioc_querycap, |
369 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 369 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
370 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 370 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
371 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 371 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
372 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 372 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
373 | .vidioc_reqbufs = vidioc_reqbufs, | 373 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
374 | .vidioc_querybuf = vidioc_querybuf, | 374 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
375 | .vidioc_qbuf = vidioc_qbuf, | 375 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
376 | .vidioc_dqbuf = vidioc_dqbuf, | 376 | .vidioc_dqbuf = vidioc_dqbuf, |
377 | #ifdef TUNER_FLAG | 377 | #ifdef TUNER_FLAG |
378 | .vidioc_s_std = vidioc_s_std, | 378 | .vidioc_s_std = cx25821_vidioc_s_std, |
379 | .vidioc_querystd = vidioc_querystd, | 379 | .vidioc_querystd = cx25821_vidioc_querystd, |
380 | #endif | 380 | #endif |
381 | .vidioc_cropcap = vidioc_cropcap, | 381 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
382 | .vidioc_s_crop = vidioc_s_crop, | 382 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
383 | .vidioc_g_crop = vidioc_g_crop, | 383 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
384 | .vidioc_enum_input = vidioc_enum_input, | 384 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
385 | .vidioc_g_input = vidioc_g_input, | 385 | .vidioc_g_input = cx25821_vidioc_g_input, |
386 | .vidioc_s_input = vidioc_s_input, | 386 | .vidioc_s_input = cx25821_vidioc_s_input, |
387 | .vidioc_g_ctrl = vidioc_g_ctrl, | 387 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
388 | .vidioc_s_ctrl = vidioc_s_ctrl, | 388 | .vidioc_s_ctrl = vidioc_s_ctrl, |
389 | .vidioc_queryctrl = vidioc_queryctrl, | 389 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
390 | .vidioc_streamon = vidioc_streamon, | 390 | .vidioc_streamon = vidioc_streamon, |
391 | .vidioc_streamoff = vidioc_streamoff, | 391 | .vidioc_streamoff = vidioc_streamoff, |
392 | .vidioc_log_status = vidioc_log_status, | 392 | .vidioc_log_status = vidioc_log_status, |
393 | .vidioc_g_priority = vidioc_g_priority, | 393 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
394 | .vidioc_s_priority = vidioc_s_priority, | 394 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
395 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 395 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
396 | .vidiocgmbuf = vidiocgmbuf, | 396 | .vidiocgmbuf = cx25821_vidiocgmbuf, |
397 | #endif | 397 | #endif |
398 | #ifdef TUNER_FLAG | 398 | #ifdef TUNER_FLAG |
399 | .vidioc_g_tuner = vidioc_g_tuner, | 399 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
400 | .vidioc_s_tuner = vidioc_s_tuner, | 400 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
401 | .vidioc_g_frequency = vidioc_g_frequency, | 401 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
402 | .vidioc_s_frequency = vidioc_s_frequency, | 402 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
403 | #endif | 403 | #endif |
404 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 404 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
405 | .vidioc_g_register = vidioc_g_register, | 405 | .vidioc_g_register = cx25821_vidioc_g_register, |
406 | .vidioc_s_register = vidioc_s_register, | 406 | .vidioc_s_register = cx25821_vidioc_s_register, |
407 | #endif | 407 | #endif |
408 | }; | 408 | }; |
409 | 409 | ||
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig new file mode 100644 index 000000000000..5fe759cc2ee9 --- /dev/null +++ b/drivers/staging/tm6000/Kconfig | |||
@@ -0,0 +1,32 @@ | |||
1 | config VIDEO_TM6000 | ||
2 | tristate "TV Master TM5600/6000/6010 driver" | ||
3 | depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL | ||
4 | select VIDEO_TUNER | ||
5 | select TUNER_XC2028 | ||
6 | select VIDEOBUF_VMALLOC | ||
7 | help | ||
8 | Support for TM5600/TM6000/TM6010 USB Device | ||
9 | |||
10 | Since these cards have no MPEG decoder onboard, they transmit | ||
11 | only compressed MPEG data over the usb bus, so you need | ||
12 | an external software decoder to watch TV on your computer. | ||
13 | |||
14 | Say Y if you own such a device and want to use it. | ||
15 | |||
16 | config VIDEO_TM6000_ALSA | ||
17 | tristate "TV Master TM5600/6000/6010 audio support" | ||
18 | depends on VIDEO_TM6000 && SND && EXPERIMENTAL | ||
19 | select SND_PCM | ||
20 | ---help--- | ||
21 | This is a video4linux driver for direct (DMA) audio for | ||
22 | TM5600/TM6000/TM6010 USB Devices. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called tm6000-alsa. | ||
26 | |||
27 | config VIDEO_TM6000_DVB | ||
28 | bool "DVB Support for tm6000 based TV cards" | ||
29 | depends on VIDEO_TM6000 && DVB_CORE && EXPERIMENTAL | ||
30 | select DVB_ZL10353 | ||
31 | ---help--- | ||
32 | This adds support for DVB cards based on the tm5600/tm6000 chip. | ||
diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile new file mode 100644 index 000000000000..93370fccc073 --- /dev/null +++ b/drivers/staging/tm6000/Makefile | |||
@@ -0,0 +1,17 @@ | |||
1 | tm6000-objs := tm6000-cards.o \ | ||
2 | tm6000-core.o \ | ||
3 | tm6000-i2c.o \ | ||
4 | tm6000-video.o \ | ||
5 | tm6000-stds.o | ||
6 | |||
7 | ifeq ($(CONFIG_VIDEO_TM6000_DVB),y) | ||
8 | tm6000-objs += tm6000-dvb.o | ||
9 | endif | ||
10 | |||
11 | obj-$(CONFIG_VIDEO_TM6000) += tm6000.o | ||
12 | obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o | ||
13 | |||
14 | EXTRA_CFLAGS = -Idrivers/media/video | ||
15 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||
16 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
17 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
diff --git a/drivers/staging/tm6000/README b/drivers/staging/tm6000/README new file mode 100644 index 000000000000..c340ebc2ee9f --- /dev/null +++ b/drivers/staging/tm6000/README | |||
@@ -0,0 +1,22 @@ | |||
1 | Todo: | ||
2 | - Fix the loss of some blocks when receiving the video URB's | ||
3 | - Add a lock at tm6000_read_write_usb() to prevent two simultaneous access to the | ||
4 | URB control transfers | ||
5 | - Properly add the locks at tm6000-video | ||
6 | - Add audio support | ||
7 | - Add vbi support | ||
8 | - Add IR support | ||
9 | - Do several cleanups | ||
10 | - I think that frame1/frame0 are inverted. This causes a funny effect at the image. | ||
11 | the fix is trivial, but require some tests | ||
12 | - My tm6010 devices sometimes insist on stop working. I need to turn them off, removing | ||
13 | from my machine and wait for a while for it to work again. I'm starting to think that | ||
14 | it is an overheat issue - is there a workaround that we could do? | ||
15 | - Sometimes, tm6010 doesn't read eeprom at the proper time (hardware bug). So, the device | ||
16 | got miss-detected as a "generic" tm6000. This can be really bad if the tuner is the | ||
17 | Low Power one, as it may result on loading the high power firmware, that could damage | ||
18 | the device. Maybe we may read eeprom to double check, when the device is marked as "generic" | ||
19 | - Coding Style fixes | ||
20 | - sparse cleanups | ||
21 | |||
22 | Please send patches to linux-media@vger.kernel.org | ||
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c new file mode 100644 index 000000000000..bc89f9d28002 --- /dev/null +++ b/drivers/staging/tm6000/tm6000-alsa.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Support for audio capture for tm5600/6000/6010 | ||
4 | * (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com> | ||
5 | * | ||
6 | * Based on cx88-alsa.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/usb.h> | ||
18 | |||
19 | #include <asm/delay.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/control.h> | ||
24 | #include <sound/initval.h> | ||
25 | |||
26 | |||
27 | #include "tm6000.h" | ||
28 | #include "tm6000-regs.h" | ||
29 | |||
30 | #undef dprintk | ||
31 | |||
32 | #define dprintk(level, fmt, arg...) do { \ | ||
33 | if (debug >= level) \ | ||
34 | printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \ | ||
35 | } while (0) | ||
36 | |||
37 | /**************************************************************************** | ||
38 | Data type declarations - Can be moded to a header file later | ||
39 | ****************************************************************************/ | ||
40 | |||
41 | struct snd_tm6000_card { | ||
42 | struct snd_card *card; | ||
43 | |||
44 | spinlock_t reg_lock; | ||
45 | |||
46 | atomic_t count; | ||
47 | |||
48 | unsigned int period_size; | ||
49 | unsigned int num_periods; | ||
50 | |||
51 | struct tm6000_core *core; | ||
52 | struct tm6000_buffer *buf; | ||
53 | |||
54 | int bufsize; | ||
55 | |||
56 | struct snd_pcm_substream *substream; | ||
57 | }; | ||
58 | |||
59 | |||
60 | /**************************************************************************** | ||
61 | Module global static vars | ||
62 | ****************************************************************************/ | ||
63 | |||
64 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
65 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
66 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; | ||
67 | |||
68 | module_param_array(enable, bool, NULL, 0444); | ||
69 | MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled."); | ||
70 | |||
71 | module_param_array(index, int, NULL, 0444); | ||
72 | MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s)."); | ||
73 | |||
74 | |||
75 | /**************************************************************************** | ||
76 | Module macros | ||
77 | ****************************************************************************/ | ||
78 | |||
79 | MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards"); | ||
80 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
81 | MODULE_LICENSE("GPL"); | ||
82 | MODULE_SUPPORTED_DEVICE("{{Trident,tm5600}," | ||
83 | "{{Trident,tm6000}," | ||
84 | "{{Trident,tm6010}"); | ||
85 | static unsigned int debug; | ||
86 | module_param(debug, int, 0644); | ||
87 | MODULE_PARM_DESC(debug, "enable debug messages"); | ||
88 | |||
89 | /**************************************************************************** | ||
90 | Module specific funtions | ||
91 | ****************************************************************************/ | ||
92 | |||
93 | /* | ||
94 | * BOARD Specific: Sets audio DMA | ||
95 | */ | ||
96 | |||
97 | static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip) | ||
98 | { | ||
99 | struct tm6000_core *core = chip->core; | ||
100 | int val; | ||
101 | |||
102 | /* Enables audio */ | ||
103 | val = tm6000_get_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x0); | ||
104 | val |= 0x20; | ||
105 | tm6000_set_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); | ||
106 | |||
107 | tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0x80); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * BOARD Specific: Resets audio DMA | ||
114 | */ | ||
115 | static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) | ||
116 | { | ||
117 | struct tm6000_core *core = chip->core; | ||
118 | int val; | ||
119 | dprintk(1, "Stopping audio DMA\n"); | ||
120 | |||
121 | /* Enables audio */ | ||
122 | val = tm6000_get_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x0); | ||
123 | val &= ~0x20; | ||
124 | tm6000_set_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); | ||
125 | |||
126 | tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int dsp_buffer_free(struct snd_tm6000_card *chip) | ||
132 | { | ||
133 | BUG_ON(!chip->bufsize); | ||
134 | |||
135 | dprintk(2, "Freeing buffer\n"); | ||
136 | |||
137 | /* FIXME: Frees buffer */ | ||
138 | |||
139 | chip->bufsize = 0; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /**************************************************************************** | ||
145 | ALSA PCM Interface | ||
146 | ****************************************************************************/ | ||
147 | |||
148 | /* | ||
149 | * Digital hardware definition | ||
150 | */ | ||
151 | #define DEFAULT_FIFO_SIZE 4096 | ||
152 | |||
153 | static struct snd_pcm_hardware snd_tm6000_digital_hw = { | ||
154 | .info = SNDRV_PCM_INFO_MMAP | | ||
155 | SNDRV_PCM_INFO_INTERLEAVED | | ||
156 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
157 | SNDRV_PCM_INFO_MMAP_VALID, | ||
158 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
159 | |||
160 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
161 | .rate_min = 44100, | ||
162 | .rate_max = 48000, | ||
163 | .channels_min = 2, | ||
164 | .channels_max = 2, | ||
165 | .period_bytes_min = DEFAULT_FIFO_SIZE/4, | ||
166 | .period_bytes_max = DEFAULT_FIFO_SIZE/4, | ||
167 | .periods_min = 1, | ||
168 | .periods_max = 1024, | ||
169 | .buffer_bytes_max = (1024*1024), | ||
170 | }; | ||
171 | |||
172 | /* | ||
173 | * audio pcm capture open callback | ||
174 | */ | ||
175 | static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream) | ||
176 | { | ||
177 | struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); | ||
178 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
179 | int err; | ||
180 | |||
181 | err = snd_pcm_hw_constraint_pow2(runtime, 0, | ||
182 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
183 | if (err < 0) | ||
184 | goto _error; | ||
185 | |||
186 | chip->substream = substream; | ||
187 | |||
188 | runtime->hw = snd_tm6000_digital_hw; | ||
189 | |||
190 | return 0; | ||
191 | _error: | ||
192 | dprintk(1, "Error opening PCM!\n"); | ||
193 | return err; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * audio close callback | ||
198 | */ | ||
199 | static int snd_tm6000_close(struct snd_pcm_substream *substream) | ||
200 | { | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * hw_params callback | ||
206 | */ | ||
207 | static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, | ||
208 | struct snd_pcm_hw_params *hw_params) | ||
209 | { | ||
210 | struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); | ||
211 | |||
212 | if (substream->runtime->dma_area) { | ||
213 | dsp_buffer_free(chip); | ||
214 | substream->runtime->dma_area = NULL; | ||
215 | } | ||
216 | |||
217 | chip->period_size = params_period_bytes(hw_params); | ||
218 | chip->num_periods = params_periods(hw_params); | ||
219 | chip->bufsize = chip->period_size * params_periods(hw_params); | ||
220 | |||
221 | BUG_ON(!chip->bufsize); | ||
222 | |||
223 | dprintk(1, "Setting buffer\n"); | ||
224 | |||
225 | /* FIXME: Allocate buffer for audio */ | ||
226 | |||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * hw free callback | ||
233 | */ | ||
234 | static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) | ||
235 | { | ||
236 | |||
237 | struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); | ||
238 | |||
239 | if (substream->runtime->dma_area) { | ||
240 | dsp_buffer_free(chip); | ||
241 | substream->runtime->dma_area = NULL; | ||
242 | } | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * prepare callback | ||
249 | */ | ||
250 | static int snd_tm6000_prepare(struct snd_pcm_substream *substream) | ||
251 | { | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | |||
256 | /* | ||
257 | * trigger callback | ||
258 | */ | ||
259 | static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) | ||
260 | { | ||
261 | struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); | ||
262 | int err; | ||
263 | |||
264 | spin_lock(&chip->reg_lock); | ||
265 | |||
266 | switch (cmd) { | ||
267 | case SNDRV_PCM_TRIGGER_START: | ||
268 | err = _tm6000_start_audio_dma(chip); | ||
269 | break; | ||
270 | case SNDRV_PCM_TRIGGER_STOP: | ||
271 | err = _tm6000_stop_audio_dma(chip); | ||
272 | break; | ||
273 | default: | ||
274 | err = -EINVAL; | ||
275 | break; | ||
276 | } | ||
277 | |||
278 | spin_unlock(&chip->reg_lock); | ||
279 | |||
280 | return err; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * pointer callback | ||
285 | */ | ||
286 | static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) | ||
287 | { | ||
288 | struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); | ||
289 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
290 | u16 count; | ||
291 | |||
292 | count = atomic_read(&chip->count); | ||
293 | |||
294 | return runtime->period_size * (count & (runtime->periods-1)); | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * operators | ||
299 | */ | ||
300 | static struct snd_pcm_ops snd_tm6000_pcm_ops = { | ||
301 | .open = snd_tm6000_pcm_open, | ||
302 | .close = snd_tm6000_close, | ||
303 | .ioctl = snd_pcm_lib_ioctl, | ||
304 | .hw_params = snd_tm6000_hw_params, | ||
305 | .hw_free = snd_tm6000_hw_free, | ||
306 | .prepare = snd_tm6000_prepare, | ||
307 | .trigger = snd_tm6000_card_trigger, | ||
308 | .pointer = snd_tm6000_pointer, | ||
309 | }; | ||
310 | |||
311 | /* | ||
312 | * create a PCM device | ||
313 | */ | ||
314 | static int __devinit snd_tm6000_pcm(struct snd_tm6000_card *chip, | ||
315 | int device, char *name) | ||
316 | { | ||
317 | int err; | ||
318 | struct snd_pcm *pcm; | ||
319 | |||
320 | err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); | ||
321 | if (err < 0) | ||
322 | return err; | ||
323 | pcm->private_data = chip; | ||
324 | strcpy(pcm->name, name); | ||
325 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* FIXME: Control interface - How to control volume/mute? */ | ||
331 | |||
332 | /**************************************************************************** | ||
333 | Basic Flow for Sound Devices | ||
334 | ****************************************************************************/ | ||
335 | |||
336 | /* | ||
337 | * Alsa Constructor - Component probe | ||
338 | */ | ||
339 | |||
340 | int tm6000_audio_init(struct tm6000_core *dev, int idx) | ||
341 | { | ||
342 | struct snd_card *card; | ||
343 | struct snd_tm6000_card *chip; | ||
344 | int rc, len; | ||
345 | char component[14]; | ||
346 | |||
347 | if (idx >= SNDRV_CARDS) | ||
348 | return -ENODEV; | ||
349 | |||
350 | if (!enable[idx]) | ||
351 | return -ENOENT; | ||
352 | |||
353 | rc = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); | ||
354 | if (rc < 0) { | ||
355 | snd_printk(KERN_ERR "cannot create card instance %d\n", idx); | ||
356 | return rc; | ||
357 | } | ||
358 | |||
359 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
360 | if (!chip) { | ||
361 | rc = -ENOMEM; | ||
362 | goto error; | ||
363 | } | ||
364 | |||
365 | chip->core = dev; | ||
366 | chip->card = card; | ||
367 | |||
368 | strcpy(card->driver, "tm6000-alsa"); | ||
369 | sprintf(component, "USB%04x:%04x", | ||
370 | le16_to_cpu(dev->udev->descriptor.idVendor), | ||
371 | le16_to_cpu(dev->udev->descriptor.idProduct)); | ||
372 | snd_component_add(card, component); | ||
373 | |||
374 | if (dev->udev->descriptor.iManufacturer) | ||
375 | len = usb_string(dev->udev, | ||
376 | dev->udev->descriptor.iManufacturer, | ||
377 | card->longname, sizeof(card->longname)); | ||
378 | else | ||
379 | len = 0; | ||
380 | |||
381 | if (len > 0) | ||
382 | strlcat(card->longname, " ", sizeof(card->longname)); | ||
383 | |||
384 | strlcat(card->longname, card->shortname, sizeof(card->longname)); | ||
385 | |||
386 | len = strlcat(card->longname, " at ", sizeof(card->longname)); | ||
387 | |||
388 | if (len < sizeof(card->longname)) | ||
389 | usb_make_path(dev->udev, card->longname + len, | ||
390 | sizeof(card->longname) - len); | ||
391 | |||
392 | strlcat(card->longname, | ||
393 | dev->udev->speed == USB_SPEED_LOW ? ", low speed" : | ||
394 | dev->udev->speed == USB_SPEED_FULL ? ", full speed" : | ||
395 | ", high speed", | ||
396 | sizeof(card->longname)); | ||
397 | |||
398 | rc = snd_tm6000_pcm(chip, 0, "tm6000 Digital"); | ||
399 | if (rc < 0) | ||
400 | goto error; | ||
401 | |||
402 | rc = snd_card_register(card); | ||
403 | if (rc < 0) | ||
404 | goto error; | ||
405 | |||
406 | |||
407 | return 0; | ||
408 | |||
409 | error: | ||
410 | snd_card_free(card); | ||
411 | return rc; | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(tm6000_audio_init); | ||
414 | |||
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c new file mode 100644 index 000000000000..6143e20d139d --- /dev/null +++ b/drivers/staging/tm6000/tm6000-cards.c | |||
@@ -0,0 +1,973 @@ | |||
1 | /* | ||
2 | tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
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 version 2 | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/version.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/tuner.h> | ||
29 | #include <media/tvaudio.h> | ||
30 | #include <media/i2c-addr.h> | ||
31 | |||
32 | #include "tm6000.h" | ||
33 | #include "tm6000-regs.h" | ||
34 | #include "tuner-xc2028.h" | ||
35 | #include "xc5000.h" | ||
36 | |||
37 | #define TM6000_BOARD_UNKNOWN 0 | ||
38 | #define TM5600_BOARD_GENERIC 1 | ||
39 | #define TM6000_BOARD_GENERIC 2 | ||
40 | #define TM6010_BOARD_GENERIC 3 | ||
41 | #define TM5600_BOARD_10MOONS_UT821 4 | ||
42 | #define TM5600_BOARD_10MOONS_UT330 5 | ||
43 | #define TM6000_BOARD_ADSTECH_DUAL_TV 6 | ||
44 | #define TM6000_BOARD_FREECOM_AND_SIMILAR 7 | ||
45 | #define TM6000_BOARD_ADSTECH_MINI_DUAL_TV 8 | ||
46 | #define TM6010_BOARD_HAUPPAUGE_900H 9 | ||
47 | #define TM6010_BOARD_BEHOLD_WANDER 10 | ||
48 | #define TM6010_BOARD_BEHOLD_VOYAGER 11 | ||
49 | #define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE 12 | ||
50 | #define TM6010_BOARD_TWINHAN_TU501 13 | ||
51 | |||
52 | #define TM6000_MAXBOARDS 16 | ||
53 | static unsigned int card[] = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET }; | ||
54 | |||
55 | module_param_array(card, int, NULL, 0444); | ||
56 | |||
57 | static unsigned long tm6000_devused; | ||
58 | |||
59 | |||
60 | struct tm6000_board { | ||
61 | char *name; | ||
62 | |||
63 | struct tm6000_capabilities caps; | ||
64 | |||
65 | enum tm6000_devtype type; /* variant of the chipset */ | ||
66 | int tuner_type; /* type of the tuner */ | ||
67 | int tuner_addr; /* tuner address */ | ||
68 | int demod_addr; /* demodulator address */ | ||
69 | |||
70 | struct tm6000_gpio gpio; | ||
71 | }; | ||
72 | |||
73 | struct tm6000_board tm6000_boards[] = { | ||
74 | [TM6000_BOARD_UNKNOWN] = { | ||
75 | .name = "Unknown tm6000 video grabber", | ||
76 | .caps = { | ||
77 | .has_tuner = 1, | ||
78 | }, | ||
79 | .gpio = { | ||
80 | .tuner_reset = TM6000_GPIO_1, | ||
81 | }, | ||
82 | }, | ||
83 | [TM5600_BOARD_GENERIC] = { | ||
84 | .name = "Generic tm5600 board", | ||
85 | .type = TM5600, | ||
86 | .tuner_type = TUNER_XC2028, | ||
87 | .tuner_addr = 0xc2 >> 1, | ||
88 | .caps = { | ||
89 | .has_tuner = 1, | ||
90 | }, | ||
91 | .gpio = { | ||
92 | .tuner_reset = TM6000_GPIO_1, | ||
93 | }, | ||
94 | }, | ||
95 | [TM6000_BOARD_GENERIC] = { | ||
96 | .name = "Generic tm6000 board", | ||
97 | .tuner_type = TUNER_XC2028, | ||
98 | .tuner_addr = 0xc2 >> 1, | ||
99 | .caps = { | ||
100 | .has_tuner = 1, | ||
101 | .has_dvb = 1, | ||
102 | }, | ||
103 | .gpio = { | ||
104 | .tuner_reset = TM6000_GPIO_1, | ||
105 | }, | ||
106 | }, | ||
107 | [TM6010_BOARD_GENERIC] = { | ||
108 | .name = "Generic tm6010 board", | ||
109 | .type = TM6010, | ||
110 | .tuner_type = TUNER_XC2028, | ||
111 | .tuner_addr = 0xc2 >> 1, | ||
112 | .demod_addr = 0x1e >> 1, | ||
113 | .caps = { | ||
114 | .has_tuner = 1, | ||
115 | .has_dvb = 1, | ||
116 | .has_zl10353 = 1, | ||
117 | .has_eeprom = 1, | ||
118 | .has_remote = 1, | ||
119 | }, | ||
120 | .gpio = { | ||
121 | .tuner_reset = TM6010_GPIO_2, | ||
122 | .tuner_on = TM6010_GPIO_3, | ||
123 | .demod_reset = TM6010_GPIO_1, | ||
124 | .demod_on = TM6010_GPIO_4, | ||
125 | .power_led = TM6010_GPIO_7, | ||
126 | .dvb_led = TM6010_GPIO_5, | ||
127 | .ir = TM6010_GPIO_0, | ||
128 | }, | ||
129 | }, | ||
130 | [TM5600_BOARD_10MOONS_UT821] = { | ||
131 | .name = "10Moons UT 821", | ||
132 | .tuner_type = TUNER_XC2028, | ||
133 | .type = TM5600, | ||
134 | .tuner_addr = 0xc2 >> 1, | ||
135 | .caps = { | ||
136 | .has_tuner = 1, | ||
137 | .has_eeprom = 1, | ||
138 | }, | ||
139 | .gpio = { | ||
140 | .tuner_reset = TM6000_GPIO_1, | ||
141 | }, | ||
142 | }, | ||
143 | [TM5600_BOARD_10MOONS_UT330] = { | ||
144 | .name = "10Moons UT 330", | ||
145 | .tuner_type = TUNER_PHILIPS_FQ1216AME_MK4, | ||
146 | .tuner_addr = 0xc8 >> 1, | ||
147 | .caps = { | ||
148 | .has_tuner = 1, | ||
149 | .has_dvb = 0, | ||
150 | .has_zl10353 = 0, | ||
151 | .has_eeprom = 1, | ||
152 | }, | ||
153 | }, | ||
154 | [TM6000_BOARD_ADSTECH_DUAL_TV] = { | ||
155 | .name = "ADSTECH Dual TV USB", | ||
156 | .tuner_type = TUNER_XC2028, | ||
157 | .tuner_addr = 0xc8 >> 1, | ||
158 | .caps = { | ||
159 | .has_tuner = 1, | ||
160 | .has_tda9874 = 1, | ||
161 | .has_dvb = 1, | ||
162 | .has_zl10353 = 1, | ||
163 | .has_eeprom = 1, | ||
164 | }, | ||
165 | }, | ||
166 | [TM6000_BOARD_FREECOM_AND_SIMILAR] = { | ||
167 | .name = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual", | ||
168 | .tuner_type = TUNER_XC2028, /* has a XC3028 */ | ||
169 | .tuner_addr = 0xc2 >> 1, | ||
170 | .demod_addr = 0x1e >> 1, | ||
171 | .caps = { | ||
172 | .has_tuner = 1, | ||
173 | .has_dvb = 1, | ||
174 | .has_zl10353 = 1, | ||
175 | .has_eeprom = 0, | ||
176 | .has_remote = 1, | ||
177 | }, | ||
178 | .gpio = { | ||
179 | .tuner_reset = TM6000_GPIO_4, | ||
180 | }, | ||
181 | }, | ||
182 | [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = { | ||
183 | .name = "ADSTECH Mini Dual TV USB", | ||
184 | .tuner_type = TUNER_XC2028, /* has a XC3028 */ | ||
185 | .tuner_addr = 0xc8 >> 1, | ||
186 | .demod_addr = 0x1e >> 1, | ||
187 | .caps = { | ||
188 | .has_tuner = 1, | ||
189 | .has_dvb = 1, | ||
190 | .has_zl10353 = 1, | ||
191 | .has_eeprom = 0, | ||
192 | }, | ||
193 | .gpio = { | ||
194 | .tuner_reset = TM6000_GPIO_4, | ||
195 | }, | ||
196 | }, | ||
197 | [TM6010_BOARD_HAUPPAUGE_900H] = { | ||
198 | .name = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick", | ||
199 | .tuner_type = TUNER_XC2028, /* has a XC3028 */ | ||
200 | .tuner_addr = 0xc2 >> 1, | ||
201 | .demod_addr = 0x1e >> 1, | ||
202 | .type = TM6010, | ||
203 | .caps = { | ||
204 | .has_tuner = 1, | ||
205 | .has_dvb = 1, | ||
206 | .has_zl10353 = 1, | ||
207 | .has_eeprom = 1, | ||
208 | .has_remote = 1, | ||
209 | }, | ||
210 | .gpio = { | ||
211 | .tuner_reset = TM6010_GPIO_2, | ||
212 | .tuner_on = TM6010_GPIO_3, | ||
213 | .demod_reset = TM6010_GPIO_1, | ||
214 | .demod_on = TM6010_GPIO_4, | ||
215 | .power_led = TM6010_GPIO_7, | ||
216 | .dvb_led = TM6010_GPIO_5, | ||
217 | .ir = TM6010_GPIO_0, | ||
218 | }, | ||
219 | }, | ||
220 | [TM6010_BOARD_BEHOLD_WANDER] = { | ||
221 | .name = "Beholder Wander DVB-T/TV/FM USB2.0", | ||
222 | .tuner_type = TUNER_XC5000, | ||
223 | .tuner_addr = 0xc2 >> 1, | ||
224 | .demod_addr = 0x1e >> 1, | ||
225 | .type = TM6010, | ||
226 | .caps = { | ||
227 | .has_tuner = 1, | ||
228 | .has_dvb = 1, | ||
229 | .has_zl10353 = 1, | ||
230 | .has_eeprom = 1, | ||
231 | .has_remote = 1, | ||
232 | }, | ||
233 | .gpio = { | ||
234 | .tuner_reset = TM6010_GPIO_0, | ||
235 | .demod_reset = TM6010_GPIO_1, | ||
236 | .power_led = TM6010_GPIO_6, | ||
237 | }, | ||
238 | }, | ||
239 | [TM6010_BOARD_BEHOLD_VOYAGER] = { | ||
240 | .name = "Beholder Voyager TV/FM USB2.0", | ||
241 | .tuner_type = TUNER_XC5000, | ||
242 | .tuner_addr = 0xc2 >> 1, | ||
243 | .type = TM6010, | ||
244 | .caps = { | ||
245 | .has_tuner = 1, | ||
246 | .has_dvb = 0, | ||
247 | .has_zl10353 = 0, | ||
248 | .has_eeprom = 1, | ||
249 | .has_remote = 1, | ||
250 | }, | ||
251 | .gpio = { | ||
252 | .tuner_reset = TM6010_GPIO_0, | ||
253 | .power_led = TM6010_GPIO_6, | ||
254 | }, | ||
255 | }, | ||
256 | [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = { | ||
257 | .name = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick", | ||
258 | .tuner_type = TUNER_XC2028, /* has a XC3028 */ | ||
259 | .tuner_addr = 0xc2 >> 1, | ||
260 | .demod_addr = 0x1e >> 1, | ||
261 | .type = TM6010, | ||
262 | .caps = { | ||
263 | .has_tuner = 1, | ||
264 | .has_dvb = 1, | ||
265 | .has_zl10353 = 1, | ||
266 | .has_eeprom = 1, | ||
267 | .has_remote = 1, | ||
268 | }, | ||
269 | .gpio = { | ||
270 | .tuner_reset = TM6010_GPIO_2, | ||
271 | .tuner_on = TM6010_GPIO_3, | ||
272 | .demod_reset = TM6010_GPIO_1, | ||
273 | .demod_on = TM6010_GPIO_4, | ||
274 | .power_led = TM6010_GPIO_7, | ||
275 | .dvb_led = TM6010_GPIO_5, | ||
276 | .ir = TM6010_GPIO_0, | ||
277 | }, | ||
278 | }, | ||
279 | [TM6010_BOARD_TWINHAN_TU501] = { | ||
280 | .name = "Twinhan TU501(704D1)", | ||
281 | .tuner_type = TUNER_XC2028, /* has a XC3028 */ | ||
282 | .tuner_addr = 0xc2 >> 1, | ||
283 | .demod_addr = 0x1e >> 1, | ||
284 | .type = TM6010, | ||
285 | .caps = { | ||
286 | .has_tuner = 1, | ||
287 | .has_dvb = 1, | ||
288 | .has_zl10353 = 1, | ||
289 | .has_eeprom = 1, | ||
290 | .has_remote = 1, | ||
291 | }, | ||
292 | .gpio = { | ||
293 | .tuner_reset = TM6010_GPIO_2, | ||
294 | .tuner_on = TM6010_GPIO_3, | ||
295 | .demod_reset = TM6010_GPIO_1, | ||
296 | .demod_on = TM6010_GPIO_4, | ||
297 | .power_led = TM6010_GPIO_7, | ||
298 | .dvb_led = TM6010_GPIO_5, | ||
299 | .ir = TM6010_GPIO_0, | ||
300 | }, | ||
301 | } | ||
302 | }; | ||
303 | |||
304 | /* table of devices that work with this driver */ | ||
305 | struct usb_device_id tm6000_id_table[] = { | ||
306 | { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_10MOONS_UT821 }, | ||
307 | { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC }, | ||
308 | { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV }, | ||
309 | { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR }, | ||
310 | { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV }, | ||
311 | { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, | ||
312 | { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, | ||
313 | { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, | ||
314 | { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, | ||
315 | { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER }, | ||
316 | { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER }, | ||
317 | { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, | ||
318 | { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, | ||
319 | { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, | ||
320 | { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, | ||
321 | { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, | ||
322 | { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, | ||
323 | { }, | ||
324 | }; | ||
325 | |||
326 | /* Tuner callback to provide the proper gpio changes needed for xc5000 */ | ||
327 | int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) | ||
328 | { | ||
329 | int rc = 0; | ||
330 | struct tm6000_core *dev = ptr; | ||
331 | |||
332 | if (dev->tuner_type != TUNER_XC5000) | ||
333 | return 0; | ||
334 | |||
335 | switch (command) { | ||
336 | case XC5000_TUNER_RESET: | ||
337 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
338 | dev->gpio.tuner_reset, 0x01); | ||
339 | msleep(15); | ||
340 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
341 | dev->gpio.tuner_reset, 0x00); | ||
342 | msleep(15); | ||
343 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
344 | dev->gpio.tuner_reset, 0x01); | ||
345 | break; | ||
346 | } | ||
347 | return (rc); | ||
348 | } | ||
349 | |||
350 | |||
351 | /* Tuner callback to provide the proper gpio changes needed for xc2028 */ | ||
352 | |||
353 | int tm6000_tuner_callback(void *ptr, int component, int command, int arg) | ||
354 | { | ||
355 | int rc = 0; | ||
356 | struct tm6000_core *dev = ptr; | ||
357 | |||
358 | if (dev->tuner_type != TUNER_XC2028) | ||
359 | return 0; | ||
360 | |||
361 | switch (command) { | ||
362 | case XC2028_RESET_CLK: | ||
363 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, | ||
364 | 0x02, arg); | ||
365 | msleep(10); | ||
366 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
367 | TM6000_GPIO_CLK, 0); | ||
368 | if (rc < 0) | ||
369 | return rc; | ||
370 | msleep(10); | ||
371 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
372 | TM6000_GPIO_CLK, 1); | ||
373 | break; | ||
374 | case XC2028_TUNER_RESET: | ||
375 | /* Reset codes during load firmware */ | ||
376 | switch (arg) { | ||
377 | case 0: | ||
378 | /* newer tuner can faster reset */ | ||
379 | switch (dev->model) { | ||
380 | case TM5600_BOARD_10MOONS_UT821: | ||
381 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
382 | dev->gpio.tuner_reset, 0x01); | ||
383 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
384 | 0x300, 0x01); | ||
385 | msleep(10); | ||
386 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
387 | dev->gpio.tuner_reset, 0x00); | ||
388 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
389 | 0x300, 0x00); | ||
390 | msleep(10); | ||
391 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
392 | dev->gpio.tuner_reset, 0x01); | ||
393 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
394 | 0x300, 0x01); | ||
395 | break; | ||
396 | case TM6010_BOARD_HAUPPAUGE_900H: | ||
397 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: | ||
398 | case TM6010_BOARD_TWINHAN_TU501: | ||
399 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
400 | dev->gpio.tuner_reset, 0x01); | ||
401 | msleep(60); | ||
402 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
403 | dev->gpio.tuner_reset, 0x00); | ||
404 | msleep(75); | ||
405 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
406 | dev->gpio.tuner_reset, 0x01); | ||
407 | msleep(60); | ||
408 | break; | ||
409 | default: | ||
410 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
411 | dev->gpio.tuner_reset, 0x00); | ||
412 | msleep(130); | ||
413 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
414 | dev->gpio.tuner_reset, 0x01); | ||
415 | msleep(130); | ||
416 | break; | ||
417 | } | ||
418 | break; | ||
419 | case 1: | ||
420 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, | ||
421 | 0x02, 0x01); | ||
422 | msleep(10); | ||
423 | break; | ||
424 | |||
425 | case 2: | ||
426 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
427 | TM6000_GPIO_CLK, 0); | ||
428 | if (rc < 0) | ||
429 | return rc; | ||
430 | msleep(100); | ||
431 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
432 | TM6000_GPIO_CLK, 1); | ||
433 | msleep(100); | ||
434 | break; | ||
435 | } | ||
436 | } | ||
437 | return rc; | ||
438 | } | ||
439 | |||
440 | int tm6000_cards_setup(struct tm6000_core *dev) | ||
441 | { | ||
442 | int i, rc; | ||
443 | |||
444 | /* | ||
445 | * Board-specific initialization sequence. Handles all GPIO | ||
446 | * initialization sequences that are board-specific. | ||
447 | * Up to now, all found devices use GPIO1 and GPIO4 at the same way. | ||
448 | * Probably, they're all based on some reference device. Due to that, | ||
449 | * there's a common routine at the end to handle those GPIO's. Devices | ||
450 | * that use different pinups or init sequences can just return at | ||
451 | * the board-specific session. | ||
452 | */ | ||
453 | switch (dev->model) { | ||
454 | case TM6010_BOARD_HAUPPAUGE_900H: | ||
455 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: | ||
456 | case TM6010_BOARD_TWINHAN_TU501: | ||
457 | case TM6010_BOARD_GENERIC: | ||
458 | /* Turn xceive 3028 on */ | ||
459 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01); | ||
460 | msleep(15); | ||
461 | /* Turn zarlink zl10353 on */ | ||
462 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); | ||
463 | msleep(15); | ||
464 | /* Reset zarlink zl10353 */ | ||
465 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); | ||
466 | msleep(50); | ||
467 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); | ||
468 | msleep(15); | ||
469 | /* Turn zarlink zl10353 off */ | ||
470 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01); | ||
471 | msleep(15); | ||
472 | /* ir ? */ | ||
473 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01); | ||
474 | msleep(15); | ||
475 | /* Power led on (blue) */ | ||
476 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00); | ||
477 | msleep(15); | ||
478 | /* DVB led off (orange) */ | ||
479 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01); | ||
480 | msleep(15); | ||
481 | /* Turn zarlink zl10353 on */ | ||
482 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); | ||
483 | msleep(15); | ||
484 | break; | ||
485 | case TM6010_BOARD_BEHOLD_WANDER: | ||
486 | /* Power led on (blue) */ | ||
487 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); | ||
488 | msleep(15); | ||
489 | /* Reset zarlink zl10353 */ | ||
490 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); | ||
491 | msleep(50); | ||
492 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); | ||
493 | msleep(15); | ||
494 | break; | ||
495 | case TM6010_BOARD_BEHOLD_VOYAGER: | ||
496 | /* Power led on (blue) */ | ||
497 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); | ||
498 | msleep(15); | ||
499 | break; | ||
500 | default: | ||
501 | break; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * Default initialization. Most of the devices seem to use GPIO1 | ||
506 | * and GPIO4.on the same way, so, this handles the common sequence | ||
507 | * used by most devices. | ||
508 | * If a device uses a different sequence or different GPIO pins for | ||
509 | * reset, just add the code at the board-specific part | ||
510 | */ | ||
511 | |||
512 | if (dev->gpio.tuner_reset) { | ||
513 | for (i = 0; i < 2; i++) { | ||
514 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
515 | dev->gpio.tuner_reset, 0x00); | ||
516 | if (rc < 0) { | ||
517 | printk(KERN_ERR "Error %i doing tuner reset\n", rc); | ||
518 | return rc; | ||
519 | } | ||
520 | |||
521 | msleep(10); /* Just to be conservative */ | ||
522 | rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, | ||
523 | dev->gpio.tuner_reset, 0x01); | ||
524 | if (rc < 0) { | ||
525 | printk(KERN_ERR "Error %i doing tuner reset\n", rc); | ||
526 | return rc; | ||
527 | } | ||
528 | msleep(10); | ||
529 | |||
530 | if (!i) { | ||
531 | rc = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); | ||
532 | if (rc >= 0) | ||
533 | printk(KERN_DEBUG "board=0x%08x\n", rc); | ||
534 | } | ||
535 | } | ||
536 | } else { | ||
537 | printk(KERN_ERR "Tuner reset is not configured\n"); | ||
538 | return -1; | ||
539 | } | ||
540 | |||
541 | msleep(50); | ||
542 | |||
543 | return 0; | ||
544 | }; | ||
545 | |||
546 | static void tm6000_config_tuner(struct tm6000_core *dev) | ||
547 | { | ||
548 | struct tuner_setup tun_setup; | ||
549 | |||
550 | /* Load tuner module */ | ||
551 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
552 | "tuner", "tuner", dev->tuner_addr, NULL); | ||
553 | |||
554 | memset(&tun_setup, 0, sizeof(tun_setup)); | ||
555 | tun_setup.type = dev->tuner_type; | ||
556 | tun_setup.addr = dev->tuner_addr; | ||
557 | |||
558 | tun_setup.mode_mask = 0; | ||
559 | if (dev->caps.has_tuner) | ||
560 | tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO); | ||
561 | if (dev->caps.has_dvb) | ||
562 | tun_setup.mode_mask |= T_DIGITAL_TV; | ||
563 | |||
564 | switch (dev->tuner_type) { | ||
565 | case TUNER_XC2028: | ||
566 | tun_setup.tuner_callback = tm6000_tuner_callback;; | ||
567 | break; | ||
568 | case TUNER_XC5000: | ||
569 | tun_setup.tuner_callback = tm6000_xc5000_callback; | ||
570 | break; | ||
571 | } | ||
572 | |||
573 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); | ||
574 | |||
575 | switch (dev->tuner_type) { | ||
576 | case TUNER_XC2028: { | ||
577 | struct v4l2_priv_tun_config xc2028_cfg; | ||
578 | struct xc2028_ctrl ctl; | ||
579 | |||
580 | memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); | ||
581 | memset(&ctl, 0, sizeof(ctl)); | ||
582 | |||
583 | ctl.input1 = 1; | ||
584 | ctl.read_not_reliable = 0; | ||
585 | ctl.msleep = 10; | ||
586 | ctl.demod = XC3028_FE_ZARLINK456; | ||
587 | ctl.vhfbw7 = 1; | ||
588 | ctl.uhfbw8 = 1; | ||
589 | xc2028_cfg.tuner = TUNER_XC2028; | ||
590 | xc2028_cfg.priv = &ctl; | ||
591 | |||
592 | switch (dev->model) { | ||
593 | case TM6010_BOARD_HAUPPAUGE_900H: | ||
594 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: | ||
595 | case TM6010_BOARD_TWINHAN_TU501: | ||
596 | ctl.fname = "xc3028L-v36.fw"; | ||
597 | break; | ||
598 | default: | ||
599 | if (dev->dev_type == TM6010) | ||
600 | ctl.fname = "xc3028-v27.fw"; | ||
601 | else | ||
602 | ctl.fname = "xc3028-v24.fw"; | ||
603 | } | ||
604 | |||
605 | printk(KERN_INFO "Setting firmware parameters for xc2028\n"); | ||
606 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, | ||
607 | &xc2028_cfg); | ||
608 | |||
609 | } | ||
610 | break; | ||
611 | case TUNER_XC5000: | ||
612 | { | ||
613 | struct v4l2_priv_tun_config xc5000_cfg; | ||
614 | struct xc5000_config ctl = { | ||
615 | .i2c_address = dev->tuner_addr, | ||
616 | .if_khz = 4570, | ||
617 | .radio_input = XC5000_RADIO_FM1, | ||
618 | }; | ||
619 | |||
620 | xc5000_cfg.tuner = TUNER_XC5000; | ||
621 | xc5000_cfg.priv = &ctl; | ||
622 | |||
623 | |||
624 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, | ||
625 | &xc5000_cfg); | ||
626 | } | ||
627 | break; | ||
628 | default: | ||
629 | printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n"); | ||
630 | break; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | static int tm6000_init_dev(struct tm6000_core *dev) | ||
635 | { | ||
636 | struct v4l2_frequency f; | ||
637 | int rc = 0; | ||
638 | |||
639 | mutex_init(&dev->lock); | ||
640 | |||
641 | mutex_lock(&dev->lock); | ||
642 | |||
643 | /* Initializa board-specific data */ | ||
644 | dev->dev_type = tm6000_boards[dev->model].type; | ||
645 | dev->tuner_type = tm6000_boards[dev->model].tuner_type; | ||
646 | dev->tuner_addr = tm6000_boards[dev->model].tuner_addr; | ||
647 | |||
648 | dev->gpio = tm6000_boards[dev->model].gpio; | ||
649 | |||
650 | dev->demod_addr = tm6000_boards[dev->model].demod_addr; | ||
651 | |||
652 | dev->caps = tm6000_boards[dev->model].caps; | ||
653 | |||
654 | /* initialize hardware */ | ||
655 | rc = tm6000_init(dev); | ||
656 | if (rc < 0) | ||
657 | goto err; | ||
658 | |||
659 | rc = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); | ||
660 | if (rc < 0) | ||
661 | goto err; | ||
662 | |||
663 | /* register i2c bus */ | ||
664 | rc = tm6000_i2c_register(dev); | ||
665 | if (rc < 0) | ||
666 | goto err; | ||
667 | |||
668 | /* Default values for STD and resolutions */ | ||
669 | dev->width = 720; | ||
670 | dev->height = 480; | ||
671 | dev->norm = V4L2_STD_PAL_M; | ||
672 | |||
673 | /* Configure tuner */ | ||
674 | tm6000_config_tuner(dev); | ||
675 | |||
676 | /* Set video standard */ | ||
677 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); | ||
678 | |||
679 | /* Set tuner frequency - also loads firmware on xc2028/xc3028 */ | ||
680 | f.tuner = 0; | ||
681 | f.type = V4L2_TUNER_ANALOG_TV; | ||
682 | f.frequency = 3092; /* 193.25 MHz */ | ||
683 | dev->freq = f.frequency; | ||
684 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); | ||
685 | |||
686 | if (dev->caps.has_tda9874) | ||
687 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
688 | "tvaudio", "tvaudio", I2C_ADDR_TDA9874, NULL); | ||
689 | |||
690 | /* register and initialize V4L2 */ | ||
691 | rc = tm6000_v4l2_register(dev); | ||
692 | if (rc < 0) | ||
693 | goto err; | ||
694 | |||
695 | if (dev->caps.has_dvb) { | ||
696 | dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL); | ||
697 | if (!dev->dvb) { | ||
698 | rc = -ENOMEM; | ||
699 | goto err2; | ||
700 | } | ||
701 | |||
702 | #ifdef CONFIG_VIDEO_TM6000_DVB | ||
703 | rc = tm6000_dvb_register(dev); | ||
704 | if (rc < 0) { | ||
705 | kfree(dev->dvb); | ||
706 | dev->dvb = NULL; | ||
707 | goto err2; | ||
708 | } | ||
709 | #endif | ||
710 | } | ||
711 | mutex_unlock(&dev->lock); | ||
712 | return 0; | ||
713 | |||
714 | err2: | ||
715 | v4l2_device_unregister(&dev->v4l2_dev); | ||
716 | |||
717 | err: | ||
718 | mutex_unlock(&dev->lock); | ||
719 | return rc; | ||
720 | } | ||
721 | |||
722 | /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ | ||
723 | #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) | ||
724 | |||
725 | static void get_max_endpoint(struct usb_device *udev, | ||
726 | struct usb_host_interface *alt, | ||
727 | char *msgtype, | ||
728 | struct usb_host_endpoint *curr_e, | ||
729 | struct tm6000_endpoint *tm_ep) | ||
730 | { | ||
731 | u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize); | ||
732 | unsigned int size = tmp & 0x7ff; | ||
733 | |||
734 | if (udev->speed == USB_SPEED_HIGH) | ||
735 | size = size * hb_mult (tmp); | ||
736 | |||
737 | if (size > tm_ep->maxsize) { | ||
738 | tm_ep->endp = curr_e; | ||
739 | tm_ep->maxsize = size; | ||
740 | tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber; | ||
741 | tm_ep->bAlternateSetting = alt->desc.bAlternateSetting; | ||
742 | |||
743 | printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n", | ||
744 | msgtype, curr_e->desc.bEndpointAddress, | ||
745 | size); | ||
746 | } | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * tm6000_usb_probe() | ||
751 | * checks for supported devices | ||
752 | */ | ||
753 | static int tm6000_usb_probe(struct usb_interface *interface, | ||
754 | const struct usb_device_id *id) | ||
755 | { | ||
756 | struct usb_device *usbdev; | ||
757 | struct tm6000_core *dev = NULL; | ||
758 | int i, rc = 0; | ||
759 | int nr = 0; | ||
760 | char *speed; | ||
761 | |||
762 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | ||
763 | |||
764 | /* Selects the proper interface */ | ||
765 | rc = usb_set_interface(usbdev, 0, 1); | ||
766 | if (rc < 0) | ||
767 | goto err; | ||
768 | |||
769 | /* Check to see next free device and mark as used */ | ||
770 | nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS); | ||
771 | if (nr >= TM6000_MAXBOARDS) { | ||
772 | printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS); | ||
773 | usb_put_dev(usbdev); | ||
774 | return -ENOMEM; | ||
775 | } | ||
776 | |||
777 | /* Create and initialize dev struct */ | ||
778 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
779 | if (dev == NULL) { | ||
780 | printk(KERN_ERR "tm6000" ": out of memory!\n"); | ||
781 | usb_put_dev(usbdev); | ||
782 | return -ENOMEM; | ||
783 | } | ||
784 | spin_lock_init(&dev->slock); | ||
785 | |||
786 | /* Increment usage count */ | ||
787 | tm6000_devused |= 1<<nr; | ||
788 | snprintf(dev->name, 29, "tm6000 #%d", nr); | ||
789 | |||
790 | dev->model = id->driver_info; | ||
791 | if ((card[nr] >= 0) && (card[nr] < ARRAY_SIZE(tm6000_boards))) | ||
792 | dev->model = card[nr]; | ||
793 | |||
794 | dev->udev = usbdev; | ||
795 | dev->devno = nr; | ||
796 | |||
797 | switch (usbdev->speed) { | ||
798 | case USB_SPEED_LOW: | ||
799 | speed = "1.5"; | ||
800 | break; | ||
801 | case USB_SPEED_UNKNOWN: | ||
802 | case USB_SPEED_FULL: | ||
803 | speed = "12"; | ||
804 | break; | ||
805 | case USB_SPEED_HIGH: | ||
806 | speed = "480"; | ||
807 | break; | ||
808 | default: | ||
809 | speed = "unknown"; | ||
810 | } | ||
811 | |||
812 | |||
813 | |||
814 | /* Get endpoints */ | ||
815 | for (i = 0; i < interface->num_altsetting; i++) { | ||
816 | int ep; | ||
817 | |||
818 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { | ||
819 | struct usb_host_endpoint *e; | ||
820 | int dir_out; | ||
821 | |||
822 | e = &interface->altsetting[i].endpoint[ep]; | ||
823 | |||
824 | dir_out = ((e->desc.bEndpointAddress & | ||
825 | USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); | ||
826 | |||
827 | printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n", | ||
828 | i, | ||
829 | interface->altsetting[i].desc.bInterfaceNumber, | ||
830 | interface->altsetting[i].desc.bInterfaceClass); | ||
831 | |||
832 | switch (e->desc.bmAttributes) { | ||
833 | case USB_ENDPOINT_XFER_BULK: | ||
834 | if (!dir_out) { | ||
835 | get_max_endpoint(usbdev, | ||
836 | &interface->altsetting[i], | ||
837 | "Bulk IN", e, | ||
838 | &dev->bulk_in); | ||
839 | } else { | ||
840 | get_max_endpoint(usbdev, | ||
841 | &interface->altsetting[i], | ||
842 | "Bulk OUT", e, | ||
843 | &dev->bulk_out); | ||
844 | } | ||
845 | break; | ||
846 | case USB_ENDPOINT_XFER_ISOC: | ||
847 | if (!dir_out) { | ||
848 | get_max_endpoint(usbdev, | ||
849 | &interface->altsetting[i], | ||
850 | "ISOC IN", e, | ||
851 | &dev->isoc_in); | ||
852 | } else { | ||
853 | get_max_endpoint(usbdev, | ||
854 | &interface->altsetting[i], | ||
855 | "ISOC OUT", e, | ||
856 | &dev->isoc_out); | ||
857 | } | ||
858 | break; | ||
859 | } | ||
860 | } | ||
861 | } | ||
862 | |||
863 | |||
864 | printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n", | ||
865 | speed, | ||
866 | le16_to_cpu(dev->udev->descriptor.idVendor), | ||
867 | le16_to_cpu(dev->udev->descriptor.idProduct), | ||
868 | interface->altsetting->desc.bInterfaceNumber); | ||
869 | |||
870 | /* check if the the device has the iso in endpoint at the correct place */ | ||
871 | if (!dev->isoc_in.endp) { | ||
872 | printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n"); | ||
873 | rc = -ENODEV; | ||
874 | |||
875 | goto err; | ||
876 | } | ||
877 | |||
878 | /* save our data pointer in this interface device */ | ||
879 | usb_set_intfdata(interface, dev); | ||
880 | |||
881 | printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name); | ||
882 | |||
883 | rc = tm6000_init_dev(dev); | ||
884 | |||
885 | if (rc < 0) | ||
886 | goto err; | ||
887 | |||
888 | return 0; | ||
889 | |||
890 | err: | ||
891 | printk(KERN_ERR "tm6000: Error %d while registering\n", rc); | ||
892 | |||
893 | tm6000_devused &= ~(1<<nr); | ||
894 | usb_put_dev(usbdev); | ||
895 | |||
896 | kfree(dev); | ||
897 | return rc; | ||
898 | } | ||
899 | |||
900 | /* | ||
901 | * tm6000_usb_disconnect() | ||
902 | * called when the device gets diconencted | ||
903 | * video device will be unregistered on v4l2_close in case it is still open | ||
904 | */ | ||
905 | static void tm6000_usb_disconnect(struct usb_interface *interface) | ||
906 | { | ||
907 | struct tm6000_core *dev = usb_get_intfdata(interface); | ||
908 | usb_set_intfdata(interface, NULL); | ||
909 | |||
910 | if (!dev) | ||
911 | return; | ||
912 | |||
913 | printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); | ||
914 | |||
915 | mutex_lock(&dev->lock); | ||
916 | |||
917 | #ifdef CONFIG_VIDEO_TM6000_DVB | ||
918 | if (dev->dvb) { | ||
919 | tm6000_dvb_unregister(dev); | ||
920 | kfree(dev->dvb); | ||
921 | } | ||
922 | #endif | ||
923 | |||
924 | tm6000_v4l2_unregister(dev); | ||
925 | |||
926 | tm6000_i2c_unregister(dev); | ||
927 | |||
928 | v4l2_device_unregister(&dev->v4l2_dev); | ||
929 | |||
930 | dev->state |= DEV_DISCONNECTED; | ||
931 | |||
932 | usb_put_dev(dev->udev); | ||
933 | |||
934 | mutex_unlock(&dev->lock); | ||
935 | kfree(dev); | ||
936 | } | ||
937 | |||
938 | static struct usb_driver tm6000_usb_driver = { | ||
939 | .name = "tm6000", | ||
940 | .probe = tm6000_usb_probe, | ||
941 | .disconnect = tm6000_usb_disconnect, | ||
942 | .id_table = tm6000_id_table, | ||
943 | }; | ||
944 | |||
945 | static int __init tm6000_module_init(void) | ||
946 | { | ||
947 | int result; | ||
948 | |||
949 | printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n", | ||
950 | (TM6000_VERSION >> 16) & 0xff, | ||
951 | (TM6000_VERSION >> 8) & 0xff, TM6000_VERSION & 0xff); | ||
952 | |||
953 | /* register this driver with the USB subsystem */ | ||
954 | result = usb_register(&tm6000_usb_driver); | ||
955 | if (result) | ||
956 | printk(KERN_ERR "tm6000" | ||
957 | " usb_register failed. Error number %d.\n", result); | ||
958 | |||
959 | return result; | ||
960 | } | ||
961 | |||
962 | static void __exit tm6000_module_exit(void) | ||
963 | { | ||
964 | /* deregister at USB subsystem */ | ||
965 | usb_deregister(&tm6000_usb_driver); | ||
966 | } | ||
967 | |||
968 | module_init(tm6000_module_init); | ||
969 | module_exit(tm6000_module_exit); | ||
970 | |||
971 | MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter"); | ||
972 | MODULE_AUTHOR("Mauro Carvalho Chehab"); | ||
973 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c new file mode 100644 index 000000000000..bfbc53bd2912 --- /dev/null +++ b/drivers/staging/tm6000/tm6000-core.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
5 | |||
6 | Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> | ||
7 | - DVB-T support | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation version 2 | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include "tm6000.h" | ||
28 | #include "tm6000-regs.h" | ||
29 | #include <media/v4l2-common.h> | ||
30 | #include <media/tuner.h> | ||
31 | |||
32 | #define USB_TIMEOUT 5*HZ /* ms */ | ||
33 | |||
34 | int tm6000_read_write_usb (struct tm6000_core *dev, u8 req_type, u8 req, | ||
35 | u16 value, u16 index, u8 *buf, u16 len) | ||
36 | { | ||
37 | int ret, i; | ||
38 | unsigned int pipe; | ||
39 | static int ini=0, last=0, n=0; | ||
40 | u8 *data=NULL; | ||
41 | |||
42 | if (len) | ||
43 | data = kzalloc(len, GFP_KERNEL); | ||
44 | |||
45 | |||
46 | if (req_type & USB_DIR_IN) | ||
47 | pipe=usb_rcvctrlpipe(dev->udev, 0); | ||
48 | else { | ||
49 | pipe=usb_sndctrlpipe(dev->udev, 0); | ||
50 | memcpy(data, buf, len); | ||
51 | } | ||
52 | |||
53 | if (tm6000_debug & V4L2_DEBUG_I2C) { | ||
54 | if (!ini) | ||
55 | last=ini=jiffies; | ||
56 | |||
57 | printk("%06i (dev %p, pipe %08x): ", n, dev->udev, pipe); | ||
58 | |||
59 | printk( "%s: %06u ms %06u ms %02x %02x %02x %02x %02x %02x %02x %02x ", | ||
60 | (req_type & USB_DIR_IN)?" IN":"OUT", | ||
61 | jiffies_to_msecs(jiffies-last), | ||
62 | jiffies_to_msecs(jiffies-ini), | ||
63 | req_type, req,value&0xff,value>>8, index&0xff, index>>8, | ||
64 | len&0xff, len>>8); | ||
65 | last=jiffies; | ||
66 | n++; | ||
67 | |||
68 | if ( !(req_type & USB_DIR_IN) ) { | ||
69 | printk(">>> "); | ||
70 | for (i=0;i<len;i++) { | ||
71 | printk(" %02x",buf[i]); | ||
72 | } | ||
73 | printk("\n"); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, data, | ||
78 | len, USB_TIMEOUT); | ||
79 | |||
80 | if (req_type & USB_DIR_IN) | ||
81 | memcpy(buf, data, len); | ||
82 | |||
83 | if (tm6000_debug & V4L2_DEBUG_I2C) { | ||
84 | if (ret<0) { | ||
85 | if (req_type & USB_DIR_IN) | ||
86 | printk("<<< (len=%d)\n",len); | ||
87 | |||
88 | printk("%s: Error #%d\n", __FUNCTION__, ret); | ||
89 | } else if (req_type & USB_DIR_IN) { | ||
90 | printk("<<< "); | ||
91 | for (i=0;i<len;i++) { | ||
92 | printk(" %02x",buf[i]); | ||
93 | } | ||
94 | printk("\n"); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | kfree(data); | ||
99 | |||
100 | msleep(5); | ||
101 | |||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index) | ||
106 | { | ||
107 | return | ||
108 | tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR, | ||
109 | req, value, index, NULL, 0); | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(tm6000_set_reg); | ||
112 | |||
113 | int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index) | ||
114 | { | ||
115 | int rc; | ||
116 | u8 buf[1]; | ||
117 | |||
118 | rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, | ||
119 | value, index, buf, 1); | ||
120 | |||
121 | if (rc<0) | ||
122 | return rc; | ||
123 | |||
124 | return *buf; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(tm6000_get_reg); | ||
127 | |||
128 | int tm6000_get_reg16 (struct tm6000_core *dev, u8 req, u16 value, u16 index) | ||
129 | { | ||
130 | int rc; | ||
131 | u8 buf[2]; | ||
132 | |||
133 | rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, | ||
134 | value, index, buf, 2); | ||
135 | |||
136 | if (rc<0) | ||
137 | return rc; | ||
138 | |||
139 | return buf[1]|buf[0]<<8; | ||
140 | } | ||
141 | |||
142 | int tm6000_get_reg32 (struct tm6000_core *dev, u8 req, u16 value, u16 index) | ||
143 | { | ||
144 | int rc; | ||
145 | u8 buf[4]; | ||
146 | |||
147 | rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, | ||
148 | value, index, buf, 4); | ||
149 | |||
150 | if (rc<0) | ||
151 | return rc; | ||
152 | |||
153 | return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24; | ||
154 | } | ||
155 | |||
156 | void tm6000_set_fourcc_format(struct tm6000_core *dev) | ||
157 | { | ||
158 | if (dev->dev_type == TM6010) { | ||
159 | int val; | ||
160 | |||
161 | val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0) & 0xfc; | ||
162 | if (dev->fourcc == V4L2_PIX_FMT_UYVY) | ||
163 | tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); | ||
164 | else | ||
165 | tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val | 1); | ||
166 | } else { | ||
167 | if (dev->fourcc == V4L2_PIX_FMT_UYVY) | ||
168 | tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); | ||
169 | else | ||
170 | tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | int tm6000_init_analog_mode (struct tm6000_core *dev) | ||
175 | { | ||
176 | if (dev->dev_type == TM6010) { | ||
177 | int val; | ||
178 | |||
179 | /* Enable video */ | ||
180 | val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0); | ||
181 | val |= 0x60; | ||
182 | tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); | ||
183 | val = tm6000_get_reg(dev, | ||
184 | TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0); | ||
185 | val &= ~0x40; | ||
186 | tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, val); | ||
187 | |||
188 | /* Init teletext */ | ||
189 | tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); | ||
190 | tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27); | ||
191 | tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55); | ||
192 | tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66); | ||
193 | tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66); | ||
194 | tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66); | ||
195 | tm6000_set_reg(dev, | ||
196 | TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66); | ||
197 | tm6000_set_reg(dev, | ||
198 | TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66); | ||
199 | tm6000_set_reg(dev, | ||
200 | TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66); | ||
201 | tm6000_set_reg(dev, | ||
202 | TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66); | ||
203 | tm6000_set_reg(dev, | ||
204 | TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66); | ||
205 | tm6000_set_reg(dev, | ||
206 | TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66); | ||
207 | tm6000_set_reg(dev, | ||
208 | TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66); | ||
209 | tm6000_set_reg(dev, | ||
210 | TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66); | ||
211 | tm6000_set_reg(dev, | ||
212 | TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66); | ||
213 | tm6000_set_reg(dev, | ||
214 | TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66); | ||
215 | tm6000_set_reg(dev, | ||
216 | TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66); | ||
217 | tm6000_set_reg(dev, | ||
218 | TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66); | ||
219 | tm6000_set_reg(dev, | ||
220 | TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66); | ||
221 | tm6000_set_reg(dev, | ||
222 | TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00); | ||
223 | tm6000_set_reg(dev, | ||
224 | TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00); | ||
225 | tm6000_set_reg(dev, | ||
226 | TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01); | ||
227 | tm6000_set_reg(dev, | ||
228 | TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00); | ||
229 | tm6000_set_reg(dev, | ||
230 | TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02); | ||
231 | tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35); | ||
232 | tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0); | ||
233 | tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11); | ||
234 | tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c); | ||
235 | tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01); | ||
236 | tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); | ||
237 | |||
238 | |||
239 | /* Init audio */ | ||
240 | tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00); | ||
241 | tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04); | ||
242 | tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00); | ||
243 | tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0); | ||
244 | tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x05); | ||
245 | tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x06); | ||
246 | tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00); | ||
247 | tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00); | ||
248 | tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08); | ||
249 | tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91); | ||
250 | tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20); | ||
251 | tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12); | ||
252 | tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20); | ||
253 | tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0); | ||
254 | tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80); | ||
255 | tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0); | ||
256 | tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80); | ||
257 | tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12); | ||
258 | tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe); | ||
259 | tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20); | ||
260 | tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14); | ||
261 | tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe); | ||
262 | tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01); | ||
263 | tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0); | ||
264 | tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32); | ||
265 | tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64); | ||
266 | tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20); | ||
267 | tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00); | ||
268 | tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00); | ||
269 | tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13); | ||
270 | tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00); | ||
271 | tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00); | ||
272 | tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); | ||
273 | tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00); | ||
274 | tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80); | ||
275 | |||
276 | } else { | ||
277 | /* Enables soft reset */ | ||
278 | tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); | ||
279 | |||
280 | if (dev->scaler) { | ||
281 | tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20); | ||
282 | } else { | ||
283 | /* Enable Hfilter and disable TS Drop err */ | ||
284 | tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80); | ||
285 | } | ||
286 | |||
287 | tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88); | ||
288 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0x23); | ||
289 | tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0); | ||
290 | tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8); | ||
291 | tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06); | ||
292 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0x1f); | ||
293 | |||
294 | /* AP Software reset */ | ||
295 | tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); | ||
296 | tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); | ||
297 | |||
298 | tm6000_set_fourcc_format(dev); | ||
299 | |||
300 | /* Disables soft reset */ | ||
301 | tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); | ||
302 | |||
303 | /* E3: Select input 0 - TV tuner */ | ||
304 | tm6000_set_reg(dev, TM6010_REQ07_RE3_OUT_SEL1, 0x00); | ||
305 | tm6000_set_reg(dev, REQ_07_SET_GET_AVREG, 0xeb, 0x60); | ||
306 | |||
307 | /* This controls input */ | ||
308 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_2, 0x0); | ||
309 | tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_3, 0x01); | ||
310 | } | ||
311 | msleep(20); | ||
312 | |||
313 | /* Tuner firmware can now be loaded */ | ||
314 | |||
315 | /*FIXME: Hack!!! */ | ||
316 | struct v4l2_frequency f; | ||
317 | mutex_lock(&dev->lock); | ||
318 | f.frequency=dev->freq; | ||
319 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); | ||
320 | mutex_unlock(&dev->lock); | ||
321 | |||
322 | msleep(100); | ||
323 | tm6000_set_standard (dev, &dev->norm); | ||
324 | tm6000_set_audio_bitrate (dev,48000); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | int tm6000_init_digital_mode (struct tm6000_core *dev) | ||
330 | { | ||
331 | if (dev->dev_type == TM6010) { | ||
332 | int val; | ||
333 | u8 buf[2]; | ||
334 | |||
335 | /* digital init */ | ||
336 | val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0); | ||
337 | val &= ~0x60; | ||
338 | tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); | ||
339 | val = tm6000_get_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0); | ||
340 | val |= 0x40; | ||
341 | tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, val); | ||
342 | tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28); | ||
343 | tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc); | ||
344 | tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff); | ||
345 | tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe); | ||
346 | tm6000_read_write_usb (dev, 0xc0, 0x0e, 0x00c2, 0x0008, buf, 2); | ||
347 | printk (KERN_INFO "buf %#x %#x \n", buf[0], buf[1]); | ||
348 | |||
349 | |||
350 | } else { | ||
351 | tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); | ||
352 | tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); | ||
353 | tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); | ||
354 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0x08); | ||
355 | tm6000_set_reg(dev, TM6010_REQ07_RE2_OUT_SEL2, 0x0c); | ||
356 | tm6000_set_reg(dev, TM6010_REQ07_RE8_TYPESEL_MOS_I2S, 0xff); | ||
357 | tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0xd8); | ||
358 | tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40); | ||
359 | tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); | ||
360 | tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09); | ||
361 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0x37); | ||
362 | tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8); | ||
363 | tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0); | ||
364 | tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60); | ||
365 | |||
366 | tm6000_set_reg(dev, TM6010_REQ07_RE2_OUT_SEL2, 0x0c); | ||
367 | tm6000_set_reg(dev, TM6010_REQ07_RE8_TYPESEL_MOS_I2S, 0xff); | ||
368 | tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0x08); | ||
369 | msleep(50); | ||
370 | |||
371 | tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); | ||
372 | msleep(50); | ||
373 | tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01); | ||
374 | msleep(50); | ||
375 | tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); | ||
376 | msleep(100); | ||
377 | } | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | struct reg_init { | ||
382 | u8 req; | ||
383 | u8 reg; | ||
384 | u8 val; | ||
385 | }; | ||
386 | |||
387 | /* The meaning of those initializations are unknown */ | ||
388 | struct reg_init tm6000_init_tab[] = { | ||
389 | /* REG VALUE */ | ||
390 | { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0x1f }, | ||
391 | { TM6010_REQ07_RFF_SOFT_RESET, 0x08 }, | ||
392 | { TM6010_REQ07_RFF_SOFT_RESET, 0x00 }, | ||
393 | { TM6010_REQ07_RD5_POWERSAVE, 0x4f }, | ||
394 | { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0x23 }, | ||
395 | { TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0x08 }, | ||
396 | { TM6010_REQ07_RE2_OUT_SEL2, 0x00 }, | ||
397 | { TM6010_REQ07_RE3_OUT_SEL1, 0x10 }, | ||
398 | { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0x00 }, | ||
399 | { TM6010_REQ07_RE8_TYPESEL_MOS_I2S, 0x00 }, | ||
400 | { REQ_07_SET_GET_AVREG, 0xeb, 0x64 }, /* 48000 bits/sample, external input */ | ||
401 | { REQ_07_SET_GET_AVREG, 0xee, 0xc2 }, | ||
402 | { TM6010_REQ07_R3F_RESET, 0x01 }, /* Start of soft reset */ | ||
403 | { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, | ||
404 | { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, | ||
405 | { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, | ||
406 | { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, | ||
407 | { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, | ||
408 | { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, | ||
409 | { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, | ||
410 | { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, | ||
411 | { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, | ||
412 | { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, | ||
413 | { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, | ||
414 | { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, | ||
415 | { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, | ||
416 | { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, | ||
417 | { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, | ||
418 | { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, | ||
419 | { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, | ||
420 | { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, | ||
421 | { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, | ||
422 | { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, | ||
423 | { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, | ||
424 | { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, | ||
425 | { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, | ||
426 | { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, | ||
427 | { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, | ||
428 | { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, | ||
429 | { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, | ||
430 | { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, | ||
431 | { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, | ||
432 | { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, | ||
433 | { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, | ||
434 | { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, | ||
435 | { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, | ||
436 | { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, | ||
437 | { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, | ||
438 | { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, | ||
439 | { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, | ||
440 | { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, | ||
441 | { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, | ||
442 | { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, | ||
443 | { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, | ||
444 | { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, | ||
445 | { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, | ||
446 | { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, | ||
447 | { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, | ||
448 | { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, | ||
449 | { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, | ||
450 | { TM6010_REQ07_RC3_HSTART1, 0x88 }, | ||
451 | { TM6010_REQ07_R3F_RESET, 0x00 }, /* End of the soft reset */ | ||
452 | { TM6010_REQ05_R18_IMASK7, 0x00 }, | ||
453 | }; | ||
454 | |||
455 | struct reg_init tm6010_init_tab[] = { | ||
456 | { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 }, | ||
457 | { TM6010_REQ07_RC4_HSTART0, 0xa0 }, | ||
458 | { TM6010_REQ07_RC6_HEND0, 0x40 }, | ||
459 | { TM6010_REQ07_RCA_VEND0, 0x31 }, | ||
460 | { TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0xe1 }, | ||
461 | { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 }, | ||
462 | { TM6010_REQ07_RFE_POWER_DOWN, 0x7f }, | ||
463 | |||
464 | { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 }, | ||
465 | { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 }, | ||
466 | { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 }, | ||
467 | { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 }, | ||
468 | { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 }, | ||
469 | { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 }, | ||
470 | { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 }, | ||
471 | { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 }, | ||
472 | { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc }, | ||
473 | |||
474 | { TM6010_REQ07_R3F_RESET, 0x01 }, | ||
475 | { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, | ||
476 | { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, | ||
477 | { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, | ||
478 | { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, | ||
479 | { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, | ||
480 | { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, | ||
481 | { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, | ||
482 | { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, | ||
483 | { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, | ||
484 | { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, | ||
485 | { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, | ||
486 | { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, | ||
487 | { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, | ||
488 | { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, | ||
489 | { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, | ||
490 | { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, | ||
491 | { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, | ||
492 | { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, | ||
493 | { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, | ||
494 | { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, | ||
495 | { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, | ||
496 | { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, | ||
497 | { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, | ||
498 | { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, | ||
499 | { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, | ||
500 | { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, | ||
501 | { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, | ||
502 | { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, | ||
503 | { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, | ||
504 | { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, | ||
505 | { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, | ||
506 | { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, | ||
507 | { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, | ||
508 | { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, | ||
509 | { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, | ||
510 | { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, | ||
511 | { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, | ||
512 | { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, | ||
513 | { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, | ||
514 | { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, | ||
515 | { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, | ||
516 | { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, | ||
517 | { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, | ||
518 | { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, | ||
519 | { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, | ||
520 | { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, | ||
521 | { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, | ||
522 | { TM6010_REQ07_RC3_HSTART1, 0x88 }, | ||
523 | { TM6010_REQ07_R3F_RESET, 0x00 }, | ||
524 | |||
525 | { TM6010_REQ05_R18_IMASK7, 0x00 }, | ||
526 | |||
527 | { TM6010_REQ07_RD8_IR_LEADER1, 0xaa }, | ||
528 | { TM6010_REQ07_RD8_IR_LEADER0, 0x30 }, | ||
529 | { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 }, | ||
530 | { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 }, | ||
531 | { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, | ||
532 | { TM6010_REQ07_RD8_IR, 0x2f }, | ||
533 | |||
534 | /* set remote wakeup key:any key wakeup */ | ||
535 | { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, | ||
536 | { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff }, | ||
537 | }; | ||
538 | |||
539 | int tm6000_init (struct tm6000_core *dev) | ||
540 | { | ||
541 | int board, rc=0, i, size; | ||
542 | struct reg_init *tab; | ||
543 | |||
544 | if (dev->dev_type == TM6010) { | ||
545 | tab = tm6010_init_tab; | ||
546 | size = ARRAY_SIZE(tm6010_init_tab); | ||
547 | } else { | ||
548 | tab = tm6000_init_tab; | ||
549 | size = ARRAY_SIZE(tm6000_init_tab); | ||
550 | } | ||
551 | |||
552 | /* Load board's initialization table */ | ||
553 | for (i=0; i< size; i++) { | ||
554 | rc= tm6000_set_reg (dev, tab[i].req, tab[i].reg, tab[i].val); | ||
555 | if (rc<0) { | ||
556 | printk (KERN_ERR "Error %i while setting req %d, " | ||
557 | "reg %d to value %d\n", rc, | ||
558 | tab[i].req,tab[i].reg, tab[i].val); | ||
559 | return rc; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | msleep(5); /* Just to be conservative */ | ||
564 | |||
565 | /* Check board version - maybe 10Moons specific */ | ||
566 | board=tm6000_get_reg32 (dev, REQ_40_GET_VERSION, 0, 0); | ||
567 | if (board >=0) { | ||
568 | printk (KERN_INFO "Board version = 0x%08x\n",board); | ||
569 | } else { | ||
570 | printk (KERN_ERR "Error %i while retrieving board version\n",board); | ||
571 | } | ||
572 | |||
573 | rc = tm6000_cards_setup(dev); | ||
574 | |||
575 | return rc; | ||
576 | } | ||
577 | |||
578 | int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) | ||
579 | { | ||
580 | int val; | ||
581 | |||
582 | val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, 0x0); | ||
583 | printk("Original value=%d\n",val); | ||
584 | if (val<0) | ||
585 | return val; | ||
586 | |||
587 | val &= 0x0f; /* Preserve the audio input control bits */ | ||
588 | switch (bitrate) { | ||
589 | case 44100: | ||
590 | val|=0xd0; | ||
591 | dev->audio_bitrate=bitrate; | ||
592 | break; | ||
593 | case 48000: | ||
594 | val|=0x60; | ||
595 | dev->audio_bitrate=bitrate; | ||
596 | break; | ||
597 | } | ||
598 | val=tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, val); | ||
599 | |||
600 | return val; | ||
601 | } | ||
602 | EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate); | ||
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c new file mode 100644 index 000000000000..eafc89c22b6b --- /dev/null +++ b/drivers/staging/tm6000/tm6000-dvb.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2007 Michel Ludwig <michel.ludwig@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 version 2 | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/usb.h> | ||
22 | |||
23 | #include "tm6000.h" | ||
24 | #include "tm6000-regs.h" | ||
25 | |||
26 | #include "zl10353.h" | ||
27 | |||
28 | #include <media/tuner.h> | ||
29 | |||
30 | #include "tuner-xc2028.h" | ||
31 | |||
32 | static void inline print_err_status (struct tm6000_core *dev, | ||
33 | int packet, int status) | ||
34 | { | ||
35 | char *errmsg = "Unknown"; | ||
36 | |||
37 | switch(status) { | ||
38 | case -ENOENT: | ||
39 | errmsg = "unlinked synchronuously"; | ||
40 | break; | ||
41 | case -ECONNRESET: | ||
42 | errmsg = "unlinked asynchronuously"; | ||
43 | break; | ||
44 | case -ENOSR: | ||
45 | errmsg = "Buffer error (overrun)"; | ||
46 | break; | ||
47 | case -EPIPE: | ||
48 | errmsg = "Stalled (device not responding)"; | ||
49 | break; | ||
50 | case -EOVERFLOW: | ||
51 | errmsg = "Babble (bad cable?)"; | ||
52 | break; | ||
53 | case -EPROTO: | ||
54 | errmsg = "Bit-stuff error (bad cable?)"; | ||
55 | break; | ||
56 | case -EILSEQ: | ||
57 | errmsg = "CRC/Timeout (could be anything)"; | ||
58 | break; | ||
59 | case -ETIME: | ||
60 | errmsg = "Device does not respond"; | ||
61 | break; | ||
62 | } | ||
63 | if (packet<0) { | ||
64 | dprintk(dev, 1, "URB status %d [%s].\n", | ||
65 | status, errmsg); | ||
66 | } else { | ||
67 | dprintk(dev, 1, "URB packet %d, status %d [%s].\n", | ||
68 | packet, status, errmsg); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static void tm6000_urb_received(struct urb *urb) | ||
73 | { | ||
74 | int ret; | ||
75 | struct tm6000_core* dev = urb->context; | ||
76 | |||
77 | if(urb->status != 0) { | ||
78 | print_err_status (dev,0,urb->status); | ||
79 | } | ||
80 | else if(urb->actual_length>0){ | ||
81 | dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, | ||
82 | urb->actual_length); | ||
83 | } | ||
84 | |||
85 | if(dev->dvb->streams > 0) { | ||
86 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
87 | if(ret < 0) { | ||
88 | printk(KERN_ERR "tm6000: error %s\n", __FUNCTION__); | ||
89 | kfree(urb->transfer_buffer); | ||
90 | usb_free_urb(urb); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | int tm6000_start_stream(struct tm6000_core *dev) | ||
96 | { | ||
97 | int ret; | ||
98 | unsigned int pipe, size; | ||
99 | struct tm6000_dvb *dvb = dev->dvb; | ||
100 | |||
101 | printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__); | ||
102 | |||
103 | tm6000_init_digital_mode(dev); | ||
104 | |||
105 | dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
106 | if(dvb->bulk_urb == NULL) { | ||
107 | printk(KERN_ERR "tm6000: couldn't allocate urb\n"); | ||
108 | return -ENOMEM; | ||
109 | } | ||
110 | |||
111 | pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress | ||
112 | & USB_ENDPOINT_NUMBER_MASK); | ||
113 | |||
114 | size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); | ||
115 | size = size * 15; /* 512 x 8 or 12 or 15 */ | ||
116 | |||
117 | dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); | ||
118 | if(dvb->bulk_urb->transfer_buffer == NULL) { | ||
119 | usb_free_urb(dvb->bulk_urb); | ||
120 | printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe, | ||
125 | dvb->bulk_urb->transfer_buffer, | ||
126 | size, | ||
127 | tm6000_urb_received, dev); | ||
128 | |||
129 | ret = usb_clear_halt(dev->udev, pipe); | ||
130 | if(ret < 0) { | ||
131 | printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",ret,__FUNCTION__); | ||
132 | return ret; | ||
133 | } | ||
134 | else { | ||
135 | printk(KERN_ERR "tm6000: pipe resetted\n"); | ||
136 | } | ||
137 | |||
138 | /* mutex_lock(&tm6000_driver.open_close_mutex); */ | ||
139 | ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL); | ||
140 | |||
141 | /* mutex_unlock(&tm6000_driver.open_close_mutex); */ | ||
142 | if (ret) { | ||
143 | printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",ret); | ||
144 | |||
145 | kfree(dvb->bulk_urb->transfer_buffer); | ||
146 | usb_free_urb(dvb->bulk_urb); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | void tm6000_stop_stream(struct tm6000_core *dev) | ||
154 | { | ||
155 | struct tm6000_dvb *dvb = dev->dvb; | ||
156 | |||
157 | if(dvb->bulk_urb) { | ||
158 | printk (KERN_INFO "urb killing\n"); | ||
159 | usb_kill_urb(dvb->bulk_urb); | ||
160 | printk (KERN_INFO "urb buffer free\n"); | ||
161 | kfree(dvb->bulk_urb->transfer_buffer); | ||
162 | usb_free_urb(dvb->bulk_urb); | ||
163 | dvb->bulk_urb = NULL; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | int tm6000_start_feed(struct dvb_demux_feed *feed) | ||
168 | { | ||
169 | struct dvb_demux *demux = feed->demux; | ||
170 | struct tm6000_core *dev = demux->priv; | ||
171 | struct tm6000_dvb *dvb = dev->dvb; | ||
172 | printk(KERN_INFO "tm6000: got start feed request %s\n",__FUNCTION__); | ||
173 | |||
174 | mutex_lock(&dvb->mutex); | ||
175 | if(dvb->streams == 0) { | ||
176 | dvb->streams = 1; | ||
177 | /* mutex_init(&tm6000_dev->streming_mutex); */ | ||
178 | tm6000_start_stream(dev); | ||
179 | } | ||
180 | else { | ||
181 | ++(dvb->streams); | ||
182 | } | ||
183 | mutex_unlock(&dvb->mutex); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | int tm6000_stop_feed(struct dvb_demux_feed *feed) { | ||
189 | struct dvb_demux *demux = feed->demux; | ||
190 | struct tm6000_core *dev = demux->priv; | ||
191 | struct tm6000_dvb *dvb = dev->dvb; | ||
192 | |||
193 | printk(KERN_INFO "tm6000: got stop feed request %s\n",__FUNCTION__); | ||
194 | |||
195 | mutex_lock(&dvb->mutex); | ||
196 | |||
197 | printk (KERN_INFO "stream %#x\n", dvb->streams); | ||
198 | --(dvb->streams); | ||
199 | if(dvb->streams == 0) { | ||
200 | printk (KERN_INFO "stop stream\n"); | ||
201 | tm6000_stop_stream(dev); | ||
202 | /* mutex_destroy(&tm6000_dev->streaming_mutex); */ | ||
203 | } | ||
204 | mutex_unlock(&dvb->mutex); | ||
205 | /* mutex_destroy(&tm6000_dev->streaming_mutex); */ | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | int tm6000_dvb_attach_frontend(struct tm6000_core *dev) | ||
211 | { | ||
212 | struct tm6000_dvb *dvb = dev->dvb; | ||
213 | |||
214 | if(dev->caps.has_zl10353) { | ||
215 | struct zl10353_config config = | ||
216 | {.demod_address = dev->demod_addr, | ||
217 | .no_tuner = 1, | ||
218 | .parallel_ts = 1, | ||
219 | .if2 = 45700, | ||
220 | .disable_i2c_gate_ctrl = 1, | ||
221 | }; | ||
222 | |||
223 | dvb->frontend = dvb_attach(zl10353_attach, &config, | ||
224 | &dev->i2c_adap); | ||
225 | } | ||
226 | else { | ||
227 | printk(KERN_ERR "tm6000: no frontend defined for the device!\n"); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | return (!dvb->frontend) ? -1 : 0; | ||
232 | } | ||
233 | |||
234 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
235 | |||
236 | int tm6000_dvb_register(struct tm6000_core *dev) | ||
237 | { | ||
238 | int ret = -1; | ||
239 | struct tm6000_dvb *dvb = dev->dvb; | ||
240 | |||
241 | mutex_init(&dvb->mutex); | ||
242 | |||
243 | dvb->streams = 0; | ||
244 | |||
245 | /* attach the frontend */ | ||
246 | ret = tm6000_dvb_attach_frontend(dev); | ||
247 | if(ret < 0) { | ||
248 | printk(KERN_ERR "tm6000: couldn't attach the frontend!\n"); | ||
249 | goto err; | ||
250 | } | ||
251 | |||
252 | ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T", | ||
253 | THIS_MODULE, &dev->udev->dev, adapter_nr); | ||
254 | dvb->adapter.priv = dev; | ||
255 | |||
256 | if (dvb->frontend) { | ||
257 | struct xc2028_config cfg = { | ||
258 | .i2c_adap = &dev->i2c_adap, | ||
259 | .i2c_addr = dev->tuner_addr, | ||
260 | }; | ||
261 | |||
262 | dvb->frontend->callback = tm6000_tuner_callback; | ||
263 | ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); | ||
264 | if (ret < 0) { | ||
265 | printk(KERN_ERR | ||
266 | "tm6000: couldn't register frontend\n"); | ||
267 | goto adapter_err; | ||
268 | } | ||
269 | |||
270 | if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { | ||
271 | printk(KERN_ERR "tm6000: couldn't register " | ||
272 | "frontend (xc3028)\n"); | ||
273 | ret = -EINVAL; | ||
274 | goto frontend_err; | ||
275 | } | ||
276 | printk(KERN_INFO "tm6000: XC2028/3028 asked to be " | ||
277 | "attached to frontend!\n"); | ||
278 | } else { | ||
279 | printk(KERN_ERR "tm6000: no frontend found\n"); | ||
280 | } | ||
281 | |||
282 | dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | ||
283 | | DMX_MEMORY_BASED_FILTERING; | ||
284 | dvb->demux.priv = dev; | ||
285 | dvb->demux.filternum = 8; | ||
286 | dvb->demux.feednum = 8; | ||
287 | dvb->demux.start_feed = tm6000_start_feed; | ||
288 | dvb->demux.stop_feed = tm6000_stop_feed; | ||
289 | dvb->demux.write_to_decoder = NULL; | ||
290 | ret = dvb_dmx_init(&dvb->demux); | ||
291 | if(ret < 0) { | ||
292 | printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret); | ||
293 | goto frontend_err; | ||
294 | } | ||
295 | |||
296 | dvb->dmxdev.filternum = dev->dvb->demux.filternum; | ||
297 | dvb->dmxdev.demux = &dev->dvb->demux.dmx; | ||
298 | dvb->dmxdev.capabilities = 0; | ||
299 | |||
300 | ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); | ||
301 | if(ret < 0) { | ||
302 | printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret); | ||
303 | goto dvb_dmx_err; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | |||
308 | dvb_dmx_err: | ||
309 | dvb_dmx_release(&dvb->demux); | ||
310 | frontend_err: | ||
311 | if(dvb->frontend) { | ||
312 | dvb_frontend_detach(dvb->frontend); | ||
313 | dvb_unregister_frontend(dvb->frontend); | ||
314 | } | ||
315 | adapter_err: | ||
316 | dvb_unregister_adapter(&dvb->adapter); | ||
317 | err: | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | void tm6000_dvb_unregister(struct tm6000_core *dev) | ||
322 | { | ||
323 | struct tm6000_dvb *dvb = dev->dvb; | ||
324 | |||
325 | if(dvb->bulk_urb != NULL) { | ||
326 | struct urb *bulk_urb = dvb->bulk_urb; | ||
327 | |||
328 | kfree(bulk_urb->transfer_buffer); | ||
329 | bulk_urb->transfer_buffer = NULL; | ||
330 | usb_unlink_urb(bulk_urb); | ||
331 | usb_free_urb(bulk_urb); | ||
332 | } | ||
333 | |||
334 | /* mutex_lock(&tm6000_driver.open_close_mutex); */ | ||
335 | if(dvb->frontend) { | ||
336 | dvb_frontend_detach(dvb->frontend); | ||
337 | dvb_unregister_frontend(dvb->frontend); | ||
338 | } | ||
339 | |||
340 | dvb_dmxdev_release(&dvb->dmxdev); | ||
341 | dvb_dmx_release(&dvb->demux); | ||
342 | dvb_unregister_adapter(&dvb->adapter); | ||
343 | mutex_destroy(&dvb->mutex); | ||
344 | /* mutex_unlock(&tm6000_driver.open_close_mutex); */ | ||
345 | |||
346 | } | ||
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c new file mode 100644 index 000000000000..94ff489a1bbb --- /dev/null +++ b/drivers/staging/tm6000/tm6000-i2c.c | |||
@@ -0,0 +1,370 @@ | |||
1 | /* | ||
2 | tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
5 | |||
6 | Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> | ||
7 | - Fix SMBus Read Byte command | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation version 2 | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/i2c.h> | ||
27 | |||
28 | #include "tm6000.h" | ||
29 | #include "tm6000-regs.h" | ||
30 | #include <media/v4l2-common.h> | ||
31 | #include <media/tuner.h> | ||
32 | #include "tuner-xc2028.h" | ||
33 | |||
34 | |||
35 | /*FIXME: Hack to avoid needing to patch i2c-id.h */ | ||
36 | #define I2C_HW_B_TM6000 I2C_HW_B_EM28XX | ||
37 | /* ----------------------------------------------------------- */ | ||
38 | |||
39 | static unsigned int i2c_debug = 0; | ||
40 | module_param(i2c_debug, int, 0644); | ||
41 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | ||
42 | |||
43 | #define i2c_dprintk(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ | ||
44 | printk(KERN_DEBUG "%s at %s: " fmt, \ | ||
45 | dev->name, __FUNCTION__ , ##args); } while (0) | ||
46 | |||
47 | static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, | ||
48 | __u8 reg, char *buf, int len) | ||
49 | { | ||
50 | int rc; | ||
51 | unsigned int tsleep; | ||
52 | unsigned int i2c_packet_limit = 16; | ||
53 | |||
54 | if (dev->dev_type == TM6010) | ||
55 | i2c_packet_limit = 64; | ||
56 | |||
57 | if (!buf) | ||
58 | return -1; | ||
59 | |||
60 | if (len < 1 || len > i2c_packet_limit) { | ||
61 | printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", | ||
62 | len, i2c_packet_limit); | ||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | /* capture mutex */ | ||
67 | rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
68 | USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, | ||
69 | addr | reg << 8, 0, buf, len); | ||
70 | |||
71 | if (rc < 0) { | ||
72 | /* release mutex */ | ||
73 | return rc; | ||
74 | } | ||
75 | |||
76 | /* Calculate delay time, 14000us for 64 bytes */ | ||
77 | tsleep = ((len * 200) + 200 + 1000) / 1000; | ||
78 | msleep(tsleep); | ||
79 | |||
80 | /* release mutex */ | ||
81 | return rc; | ||
82 | } | ||
83 | |||
84 | /* Generic read - doesn't work fine with 16bit registers */ | ||
85 | static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr, | ||
86 | __u8 reg, char *buf, int len) | ||
87 | { | ||
88 | int rc; | ||
89 | u8 b[2]; | ||
90 | unsigned int i2c_packet_limit = 16; | ||
91 | |||
92 | if (dev->dev_type == TM6010) | ||
93 | i2c_packet_limit = 64; | ||
94 | |||
95 | if (!buf) | ||
96 | return -1; | ||
97 | |||
98 | if (len < 1 || len > i2c_packet_limit) { | ||
99 | printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", | ||
100 | len, i2c_packet_limit); | ||
101 | return -1; | ||
102 | } | ||
103 | |||
104 | /* capture mutex */ | ||
105 | if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) { | ||
106 | /* | ||
107 | * Workaround an I2C bug when reading from zl10353 | ||
108 | */ | ||
109 | reg -= 1; | ||
110 | len += 1; | ||
111 | |||
112 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
113 | REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len); | ||
114 | |||
115 | *buf = b[1]; | ||
116 | } else { | ||
117 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
118 | REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len); | ||
119 | } | ||
120 | |||
121 | /* release mutex */ | ||
122 | return rc; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * read from a 16bit register | ||
127 | * for example xc2028, xc3028 or xc3028L | ||
128 | */ | ||
129 | static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr, | ||
130 | __u16 reg, char *buf, int len) | ||
131 | { | ||
132 | int rc; | ||
133 | unsigned char ureg; | ||
134 | |||
135 | if (!buf || len != 2) | ||
136 | return -1; | ||
137 | |||
138 | /* capture mutex */ | ||
139 | if (dev->dev_type == TM6010) { | ||
140 | ureg = reg & 0xFF; | ||
141 | rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
142 | USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, | ||
143 | addr | (reg & 0xFF00), 0, &ureg, 1); | ||
144 | |||
145 | if (rc < 0) { | ||
146 | /* release mutex */ | ||
147 | return rc; | ||
148 | } | ||
149 | |||
150 | msleep(1400 / 1000); | ||
151 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | | ||
152 | USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, | ||
153 | reg, 0, buf, len); | ||
154 | } else { | ||
155 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | | ||
156 | USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN, | ||
157 | addr, reg, buf, len); | ||
158 | } | ||
159 | |||
160 | /* release mutex */ | ||
161 | return rc; | ||
162 | } | ||
163 | |||
164 | static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, | ||
165 | struct i2c_msg msgs[], int num) | ||
166 | { | ||
167 | struct tm6000_core *dev = i2c_adap->algo_data; | ||
168 | int addr, rc, i, byte; | ||
169 | |||
170 | if (num <= 0) | ||
171 | return 0; | ||
172 | for (i = 0; i < num; i++) { | ||
173 | addr = (msgs[i].addr << 1) & 0xff; | ||
174 | i2c_dprintk(2,"%s %s addr=0x%x len=%d:", | ||
175 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", | ||
176 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | ||
177 | if (msgs[i].flags & I2C_M_RD) { | ||
178 | /* read request without preceding register selection */ | ||
179 | /* | ||
180 | * The TM6000 only supports a read transaction | ||
181 | * immediately after a 1 or 2 byte write to select | ||
182 | * a register. We cannot fulfil this request. | ||
183 | */ | ||
184 | i2c_dprintk(2, " read without preceding write not" | ||
185 | " supported"); | ||
186 | rc = -EOPNOTSUPP; | ||
187 | goto err; | ||
188 | } else if (i + 1 < num && msgs[i].len <= 2 && | ||
189 | (msgs[i + 1].flags & I2C_M_RD) && | ||
190 | msgs[i].addr == msgs[i + 1].addr) { | ||
191 | /* 1 or 2 byte write followed by a read */ | ||
192 | if (i2c_debug >= 2) | ||
193 | for (byte = 0; byte < msgs[i].len; byte++) | ||
194 | printk(" %02x", msgs[i].buf[byte]); | ||
195 | i2c_dprintk(2, "; joined to read %s len=%d:", | ||
196 | i == num - 2 ? "stop" : "nonstop", | ||
197 | msgs[i + 1].len); | ||
198 | |||
199 | if (msgs[i].len == 2) { | ||
200 | rc = tm6000_i2c_recv_regs16(dev, addr, | ||
201 | msgs[i].buf[0] << 8 | msgs[i].buf[1], | ||
202 | msgs[i + 1].buf, msgs[i + 1].len); | ||
203 | } else { | ||
204 | rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0], | ||
205 | msgs[i + 1].buf, msgs[i + 1].len); | ||
206 | } | ||
207 | |||
208 | i++; | ||
209 | |||
210 | if (addr == dev->tuner_addr << 1) { | ||
211 | tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); | ||
212 | tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); | ||
213 | } | ||
214 | if (i2c_debug >= 2) | ||
215 | for (byte = 0; byte < msgs[i].len; byte++) | ||
216 | printk(" %02x", msgs[i].buf[byte]); | ||
217 | } else { | ||
218 | /* write bytes */ | ||
219 | if (i2c_debug >= 2) | ||
220 | for (byte = 0; byte < msgs[i].len; byte++) | ||
221 | printk(" %02x", msgs[i].buf[byte]); | ||
222 | rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0], | ||
223 | msgs[i].buf + 1, msgs[i].len - 1); | ||
224 | |||
225 | if (addr == dev->tuner_addr << 1) { | ||
226 | tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); | ||
227 | tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); | ||
228 | } | ||
229 | } | ||
230 | if (i2c_debug >= 2) | ||
231 | printk("\n"); | ||
232 | if (rc < 0) | ||
233 | goto err; | ||
234 | } | ||
235 | |||
236 | return num; | ||
237 | err: | ||
238 | i2c_dprintk(2," ERROR: %i\n", rc); | ||
239 | return rc; | ||
240 | } | ||
241 | |||
242 | static int tm6000_i2c_eeprom(struct tm6000_core *dev, | ||
243 | unsigned char *eedata, int len) | ||
244 | { | ||
245 | int i, rc; | ||
246 | unsigned char *p = eedata; | ||
247 | unsigned char bytes[17]; | ||
248 | |||
249 | dev->i2c_client.addr = 0xa0 >> 1; | ||
250 | |||
251 | bytes[16] = '\0'; | ||
252 | for (i = 0; i < len; ) { | ||
253 | *p = i; | ||
254 | rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1); | ||
255 | if (rc < 1) { | ||
256 | if (p == eedata) | ||
257 | goto noeeprom; | ||
258 | else { | ||
259 | printk(KERN_WARNING | ||
260 | "%s: i2c eeprom read error (err=%d)\n", | ||
261 | dev->name, rc); | ||
262 | } | ||
263 | return -1; | ||
264 | } | ||
265 | p++; | ||
266 | if (0 == (i % 16)) | ||
267 | printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); | ||
268 | printk(" %02x", eedata[i]); | ||
269 | if ((eedata[i] >= ' ') && (eedata[i] <= 'z')) { | ||
270 | bytes[i%16] = eedata[i]; | ||
271 | } else { | ||
272 | bytes[i%16]='.'; | ||
273 | } | ||
274 | |||
275 | i++; | ||
276 | |||
277 | if (0 == (i % 16)) { | ||
278 | bytes[16] = '\0'; | ||
279 | printk(" %s\n", bytes); | ||
280 | } | ||
281 | } | ||
282 | if (0 != (i%16)) { | ||
283 | bytes[i%16] = '\0'; | ||
284 | for (i %= 16; i < 16; i++) | ||
285 | printk(" "); | ||
286 | } | ||
287 | printk(" %s\n", bytes); | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | noeeprom: | ||
292 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", | ||
293 | dev->name, rc); | ||
294 | return rc; | ||
295 | } | ||
296 | |||
297 | /* ----------------------------------------------------------- */ | ||
298 | |||
299 | /* | ||
300 | * functionality() | ||
301 | */ | ||
302 | static u32 functionality(struct i2c_adapter *adap) | ||
303 | { | ||
304 | return I2C_FUNC_SMBUS_EMUL; | ||
305 | } | ||
306 | |||
307 | #define mass_write(addr, reg, data...) \ | ||
308 | { const static u8 _val[] = data; \ | ||
309 | rc=tm6000_read_write_usb(dev,USB_DIR_OUT | USB_TYPE_VENDOR, \ | ||
310 | REQ_16_SET_GET_I2C_WR1_RDN,(reg<<8)+addr, 0x00, (u8 *) _val, \ | ||
311 | ARRAY_SIZE(_val)); \ | ||
312 | if (rc<0) { \ | ||
313 | printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc); \ | ||
314 | return rc; \ | ||
315 | } \ | ||
316 | msleep (10); \ | ||
317 | } | ||
318 | |||
319 | static struct i2c_algorithm tm6000_algo = { | ||
320 | .master_xfer = tm6000_i2c_xfer, | ||
321 | .functionality = functionality, | ||
322 | }; | ||
323 | |||
324 | static struct i2c_adapter tm6000_adap_template = { | ||
325 | .owner = THIS_MODULE, | ||
326 | .class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, | ||
327 | .name = "tm6000", | ||
328 | .id = I2C_HW_B_TM6000, | ||
329 | .algo = &tm6000_algo, | ||
330 | }; | ||
331 | |||
332 | static struct i2c_client tm6000_client_template = { | ||
333 | .name = "tm6000 internal", | ||
334 | }; | ||
335 | |||
336 | /* ----------------------------------------------------------- */ | ||
337 | |||
338 | /* | ||
339 | * tm6000_i2c_register() | ||
340 | * register i2c bus | ||
341 | */ | ||
342 | int tm6000_i2c_register(struct tm6000_core *dev) | ||
343 | { | ||
344 | unsigned char eedata[256]; | ||
345 | |||
346 | dev->i2c_adap = tm6000_adap_template; | ||
347 | dev->i2c_adap.dev.parent = &dev->udev->dev; | ||
348 | strcpy(dev->i2c_adap.name, dev->name); | ||
349 | dev->i2c_adap.algo_data = dev; | ||
350 | i2c_add_adapter(&dev->i2c_adap); | ||
351 | |||
352 | dev->i2c_client = tm6000_client_template; | ||
353 | dev->i2c_client.adapter = &dev->i2c_adap; | ||
354 | |||
355 | i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); | ||
356 | |||
357 | tm6000_i2c_eeprom(dev, eedata, sizeof(eedata)); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * tm6000_i2c_unregister() | ||
364 | * unregister i2c_bus | ||
365 | */ | ||
366 | int tm6000_i2c_unregister(struct tm6000_core *dev) | ||
367 | { | ||
368 | i2c_del_adapter(&dev->i2c_adap); | ||
369 | return 0; | ||
370 | } | ||
diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/staging/tm6000/tm6000-regs.h new file mode 100644 index 000000000000..1c5289c971fa --- /dev/null +++ b/drivers/staging/tm6000/tm6000-regs.h | |||
@@ -0,0 +1,541 @@ | |||
1 | /* | ||
2 | tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
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 version 2 | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * Define TV Master TM5600/TM6000/TM6010 Request codes | ||
22 | */ | ||
23 | #define REQ_00_SET_IR_VALUE 0 | ||
24 | #define REQ_01_SET_WAKEUP_IRCODE 1 | ||
25 | #define REQ_02_GET_IR_CODE 2 | ||
26 | #define REQ_03_SET_GET_MCU_PIN 3 | ||
27 | #define REQ_04_EN_DISABLE_MCU_INT 4 | ||
28 | #define REQ_05_SET_GET_USBREG 5 | ||
29 | /* Write: RegNum, Value, 0 */ | ||
30 | /* Read : RegNum, Value, 1, RegStatus */ | ||
31 | #define REQ_06_SET_GET_USBREG_BIT 6 | ||
32 | #define REQ_07_SET_GET_AVREG 7 | ||
33 | /* Write: RegNum, Value, 0 */ | ||
34 | /* Read : RegNum, Value, 1, RegStatus */ | ||
35 | #define REQ_08_SET_GET_AVREG_BIT 8 | ||
36 | #define REQ_09_SET_GET_TUNER_FQ 9 | ||
37 | #define REQ_10_SET_TUNER_SYSTEM 10 | ||
38 | #define REQ_11_SET_EEPROM_ADDR 11 | ||
39 | #define REQ_12_SET_GET_EEPROMBYTE 12 | ||
40 | #define REQ_13_GET_EEPROM_SEQREAD 13 | ||
41 | #define REQ_14_SET_GET_I2C_WR2_RDN 14 | ||
42 | #define REQ_15_SET_GET_I2CBYTE 15 | ||
43 | /* Write: Subaddr, Slave Addr, value, 0 */ | ||
44 | /* Read : Subaddr, Slave Addr, value, 1 */ | ||
45 | #define REQ_16_SET_GET_I2C_WR1_RDN 16 | ||
46 | /* Subaddr, Slave Addr, 0, length */ | ||
47 | #define REQ_17_SET_GET_I2CFP 17 | ||
48 | /* Write: Slave Addr, register, value */ | ||
49 | /* Read : Slave Addr, register, 2, data */ | ||
50 | #define REQ_20_DATA_TRANSFER 20 | ||
51 | #define REQ_30_I2C_WRITE 30 | ||
52 | #define REQ_31_I2C_READ 31 | ||
53 | #define REQ_35_AFTEK_TUNER_READ 35 | ||
54 | #define REQ_40_GET_VERSION 40 | ||
55 | #define REQ_50_SET_START 50 | ||
56 | #define REQ_51_SET_STOP 51 | ||
57 | #define REQ_52_TRANSMIT_DATA 52 | ||
58 | #define REQ_53_SPI_INITIAL 53 | ||
59 | #define REQ_54_SPI_SETSTART 54 | ||
60 | #define REQ_55_SPI_INOUTDATA 55 | ||
61 | #define REQ_56_SPI_SETSTOP 56 | ||
62 | |||
63 | /* | ||
64 | * Define TV Master TM5600/TM6000/TM6010 GPIO lines | ||
65 | */ | ||
66 | |||
67 | #define TM6000_GPIO_CLK 0x101 | ||
68 | #define TM6000_GPIO_DATA 0x100 | ||
69 | |||
70 | #define TM6000_GPIO_1 0x102 | ||
71 | #define TM6000_GPIO_2 0x103 | ||
72 | #define TM6000_GPIO_3 0x104 | ||
73 | #define TM6000_GPIO_4 0x300 | ||
74 | #define TM6000_GPIO_5 0x301 | ||
75 | #define TM6000_GPIO_6 0x304 | ||
76 | #define TM6000_GPIO_7 0x305 | ||
77 | |||
78 | /* tm6010 defines GPIO with different values */ | ||
79 | #define TM6010_GPIO_0 0x0102 | ||
80 | #define TM6010_GPIO_1 0x0103 | ||
81 | #define TM6010_GPIO_2 0x0104 | ||
82 | #define TM6010_GPIO_3 0x0105 | ||
83 | #define TM6010_GPIO_4 0x0106 | ||
84 | #define TM6010_GPIO_5 0x0107 | ||
85 | #define TM6010_GPIO_6 0x0300 | ||
86 | #define TM6010_GPIO_7 0x0301 | ||
87 | #define TM6010_GPIO_9 0x0305 | ||
88 | /* | ||
89 | * Define TV Master TM5600/TM6000/TM6010 URB message codes and length | ||
90 | */ | ||
91 | |||
92 | enum { | ||
93 | TM6000_URB_MSG_VIDEO=1, | ||
94 | TM6000_URB_MSG_AUDIO, | ||
95 | TM6000_URB_MSG_VBI, | ||
96 | TM6000_URB_MSG_PTS, | ||
97 | TM6000_URB_MSG_ERR, | ||
98 | }; | ||
99 | |||
100 | /* Define TM6000/TM6010 Video decoder registers */ | ||
101 | #define TM6010_REQ07_R00_VIDEO_CONTROL0 0x07, 0x00 | ||
102 | #define TM6010_REQ07_R01_VIDEO_CONTROL1 0x07, 0x01 | ||
103 | #define TM6010_REQ07_R02_VIDEO_CONTROL2 0x07, 0x02 | ||
104 | #define TM6010_REQ07_R03_YC_SEP_CONTROL 0x07, 0x03 | ||
105 | #define TM6010_REQ07_R04_LUMA_HAGC_CONTROL 0x07, 0x04 | ||
106 | #define TM6010_REQ07_R05_NOISE_THRESHOLD 0x07, 0x05 | ||
107 | #define TM6010_REQ07_R06_AGC_GATE_THRESHOLD 0x07, 0x06 | ||
108 | #define TM6010_REQ07_R07_OUTPUT_CONTROL 0x07, 0x07 | ||
109 | #define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ 0x07, 0x08 | ||
110 | #define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ 0x07, 0x09 | ||
111 | #define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ 0x07, 0x0a | ||
112 | #define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ 0x07, 0x0b | ||
113 | #define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL 0x07, 0x0c | ||
114 | #define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL 0x07, 0x0d | ||
115 | #define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION 0x07, 0x0f | ||
116 | #define TM6010_REQ07_R10_AGC_PEAK_NOMINAL 0x07, 0x10 | ||
117 | #define TM6010_REQ07_R11_AGC_PEAK_CONTROL 0x07, 0x11 | ||
118 | #define TM6010_REQ07_R12_AGC_GATE_STARTH 0x07, 0x12 | ||
119 | #define TM6010_REQ07_R13_AGC_GATE_STARTL 0x07, 0x13 | ||
120 | #define TM6010_REQ07_R14_AGC_GATE_WIDTH 0x07, 0x14 | ||
121 | #define TM6010_REQ07_R15_AGC_BP_DELAY 0x07, 0x15 | ||
122 | #define TM6010_REQ07_R16_LOCK_COUNT 0x07, 0x16 | ||
123 | #define TM6010_REQ07_R17_HLOOP_MAXSTATE 0x07, 0x17 | ||
124 | #define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3 0x07, 0x18 | ||
125 | #define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2 0x07, 0x19 | ||
126 | #define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1 0x07, 0x1a | ||
127 | #define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0 0x07, 0x1b | ||
128 | #define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3 0x07, 0x1c | ||
129 | #define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2 0x07, 0x1d | ||
130 | #define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1 0x07, 0x1e | ||
131 | #define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0 0x07, 0x1f | ||
132 | #define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME 0x07, 0x20 | ||
133 | #define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET 0x07, 0x21 | ||
134 | #define TM6010_REQ07_R22_HSYNC_PLL_START_TIME 0x07, 0x22 | ||
135 | #define TM6010_REQ07_R23_HSYNC_PLL_END_TIME 0x07, 0x23 | ||
136 | #define TM6010_REQ07_R24_HSYNC_TIP_START_TIME 0x07, 0x24 | ||
137 | #define TM6010_REQ07_R25_HSYNC_TIP_END_TIME 0x07, 0x25 | ||
138 | #define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START 0x07, 0x26 | ||
139 | #define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END 0x07, 0x27 | ||
140 | #define TM6010_REQ07_R28_BACKPORCH_START 0x07, 0x28 | ||
141 | #define TM6010_REQ07_R29_BACKPORCH_END 0x07, 0x29 | ||
142 | #define TM6010_REQ07_R2A_HSYNC_FILTER_START 0x07, 0x2a | ||
143 | #define TM6010_REQ07_R2B_HSYNC_FILTER_END 0x07, 0x2b | ||
144 | #define TM6010_REQ07_R2C_CHROMA_BURST_START 0x07, 0x2c | ||
145 | #define TM6010_REQ07_R2D_CHROMA_BURST_END 0x07, 0x2d | ||
146 | #define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART 0x07, 0x2e | ||
147 | #define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH 0x07, 0x2f | ||
148 | #define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART 0x07, 0x30 | ||
149 | #define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT 0x07, 0x31 | ||
150 | #define TM6010_REQ07_R32_VSYNC_HLOCK_MIN 0x07, 0x32 | ||
151 | #define TM6010_REQ07_R33_VSYNC_HLOCK_MAX 0x07, 0x33 | ||
152 | #define TM6010_REQ07_R34_VSYNC_AGC_MIN 0x07, 0x34 | ||
153 | #define TM6010_REQ07_R35_VSYNC_AGC_MAX 0x07, 0x35 | ||
154 | #define TM6010_REQ07_R36_VSYNC_VBI_MIN 0x07, 0x36 | ||
155 | #define TM6010_REQ07_R37_VSYNC_VBI_MAX 0x07, 0x37 | ||
156 | #define TM6010_REQ07_R38_VSYNC_THRESHOLD 0x07, 0x38 | ||
157 | #define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT 0x07, 0x39 | ||
158 | #define TM6010_REQ07_R3A_STATUS1 0x07, 0x3a | ||
159 | #define TM6010_REQ07_R3B_STATUS2 0x07, 0x3b | ||
160 | #define TM6010_REQ07_R3C_STATUS3 0x07, 0x3c | ||
161 | #define TM6010_REQ07_R3F_RESET 0x07, 0x3f | ||
162 | #define TM6010_REQ07_R40_TELETEXT_VBI_CODE0 0x07, 0x40 | ||
163 | #define TM6010_REQ07_R41_TELETEXT_VBI_CODE1 0x07, 0x41 | ||
164 | #define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL 0x07, 0x42 | ||
165 | #define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7 0x07, 0x43 | ||
166 | #define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8 0x07, 0x44 | ||
167 | #define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9 0x07, 0x45 | ||
168 | #define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10 0x07, 0x46 | ||
169 | #define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11 0x07, 0x47 | ||
170 | #define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12 0x07, 0x48 | ||
171 | #define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13 0x07, 0x49 | ||
172 | #define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14 0x07, 0x4a | ||
173 | #define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15 0x07, 0x4b | ||
174 | #define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16 0x07, 0x4c | ||
175 | #define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17 0x07, 0x4d | ||
176 | #define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18 0x07, 0x4e | ||
177 | #define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19 0x07, 0x4f | ||
178 | #define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20 0x07, 0x50 | ||
179 | #define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 0x07, 0x51 | ||
180 | #define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22 0x07, 0x52 | ||
181 | #define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23 0x07, 0x53 | ||
182 | #define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES 0x07, 0x54 | ||
183 | #define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN 0x07, 0x55 | ||
184 | #define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN 0x07, 0x56 | ||
185 | #define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN 0x07, 0x57 | ||
186 | #define TM6010_REQ07_R58_VBI_CAPTION_DTO1 0x07, 0x58 | ||
187 | #define TM6010_REQ07_R59_VBI_CAPTION_DTO0 0x07, 0x59 | ||
188 | #define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1 0x07, 0x5a | ||
189 | #define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0 0x07, 0x5b | ||
190 | #define TM6010_REQ07_R5C_VBI_WSS625_DTO1 0x07, 0x5c | ||
191 | #define TM6010_REQ07_R5D_VBI_WSS625_DTO0 0x07, 0x5d | ||
192 | #define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START 0x07, 0x5e | ||
193 | #define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START 0x07, 0x5f | ||
194 | #define TM6010_REQ07_R60_TELETEXT_FRAME_START 0x07, 0x60 | ||
195 | #define TM6010_REQ07_R61_VBI_CCDATA1 0x07, 0x61 | ||
196 | #define TM6010_REQ07_R62_VBI_CCDATA2 0x07, 0x62 | ||
197 | #define TM6010_REQ07_R63_VBI_WSS625_DATA1 0x07, 0x63 | ||
198 | #define TM6010_REQ07_R64_VBI_WSS625_DATA2 0x07, 0x64 | ||
199 | #define TM6010_REQ07_R65_VBI_DATA_STATUS 0x07, 0x65 | ||
200 | #define TM6010_REQ07_R66_VBI_CAPTION_START 0x07, 0x66 | ||
201 | #define TM6010_REQ07_R67_VBI_WSS625_START 0x07, 0x67 | ||
202 | #define TM6010_REQ07_R68_VBI_TELETEXT_START 0x07, 0x68 | ||
203 | #define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3 0x07, 0x70 | ||
204 | #define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2 0x07, 0x71 | ||
205 | #define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1 0x07, 0x72 | ||
206 | #define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0 0x07, 0x73 | ||
207 | #define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3 0x07, 0x74 | ||
208 | #define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2 0x07, 0x75 | ||
209 | #define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1 0x07, 0x76 | ||
210 | #define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0 0x07, 0x77 | ||
211 | #define TM6010_REQ07_R78_AGC_AGAIN_STATUS 0x07, 0x78 | ||
212 | #define TM6010_REQ07_R79_AGC_DGAIN_STATUS 0x07, 0x79 | ||
213 | #define TM6010_REQ07_R7A_CHROMA_MAG_STATUS 0x07, 0x7a | ||
214 | #define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1 0x07, 0x7b | ||
215 | #define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0 0x07, 0x7c | ||
216 | #define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS 0x07, 0x7d | ||
217 | #define TM6010_REQ07_R7F_STATUS_NOISE 0x07, 0x7f | ||
218 | #define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD 0x07, 0x80 | ||
219 | #define TM6010_REQ07_R82_COMB_FILTER_CONFIG 0x07, 0x82 | ||
220 | #define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG 0x07, 0x83 | ||
221 | #define TM6010_REQ07_R84_NOISE_NTSC_C 0x07, 0x84 | ||
222 | #define TM6010_REQ07_R85_NOISE_PAL_C 0x07, 0x85 | ||
223 | #define TM6010_REQ07_R86_NOISE_PHASE_C 0x07, 0x86 | ||
224 | #define TM6010_REQ07_R87_NOISE_PHASE_Y 0x07, 0x87 | ||
225 | #define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE 0x07, 0x8a | ||
226 | #define TM6010_REQ07_R8B_CHROMA_HRESAMPLER 0x07, 0x8b | ||
227 | #define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ 0x07, 0x8d | ||
228 | #define TM6010_REQ07_R8E_CPUMP_ADJ 0x07, 0x8e | ||
229 | #define TM6010_REQ07_R8F_CPUMP_DELAY 0x07, 0x8f | ||
230 | |||
231 | /* Define TM6000/TM6010 Miscellaneous registers */ | ||
232 | #define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE 0x07, 0xc0 | ||
233 | #define TM6010_REQ07_RC1_TRESHOLD 0x07, 0xc1 | ||
234 | #define TM6010_REQ07_RC2_HSYNC_WIDTH 0x07, 0xc2 | ||
235 | #define TM6010_REQ07_RC3_HSTART1 0x07, 0xc3 | ||
236 | #define TM6010_REQ07_RC4_HSTART0 0x07, 0xc4 | ||
237 | #define TM6010_REQ07_RC5_HEND1 0x07, 0xc5 | ||
238 | #define TM6010_REQ07_RC6_HEND0 0x07, 0xc6 | ||
239 | #define TM6010_REQ07_RC7_VSTART1 0x07, 0xc7 | ||
240 | #define TM6010_REQ07_RC8_VSTART0 0x07, 0xc8 | ||
241 | #define TM6010_REQ07_RC9_VEND1 0x07, 0xc9 | ||
242 | #define TM6010_REQ07_RCA_VEND0 0x07, 0xca | ||
243 | #define TM6010_REQ07_RCB_DELAY 0x07, 0xcb | ||
244 | #define TM6010_REQ07_RCC_ACTIVE_VIDEO_IF 0x07, 0xcc | ||
245 | #define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL 0x07, 0xd0 | ||
246 | #define TM6010_REQ07_RD1_ADDR_FOR_REQ1 0x07, 0xd1 | ||
247 | #define TM6010_REQ07_RD2_ADDR_FOR_REQ2 0x07, 0xd2 | ||
248 | #define TM6010_REQ07_RD3_ADDR_FOR_REQ3 0x07, 0xd3 | ||
249 | #define TM6010_REQ07_RD4_ADDR_FOR_REQ4 0x07, 0xd4 | ||
250 | #define TM6010_REQ07_RD5_POWERSAVE 0x07, 0xd5 | ||
251 | #define TM6010_REQ07_RD6_ENDP_REQ1_REQ2 0x07, 0xd6 | ||
252 | #define TM6010_REQ07_RD7_ENDP_REQ3_REQ4 0x07, 0xd7 | ||
253 | #define TM6010_REQ07_RD8_IR 0x07, 0xd8 | ||
254 | #define TM6010_REQ07_RD8_IR_BSIZE 0x07, 0xd9 | ||
255 | #define TM6010_REQ07_RD8_IR_WAKEUP_SEL 0x07, 0xda | ||
256 | #define TM6010_REQ07_RD8_IR_WAKEUP_ADD 0x07, 0xdb | ||
257 | #define TM6010_REQ07_RD8_IR_LEADER1 0x07, 0xdc | ||
258 | #define TM6010_REQ07_RD8_IR_LEADER0 0x07, 0xdd | ||
259 | #define TM6010_REQ07_RD8_IR_PULSE_CNT1 0x07, 0xde | ||
260 | #define TM6010_REQ07_RD8_IR_PULSE_CNT0 0x07, 0xdf | ||
261 | #define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 | ||
262 | #define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF 0x07, 0xe1 | ||
263 | #define TM6010_REQ07_RE2_OUT_SEL2 0x07, 0xe2 | ||
264 | #define TM6010_REQ07_RE3_OUT_SEL1 0x07, 0xe3 | ||
265 | #define TM6010_REQ07_RE4_OUT_SEL0 0x07, 0xe4 | ||
266 | #define TM6010_REQ07_RE5_REMOTE_WAKEUP 0x07, 0xe5 | ||
267 | #define TM6010_REQ07_RE7_PUB_GPIO 0x07, 0xe7 | ||
268 | #define TM6010_REQ07_RE8_TYPESEL_MOS_I2S 0x07, 0xe8 | ||
269 | #define TM6010_REQ07_RE9_TYPESEL_MOS_TS 0x07, 0xe9 | ||
270 | #define TM6010_REQ07_REA_TYPESEL_MOS_CCIR 0x07, 0xea | ||
271 | #define TM6010_REQ07_RF0_BIST_CRC_RESULT0 0x07, 0xf0 | ||
272 | #define TM6010_REQ07_RF1_BIST_CRC_RESULT1 0x07, 0xf1 | ||
273 | #define TM6010_REQ07_RF2_BIST_CRC_RESULT2 0x07, 0xf2 | ||
274 | #define TM6010_REQ07_RF3_BIST_CRC_RESULT3 0x07, 0xf3 | ||
275 | #define TM6010_REQ07_RF4_BIST_ERR_VST2 0x07, 0xf4 | ||
276 | #define TM6010_REQ07_RF5_BIST_ERR_VST1 0x07, 0xf5 | ||
277 | #define TM6010_REQ07_RF6_BIST_ERR_VST0 0x07, 0xf6 | ||
278 | #define TM6010_REQ07_RF7_BIST 0x07, 0xf7 | ||
279 | #define TM6010_REQ07_RFE_POWER_DOWN 0x07, 0xfe | ||
280 | #define TM6010_REQ07_RFF_SOFT_RESET 0x07, 0xff | ||
281 | |||
282 | /* Define TM6000/TM6010 USB registers */ | ||
283 | #define TM6010_REQ05_R00_MAIN_CTRL 0x05, 0x00 | ||
284 | #define TM6010_REQ05_R01_DEVADDR 0x05, 0x01 | ||
285 | #define TM6010_REQ05_R02_TEST 0x05, 0x02 | ||
286 | #define TM6010_REQ05_R04_SOFN0 0x05, 0x04 | ||
287 | #define TM6010_REQ05_R05_SOFN1 0x05, 0x05 | ||
288 | #define TM6010_REQ05_R06_SOFTM0 0x05, 0x06 | ||
289 | #define TM6010_REQ05_R07_SOFTM1 0x05, 0x07 | ||
290 | #define TM6010_REQ05_R08_PHY_TEST 0x05, 0x08 | ||
291 | #define TM6010_REQ05_R09_VCTL 0x05, 0x09 | ||
292 | #define TM6010_REQ05_R0A_VSTA 0x05, 0x0a | ||
293 | #define TM6010_REQ05_R0B_CX_CFG 0x05, 0x0b | ||
294 | #define TM6010_REQ05_R0C_ENDP0_REG0 0x05, 0x0c | ||
295 | #define TM6010_REQ05_R10_GMASK 0x05, 0x10 | ||
296 | #define TM6010_REQ05_R11_IMASK0 0x05, 0x11 | ||
297 | #define TM6010_REQ05_R12_IMASK1 0x05, 0x12 | ||
298 | #define TM6010_REQ05_R13_IMASK2 0x05, 0x13 | ||
299 | #define TM6010_REQ05_R14_IMASK3 0x05, 0x14 | ||
300 | #define TM6010_REQ05_R15_IMASK4 0x05, 0x15 | ||
301 | #define TM6010_REQ05_R16_IMASK5 0x05, 0x16 | ||
302 | #define TM6010_REQ05_R17_IMASK6 0x05, 0x17 | ||
303 | #define TM6010_REQ05_R18_IMASK7 0x05, 0x18 | ||
304 | #define TM6010_REQ05_R19_ZEROP0 0x05, 0x19 | ||
305 | #define TM6010_REQ05_R1A_ZEROP1 0x05, 0x1a | ||
306 | #define TM6010_REQ05_R1C_FIFO_EMP0 0x05, 0x1c | ||
307 | #define TM6010_REQ05_R1D_FIFO_EMP1 0x05, 0x1d | ||
308 | #define TM6010_REQ05_R20_IRQ_GROUP 0x05, 0x20 | ||
309 | #define TM6010_REQ05_R21_IRQ_SOURCE0 0x05, 0x21 | ||
310 | #define TM6010_REQ05_R22_IRQ_SOURCE1 0x05, 0x22 | ||
311 | #define TM6010_REQ05_R23_IRQ_SOURCE2 0x05, 0x23 | ||
312 | #define TM6010_REQ05_R24_IRQ_SOURCE3 0x05, 0x24 | ||
313 | #define TM6010_REQ05_R25_IRQ_SOURCE4 0x05, 0x25 | ||
314 | #define TM6010_REQ05_R26_IRQ_SOURCE5 0x05, 0x26 | ||
315 | #define TM6010_REQ05_R27_IRQ_SOURCE6 0x05, 0x27 | ||
316 | #define TM6010_REQ05_R28_IRQ_SOURCE7 0x05, 0x28 | ||
317 | #define TM6010_REQ05_R29_SEQ_ERR0 0x05, 0x29 | ||
318 | #define TM6010_REQ05_R2A_SEQ_ERR1 0x05, 0x2a | ||
319 | #define TM6010_REQ05_R2B_SEQ_ABORT0 0x05, 0x2b | ||
320 | #define TM6010_REQ05_R2C_SEQ_ABORT1 0x05, 0x2c | ||
321 | #define TM6010_REQ05_R2D_TX_ZERO0 0x05, 0x2d | ||
322 | #define TM6010_REQ05_R2E_TX_ZERO1 0x05, 0x2e | ||
323 | #define TM6010_REQ05_R2F_IDLE_CNT 0x05, 0x2f | ||
324 | #define TM6010_REQ05_R30_FNO_P1 0x05, 0x30 | ||
325 | #define TM6010_REQ05_R31_FNO_P2 0x05, 0x31 | ||
326 | #define TM6010_REQ05_R32_FNO_P3 0x05, 0x32 | ||
327 | #define TM6010_REQ05_R33_FNO_P4 0x05, 0x33 | ||
328 | #define TM6010_REQ05_R34_FNO_P5 0x05, 0x34 | ||
329 | #define TM6010_REQ05_R35_FNO_P6 0x05, 0x35 | ||
330 | #define TM6010_REQ05_R36_FNO_P7 0x05, 0x36 | ||
331 | #define TM6010_REQ05_R37_FNO_P8 0x05, 0x37 | ||
332 | #define TM6010_REQ05_R38_FNO_P9 0x05, 0x38 | ||
333 | #define TM6010_REQ05_R30_FNO_P10 0x05, 0x39 | ||
334 | #define TM6010_REQ05_R30_FNO_P11 0x05, 0x3a | ||
335 | #define TM6010_REQ05_R30_FNO_P12 0x05, 0x3b | ||
336 | #define TM6010_REQ05_R30_FNO_P13 0x05, 0x3c | ||
337 | #define TM6010_REQ05_R30_FNO_P14 0x05, 0x3d | ||
338 | #define TM6010_REQ05_R30_FNO_P15 0x05, 0x3e | ||
339 | #define TM6010_REQ05_R40_IN_MAXPS_LOW1 0x05, 0x40 | ||
340 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH1 0x05, 0x41 | ||
341 | #define TM6010_REQ05_R42_IN_MAXPS_LOW2 0x05, 0x42 | ||
342 | #define TM6010_REQ05_R43_IN_MAXPS_HIGH2 0x05, 0x43 | ||
343 | #define TM6010_REQ05_R44_IN_MAXPS_LOW3 0x05, 0x44 | ||
344 | #define TM6010_REQ05_R45_IN_MAXPS_HIGH3 0x05, 0x45 | ||
345 | #define TM6010_REQ05_R46_IN_MAXPS_LOW4 0x05, 0x46 | ||
346 | #define TM6010_REQ05_R47_IN_MAXPS_HIGH4 0x05, 0x47 | ||
347 | #define TM6010_REQ05_R48_IN_MAXPS_LOW5 0x05, 0x48 | ||
348 | #define TM6010_REQ05_R49_IN_MAXPS_HIGH5 0x05, 0x49 | ||
349 | #define TM6010_REQ05_R4A_IN_MAXPS_LOW6 0x05, 0x4a | ||
350 | #define TM6010_REQ05_R4B_IN_MAXPS_HIGH6 0x05, 0x4b | ||
351 | #define TM6010_REQ05_R4C_IN_MAXPS_LOW7 0x05, 0x4c | ||
352 | #define TM6010_REQ05_R4D_IN_MAXPS_HIGH7 0x05, 0x4d | ||
353 | #define TM6010_REQ05_R4E_IN_MAXPS_LOW8 0x05, 0x4e | ||
354 | #define TM6010_REQ05_R4F_IN_MAXPS_HIGH8 0x05, 0x4f | ||
355 | #define TM6010_REQ05_R50_IN_MAXPS_LOW9 0x05, 0x50 | ||
356 | #define TM6010_REQ05_R51_IN_MAXPS_HIGH9 0x05, 0x51 | ||
357 | #define TM6010_REQ05_R40_IN_MAXPS_LOW10 0x05, 0x52 | ||
358 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH10 0x05, 0x53 | ||
359 | #define TM6010_REQ05_R40_IN_MAXPS_LOW11 0x05, 0x54 | ||
360 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH11 0x05, 0x55 | ||
361 | #define TM6010_REQ05_R40_IN_MAXPS_LOW12 0x05, 0x56 | ||
362 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH12 0x05, 0x57 | ||
363 | #define TM6010_REQ05_R40_IN_MAXPS_LOW13 0x05, 0x58 | ||
364 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH13 0x05, 0x59 | ||
365 | #define TM6010_REQ05_R40_IN_MAXPS_LOW14 0x05, 0x5a | ||
366 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH14 0x05, 0x5b | ||
367 | #define TM6010_REQ05_R40_IN_MAXPS_LOW15 0x05, 0x5c | ||
368 | #define TM6010_REQ05_R41_IN_MAXPS_HIGH15 0x05, 0x5d | ||
369 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW1 0x05, 0x60 | ||
370 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH1 0x05, 0x61 | ||
371 | #define TM6010_REQ05_R62_OUT_MAXPS_LOW2 0x05, 0x62 | ||
372 | #define TM6010_REQ05_R63_OUT_MAXPS_HIGH2 0x05, 0x63 | ||
373 | #define TM6010_REQ05_R64_OUT_MAXPS_LOW3 0x05, 0x64 | ||
374 | #define TM6010_REQ05_R65_OUT_MAXPS_HIGH3 0x05, 0x65 | ||
375 | #define TM6010_REQ05_R66_OUT_MAXPS_LOW4 0x05, 0x66 | ||
376 | #define TM6010_REQ05_R67_OUT_MAXPS_HIGH4 0x05, 0x67 | ||
377 | #define TM6010_REQ05_R68_OUT_MAXPS_LOW5 0x05, 0x68 | ||
378 | #define TM6010_REQ05_R69_OUT_MAXPS_HIGH5 0x05, 0x69 | ||
379 | #define TM6010_REQ05_R6A_OUT_MAXPS_LOW6 0x05, 0x6a | ||
380 | #define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6 0x05, 0x6b | ||
381 | #define TM6010_REQ05_R6C_OUT_MAXPS_LOW7 0x05, 0x6c | ||
382 | #define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7 0x05, 0x6d | ||
383 | #define TM6010_REQ05_R6E_OUT_MAXPS_LOW8 0x05, 0x6e | ||
384 | #define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8 0x05, 0x6f | ||
385 | #define TM6010_REQ05_R70_OUT_MAXPS_LOW9 0x05, 0x70 | ||
386 | #define TM6010_REQ05_R71_OUT_MAXPS_HIGH9 0x05, 0x71 | ||
387 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW10 0x05, 0x72 | ||
388 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH10 0x05, 0x73 | ||
389 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW11 0x05, 0x74 | ||
390 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH11 0x05, 0x75 | ||
391 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW12 0x05, 0x76 | ||
392 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH12 0x05, 0x77 | ||
393 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW13 0x05, 0x78 | ||
394 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH13 0x05, 0x79 | ||
395 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW14 0x05, 0x7a | ||
396 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH14 0x05, 0x7b | ||
397 | #define TM6010_REQ05_R60_OUT_MAXPS_LOW15 0x05, 0x7c | ||
398 | #define TM6010_REQ05_R61_OUT_MAXPS_HIGH15 0x05, 0x7d | ||
399 | #define TM6010_REQ05_R80_FIFO0 0x05, 0x80 | ||
400 | #define TM6010_REQ05_R81_FIFO1 0x05, 0x81 | ||
401 | #define TM6010_REQ05_R82_FIFO2 0x05, 0x82 | ||
402 | #define TM6010_REQ05_R83_FIFO3 0x05, 0x83 | ||
403 | #define TM6010_REQ05_R84_FIFO4 0x05, 0x84 | ||
404 | #define TM6010_REQ05_R85_FIFO5 0x05, 0x85 | ||
405 | #define TM6010_REQ05_R86_FIFO6 0x05, 0x86 | ||
406 | #define TM6010_REQ05_R87_FIFO7 0x05, 0x87 | ||
407 | #define TM6010_REQ05_R88_FIFO8 0x05, 0x88 | ||
408 | #define TM6010_REQ05_R89_FIFO9 0x05, 0x89 | ||
409 | #define TM6010_REQ05_R81_FIFO10 0x05, 0x8a | ||
410 | #define TM6010_REQ05_R81_FIFO11 0x05, 0x8b | ||
411 | #define TM6010_REQ05_R81_FIFO12 0x05, 0x8c | ||
412 | #define TM6010_REQ05_R81_FIFO13 0x05, 0x8d | ||
413 | #define TM6010_REQ05_R81_FIFO14 0x05, 0x8e | ||
414 | #define TM6010_REQ05_R81_FIFO15 0x05, 0x8f | ||
415 | #define TM6010_REQ05_R90_CFG_FIFO0 0x05, 0x90 | ||
416 | #define TM6010_REQ05_R91_CFG_FIFO1 0x05, 0x91 | ||
417 | #define TM6010_REQ05_R92_CFG_FIFO2 0x05, 0x92 | ||
418 | #define TM6010_REQ05_R93_CFG_FIFO3 0x05, 0x93 | ||
419 | #define TM6010_REQ05_R94_CFG_FIFO4 0x05, 0x94 | ||
420 | #define TM6010_REQ05_R95_CFG_FIFO5 0x05, 0x95 | ||
421 | #define TM6010_REQ05_R96_CFG_FIFO6 0x05, 0x96 | ||
422 | #define TM6010_REQ05_R97_CFG_FIFO7 0x05, 0x97 | ||
423 | #define TM6010_REQ05_R98_CFG_FIFO8 0x05, 0x98 | ||
424 | #define TM6010_REQ05_R99_CFG_FIFO9 0x05, 0x99 | ||
425 | #define TM6010_REQ05_R91_CFG_FIFO10 0x05, 0x9a | ||
426 | #define TM6010_REQ05_R91_CFG_FIFO11 0x05, 0x9b | ||
427 | #define TM6010_REQ05_R91_CFG_FIFO12 0x05, 0x9c | ||
428 | #define TM6010_REQ05_R91_CFG_FIFO13 0x05, 0x9d | ||
429 | #define TM6010_REQ05_R91_CFG_FIFO14 0x05, 0x9e | ||
430 | #define TM6010_REQ05_R91_CFG_FIFO15 0x05, 0x9f | ||
431 | #define TM6010_REQ05_RA0_CTL_FIFO0 0x05, 0xa0 | ||
432 | #define TM6010_REQ05_RA1_CTL_FIFO1 0x05, 0xa1 | ||
433 | #define TM6010_REQ05_RA2_CTL_FIFO2 0x05, 0xa2 | ||
434 | #define TM6010_REQ05_RA3_CTL_FIFO3 0x05, 0xa3 | ||
435 | #define TM6010_REQ05_RA4_CTL_FIFO4 0x05, 0xa4 | ||
436 | #define TM6010_REQ05_RA5_CTL_FIFO5 0x05, 0xa5 | ||
437 | #define TM6010_REQ05_RA6_CTL_FIFO6 0x05, 0xa6 | ||
438 | #define TM6010_REQ05_RA7_CTL_FIFO7 0x05, 0xa7 | ||
439 | #define TM6010_REQ05_RA8_CTL_FIFO8 0x05, 0xa8 | ||
440 | #define TM6010_REQ05_RA9_CTL_FIFO9 0x05, 0xa9 | ||
441 | #define TM6010_REQ05_RA1_CTL_FIFO10 0x05, 0xaa | ||
442 | #define TM6010_REQ05_RA1_CTL_FIFO11 0x05, 0xab | ||
443 | #define TM6010_REQ05_RA1_CTL_FIFO12 0x05, 0xac | ||
444 | #define TM6010_REQ05_RA1_CTL_FIFO13 0x05, 0xad | ||
445 | #define TM6010_REQ05_RA1_CTL_FIFO14 0x05, 0xae | ||
446 | #define TM6010_REQ05_RA1_CTL_FIFO15 0x05, 0xaf | ||
447 | #define TM6010_REQ05_RB0_BC_LOW_FIFO0 0x05, 0xb0 | ||
448 | #define TM6010_REQ05_RB1_BC_LOW_FIFO1 0x05, 0xb1 | ||
449 | #define TM6010_REQ05_RB2_BC_LOW_FIFO2 0x05, 0xb2 | ||
450 | #define TM6010_REQ05_RB3_BC_LOW_FIFO3 0x05, 0xb3 | ||
451 | #define TM6010_REQ05_RB4_BC_LOW_FIFO4 0x05, 0xb4 | ||
452 | #define TM6010_REQ05_RB5_BC_LOW_FIFO5 0x05, 0xb5 | ||
453 | #define TM6010_REQ05_RB6_BC_LOW_FIFO6 0x05, 0xb6 | ||
454 | #define TM6010_REQ05_RB7_BC_LOW_FIFO7 0x05, 0xb7 | ||
455 | #define TM6010_REQ05_RB8_BC_LOW_FIFO8 0x05, 0xb8 | ||
456 | #define TM6010_REQ05_RB9_BC_LOW_FIFO9 0x05, 0xb9 | ||
457 | #define TM6010_REQ05_RB1_BC_LOW_FIFO10 0x05, 0xba | ||
458 | #define TM6010_REQ05_RB1_BC_LOW_FIFO11 0x05, 0xbb | ||
459 | #define TM6010_REQ05_RB1_BC_LOW_FIFO12 0x05, 0xbc | ||
460 | #define TM6010_REQ05_RB1_BC_LOW_FIFO13 0x05, 0xbd | ||
461 | #define TM6010_REQ05_RB1_BC_LOW_FIFO14 0x05, 0xbe | ||
462 | #define TM6010_REQ05_RB1_BC_LOW_FIFO15 0x05, 0xbf | ||
463 | #define TM6010_REQ05_RC0_DATA_FIFO0 0x05, 0xc0 | ||
464 | #define TM6010_REQ05_RC4_DATA_FIFO1 0x05, 0xc4 | ||
465 | #define TM6010_REQ05_RC8_DATA_FIFO2 0x05, 0xc8 | ||
466 | #define TM6010_REQ05_RCC_DATA_FIFO3 0x05, 0xcc | ||
467 | #define TM6010_REQ05_RD0_DATA_FIFO4 0x05, 0xd0 | ||
468 | #define TM6010_REQ05_RD4_DATA_FIFO5 0x05, 0xd4 | ||
469 | #define TM6010_REQ05_RD8_DATA_FIFO6 0x05, 0xd8 | ||
470 | #define TM6010_REQ05_RDC_DATA_FIFO7 0x05, 0xdc | ||
471 | #define TM6010_REQ05_RE0_DATA_FIFO8 0x05, 0xe0 | ||
472 | #define TM6010_REQ05_RE4_DATA_FIFO9 0x05, 0xe4 | ||
473 | #define TM6010_REQ05_RC4_DATA_FIFO10 0x05, 0xe8 | ||
474 | #define TM6010_REQ05_RC4_DATA_FIFO11 0x05, 0xec | ||
475 | #define TM6010_REQ05_RC4_DATA_FIFO12 0x05, 0xf0 | ||
476 | #define TM6010_REQ05_RC4_DATA_FIFO13 0x05, 0xf4 | ||
477 | #define TM6010_REQ05_RC4_DATA_FIFO14 0x05, 0xf8 | ||
478 | #define TM6010_REQ05_RC4_DATA_FIFO15 0x05, 0xfc | ||
479 | |||
480 | /* Define TM6000/TM6010 Audio decoder registers */ | ||
481 | #define TM6010_REQ08_R00_A_VERSION 0x08, 0x00 | ||
482 | #define TM6010_REQ08_R01_A_INIT 0x08, 0x01 | ||
483 | #define TM6010_REQ08_R02_A_FIX_GAIN_CTRL 0x08, 0x02 | ||
484 | #define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL 0x08, 0x03 | ||
485 | #define TM6010_REQ08_R04_A_SIF_AMP_CTRL 0x08, 0x04 | ||
486 | #define TM6010_REQ08_R05_A_STANDARD_MOD 0x08, 0x05 | ||
487 | #define TM6010_REQ08_R06_A_SOUND_MOD 0x08, 0x06 | ||
488 | #define TM6010_REQ08_R07_A_LEFT_VOL 0x08, 0x07 | ||
489 | #define TM6010_REQ08_R08_A_RIGHT_VOL 0x08, 0x08 | ||
490 | #define TM6010_REQ08_R09_A_MAIN_VOL 0x08, 0x09 | ||
491 | #define TM6010_REQ08_R0A_A_I2S_MOD 0x08, 0x0a | ||
492 | #define TM6010_REQ08_R0B_A_ASD_THRES1 0x08, 0x0b | ||
493 | #define TM6010_REQ08_R0C_A_ASD_THRES2 0x08, 0x0c | ||
494 | #define TM6010_REQ08_R0D_A_AMD_THRES 0x08, 0x0d | ||
495 | #define TM6010_REQ08_R0E_A_MONO_THRES1 0x08, 0x0e | ||
496 | #define TM6010_REQ08_R0F_A_MONO_THRES2 0x08, 0x0f | ||
497 | #define TM6010_REQ08_R10_A_MUTE_THRES1 0x08, 0x10 | ||
498 | #define TM6010_REQ08_R11_A_MUTE_THRES2 0x08, 0x11 | ||
499 | #define TM6010_REQ08_R12_A_AGC_U 0x08, 0x12 | ||
500 | #define TM6010_REQ08_R13_A_AGC_ERR_T 0x08, 0x13 | ||
501 | #define TM6010_REQ08_R14_A_AGC_GAIN_INIT 0x08, 0x14 | ||
502 | #define TM6010_REQ08_R15_A_AGC_STEP_THR 0x08, 0x15 | ||
503 | #define TM6010_REQ08_R16_A_AGC_GAIN_MAX 0x08, 0x16 | ||
504 | #define TM6010_REQ08_R17_A_AGC_GAIN_MIN 0x08, 0x17 | ||
505 | #define TM6010_REQ08_R18_A_TR_CTRL 0x08, 0x18 | ||
506 | #define TM6010_REQ08_R19_A_FH_2FH_GAIN 0x08, 0x19 | ||
507 | #define TM6010_REQ08_R1A_A_NICAM_SER_MAX 0x08, 0x1a | ||
508 | #define TM6010_REQ08_R1B_A_NICAM_SER_MIN 0x08, 0x1b | ||
509 | #define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT 0x08, 0x1e | ||
510 | #define TM6010_REQ08_R1F_A_TEST_INTF_SEL 0x08, 0x1f | ||
511 | #define TM6010_REQ08_R20_A_TEST_PIN_SEL 0x08, 0x20 | ||
512 | #define TM6010_REQ08_R21_A_AGC_ERR 0x08, 0x21 | ||
513 | #define TM6010_REQ08_R22_A_AGC_GAIN 0x08, 0x22 | ||
514 | #define TM6010_REQ08_R23_A_NICAM_INFO 0x08, 0x23 | ||
515 | #define TM6010_REQ08_R24_A_SER 0x08, 0x24 | ||
516 | #define TM6010_REQ08_R25_A_C1_AMP 0x08, 0x25 | ||
517 | #define TM6010_REQ08_R26_A_C2_AMP 0x08, 0x26 | ||
518 | #define TM6010_REQ08_R27_A_NOISE_AMP 0x08, 0x27 | ||
519 | #define TM6010_REQ08_R28_A_AUDIO_MODE_RES 0x08, 0x28 | ||
520 | |||
521 | /* Define TM6000/TM6010 Video ADC registers */ | ||
522 | #define TM6010_REQ08_RE0_ADC_REF 0x08, 0xe0 | ||
523 | #define TM6010_REQ08_RE1_DAC_CLMP 0x08, 0xe1 | ||
524 | #define TM6010_REQ08_RE2_POWER_DOWN_CTRL1 0x08, 0xe2 | ||
525 | #define TM6010_REQ08_RE3_ADC_IN1_SEL 0x08, 0xe3 | ||
526 | #define TM6010_REQ08_RE4_ADC_IN2_SEL 0x08, 0xe4 | ||
527 | #define TM6010_REQ08_RE5_GAIN_PARAM 0x08, 0xe5 | ||
528 | #define TM6010_REQ08_RE6_POWER_DOWN_CTRL2 0x08, 0xe6 | ||
529 | #define TM6010_REQ08_RE7_REG_GAIN_Y 0x08, 0xe7 | ||
530 | #define TM6010_REQ08_RE8_REG_GAIN_C 0x08, 0xe8 | ||
531 | #define TM6010_REQ08_RE9_BIAS_CTRL 0x08, 0xe9 | ||
532 | #define TM6010_REQ08_REA_BUFF_DRV_CTRL 0x08, 0xea | ||
533 | #define TM6010_REQ08_REB_SIF_GAIN_CTRL 0x08, 0xeb | ||
534 | #define TM6010_REQ08_REC_REVERSE_YC_CTRL 0x08, 0xec | ||
535 | #define TM6010_REQ08_RED_GAIN_SEL 0x08, 0xed | ||
536 | |||
537 | /* Define TM6000/TM6010 Audio ADC registers */ | ||
538 | #define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG 0x08, 0xf0 | ||
539 | #define TM6010_REQ08_RF1_AADC_POWER_DOWN 0x08, 0xf1 | ||
540 | #define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL 0x08, 0xf2 | ||
541 | #define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL 0x08, 0xf3 | ||
diff --git a/drivers/staging/tm6000/tm6000-stds.c b/drivers/staging/tm6000/tm6000-stds.c new file mode 100644 index 000000000000..b3564f611e5e --- /dev/null +++ b/drivers/staging/tm6000/tm6000-stds.c | |||
@@ -0,0 +1,873 @@ | |||
1 | /* | ||
2 | tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.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 version 2 | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include "tm6000.h" | ||
23 | #include "tm6000-regs.h" | ||
24 | |||
25 | struct tm6000_reg_settings { | ||
26 | unsigned char req; | ||
27 | unsigned char reg; | ||
28 | unsigned char value; | ||
29 | }; | ||
30 | |||
31 | struct tm6000_std_tv_settings { | ||
32 | v4l2_std_id id; | ||
33 | struct tm6000_reg_settings sif[12]; | ||
34 | struct tm6000_reg_settings nosif[12]; | ||
35 | struct tm6000_reg_settings common[25]; | ||
36 | }; | ||
37 | |||
38 | struct tm6000_std_settings { | ||
39 | v4l2_std_id id; | ||
40 | struct tm6000_reg_settings common[37]; | ||
41 | }; | ||
42 | |||
43 | static struct tm6000_std_tv_settings tv_stds[] = { | ||
44 | { | ||
45 | .id = V4L2_STD_PAL_M, | ||
46 | .sif = { | ||
47 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2}, | ||
48 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
49 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
50 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08}, | ||
51 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
52 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
53 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
54 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
55 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62}, | ||
56 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe}, | ||
57 | {TM6010_REQ07_RFE_POWER_DOWN, 0xcb}, | ||
58 | {0, 0, 0}, | ||
59 | }, | ||
60 | .nosif = { | ||
61 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
62 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
63 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
64 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
65 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
66 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
67 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
68 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
69 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60}, | ||
70 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
71 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
72 | {0, 0, 0}, | ||
73 | }, | ||
74 | .common = { | ||
75 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
76 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04}, | ||
77 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
78 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
79 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, | ||
80 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
81 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
82 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, | ||
83 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, | ||
84 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0}, | ||
85 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
86 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
87 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
88 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
89 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
90 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20}, | ||
91 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
92 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
93 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
94 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
95 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
96 | |||
97 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
98 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
99 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
100 | {0, 0, 0}, | ||
101 | }, | ||
102 | }, { | ||
103 | .id = V4L2_STD_PAL_Nc, | ||
104 | .sif = { | ||
105 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2}, | ||
106 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
107 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
108 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08}, | ||
109 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
110 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
111 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
112 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
113 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62}, | ||
114 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe}, | ||
115 | {TM6010_REQ07_RFE_POWER_DOWN, 0xcb}, | ||
116 | {0, 0, 0}, | ||
117 | }, | ||
118 | .nosif = { | ||
119 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
120 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
121 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
122 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
123 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
124 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
125 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
126 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
127 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60}, | ||
128 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
129 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
130 | {0, 0, 0}, | ||
131 | }, | ||
132 | .common = { | ||
133 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
134 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36}, | ||
135 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
136 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
137 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
138 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
139 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
140 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, | ||
141 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, | ||
142 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c}, | ||
143 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
144 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
145 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
146 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
147 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
148 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
149 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
150 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
151 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
152 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
153 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
154 | |||
155 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
156 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
157 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
158 | {0, 0, 0}, | ||
159 | }, | ||
160 | }, { | ||
161 | .id = V4L2_STD_PAL, | ||
162 | .sif = { | ||
163 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2}, | ||
164 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
165 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
166 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08}, | ||
167 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
168 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
169 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
170 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
171 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62}, | ||
172 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe}, | ||
173 | {TM6010_REQ07_RFE_POWER_DOWN, 0xcb}, | ||
174 | {0, 0, 0} | ||
175 | }, | ||
176 | .nosif = { | ||
177 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
178 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
179 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
180 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
181 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
182 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
183 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
184 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
185 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60}, | ||
186 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
187 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
188 | {0, 0, 0}, | ||
189 | }, | ||
190 | .common = { | ||
191 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
192 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32}, | ||
193 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
194 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
195 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
196 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
197 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, | ||
198 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, | ||
199 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, | ||
200 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50}, | ||
201 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
202 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
203 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
204 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
205 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
206 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
207 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
208 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
209 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
210 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
211 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
212 | |||
213 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
214 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
215 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
216 | {0, 0, 0}, | ||
217 | }, | ||
218 | }, { | ||
219 | .id = V4L2_STD_SECAM, | ||
220 | .sif = { | ||
221 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2}, | ||
222 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
223 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
224 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08}, | ||
225 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
226 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
227 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
228 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
229 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62}, | ||
230 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe}, | ||
231 | {TM6010_REQ07_RFE_POWER_DOWN, 0xcb}, | ||
232 | {0, 0, 0}, | ||
233 | }, | ||
234 | .nosif = { | ||
235 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
236 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
237 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
238 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
239 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
240 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
241 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
242 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
243 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60}, | ||
244 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
245 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
246 | {0, 0, 0}, | ||
247 | }, | ||
248 | .common = { | ||
249 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
250 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38}, | ||
251 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
252 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
253 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
254 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
255 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, | ||
256 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, | ||
257 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, | ||
258 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed}, | ||
259 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
260 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
261 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
262 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
263 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
264 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
265 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
266 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c}, | ||
267 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18}, | ||
268 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
269 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xFF}, | ||
270 | |||
271 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
272 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
273 | {0, 0, 0}, | ||
274 | }, | ||
275 | }, { | ||
276 | .id = V4L2_STD_NTSC, | ||
277 | .sif = { | ||
278 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf2}, | ||
279 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
280 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
281 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x08}, | ||
282 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
283 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
284 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
285 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
286 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x62}, | ||
287 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe}, | ||
288 | {TM6010_REQ07_RFE_POWER_DOWN, 0xcb}, | ||
289 | {0, 0, 0}, | ||
290 | }, | ||
291 | .nosif = { | ||
292 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
293 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8}, | ||
294 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
295 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
296 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
297 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
298 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
299 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
300 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60}, | ||
301 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
302 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
303 | {0, 0, 0}, | ||
304 | }, | ||
305 | .common = { | ||
306 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
307 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00}, | ||
308 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, | ||
309 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
310 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, | ||
311 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
312 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
313 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, | ||
314 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2}, | ||
315 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9}, | ||
316 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
317 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
318 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
319 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
320 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
321 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22}, | ||
322 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
323 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c}, | ||
324 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
325 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
326 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
327 | |||
328 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd}, | ||
329 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
330 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
331 | {0, 0, 0}, | ||
332 | }, | ||
333 | }, | ||
334 | }; | ||
335 | |||
336 | static struct tm6000_std_settings composite_stds[] = { | ||
337 | { | ||
338 | .id = V4L2_STD_PAL_M, | ||
339 | .common = { | ||
340 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
341 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4}, | ||
342 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
343 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
344 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
345 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
346 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
347 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
348 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
349 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
350 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
351 | |||
352 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
353 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04}, | ||
354 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
355 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
356 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, | ||
357 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
358 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
359 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, | ||
360 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, | ||
361 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0}, | ||
362 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
363 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
364 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
365 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
366 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
367 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20}, | ||
368 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
369 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
370 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
371 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
372 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
373 | |||
374 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
375 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
376 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
377 | {0, 0, 0}, | ||
378 | }, | ||
379 | }, { | ||
380 | .id = V4L2_STD_PAL_Nc, | ||
381 | .common = { | ||
382 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
383 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4}, | ||
384 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
385 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
386 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
387 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
388 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
389 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
390 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
391 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
392 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
393 | |||
394 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
395 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36}, | ||
396 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
397 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
398 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
399 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
400 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
401 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, | ||
402 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, | ||
403 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c}, | ||
404 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
405 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
406 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
407 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
408 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
409 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
410 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
411 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
412 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
413 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
414 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
415 | |||
416 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
417 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
418 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
419 | {0, 0, 0}, | ||
420 | }, | ||
421 | }, { | ||
422 | .id = V4L2_STD_PAL, | ||
423 | .common = { | ||
424 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
425 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4}, | ||
426 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
427 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
428 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
429 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
430 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
431 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
432 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
433 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
434 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
435 | |||
436 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
437 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32}, | ||
438 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
439 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
440 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
441 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
442 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, | ||
443 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, | ||
444 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, | ||
445 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50}, | ||
446 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
447 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
448 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
449 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
450 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
451 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
452 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
453 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
454 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
455 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
456 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
457 | |||
458 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
459 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
460 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
461 | {0, 0, 0}, | ||
462 | }, | ||
463 | }, { | ||
464 | .id = V4L2_STD_SECAM, | ||
465 | .common = { | ||
466 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
467 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4}, | ||
468 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
469 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
470 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
471 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
472 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
473 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
474 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
475 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
476 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
477 | |||
478 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
479 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38}, | ||
480 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
481 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
482 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, | ||
483 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
484 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, | ||
485 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, | ||
486 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, | ||
487 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed}, | ||
488 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
489 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
490 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
491 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
492 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
493 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c}, | ||
494 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
495 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c}, | ||
496 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18}, | ||
497 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
498 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xFF}, | ||
499 | |||
500 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
501 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
502 | {0, 0, 0}, | ||
503 | }, | ||
504 | }, { | ||
505 | .id = V4L2_STD_NTSC, | ||
506 | .common = { | ||
507 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
508 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4}, | ||
509 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3}, | ||
510 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x0f}, | ||
511 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1}, | ||
512 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0}, | ||
513 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
514 | {TM6010_REQ08_RED_GAIN_SEL, 0xe8}, | ||
515 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
516 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
517 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8b}, | ||
518 | |||
519 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
520 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00}, | ||
521 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, | ||
522 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
523 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, | ||
524 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
525 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
526 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, | ||
527 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2}, | ||
528 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9}, | ||
529 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
530 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
531 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
532 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
533 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
534 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22}, | ||
535 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
536 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c}, | ||
537 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
538 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
539 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
540 | |||
541 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd}, | ||
542 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
543 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
544 | {0, 0, 0}, | ||
545 | }, | ||
546 | }, | ||
547 | }; | ||
548 | |||
549 | static struct tm6000_std_settings svideo_stds[] = { | ||
550 | { | ||
551 | .id = V4L2_STD_PAL_M, | ||
552 | .common = { | ||
553 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
554 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc}, | ||
555 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8}, | ||
556 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00}, | ||
557 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2}, | ||
558 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0}, | ||
559 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
560 | {TM6010_REQ08_RED_GAIN_SEL, 0xe0}, | ||
561 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
562 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
563 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8a}, | ||
564 | |||
565 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
566 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05}, | ||
567 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
568 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
569 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, | ||
570 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
571 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
572 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, | ||
573 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, | ||
574 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0}, | ||
575 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
576 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
577 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
578 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
579 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
580 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22}, | ||
581 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
582 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
583 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
584 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
585 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
586 | |||
587 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
588 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
589 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
590 | {0, 0, 0}, | ||
591 | }, | ||
592 | }, { | ||
593 | .id = V4L2_STD_PAL_Nc, | ||
594 | .common = { | ||
595 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
596 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc}, | ||
597 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8}, | ||
598 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00}, | ||
599 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2}, | ||
600 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0}, | ||
601 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
602 | {TM6010_REQ08_RED_GAIN_SEL, 0xe0}, | ||
603 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
604 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
605 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8a}, | ||
606 | |||
607 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
608 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37}, | ||
609 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
610 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
611 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, | ||
612 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
613 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
614 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, | ||
615 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, | ||
616 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c}, | ||
617 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
618 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
619 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
620 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
621 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
622 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22}, | ||
623 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
624 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
625 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
626 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
627 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
628 | |||
629 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
630 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
631 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
632 | {0, 0, 0}, | ||
633 | }, | ||
634 | }, { | ||
635 | .id = V4L2_STD_PAL, | ||
636 | .common = { | ||
637 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
638 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc}, | ||
639 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8}, | ||
640 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00}, | ||
641 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2}, | ||
642 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0}, | ||
643 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
644 | {TM6010_REQ08_RED_GAIN_SEL, 0xe0}, | ||
645 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
646 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
647 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8a}, | ||
648 | |||
649 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
650 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33}, | ||
651 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
652 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
653 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, | ||
654 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x00}, | ||
655 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, | ||
656 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, | ||
657 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, | ||
658 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50}, | ||
659 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
660 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
661 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
662 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
663 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
664 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a}, | ||
665 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
666 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c}, | ||
667 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
668 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52}, | ||
669 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
670 | |||
671 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc}, | ||
672 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
673 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
674 | {0, 0, 0}, | ||
675 | }, | ||
676 | }, { | ||
677 | .id = V4L2_STD_SECAM, | ||
678 | .common = { | ||
679 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
680 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc}, | ||
681 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8}, | ||
682 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00}, | ||
683 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2}, | ||
684 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0}, | ||
685 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
686 | {TM6010_REQ08_RED_GAIN_SEL, 0xe0}, | ||
687 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
688 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
689 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8a}, | ||
690 | |||
691 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
692 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39}, | ||
693 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, | ||
694 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
695 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03}, | ||
696 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, | ||
697 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, | ||
698 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, | ||
699 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, | ||
700 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed}, | ||
701 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
702 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
703 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
704 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
705 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c}, | ||
706 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a}, | ||
707 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1}, | ||
708 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c}, | ||
709 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18}, | ||
710 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
711 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xFF}, | ||
712 | |||
713 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
714 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
715 | {0, 0, 0}, | ||
716 | }, | ||
717 | }, { | ||
718 | .id = V4L2_STD_NTSC, | ||
719 | .common = { | ||
720 | {TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0}, | ||
721 | {TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc}, | ||
722 | {TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8}, | ||
723 | {TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00}, | ||
724 | {TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2}, | ||
725 | {TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0}, | ||
726 | {TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2}, | ||
727 | {TM6010_REQ08_RED_GAIN_SEL, 0xe0}, | ||
728 | {TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x68}, | ||
729 | {TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc}, | ||
730 | {TM6010_REQ07_RFE_POWER_DOWN, 0x8a}, | ||
731 | |||
732 | {TM6010_REQ07_R3F_RESET, 0x01}, | ||
733 | {TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01}, | ||
734 | {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, | ||
735 | {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, | ||
736 | {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03}, | ||
737 | {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x00}, | ||
738 | {TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b}, | ||
739 | {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, | ||
740 | {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, | ||
741 | {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2}, | ||
742 | {TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9}, | ||
743 | {TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c}, | ||
744 | {TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc}, | ||
745 | {TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc}, | ||
746 | {TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd}, | ||
747 | {TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88}, | ||
748 | {TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22}, | ||
749 | {TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61}, | ||
750 | {TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c}, | ||
751 | {TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c}, | ||
752 | {TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42}, | ||
753 | {TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6F}, | ||
754 | |||
755 | {TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd}, | ||
756 | {TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07}, | ||
757 | {TM6010_REQ07_R3F_RESET, 0x00}, | ||
758 | {0, 0, 0}, | ||
759 | }, | ||
760 | }, | ||
761 | }; | ||
762 | |||
763 | void tm6000_get_std_res(struct tm6000_core *dev) | ||
764 | { | ||
765 | /* Currently, those are the only supported resoltions */ | ||
766 | if (dev->norm & V4L2_STD_525_60) { | ||
767 | dev->height = 480; | ||
768 | } else { | ||
769 | dev->height = 576; | ||
770 | } | ||
771 | dev->width = 720; | ||
772 | } | ||
773 | |||
774 | static int tm6000_load_std(struct tm6000_core *dev, | ||
775 | struct tm6000_reg_settings *set, int max_size) | ||
776 | { | ||
777 | int i, rc; | ||
778 | |||
779 | /* Load board's initialization table */ | ||
780 | for (i = 0; max_size; i++) { | ||
781 | if (!set[i].req) | ||
782 | return 0; | ||
783 | |||
784 | if ((dev->dev_type != TM6010) && | ||
785 | (set[i].req == REQ_08_SET_GET_AVREG_BIT)) | ||
786 | continue; | ||
787 | |||
788 | rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value); | ||
789 | if (rc < 0) { | ||
790 | printk(KERN_ERR "Error %i while setting " | ||
791 | "req %d, reg %d to value %d\n", | ||
792 | rc, set[i].req, set[i].reg, set[i].value); | ||
793 | return rc; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int tm6000_set_tv(struct tm6000_core *dev, int pos) | ||
801 | { | ||
802 | int rc; | ||
803 | |||
804 | /* FIXME: This code is for tm6010 - not tested yet - doesn't work with | ||
805 | tm5600 | ||
806 | */ | ||
807 | |||
808 | /* FIXME: This is tuner-dependent */ | ||
809 | int nosif = 0; | ||
810 | |||
811 | if (nosif) { | ||
812 | rc = tm6000_load_std(dev, tv_stds[pos].nosif, | ||
813 | sizeof(tv_stds[pos].nosif)); | ||
814 | } else { | ||
815 | rc = tm6000_load_std(dev, tv_stds[pos].sif, | ||
816 | sizeof(tv_stds[pos].sif)); | ||
817 | } | ||
818 | if (rc < 0) | ||
819 | return rc; | ||
820 | rc = tm6000_load_std(dev, tv_stds[pos].common, | ||
821 | sizeof(tv_stds[pos].common)); | ||
822 | |||
823 | return rc; | ||
824 | } | ||
825 | |||
826 | int tm6000_set_standard(struct tm6000_core *dev, v4l2_std_id * norm) | ||
827 | { | ||
828 | int i, rc = 0; | ||
829 | |||
830 | dev->norm = *norm; | ||
831 | tm6000_get_std_res(dev); | ||
832 | |||
833 | switch (dev->input) { | ||
834 | case TM6000_INPUT_TV: | ||
835 | for (i = 0; i < ARRAY_SIZE(tv_stds); i++) { | ||
836 | if (*norm & tv_stds[i].id) { | ||
837 | rc = tm6000_set_tv(dev, i); | ||
838 | goto ret; | ||
839 | } | ||
840 | } | ||
841 | return -EINVAL; | ||
842 | case TM6000_INPUT_SVIDEO: | ||
843 | for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) { | ||
844 | if (*norm & svideo_stds[i].id) { | ||
845 | rc = tm6000_load_std(dev, svideo_stds[i].common, | ||
846 | sizeof(svideo_stds[i]. | ||
847 | common)); | ||
848 | goto ret; | ||
849 | } | ||
850 | } | ||
851 | return -EINVAL; | ||
852 | case TM6000_INPUT_COMPOSITE: | ||
853 | for (i = 0; i < ARRAY_SIZE(composite_stds); i++) { | ||
854 | if (*norm & composite_stds[i].id) { | ||
855 | rc = tm6000_load_std(dev, | ||
856 | composite_stds[i].common, | ||
857 | sizeof(composite_stds[i]. | ||
858 | common)); | ||
859 | goto ret; | ||
860 | } | ||
861 | } | ||
862 | return -EINVAL; | ||
863 | } | ||
864 | |||
865 | ret: | ||
866 | if (rc < 0) | ||
867 | return rc; | ||
868 | |||
869 | msleep(40); | ||
870 | |||
871 | |||
872 | return 0; | ||
873 | } | ||
diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h new file mode 100644 index 000000000000..5a5049acd4ec --- /dev/null +++ b/drivers/staging/tm6000/tm6000-usb-isoc.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
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 version 2 | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/videodev2.h> | ||
21 | |||
22 | #define TM6000_URB_MSG_LEN 180 | ||
23 | |||
24 | struct usb_isoc_ctl { | ||
25 | /* max packet size of isoc transaction */ | ||
26 | int max_pkt_size; | ||
27 | |||
28 | /* number of allocated urbs */ | ||
29 | int num_bufs; | ||
30 | |||
31 | /* urb for isoc transfers */ | ||
32 | struct urb **urb; | ||
33 | |||
34 | /* transfer buffers for isoc transfer */ | ||
35 | char **transfer_buffer; | ||
36 | |||
37 | /* Last buffer command and region */ | ||
38 | u8 cmd; | ||
39 | int pos, size, pktsize; | ||
40 | |||
41 | /* Last field: ODD or EVEN? */ | ||
42 | int field; | ||
43 | |||
44 | /* Stores incomplete commands */ | ||
45 | u32 tmp_buf; | ||
46 | int tmp_buf_len; | ||
47 | |||
48 | /* Stores already requested buffers */ | ||
49 | struct tm6000_buffer *buf; | ||
50 | |||
51 | /* Stores the number of received fields */ | ||
52 | int nfields; | ||
53 | }; | ||
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c new file mode 100644 index 000000000000..f2b7fe4a3581 --- /dev/null +++ b/drivers/staging/tm6000/tm6000-video.c | |||
@@ -0,0 +1,1557 @@ | |||
1 | /* | ||
2 | tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
5 | |||
6 | Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> | ||
7 | - Fixed module load/unload | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation version 2 | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/random.h> | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/videodev2.h> | ||
36 | #include <media/v4l2-ioctl.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/kthread.h> | ||
39 | #include <linux/highmem.h> | ||
40 | #include <linux/freezer.h> | ||
41 | |||
42 | #include "tm6000-regs.h" | ||
43 | #include "tm6000.h" | ||
44 | |||
45 | #define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ | ||
46 | |||
47 | /* Limits minimum and default number of buffers */ | ||
48 | #define TM6000_MIN_BUF 4 | ||
49 | #define TM6000_DEF_BUF 8 | ||
50 | |||
51 | #define TM6000_MAX_ISO_PACKETS 40 /* Max number of ISO packets */ | ||
52 | |||
53 | /* Declare static vars that will be used as parameters */ | ||
54 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ | ||
55 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | ||
56 | |||
57 | /* Debug level */ | ||
58 | int tm6000_debug; | ||
59 | |||
60 | /* supported controls */ | ||
61 | static struct v4l2_queryctrl tm6000_qctrl[] = { | ||
62 | { | ||
63 | .id = V4L2_CID_BRIGHTNESS, | ||
64 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
65 | .name = "Brightness", | ||
66 | .minimum = 0, | ||
67 | .maximum = 255, | ||
68 | .step = 1, | ||
69 | .default_value = 54, | ||
70 | .flags = 0, | ||
71 | }, { | ||
72 | .id = V4L2_CID_CONTRAST, | ||
73 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
74 | .name = "Contrast", | ||
75 | .minimum = 0, | ||
76 | .maximum = 255, | ||
77 | .step = 0x1, | ||
78 | .default_value = 119, | ||
79 | .flags = 0, | ||
80 | }, { | ||
81 | .id = V4L2_CID_SATURATION, | ||
82 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
83 | .name = "Saturation", | ||
84 | .minimum = 0, | ||
85 | .maximum = 255, | ||
86 | .step = 0x1, | ||
87 | .default_value = 112, | ||
88 | .flags = 0, | ||
89 | }, { | ||
90 | .id = V4L2_CID_HUE, | ||
91 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
92 | .name = "Hue", | ||
93 | .minimum = -128, | ||
94 | .maximum = 127, | ||
95 | .step = 0x1, | ||
96 | .default_value = 0, | ||
97 | .flags = 0, | ||
98 | } | ||
99 | }; | ||
100 | |||
101 | static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)]; | ||
102 | |||
103 | static struct tm6000_fmt format[] = { | ||
104 | { | ||
105 | .name = "4:2:2, packed, YVY2", | ||
106 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
107 | .depth = 16, | ||
108 | }, { | ||
109 | .name = "4:2:2, packed, UYVY", | ||
110 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
111 | .depth = 16, | ||
112 | }, { | ||
113 | .name = "A/V + VBI mux packet", | ||
114 | .fourcc = V4L2_PIX_FMT_TM6000, | ||
115 | .depth = 16, | ||
116 | } | ||
117 | }; | ||
118 | |||
119 | /* ------------------------------------------------------------------ | ||
120 | DMA and thread functions | ||
121 | ------------------------------------------------------------------*/ | ||
122 | |||
123 | #define norm_maxw(a) 720 | ||
124 | #define norm_maxh(a) 576 | ||
125 | |||
126 | #define norm_minw(a) norm_maxw(a) | ||
127 | #define norm_minh(a) norm_maxh(a) | ||
128 | |||
129 | /* | ||
130 | * video-buf generic routine to get the next available buffer | ||
131 | */ | ||
132 | static inline void get_next_buf(struct tm6000_dmaqueue *dma_q, | ||
133 | struct tm6000_buffer **buf) | ||
134 | { | ||
135 | struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); | ||
136 | char *outp; | ||
137 | |||
138 | if (list_empty(&dma_q->active)) { | ||
139 | dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n"); | ||
140 | *buf = NULL; | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | *buf = list_entry(dma_q->active.next, | ||
145 | struct tm6000_buffer, vb.queue); | ||
146 | |||
147 | if (!buf) | ||
148 | return; | ||
149 | |||
150 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
151 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
152 | // if (outp) | ||
153 | // memset(outp, 0, (*buf)->vb.size); | ||
154 | |||
155 | return; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Announces that a buffer were filled and request the next | ||
160 | */ | ||
161 | static inline void buffer_filled(struct tm6000_core *dev, | ||
162 | struct tm6000_dmaqueue *dma_q, | ||
163 | struct tm6000_buffer *buf) | ||
164 | { | ||
165 | /* Advice that buffer was filled */ | ||
166 | dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i); | ||
167 | buf->vb.state = VIDEOBUF_DONE; | ||
168 | buf->vb.field_count++; | ||
169 | do_gettimeofday(&buf->vb.ts); | ||
170 | |||
171 | list_del(&buf->vb.queue); | ||
172 | wake_up(&buf->vb.done); | ||
173 | } | ||
174 | |||
175 | const char *tm6000_msg_type[] = { | ||
176 | "unknown(0)", /* 0 */ | ||
177 | "video", /* 1 */ | ||
178 | "audio", /* 2 */ | ||
179 | "vbi", /* 3 */ | ||
180 | "pts", /* 4 */ | ||
181 | "err", /* 5 */ | ||
182 | "unknown(6)", /* 6 */ | ||
183 | "unknown(7)", /* 7 */ | ||
184 | }; | ||
185 | |||
186 | /* | ||
187 | * Identify the tm5600/6000 buffer header type and properly handles | ||
188 | */ | ||
189 | static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, | ||
190 | u8 *out_p, struct tm6000_buffer **buf) | ||
191 | { | ||
192 | struct tm6000_dmaqueue *dma_q = urb->context; | ||
193 | struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); | ||
194 | u8 c; | ||
195 | unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; | ||
196 | int rc = 0; | ||
197 | /* FIXME: move to tm6000-isoc */ | ||
198 | static int last_line = -2, start_line = -2, last_field = -2; | ||
199 | |||
200 | /* FIXME: this is the hardcoded window size | ||
201 | */ | ||
202 | unsigned int linewidth = (*buf)->vb.width << 1; | ||
203 | |||
204 | if (!dev->isoc_ctl.cmd) { | ||
205 | c = (header >> 24) & 0xff; | ||
206 | |||
207 | /* split the header fields */ | ||
208 | size = (((header & 0x7e) << 1) -1) *4; | ||
209 | block = (header >> 7) & 0xf; | ||
210 | field = (header >> 11) & 0x1; | ||
211 | line = (header >> 12) & 0x1ff; | ||
212 | cmd = (header >> 21) & 0x7; | ||
213 | |||
214 | /* Validates header fields */ | ||
215 | if(size > TM6000_URB_MSG_LEN) | ||
216 | size = TM6000_URB_MSG_LEN; | ||
217 | |||
218 | if (cmd == TM6000_URB_MSG_VIDEO) { | ||
219 | if ((block+1)*TM6000_URB_MSG_LEN>linewidth) | ||
220 | cmd = TM6000_URB_MSG_ERR; | ||
221 | |||
222 | /* FIXME: Mounts the image as field0+field1 | ||
223 | * It should, instead, check if the user selected | ||
224 | * entrelaced or non-entrelaced mode | ||
225 | */ | ||
226 | pos = ((line << 1) - field - 1) * linewidth + | ||
227 | block * TM6000_URB_MSG_LEN; | ||
228 | |||
229 | /* Don't allow to write out of the buffer */ | ||
230 | if (pos+TM6000_URB_MSG_LEN > (*buf)->vb.size) { | ||
231 | dprintk(dev, V4L2_DEBUG_ISOC, | ||
232 | "ERR: size=%d, num=%d, line=%d, " | ||
233 | "field=%d\n", | ||
234 | size, block, line, field); | ||
235 | |||
236 | cmd = TM6000_URB_MSG_ERR; | ||
237 | } | ||
238 | } else { | ||
239 | pos=0; | ||
240 | } | ||
241 | |||
242 | /* Prints debug info */ | ||
243 | dprintk(dev, V4L2_DEBUG_ISOC, "size=%d, num=%d, " | ||
244 | " line=%d, field=%d\n", | ||
245 | size, block, line, field); | ||
246 | |||
247 | if ((last_line!=line)&&(last_line+1!=line) && | ||
248 | (cmd != TM6000_URB_MSG_ERR) ) { | ||
249 | if (cmd != TM6000_URB_MSG_VIDEO) { | ||
250 | dprintk(dev, V4L2_DEBUG_ISOC, "cmd=%d, " | ||
251 | "size=%d, num=%d, line=%d, field=%d\n", | ||
252 | cmd, size, block, line, field); | ||
253 | } | ||
254 | if (start_line<0) | ||
255 | start_line=last_line; | ||
256 | /* Prints debug info */ | ||
257 | dprintk(dev, V4L2_DEBUG_ISOC, "lines= %d-%d, " | ||
258 | "field=%d\n", | ||
259 | start_line, last_line, field); | ||
260 | |||
261 | if ((start_line<6 && last_line>200) && | ||
262 | (last_field != field) ) { | ||
263 | |||
264 | dev->isoc_ctl.nfields++; | ||
265 | if (dev->isoc_ctl.nfields>=2) { | ||
266 | dev->isoc_ctl.nfields=0; | ||
267 | |||
268 | /* Announces that a new buffer were filled */ | ||
269 | buffer_filled (dev, dma_q, *buf); | ||
270 | dprintk(dev, V4L2_DEBUG_ISOC, | ||
271 | "new buffer filled\n"); | ||
272 | get_next_buf (dma_q, buf); | ||
273 | if (!*buf) | ||
274 | return rc; | ||
275 | out_p = videobuf_to_vmalloc(&((*buf)->vb)); | ||
276 | if (!out_p) | ||
277 | return rc; | ||
278 | |||
279 | pos = dev->isoc_ctl.pos = 0; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | start_line=line; | ||
284 | last_field=field; | ||
285 | } | ||
286 | if (cmd == TM6000_URB_MSG_VIDEO) | ||
287 | last_line = line; | ||
288 | |||
289 | pktsize = TM6000_URB_MSG_LEN; | ||
290 | } else { | ||
291 | /* Continue the last copy */ | ||
292 | cmd = dev->isoc_ctl.cmd; | ||
293 | size= dev->isoc_ctl.size; | ||
294 | pos = dev->isoc_ctl.pos; | ||
295 | pktsize = dev->isoc_ctl.pktsize; | ||
296 | } | ||
297 | |||
298 | cpysize = (endp-(*ptr) > size) ? size : endp - *ptr; | ||
299 | |||
300 | if (cpysize) { | ||
301 | /* handles each different URB message */ | ||
302 | switch(cmd) { | ||
303 | case TM6000_URB_MSG_VIDEO: | ||
304 | /* Fills video buffer */ | ||
305 | memcpy(&out_p[pos], *ptr, cpysize); | ||
306 | break; | ||
307 | case TM6000_URB_MSG_PTS: | ||
308 | break; | ||
309 | case TM6000_URB_MSG_AUDIO: | ||
310 | /* Need some code to process audio */ | ||
311 | printk ("%ld: cmd=%s, size=%d\n", jiffies, | ||
312 | tm6000_msg_type[cmd],size); | ||
313 | break; | ||
314 | default: | ||
315 | dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n", | ||
316 | tm6000_msg_type[cmd],size); | ||
317 | } | ||
318 | } | ||
319 | if (cpysize<size) { | ||
320 | /* End of URB packet, but cmd processing is not | ||
321 | * complete. Preserve the state for a next packet | ||
322 | */ | ||
323 | dev->isoc_ctl.pos = pos+cpysize; | ||
324 | dev->isoc_ctl.size= size-cpysize; | ||
325 | dev->isoc_ctl.cmd = cmd; | ||
326 | dev->isoc_ctl.pktsize = pktsize-cpysize; | ||
327 | (*ptr)+=cpysize; | ||
328 | } else { | ||
329 | dev->isoc_ctl.cmd = 0; | ||
330 | (*ptr)+=pktsize; | ||
331 | } | ||
332 | |||
333 | return rc; | ||
334 | } | ||
335 | |||
336 | static int copy_streams(u8 *data, u8 *out_p, unsigned long len, | ||
337 | struct urb *urb, struct tm6000_buffer **buf) | ||
338 | { | ||
339 | struct tm6000_dmaqueue *dma_q = urb->context; | ||
340 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | ||
341 | u8 *ptr=data, *endp=data+len; | ||
342 | unsigned long header=0; | ||
343 | int rc=0; | ||
344 | |||
345 | for (ptr=data; ptr<endp;) { | ||
346 | if (!dev->isoc_ctl.cmd) { | ||
347 | u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf; | ||
348 | /* FIXME: This seems very complex | ||
349 | * It just recovers up to 3 bytes of the header that | ||
350 | * might be at the previous packet | ||
351 | */ | ||
352 | if (dev->isoc_ctl.tmp_buf_len) { | ||
353 | while (dev->isoc_ctl.tmp_buf_len) { | ||
354 | if ( *(ptr+3-dev->isoc_ctl.tmp_buf_len) == 0x47) { | ||
355 | break; | ||
356 | } | ||
357 | p++; | ||
358 | dev->isoc_ctl.tmp_buf_len--; | ||
359 | } | ||
360 | if (dev->isoc_ctl.tmp_buf_len) { | ||
361 | memcpy(&header, p, | ||
362 | dev->isoc_ctl.tmp_buf_len); | ||
363 | memcpy((u8 *)&header + | ||
364 | dev->isoc_ctl.tmp_buf_len, | ||
365 | ptr, | ||
366 | 4 - dev->isoc_ctl.tmp_buf_len); | ||
367 | ptr += 4 - dev->isoc_ctl.tmp_buf_len; | ||
368 | goto HEADER; | ||
369 | } | ||
370 | } | ||
371 | /* Seek for sync */ | ||
372 | for (;ptr<endp-3;ptr++) { | ||
373 | if (*(ptr+3)==0x47) | ||
374 | break; | ||
375 | } | ||
376 | |||
377 | if (ptr+3>=endp) { | ||
378 | dev->isoc_ctl.tmp_buf_len=endp-ptr; | ||
379 | memcpy (&dev->isoc_ctl.tmp_buf,ptr, | ||
380 | dev->isoc_ctl.tmp_buf_len); | ||
381 | dev->isoc_ctl.cmd=0; | ||
382 | return rc; | ||
383 | } | ||
384 | |||
385 | /* Get message header */ | ||
386 | header=*(unsigned long *)ptr; | ||
387 | ptr+=4; | ||
388 | } | ||
389 | HEADER: | ||
390 | /* Copy or continue last copy */ | ||
391 | rc=copy_packet(urb,header,&ptr,endp,out_p,buf); | ||
392 | if (rc<0) { | ||
393 | buf=NULL; | ||
394 | printk(KERN_ERR "tm6000: buffer underrun at %ld\n", | ||
395 | jiffies); | ||
396 | return rc; | ||
397 | } | ||
398 | if (!*buf) | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | /* | ||
405 | * Identify the tm5600/6000 buffer header type and properly handles | ||
406 | */ | ||
407 | static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, | ||
408 | struct urb *urb, struct tm6000_buffer **buf) | ||
409 | { | ||
410 | struct tm6000_dmaqueue *dma_q = urb->context; | ||
411 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | ||
412 | unsigned int pos=dev->isoc_ctl.pos,cpysize; | ||
413 | int rc=1; | ||
414 | |||
415 | while (len>0) { | ||
416 | cpysize=min(len,(*buf)->vb.size-pos); | ||
417 | //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); | ||
418 | memcpy(&out_p[pos], ptr, cpysize); | ||
419 | pos+=cpysize; | ||
420 | ptr+=cpysize; | ||
421 | len-=cpysize; | ||
422 | if (pos >= (*buf)->vb.size) { | ||
423 | pos=0; | ||
424 | /* Announces that a new buffer were filled */ | ||
425 | buffer_filled (dev, dma_q, *buf); | ||
426 | dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); | ||
427 | get_next_buf (dma_q, buf); | ||
428 | if (!*buf) | ||
429 | break; | ||
430 | out_p = videobuf_to_vmalloc(&((*buf)->vb)); | ||
431 | if (!out_p) | ||
432 | return rc; | ||
433 | pos = 0; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | dev->isoc_ctl.pos=pos; | ||
438 | return rc; | ||
439 | } | ||
440 | |||
441 | static void inline print_err_status (struct tm6000_core *dev, | ||
442 | int packet, int status) | ||
443 | { | ||
444 | char *errmsg = "Unknown"; | ||
445 | |||
446 | switch(status) { | ||
447 | case -ENOENT: | ||
448 | errmsg = "unlinked synchronuously"; | ||
449 | break; | ||
450 | case -ECONNRESET: | ||
451 | errmsg = "unlinked asynchronuously"; | ||
452 | break; | ||
453 | case -ENOSR: | ||
454 | errmsg = "Buffer error (overrun)"; | ||
455 | break; | ||
456 | case -EPIPE: | ||
457 | errmsg = "Stalled (device not responding)"; | ||
458 | break; | ||
459 | case -EOVERFLOW: | ||
460 | errmsg = "Babble (bad cable?)"; | ||
461 | break; | ||
462 | case -EPROTO: | ||
463 | errmsg = "Bit-stuff error (bad cable?)"; | ||
464 | break; | ||
465 | case -EILSEQ: | ||
466 | errmsg = "CRC/Timeout (could be anything)"; | ||
467 | break; | ||
468 | case -ETIME: | ||
469 | errmsg = "Device does not respond"; | ||
470 | break; | ||
471 | } | ||
472 | if (packet<0) { | ||
473 | dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n", | ||
474 | status, errmsg); | ||
475 | } else { | ||
476 | dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", | ||
477 | packet, status, errmsg); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | |||
482 | /* | ||
483 | * Controls the isoc copy of each urb packet | ||
484 | */ | ||
485 | static inline int tm6000_isoc_copy(struct urb *urb) | ||
486 | { | ||
487 | struct tm6000_dmaqueue *dma_q = urb->context; | ||
488 | struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); | ||
489 | struct tm6000_buffer *buf; | ||
490 | int i, len=0, rc=1; | ||
491 | int size; | ||
492 | char *outp = NULL, *p; | ||
493 | unsigned long copied; | ||
494 | |||
495 | get_next_buf(dma_q, &buf); | ||
496 | if (buf) | ||
497 | outp = videobuf_to_vmalloc(&buf->vb); | ||
498 | |||
499 | if (!outp) | ||
500 | return 0; | ||
501 | |||
502 | size = buf->vb.size; | ||
503 | |||
504 | copied=0; | ||
505 | |||
506 | if (urb->status<0) { | ||
507 | print_err_status (dev,-1,urb->status); | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | for (i = 0; i < urb->number_of_packets; i++) { | ||
512 | int status = urb->iso_frame_desc[i].status; | ||
513 | |||
514 | if (status<0) { | ||
515 | print_err_status (dev,i,status); | ||
516 | continue; | ||
517 | } | ||
518 | |||
519 | len=urb->iso_frame_desc[i].actual_length; | ||
520 | |||
521 | // if (len>=TM6000_URB_MSG_LEN) { | ||
522 | p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
523 | if (!urb->iso_frame_desc[i].status) { | ||
524 | if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { | ||
525 | rc=copy_multiplexed(p, outp, len, urb, &buf); | ||
526 | if (rc<=0) | ||
527 | return rc; | ||
528 | } else { | ||
529 | copy_streams(p, outp, len, urb, &buf); | ||
530 | } | ||
531 | } | ||
532 | copied += len; | ||
533 | if (copied >= size || !buf) | ||
534 | break; | ||
535 | // } | ||
536 | } | ||
537 | return rc; | ||
538 | } | ||
539 | |||
540 | /* ------------------------------------------------------------------ | ||
541 | URB control | ||
542 | ------------------------------------------------------------------*/ | ||
543 | |||
544 | /* | ||
545 | * IRQ callback, called by URB callback | ||
546 | */ | ||
547 | static void tm6000_irq_callback(struct urb *urb) | ||
548 | { | ||
549 | struct tm6000_dmaqueue *dma_q = urb->context; | ||
550 | struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); | ||
551 | int i; | ||
552 | |||
553 | if (!dev) | ||
554 | return; | ||
555 | |||
556 | spin_lock(&dev->slock); | ||
557 | tm6000_isoc_copy(urb); | ||
558 | spin_unlock(&dev->slock); | ||
559 | |||
560 | /* Reset urb buffers */ | ||
561 | for (i = 0; i < urb->number_of_packets; i++) { | ||
562 | urb->iso_frame_desc[i].status = 0; | ||
563 | urb->iso_frame_desc[i].actual_length = 0; | ||
564 | } | ||
565 | |||
566 | urb->status = usb_submit_urb(urb, GFP_ATOMIC); | ||
567 | if (urb->status) | ||
568 | tm6000_err("urb resubmit failed (error=%i)\n", | ||
569 | urb->status); | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * Stop and Deallocate URBs | ||
574 | */ | ||
575 | static void tm6000_uninit_isoc(struct tm6000_core *dev) | ||
576 | { | ||
577 | struct urb *urb; | ||
578 | int i; | ||
579 | |||
580 | dev->isoc_ctl.nfields = -1; | ||
581 | dev->isoc_ctl.buf = NULL; | ||
582 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | ||
583 | urb=dev->isoc_ctl.urb[i]; | ||
584 | if (urb) { | ||
585 | usb_kill_urb(urb); | ||
586 | usb_unlink_urb(urb); | ||
587 | if (dev->isoc_ctl.transfer_buffer[i]) { | ||
588 | usb_free_coherent(dev->udev, | ||
589 | urb->transfer_buffer_length, | ||
590 | dev->isoc_ctl.transfer_buffer[i], | ||
591 | urb->transfer_dma); | ||
592 | } | ||
593 | usb_free_urb(urb); | ||
594 | dev->isoc_ctl.urb[i] = NULL; | ||
595 | } | ||
596 | dev->isoc_ctl.transfer_buffer[i] = NULL; | ||
597 | } | ||
598 | |||
599 | kfree (dev->isoc_ctl.urb); | ||
600 | kfree (dev->isoc_ctl.transfer_buffer); | ||
601 | |||
602 | dev->isoc_ctl.urb=NULL; | ||
603 | dev->isoc_ctl.transfer_buffer=NULL; | ||
604 | dev->isoc_ctl.num_bufs = 0; | ||
605 | |||
606 | dev->isoc_ctl.num_bufs=0; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Allocate URBs and start IRQ | ||
611 | */ | ||
612 | static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize) | ||
613 | { | ||
614 | struct tm6000_dmaqueue *dma_q = &dev->vidq; | ||
615 | int i, j, sb_size, pipe, size, max_packets, num_bufs = 5; | ||
616 | struct urb *urb; | ||
617 | |||
618 | /* De-allocates all pending stuff */ | ||
619 | tm6000_uninit_isoc(dev); | ||
620 | |||
621 | usb_set_interface(dev->udev, | ||
622 | dev->isoc_in.bInterfaceNumber, | ||
623 | dev->isoc_in.bAlternateSetting); | ||
624 | |||
625 | pipe = usb_rcvisocpipe(dev->udev, | ||
626 | dev->isoc_in.endp->desc.bEndpointAddress & | ||
627 | USB_ENDPOINT_NUMBER_MASK); | ||
628 | |||
629 | size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); | ||
630 | |||
631 | if (size > dev->isoc_in.maxsize) | ||
632 | size = dev->isoc_in.maxsize; | ||
633 | |||
634 | dev->isoc_ctl.max_pkt_size = size; | ||
635 | |||
636 | max_packets = ( framesize + size - 1) / size; | ||
637 | |||
638 | if (max_packets > TM6000_MAX_ISO_PACKETS) | ||
639 | max_packets = TM6000_MAX_ISO_PACKETS; | ||
640 | |||
641 | sb_size = max_packets * size; | ||
642 | |||
643 | dev->isoc_ctl.num_bufs = num_bufs; | ||
644 | |||
645 | dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); | ||
646 | if (!dev->isoc_ctl.urb) { | ||
647 | tm6000_err("cannot alloc memory for usb buffers\n"); | ||
648 | return -ENOMEM; | ||
649 | } | ||
650 | |||
651 | dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, | ||
652 | GFP_KERNEL); | ||
653 | if (!dev->isoc_ctl.transfer_buffer) { | ||
654 | tm6000_err("cannot allocate memory for usbtransfer\n"); | ||
655 | kfree(dev->isoc_ctl.urb); | ||
656 | return -ENOMEM; | ||
657 | } | ||
658 | |||
659 | dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets" | ||
660 | " (%d bytes) of %d bytes each to handle %u size\n", | ||
661 | max_packets, num_bufs, sb_size, | ||
662 | dev->isoc_in.maxsize, size); | ||
663 | |||
664 | /* allocate urbs and transfer buffers */ | ||
665 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | ||
666 | urb = usb_alloc_urb(max_packets, GFP_KERNEL); | ||
667 | if (!urb) { | ||
668 | tm6000_err("cannot alloc isoc_ctl.urb %i\n", i); | ||
669 | tm6000_uninit_isoc(dev); | ||
670 | usb_free_urb(urb); | ||
671 | return -ENOMEM; | ||
672 | } | ||
673 | dev->isoc_ctl.urb[i] = urb; | ||
674 | |||
675 | dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, | ||
676 | sb_size, GFP_KERNEL, &urb->transfer_dma); | ||
677 | if (!dev->isoc_ctl.transfer_buffer[i]) { | ||
678 | tm6000_err ("unable to allocate %i bytes for transfer" | ||
679 | " buffer %i%s\n", | ||
680 | sb_size, i, | ||
681 | in_interrupt()?" while in int":""); | ||
682 | tm6000_uninit_isoc(dev); | ||
683 | return -ENOMEM; | ||
684 | } | ||
685 | memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); | ||
686 | |||
687 | usb_fill_bulk_urb(urb, dev->udev, pipe, | ||
688 | dev->isoc_ctl.transfer_buffer[i], sb_size, | ||
689 | tm6000_irq_callback, dma_q); | ||
690 | urb->interval = dev->isoc_in.endp->desc.bInterval; | ||
691 | urb->number_of_packets = max_packets; | ||
692 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
693 | |||
694 | for (j = 0; j < max_packets; j++) { | ||
695 | urb->iso_frame_desc[j].offset = size * j; | ||
696 | urb->iso_frame_desc[j].length = size; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static int tm6000_start_thread( struct tm6000_core *dev) | ||
704 | { | ||
705 | struct tm6000_dmaqueue *dma_q = &dev->vidq; | ||
706 | int i; | ||
707 | |||
708 | dma_q->frame=0; | ||
709 | dma_q->ini_jiffies=jiffies; | ||
710 | |||
711 | init_waitqueue_head(&dma_q->wq); | ||
712 | |||
713 | /* submit urbs and enables IRQ */ | ||
714 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | ||
715 | int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); | ||
716 | if (rc) { | ||
717 | tm6000_err("submit of urb %i failed (error=%i)\n", i, | ||
718 | rc); | ||
719 | tm6000_uninit_isoc(dev); | ||
720 | return rc; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | /* ------------------------------------------------------------------ | ||
728 | Videobuf operations | ||
729 | ------------------------------------------------------------------*/ | ||
730 | |||
731 | static int | ||
732 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | ||
733 | { | ||
734 | struct tm6000_fh *fh = vq->priv_data; | ||
735 | |||
736 | *size = fh->fmt->depth * fh->width * fh->height >> 3; | ||
737 | if (0 == *count) | ||
738 | *count = TM6000_DEF_BUF; | ||
739 | |||
740 | if (*count < TM6000_MIN_BUF) { | ||
741 | *count=TM6000_MIN_BUF; | ||
742 | } | ||
743 | |||
744 | while (*size * *count > vid_limit * 1024 * 1024) | ||
745 | (*count)--; | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf) | ||
751 | { | ||
752 | struct tm6000_fh *fh = vq->priv_data; | ||
753 | struct tm6000_core *dev = fh->dev; | ||
754 | unsigned long flags; | ||
755 | |||
756 | if (in_interrupt()) | ||
757 | BUG(); | ||
758 | |||
759 | /* We used to wait for the buffer to finish here, but this didn't work | ||
760 | because, as we were keeping the state as VIDEOBUF_QUEUED, | ||
761 | videobuf_queue_cancel marked it as finished for us. | ||
762 | (Also, it could wedge forever if the hardware was misconfigured.) | ||
763 | |||
764 | This should be safe; by the time we get here, the buffer isn't | ||
765 | queued anymore. If we ever start marking the buffers as | ||
766 | VIDEOBUF_ACTIVE, it won't be, though. | ||
767 | */ | ||
768 | spin_lock_irqsave(&dev->slock, flags); | ||
769 | if (dev->isoc_ctl.buf == buf) | ||
770 | dev->isoc_ctl.buf = NULL; | ||
771 | spin_unlock_irqrestore(&dev->slock, flags); | ||
772 | |||
773 | videobuf_vmalloc_free(&buf->vb); | ||
774 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
775 | } | ||
776 | |||
777 | static int | ||
778 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | ||
779 | enum v4l2_field field) | ||
780 | { | ||
781 | struct tm6000_fh *fh = vq->priv_data; | ||
782 | struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb); | ||
783 | struct tm6000_core *dev = fh->dev; | ||
784 | int rc = 0, urb_init = 0; | ||
785 | |||
786 | BUG_ON(NULL == fh->fmt); | ||
787 | |||
788 | |||
789 | /* FIXME: It assumes depth=2 */ | ||
790 | /* The only currently supported format is 16 bits/pixel */ | ||
791 | buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3; | ||
792 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
793 | return -EINVAL; | ||
794 | |||
795 | if (buf->fmt != fh->fmt || | ||
796 | buf->vb.width != fh->width || | ||
797 | buf->vb.height != fh->height || | ||
798 | buf->vb.field != field) { | ||
799 | buf->fmt = fh->fmt; | ||
800 | buf->vb.width = fh->width; | ||
801 | buf->vb.height = fh->height; | ||
802 | buf->vb.field = field; | ||
803 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
804 | } | ||
805 | |||
806 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
807 | if (0 != (rc = videobuf_iolock(vq, &buf->vb, NULL))) | ||
808 | goto fail; | ||
809 | urb_init = 1; | ||
810 | } | ||
811 | |||
812 | if (!dev->isoc_ctl.num_bufs) | ||
813 | urb_init = 1; | ||
814 | |||
815 | if (urb_init) { | ||
816 | rc = tm6000_prepare_isoc(dev, buf->vb.size); | ||
817 | if (rc < 0) | ||
818 | goto fail; | ||
819 | |||
820 | rc = tm6000_start_thread(dev); | ||
821 | if (rc < 0) | ||
822 | goto fail; | ||
823 | |||
824 | } | ||
825 | |||
826 | buf->vb.state = VIDEOBUF_PREPARED; | ||
827 | return 0; | ||
828 | |||
829 | fail: | ||
830 | free_buffer(vq, buf); | ||
831 | return rc; | ||
832 | } | ||
833 | |||
834 | static void | ||
835 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
836 | { | ||
837 | struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb); | ||
838 | struct tm6000_fh *fh = vq->priv_data; | ||
839 | struct tm6000_core *dev = fh->dev; | ||
840 | struct tm6000_dmaqueue *vidq = &dev->vidq; | ||
841 | |||
842 | buf->vb.state = VIDEOBUF_QUEUED; | ||
843 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
844 | } | ||
845 | |||
846 | static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
847 | { | ||
848 | struct tm6000_buffer *buf = container_of(vb,struct tm6000_buffer,vb); | ||
849 | |||
850 | free_buffer(vq,buf); | ||
851 | } | ||
852 | |||
853 | static struct videobuf_queue_ops tm6000_video_qops = { | ||
854 | .buf_setup = buffer_setup, | ||
855 | .buf_prepare = buffer_prepare, | ||
856 | .buf_queue = buffer_queue, | ||
857 | .buf_release = buffer_release, | ||
858 | }; | ||
859 | |||
860 | /* ------------------------------------------------------------------ | ||
861 | IOCTL handling | ||
862 | ------------------------------------------------------------------*/ | ||
863 | |||
864 | static int res_get(struct tm6000_core *dev, struct tm6000_fh *fh) | ||
865 | { | ||
866 | /* is it free? */ | ||
867 | mutex_lock(&dev->lock); | ||
868 | if (dev->resources) { | ||
869 | /* no, someone else uses it */ | ||
870 | mutex_unlock(&dev->lock); | ||
871 | return 0; | ||
872 | } | ||
873 | /* it's free, grab it */ | ||
874 | dev->resources =1; | ||
875 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); | ||
876 | mutex_unlock(&dev->lock); | ||
877 | return 1; | ||
878 | } | ||
879 | |||
880 | static int res_locked(struct tm6000_core *dev) | ||
881 | { | ||
882 | return (dev->resources); | ||
883 | } | ||
884 | |||
885 | static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) | ||
886 | { | ||
887 | mutex_lock(&dev->lock); | ||
888 | dev->resources = 0; | ||
889 | dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); | ||
890 | mutex_unlock(&dev->lock); | ||
891 | } | ||
892 | |||
893 | /* ------------------------------------------------------------------ | ||
894 | IOCTL vidioc handling | ||
895 | ------------------------------------------------------------------*/ | ||
896 | static int vidioc_querycap (struct file *file, void *priv, | ||
897 | struct v4l2_capability *cap) | ||
898 | { | ||
899 | // struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; | ||
900 | |||
901 | strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); | ||
902 | strlcpy(cap->card,"Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); | ||
903 | // strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info)); | ||
904 | cap->version = TM6000_VERSION; | ||
905 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
906 | V4L2_CAP_STREAMING | | ||
907 | V4L2_CAP_TUNER | | ||
908 | V4L2_CAP_READWRITE; | ||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | ||
913 | struct v4l2_fmtdesc *f) | ||
914 | { | ||
915 | if (unlikely(f->index >= ARRAY_SIZE(format))) | ||
916 | return -EINVAL; | ||
917 | |||
918 | strlcpy(f->description,format[f->index].name,sizeof(f->description)); | ||
919 | f->pixelformat = format[f->index].fourcc; | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | ||
924 | struct v4l2_format *f) | ||
925 | { | ||
926 | struct tm6000_fh *fh=priv; | ||
927 | |||
928 | f->fmt.pix.width = fh->width; | ||
929 | f->fmt.pix.height = fh->height; | ||
930 | f->fmt.pix.field = fh->vb_vidq.field; | ||
931 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
932 | f->fmt.pix.bytesperline = | ||
933 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
934 | f->fmt.pix.sizeimage = | ||
935 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
936 | |||
937 | return (0); | ||
938 | } | ||
939 | |||
940 | static struct tm6000_fmt* format_by_fourcc(unsigned int fourcc) | ||
941 | { | ||
942 | unsigned int i; | ||
943 | |||
944 | for (i = 0; i < ARRAY_SIZE(format); i++) | ||
945 | if (format[i].fourcc == fourcc) | ||
946 | return format+i; | ||
947 | return NULL; | ||
948 | } | ||
949 | |||
950 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | ||
951 | struct v4l2_format *f) | ||
952 | { | ||
953 | struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; | ||
954 | struct tm6000_fmt *fmt; | ||
955 | enum v4l2_field field; | ||
956 | |||
957 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
958 | if (NULL == fmt) { | ||
959 | dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)" | ||
960 | " invalid.\n", f->fmt.pix.pixelformat); | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | |||
964 | field = f->fmt.pix.field; | ||
965 | |||
966 | if (field == V4L2_FIELD_ANY) { | ||
967 | // field=V4L2_FIELD_INTERLACED; | ||
968 | field=V4L2_FIELD_SEQ_TB; | ||
969 | } else if (V4L2_FIELD_INTERLACED != field) { | ||
970 | dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n"); | ||
971 | return -EINVAL; | ||
972 | } | ||
973 | |||
974 | tm6000_get_std_res (dev); | ||
975 | |||
976 | f->fmt.pix.width = dev->width; | ||
977 | f->fmt.pix.height = dev->height; | ||
978 | |||
979 | f->fmt.pix.width &= ~0x01; | ||
980 | |||
981 | f->fmt.pix.field = field; | ||
982 | |||
983 | f->fmt.pix.bytesperline = | ||
984 | (f->fmt.pix.width * fmt->depth) >> 3; | ||
985 | f->fmt.pix.sizeimage = | ||
986 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
987 | |||
988 | return 0; | ||
989 | } | ||
990 | |||
991 | /*FIXME: This seems to be generic enough to be at videodev2 */ | ||
992 | static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, | ||
993 | struct v4l2_format *f) | ||
994 | { | ||
995 | struct tm6000_fh *fh=priv; | ||
996 | struct tm6000_core *dev = fh->dev; | ||
997 | int ret = vidioc_try_fmt_vid_cap(file,fh,f); | ||
998 | if (ret < 0) | ||
999 | return (ret); | ||
1000 | |||
1001 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
1002 | fh->width = f->fmt.pix.width; | ||
1003 | fh->height = f->fmt.pix.height; | ||
1004 | fh->vb_vidq.field = f->fmt.pix.field; | ||
1005 | fh->type = f->type; | ||
1006 | |||
1007 | dev->fourcc = f->fmt.pix.pixelformat; | ||
1008 | |||
1009 | tm6000_set_fourcc_format(dev); | ||
1010 | |||
1011 | return (0); | ||
1012 | } | ||
1013 | |||
1014 | static int vidioc_reqbufs (struct file *file, void *priv, | ||
1015 | struct v4l2_requestbuffers *p) | ||
1016 | { | ||
1017 | struct tm6000_fh *fh=priv; | ||
1018 | |||
1019 | return (videobuf_reqbufs(&fh->vb_vidq, p)); | ||
1020 | } | ||
1021 | |||
1022 | static int vidioc_querybuf (struct file *file, void *priv, | ||
1023 | struct v4l2_buffer *p) | ||
1024 | { | ||
1025 | struct tm6000_fh *fh=priv; | ||
1026 | |||
1027 | return (videobuf_querybuf(&fh->vb_vidq, p)); | ||
1028 | } | ||
1029 | |||
1030 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1031 | { | ||
1032 | struct tm6000_fh *fh=priv; | ||
1033 | |||
1034 | return (videobuf_qbuf(&fh->vb_vidq, p)); | ||
1035 | } | ||
1036 | |||
1037 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1038 | { | ||
1039 | struct tm6000_fh *fh=priv; | ||
1040 | |||
1041 | return (videobuf_dqbuf(&fh->vb_vidq, p, | ||
1042 | file->f_flags & O_NONBLOCK)); | ||
1043 | } | ||
1044 | |||
1045 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1046 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) | ||
1047 | { | ||
1048 | struct tm6000_fh *fh=priv; | ||
1049 | |||
1050 | return videobuf_cgmbuf (&fh->vb_vidq, mbuf, 8); | ||
1051 | } | ||
1052 | #endif | ||
1053 | |||
1054 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1055 | { | ||
1056 | struct tm6000_fh *fh=priv; | ||
1057 | struct tm6000_core *dev = fh->dev; | ||
1058 | |||
1059 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1060 | return -EINVAL; | ||
1061 | if (i != fh->type) | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | if (!res_get(dev,fh)) | ||
1065 | return -EBUSY; | ||
1066 | return (videobuf_streamon(&fh->vb_vidq)); | ||
1067 | } | ||
1068 | |||
1069 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1070 | { | ||
1071 | struct tm6000_fh *fh=priv; | ||
1072 | struct tm6000_core *dev = fh->dev; | ||
1073 | |||
1074 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1075 | return -EINVAL; | ||
1076 | if (i != fh->type) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | videobuf_streamoff(&fh->vb_vidq); | ||
1080 | res_free(dev,fh); | ||
1081 | |||
1082 | return (0); | ||
1083 | } | ||
1084 | |||
1085 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm) | ||
1086 | { | ||
1087 | int rc=0; | ||
1088 | struct tm6000_fh *fh=priv; | ||
1089 | struct tm6000_core *dev = fh->dev; | ||
1090 | |||
1091 | rc=tm6000_set_standard (dev, norm); | ||
1092 | |||
1093 | fh->width = dev->width; | ||
1094 | fh->height = dev->height; | ||
1095 | |||
1096 | if (rc<0) | ||
1097 | return rc; | ||
1098 | |||
1099 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static int vidioc_enum_input (struct file *file, void *priv, | ||
1105 | struct v4l2_input *inp) | ||
1106 | { | ||
1107 | switch (inp->index) { | ||
1108 | case TM6000_INPUT_TV: | ||
1109 | inp->type = V4L2_INPUT_TYPE_TUNER; | ||
1110 | strcpy(inp->name,"Television"); | ||
1111 | break; | ||
1112 | case TM6000_INPUT_COMPOSITE: | ||
1113 | inp->type = V4L2_INPUT_TYPE_CAMERA; | ||
1114 | strcpy(inp->name,"Composite"); | ||
1115 | break; | ||
1116 | case TM6000_INPUT_SVIDEO: | ||
1117 | inp->type = V4L2_INPUT_TYPE_CAMERA; | ||
1118 | strcpy(inp->name,"S-Video"); | ||
1119 | break; | ||
1120 | default: | ||
1121 | return -EINVAL; | ||
1122 | } | ||
1123 | inp->std = TM6000_STD; | ||
1124 | |||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | ||
1129 | { | ||
1130 | struct tm6000_fh *fh=priv; | ||
1131 | struct tm6000_core *dev = fh->dev; | ||
1132 | |||
1133 | *i=dev->input; | ||
1134 | |||
1135 | return 0; | ||
1136 | } | ||
1137 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | ||
1138 | { | ||
1139 | struct tm6000_fh *fh=priv; | ||
1140 | struct tm6000_core *dev = fh->dev; | ||
1141 | int rc=0; | ||
1142 | char buf[1]; | ||
1143 | |||
1144 | switch (i) { | ||
1145 | case TM6000_INPUT_TV: | ||
1146 | dev->input=i; | ||
1147 | *buf=0; | ||
1148 | break; | ||
1149 | case TM6000_INPUT_COMPOSITE: | ||
1150 | case TM6000_INPUT_SVIDEO: | ||
1151 | dev->input=i; | ||
1152 | *buf=1; | ||
1153 | break; | ||
1154 | default: | ||
1155 | return -EINVAL; | ||
1156 | } | ||
1157 | rc=tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR, | ||
1158 | REQ_03_SET_GET_MCU_PIN, 0x03, 1, buf, 1); | ||
1159 | |||
1160 | if (!rc) { | ||
1161 | dev->input=i; | ||
1162 | rc=vidioc_s_std (file, priv, &dev->vfd->current_norm); | ||
1163 | } | ||
1164 | |||
1165 | return (rc); | ||
1166 | } | ||
1167 | |||
1168 | /* --- controls ---------------------------------------------- */ | ||
1169 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
1170 | struct v4l2_queryctrl *qc) | ||
1171 | { | ||
1172 | int i; | ||
1173 | |||
1174 | for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) | ||
1175 | if (qc->id && qc->id == tm6000_qctrl[i].id) { | ||
1176 | memcpy(qc, &(tm6000_qctrl[i]), | ||
1177 | sizeof(*qc)); | ||
1178 | return (0); | ||
1179 | } | ||
1180 | |||
1181 | return -EINVAL; | ||
1182 | } | ||
1183 | |||
1184 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
1185 | struct v4l2_control *ctrl) | ||
1186 | { | ||
1187 | struct tm6000_fh *fh=priv; | ||
1188 | struct tm6000_core *dev = fh->dev; | ||
1189 | int val; | ||
1190 | |||
1191 | /* FIXME: Probably, those won't work! Maybe we need shadow regs */ | ||
1192 | switch (ctrl->id) { | ||
1193 | case V4L2_CID_CONTRAST: | ||
1194 | val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); | ||
1195 | break; | ||
1196 | case V4L2_CID_BRIGHTNESS: | ||
1197 | val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); | ||
1198 | return 0; | ||
1199 | case V4L2_CID_SATURATION: | ||
1200 | val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); | ||
1201 | return 0; | ||
1202 | case V4L2_CID_HUE: | ||
1203 | val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); | ||
1204 | return 0; | ||
1205 | default: | ||
1206 | return -EINVAL; | ||
1207 | } | ||
1208 | |||
1209 | if (val<0) | ||
1210 | return val; | ||
1211 | |||
1212 | ctrl->value=val; | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | static int vidioc_s_ctrl (struct file *file, void *priv, | ||
1217 | struct v4l2_control *ctrl) | ||
1218 | { | ||
1219 | struct tm6000_fh *fh =priv; | ||
1220 | struct tm6000_core *dev = fh->dev; | ||
1221 | u8 val=ctrl->value; | ||
1222 | |||
1223 | switch (ctrl->id) { | ||
1224 | case V4L2_CID_CONTRAST: | ||
1225 | tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val); | ||
1226 | return 0; | ||
1227 | case V4L2_CID_BRIGHTNESS: | ||
1228 | tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val); | ||
1229 | return 0; | ||
1230 | case V4L2_CID_SATURATION: | ||
1231 | tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val); | ||
1232 | return 0; | ||
1233 | case V4L2_CID_HUE: | ||
1234 | tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val); | ||
1235 | return 0; | ||
1236 | } | ||
1237 | return -EINVAL; | ||
1238 | } | ||
1239 | |||
1240 | static int vidioc_g_tuner (struct file *file, void *priv, | ||
1241 | struct v4l2_tuner *t) | ||
1242 | { | ||
1243 | struct tm6000_fh *fh =priv; | ||
1244 | struct tm6000_core *dev = fh->dev; | ||
1245 | |||
1246 | if (unlikely(UNSET == dev->tuner_type)) | ||
1247 | return -EINVAL; | ||
1248 | if (0 != t->index) | ||
1249 | return -EINVAL; | ||
1250 | |||
1251 | strcpy(t->name, "Television"); | ||
1252 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1253 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1254 | t->rangehigh = 0xffffffffUL; | ||
1255 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static int vidioc_s_tuner (struct file *file, void *priv, | ||
1261 | struct v4l2_tuner *t) | ||
1262 | { | ||
1263 | struct tm6000_fh *fh =priv; | ||
1264 | struct tm6000_core *dev = fh->dev; | ||
1265 | |||
1266 | if (UNSET == dev->tuner_type) | ||
1267 | return -EINVAL; | ||
1268 | if (0 != t->index) | ||
1269 | return -EINVAL; | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | static int vidioc_g_frequency (struct file *file, void *priv, | ||
1275 | struct v4l2_frequency *f) | ||
1276 | { | ||
1277 | struct tm6000_fh *fh =priv; | ||
1278 | struct tm6000_core *dev = fh->dev; | ||
1279 | |||
1280 | if (unlikely(UNSET == dev->tuner_type)) | ||
1281 | return -EINVAL; | ||
1282 | |||
1283 | f->type = V4L2_TUNER_ANALOG_TV; | ||
1284 | f->frequency = dev->freq; | ||
1285 | |||
1286 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f); | ||
1287 | |||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static int vidioc_s_frequency (struct file *file, void *priv, | ||
1292 | struct v4l2_frequency *f) | ||
1293 | { | ||
1294 | struct tm6000_fh *fh =priv; | ||
1295 | struct tm6000_core *dev = fh->dev; | ||
1296 | |||
1297 | if (unlikely(f->type != V4L2_TUNER_ANALOG_TV)) | ||
1298 | return -EINVAL; | ||
1299 | |||
1300 | if (unlikely(UNSET == dev->tuner_type)) | ||
1301 | return -EINVAL; | ||
1302 | if (unlikely(f->tuner != 0)) | ||
1303 | return -EINVAL; | ||
1304 | |||
1305 | // mutex_lock(&dev->lock); | ||
1306 | dev->freq = f->frequency; | ||
1307 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); | ||
1308 | // mutex_unlock(&dev->lock); | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | /* ------------------------------------------------------------------ | ||
1314 | File operations for the device | ||
1315 | ------------------------------------------------------------------*/ | ||
1316 | |||
1317 | static int tm6000_open(struct file *file) | ||
1318 | { | ||
1319 | struct video_device *vdev = video_devdata(file); | ||
1320 | struct tm6000_core *dev = video_drvdata(file); | ||
1321 | struct tm6000_fh *fh; | ||
1322 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1323 | int i,rc; | ||
1324 | |||
1325 | printk(KERN_INFO "tm6000: open called (dev=%s)\n", | ||
1326 | video_device_node_name(vdev)); | ||
1327 | |||
1328 | dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", | ||
1329 | video_device_node_name(vdev)); | ||
1330 | |||
1331 | |||
1332 | /* If more than one user, mutex should be added */ | ||
1333 | dev->users++; | ||
1334 | |||
1335 | dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n", | ||
1336 | video_device_node_name(vdev), v4l2_type_names[type], | ||
1337 | dev->users); | ||
1338 | |||
1339 | /* allocate + initialize per filehandle data */ | ||
1340 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
1341 | if (NULL == fh) { | ||
1342 | dev->users--; | ||
1343 | return -ENOMEM; | ||
1344 | } | ||
1345 | |||
1346 | file->private_data = fh; | ||
1347 | fh->dev = dev; | ||
1348 | |||
1349 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1350 | dev->fourcc = format[0].fourcc; | ||
1351 | |||
1352 | fh->fmt = format_by_fourcc(dev->fourcc); | ||
1353 | |||
1354 | tm6000_get_std_res (dev); | ||
1355 | |||
1356 | fh->width = dev->width; | ||
1357 | fh->height = dev->height; | ||
1358 | |||
1359 | dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, " | ||
1360 | "dev->vidq=0x%08lx\n", | ||
1361 | (unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq); | ||
1362 | dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " | ||
1363 | "queued=%d\n",list_empty(&dev->vidq.queued)); | ||
1364 | dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " | ||
1365 | "active=%d\n",list_empty(&dev->vidq.active)); | ||
1366 | |||
1367 | /* initialize hardware on analog mode */ | ||
1368 | if (dev->mode!=TM6000_MODE_ANALOG) { | ||
1369 | rc=tm6000_init_analog_mode (dev); | ||
1370 | if (rc<0) | ||
1371 | return rc; | ||
1372 | |||
1373 | /* Put all controls at a sane state */ | ||
1374 | for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) | ||
1375 | qctl_regs[i] =tm6000_qctrl[i].default_value; | ||
1376 | |||
1377 | dev->mode=TM6000_MODE_ANALOG; | ||
1378 | } | ||
1379 | |||
1380 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, | ||
1381 | NULL, &dev->slock, | ||
1382 | fh->type, | ||
1383 | V4L2_FIELD_INTERLACED, | ||
1384 | sizeof(struct tm6000_buffer),fh); | ||
1385 | |||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1389 | static ssize_t | ||
1390 | tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) | ||
1391 | { | ||
1392 | struct tm6000_fh *fh = file->private_data; | ||
1393 | |||
1394 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1395 | if (res_locked(fh->dev)) | ||
1396 | return -EBUSY; | ||
1397 | |||
1398 | return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, | ||
1399 | file->f_flags & O_NONBLOCK); | ||
1400 | } | ||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static unsigned int | ||
1405 | tm6000_poll(struct file *file, struct poll_table_struct *wait) | ||
1406 | { | ||
1407 | struct tm6000_fh *fh = file->private_data; | ||
1408 | struct tm6000_buffer *buf; | ||
1409 | |||
1410 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | ||
1411 | return POLLERR; | ||
1412 | |||
1413 | if (res_get(fh->dev,fh)) { | ||
1414 | /* streaming capture */ | ||
1415 | if (list_empty(&fh->vb_vidq.stream)) | ||
1416 | return POLLERR; | ||
1417 | buf = list_entry(fh->vb_vidq.stream.next,struct tm6000_buffer,vb.stream); | ||
1418 | } else { | ||
1419 | /* read() capture */ | ||
1420 | return videobuf_poll_stream(file, &fh->vb_vidq, | ||
1421 | wait); | ||
1422 | } | ||
1423 | poll_wait(file, &buf->vb.done, wait); | ||
1424 | if (buf->vb.state == VIDEOBUF_DONE || | ||
1425 | buf->vb.state == VIDEOBUF_ERROR) | ||
1426 | return POLLIN|POLLRDNORM; | ||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static int tm6000_release(struct file *file) | ||
1431 | { | ||
1432 | struct tm6000_fh *fh = file->private_data; | ||
1433 | struct tm6000_core *dev = fh->dev; | ||
1434 | struct video_device *vdev = video_devdata(file); | ||
1435 | |||
1436 | dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n", | ||
1437 | video_device_node_name(vdev), dev->users); | ||
1438 | |||
1439 | dev->users--; | ||
1440 | |||
1441 | if (!dev->users) { | ||
1442 | tm6000_uninit_isoc(dev); | ||
1443 | videobuf_mmap_free(&fh->vb_vidq); | ||
1444 | } | ||
1445 | |||
1446 | kfree (fh); | ||
1447 | |||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | static int tm6000_mmap(struct file *file, struct vm_area_struct * vma) | ||
1452 | { | ||
1453 | struct tm6000_fh *fh = file->private_data; | ||
1454 | int ret; | ||
1455 | |||
1456 | ret=videobuf_mmap_mapper(&fh->vb_vidq, vma); | ||
1457 | |||
1458 | return ret; | ||
1459 | } | ||
1460 | |||
1461 | static struct v4l2_file_operations tm6000_fops = { | ||
1462 | .owner = THIS_MODULE, | ||
1463 | .open = tm6000_open, | ||
1464 | .release = tm6000_release, | ||
1465 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ | ||
1466 | .read = tm6000_read, | ||
1467 | .poll = tm6000_poll, | ||
1468 | .mmap = tm6000_mmap, | ||
1469 | }; | ||
1470 | |||
1471 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
1472 | .vidioc_querycap = vidioc_querycap, | ||
1473 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
1474 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
1475 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
1476 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
1477 | .vidioc_s_std = vidioc_s_std, | ||
1478 | .vidioc_enum_input = vidioc_enum_input, | ||
1479 | .vidioc_g_input = vidioc_g_input, | ||
1480 | .vidioc_s_input = vidioc_s_input, | ||
1481 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1482 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1483 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1484 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1485 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1486 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1487 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1488 | .vidioc_streamon = vidioc_streamon, | ||
1489 | .vidioc_streamoff = vidioc_streamoff, | ||
1490 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1491 | .vidioc_querybuf = vidioc_querybuf, | ||
1492 | .vidioc_qbuf = vidioc_qbuf, | ||
1493 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1494 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1495 | .vidiocgmbuf = vidiocgmbuf, | ||
1496 | #endif | ||
1497 | }; | ||
1498 | |||
1499 | static struct video_device tm6000_template = { | ||
1500 | .name = "tm6000", | ||
1501 | .fops = &tm6000_fops, | ||
1502 | .ioctl_ops = &video_ioctl_ops, | ||
1503 | .release = video_device_release, | ||
1504 | .tvnorms = TM6000_STD, | ||
1505 | .current_norm = V4L2_STD_NTSC_M, | ||
1506 | }; | ||
1507 | |||
1508 | /* ----------------------------------------------------------------- | ||
1509 | Initialization and module stuff | ||
1510 | ------------------------------------------------------------------*/ | ||
1511 | |||
1512 | int tm6000_v4l2_register(struct tm6000_core *dev) | ||
1513 | { | ||
1514 | int ret = -1; | ||
1515 | struct video_device *vfd; | ||
1516 | |||
1517 | vfd = video_device_alloc(); | ||
1518 | if(!vfd) { | ||
1519 | return -ENOMEM; | ||
1520 | } | ||
1521 | dev->vfd = vfd; | ||
1522 | |||
1523 | /* init video dma queues */ | ||
1524 | INIT_LIST_HEAD(&dev->vidq.active); | ||
1525 | INIT_LIST_HEAD(&dev->vidq.queued); | ||
1526 | |||
1527 | memcpy (dev->vfd, &tm6000_template, sizeof(*(dev->vfd))); | ||
1528 | dev->vfd->debug=tm6000_debug; | ||
1529 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
1530 | video_set_drvdata(vfd, dev); | ||
1531 | |||
1532 | ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); | ||
1533 | printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); | ||
1534 | return ret; | ||
1535 | } | ||
1536 | |||
1537 | int tm6000_v4l2_unregister(struct tm6000_core *dev) | ||
1538 | { | ||
1539 | video_unregister_device(dev->vfd); | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | int tm6000_v4l2_exit(void) | ||
1545 | { | ||
1546 | return 0; | ||
1547 | } | ||
1548 | |||
1549 | module_param(video_nr, int, 0); | ||
1550 | MODULE_PARM_DESC(video_nr,"Allow changing video device number"); | ||
1551 | |||
1552 | module_param_named (debug, tm6000_debug, int, 0444); | ||
1553 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
1554 | |||
1555 | module_param(vid_limit,int,0644); | ||
1556 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
1557 | |||
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h new file mode 100644 index 000000000000..6812d6867d57 --- /dev/null +++ b/drivers/staging/tm6000/tm6000.h | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices | ||
3 | |||
4 | Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> | ||
5 | |||
6 | Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> | ||
7 | - DVB-T support | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation version 2 | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | // Use the tm6000-hack, instead of the proper initialization code | ||
24 | //#define HACK 1 | ||
25 | |||
26 | #include <linux/videodev2.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/videobuf-vmalloc.h> | ||
29 | #include "tm6000-usb-isoc.h" | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <media/v4l2-device.h> | ||
33 | |||
34 | |||
35 | #include <linux/dvb/frontend.h> | ||
36 | #include "dvb_demux.h" | ||
37 | #include "dvb_frontend.h" | ||
38 | #include "dmxdev.h" | ||
39 | |||
40 | #define TM6000_VERSION KERNEL_VERSION(0, 0, 2) | ||
41 | |||
42 | /* Inputs */ | ||
43 | |||
44 | enum tm6000_itype { | ||
45 | TM6000_INPUT_TV = 0, | ||
46 | TM6000_INPUT_COMPOSITE, | ||
47 | TM6000_INPUT_SVIDEO, | ||
48 | }; | ||
49 | |||
50 | enum tm6000_devtype { | ||
51 | TM6000 = 0, | ||
52 | TM5600, | ||
53 | TM6010, | ||
54 | }; | ||
55 | |||
56 | /* ------------------------------------------------------------------ | ||
57 | Basic structures | ||
58 | ------------------------------------------------------------------*/ | ||
59 | |||
60 | struct tm6000_fmt { | ||
61 | char *name; | ||
62 | u32 fourcc; /* v4l2 format id */ | ||
63 | int depth; | ||
64 | }; | ||
65 | |||
66 | /* buffer for one video frame */ | ||
67 | struct tm6000_buffer { | ||
68 | /* common v4l buffer stuff -- must be first */ | ||
69 | struct videobuf_buffer vb; | ||
70 | |||
71 | struct tm6000_fmt *fmt; | ||
72 | }; | ||
73 | |||
74 | struct tm6000_dmaqueue { | ||
75 | struct list_head active; | ||
76 | struct list_head queued; | ||
77 | |||
78 | /* thread for generating video stream*/ | ||
79 | struct task_struct *kthread; | ||
80 | wait_queue_head_t wq; | ||
81 | /* Counters to control fps rate */ | ||
82 | int frame; | ||
83 | int ini_jiffies; | ||
84 | }; | ||
85 | |||
86 | /* device states */ | ||
87 | enum tm6000_core_state { | ||
88 | DEV_INITIALIZED = 0x01, | ||
89 | DEV_DISCONNECTED = 0x02, | ||
90 | DEV_MISCONFIGURED = 0x04, | ||
91 | }; | ||
92 | |||
93 | /* io methods */ | ||
94 | enum tm6000_io_method { | ||
95 | IO_NONE, | ||
96 | IO_READ, | ||
97 | IO_MMAP, | ||
98 | }; | ||
99 | |||
100 | enum tm6000_mode { | ||
101 | TM6000_MODE_UNKNOWN=0, | ||
102 | TM6000_MODE_ANALOG, | ||
103 | TM6000_MODE_DIGITAL, | ||
104 | }; | ||
105 | |||
106 | struct tm6000_gpio { | ||
107 | int tuner_reset; | ||
108 | int tuner_on; | ||
109 | int demod_reset; | ||
110 | int demod_on; | ||
111 | int power_led; | ||
112 | int dvb_led; | ||
113 | int ir; | ||
114 | }; | ||
115 | |||
116 | struct tm6000_capabilities { | ||
117 | unsigned int has_tuner:1; | ||
118 | unsigned int has_tda9874:1; | ||
119 | unsigned int has_dvb:1; | ||
120 | unsigned int has_zl10353:1; | ||
121 | unsigned int has_eeprom:1; | ||
122 | unsigned int has_remote:1; | ||
123 | }; | ||
124 | |||
125 | struct tm6000_dvb { | ||
126 | struct dvb_adapter adapter; | ||
127 | struct dvb_demux demux; | ||
128 | struct dvb_frontend *frontend; | ||
129 | struct dmxdev dmxdev; | ||
130 | unsigned int streams; | ||
131 | struct urb *bulk_urb; | ||
132 | struct mutex mutex; | ||
133 | }; | ||
134 | |||
135 | struct tm6000_endpoint { | ||
136 | struct usb_host_endpoint *endp; | ||
137 | __u8 bInterfaceNumber; | ||
138 | __u8 bAlternateSetting; | ||
139 | unsigned maxsize; | ||
140 | }; | ||
141 | |||
142 | struct tm6000_core { | ||
143 | /* generic device properties */ | ||
144 | char name[30]; /* name (including minor) of the device */ | ||
145 | int model; /* index in the device_data struct */ | ||
146 | int devno; /* marks the number of this device */ | ||
147 | enum tm6000_devtype dev_type; /* type of device */ | ||
148 | |||
149 | v4l2_std_id norm; /* Current norm */ | ||
150 | int width,height; /* Selected resolution */ | ||
151 | |||
152 | enum tm6000_core_state state; | ||
153 | |||
154 | /* Device Capabilities*/ | ||
155 | struct tm6000_capabilities caps; | ||
156 | |||
157 | /* Tuner configuration */ | ||
158 | int tuner_type; /* type of the tuner */ | ||
159 | int tuner_addr; /* tuner address */ | ||
160 | |||
161 | struct tm6000_gpio gpio; | ||
162 | |||
163 | /* Demodulator configuration */ | ||
164 | int demod_addr; /* demodulator address */ | ||
165 | |||
166 | int audio_bitrate; | ||
167 | /* i2c i/o */ | ||
168 | struct i2c_adapter i2c_adap; | ||
169 | struct i2c_client i2c_client; | ||
170 | |||
171 | /* video for linux */ | ||
172 | int users; | ||
173 | |||
174 | /* various device info */ | ||
175 | unsigned int resources; | ||
176 | struct video_device *vfd; | ||
177 | struct tm6000_dmaqueue vidq; | ||
178 | struct v4l2_device v4l2_dev; | ||
179 | |||
180 | int input; | ||
181 | int freq; | ||
182 | unsigned int fourcc; | ||
183 | |||
184 | enum tm6000_mode mode; | ||
185 | |||
186 | /* DVB-T support */ | ||
187 | struct tm6000_dvb *dvb; | ||
188 | |||
189 | /* locks */ | ||
190 | struct mutex lock; | ||
191 | |||
192 | /* usb transfer */ | ||
193 | struct usb_device *udev; /* the usb device */ | ||
194 | |||
195 | struct tm6000_endpoint bulk_in, bulk_out, isoc_in, isoc_out; | ||
196 | |||
197 | /* scaler!=0 if scaler is active*/ | ||
198 | int scaler; | ||
199 | |||
200 | /* Isoc control struct */ | ||
201 | struct usb_isoc_ctl isoc_ctl; | ||
202 | |||
203 | spinlock_t slock; | ||
204 | }; | ||
205 | |||
206 | struct tm6000_fh { | ||
207 | struct tm6000_core *dev; | ||
208 | |||
209 | /* video capture */ | ||
210 | struct tm6000_fmt *fmt; | ||
211 | unsigned int width,height; | ||
212 | struct videobuf_queue vb_vidq; | ||
213 | |||
214 | enum v4l2_buf_type type; | ||
215 | }; | ||
216 | |||
217 | #define TM6000_STD V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \ | ||
218 | V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \ | ||
219 | V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM | ||
220 | |||
221 | /* In tm6000-cards.c */ | ||
222 | |||
223 | int tm6000_tuner_callback (void *ptr, int component, int command, int arg); | ||
224 | int tm6000_xc5000_callback (void *ptr, int component, int command, int arg); | ||
225 | int tm6000_cards_setup(struct tm6000_core *dev); | ||
226 | |||
227 | /* In tm6000-core.c */ | ||
228 | |||
229 | int tm6000_read_write_usb (struct tm6000_core *dev, u8 reqtype, u8 req, | ||
230 | u16 value, u16 index, u8 *buf, u16 len); | ||
231 | int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index); | ||
232 | int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index); | ||
233 | int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index); | ||
234 | int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index); | ||
235 | int tm6000_init (struct tm6000_core *dev); | ||
236 | |||
237 | int tm6000_init_analog_mode (struct tm6000_core *dev); | ||
238 | int tm6000_init_digital_mode (struct tm6000_core *dev); | ||
239 | int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate); | ||
240 | |||
241 | int tm6000_dvb_register(struct tm6000_core *dev); | ||
242 | void tm6000_dvb_unregister(struct tm6000_core *dev); | ||
243 | |||
244 | int tm6000_v4l2_register(struct tm6000_core *dev); | ||
245 | int tm6000_v4l2_unregister(struct tm6000_core *dev); | ||
246 | int tm6000_v4l2_exit(void); | ||
247 | void tm6000_set_fourcc_format(struct tm6000_core *dev); | ||
248 | |||
249 | /* In tm6000-stds.c */ | ||
250 | void tm6000_get_std_res(struct tm6000_core *dev); | ||
251 | int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm); | ||
252 | |||
253 | /* In tm6000-i2c.c */ | ||
254 | int tm6000_i2c_register(struct tm6000_core *dev); | ||
255 | int tm6000_i2c_unregister(struct tm6000_core *dev); | ||
256 | |||
257 | /* In tm6000-queue.c */ | ||
258 | |||
259 | int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma); | ||
260 | |||
261 | int tm6000_vidioc_streamon(struct file *file, void *priv, | ||
262 | enum v4l2_buf_type i); | ||
263 | int tm6000_vidioc_streamoff(struct file *file, void *priv, | ||
264 | enum v4l2_buf_type i); | ||
265 | int tm6000_vidioc_reqbufs (struct file *file, void *priv, | ||
266 | struct v4l2_requestbuffers *rb); | ||
267 | int tm6000_vidioc_querybuf (struct file *file, void *priv, | ||
268 | struct v4l2_buffer *b); | ||
269 | int tm6000_vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *b); | ||
270 | int tm6000_vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *b); | ||
271 | ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count, | ||
272 | loff_t * f_pos); | ||
273 | unsigned int tm6000_v4l2_poll(struct file *file, | ||
274 | struct poll_table_struct *wait); | ||
275 | int tm6000_queue_init(struct tm6000_core *dev); | ||
276 | |||
277 | /* In tm6000-alsa.c */ | ||
278 | int tm6000_audio_init(struct tm6000_core *dev, int idx); | ||
279 | |||
280 | |||
281 | /* Debug stuff */ | ||
282 | |||
283 | extern int tm6000_debug; | ||
284 | |||
285 | #define dprintk(dev, level, fmt, arg...) do {\ | ||
286 | if (tm6000_debug & level) \ | ||
287 | printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \ | ||
288 | dev->name, __FUNCTION__ , ##arg); } while (0) | ||
289 | |||
290 | #define V4L2_DEBUG_REG 0x0004 | ||
291 | #define V4L2_DEBUG_I2C 0x0008 | ||
292 | #define V4L2_DEBUG_QUEUE 0x0010 | ||
293 | #define V4L2_DEBUG_ISOC 0x0020 | ||
294 | #define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */ | ||
295 | #define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */ | ||
296 | |||
297 | #define tm6000_err(fmt, arg...) do {\ | ||
298 | printk(KERN_ERR "tm6000 %s :"fmt, \ | ||
299 | __FUNCTION__ , ##arg); } while (0) | ||
300 | |||
301 | |||
diff --git a/include/linux/meye.h b/include/linux/meye.h index 12010ace1f04..0dd49954f746 100644 --- a/include/linux/meye.h +++ b/include/linux/meye.h | |||
@@ -44,17 +44,17 @@ struct meye_params { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* query the extended parameters */ | 46 | /* query the extended parameters */ |
47 | #define MEYEIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct meye_params) | 47 | #define MEYEIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct meye_params) |
48 | /* set the extended parameters */ | 48 | /* set the extended parameters */ |
49 | #define MEYEIOC_S_PARAMS _IOW ('v', BASE_VIDIOCPRIVATE+1, struct meye_params) | 49 | #define MEYEIOC_S_PARAMS _IOW ('v', BASE_VIDIOC_PRIVATE+1, struct meye_params) |
50 | /* queue a buffer for mjpeg capture */ | 50 | /* queue a buffer for mjpeg capture */ |
51 | #define MEYEIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+2, int) | 51 | #define MEYEIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+2, int) |
52 | /* sync a previously queued mjpeg buffer */ | 52 | /* sync a previously queued mjpeg buffer */ |
53 | #define MEYEIOC_SYNC _IOWR('v', BASE_VIDIOCPRIVATE+3, int) | 53 | #define MEYEIOC_SYNC _IOWR('v', BASE_VIDIOC_PRIVATE+3, int) |
54 | /* get a still uncompressed snapshot */ | 54 | /* get a still uncompressed snapshot */ |
55 | #define MEYEIOC_STILLCAPT _IO ('v', BASE_VIDIOCPRIVATE+4) | 55 | #define MEYEIOC_STILLCAPT _IO ('v', BASE_VIDIOC_PRIVATE+4) |
56 | /* get a jpeg compressed snapshot */ | 56 | /* get a jpeg compressed snapshot */ |
57 | #define MEYEIOC_STILLJCAPT _IOR ('v', BASE_VIDIOCPRIVATE+5, int) | 57 | #define MEYEIOC_STILLJCAPT _IOR ('v', BASE_VIDIOC_PRIVATE+5, int) |
58 | 58 | ||
59 | /* V4L2 private controls */ | 59 | /* V4L2 private controls */ |
60 | #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE | 60 | #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 3793d168b44d..047f7e6edb86 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -160,16 +160,6 @@ enum v4l2_buf_type { | |||
160 | V4L2_BUF_TYPE_PRIVATE = 0x80, | 160 | V4L2_BUF_TYPE_PRIVATE = 0x80, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | enum v4l2_ctrl_type { | ||
164 | V4L2_CTRL_TYPE_INTEGER = 1, | ||
165 | V4L2_CTRL_TYPE_BOOLEAN = 2, | ||
166 | V4L2_CTRL_TYPE_MENU = 3, | ||
167 | V4L2_CTRL_TYPE_BUTTON = 4, | ||
168 | V4L2_CTRL_TYPE_INTEGER64 = 5, | ||
169 | V4L2_CTRL_TYPE_CTRL_CLASS = 6, | ||
170 | V4L2_CTRL_TYPE_STRING = 7, | ||
171 | }; | ||
172 | |||
173 | enum v4l2_tuner_type { | 163 | enum v4l2_tuner_type { |
174 | V4L2_TUNER_RADIO = 1, | 164 | V4L2_TUNER_RADIO = 1, |
175 | V4L2_TUNER_ANALOG_TV = 2, | 165 | V4L2_TUNER_ANALOG_TV = 2, |
@@ -294,6 +284,8 @@ struct v4l2_pix_format { | |||
294 | 284 | ||
295 | /* Grey formats */ | 285 | /* Grey formats */ |
296 | #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ | 286 | #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ |
287 | #define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ | ||
288 | #define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */ | ||
297 | #define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ | 289 | #define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ |
298 | #define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ | 290 | #define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ |
299 | 291 | ||
@@ -369,6 +361,7 @@ struct v4l2_pix_format { | |||
369 | #define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ | 361 | #define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ |
370 | #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ | 362 | #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ |
371 | #define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ | 363 | #define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ |
364 | #define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ | ||
372 | 365 | ||
373 | /* | 366 | /* |
374 | * F O R M A T E N U M E R A T I O N | 367 | * F O R M A T E N U M E R A T I O N |
@@ -549,6 +542,8 @@ struct v4l2_buffer { | |||
549 | #define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ | 542 | #define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ |
550 | #define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ | 543 | #define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ |
551 | #define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ | 544 | #define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ |
545 | /* Buffer is ready, but the data contained within is corrupted. */ | ||
546 | #define V4L2_BUF_FLAG_ERROR 0x0040 | ||
552 | #define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ | 547 | #define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ |
553 | #define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ | 548 | #define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ |
554 | 549 | ||
@@ -939,6 +934,16 @@ struct v4l2_ext_controls { | |||
939 | #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) | 934 | #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) |
940 | #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) | 935 | #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) |
941 | 936 | ||
937 | enum v4l2_ctrl_type { | ||
938 | V4L2_CTRL_TYPE_INTEGER = 1, | ||
939 | V4L2_CTRL_TYPE_BOOLEAN = 2, | ||
940 | V4L2_CTRL_TYPE_MENU = 3, | ||
941 | V4L2_CTRL_TYPE_BUTTON = 4, | ||
942 | V4L2_CTRL_TYPE_INTEGER64 = 5, | ||
943 | V4L2_CTRL_TYPE_CTRL_CLASS = 6, | ||
944 | V4L2_CTRL_TYPE_STRING = 7, | ||
945 | }; | ||
946 | |||
942 | /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ | 947 | /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ |
943 | struct v4l2_queryctrl { | 948 | struct v4l2_queryctrl { |
944 | __u32 id; | 949 | __u32 id; |
@@ -1023,14 +1028,24 @@ enum v4l2_colorfx { | |||
1023 | V4L2_COLORFX_NONE = 0, | 1028 | V4L2_COLORFX_NONE = 0, |
1024 | V4L2_COLORFX_BW = 1, | 1029 | V4L2_COLORFX_BW = 1, |
1025 | V4L2_COLORFX_SEPIA = 2, | 1030 | V4L2_COLORFX_SEPIA = 2, |
1031 | V4L2_COLORFX_NEGATIVE = 3, | ||
1032 | V4L2_COLORFX_EMBOSS = 4, | ||
1033 | V4L2_COLORFX_SKETCH = 5, | ||
1034 | V4L2_COLORFX_SKY_BLUE = 6, | ||
1035 | V4L2_COLORFX_GRASS_GREEN = 7, | ||
1036 | V4L2_COLORFX_SKIN_WHITEN = 8, | ||
1037 | V4L2_COLORFX_VIVID = 9, | ||
1026 | }; | 1038 | }; |
1027 | #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) | 1039 | #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) |
1028 | #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) | 1040 | #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) |
1029 | 1041 | ||
1030 | #define V4L2_CID_ROTATE (V4L2_CID_BASE+34) | 1042 | #define V4L2_CID_ROTATE (V4L2_CID_BASE+34) |
1031 | #define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) | 1043 | #define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) |
1044 | |||
1045 | #define V4L2_CID_CHROMA_GAIN (V4L2_CID_BASE+36) | ||
1046 | |||
1032 | /* last CID + 1 */ | 1047 | /* last CID + 1 */ |
1033 | #define V4L2_CID_LASTP1 (V4L2_CID_BASE+36) | 1048 | #define V4L2_CID_LASTP1 (V4L2_CID_BASE+37) |
1034 | 1049 | ||
1035 | /* MPEG-class control IDs defined by V4L2 */ | 1050 | /* MPEG-class control IDs defined by V4L2 */ |
1036 | #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) | 1051 | #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) |
@@ -1276,6 +1291,9 @@ enum v4l2_exposure_auto_type { | |||
1276 | 1291 | ||
1277 | #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) | 1292 | #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) |
1278 | 1293 | ||
1294 | #define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) | ||
1295 | #define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) | ||
1296 | |||
1279 | /* FM Modulator class control IDs */ | 1297 | /* FM Modulator class control IDs */ |
1280 | #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) | 1298 | #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) |
1281 | #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) | 1299 | #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) |
@@ -1621,6 +1639,38 @@ struct v4l2_streamparm { | |||
1621 | }; | 1639 | }; |
1622 | 1640 | ||
1623 | /* | 1641 | /* |
1642 | * E V E N T S | ||
1643 | */ | ||
1644 | |||
1645 | #define V4L2_EVENT_ALL 0 | ||
1646 | #define V4L2_EVENT_VSYNC 1 | ||
1647 | #define V4L2_EVENT_EOS 2 | ||
1648 | #define V4L2_EVENT_PRIVATE_START 0x08000000 | ||
1649 | |||
1650 | /* Payload for V4L2_EVENT_VSYNC */ | ||
1651 | struct v4l2_event_vsync { | ||
1652 | /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */ | ||
1653 | __u8 field; | ||
1654 | } __attribute__ ((packed)); | ||
1655 | |||
1656 | struct v4l2_event { | ||
1657 | __u32 type; | ||
1658 | union { | ||
1659 | struct v4l2_event_vsync vsync; | ||
1660 | __u8 data[64]; | ||
1661 | } u; | ||
1662 | __u32 pending; | ||
1663 | __u32 sequence; | ||
1664 | struct timespec timestamp; | ||
1665 | __u32 reserved[9]; | ||
1666 | }; | ||
1667 | |||
1668 | struct v4l2_event_subscription { | ||
1669 | __u32 type; | ||
1670 | __u32 reserved[7]; | ||
1671 | }; | ||
1672 | |||
1673 | /* | ||
1624 | * A D V A N C E D D E B U G G I N G | 1674 | * A D V A N C E D D E B U G G I N G |
1625 | * | 1675 | * |
1626 | * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! | 1676 | * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! |
@@ -1742,6 +1792,9 @@ struct v4l2_dbg_chip_ident { | |||
1742 | #define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) | 1792 | #define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) |
1743 | #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) | 1793 | #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) |
1744 | #define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) | 1794 | #define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) |
1795 | #define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) | ||
1796 | #define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) | ||
1797 | #define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) | ||
1745 | 1798 | ||
1746 | /* Reminder: when adding new ioctls please add support for them to | 1799 | /* Reminder: when adding new ioctls please add support for them to |
1747 | drivers/media/video/v4l2-compat-ioctl32.c as well! */ | 1800 | drivers/media/video/v4l2-compat-ioctl32.c as well! */ |
diff --git a/include/media/ak881x.h b/include/media/ak881x.h new file mode 100644 index 000000000000..b7f2add5ce7b --- /dev/null +++ b/include/media/ak881x.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Header for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM) | ||
3 | * | ||
4 | * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef AK881X_H | ||
12 | #define AK881X_H | ||
13 | |||
14 | #define AK881X_IF_MODE_MASK (3 << 0) | ||
15 | #define AK881X_IF_MODE_BT656 (0 << 0) | ||
16 | #define AK881X_IF_MODE_MASTER (1 << 0) | ||
17 | #define AK881X_IF_MODE_SLAVE (2 << 0) | ||
18 | #define AK881X_FIELD (1 << 2) | ||
19 | #define AK881X_COMPONENT (1 << 3) | ||
20 | |||
21 | struct ak881x_pdata { | ||
22 | unsigned long flags; | ||
23 | }; | ||
24 | |||
25 | #endif | ||
diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h index 4314a5f6a087..cc973ed845a7 100644 --- a/include/media/davinci/vpfe_capture.h +++ b/include/media/davinci/vpfe_capture.h | |||
@@ -94,6 +94,8 @@ struct vpfe_config { | |||
94 | /* vpfe clock */ | 94 | /* vpfe clock */ |
95 | struct clk *vpssclk; | 95 | struct clk *vpssclk; |
96 | struct clk *slaveclk; | 96 | struct clk *slaveclk; |
97 | /* Function for Clearing the interrupt */ | ||
98 | void (*clr_intr)(int vdint); | ||
97 | }; | 99 | }; |
98 | 100 | ||
99 | struct vpfe_device { | 101 | struct vpfe_device { |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index c66298062d39..528050e39ad9 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -50,6 +50,10 @@ struct card_ir { | |||
50 | struct ir_input_state ir; | 50 | struct ir_input_state ir; |
51 | char name[32]; | 51 | char name[32]; |
52 | char phys[32]; | 52 | char phys[32]; |
53 | int users; | ||
54 | |||
55 | u32 running:1; | ||
56 | struct ir_dev_props props; | ||
53 | 57 | ||
54 | /* Usual gpio signalling */ | 58 | /* Usual gpio signalling */ |
55 | 59 | ||
@@ -79,6 +83,9 @@ struct card_ir { | |||
79 | /* NEC decoding */ | 83 | /* NEC decoding */ |
80 | u32 nec_gpio; | 84 | u32 nec_gpio; |
81 | struct tasklet_struct tlet; | 85 | struct tasklet_struct tlet; |
86 | |||
87 | /* IR core raw decoding */ | ||
88 | u32 raw_decode; | ||
82 | }; | 89 | }; |
83 | 90 | ||
84 | /* Routines from ir-functions.c */ | 91 | /* Routines from ir-functions.c */ |
@@ -97,71 +104,4 @@ u32 ir_rc5_decode(unsigned int code); | |||
97 | void ir_rc5_timer_end(unsigned long data); | 104 | void ir_rc5_timer_end(unsigned long data); |
98 | void ir_rc5_timer_keyup(unsigned long data); | 105 | void ir_rc5_timer_keyup(unsigned long data); |
99 | 106 | ||
100 | /* scancode->keycode map tables from ir-keymaps.c */ | ||
101 | |||
102 | extern struct ir_scancode_table ir_codes_empty_table; | ||
103 | extern struct ir_scancode_table ir_codes_avermedia_table; | ||
104 | extern struct ir_scancode_table ir_codes_avermedia_dvbt_table; | ||
105 | extern struct ir_scancode_table ir_codes_avermedia_m135a_table; | ||
106 | extern struct ir_scancode_table ir_codes_avermedia_cardbus_table; | ||
107 | extern struct ir_scancode_table ir_codes_apac_viewcomp_table; | ||
108 | extern struct ir_scancode_table ir_codes_pixelview_table; | ||
109 | extern struct ir_scancode_table ir_codes_pixelview_new_table; | ||
110 | extern struct ir_scancode_table ir_codes_nebula_table; | ||
111 | extern struct ir_scancode_table ir_codes_dntv_live_dvb_t_table; | ||
112 | extern struct ir_scancode_table ir_codes_iodata_bctv7e_table; | ||
113 | extern struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table; | ||
114 | extern struct ir_scancode_table ir_codes_msi_tvanywhere_table; | ||
115 | extern struct ir_scancode_table ir_codes_cinergy_1400_table; | ||
116 | extern struct ir_scancode_table ir_codes_avertv_303_table; | ||
117 | extern struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table; | ||
118 | extern struct ir_scancode_table ir_codes_em_terratec_table; | ||
119 | extern struct ir_scancode_table ir_codes_pinnacle_grey_table; | ||
120 | extern struct ir_scancode_table ir_codes_flyvideo_table; | ||
121 | extern struct ir_scancode_table ir_codes_flydvb_table; | ||
122 | extern struct ir_scancode_table ir_codes_cinergy_table; | ||
123 | extern struct ir_scancode_table ir_codes_eztv_table; | ||
124 | extern struct ir_scancode_table ir_codes_avermedia_table; | ||
125 | extern struct ir_scancode_table ir_codes_videomate_tv_pvr_table; | ||
126 | extern struct ir_scancode_table ir_codes_manli_table; | ||
127 | extern struct ir_scancode_table ir_codes_gotview7135_table; | ||
128 | extern struct ir_scancode_table ir_codes_purpletv_table; | ||
129 | extern struct ir_scancode_table ir_codes_pctv_sedna_table; | ||
130 | extern struct ir_scancode_table ir_codes_pv951_table; | ||
131 | extern struct ir_scancode_table ir_codes_rc5_tv_table; | ||
132 | extern struct ir_scancode_table ir_codes_winfast_table; | ||
133 | extern struct ir_scancode_table ir_codes_pinnacle_color_table; | ||
134 | extern struct ir_scancode_table ir_codes_hauppauge_new_table; | ||
135 | extern struct ir_scancode_table ir_codes_rc5_hauppauge_new_table; | ||
136 | extern struct ir_scancode_table ir_codes_npgtech_table; | ||
137 | extern struct ir_scancode_table ir_codes_norwood_table; | ||
138 | extern struct ir_scancode_table ir_codes_proteus_2309_table; | ||
139 | extern struct ir_scancode_table ir_codes_budget_ci_old_table; | ||
140 | extern struct ir_scancode_table ir_codes_asus_pc39_table; | ||
141 | extern struct ir_scancode_table ir_codes_encore_enltv_table; | ||
142 | extern struct ir_scancode_table ir_codes_encore_enltv2_table; | ||
143 | extern struct ir_scancode_table ir_codes_tt_1500_table; | ||
144 | extern struct ir_scancode_table ir_codes_fusionhdtv_mce_table; | ||
145 | extern struct ir_scancode_table ir_codes_behold_table; | ||
146 | extern struct ir_scancode_table ir_codes_behold_columbus_table; | ||
147 | extern struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table; | ||
148 | extern struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table; | ||
149 | extern struct ir_scancode_table ir_codes_powercolor_real_angel_table; | ||
150 | extern struct ir_scancode_table ir_codes_avermedia_a16d_table; | ||
151 | extern struct ir_scancode_table ir_codes_encore_enltv_fm53_table; | ||
152 | extern struct ir_scancode_table ir_codes_real_audio_220_32_keys_table; | ||
153 | extern struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table; | ||
154 | extern struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table; | ||
155 | extern struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table; | ||
156 | extern struct ir_scancode_table ir_codes_kaiomy_table; | ||
157 | extern struct ir_scancode_table ir_codes_dm1105_nec_table; | ||
158 | extern struct ir_scancode_table ir_codes_tevii_nec_table; | ||
159 | extern struct ir_scancode_table ir_codes_tbs_nec_table; | ||
160 | extern struct ir_scancode_table ir_codes_evga_indtube_table; | ||
161 | extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table; | ||
162 | extern struct ir_scancode_table ir_codes_videomate_s350_table; | ||
163 | extern struct ir_scancode_table ir_codes_gadmei_rm008z_table; | ||
164 | extern struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table; | ||
165 | extern struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table; | ||
166 | extern struct ir_scancode_table ir_codes_kworld_315u_table; | ||
167 | #endif | 107 | #endif |
diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 61c223bc3953..ad1303f20e00 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Remote Controller core header | 2 | * Remote Controller core header |
3 | * | 3 | * |
4 | * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
5 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation version 2 of the License. | 8 | * the Free Software Foundation version 2 of the License. |
@@ -14,61 +16,133 @@ | |||
14 | #ifndef _IR_CORE | 16 | #ifndef _IR_CORE |
15 | #define _IR_CORE | 17 | #define _IR_CORE |
16 | 18 | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/kfifo.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/timer.h> | ||
23 | #include <media/rc-map.h> | ||
19 | 24 | ||
20 | extern int ir_core_debug; | 25 | extern int ir_core_debug; |
21 | #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ | 26 | #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ |
22 | printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) | 27 | printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) |
23 | 28 | ||
24 | #define IR_TYPE_UNKNOWN 0 | 29 | enum rc_driver_type { |
25 | #define IR_TYPE_RC5 (1 << 0) /* Philips RC5 protocol */ | 30 | RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */ |
26 | #define IR_TYPE_PD (1 << 1) /* Pulse distance encoded IR */ | 31 | RC_DRIVER_IR_RAW, /* Needs a Infra-Red pulse/space decoder */ |
27 | #define IR_TYPE_NEC (1 << 2) | ||
28 | #define IR_TYPE_OTHER (((u64)1) << 63l) | ||
29 | |||
30 | struct ir_scancode { | ||
31 | u16 scancode; | ||
32 | u32 keycode; | ||
33 | }; | ||
34 | |||
35 | struct ir_scancode_table { | ||
36 | struct ir_scancode *scan; | ||
37 | int size; | ||
38 | u64 ir_type; | ||
39 | spinlock_t lock; | ||
40 | }; | 32 | }; |
41 | 33 | ||
34 | /** | ||
35 | * struct ir_dev_props - Allow caller drivers to set special properties | ||
36 | * @driver_type: specifies if the driver or hardware have already a decoder, | ||
37 | * or if it needs to use the IR raw event decoders to produce a scancode | ||
38 | * @allowed_protos: bitmask with the supported IR_TYPE_* protocols | ||
39 | * @scanmask: some hardware decoders are not capable of providing the full | ||
40 | * scancode to the application. As this is a hardware limit, we can't do | ||
41 | * anything with it. Yet, as the same keycode table can be used with other | ||
42 | * devices, a mask is provided to allow its usage. Drivers should generally | ||
43 | * leave this field in blank | ||
44 | * @priv: driver-specific data, to be used on the callbacks | ||
45 | * @change_protocol: allow changing the protocol used on hardware decoders | ||
46 | * @open: callback to allow drivers to enable polling/irq when IR input device | ||
47 | * is opened. | ||
48 | * @close: callback to allow drivers to disable polling/irq when IR input device | ||
49 | * is opened. | ||
50 | */ | ||
42 | struct ir_dev_props { | 51 | struct ir_dev_props { |
43 | unsigned long allowed_protos; | 52 | enum rc_driver_type driver_type; |
44 | void *priv; | 53 | unsigned long allowed_protos; |
45 | int (*change_protocol)(void *priv, u64 ir_type); | 54 | u32 scanmask; |
55 | void *priv; | ||
56 | int (*change_protocol)(void *priv, u64 ir_type); | ||
57 | int (*open)(void *priv); | ||
58 | void (*close)(void *priv); | ||
46 | }; | 59 | }; |
47 | 60 | ||
48 | |||
49 | struct ir_input_dev { | 61 | struct ir_input_dev { |
50 | struct input_dev *dev; /* Input device*/ | 62 | struct device dev; /* device */ |
63 | char *driver_name; /* Name of the driver module */ | ||
51 | struct ir_scancode_table rc_tab; /* scan/key table */ | 64 | struct ir_scancode_table rc_tab; /* scan/key table */ |
52 | unsigned long devno; /* device number */ | 65 | unsigned long devno; /* device number */ |
53 | struct attribute_group attr; /* IR attributes */ | ||
54 | struct device *class_dev; /* virtual class dev */ | ||
55 | const struct ir_dev_props *props; /* Device properties */ | 66 | const struct ir_dev_props *props; /* Device properties */ |
67 | struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */ | ||
68 | struct input_dev *input_dev; /* the input device associated with this device */ | ||
69 | |||
70 | /* key info - needed by IR keycode handlers */ | ||
71 | spinlock_t keylock; /* protects the below members */ | ||
72 | bool keypressed; /* current state */ | ||
73 | unsigned long keyup_jiffies; /* when should the current keypress be released? */ | ||
74 | struct timer_list timer_keyup; /* timer for releasing a keypress */ | ||
75 | u32 last_keycode; /* keycode of last command */ | ||
76 | u32 last_scancode; /* scancode of last command */ | ||
77 | u8 last_toggle; /* toggle of last command */ | ||
56 | }; | 78 | }; |
57 | #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) | ||
58 | 79 | ||
59 | /* Routines from ir-keytable.c */ | 80 | enum raw_event_type { |
81 | IR_SPACE = (1 << 0), | ||
82 | IR_PULSE = (1 << 1), | ||
83 | IR_START_EVENT = (1 << 2), | ||
84 | IR_STOP_EVENT = (1 << 3), | ||
85 | }; | ||
60 | 86 | ||
61 | u32 ir_g_keycode_from_table(struct input_dev *input_dev, | 87 | #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) |
62 | u32 scancode); | ||
63 | 88 | ||
64 | int ir_input_register(struct input_dev *dev, | 89 | /* From ir-keytable.c */ |
90 | int __ir_input_register(struct input_dev *dev, | ||
65 | const struct ir_scancode_table *ir_codes, | 91 | const struct ir_scancode_table *ir_codes, |
66 | const struct ir_dev_props *props); | 92 | const struct ir_dev_props *props, |
93 | const char *driver_name); | ||
94 | |||
95 | static inline int ir_input_register(struct input_dev *dev, | ||
96 | const char *map_name, | ||
97 | const struct ir_dev_props *props, | ||
98 | const char *driver_name) { | ||
99 | struct ir_scancode_table *ir_codes; | ||
100 | struct ir_input_dev *ir_dev; | ||
101 | int rc; | ||
102 | |||
103 | if (!map_name) | ||
104 | return -EINVAL; | ||
105 | |||
106 | ir_codes = get_rc_map(map_name); | ||
107 | if (!ir_codes) | ||
108 | return -EINVAL; | ||
109 | |||
110 | rc = __ir_input_register(dev, ir_codes, props, driver_name); | ||
111 | if (rc < 0) | ||
112 | return -EINVAL; | ||
113 | |||
114 | ir_dev = input_get_drvdata(dev); | ||
115 | |||
116 | if (!rc && ir_dev->props && ir_dev->props->change_protocol) | ||
117 | rc = ir_dev->props->change_protocol(ir_dev->props->priv, | ||
118 | ir_codes->ir_type); | ||
119 | |||
120 | return rc; | ||
121 | } | ||
122 | |||
67 | void ir_input_unregister(struct input_dev *input_dev); | 123 | void ir_input_unregister(struct input_dev *input_dev); |
68 | 124 | ||
69 | /* Routines from ir-sysfs.c */ | 125 | void ir_repeat(struct input_dev *dev); |
126 | void ir_keydown(struct input_dev *dev, int scancode, u8 toggle); | ||
127 | u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); | ||
128 | |||
129 | /* From ir-raw-event.c */ | ||
130 | |||
131 | struct ir_raw_event { | ||
132 | unsigned pulse:1; | ||
133 | unsigned duration:31; | ||
134 | }; | ||
135 | |||
136 | #define IR_MAX_DURATION 0x7FFFFFFF /* a bit more than 2 seconds */ | ||
70 | 137 | ||
71 | int ir_register_class(struct input_dev *input_dev); | 138 | void ir_raw_event_handle(struct input_dev *input_dev); |
72 | void ir_unregister_class(struct input_dev *input_dev); | 139 | int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev); |
140 | int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type); | ||
141 | static inline void ir_raw_event_reset(struct input_dev *input_dev) | ||
142 | { | ||
143 | struct ir_raw_event ev = { .pulse = false, .duration = 0 }; | ||
144 | ir_raw_event_store(input_dev, &ev); | ||
145 | ir_raw_event_handle(input_dev); | ||
146 | } | ||
73 | 147 | ||
74 | #endif | 148 | #endif /* _IR_CORE */ |
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 9142936603cc..0506e45c9a4f 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h | |||
@@ -6,7 +6,7 @@ | |||
6 | struct IR_i2c; | 6 | struct IR_i2c; |
7 | 7 | ||
8 | struct IR_i2c { | 8 | struct IR_i2c { |
9 | struct ir_scancode_table *ir_codes; | 9 | char *ir_codes; |
10 | 10 | ||
11 | struct i2c_client *c; | 11 | struct i2c_client *c; |
12 | struct input_dev *input; | 12 | struct input_dev *input; |
@@ -34,9 +34,9 @@ enum ir_kbd_get_key_fn { | |||
34 | 34 | ||
35 | /* Can be passed when instantiating an ir_video i2c device */ | 35 | /* Can be passed when instantiating an ir_video i2c device */ |
36 | struct IR_i2c_init_data { | 36 | struct IR_i2c_init_data { |
37 | struct ir_scancode_table *ir_codes; | 37 | char *ir_codes; |
38 | const char *name; | 38 | const char *name; |
39 | u64 type; /* IR_TYPE_RC5, IR_TYPE_PD, etc */ | 39 | u64 type; /* IR_TYPE_RC5, etc */ |
40 | /* | 40 | /* |
41 | * Specify either a function pointer or a value indicating one of | 41 | * Specify either a function pointer or a value indicating one of |
42 | * ir_kbd_i2c's internal get_key functions | 42 | * ir_kbd_i2c's internal get_key functions |
diff --git a/include/media/rc-map.h b/include/media/rc-map.h new file mode 100644 index 000000000000..5833966a7100 --- /dev/null +++ b/include/media/rc-map.h | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * rc-map.h - define RC map names used by RC drivers | ||
3 | * | ||
4 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.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 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/input.h> | ||
13 | |||
14 | #define IR_TYPE_UNKNOWN 0 | ||
15 | #define IR_TYPE_RC5 (1 << 0) /* Philips RC5 protocol */ | ||
16 | #define IR_TYPE_NEC (1 << 1) | ||
17 | #define IR_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */ | ||
18 | #define IR_TYPE_JVC (1 << 3) /* JVC protocol */ | ||
19 | #define IR_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ | ||
20 | #define IR_TYPE_OTHER (1u << 31) | ||
21 | |||
22 | struct ir_scancode { | ||
23 | u32 scancode; | ||
24 | u32 keycode; | ||
25 | }; | ||
26 | |||
27 | struct ir_scancode_table { | ||
28 | struct ir_scancode *scan; | ||
29 | unsigned int size; /* Max number of entries */ | ||
30 | unsigned int len; /* Used number of entries */ | ||
31 | unsigned int alloc; /* Size of *scan in bytes */ | ||
32 | u64 ir_type; | ||
33 | char *name; | ||
34 | spinlock_t lock; | ||
35 | }; | ||
36 | |||
37 | struct rc_keymap { | ||
38 | struct list_head list; | ||
39 | struct ir_scancode_table map; | ||
40 | }; | ||
41 | |||
42 | /* Routines from rc-map.c */ | ||
43 | |||
44 | int ir_register_map(struct rc_keymap *map); | ||
45 | void ir_unregister_map(struct rc_keymap *map); | ||
46 | struct ir_scancode_table *get_rc_map(const char *name); | ||
47 | void rc_map_init(void); | ||
48 | |||
49 | /* Names of the several keytables defined in-kernel */ | ||
50 | |||
51 | #define RC_MAP_ADSTECH_DVB_T_PCI "rc-adstech-dvb-t-pci" | ||
52 | #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" | ||
53 | #define RC_MAP_ASUS_PC39 "rc-asus-pc39" | ||
54 | #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" | ||
55 | #define RC_MAP_AVERMEDIA_A16D "rc-avermedia-a16d" | ||
56 | #define RC_MAP_AVERMEDIA_CARDBUS "rc-avermedia-cardbus" | ||
57 | #define RC_MAP_AVERMEDIA_DVBT "rc-avermedia-dvbt" | ||
58 | #define RC_MAP_AVERMEDIA_M135A_RM_JX "rc-avermedia-m135a-rm-jx" | ||
59 | #define RC_MAP_AVERMEDIA "rc-avermedia" | ||
60 | #define RC_MAP_AVERTV_303 "rc-avertv-303" | ||
61 | #define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus" | ||
62 | #define RC_MAP_BEHOLD "rc-behold" | ||
63 | #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" | ||
64 | #define RC_MAP_CINERGY_1400 "rc-cinergy-1400" | ||
65 | #define RC_MAP_CINERGY "rc-cinergy" | ||
66 | #define RC_MAP_DM1105_NEC "rc-dm1105-nec" | ||
67 | #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro" | ||
68 | #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t" | ||
69 | #define RC_MAP_EMPTY "rc-empty" | ||
70 | #define RC_MAP_EM_TERRATEC "rc-em-terratec" | ||
71 | #define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2" | ||
72 | #define RC_MAP_ENCORE_ENLTV_FM53 "rc-encore-enltv-fm53" | ||
73 | #define RC_MAP_ENCORE_ENLTV "rc-encore-enltv" | ||
74 | #define RC_MAP_EVGA_INDTUBE "rc-evga-indtube" | ||
75 | #define RC_MAP_EZTV "rc-eztv" | ||
76 | #define RC_MAP_FLYDVB "rc-flydvb" | ||
77 | #define RC_MAP_FLYVIDEO "rc-flyvideo" | ||
78 | #define RC_MAP_FUSIONHDTV_MCE "rc-fusionhdtv-mce" | ||
79 | #define RC_MAP_GADMEI_RM008Z "rc-gadmei-rm008z" | ||
80 | #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" | ||
81 | #define RC_MAP_GOTVIEW7135 "rc-gotview7135" | ||
82 | #define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge-new" | ||
83 | #define RC_MAP_IMON_MCE "rc-imon-mce" | ||
84 | #define RC_MAP_IMON_PAD "rc-imon-pad" | ||
85 | #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" | ||
86 | #define RC_MAP_KAIOMY "rc-kaiomy" | ||
87 | #define RC_MAP_KWORLD_315U "rc-kworld-315u" | ||
88 | #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" | ||
89 | #define RC_MAP_MANLI "rc-manli" | ||
90 | #define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" | ||
91 | #define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere" | ||
92 | #define RC_MAP_NEBULA "rc-nebula" | ||
93 | #define RC_MAP_NEC_TERRATEC_CINERGY_XS "rc-nec-terratec-cinergy-xs" | ||
94 | #define RC_MAP_NORWOOD "rc-norwood" | ||
95 | #define RC_MAP_NPGTECH "rc-npgtech" | ||
96 | #define RC_MAP_PCTV_SEDNA "rc-pctv-sedna" | ||
97 | #define RC_MAP_PINNACLE_COLOR "rc-pinnacle-color" | ||
98 | #define RC_MAP_PINNACLE_GREY "rc-pinnacle-grey" | ||
99 | #define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" | ||
100 | #define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new" | ||
101 | #define RC_MAP_PIXELVIEW "rc-pixelview" | ||
102 | #define RC_MAP_PIXELVIEW_MK12 "rc-pixelview-mk12" | ||
103 | #define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel" | ||
104 | #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" | ||
105 | #define RC_MAP_PURPLETV "rc-purpletv" | ||
106 | #define RC_MAP_PV951 "rc-pv951" | ||
107 | #define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new" | ||
108 | #define RC_MAP_RC5_TV "rc-rc5-tv" | ||
109 | #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" | ||
110 | #define RC_MAP_TBS_NEC "rc-tbs-nec" | ||
111 | #define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" | ||
112 | #define RC_MAP_TEVII_NEC "rc-tevii-nec" | ||
113 | #define RC_MAP_TT_1500 "rc-tt-1500" | ||
114 | #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" | ||
115 | #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" | ||
116 | #define RC_MAP_WINFAST "rc-winfast" | ||
117 | #define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe" | ||
118 | /* | ||
119 | * Please, do not just append newer Remote Controller names at the end. | ||
120 | * The names should be ordered in alphabetical order | ||
121 | */ | ||
diff --git a/include/media/sh_vou.h b/include/media/sh_vou.h new file mode 100644 index 000000000000..a3ef30242b00 --- /dev/null +++ b/include/media/sh_vou.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * SuperH Video Output Unit (VOU) driver header | ||
3 | * | ||
4 | * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef SH_VOU_H | ||
11 | #define SH_VOU_H | ||
12 | |||
13 | #include <linux/i2c.h> | ||
14 | |||
15 | /* Bus flags */ | ||
16 | #define SH_VOU_PCLK_FALLING (1 << 0) | ||
17 | #define SH_VOU_HSYNC_LOW (1 << 1) | ||
18 | #define SH_VOU_VSYNC_LOW (1 << 2) | ||
19 | |||
20 | enum sh_vou_bus_fmt { | ||
21 | SH_VOU_BUS_8BIT, | ||
22 | SH_VOU_BUS_16BIT, | ||
23 | SH_VOU_BUS_BT656, | ||
24 | }; | ||
25 | |||
26 | struct sh_vou_pdata { | ||
27 | enum sh_vou_bus_fmt bus_fmt; | ||
28 | int i2c_adap; | ||
29 | struct i2c_board_info *board_info; | ||
30 | unsigned long flags; | ||
31 | char *module_name; | ||
32 | }; | ||
33 | |||
34 | #endif | ||
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 9d69f01b6fa2..c9a5bbfa6ab5 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -266,8 +266,8 @@ static inline unsigned long soc_camera_bus_param_compatible( | |||
266 | common_flags; | 266 | common_flags; |
267 | } | 267 | } |
268 | 268 | ||
269 | static inline void soc_camera_limit_side(unsigned int *start, | 269 | static inline void soc_camera_limit_side(int *start, int *length, |
270 | unsigned int *length, unsigned int start_min, | 270 | unsigned int start_min, |
271 | unsigned int length_min, unsigned int length_max) | 271 | unsigned int length_min, unsigned int length_max) |
272 | { | 272 | { |
273 | if (*length < length_min) | 273 | if (*length < length_min) |
@@ -284,4 +284,12 @@ static inline void soc_camera_limit_side(unsigned int *start, | |||
284 | extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, | 284 | extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, |
285 | unsigned long flags); | 285 | unsigned long flags); |
286 | 286 | ||
287 | /* This is only temporary here - until v4l2-subdev begins to link to video_device */ | ||
288 | #include <linux/i2c.h> | ||
289 | static inline struct video_device *soc_camera_i2c_to_vdev(struct i2c_client *client) | ||
290 | { | ||
291 | struct soc_camera_device *icd = client->dev.platform_data; | ||
292 | return icd->vdev; | ||
293 | } | ||
294 | |||
287 | #endif | 295 | #endif |
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 56abf21dd786..21b4428c12ab 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h | |||
@@ -25,6 +25,10 @@ | |||
25 | #define V4L2_CHIP_IDENT_H_ | 25 | #define V4L2_CHIP_IDENT_H_ |
26 | 26 | ||
27 | /* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ | 27 | /* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ |
28 | |||
29 | /* KEEP THIS LIST ORDERED BY ID! | ||
30 | Otherwise it will be hard to see which ranges are already in use when | ||
31 | adding support to a new chip family. */ | ||
28 | enum { | 32 | enum { |
29 | /* general idents: reserved range 0-49 */ | 33 | /* general idents: reserved range 0-49 */ |
30 | V4L2_IDENT_NONE = 0, /* No chip matched */ | 34 | V4L2_IDENT_NONE = 0, /* No chip matched */ |
@@ -77,17 +81,14 @@ enum { | |||
77 | V4L2_IDENT_CX23417 = 417, | 81 | V4L2_IDENT_CX23417 = 417, |
78 | V4L2_IDENT_CX23418 = 418, | 82 | V4L2_IDENT_CX23418 = 418, |
79 | 83 | ||
80 | /* module au0828 */ | ||
81 | V4L2_IDENT_AU0828 = 828, | ||
82 | |||
83 | /* module indycam: just ident 2000 */ | ||
84 | V4L2_IDENT_INDYCAM = 2000, | ||
85 | |||
86 | /* module bt819: reserved range 810-819 */ | 84 | /* module bt819: reserved range 810-819 */ |
87 | V4L2_IDENT_BT815A = 815, | 85 | V4L2_IDENT_BT815A = 815, |
88 | V4L2_IDENT_BT817A = 817, | 86 | V4L2_IDENT_BT817A = 817, |
89 | V4L2_IDENT_BT819A = 819, | 87 | V4L2_IDENT_BT819A = 819, |
90 | 88 | ||
89 | /* module au0828 */ | ||
90 | V4L2_IDENT_AU0828 = 828, | ||
91 | |||
91 | /* module bt856: just ident 856 */ | 92 | /* module bt856: just ident 856 */ |
92 | V4L2_IDENT_BT856 = 856, | 93 | V4L2_IDENT_BT856 = 856, |
93 | 94 | ||
@@ -99,6 +100,9 @@ enum { | |||
99 | V4L2_IDENT_KS0127 = 1127, | 100 | V4L2_IDENT_KS0127 = 1127, |
100 | V4L2_IDENT_KS0127B = 1128, | 101 | V4L2_IDENT_KS0127B = 1128, |
101 | 102 | ||
103 | /* module indycam: just ident 2000 */ | ||
104 | V4L2_IDENT_INDYCAM = 2000, | ||
105 | |||
102 | /* module vp27smpx: just ident 2700 */ | 106 | /* module vp27smpx: just ident 2700 */ |
103 | V4L2_IDENT_VP27SMPX = 2700, | 107 | V4L2_IDENT_VP27SMPX = 2700, |
104 | 108 | ||
@@ -162,20 +166,21 @@ enum { | |||
162 | /* module saa7706h: just ident 7706 */ | 166 | /* module saa7706h: just ident 7706 */ |
163 | V4L2_IDENT_SAA7706H = 7706, | 167 | V4L2_IDENT_SAA7706H = 7706, |
164 | 168 | ||
169 | /* module mt9v011, just ident 8243 */ | ||
170 | V4L2_IDENT_MT9V011 = 8243, | ||
171 | |||
165 | /* module wm8739: just ident 8739 */ | 172 | /* module wm8739: just ident 8739 */ |
166 | V4L2_IDENT_WM8739 = 8739, | 173 | V4L2_IDENT_WM8739 = 8739, |
167 | 174 | ||
168 | /* module wm8775: just ident 8775 */ | 175 | /* module wm8775: just ident 8775 */ |
169 | V4L2_IDENT_WM8775 = 8775, | 176 | V4L2_IDENT_WM8775 = 8775, |
170 | 177 | ||
171 | /* module tda9840: just ident 9840 */ | ||
172 | V4L2_IDENT_TDA9840 = 9840, | ||
173 | |||
174 | /* module cafe_ccic, just ident 8801 */ | 178 | /* module cafe_ccic, just ident 8801 */ |
175 | V4L2_IDENT_CAFE = 8801, | 179 | V4L2_IDENT_CAFE = 8801, |
176 | 180 | ||
177 | /* module mt9v011, just ident 8243 */ | 181 | /* AKM AK8813/AK8814 */ |
178 | V4L2_IDENT_MT9V011 = 8243, | 182 | V4L2_IDENT_AK8813 = 8813, |
183 | V4L2_IDENT_AK8814 = 8814, | ||
179 | 184 | ||
180 | /* module cx23885 and cx25840 */ | 185 | /* module cx23885 and cx25840 */ |
181 | V4L2_IDENT_CX23885 = 8850, | 186 | V4L2_IDENT_CX23885 = 8850, |
@@ -186,6 +191,9 @@ enum { | |||
186 | V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ | 191 | V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ |
187 | V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ | 192 | V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ |
188 | 193 | ||
194 | /* module tda9840: just ident 9840 */ | ||
195 | V4L2_IDENT_TDA9840 = 9840, | ||
196 | |||
189 | /* module tw9910: just ident 9910 */ | 197 | /* module tw9910: just ident 9910 */ |
190 | V4L2_IDENT_TW9910 = 9910, | 198 | V4L2_IDENT_TW9910 = 9910, |
191 | 199 | ||
@@ -198,72 +206,70 @@ enum { | |||
198 | V4L2_IDENT_CX23101 = 23101, | 206 | V4L2_IDENT_CX23101 = 23101, |
199 | V4L2_IDENT_CX23102 = 23102, | 207 | V4L2_IDENT_CX23102 = 23102, |
200 | 208 | ||
201 | /* module msp3400: reserved range 34000-34999 and 44000-44999 */ | 209 | /* module msp3400: reserved range 34000-34999 for msp34xx */ |
202 | V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only | 210 | V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only |
203 | use internally (tveeprom.c). */ | 211 | use internally (tveeprom.c). */ |
204 | 212 | ||
205 | V4L2_IDENT_MSP3400B = 34002, | 213 | V4L2_IDENT_MSP3400B = 34002, |
206 | V4L2_IDENT_MSP3410B = 34102, | ||
207 | |||
208 | V4L2_IDENT_MSP3400C = 34003, | 214 | V4L2_IDENT_MSP3400C = 34003, |
209 | V4L2_IDENT_MSP3410C = 34103, | ||
210 | |||
211 | V4L2_IDENT_MSP3400D = 34004, | 215 | V4L2_IDENT_MSP3400D = 34004, |
212 | V4L2_IDENT_MSP3410D = 34104, | 216 | V4L2_IDENT_MSP3400G = 34007, |
217 | V4L2_IDENT_MSP3401G = 34017, | ||
218 | V4L2_IDENT_MSP3402G = 34027, | ||
213 | V4L2_IDENT_MSP3405D = 34054, | 219 | V4L2_IDENT_MSP3405D = 34054, |
214 | V4L2_IDENT_MSP3415D = 34154, | 220 | V4L2_IDENT_MSP3405G = 34057, |
215 | V4L2_IDENT_MSP3407D = 34074, | 221 | V4L2_IDENT_MSP3407D = 34074, |
216 | V4L2_IDENT_MSP3417D = 34174, | 222 | V4L2_IDENT_MSP3407G = 34077, |
217 | 223 | ||
218 | V4L2_IDENT_MSP3400G = 34007, | 224 | V4L2_IDENT_MSP3410B = 34102, |
225 | V4L2_IDENT_MSP3410C = 34103, | ||
226 | V4L2_IDENT_MSP3410D = 34104, | ||
219 | V4L2_IDENT_MSP3410G = 34107, | 227 | V4L2_IDENT_MSP3410G = 34107, |
220 | V4L2_IDENT_MSP3420G = 34207, | ||
221 | V4L2_IDENT_MSP3430G = 34307, | ||
222 | V4L2_IDENT_MSP3440G = 34407, | ||
223 | V4L2_IDENT_MSP3450G = 34507, | ||
224 | V4L2_IDENT_MSP3460G = 34607, | ||
225 | |||
226 | V4L2_IDENT_MSP3401G = 34017, | ||
227 | V4L2_IDENT_MSP3411G = 34117, | 228 | V4L2_IDENT_MSP3411G = 34117, |
228 | V4L2_IDENT_MSP3421G = 34217, | ||
229 | V4L2_IDENT_MSP3431G = 34317, | ||
230 | V4L2_IDENT_MSP3441G = 34417, | ||
231 | V4L2_IDENT_MSP3451G = 34517, | ||
232 | V4L2_IDENT_MSP3461G = 34617, | ||
233 | |||
234 | V4L2_IDENT_MSP3402G = 34027, | ||
235 | V4L2_IDENT_MSP3412G = 34127, | 229 | V4L2_IDENT_MSP3412G = 34127, |
236 | V4L2_IDENT_MSP3422G = 34227, | 230 | V4L2_IDENT_MSP3415D = 34154, |
237 | V4L2_IDENT_MSP3442G = 34427, | ||
238 | V4L2_IDENT_MSP3452G = 34527, | ||
239 | |||
240 | V4L2_IDENT_MSP3405G = 34057, | ||
241 | V4L2_IDENT_MSP3415G = 34157, | 231 | V4L2_IDENT_MSP3415G = 34157, |
242 | V4L2_IDENT_MSP3425G = 34257, | 232 | V4L2_IDENT_MSP3417D = 34174, |
243 | V4L2_IDENT_MSP3435G = 34357, | ||
244 | V4L2_IDENT_MSP3445G = 34457, | ||
245 | V4L2_IDENT_MSP3455G = 34557, | ||
246 | V4L2_IDENT_MSP3465G = 34657, | ||
247 | |||
248 | V4L2_IDENT_MSP3407G = 34077, | ||
249 | V4L2_IDENT_MSP3417G = 34177, | 233 | V4L2_IDENT_MSP3417G = 34177, |
234 | |||
235 | V4L2_IDENT_MSP3420G = 34207, | ||
236 | V4L2_IDENT_MSP3421G = 34217, | ||
237 | V4L2_IDENT_MSP3422G = 34227, | ||
238 | V4L2_IDENT_MSP3425G = 34257, | ||
250 | V4L2_IDENT_MSP3427G = 34277, | 239 | V4L2_IDENT_MSP3427G = 34277, |
240 | |||
241 | V4L2_IDENT_MSP3430G = 34307, | ||
242 | V4L2_IDENT_MSP3431G = 34317, | ||
243 | V4L2_IDENT_MSP3435G = 34357, | ||
251 | V4L2_IDENT_MSP3437G = 34377, | 244 | V4L2_IDENT_MSP3437G = 34377, |
245 | |||
246 | V4L2_IDENT_MSP3440G = 34407, | ||
247 | V4L2_IDENT_MSP3441G = 34417, | ||
248 | V4L2_IDENT_MSP3442G = 34427, | ||
249 | V4L2_IDENT_MSP3445G = 34457, | ||
252 | V4L2_IDENT_MSP3447G = 34477, | 250 | V4L2_IDENT_MSP3447G = 34477, |
251 | |||
252 | V4L2_IDENT_MSP3450G = 34507, | ||
253 | V4L2_IDENT_MSP3451G = 34517, | ||
254 | V4L2_IDENT_MSP3452G = 34527, | ||
255 | V4L2_IDENT_MSP3455G = 34557, | ||
253 | V4L2_IDENT_MSP3457G = 34577, | 256 | V4L2_IDENT_MSP3457G = 34577, |
257 | |||
258 | V4L2_IDENT_MSP3460G = 34607, | ||
259 | V4L2_IDENT_MSP3461G = 34617, | ||
260 | V4L2_IDENT_MSP3465G = 34657, | ||
254 | V4L2_IDENT_MSP3467G = 34677, | 261 | V4L2_IDENT_MSP3467G = 34677, |
255 | 262 | ||
256 | /* module msp3400: reserved range 34000-34999 and 44000-44999 */ | 263 | /* module msp3400: reserved range 44000-44999 for msp44xx */ |
257 | V4L2_IDENT_MSP4400G = 44007, | 264 | V4L2_IDENT_MSP4400G = 44007, |
258 | V4L2_IDENT_MSP4410G = 44107, | ||
259 | V4L2_IDENT_MSP4420G = 44207, | ||
260 | V4L2_IDENT_MSP4440G = 44407, | ||
261 | V4L2_IDENT_MSP4450G = 44507, | ||
262 | |||
263 | V4L2_IDENT_MSP4408G = 44087, | 265 | V4L2_IDENT_MSP4408G = 44087, |
266 | V4L2_IDENT_MSP4410G = 44107, | ||
264 | V4L2_IDENT_MSP4418G = 44187, | 267 | V4L2_IDENT_MSP4418G = 44187, |
268 | V4L2_IDENT_MSP4420G = 44207, | ||
265 | V4L2_IDENT_MSP4428G = 44287, | 269 | V4L2_IDENT_MSP4428G = 44287, |
270 | V4L2_IDENT_MSP4440G = 44407, | ||
266 | V4L2_IDENT_MSP4448G = 44487, | 271 | V4L2_IDENT_MSP4448G = 44487, |
272 | V4L2_IDENT_MSP4450G = 44507, | ||
267 | V4L2_IDENT_MSP4458G = 44587, | 273 | V4L2_IDENT_MSP4458G = 44587, |
268 | 274 | ||
269 | /* Micron CMOS sensor chips: 45000-45099 */ | 275 | /* Micron CMOS sensor chips: 45000-45099 */ |
@@ -282,20 +288,27 @@ enum { | |||
282 | /* HV7131R CMOS sensor: just ident 46000 */ | 288 | /* HV7131R CMOS sensor: just ident 46000 */ |
283 | V4L2_IDENT_HV7131R = 46000, | 289 | V4L2_IDENT_HV7131R = 46000, |
284 | 290 | ||
291 | /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ | ||
292 | V4L2_IDENT_RJ54N1CB0C = 51980, | ||
293 | |||
294 | /* module m52790: just ident 52790 */ | ||
295 | V4L2_IDENT_M52790 = 52790, | ||
296 | |||
285 | /* module cs53132a: just ident 53132 */ | 297 | /* module cs53132a: just ident 53132 */ |
286 | V4L2_IDENT_CS53l32A = 53132, | 298 | V4L2_IDENT_CS53l32A = 53132, |
287 | 299 | ||
300 | /* modules upd61151 MPEG2 encoder: just ident 54000 */ | ||
301 | V4L2_IDENT_UPD61161 = 54000, | ||
302 | /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */ | ||
303 | V4L2_IDENT_UPD61162 = 54001, | ||
304 | |||
288 | /* module upd64031a: just ident 64031 */ | 305 | /* module upd64031a: just ident 64031 */ |
289 | V4L2_IDENT_UPD64031A = 64031, | 306 | V4L2_IDENT_UPD64031A = 64031, |
290 | 307 | ||
291 | /* module upd64083: just ident 64083 */ | 308 | /* module upd64083: just ident 64083 */ |
292 | V4L2_IDENT_UPD64083 = 64083, | 309 | V4L2_IDENT_UPD64083 = 64083, |
293 | 310 | ||
294 | /* module m52790: just ident 52790 */ | 311 | /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */ |
295 | V4L2_IDENT_M52790 = 52790, | ||
296 | |||
297 | /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ | ||
298 | V4L2_IDENT_RJ54N1CB0C = 51980, | ||
299 | }; | 312 | }; |
300 | 313 | ||
301 | #endif | 314 | #endif |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1c7b259f341c..98b32645e5a7 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
@@ -85,13 +85,13 @@ | |||
85 | struct v4l2_prio_state { | 85 | struct v4l2_prio_state { |
86 | atomic_t prios[4]; | 86 | atomic_t prios[4]; |
87 | }; | 87 | }; |
88 | int v4l2_prio_init(struct v4l2_prio_state *global); | 88 | void v4l2_prio_init(struct v4l2_prio_state *global); |
89 | int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, | 89 | int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, |
90 | enum v4l2_priority new); | 90 | enum v4l2_priority new); |
91 | int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); | 91 | void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); |
92 | int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local); | 92 | void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local); |
93 | enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); | 93 | enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); |
94 | int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); | 94 | int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local); |
95 | 95 | ||
96 | /* ------------------------------------------------------------------------- */ | 96 | /* ------------------------------------------------------------------------- */ |
97 | 97 | ||
@@ -184,6 +184,25 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type); | |||
184 | 184 | ||
185 | /* ------------------------------------------------------------------------- */ | 185 | /* ------------------------------------------------------------------------- */ |
186 | 186 | ||
187 | /* SPI Helper functions */ | ||
188 | #if defined(CONFIG_SPI) | ||
189 | |||
190 | #include <linux/spi/spi.h> | ||
191 | |||
192 | struct spi_device; | ||
193 | |||
194 | /* Load an spi module and return an initialized v4l2_subdev struct. | ||
195 | The client_type argument is the name of the chip that's on the adapter. */ | ||
196 | struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, | ||
197 | struct spi_master *master, struct spi_board_info *info); | ||
198 | |||
199 | /* Initialize an v4l2_subdev with data from an spi_device struct */ | ||
200 | void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, | ||
201 | const struct v4l2_subdev_ops *ops); | ||
202 | #endif | ||
203 | |||
204 | /* ------------------------------------------------------------------------- */ | ||
205 | |||
187 | /* Note: these remaining ioctls/structs should be removed as well, but they are | 206 | /* Note: these remaining ioctls/structs should be removed as well, but they are |
188 | still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and | 207 | still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and |
189 | v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup | 208 | v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup |
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2dee93892ea2..bebe44b03e0f 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h | |||
@@ -32,6 +32,7 @@ struct v4l2_device; | |||
32 | Drivers can clear this flag if they want to block all future | 32 | Drivers can clear this flag if they want to block all future |
33 | device access. It is cleared by video_unregister_device. */ | 33 | device access. It is cleared by video_unregister_device. */ |
34 | #define V4L2_FL_REGISTERED (0) | 34 | #define V4L2_FL_REGISTERED (0) |
35 | #define V4L2_FL_USES_V4L2_FH (1) | ||
35 | 36 | ||
36 | struct v4l2_file_operations { | 37 | struct v4l2_file_operations { |
37 | struct module *owner; | 38 | struct module *owner; |
@@ -77,6 +78,10 @@ struct video_device | |||
77 | /* attribute to differentiate multiple indices on one physical device */ | 78 | /* attribute to differentiate multiple indices on one physical device */ |
78 | int index; | 79 | int index; |
79 | 80 | ||
81 | /* V4L2 file handles */ | ||
82 | spinlock_t fh_lock; /* Lock for all v4l2_fhs */ | ||
83 | struct list_head fh_list; /* List of struct v4l2_fh */ | ||
84 | |||
80 | int debug; /* Activates debug level*/ | 85 | int debug; /* Activates debug level*/ |
81 | 86 | ||
82 | /* Video standard vars */ | 87 | /* Video standard vars */ |
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h new file mode 100644 index 000000000000..3b86177c8cd2 --- /dev/null +++ b/include/media/v4l2-event.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * v4l2-event.h | ||
3 | * | ||
4 | * V4L2 events. | ||
5 | * | ||
6 | * Copyright (C) 2009--2010 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #ifndef V4L2_EVENT_H | ||
26 | #define V4L2_EVENT_H | ||
27 | |||
28 | #include <linux/types.h> | ||
29 | #include <linux/videodev2.h> | ||
30 | #include <linux/wait.h> | ||
31 | |||
32 | struct v4l2_fh; | ||
33 | struct video_device; | ||
34 | |||
35 | struct v4l2_kevent { | ||
36 | struct list_head list; | ||
37 | struct v4l2_event event; | ||
38 | }; | ||
39 | |||
40 | struct v4l2_subscribed_event { | ||
41 | struct list_head list; | ||
42 | u32 type; | ||
43 | }; | ||
44 | |||
45 | struct v4l2_events { | ||
46 | wait_queue_head_t wait; | ||
47 | struct list_head subscribed; /* Subscribed events */ | ||
48 | struct list_head free; /* Events ready for use */ | ||
49 | struct list_head available; /* Dequeueable event */ | ||
50 | unsigned int navailable; | ||
51 | unsigned int nallocated; /* Number of allocated events */ | ||
52 | u32 sequence; | ||
53 | }; | ||
54 | |||
55 | int v4l2_event_init(struct v4l2_fh *fh); | ||
56 | int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n); | ||
57 | void v4l2_event_free(struct v4l2_fh *fh); | ||
58 | int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, | ||
59 | int nonblocking); | ||
60 | void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev); | ||
61 | int v4l2_event_pending(struct v4l2_fh *fh); | ||
62 | int v4l2_event_subscribe(struct v4l2_fh *fh, | ||
63 | struct v4l2_event_subscription *sub); | ||
64 | int v4l2_event_unsubscribe(struct v4l2_fh *fh, | ||
65 | struct v4l2_event_subscription *sub); | ||
66 | |||
67 | #endif /* V4L2_EVENT_H */ | ||
diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h new file mode 100644 index 000000000000..1d72dde320bf --- /dev/null +++ b/include/media/v4l2-fh.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * v4l2-fh.h | ||
3 | * | ||
4 | * V4L2 file handle. Store per file handle data for the V4L2 | ||
5 | * framework. Using file handles is optional for the drivers. | ||
6 | * | ||
7 | * Copyright (C) 2009--2010 Nokia Corporation. | ||
8 | * | ||
9 | * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #ifndef V4L2_FH_H | ||
27 | #define V4L2_FH_H | ||
28 | |||
29 | #include <linux/list.h> | ||
30 | |||
31 | struct video_device; | ||
32 | struct v4l2_events; | ||
33 | |||
34 | struct v4l2_fh { | ||
35 | struct list_head list; | ||
36 | struct video_device *vdev; | ||
37 | struct v4l2_events *events; /* events, pending and subscribed */ | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Initialise the file handle. Parts of the V4L2 framework using the | ||
42 | * file handles should be initialised in this function. Must be called | ||
43 | * from driver's v4l2_file_operations->open() handler if the driver | ||
44 | * uses v4l2_fh. | ||
45 | */ | ||
46 | int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev); | ||
47 | /* | ||
48 | * Add the fh to the list of file handles on a video_device. The file | ||
49 | * handle must be initialised first. | ||
50 | */ | ||
51 | void v4l2_fh_add(struct v4l2_fh *fh); | ||
52 | /* | ||
53 | * Remove file handle from the list of file handles. Must be called in | ||
54 | * v4l2_file_operations->release() handler if the driver uses v4l2_fh. | ||
55 | */ | ||
56 | void v4l2_fh_del(struct v4l2_fh *fh); | ||
57 | /* | ||
58 | * Release resources related to a file handle. Parts of the V4L2 | ||
59 | * framework using the v4l2_fh must release their resources here, too. | ||
60 | * Must be called in v4l2_file_operations->release() handler if the | ||
61 | * driver uses v4l2_fh. | ||
62 | */ | ||
63 | void v4l2_fh_exit(struct v4l2_fh *fh); | ||
64 | |||
65 | #endif /* V4L2_EVENT_H */ | ||
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index e8ba0f2efbae..06daa6e8e051 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/videodev2.h> | 21 | #include <linux/videodev2.h> |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | struct v4l2_fh; | ||
25 | |||
24 | struct v4l2_ioctl_ops { | 26 | struct v4l2_ioctl_ops { |
25 | /* ioctl callbacks */ | 27 | /* ioctl callbacks */ |
26 | 28 | ||
@@ -254,6 +256,11 @@ struct v4l2_ioctl_ops { | |||
254 | int (*vidioc_g_dv_timings) (struct file *file, void *fh, | 256 | int (*vidioc_g_dv_timings) (struct file *file, void *fh, |
255 | struct v4l2_dv_timings *timings); | 257 | struct v4l2_dv_timings *timings); |
256 | 258 | ||
259 | int (*vidioc_subscribe_event) (struct v4l2_fh *fh, | ||
260 | struct v4l2_event_subscription *sub); | ||
261 | int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh, | ||
262 | struct v4l2_event_subscription *sub); | ||
263 | |||
257 | /* For other private ioctls */ | 264 | /* For other private ioctls */ |
258 | long (*vidioc_default) (struct file *file, void *fh, | 265 | long (*vidioc_default) (struct file *file, void *fh, |
259 | int cmd, void *arg); | 266 | int cmd, void *arg); |
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h new file mode 100644 index 000000000000..8d149f1c58d0 --- /dev/null +++ b/include/media/v4l2-mem2mem.h | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Memory-to-memory device framework for Video for Linux 2. | ||
3 | * | ||
4 | * Helper functions for devices that use memory buffers for both source | ||
5 | * and destination. | ||
6 | * | ||
7 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Pawel Osciak, <p.osciak@samsung.com> | ||
9 | * Marek Szyprowski, <m.szyprowski@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the | ||
14 | * License, or (at your option) any later version | ||
15 | */ | ||
16 | |||
17 | #ifndef _MEDIA_V4L2_MEM2MEM_H | ||
18 | #define _MEDIA_V4L2_MEM2MEM_H | ||
19 | |||
20 | #include <media/videobuf-core.h> | ||
21 | |||
22 | /** | ||
23 | * struct v4l2_m2m_ops - mem-to-mem device driver callbacks | ||
24 | * @device_run: required. Begin the actual job (transaction) inside this | ||
25 | * callback. | ||
26 | * The job does NOT have to end before this callback returns | ||
27 | * (and it will be the usual case). When the job finishes, | ||
28 | * v4l2_m2m_job_finish() has to be called. | ||
29 | * @job_ready: optional. Should return 0 if the driver does not have a job | ||
30 | * fully prepared to run yet (i.e. it will not be able to finish a | ||
31 | * transaction without sleeping). If not provided, it will be | ||
32 | * assumed that one source and one destination buffer are all | ||
33 | * that is required for the driver to perform one full transaction. | ||
34 | * This method may not sleep. | ||
35 | * @job_abort: required. Informs the driver that it has to abort the currently | ||
36 | * running transaction as soon as possible (i.e. as soon as it can | ||
37 | * stop the device safely; e.g. in the next interrupt handler), | ||
38 | * even if the transaction would not have been finished by then. | ||
39 | * After the driver performs the necessary steps, it has to call | ||
40 | * v4l2_m2m_job_finish() (as if the transaction ended normally). | ||
41 | * This function does not have to (and will usually not) wait | ||
42 | * until the device enters a state when it can be stopped. | ||
43 | */ | ||
44 | struct v4l2_m2m_ops { | ||
45 | void (*device_run)(void *priv); | ||
46 | int (*job_ready)(void *priv); | ||
47 | void (*job_abort)(void *priv); | ||
48 | }; | ||
49 | |||
50 | struct v4l2_m2m_dev; | ||
51 | |||
52 | struct v4l2_m2m_queue_ctx { | ||
53 | /* private: internal use only */ | ||
54 | struct videobuf_queue q; | ||
55 | |||
56 | /* Queue for buffers ready to be processed as soon as this | ||
57 | * instance receives access to the device */ | ||
58 | struct list_head rdy_queue; | ||
59 | u8 num_rdy; | ||
60 | }; | ||
61 | |||
62 | struct v4l2_m2m_ctx { | ||
63 | /* private: internal use only */ | ||
64 | struct v4l2_m2m_dev *m2m_dev; | ||
65 | |||
66 | /* Capture (output to memory) queue context */ | ||
67 | struct v4l2_m2m_queue_ctx cap_q_ctx; | ||
68 | |||
69 | /* Output (input from memory) queue context */ | ||
70 | struct v4l2_m2m_queue_ctx out_q_ctx; | ||
71 | |||
72 | /* For device job queue */ | ||
73 | struct list_head queue; | ||
74 | unsigned long job_flags; | ||
75 | |||
76 | /* Instance private data */ | ||
77 | void *priv; | ||
78 | }; | ||
79 | |||
80 | void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev); | ||
81 | |||
82 | struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, | ||
83 | enum v4l2_buf_type type); | ||
84 | |||
85 | void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||
86 | struct v4l2_m2m_ctx *m2m_ctx); | ||
87 | |||
88 | int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
89 | struct v4l2_requestbuffers *reqbufs); | ||
90 | |||
91 | int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
92 | struct v4l2_buffer *buf); | ||
93 | |||
94 | int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
95 | struct v4l2_buffer *buf); | ||
96 | int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
97 | struct v4l2_buffer *buf); | ||
98 | |||
99 | int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
100 | enum v4l2_buf_type type); | ||
101 | int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
102 | enum v4l2_buf_type type); | ||
103 | |||
104 | unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
105 | struct poll_table_struct *wait); | ||
106 | |||
107 | int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||
108 | struct vm_area_struct *vma); | ||
109 | |||
110 | struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops); | ||
111 | void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev); | ||
112 | |||
113 | struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, | ||
114 | void (*vq_init)(void *priv, struct videobuf_queue *, | ||
115 | enum v4l2_buf_type)); | ||
116 | void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx); | ||
117 | |||
118 | void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, | ||
119 | struct videobuf_buffer *vb); | ||
120 | |||
121 | /** | ||
122 | * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for | ||
123 | * use | ||
124 | */ | ||
125 | static inline | ||
126 | unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) | ||
127 | { | ||
128 | return m2m_ctx->cap_q_ctx.num_rdy; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * v4l2_m2m_num_src_bufs_ready() - return the number of destination buffers | ||
133 | * ready for use | ||
134 | */ | ||
135 | static inline | ||
136 | unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) | ||
137 | { | ||
138 | return m2m_ctx->out_q_ctx.num_rdy; | ||
139 | } | ||
140 | |||
141 | void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type); | ||
142 | |||
143 | /** | ||
144 | * v4l2_m2m_next_src_buf() - return next source buffer from the list of ready | ||
145 | * buffers | ||
146 | */ | ||
147 | static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx) | ||
148 | { | ||
149 | return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * v4l2_m2m_next_dst_buf() - return next destination buffer from the list of | ||
154 | * ready buffers | ||
155 | */ | ||
156 | static inline void *v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx) | ||
157 | { | ||
158 | return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * v4l2_m2m_get_src_vq() - return videobuf_queue for source buffers | ||
163 | */ | ||
164 | static inline | ||
165 | struct videobuf_queue *v4l2_m2m_get_src_vq(struct v4l2_m2m_ctx *m2m_ctx) | ||
166 | { | ||
167 | return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * v4l2_m2m_get_dst_vq() - return videobuf_queue for destination buffers | ||
172 | */ | ||
173 | static inline | ||
174 | struct videobuf_queue *v4l2_m2m_get_dst_vq(struct v4l2_m2m_ctx *m2m_ctx) | ||
175 | { | ||
176 | return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
177 | } | ||
178 | |||
179 | void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, | ||
180 | enum v4l2_buf_type type); | ||
181 | |||
182 | /** | ||
183 | * v4l2_m2m_src_buf_remove() - take off a source buffer from the list of ready | ||
184 | * buffers and return it | ||
185 | */ | ||
186 | static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) | ||
187 | { | ||
188 | return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * v4l2_m2m_dst_buf_remove() - take off a destination buffer from the list of | ||
193 | * ready buffers and return it | ||
194 | */ | ||
195 | static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) | ||
196 | { | ||
197 | return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
198 | } | ||
199 | |||
200 | #endif /* _MEDIA_V4L2_MEM2MEM_H */ | ||
201 | |||
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 2bcdca0a57fc..a88889355ae0 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h | |||
@@ -184,28 +184,6 @@ struct v4l2_subdev_audio_ops { | |||
184 | }; | 184 | }; |
185 | 185 | ||
186 | /* | 186 | /* |
187 | decode_vbi_line: video decoders that support sliced VBI need to implement | ||
188 | this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the | ||
189 | start of the VBI data that was generated by the decoder. The driver | ||
190 | then parses the sliced VBI data and sets the other fields in the | ||
191 | struct accordingly. The pointer p is updated to point to the start of | ||
192 | the payload which can be copied verbatim into the data field of the | ||
193 | v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the | ||
194 | type field is set to 0 on return. | ||
195 | |||
196 | s_vbi_data: used to generate VBI signals on a video signal. | ||
197 | v4l2_sliced_vbi_data is filled with the data packets that should be | ||
198 | output. Note that if you set the line field to 0, then that VBI signal | ||
199 | is disabled. If no valid VBI data was found, then the type field is | ||
200 | set to 0 on return. | ||
201 | |||
202 | g_vbi_data: used to obtain the sliced VBI packet from a readback register. | ||
203 | Not all video decoders support this. If no data is available because | ||
204 | the readback register contains invalid or erroneous data -EIO is | ||
205 | returned. Note that you must fill in the 'id' member and the 'field' | ||
206 | member (to determine whether CC data from the first or second field | ||
207 | should be obtained). | ||
208 | |||
209 | s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by | 187 | s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by |
210 | video input devices. | 188 | video input devices. |
211 | 189 | ||
@@ -243,10 +221,6 @@ struct v4l2_subdev_audio_ops { | |||
243 | struct v4l2_subdev_video_ops { | 221 | struct v4l2_subdev_video_ops { |
244 | int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); | 222 | int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); |
245 | int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags); | 223 | int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags); |
246 | int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); | ||
247 | int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); | ||
248 | int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); | ||
249 | int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); | ||
250 | int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); | 224 | int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); |
251 | int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); | 225 | int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); |
252 | int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); | 226 | int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); |
@@ -262,6 +236,8 @@ struct v4l2_subdev_video_ops { | |||
262 | int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); | 236 | int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); |
263 | int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); | 237 | int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); |
264 | int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); | 238 | int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); |
239 | int (*enum_dv_presets) (struct v4l2_subdev *sd, | ||
240 | struct v4l2_dv_enum_preset *preset); | ||
265 | int (*s_dv_preset)(struct v4l2_subdev *sd, | 241 | int (*s_dv_preset)(struct v4l2_subdev *sd, |
266 | struct v4l2_dv_preset *preset); | 242 | struct v4l2_dv_preset *preset); |
267 | int (*query_dv_preset)(struct v4l2_subdev *sd, | 243 | int (*query_dv_preset)(struct v4l2_subdev *sd, |
@@ -280,6 +256,45 @@ struct v4l2_subdev_video_ops { | |||
280 | struct v4l2_mbus_framefmt *fmt); | 256 | struct v4l2_mbus_framefmt *fmt); |
281 | }; | 257 | }; |
282 | 258 | ||
259 | /* | ||
260 | decode_vbi_line: video decoders that support sliced VBI need to implement | ||
261 | this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the | ||
262 | start of the VBI data that was generated by the decoder. The driver | ||
263 | then parses the sliced VBI data and sets the other fields in the | ||
264 | struct accordingly. The pointer p is updated to point to the start of | ||
265 | the payload which can be copied verbatim into the data field of the | ||
266 | v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the | ||
267 | type field is set to 0 on return. | ||
268 | |||
269 | s_vbi_data: used to generate VBI signals on a video signal. | ||
270 | v4l2_sliced_vbi_data is filled with the data packets that should be | ||
271 | output. Note that if you set the line field to 0, then that VBI signal | ||
272 | is disabled. If no valid VBI data was found, then the type field is | ||
273 | set to 0 on return. | ||
274 | |||
275 | g_vbi_data: used to obtain the sliced VBI packet from a readback register. | ||
276 | Not all video decoders support this. If no data is available because | ||
277 | the readback register contains invalid or erroneous data -EIO is | ||
278 | returned. Note that you must fill in the 'id' member and the 'field' | ||
279 | member (to determine whether CC data from the first or second field | ||
280 | should be obtained). | ||
281 | |||
282 | s_raw_fmt: setup the video encoder/decoder for raw VBI. | ||
283 | |||
284 | g_sliced_fmt: retrieve the current sliced VBI settings. | ||
285 | |||
286 | s_sliced_fmt: setup the sliced VBI settings. | ||
287 | */ | ||
288 | struct v4l2_subdev_vbi_ops { | ||
289 | int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); | ||
290 | int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); | ||
291 | int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); | ||
292 | int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); | ||
293 | int (*s_raw_fmt)(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); | ||
294 | int (*g_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); | ||
295 | int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); | ||
296 | }; | ||
297 | |||
283 | /** | 298 | /** |
284 | * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations | 299 | * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations |
285 | * @g_skip_top_lines: number of lines at the top of the image to be skipped. | 300 | * @g_skip_top_lines: number of lines at the top of the image to be skipped. |
@@ -379,6 +394,7 @@ struct v4l2_subdev_ops { | |||
379 | const struct v4l2_subdev_tuner_ops *tuner; | 394 | const struct v4l2_subdev_tuner_ops *tuner; |
380 | const struct v4l2_subdev_audio_ops *audio; | 395 | const struct v4l2_subdev_audio_ops *audio; |
381 | const struct v4l2_subdev_video_ops *video; | 396 | const struct v4l2_subdev_video_ops *video; |
397 | const struct v4l2_subdev_vbi_ops *vbi; | ||
382 | const struct v4l2_subdev_ir_ops *ir; | 398 | const struct v4l2_subdev_ir_ops *ir; |
383 | const struct v4l2_subdev_sensor_ops *sensor; | 399 | const struct v4l2_subdev_sensor_ops *sensor; |
384 | }; | 400 | }; |
@@ -387,6 +403,8 @@ struct v4l2_subdev_ops { | |||
387 | 403 | ||
388 | /* Set this flag if this subdev is a i2c device. */ | 404 | /* Set this flag if this subdev is a i2c device. */ |
389 | #define V4L2_SUBDEV_FL_IS_I2C (1U << 0) | 405 | #define V4L2_SUBDEV_FL_IS_I2C (1U << 0) |
406 | /* Set this flag if this subdev is a spi device. */ | ||
407 | #define V4L2_SUBDEV_FL_IS_SPI (1U << 1) | ||
390 | 408 | ||
391 | /* Each instance of a subdev driver should create this struct, either | 409 | /* Each instance of a subdev driver should create this struct, either |
392 | stand-alone or embedded in a larger struct. | 410 | stand-alone or embedded in a larger struct. |
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 316fdccdcaa0..f91a736c133d 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h | |||
@@ -127,30 +127,16 @@ struct videobuf_queue_ops { | |||
127 | struct videobuf_qtype_ops { | 127 | struct videobuf_qtype_ops { |
128 | u32 magic; | 128 | u32 magic; |
129 | 129 | ||
130 | void *(*alloc) (size_t size); | 130 | struct videobuf_buffer *(*alloc)(size_t size); |
131 | void *(*vmalloc) (struct videobuf_buffer *buf); | 131 | void *(*vaddr) (struct videobuf_buffer *buf); |
132 | int (*iolock) (struct videobuf_queue* q, | 132 | int (*iolock) (struct videobuf_queue *q, |
133 | struct videobuf_buffer *vb, | 133 | struct videobuf_buffer *vb, |
134 | struct v4l2_framebuffer *fbuf); | 134 | struct v4l2_framebuffer *fbuf); |
135 | int (*mmap) (struct videobuf_queue *q, | 135 | int (*sync) (struct videobuf_queue *q, |
136 | unsigned int *count, | ||
137 | unsigned int *size, | ||
138 | enum v4l2_memory memory); | ||
139 | int (*sync) (struct videobuf_queue* q, | ||
140 | struct videobuf_buffer *buf); | 136 | struct videobuf_buffer *buf); |
141 | int (*video_copy_to_user)(struct videobuf_queue *q, | ||
142 | char __user *data, | ||
143 | size_t count, | ||
144 | int nonblocking); | ||
145 | int (*copy_stream) (struct videobuf_queue *q, | ||
146 | char __user *data, | ||
147 | size_t count, | ||
148 | size_t pos, | ||
149 | int vbihack, | ||
150 | int nonblocking); | ||
151 | int (*mmap_free) (struct videobuf_queue *q); | ||
152 | int (*mmap_mapper) (struct videobuf_queue *q, | 137 | int (*mmap_mapper) (struct videobuf_queue *q, |
153 | struct vm_area_struct *vma); | 138 | struct videobuf_buffer *buf, |
139 | struct vm_area_struct *vma); | ||
154 | }; | 140 | }; |
155 | 141 | ||
156 | struct videobuf_queue { | 142 | struct videobuf_queue { |
@@ -171,7 +157,6 @@ struct videobuf_queue { | |||
171 | 157 | ||
172 | unsigned int streaming:1; | 158 | unsigned int streaming:1; |
173 | unsigned int reading:1; | 159 | unsigned int reading:1; |
174 | unsigned int is_mmapped:1; | ||
175 | 160 | ||
176 | /* capture via mmap() + ioctl(QBUF/DQBUF) */ | 161 | /* capture via mmap() + ioctl(QBUF/DQBUF) */ |
177 | struct list_head stream; | 162 | struct list_head stream; |
@@ -185,14 +170,14 @@ struct videobuf_queue { | |||
185 | }; | 170 | }; |
186 | 171 | ||
187 | int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); | 172 | int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); |
188 | int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, | 173 | int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, |
189 | struct v4l2_framebuffer *fbuf); | 174 | struct v4l2_framebuffer *fbuf); |
190 | 175 | ||
191 | void *videobuf_alloc(struct videobuf_queue* q); | 176 | struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q); |
192 | 177 | ||
193 | /* Used on videobuf-dvb */ | 178 | /* Used on videobuf-dvb */ |
194 | void *videobuf_queue_to_vmalloc (struct videobuf_queue* q, | 179 | void *videobuf_queue_to_vaddr(struct videobuf_queue *q, |
195 | struct videobuf_buffer *buf); | 180 | struct videobuf_buffer *buf); |
196 | 181 | ||
197 | void videobuf_queue_core_init(struct videobuf_queue *q, | 182 | void videobuf_queue_core_init(struct videobuf_queue *q, |
198 | const struct videobuf_queue_ops *ops, | 183 | const struct videobuf_queue_ops *ops, |
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 53e72f787175..a195f3b9c00a 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h | |||
@@ -17,6 +17,8 @@ | |||
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
18 | * the Free Software Foundation; either version 2 | 18 | * the Free Software Foundation; either version 2 |
19 | */ | 19 | */ |
20 | #ifndef _VIDEOBUF_DMA_SG_H | ||
21 | #define _VIDEOBUF_DMA_SG_H | ||
20 | 22 | ||
21 | #include <media/videobuf-core.h> | 23 | #include <media/videobuf-core.h> |
22 | 24 | ||
@@ -27,14 +29,14 @@ | |||
27 | * block (NULL on errors). Memory for the scatterlist is allocated | 29 | * block (NULL on errors). Memory for the scatterlist is allocated |
28 | * using kmalloc. The caller must free the memory. | 30 | * using kmalloc. The caller must free the memory. |
29 | */ | 31 | */ |
30 | struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); | 32 | struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); |
31 | 33 | ||
32 | /* | 34 | /* |
33 | * Return a scatterlist for a an array of userpages (NULL on errors). | 35 | * Return a scatterlist for a an array of userpages (NULL on errors). |
34 | * Memory for the scatterlist is allocated using kmalloc. The caller | 36 | * Memory for the scatterlist is allocated using kmalloc. The caller |
35 | * must free the memory. | 37 | * must free the memory. |
36 | */ | 38 | */ |
37 | struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, | 39 | struct scatterlist *videobuf_pages_to_sg(struct page **pages, int nr_pages, |
38 | int offset); | 40 | int offset); |
39 | 41 | ||
40 | /* --------------------------------------------------------------------- */ | 42 | /* --------------------------------------------------------------------- */ |
@@ -78,8 +80,7 @@ struct videobuf_dmabuf { | |||
78 | int direction; | 80 | int direction; |
79 | }; | 81 | }; |
80 | 82 | ||
81 | struct videobuf_dma_sg_memory | 83 | struct videobuf_dma_sg_memory { |
82 | { | ||
83 | u32 magic; | 84 | u32 magic; |
84 | 85 | ||
85 | /* for mmap'ed buffers */ | 86 | /* for mmap'ed buffers */ |
@@ -95,14 +96,13 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | |||
95 | dma_addr_t addr, int nr_pages); | 96 | dma_addr_t addr, int nr_pages); |
96 | int videobuf_dma_free(struct videobuf_dmabuf *dma); | 97 | int videobuf_dma_free(struct videobuf_dmabuf *dma); |
97 | 98 | ||
98 | int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | 99 | int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma); |
99 | int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | 100 | int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma); |
100 | int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); | 101 | struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); |
101 | struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); | ||
102 | 102 | ||
103 | void *videobuf_sg_alloc(size_t size); | 103 | void *videobuf_sg_alloc(size_t size); |
104 | 104 | ||
105 | void videobuf_queue_sg_init(struct videobuf_queue* q, | 105 | void videobuf_queue_sg_init(struct videobuf_queue *q, |
106 | const struct videobuf_queue_ops *ops, | 106 | const struct videobuf_queue_ops *ops, |
107 | struct device *dev, | 107 | struct device *dev, |
108 | spinlock_t *irqlock, | 108 | spinlock_t *irqlock, |
@@ -111,9 +111,11 @@ void videobuf_queue_sg_init(struct videobuf_queue* q, | |||
111 | unsigned int msize, | 111 | unsigned int msize, |
112 | void *priv); | 112 | void *priv); |
113 | 113 | ||
114 | /*FIXME: these variants are used only on *-alsa code, where videobuf is | 114 | /*FIXME: these variants are used only on *-alsa code, where videobuf is |
115 | * used without queue | 115 | * used without queue |
116 | */ | 116 | */ |
117 | int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); | 117 | int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); |
118 | int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); | 118 | int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); |
119 | 119 | ||
120 | #endif /* _VIDEOBUF_DMA_SG_H */ | ||
121 | |||
diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index 4b419a257a7d..851eb1a2ff2a 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h | |||
@@ -19,17 +19,17 @@ | |||
19 | 19 | ||
20 | /* --------------------------------------------------------------------- */ | 20 | /* --------------------------------------------------------------------- */ |
21 | 21 | ||
22 | struct videobuf_vmalloc_memory | 22 | struct videobuf_vmalloc_memory { |
23 | { | ||
24 | u32 magic; | 23 | u32 magic; |
25 | 24 | ||
26 | void *vmalloc; | 25 | void *vmalloc; |
27 | 26 | ||
28 | /* remap_vmalloc_range seems to need to run after mmap() on some cases */ | 27 | /* remap_vmalloc_range seems to need to run |
28 | * after mmap() on some cases */ | ||
29 | struct vm_area_struct *vma; | 29 | struct vm_area_struct *vma; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | 32 | void videobuf_queue_vmalloc_init(struct videobuf_queue *q, |
33 | const struct videobuf_queue_ops *ops, | 33 | const struct videobuf_queue_ops *ops, |
34 | struct device *dev, | 34 | struct device *dev, |
35 | spinlock_t *irqlock, | 35 | spinlock_t *irqlock, |
@@ -38,8 +38,8 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | |||
38 | unsigned int msize, | 38 | unsigned int msize, |
39 | void *priv); | 39 | void *priv); |
40 | 40 | ||
41 | void *videobuf_to_vmalloc (struct videobuf_buffer *buf); | 41 | void *videobuf_to_vmalloc(struct videobuf_buffer *buf); |
42 | 42 | ||
43 | void videobuf_vmalloc_free (struct videobuf_buffer *buf); | 43 | void videobuf_vmalloc_free(struct videobuf_buffer *buf); |
44 | 44 | ||
45 | #endif | 45 | #endif |