* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (57 commits) [media] as3645a: Fix compilation by including slab.h [media] s5p-fimc: Remove linux/version.h include from fimc-mdevice.c [media] s5p-mfc: Remove linux/version.h include from s5p_mfc.c [media] ds3000: using logical && instead of bitwise & [media] v4l2-ctrls: make control names consistent [media] DVB: dib0700, add support for Nova-TD LEDs [media] DVB: dib0700, add corrected Nova-TD frontend_attach [media] DVB: dib0700, separate stk7070pd initialization [media] DVB: dib0700, move Nova-TD Stick to a separate set [media] : add MODULE_FIRMWARE to dib0700 [media] DVB-CORE: remove superfluous DTV_CMDs [media] s5p-jpeg: adapt to recent videobuf2 changes [media] s5p-g2d: fixed a bug in controls setting function [media] s5p-mfc: Fix volatile controls setup [media] drivers/media/video/s5p-mfc/s5p_mfc.c: adjust double test [media] drivers/media/video/s5p-fimc/fimc-capture.c: adjust double test [media] s5p-fimc: Fix incorrect control ID assignment [media] dvb_frontend: Don't call get_frontend() if idle [media] DocBook/dvbproperty.xml: Remove DTV_MODULATION from ISDB-T [media] DocBook/dvbproperty.xml: Fix ISDB-T delivery system parameters ...
Unified · Split
| @@ -163,14 +163,16 @@ get/set up to 64 properties. The actual meaning of each property is described on · 162 unmodified lines | ||
| 163 | 163 | <section id="DTV-FREQUENCY"> |
| 164 | 164 | <title><constant>DTV_FREQUENCY</constant></title> |
| 165 | 165 | |
| 166 | − <para>Central frequency of the channel, in HZ.</para> | |
| 166 | + <para>Central frequency of the channel.</para> | |
| 167 | 167 | |
| 168 | 168 | <para>Notes:</para> |
| 169 | − <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz. | |
| 169 | + <para>1)For satellital delivery systems, it is measured in kHz. | |
| 170 | + For the other ones, it is measured in Hz.</para> | |
| 171 | + <para>2)For ISDB-T, the channels are usually transmitted with an offset of 143kHz. | |
| 170 | 172 | E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of |
| 171 | 173 | the channel which is 6MHz.</para> |
| 172 | 174 | |
| 173 | − <para>2)As in ISDB-Tsb the channel consists of only one or three segments the | |
| 175 | + <para>3)As in ISDB-Tsb the channel consists of only one or three segments the | |
| 174 | 176 | frequency step is 429kHz, 3*429 respectively. As for ISDB-T the |
| 175 | 177 | central frequency of the channel is expected.</para> |
| 176 | 178 | </section> |
| @@ -735,14 +737,10 @@ typedef enum fe_hierarchy { · 558 unmodified lines | ||
| 735 | 737 | <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem> |
| 736 | 738 | <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem> |
| 737 | 739 | <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem> |
| 738 | − <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem> | |
| 739 | 740 | <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem> |
| 740 | 741 | <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem> |
| 741 | − <listitem><para><link linkend="DTV-CODE-RATE-HP"><constant>DTV_CODE_RATE_HP</constant></link></para></listitem> | |
| 742 | − <listitem><para><link linkend="DTV-CODE-RATE-LP"><constant>DTV_CODE_RATE_LP</constant></link></para></listitem> | |
| 743 | 742 | <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem> |
| 744 | 743 | <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem> |
| 745 | − <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem> | |
| 746 | 744 | <listitem><para><link linkend="DTV-ISDBT-LAYER-ENABLED"><constant>DTV_ISDBT_LAYER_ENABLED</constant></link></para></listitem> |
| 747 | 745 | <listitem><para><link linkend="DTV-ISDBT-PARTIAL-RECEPTION"><constant>DTV_ISDBT_PARTIAL_RECEPTION</constant></link></para></listitem> |
| 748 | 746 | <listitem><para><link linkend="DTV-ISDBT-SOUND-BROADCASTING"><constant>DTV_ISDBT_SOUND_BROADCASTING</constant></link></para></listitem> |
| @@ -183,7 +183,12 @@ applications must set the array to zero.</entry> · 182 unmodified lines | ||
| 183 | 183 | <entry>__u32</entry> |
| 184 | 184 | <entry><structfield>ctrl_class</structfield></entry> |
| 185 | 185 | <entry>The control class to which all controls belong, see |
| 186 | −<xref linkend="ctrl-class" />.</entry> | |
| 186 | +<xref linkend="ctrl-class" />. Drivers that use a kernel framework for handling | |
| 187 | +controls will also accept a value of 0 here, meaning that the controls can | |
| 188 | +belong to any control class. Whether drivers support this can be tested by setting | |
| 189 | +<structfield>ctrl_class</structfield> to 0 and calling <constant>VIDIOC_TRY_EXT_CTRLS</constant> | |
| 190 | +with a <structfield>count</structfield> of 0. If that succeeds, then the driver | |
| 191 | +supports this feature.</entry> | |
| 187 | 192 | </row> |
| 188 | 193 | <row> |
| 189 | 194 | <entry>__u32</entry> |
| @@ -194,10 +199,13 @@ also be zero.</entry> · 4 unmodified lines | ||
| 194 | 199 | <row> |
| 195 | 200 | <entry>__u32</entry> |
| 196 | 201 | <entry><structfield>error_idx</structfield></entry> |
| 197 | − <entry>Set by the driver in case of an error. It is the | |
| 198 | −index of the control causing the error or equal to 'count' when the | |
| 199 | −error is not associated with a particular control. Undefined when the | |
| 200 | −ioctl returns 0 (success).</entry> | |
| 202 | + <entry>Set by the driver in case of an error. If it is equal | |
| 203 | +to <structfield>count</structfield>, then no actual changes were made to | |
| 204 | +controls. In other words, the error was not associated with setting a particular | |
| 205 | +control. If it is another value, then only the controls up to <structfield>error_idx-1</structfield> | |
| 206 | +were modified and control <structfield>error_idx</structfield> is the one that | |
| 207 | +caused the error. The <structfield>error_idx</structfield> value is undefined | |
| 208 | +if the ioctl returned 0 (success).</entry> | |
| 201 | 209 | </row> |
| 202 | 210 | <row> |
| 203 | 211 | <entry>__u32</entry> |
| @@ -364,15 +364,20 @@ capability and it is cleared otherwise.</entry> · 363 unmodified lines | ||
| 364 | 364 | <row> |
| 365 | 365 | <entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry> |
| 366 | 366 | <entry>0x0002</entry> |
| 367 | − <entry>The frame buffer is an overlay surface the same | |
| 368 | −size as the capture. [?]</entry> | |
| 369 | − </row> | |
| 370 | − <row> | |
| 371 | − <entry spanname="hspan">The purpose of | |
| 372 | −<constant>V4L2_FBUF_FLAG_OVERLAY</constant> was never quite clear. | |
| 373 | −Most drivers seem to ignore this flag. For compatibility with the | |
| 374 | −<wordasword>bttv</wordasword> driver applications should set the | |
| 375 | −<constant>V4L2_FBUF_FLAG_OVERLAY</constant> flag.</entry> | |
| 367 | + <entry>If this flag is set for a video capture device, then the | |
| 368 | +driver will set the initial overlay size to cover the full framebuffer size, | |
| 369 | +otherwise the existing overlay size (as set by &VIDIOC-S-FMT;) will be used. | |
| 370 | + | |
| 371 | +Only one video capture driver (bttv) supports this flag. The use of this flag | |
| 372 | +for capture devices is deprecated. There is no way to detect which drivers | |
| 373 | +support this flag, so the only reliable method of setting the overlay size is | |
| 374 | +through &VIDIOC-S-FMT;. | |
| 375 | + | |
| 376 | +If this flag is set for a video output device, then the video output overlay | |
| 377 | +window is relative to the top-left corner of the framebuffer and restricted | |
| 378 | +to the size of the framebuffer. If it is cleared, then the video output | |
| 379 | +overlay window is relative to the video output display. | |
| 380 | + </entry> | |
| 376 | 381 | </row> |
| 377 | 382 | <row> |
| 378 | 383 | <entry><constant>V4L2_FBUF_FLAG_CHROMAKEY</constant></entry> |
| @@ -98,8 +98,11 @@ the &v4l2-output; <structfield>modulator</structfield> field and the · 97 unmodified lines | ||
| 98 | 98 | <entry>&v4l2-tuner-type;</entry> |
| 99 | 99 | <entry><structfield>type</structfield></entry> |
| 100 | 100 | <entry>The tuner type. This is the same value as in the |
| 101 | −&v4l2-tuner; <structfield>type</structfield> field. The field is not | |
| 102 | −applicable to modulators, &ie; ignored by drivers.</entry> | |
| 101 | +&v4l2-tuner; <structfield>type</structfield> field. The type must be set | |
| 102 | +to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename> | |
| 103 | +device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant> | |
| 104 | +for all others. The field is not applicable to modulators, &ie; ignored | |
| 105 | +by drivers.</entry> | |
| 103 | 106 | </row> |
| 104 | 107 | <row> |
| 105 | 108 | <entry>__u32</entry> |
| @@ -61,8 +61,8 @@ desired input in an integer and call the · 60 unmodified lines | ||
| 61 | 61 | <constant>VIDIOC_S_INPUT</constant> ioctl with a pointer to this |
| 62 | 62 | integer. Side effects are possible. For example inputs may support |
| 63 | 63 | different video standards, so the driver may implicitly switch the |
| 64 | −current standard. It is good practice to select an input before | |
| 65 | −querying or negotiating any other parameters.</para> | |
| 64 | +current standard. Because of these possible side effects applications | |
| 65 | +must select an input before querying or negotiating any other parameters.</para> | |
| 66 | 66 | |
| 67 | 67 | <para>Information about video inputs is available using the |
| 68 | 68 | &VIDIOC-ENUMINPUT; ioctl.</para> |
| @@ -61,8 +61,9 @@ desired output in an integer and call the · 60 unmodified lines | ||
| 61 | 61 | <constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this integer. |
| 62 | 62 | Side effects are possible. For example outputs may support different |
| 63 | 63 | video standards, so the driver may implicitly switch the current |
| 64 | −standard. It is good practice to select an output before querying or | |
| 65 | −negotiating any other parameters.</para> | |
| 64 | +standard. | |
| 65 | +standard. Because of these possible side effects applications | |
| 66 | +must select an output before querying or negotiating any other parameters.</para> | |
| 66 | 67 | |
| 67 | 68 | <para>Information about video outputs is available using the |
| 68 | 69 | &VIDIOC-ENUMOUTPUT; ioctl.</para> |
| @@ -439,17 +439,6 @@ Who: Jean Delvare <khali@linux-fr.org> · 438 unmodified lines | ||
| 439 | 439 | |
| 440 | 440 | ---------------------------- |
| 441 | 441 | |
| 442 | −What: For VIDIOC_S_FREQUENCY the type field must match the device node's type. | |
| 443 | − If not, return -EINVAL. | |
| 444 | −When: 3.2 | |
| 445 | −Why: It makes no sense to switch the tuner to radio mode by calling | |
| 446 | − VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by | |
| 447 | − calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a | |
| 448 | − move to more consistent handling of tv and radio tuners. | |
| 449 | −Who: Hans Verkuil <hans.verkuil@cisco.com> | |
| 450 | − | |
| 451 | −---------------------------- | |
| 452 | − | |
| 453 | 442 | What: Opening a radio device node will no longer automatically switch the |
| 454 | 443 | tuner mode from tv to radio. |
| 455 | 444 | When: 3.3 |
| @@ -666,27 +666,6 @@ a control of this type whenever the first control belonging to a new control · 665 unmodified lines | ||
| 666 | 666 | class is added. |
| 667 | 667 | |
| 668 | 668 | |
| 669 | −Differences from the Spec | |
| 670 | −========================= | |
| 671 | − | |
| 672 | −There are a few places where the framework acts slightly differently from the | |
| 673 | −V4L2 Specification. Those differences are described in this section. We will | |
| 674 | −have to see whether we need to adjust the spec or not. | |
| 675 | − | |
| 676 | −1) It is no longer required to have all controls contained in a | |
| 677 | −v4l2_ext_control array be from the same control class. The framework will be | |
| 678 | −able to handle any type of control in the array. You need to set ctrl_class | |
| 679 | −to 0 in order to enable this. If ctrl_class is non-zero, then it will still | |
| 680 | −check that all controls belong to that control class. | |
| 681 | − | |
| 682 | −If you set ctrl_class to 0 and count to 0, then it will only return an error | |
| 683 | −if there are no controls at all. | |
| 684 | − | |
| 685 | −2) Clarified the way error_idx works. For get and set it will be equal to | |
| 686 | −count if nothing was done yet. If it is less than count then only the controls | |
| 687 | −up to error_idx-1 were successfully applied. | |
| 688 | − | |
| 689 | − | |
| 690 | 669 | Proposals for Extensions |
| 691 | 670 | ======================== |
| 692 | 671 | |
| @@ -24,6 +24,21 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/dvb/frontend.h> |
| 25 | 25 | #include "dvb_frontend.h" |
| 26 | 26 | |
| 27 | +/* Registers (Write-only) */ | |
| 28 | +#define XREG_INIT 0x00 | |
| 29 | +#define XREG_RF_FREQ 0x02 | |
| 30 | +#define XREG_POWER_DOWN 0x08 | |
| 31 | + | |
| 32 | +/* Registers (Read-only) */ | |
| 33 | +#define XREG_FREQ_ERROR 0x01 | |
| 34 | +#define XREG_LOCK 0x02 | |
| 35 | +#define XREG_VERSION 0x04 | |
| 36 | +#define XREG_PRODUCT_ID 0x08 | |
| 37 | +#define XREG_HSYNC_FREQ 0x10 | |
| 38 | +#define XREG_FRAME_LINES 0x20 | |
| 39 | +#define XREG_SNR 0x40 | |
| 40 | + | |
| 41 | +#define XREG_ADC_ENV 0x0100 | |
| 27 | 42 | |
| 28 | 43 | static int debug; |
| 29 | 44 | module_param(debug, int, 0644); |
| @@ -885,7 +900,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) · 855 unmodified lines | ||
| 885 | 900 | mutex_lock(&priv->lock); |
| 886 | 901 | |
| 887 | 902 | /* Sync Lock Indicator */ |
| 888 | − rc = xc2028_get_reg(priv, 0x0002, &frq_lock); | |
| 903 | + rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock); | |
| 889 | 904 | if (rc < 0) |
| 890 | 905 | goto ret; |
| 891 | 906 | |
| @@ -894,7 +909,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) · 2 unmodified lines | ||
| 894 | 909 | signal = 1 << 11; |
| 895 | 910 | |
| 896 | 911 | /* Get SNR of the video signal */ |
| 897 | − rc = xc2028_get_reg(priv, 0x0040, &signal); | |
| 912 | + rc = xc2028_get_reg(priv, XREG_SNR, &signal); | |
| 898 | 913 | if (rc < 0) |
| 899 | 914 | goto ret; |
| 900 | 915 | |
| @@ -1019,9 +1034,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, · 118 unmodified lines | ||
| 1019 | 1034 | |
| 1020 | 1035 | /* CMD= Set frequency */ |
| 1021 | 1036 | if (priv->firm_version < 0x0202) |
| 1022 | − rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00}); | |
| 1037 | + rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00}); | |
| 1023 | 1038 | else |
| 1024 | − rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00}); | |
| 1039 | + rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00}); | |
| 1025 | 1040 | if (rc < 0) |
| 1026 | 1041 | goto ret; |
| 1027 | 1042 | |
| @@ -1201,9 +1216,9 @@ static int xc2028_sleep(struct dvb_frontend *fe) · 173 unmodified lines | ||
| 1201 | 1216 | mutex_lock(&priv->lock); |
| 1202 | 1217 | |
| 1203 | 1218 | if (priv->firm_version < 0x0202) |
| 1204 | − rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00}); | |
| 1219 | + rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00}); | |
| 1205 | 1220 | else |
| 1206 | − rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00}); | |
| 1221 | + rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00}); | |
| 1207 | 1222 | |
| 1208 | 1223 | priv->cur_fw.type = 0; /* need firmware reload */ |
| 1209 | 1224 | |
| @@ -154,6 +154,8 @@ struct xc4000_priv { · 153 unmodified lines | ||
| 154 | 154 | #define XREG_SNR 0x06 |
| 155 | 155 | #define XREG_VERSION 0x07 |
| 156 | 156 | #define XREG_PRODUCT_ID 0x08 |
| 157 | +#define XREG_SIGNAL_LEVEL 0x0A | |
| 158 | +#define XREG_NOISE_LEVEL 0x0B | |
| 157 | 159 | |
| 158 | 160 | /* |
| 159 | 161 | Basic firmware description. This will remain with |
| @@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality) · 326 unmodified lines | ||
| 486 | 488 | return xc4000_readreg(priv, XREG_QUALITY, quality); |
| 487 | 489 | } |
| 488 | 490 | |
| 491 | +static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal) | |
| 492 | +{ | |
| 493 | + return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal); | |
| 494 | +} | |
| 495 | + | |
| 496 | +static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise) | |
| 497 | +{ | |
| 498 | + return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise); | |
| 499 | +} | |
| 500 | + | |
| 489 | 501 | static u16 xc_wait_for_lock(struct xc4000_priv *priv) |
| 490 | 502 | { |
| 491 | 503 | u16 lock_state = 0; |
| @@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv) · 597 unmodified lines | ||
| 1089 | 1101 | u32 hsync_freq_hz = 0; |
| 1090 | 1102 | u16 frame_lines; |
| 1091 | 1103 | u16 quality; |
| 1104 | + u16 signal = 0; | |
| 1105 | + u16 noise = 0; | |
| 1092 | 1106 | u8 hw_majorversion = 0, hw_minorversion = 0; |
| 1093 | 1107 | u8 fw_majorversion = 0, fw_minorversion = 0; |
| 1094 | 1108 | |
| @@ -1119,6 +1133,12 @@ static void xc_debug_dump(struct xc4000_priv *priv) · 24 unmodified lines | ||
| 1119 | 1133 | |
| 1120 | 1134 | xc_get_quality(priv, &quality); |
| 1121 | 1135 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); |
| 1136 | + | |
| 1137 | + xc_get_signal_level(priv, &signal); | |
| 1138 | + dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal); | |
| 1139 | + | |
| 1140 | + xc_get_noise_level(priv, &noise); | |
| 1141 | + dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise); | |
| 1122 | 1142 | } |
| 1123 | 1143 | |
| 1124 | 1144 | static int xc4000_set_params(struct dvb_frontend *fe) |
| @@ -1432,6 +1452,71 @@ fail: · 307 unmodified lines | ||
| 1432 | 1452 | return ret; |
| 1433 | 1453 | } |
| 1434 | 1454 | |
| 1455 | +static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength) | |
| 1456 | +{ | |
| 1457 | + struct xc4000_priv *priv = fe->tuner_priv; | |
| 1458 | + u16 value = 0; | |
| 1459 | + int rc; | |
| 1460 | + | |
| 1461 | + mutex_lock(&priv->lock); | |
| 1462 | + rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value); | |
| 1463 | + mutex_unlock(&priv->lock); | |
| 1464 | + | |
| 1465 | + if (rc < 0) | |
| 1466 | + goto ret; | |
| 1467 | + | |
| 1468 | + /* Informations from real testing of DVB-T and radio part, | |
| 1469 | + coeficient for one dB is 0xff. | |
| 1470 | + */ | |
| 1471 | + tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value); | |
| 1472 | + | |
| 1473 | + /* all known digital modes */ | |
| 1474 | + if ((priv->video_standard == XC4000_DTV6) || | |
| 1475 | + (priv->video_standard == XC4000_DTV7) || | |
| 1476 | + (priv->video_standard == XC4000_DTV7_8) || | |
| 1477 | + (priv->video_standard == XC4000_DTV8)) | |
| 1478 | + goto digital; | |
| 1479 | + | |
| 1480 | + /* Analog mode has NOISE LEVEL important, signal | |
| 1481 | + depends only on gain of antenna and amplifiers, | |
| 1482 | + but it doesn't tell anything about real quality | |
| 1483 | + of reception. | |
| 1484 | + */ | |
| 1485 | + mutex_lock(&priv->lock); | |
| 1486 | + rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value); | |
| 1487 | + mutex_unlock(&priv->lock); | |
| 1488 | + | |
| 1489 | + tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value); | |
| 1490 | + | |
| 1491 | + /* highest noise level: 32dB */ | |
| 1492 | + if (value >= 0x2000) { | |
| 1493 | + value = 0; | |
| 1494 | + } else { | |
| 1495 | + value = ~value << 3; | |
| 1496 | + } | |
| 1497 | + | |
| 1498 | + goto ret; | |
| 1499 | + | |
| 1500 | + /* Digital mode has SIGNAL LEVEL important and real | |
| 1501 | + noise level is stored in demodulator registers. | |
| 1502 | + */ | |
| 1503 | +digital: | |
| 1504 | + /* best signal: -50dB */ | |
| 1505 | + if (value <= 0x3200) { | |
| 1506 | + value = 0xffff; | |
| 1507 | + /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */ | |
| 1508 | + } else if (value >= 0x713A) { | |
| 1509 | + value = 0; | |
| 1510 | + } else { | |
| 1511 | + value = ~(value - 0x3200) << 2; | |
| 1512 | + } | |
| 1513 | + | |
| 1514 | +ret: | |
| 1515 | + *strength = value; | |
| 1516 | + | |
| 1517 | + return rc; | |
| 1518 | +} | |
| 1519 | + | |
| 1435 | 1520 | static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) |
| 1436 | 1521 | { |
| 1437 | 1522 | struct xc4000_priv *priv = fe->tuner_priv; |
| @@ -1559,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = { · 121 unmodified lines | ||
| 1559 | 1644 | .set_params = xc4000_set_params, |
| 1560 | 1645 | .set_analog_params = xc4000_set_analog_params, |
| 1561 | 1646 | .get_frequency = xc4000_get_frequency, |
| 1647 | + .get_rf_strength = xc4000_get_signal, | |
| 1562 | 1648 | .get_bandwidth = xc4000_get_bandwidth, |
| 1563 | 1649 | .get_status = xc4000_get_status |
| 1564 | 1650 | }; |
| @@ -904,8 +904,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) · 903 unmodified lines | ||
| 904 | 904 | { |
| 905 | 905 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 906 | 906 | int i; |
| 907 | + u32 delsys; | |
| 907 | 908 | |
| 909 | + delsys = c->delivery_system; | |
| 908 | 910 | memset(c, 0, sizeof(struct dtv_frontend_properties)); |
| 911 | + c->delivery_system = delsys; | |
| 909 | 912 | |
| 910 | 913 | c->state = DTV_CLEAR; |
| 911 | 914 | |
| @@ -1009,25 +1012,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { · 97 unmodified lines | ||
| 1009 | 1012 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), |
| 1010 | 1013 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), |
| 1011 | 1014 | |
| 1012 | − _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0), | |
| 1013 | − _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0), | |
| 1014 | − _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0), | |
| 1015 | − _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0), | |
| 1016 | − _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0), | |
| 1017 | − _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0), | |
| 1018 | − _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0), | |
| 1019 | − _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0), | |
| 1020 | − _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0), | |
| 1021 | − _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0), | |
| 1022 | − _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0), | |
| 1023 | − _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0), | |
| 1024 | − _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0), | |
| 1025 | − _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0), | |
| 1026 | − _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0), | |
| 1027 | − _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0), | |
| 1028 | − _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0), | |
| 1029 | − _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0), | |
| 1030 | − | |
| 1031 | 1015 | _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), |
| 1032 | 1016 | _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), |
| 1033 | 1017 | |
| @@ -1413,6 +1397,15 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) · 379 unmodified lines | ||
| 1413 | 1397 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1414 | 1398 | enum dvbv3_emulation_type type; |
| 1415 | 1399 | |
| 1400 | + /* | |
| 1401 | + * It was reported that some old DVBv5 applications were | |
| 1402 | + * filling delivery_system with SYS_UNDEFINED. If this happens, | |
| 1403 | + * assume that the application wants to use the first supported | |
| 1404 | + * delivery system. | |
| 1405 | + */ | |
| 1406 | + if (c->delivery_system == SYS_UNDEFINED) | |
| 1407 | + c->delivery_system = fe->ops.delsys[0]; | |
| 1408 | + | |
| 1416 | 1409 | if (desired_system == SYS_UNDEFINED) { |
| 1417 | 1410 | /* |
| 1418 | 1411 | * A DVBv3 call doesn't know what's the desired system. |
| @@ -1732,6 +1725,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, · 313 unmodified lines | ||
| 1732 | 1725 | { |
| 1733 | 1726 | struct dvb_device *dvbdev = file->private_data; |
| 1734 | 1727 | struct dvb_frontend *fe = dvbdev->priv; |
| 1728 | + struct dvb_frontend_private *fepriv = fe->frontend_priv; | |
| 1735 | 1729 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
| 1736 | 1730 | int err = 0; |
| 1737 | 1731 | |
| @@ -1798,9 +1792,14 @@ static int dvb_frontend_ioctl_properties(struct file *file, · 60 unmodified lines | ||
| 1798 | 1792 | |
| 1799 | 1793 | /* |
| 1800 | 1794 | * Fills the cache out struct with the cache contents, plus |
| 1801 | − * the data retrieved from get_frontend. | |
| 1795 | + * the data retrieved from get_frontend, if the frontend | |
| 1796 | + * is not idle. Otherwise, returns the cached content | |
| 1802 | 1797 | */ |
| 1803 | − dtv_get_frontend(fe, NULL); | |
| 1798 | + if (fepriv->state != FESTATE_IDLE) { | |
| 1799 | + err = dtv_get_frontend(fe, NULL); | |
| 1800 | + if (err < 0) | |
| 1801 | + goto out; | |
| 1802 | + } | |
| 1804 | 1803 | for (i = 0; i < tvps->num; i++) { |
| 1805 | 1804 | err = dtv_property_process_get(fe, c, tvp + i, file); |
| 1806 | 1805 | if (err < 0) |
| @@ -877,24 +877,18 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) · 876 unmodified lines | ||
| 877 | 877 | case ANYSEE_HW_508T2C: /* 20 */ |
| 878 | 878 | /* E7 T2C */ |
| 879 | 879 | |
| 880 | + if (state->fe_id) | |
| 881 | + break; | |
| 882 | + | |
| 880 | 883 | /* enable DVB-T/T2/C demod on IOE[5] */ |
| 881 | 884 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); |
| 882 | 885 | if (ret) |
| 883 | 886 | goto error; |
| 884 | 887 | |
| 885 | − if (state->fe_id == 0) { | |
| 886 | − /* DVB-T/T2 */ | |
| 887 | − adap->fe_adap[state->fe_id].fe = | |
| 888 | − dvb_attach(cxd2820r_attach, | |
| 889 | − &anysee_cxd2820r_config, | |
| 890 | − &adap->dev->i2c_adap, NULL); | |
| 891 | − } else { | |
| 892 | − /* DVB-C */ | |
| 893 | − adap->fe_adap[state->fe_id].fe = | |
| 894 | − dvb_attach(cxd2820r_attach, | |
| 895 | − &anysee_cxd2820r_config, | |
| 896 | − &adap->dev->i2c_adap, adap->fe_adap[0].fe); | |
| 897 | − } | |
| 888 | + /* attach demod */ | |
| 889 | + adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, | |
| 890 | + &anysee_cxd2820r_config, &adap->dev->i2c_adap, | |
| 891 | + NULL); | |
| 898 | 892 | |
| 899 | 893 | state->has_ci = true; |
| 900 | 894 | |
| @@ -48,6 +48,8 @@ struct dib0700_state { · 47 unmodified lines | ||
| 48 | 48 | u8 disable_streaming_master_mode; |
| 49 | 49 | u32 fw_version; |
| 50 | 50 | u32 nb_packet_buffer_size; |
| 51 | + int (*read_status)(struct dvb_frontend *, fe_status_t *); | |
| 52 | + int (*sleep)(struct dvb_frontend* fe); | |
| 51 | 53 | u8 buf[255]; |
| 52 | 54 | }; |
| 53 | 55 | |
| @@ -834,6 +834,7 @@ static struct usb_driver dib0700_driver = { · 833 unmodified lines | ||
| 834 | 834 | |
| 835 | 835 | module_usb_driver(dib0700_driver); |
| 836 | 836 | |
| 837 | +MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw"); | |
| 837 | 838 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
| 838 | 839 | MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); |
| 839 | 840 | MODULE_VERSION("1.0"); |
| @@ -3066,19 +3066,25 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = { · 3065 unmodified lines | ||
| 3066 | 3066 | } |
| 3067 | 3067 | }; |
| 3068 | 3068 | |
| 3069 | −static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) | |
| 3069 | +static void stk7070pd_init(struct dvb_usb_device *dev) | |
| 3070 | 3070 | { |
| 3071 | − dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | |
| 3071 | + dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1); | |
| 3072 | 3072 | msleep(10); |
| 3073 | − dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | |
| 3074 | − dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | |
| 3075 | − dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | |
| 3076 | − dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | |
| 3073 | + dib0700_set_gpio(dev, GPIO9, GPIO_OUT, 1); | |
| 3074 | + dib0700_set_gpio(dev, GPIO4, GPIO_OUT, 1); | |
| 3075 | + dib0700_set_gpio(dev, GPIO7, GPIO_OUT, 1); | |
| 3076 | + dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 0); | |
| 3077 | 3077 | |
| 3078 | − dib0700_ctrl_clock(adap->dev, 72, 1); | |
| 3078 | + dib0700_ctrl_clock(dev, 72, 1); | |
| 3079 | 3079 | |
| 3080 | 3080 | msleep(10); |
| 3081 | − dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | |
| 3081 | + dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1); | |
| 3082 | +} | |
| 3083 | + | |
| 3084 | +static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) | |
| 3085 | +{ | |
| 3086 | + stk7070pd_init(adap->dev); | |
| 3087 | + | |
| 3082 | 3088 | msleep(10); |
| 3083 | 3089 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 3084 | 3090 | |
| @@ -3099,6 +3105,77 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) · 14 unmodified lines | ||
| 3099 | 3105 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 3100 | 3106 | } |
| 3101 | 3107 | |
| 3108 | +static int novatd_read_status_override(struct dvb_frontend *fe, | |
| 3109 | + fe_status_t *stat) | |
| 3110 | +{ | |
| 3111 | + struct dvb_usb_adapter *adap = fe->dvb->priv; | |
| 3112 | + struct dvb_usb_device *dev = adap->dev; | |
| 3113 | + struct dib0700_state *state = dev->priv; | |
| 3114 | + int ret; | |
| 3115 | + | |
| 3116 | + ret = state->read_status(fe, stat); | |
| 3117 | + | |
| 3118 | + if (!ret) | |
| 3119 | + dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, | |
| 3120 | + !!(*stat & FE_HAS_LOCK)); | |
| 3121 | + | |
| 3122 | + return ret; | |
| 3123 | +} | |
| 3124 | + | |
| 3125 | +static int novatd_sleep_override(struct dvb_frontend* fe) | |
| 3126 | +{ | |
| 3127 | + struct dvb_usb_adapter *adap = fe->dvb->priv; | |
| 3128 | + struct dvb_usb_device *dev = adap->dev; | |
| 3129 | + struct dib0700_state *state = dev->priv; | |
| 3130 | + | |
| 3131 | + /* turn off LED */ | |
| 3132 | + dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0); | |
| 3133 | + | |
| 3134 | + return state->sleep(fe); | |
| 3135 | +} | |
| 3136 | + | |
| 3137 | +/** | |
| 3138 | + * novatd_frontend_attach - Nova-TD specific attach | |
| 3139 | + * | |
| 3140 | + * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for | |
| 3141 | + * information purposes. | |
| 3142 | + */ | |
| 3143 | +static int novatd_frontend_attach(struct dvb_usb_adapter *adap) | |
| 3144 | +{ | |
| 3145 | + struct dvb_usb_device *dev = adap->dev; | |
| 3146 | + struct dib0700_state *st = dev->priv; | |
| 3147 | + | |
| 3148 | + if (adap->id == 0) { | |
| 3149 | + stk7070pd_init(dev); | |
| 3150 | + | |
| 3151 | + /* turn the power LED on, the other two off (just in case) */ | |
| 3152 | + dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0); | |
| 3153 | + dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0); | |
| 3154 | + dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1); | |
| 3155 | + | |
| 3156 | + if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18, | |
| 3157 | + stk7070pd_dib7000p_config) != 0) { | |
| 3158 | + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | |
| 3159 | + __func__); | |
| 3160 | + return -ENODEV; | |
| 3161 | + } | |
| 3162 | + } | |
| 3163 | + | |
| 3164 | + adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap, | |
| 3165 | + adap->id == 0 ? 0x80 : 0x82, | |
| 3166 | + &stk7070pd_dib7000p_config[adap->id]); | |
| 3167 | + | |
| 3168 | + if (adap->fe_adap[0].fe == NULL) | |
| 3169 | + return -ENODEV; | |
| 3170 | + | |
| 3171 | + st->read_status = adap->fe_adap[0].fe->ops.read_status; | |
| 3172 | + adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override; | |
| 3173 | + st->sleep = adap->fe_adap[0].fe->ops.sleep; | |
| 3174 | + adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override; | |
| 3175 | + | |
| 3176 | + return 0; | |
| 3177 | +} | |
| 3178 | + | |
| 3102 | 3179 | /* S5H1411 */ |
| 3103 | 3180 | static struct s5h1411_config pinnacle_801e_config = { |
| 3104 | 3181 | .output_mode = S5H1411_PARALLEL_OUTPUT, |
| @@ -3861,6 +3938,57 @@ struct dvb_usb_device_properties dib0700_devices[] = { · 756 unmodified lines | ||
| 3861 | 3938 | }, |
| 3862 | 3939 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
| 3863 | 3940 | |
| 3941 | + .num_adapters = 2, | |
| 3942 | + .adapter = { | |
| 3943 | + { | |
| 3944 | + .num_frontends = 1, | |
| 3945 | + .fe = {{ | |
| 3946 | + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | |
| 3947 | + .pid_filter_count = 32, | |
| 3948 | + .pid_filter = stk70x0p_pid_filter, | |
| 3949 | + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | |
| 3950 | + .frontend_attach = novatd_frontend_attach, | |
| 3951 | + .tuner_attach = dib7070p_tuner_attach, | |
| 3952 | + | |
| 3953 | + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | |
| 3954 | + }}, | |
| 3955 | + .size_of_priv = sizeof(struct dib0700_adapter_state), | |
| 3956 | + }, { | |
| 3957 | + .num_frontends = 1, | |
| 3958 | + .fe = {{ | |
| 3959 | + .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | |
| 3960 | + .pid_filter_count = 32, | |
| 3961 | + .pid_filter = stk70x0p_pid_filter, | |
| 3962 | + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | |
| 3963 | + .frontend_attach = novatd_frontend_attach, | |
| 3964 | + .tuner_attach = dib7070p_tuner_attach, | |
| 3965 | + | |
| 3966 | + DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | |
| 3967 | + }}, | |
| 3968 | + .size_of_priv = sizeof(struct dib0700_adapter_state), | |
| 3969 | + } | |
| 3970 | + }, | |
| 3971 | + | |
| 3972 | + .num_device_descs = 1, | |
| 3973 | + .devices = { | |
| 3974 | + { "Hauppauge Nova-TD Stick (52009)", | |
| 3975 | + { &dib0700_usb_id_table[35], NULL }, | |
| 3976 | + { NULL }, | |
| 3977 | + }, | |
| 3978 | + }, | |
| 3979 | + | |
| 3980 | + .rc.core = { | |
| 3981 | + .rc_interval = DEFAULT_RC_INTERVAL, | |
| 3982 | + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | |
| 3983 | + .module_name = "dib0700", | |
| 3984 | + .rc_query = dib0700_rc_query_old_firmware, | |
| 3985 | + .allowed_protos = RC_TYPE_RC5 | | |
| 3986 | + RC_TYPE_RC6 | | |
| 3987 | + RC_TYPE_NEC, | |
| 3988 | + .change_protocol = dib0700_change_protocol, | |
| 3989 | + }, | |
| 3990 | + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | |
| 3991 | + | |
| 3864 | 3992 | .num_adapters = 2, |
| 3865 | 3993 | .adapter = { |
| 3866 | 3994 | { |
| @@ -3892,7 +4020,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { · 25 unmodified lines | ||
| 3892 | 4020 | } |
| 3893 | 4021 | }, |
| 3894 | 4022 | |
| 3895 | − .num_device_descs = 6, | |
| 4023 | + .num_device_descs = 5, | |
| 3896 | 4024 | .devices = { |
| 3897 | 4025 | { "DiBcom STK7070PD reference design", |
| 3898 | 4026 | { &dib0700_usb_id_table[17], NULL }, |
| @@ -3902,10 +4030,6 @@ struct dvb_usb_device_properties dib0700_devices[] = { · 3 unmodified lines | ||
| 3902 | 4030 | { &dib0700_usb_id_table[18], NULL }, |
| 3903 | 4031 | { NULL }, |
| 3904 | 4032 | }, |
| 3905 | − { "Hauppauge Nova-TD Stick (52009)", | |
| 3906 | − { &dib0700_usb_id_table[35], NULL }, | |
| 3907 | − { NULL }, | |
| 3908 | − }, | |
| 3909 | 4033 | { "Hauppauge Nova-TD-500 (84xxx)", |
| 3910 | 4034 | { &dib0700_usb_id_table[36], NULL }, |
| 3911 | 4035 | { NULL }, |
| @@ -309,9 +309,14 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status) · 308 unmodified lines | ||
| 309 | 309 | |
| 310 | 310 | static int cxd2820r_get_frontend(struct dvb_frontend *fe) |
| 311 | 311 | { |
| 312 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 312 | 313 | int ret; |
| 313 | 314 | |
| 314 | 315 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); |
| 316 | + | |
| 317 | + if (priv->delivery_system == SYS_UNDEFINED) | |
| 318 | + return 0; | |
| 319 | + | |
| 315 | 320 | switch (fe->dtv_property_cache.delivery_system) { |
| 316 | 321 | case SYS_DVBT: |
| 317 | 322 | ret = cxd2820r_get_frontend_t(fe); |
| @@ -476,10 +481,10 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) · 158 unmodified lines | ||
| 476 | 481 | dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); |
| 477 | 482 | |
| 478 | 483 | /* switch between DVB-T and DVB-T2 when tune fails */ |
| 479 | − if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) { | |
| 484 | + if (priv->last_tune_failed) { | |
| 480 | 485 | if (priv->delivery_system == SYS_DVBT) |
| 481 | 486 | c->delivery_system = SYS_DVBT2; |
| 482 | − else | |
| 487 | + else if (priv->delivery_system == SYS_DVBT2) | |
| 483 | 488 | c->delivery_system = SYS_DVBT; |
| 484 | 489 | } |
| 485 | 490 | |
| @@ -492,6 +497,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) · 6 unmodified lines | ||
| 492 | 497 | /* frontend lock wait loop count */ |
| 493 | 498 | switch (priv->delivery_system) { |
| 494 | 499 | case SYS_DVBT: |
| 500 | + case SYS_DVBC_ANNEX_A: | |
| 495 | 501 | i = 20; |
| 496 | 502 | break; |
| 497 | 503 | case SYS_DVBT2: |
| @@ -1195,7 +1195,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe) · 1194 unmodified lines | ||
| 1195 | 1195 | |
| 1196 | 1196 | for (i = 0; i < 30 ; i++) { |
| 1197 | 1197 | ds3000_read_status(fe, &status); |
| 1198 | − if (status && FE_HAS_LOCK) | |
| 1198 | + if (status & FE_HAS_LOCK) | |
| 1199 | 1199 | break; |
| 1200 | 1200 | |
| 1201 | 1201 | msleep(10); |
| @@ -402,7 +402,7 @@ static int mb86a20s_get_modulation(struct mb86a20s_state *state, · 401 unmodified lines | ||
| 402 | 402 | [2] = 0x8e, /* Layer C */ |
| 403 | 403 | }; |
| 404 | 404 | |
| 405 | − if (layer > ARRAY_SIZE(reg)) | |
| 405 | + if (layer >= ARRAY_SIZE(reg)) | |
| 406 | 406 | return -EINVAL; |
| 407 | 407 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
| 408 | 408 | if (rc < 0) |
| @@ -435,7 +435,7 @@ static int mb86a20s_get_fec(struct mb86a20s_state *state, · 26 unmodified lines | ||
| 435 | 435 | [2] = 0x8f, /* Layer C */ |
| 436 | 436 | }; |
| 437 | 437 | |
| 438 | − if (layer > ARRAY_SIZE(reg)) | |
| 438 | + if (layer >= ARRAY_SIZE(reg)) | |
| 439 | 439 | return -EINVAL; |
| 440 | 440 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
| 441 | 441 | if (rc < 0) |
| @@ -470,7 +470,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state, · 28 unmodified lines | ||
| 470 | 470 | [2] = 0x90, /* Layer C */ |
| 471 | 471 | }; |
| 472 | 472 | |
| 473 | − if (layer > ARRAY_SIZE(reg)) | |
| 473 | + if (layer >= ARRAY_SIZE(reg)) | |
| 474 | 474 | return -EINVAL; |
| 475 | 475 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
| 476 | 476 | if (rc < 0) |
| @@ -494,7 +494,7 @@ static int mb86a20s_get_segment_count(struct mb86a20s_state *state, · 17 unmodified lines | ||
| 494 | 494 | [2] = 0x91, /* Layer C */ |
| 495 | 495 | }; |
| 496 | 496 | |
| 497 | − if (layer > ARRAY_SIZE(reg)) | |
| 497 | + if (layer >= ARRAY_SIZE(reg)) | |
| 498 | 498 | return -EINVAL; |
| 499 | 499 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
| 500 | 500 | if (rc < 0) |
| @@ -29,7 +29,6 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/delay.h> |
| 30 | 30 | #include <linux/firmware.h> |
| 31 | 31 | #include <linux/i2c.h> |
| 32 | −#include <linux/version.h> | |
| 33 | 32 | #include <asm/div64.h> |
| 34 | 33 | |
| 35 | 34 | #include "dvb_frontend.h" |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/i2c.h> |
| 30 | 30 | #include <linux/module.h> |
| 31 | 31 | #include <linux/mutex.h> |
| 32 | +#include <linux/slab.h> | |
| 32 | 33 | |
| 33 | 34 | #include <media/as3645a.h> |
| 34 | 35 | #include <media/v4l2-ctrls.h> |
| @@ -751,20 +751,10 @@ int cx18_v4l2_close(struct file *filp) · 750 unmodified lines | ||
| 751 | 751 | |
| 752 | 752 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); |
| 753 | 753 | |
| 754 | − v4l2_fh_del(fh); | |
| 755 | − v4l2_fh_exit(fh); | |
| 756 | − | |
| 757 | − /* Easy case first: this stream was never claimed by us */ | |
| 758 | − if (s->id != id->open_id) { | |
| 759 | − kfree(id); | |
| 760 | − return 0; | |
| 761 | − } | |
| 762 | − | |
| 763 | − /* 'Unclaim' this stream */ | |
| 764 | − | |
| 765 | − /* Stop radio */ | |
| 766 | 754 | mutex_lock(&cx->serialize_lock); |
| 767 | − if (id->type == CX18_ENC_STREAM_TYPE_RAD) { | |
| 755 | + /* Stop radio */ | |
| 756 | + if (id->type == CX18_ENC_STREAM_TYPE_RAD && | |
| 757 | + v4l2_fh_is_singular_file(filp)) { | |
| 768 | 758 | /* Closing radio device, return to TV mode */ |
| 769 | 759 | cx18_mute(cx); |
| 770 | 760 | /* Mark that the radio is no longer in use */ |
| @@ -781,10 +771,14 @@ int cx18_v4l2_close(struct file *filp) · 10 unmodified lines | ||
| 781 | 771 | } |
| 782 | 772 | /* Done! Unmute and continue. */ |
| 783 | 773 | cx18_unmute(cx); |
| 784 | − cx18_release_stream(s); | |
| 785 | − } else { | |
| 786 | − cx18_stop_capture(id, 0); | |
| 787 | 774 | } |
| 775 | + | |
| 776 | + v4l2_fh_del(fh); | |
| 777 | + v4l2_fh_exit(fh); | |
| 778 | + | |
| 779 | + /* 'Unclaim' this stream */ | |
| 780 | + if (s->id == id->open_id) | |
| 781 | + cx18_stop_capture(id, 0); | |
| 788 | 782 | kfree(id); |
| 789 | 783 | mutex_unlock(&cx->serialize_lock); |
| 790 | 784 | return 0; |
| @@ -810,21 +804,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) · 19 unmodified lines | ||
| 810 | 804 | |
| 811 | 805 | item->open_id = cx->open_id++; |
| 812 | 806 | filp->private_data = &item->fh; |
| 807 | + v4l2_fh_add(&item->fh); | |
| 813 | 808 | |
| 814 | − if (item->type == CX18_ENC_STREAM_TYPE_RAD) { | |
| 815 | − /* Try to claim this stream */ | |
| 816 | − if (cx18_claim_stream(item, item->type)) { | |
| 817 | − /* No, it's already in use */ | |
| 818 | − v4l2_fh_exit(&item->fh); | |
| 819 | − kfree(item); | |
| 820 | − return -EBUSY; | |
| 821 | − } | |
| 822 | − | |
| 809 | + if (item->type == CX18_ENC_STREAM_TYPE_RAD && | |
| 810 | + v4l2_fh_is_singular_file(filp)) { | |
| 823 | 811 | if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { |
| 824 | 812 | if (atomic_read(&cx->ana_capturing) > 0) { |
| 825 | 813 | /* switching to radio while capture is |
| 826 | 814 | in progress is not polite */ |
| 827 | − cx18_release_stream(s); | |
| 815 | + v4l2_fh_del(&item->fh); | |
| 828 | 816 | v4l2_fh_exit(&item->fh); |
| 829 | 817 | kfree(item); |
| 830 | 818 | return -EBUSY; |
| @@ -842,7 +830,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) · 11 unmodified lines | ||
| 842 | 830 | /* Done! Unmute and continue. */ |
| 843 | 831 | cx18_unmute(cx); |
| 844 | 832 | } |
| 845 | − v4l2_fh_add(&item->fh); | |
| 846 | 833 | return 0; |
| 847 | 834 | } |
| 848 | 835 | |
| @@ -1052,7 +1052,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, · 1051 unmodified lines | ||
| 1052 | 1052 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
| 1053 | 1053 | if (dev == NULL) { |
| 1054 | 1054 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); |
| 1055 | − clear_bit(dev->devno, &cx231xx_devused); | |
| 1055 | + clear_bit(nr, &cx231xx_devused); | |
| 1056 | 1056 | return -ENOMEM; |
| 1057 | 1057 | } |
| 1058 | 1058 | |
| @@ -213,8 +213,8 @@ struct cx23885_board cx23885_boards[] = { · 212 unmodified lines | ||
| 213 | 213 | .portc = CX23885_MPEG_DVB, |
| 214 | 214 | .tuner_type = TUNER_XC4000, |
| 215 | 215 | .tuner_addr = 0x61, |
| 216 | − .radio_type = TUNER_XC4000, | |
| 217 | − .radio_addr = 0x61, | |
| 216 | + .radio_type = UNSET, | |
| 217 | + .radio_addr = ADDR_UNSET, | |
| 218 | 218 | .input = {{ |
| 219 | 219 | .type = CX23885_VMUX_TELEVISION, |
| 220 | 220 | .vmux = CX25840_VIN2_CH1 | |
| @@ -943,6 +943,11 @@ static int dvb_register(struct cx23885_tsport *port) · 942 unmodified lines | ||
| 943 | 943 | |
| 944 | 944 | fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, |
| 945 | 945 | &dev->i2c_bus[1].i2c_adap, &cfg); |
| 946 | + if (!fe) { | |
| 947 | + printk(KERN_ERR "%s/2: xc4000 attach failed\n", | |
| 948 | + dev->name); | |
| 949 | + goto frontend_detach; | |
| 950 | + } | |
| 946 | 951 | } |
| 947 | 952 | break; |
| 948 | 953 | case CX23885_BOARD_TBS_6920: |
| @@ -1550,7 +1550,6 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, · 1549 unmodified lines | ||
| 1550 | 1550 | struct v4l2_control ctrl; |
| 1551 | 1551 | struct videobuf_dvb_frontend *vfe; |
| 1552 | 1552 | struct dvb_frontend *fe; |
| 1553 | − int err = 0; | |
| 1554 | 1553 | |
| 1555 | 1554 | struct analog_parameters params = { |
| 1556 | 1555 | .mode = V4L2_TUNER_ANALOG_TV, |
| @@ -1572,8 +1571,10 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, · 15 unmodified lines | ||
| 1572 | 1571 | params.frequency, f->tuner, params.std); |
| 1573 | 1572 | |
| 1574 | 1573 | vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1); |
| 1575 | − if (!vfe) | |
| 1576 | − err = -EINVAL; | |
| 1574 | + if (!vfe) { | |
| 1575 | + mutex_unlock(&dev->lock); | |
| 1576 | + return -EINVAL; | |
| 1577 | + } | |
| 1577 | 1578 | |
| 1578 | 1579 | fe = vfe->dvb.frontend; |
| 1579 | 1580 | |
| @@ -1573,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = { · 1572 unmodified lines | ||
| 1573 | 1573 | .name = "Pinnacle Hybrid PCTV", |
| 1574 | 1574 | .tuner_type = TUNER_XC2028, |
| 1575 | 1575 | .tuner_addr = 0x61, |
| 1576 | − .radio_type = TUNER_XC2028, | |
| 1577 | − .radio_addr = 0x61, | |
| 1576 | + .radio_type = UNSET, | |
| 1577 | + .radio_addr = ADDR_UNSET, | |
| 1578 | 1578 | .input = { { |
| 1579 | 1579 | .type = CX88_VMUX_TELEVISION, |
| 1580 | 1580 | .vmux = 0, |
| @@ -1611,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = { · 30 unmodified lines | ||
| 1611 | 1611 | .name = "Leadtek TV2000 XP Global", |
| 1612 | 1612 | .tuner_type = TUNER_XC2028, |
| 1613 | 1613 | .tuner_addr = 0x61, |
| 1614 | − .radio_type = TUNER_XC2028, | |
| 1615 | − .radio_addr = 0x61, | |
| 1614 | + .radio_type = UNSET, | |
| 1615 | + .radio_addr = ADDR_UNSET, | |
| 1616 | 1616 | .input = { { |
| 1617 | 1617 | .type = CX88_VMUX_TELEVISION, |
| 1618 | 1618 | .vmux = 0, |
| @@ -2115,8 +2115,8 @@ static const struct cx88_board cx88_boards[] = { · 496 unmodified lines | ||
| 2115 | 2115 | .name = "Terratec Cinergy HT PCI MKII", |
| 2116 | 2116 | .tuner_type = TUNER_XC2028, |
| 2117 | 2117 | .tuner_addr = 0x61, |
| 2118 | − .radio_type = TUNER_XC2028, | |
| 2119 | − .radio_addr = 0x61, | |
| 2118 | + .radio_type = UNSET, | |
| 2119 | + .radio_addr = ADDR_UNSET, | |
| 2120 | 2120 | .input = { { |
| 2121 | 2121 | .type = CX88_VMUX_TELEVISION, |
| 2122 | 2122 | .vmux = 0, |
| @@ -2154,9 +2154,9 @@ static const struct cx88_board cx88_boards[] = { · 31 unmodified lines | ||
| 2154 | 2154 | [CX88_BOARD_WINFAST_DTV1800H] = { |
| 2155 | 2155 | .name = "Leadtek WinFast DTV1800 Hybrid", |
| 2156 | 2156 | .tuner_type = TUNER_XC2028, |
| 2157 | − .radio_type = TUNER_XC2028, | |
| 2157 | + .radio_type = UNSET, | |
| 2158 | 2158 | .tuner_addr = 0x61, |
| 2159 | − .radio_addr = 0x61, | |
| 2159 | + .radio_addr = ADDR_UNSET, | |
| 2160 | 2160 | /* |
| 2161 | 2161 | * GPIO setting |
| 2162 | 2162 | * |
| @@ -2195,9 +2195,9 @@ static const struct cx88_board cx88_boards[] = { · 32 unmodified lines | ||
| 2195 | 2195 | [CX88_BOARD_WINFAST_DTV1800H_XC4000] = { |
| 2196 | 2196 | .name = "Leadtek WinFast DTV1800 H (XC4000)", |
| 2197 | 2197 | .tuner_type = TUNER_XC4000, |
| 2198 | − .radio_type = TUNER_XC4000, | |
| 2198 | + .radio_type = UNSET, | |
| 2199 | 2199 | .tuner_addr = 0x61, |
| 2200 | − .radio_addr = 0x61, | |
| 2200 | + .radio_addr = ADDR_UNSET, | |
| 2201 | 2201 | /* |
| 2202 | 2202 | * GPIO setting |
| 2203 | 2203 | * |
| @@ -2236,9 +2236,9 @@ static const struct cx88_board cx88_boards[] = { · 32 unmodified lines | ||
| 2236 | 2236 | [CX88_BOARD_WINFAST_DTV2000H_PLUS] = { |
| 2237 | 2237 | .name = "Leadtek WinFast DTV2000 H PLUS", |
| 2238 | 2238 | .tuner_type = TUNER_XC4000, |
| 2239 | − .radio_type = TUNER_XC4000, | |
| 2239 | + .radio_type = UNSET, | |
| 2240 | 2240 | .tuner_addr = 0x61, |
| 2241 | − .radio_addr = 0x61, | |
| 2241 | + .radio_addr = ADDR_UNSET, | |
| 2242 | 2242 | /* |
| 2243 | 2243 | * GPIO |
| 2244 | 2244 | * 2: 1: mute audio |
| @@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) · 730 unmodified lines | ||
| 731 | 731 | |
| 732 | 732 | init_kthread_work(&itv->irq_work, ivtv_irq_work_handler); |
| 733 | 733 | |
| 734 | − /* start counting open_id at 1 */ | |
| 735 | − itv->open_id = 1; | |
| 736 | − | |
| 737 | 734 | /* Initial settings */ |
| 738 | 735 | itv->cxhdl.port = CX2341X_PORT_MEMORY; |
| 739 | 736 | itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI; |
| @@ -332,7 +332,7 @@ struct ivtv_stream { · 331 unmodified lines | ||
| 332 | 332 | const char *name; /* name of the stream */ |
| 333 | 333 | int type; /* stream type */ |
| 334 | 334 | |
| 335 | − u32 id; | |
| 335 | + struct v4l2_fh *fh; /* pointer to the streaming filehandle */ | |
| 336 | 336 | spinlock_t qlock; /* locks access to the queues */ |
| 337 | 337 | unsigned long s_flags; /* status flags, see above */ |
| 338 | 338 | int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ |
| @@ -379,7 +379,6 @@ struct ivtv_stream { · 40 unmodified lines | ||
| 379 | 379 | |
| 380 | 380 | struct ivtv_open_id { |
| 381 | 381 | struct v4l2_fh fh; |
| 382 | − u32 open_id; /* unique ID for this file descriptor */ | |
| 383 | 382 | int type; /* stream type */ |
| 384 | 383 | int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ |
| 385 | 384 | struct ivtv *itv; |
| @@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type) · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { |
| 52 | 52 | /* someone already claimed this stream */ |
| 53 | − if (s->id == id->open_id) { | |
| 53 | + if (s->fh == &id->fh) { | |
| 54 | 54 | /* yes, this file descriptor did. So that's OK. */ |
| 55 | 55 | return 0; |
| 56 | 56 | } |
| 57 | − if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI || | |
| 57 | + if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI || | |
| 58 | 58 | type == IVTV_ENC_STREAM_TYPE_VBI)) { |
| 59 | 59 | /* VBI is handled already internally, now also assign |
| 60 | 60 | the file descriptor to this stream for external |
| 61 | 61 | reading of the stream. */ |
| 62 | − s->id = id->open_id; | |
| 62 | + s->fh = &id->fh; | |
| 63 | 63 | IVTV_DEBUG_INFO("Start Read VBI\n"); |
| 64 | 64 | return 0; |
| 65 | 65 | } |
| @@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type) · 1 unmodified line | ||
| 67 | 67 | IVTV_DEBUG_INFO("Stream %d is busy\n", type); |
| 68 | 68 | return -EBUSY; |
| 69 | 69 | } |
| 70 | − s->id = id->open_id; | |
| 70 | + s->fh = &id->fh; | |
| 71 | 71 | if (type == IVTV_DEC_STREAM_TYPE_VBI) { |
| 72 | 72 | /* Enable reinsertion interrupt */ |
| 73 | 73 | ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); |
| @@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s) · 30 unmodified lines | ||
| 104 | 104 | struct ivtv *itv = s->itv; |
| 105 | 105 | struct ivtv_stream *s_vbi; |
| 106 | 106 | |
| 107 | − s->id = -1; | |
| 107 | + s->fh = NULL; | |
| 108 | 108 | if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && |
| 109 | 109 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { |
| 110 | 110 | /* this stream is still in use internally */ |
| @@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s) · 25 unmodified lines | ||
| 136 | 136 | /* was already cleared */ |
| 137 | 137 | return; |
| 138 | 138 | } |
| 139 | − if (s_vbi->id != -1) { | |
| 139 | + if (s_vbi->fh) { | |
| 140 | 140 | /* VBI stream still claimed by a file descriptor */ |
| 141 | 141 | return; |
| 142 | 142 | } |
| @@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, · 125 unmodified lines | ||
| 268 | 268 | } |
| 269 | 269 | |
| 270 | 270 | /* wait for more data to arrive */ |
| 271 | + mutex_unlock(&itv->serialize_lock); | |
| 271 | 272 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
| 272 | 273 | /* New buffers might have become available before we were added to the waitqueue */ |
| 273 | 274 | if (!s->q_full.buffers) |
| 274 | 275 | schedule(); |
| 275 | 276 | finish_wait(&s->waitq, &wait); |
| 277 | + mutex_lock(&itv->serialize_lock); | |
| 276 | 278 | if (signal_pending(current)) { |
| 277 | 279 | /* return if a signal was received */ |
| 278 | 280 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); |
| @@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co · 78 unmodified lines | ||
| 357 | 359 | size_t tot_written = 0; |
| 358 | 360 | int single_frame = 0; |
| 359 | 361 | |
| 360 | − if (atomic_read(&itv->capturing) == 0 && s->id == -1) { | |
| 362 | + if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) { | |
| 361 | 363 | /* shouldn't happen */ |
| 362 | 364 | IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); |
| 363 | 365 | return -EIO; |
| @@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ · 143 unmodified lines | ||
| 507 | 509 | |
| 508 | 510 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); |
| 509 | 511 | |
| 510 | − mutex_lock(&itv->serialize_lock); | |
| 511 | 512 | rc = ivtv_start_capture(id); |
| 512 | − mutex_unlock(&itv->serialize_lock); | |
| 513 | 513 | if (rc) |
| 514 | 514 | return rc; |
| 515 | 515 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); |
| @@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c · 68 unmodified lines | ||
| 584 | 584 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
| 585 | 585 | |
| 586 | 586 | /* Start decoder (returns 0 if already started) */ |
| 587 | − mutex_lock(&itv->serialize_lock); | |
| 588 | 587 | rc = ivtv_start_decoding(id, itv->speed); |
| 589 | − mutex_unlock(&itv->serialize_lock); | |
| 590 | 588 | if (rc) { |
| 591 | 589 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); |
| 592 | 590 | |
| @@ -627,11 +625,13 @@ retry: · 34 unmodified lines | ||
| 627 | 625 | break; |
| 628 | 626 | if (filp->f_flags & O_NONBLOCK) |
| 629 | 627 | return -EAGAIN; |
| 628 | + mutex_unlock(&itv->serialize_lock); | |
| 630 | 629 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
| 631 | 630 | /* New buffers might have become free before we were added to the waitqueue */ |
| 632 | 631 | if (!s->q_free.buffers) |
| 633 | 632 | schedule(); |
| 634 | 633 | finish_wait(&s->waitq, &wait); |
| 634 | + mutex_lock(&itv->serialize_lock); | |
| 635 | 635 | if (signal_pending(current)) { |
| 636 | 636 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); |
| 637 | 637 | return -EINTR; |
| @@ -686,12 +686,14 @@ retry: · 48 unmodified lines | ||
| 686 | 686 | if (mode == OUT_YUV) |
| 687 | 687 | ivtv_yuv_setup_stream_frame(itv); |
| 688 | 688 | |
| 689 | + mutex_unlock(&itv->serialize_lock); | |
| 689 | 690 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
| 690 | 691 | while (!(got_sig = signal_pending(current)) && |
| 691 | 692 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { |
| 692 | 693 | schedule(); |
| 693 | 694 | } |
| 694 | 695 | finish_wait(&itv->dma_waitq, &wait); |
| 696 | + mutex_lock(&itv->serialize_lock); | |
| 695 | 697 | if (got_sig) { |
| 696 | 698 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); |
| 697 | 699 | return -EINTR; |
| @@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) · 58 unmodified lines | ||
| 756 | 758 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
| 757 | 759 | int rc; |
| 758 | 760 | |
| 759 | − mutex_lock(&itv->serialize_lock); | |
| 760 | 761 | rc = ivtv_start_capture(id); |
| 761 | − mutex_unlock(&itv->serialize_lock); | |
| 762 | 762 | if (rc) { |
| 763 | 763 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", |
| 764 | 764 | s->name, rc); |
| @@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) · 43 unmodified lines | ||
| 808 | 808 | id->type == IVTV_ENC_STREAM_TYPE_VBI) && |
| 809 | 809 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { |
| 810 | 810 | /* Also used internally, don't stop capturing */ |
| 811 | − s->id = -1; | |
| 811 | + s->fh = NULL; | |
| 812 | 812 | } |
| 813 | 813 | else { |
| 814 | 814 | ivtv_stop_v4l2_encode_stream(s, gop_end); |
| @@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp) · 46 unmodified lines | ||
| 861 | 861 | |
| 862 | 862 | IVTV_DEBUG_FILE("close %s\n", s->name); |
| 863 | 863 | |
| 864 | − v4l2_fh_del(fh); | |
| 865 | − v4l2_fh_exit(fh); | |
| 866 | − | |
| 867 | − /* Easy case first: this stream was never claimed by us */ | |
| 868 | − if (s->id != id->open_id) { | |
| 869 | − kfree(id); | |
| 870 | − return 0; | |
| 871 | − } | |
| 872 | − | |
| 873 | − /* 'Unclaim' this stream */ | |
| 874 | − | |
| 875 | 864 | /* Stop radio */ |
| 876 | − mutex_lock(&itv->serialize_lock); | |
| 877 | − if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { | |
| 865 | + if (id->type == IVTV_ENC_STREAM_TYPE_RAD && | |
| 866 | + v4l2_fh_is_singular_file(filp)) { | |
| 878 | 867 | /* Closing radio device, return to TV mode */ |
| 879 | 868 | ivtv_mute(itv); |
| 880 | 869 | /* Mark that the radio is no longer in use */ |
| @@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp) · 9 unmodified lines | ||
| 890 | 879 | if (atomic_read(&itv->capturing) > 0) { |
| 891 | 880 | /* Undo video mute */ |
| 892 | 881 | ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, |
| 893 | − v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) | | |
| 894 | − (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); | |
| 882 | + v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) | | |
| 883 | + (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); | |
| 895 | 884 | } |
| 896 | 885 | /* Done! Unmute and continue. */ |
| 897 | 886 | ivtv_unmute(itv); |
| 898 | − ivtv_release_stream(s); | |
| 899 | − } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | |
| 887 | + } | |
| 888 | + | |
| 889 | + v4l2_fh_del(fh); | |
| 890 | + v4l2_fh_exit(fh); | |
| 891 | + | |
| 892 | + /* Easy case first: this stream was never claimed by us */ | |
| 893 | + if (s->fh != &id->fh) { | |
| 894 | + kfree(id); | |
| 895 | + return 0; | |
| 896 | + } | |
| 897 | + | |
| 898 | + /* 'Unclaim' this stream */ | |
| 899 | + | |
| 900 | + if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | |
| 900 | 901 | struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; |
| 901 | 902 | |
| 902 | 903 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); |
| @@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp) · 8 unmodified lines | ||
| 911 | 912 | ivtv_stop_capture(id, 0); |
| 912 | 913 | } |
| 913 | 914 | kfree(id); |
| 914 | − mutex_unlock(&itv->serialize_lock); | |
| 915 | 915 | return 0; |
| 916 | 916 | } |
| 917 | 917 | |
| 918 | −static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |
| 918 | +int ivtv_v4l2_open(struct file *filp) | |
| 919 | 919 | { |
| 920 | −#ifdef CONFIG_VIDEO_ADV_DEBUG | |
| 921 | 920 | struct video_device *vdev = video_devdata(filp); |
| 922 | −#endif | |
| 921 | + struct ivtv_stream *s = video_get_drvdata(vdev); | |
| 923 | 922 | struct ivtv *itv = s->itv; |
| 924 | 923 | struct ivtv_open_id *item; |
| 925 | 924 | int res = 0; |
| 926 | 925 | |
| 927 | 926 | IVTV_DEBUG_FILE("open %s\n", s->name); |
| 928 | 927 | |
| 928 | + if (ivtv_init_on_first_open(itv)) { | |
| 929 | + IVTV_ERR("Failed to initialize on device %s\n", | |
| 930 | + video_device_node_name(vdev)); | |
| 931 | + return -ENXIO; | |
| 932 | + } | |
| 933 | + | |
| 929 | 934 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
| 930 | 935 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ |
| 931 | 936 | if (ivtv_fw_debug) { |
| @@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) · 34 unmodified lines | ||
| 966 | 971 | return -ENOMEM; |
| 967 | 972 | } |
| 968 | 973 | v4l2_fh_init(&item->fh, s->vdev); |
| 969 | − if (res < 0) { | |
| 970 | − v4l2_fh_exit(&item->fh); | |
| 971 | − kfree(item); | |
| 972 | − return res; | |
| 973 | − } | |
| 974 | 974 | item->itv = itv; |
| 975 | 975 | item->type = s->type; |
| 976 | 976 | |
| 977 | − item->open_id = itv->open_id++; | |
| 978 | 977 | filp->private_data = &item->fh; |
| 978 | + v4l2_fh_add(&item->fh); | |
| 979 | 979 | |
| 980 | − if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { | |
| 981 | − /* Try to claim this stream */ | |
| 982 | − if (ivtv_claim_stream(item, item->type)) { | |
| 983 | − /* No, it's already in use */ | |
| 984 | − v4l2_fh_exit(&item->fh); | |
| 985 | − kfree(item); | |
| 986 | − return -EBUSY; | |
| 987 | − } | |
| 988 | − | |
| 980 | + if (item->type == IVTV_ENC_STREAM_TYPE_RAD && | |
| 981 | + v4l2_fh_is_singular_file(filp)) { | |
| 989 | 982 | if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { |
| 990 | 983 | if (atomic_read(&itv->capturing) > 0) { |
| 991 | 984 | /* switching to radio while capture is |
| 992 | 985 | in progress is not polite */ |
| 993 | − ivtv_release_stream(s); | |
| 986 | + v4l2_fh_del(&item->fh); | |
| 994 | 987 | v4l2_fh_exit(&item->fh); |
| 995 | 988 | kfree(item); |
| 996 | 989 | return -EBUSY; |
| @@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) · 25 unmodified lines | ||
| 1022 | 1015 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
| 1023 | 1016 | itv->yuv_info.stream_size = 0; |
| 1024 | 1017 | } |
| 1025 | − v4l2_fh_add(&item->fh); | |
| 1026 | 1018 | return 0; |
| 1027 | 1019 | } |
| 1028 | 1020 | |
| 1029 | −int ivtv_v4l2_open(struct file *filp) | |
| 1030 | −{ | |
| 1031 | − int res; | |
| 1032 | − struct ivtv *itv = NULL; | |
| 1033 | − struct ivtv_stream *s = NULL; | |
| 1034 | − struct video_device *vdev = video_devdata(filp); | |
| 1035 | − | |
| 1036 | − s = video_get_drvdata(vdev); | |
| 1037 | − itv = s->itv; | |
| 1038 | − | |
| 1039 | − mutex_lock(&itv->serialize_lock); | |
| 1040 | − if (ivtv_init_on_first_open(itv)) { | |
| 1041 | − IVTV_ERR("Failed to initialize on device %s\n", | |
| 1042 | − video_device_node_name(vdev)); | |
| 1043 | − mutex_unlock(&itv->serialize_lock); | |
| 1044 | − return -ENXIO; | |
| 1045 | − } | |
| 1046 | − res = ivtv_serialized_open(s, filp); | |
| 1047 | − mutex_unlock(&itv->serialize_lock); | |
| 1048 | − return res; | |
| 1049 | −} | |
| 1050 | − | |
| 1051 | 1021 | void ivtv_mute(struct ivtv *itv) |
| 1052 | 1022 | { |
| 1053 | 1023 | if (atomic_read(&itv->capturing)) |
| @@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) · 178 unmodified lines | ||
| 179 | 179 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); |
| 180 | 180 | |
| 181 | 181 | /* Wait for any DMA to finish */ |
| 182 | + mutex_unlock(&itv->serialize_lock); | |
| 182 | 183 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
| 183 | 184 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { |
| 184 | 185 | got_sig = signal_pending(current); |
| @@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) · 3 unmodified lines | ||
| 188 | 189 | schedule(); |
| 189 | 190 | } |
| 190 | 191 | finish_wait(&itv->dma_waitq, &wait); |
| 192 | + mutex_lock(&itv->serialize_lock); | |
| 191 | 193 | if (got_sig) |
| 192 | 194 | return -EINTR; |
| 193 | 195 | |
| @@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) · 913 unmodified lines | ||
| 1107 | 1109 | * happens within the first 100 lines of the top field. |
| 1108 | 1110 | * Make 4 attempts to sync to the decoder before giving up. |
| 1109 | 1111 | */ |
| 1112 | + mutex_unlock(&itv->serialize_lock); | |
| 1110 | 1113 | for (f = 0; f < 4; f++) { |
| 1111 | 1114 | prepare_to_wait(&itv->vsync_waitq, &wait, |
| 1112 | 1115 | TASK_UNINTERRUPTIBLE); |
| @@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) · 2 unmodified lines | ||
| 1115 | 1118 | schedule_timeout(msecs_to_jiffies(25)); |
| 1116 | 1119 | } |
| 1117 | 1120 | finish_wait(&itv->vsync_waitq, &wait); |
| 1121 | + mutex_lock(&itv->serialize_lock); | |
| 1118 | 1122 | |
| 1119 | 1123 | if (f == 4) |
| 1120 | 1124 | IVTV_WARN("Mode change failed to sync to decoder\n"); |
| @@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, · 721 unmodified lines | ||
| 1842 | 1846 | return 0; |
| 1843 | 1847 | } |
| 1844 | 1848 | |
| 1845 | −static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |
| 1846 | − unsigned int cmd, unsigned long arg) | |
| 1849 | +long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |
| 1847 | 1850 | { |
| 1848 | 1851 | struct video_device *vfd = video_devdata(filp); |
| 1849 | 1852 | long ret; |
| @@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, · 5 unmodified lines | ||
| 1855 | 1858 | return ret; |
| 1856 | 1859 | } |
| 1857 | 1860 | |
| 1858 | −long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |
| 1859 | −{ | |
| 1860 | − struct ivtv_open_id *id = fh2id(filp->private_data); | |
| 1861 | − struct ivtv *itv = id->itv; | |
| 1862 | − long res; | |
| 1863 | − | |
| 1864 | − /* DQEVENT can block, so this should not run with the serialize lock */ | |
| 1865 | − if (cmd == VIDIOC_DQEVENT) | |
| 1866 | − return ivtv_serialized_ioctl(itv, filp, cmd, arg); | |
| 1867 | − mutex_lock(&itv->serialize_lock); | |
| 1868 | − res = ivtv_serialized_ioctl(itv, filp, cmd, arg); | |
| 1869 | − mutex_unlock(&itv->serialize_lock); | |
| 1870 | − return res; | |
| 1871 | −} | |
| 1872 | − | |
| 1873 | 1861 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { |
| 1874 | 1862 | .vidioc_querycap = ivtv_querycap, |
| 1875 | 1863 | .vidioc_s_audio = ivtv_s_audio, |
| @@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s) · 287 unmodified lines | ||
| 288 | 288 | ivtv_process_vbi_data(itv, buf, 0, s->type); |
| 289 | 289 | s->q_dma.bytesused += buf->bytesused; |
| 290 | 290 | } |
| 291 | − if (s->id == -1) { | |
| 291 | + if (s->fh == NULL) { | |
| 292 | 292 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); |
| 293 | 293 | return; |
| 294 | 294 | } |
| 295 | 295 | } |
| 296 | 296 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); |
| 297 | − if (s->id != -1) | |
| 297 | + if (s->fh) | |
| 298 | 298 | wake_up(&s->waitq); |
| 299 | 299 | } |
| 300 | 300 | |
| @@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type) · 158 unmodified lines | ||
| 159 | 159 | s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size; |
| 160 | 160 | spin_lock_init(&s->qlock); |
| 161 | 161 | init_waitqueue_head(&s->waitq); |
| 162 | − s->id = -1; | |
| 163 | 162 | s->sg_handle = IVTV_DMA_UNMAPPED; |
| 164 | 163 | ivtv_queue_init(&s->q_free); |
| 165 | 164 | ivtv_queue_init(&s->q_full); |
| @@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) · 48 unmodified lines | ||
| 214 | 213 | s->vdev->fops = ivtv_stream_info[type].fops; |
| 215 | 214 | s->vdev->release = video_device_release; |
| 216 | 215 | s->vdev->tvnorms = V4L2_STD_ALL; |
| 216 | + s->vdev->lock = &itv->serialize_lock; | |
| 217 | 217 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); |
| 218 | 218 | ivtv_set_funcs(s->vdev); |
| 219 | 219 | return 0; |
| @@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) · 1148 unmodified lines | ||
| 1149 | 1149 | { |
| 1150 | 1150 | struct yuv_playback_info *yi = &itv->yuv_info; |
| 1151 | 1151 | struct ivtv_dma_frame dma_args; |
| 1152 | + int res; | |
| 1152 | 1153 | |
| 1153 | 1154 | ivtv_yuv_setup_stream_frame(itv); |
| 1154 | 1155 | |
| 1155 | 1156 | /* We only need to supply source addresses for this */ |
| 1156 | 1157 | dma_args.y_source = src; |
| 1157 | 1158 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); |
| 1158 | − return ivtv_yuv_udma_frame(itv, &dma_args); | |
| 1159 | + /* Wait for frame DMA. Note that serialize_lock is locked, | |
| 1160 | + so to allow other processes to access the driver while | |
| 1161 | + we are waiting unlock first and later lock again. */ | |
| 1162 | + mutex_unlock(&itv->serialize_lock); | |
| 1163 | + res = ivtv_yuv_udma_frame(itv, &dma_args); | |
| 1164 | + mutex_lock(&itv->serialize_lock); | |
| 1165 | + return res; | |
| 1159 | 1166 | } |
| 1160 | 1167 | |
| 1161 | 1168 | /* IVTV_IOC_DMA_FRAME ioctl handler */ |
| 1162 | 1169 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) |
| 1163 | 1170 | { |
| 1164 | −/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | |
| 1171 | + int res; | |
| 1165 | 1172 | |
| 1173 | +/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | |
| 1166 | 1174 | ivtv_yuv_next_free(itv); |
| 1167 | 1175 | ivtv_yuv_setup_frame(itv, args); |
| 1168 | − return ivtv_yuv_udma_frame(itv, args); | |
| 1176 | + /* Wait for frame DMA. Note that serialize_lock is locked, | |
| 1177 | + so to allow other processes to access the driver while | |
| 1178 | + we are waiting unlock first and later lock again. */ | |
| 1179 | + mutex_unlock(&itv->serialize_lock); | |
| 1180 | + res = ivtv_yuv_udma_frame(itv, args); | |
| 1181 | + mutex_lock(&itv->serialize_lock); | |
| 1182 | + return res; | |
| 1169 | 1183 | } |
| 1170 | 1184 | |
| 1171 | 1185 | void ivtv_yuv_close(struct ivtv *itv) |
| @@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv) · 2 unmodified lines | ||
| 1174 | 1188 | int h_filter, v_filter_1, v_filter_2; |
| 1175 | 1189 | |
| 1176 | 1190 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); |
| 1191 | + mutex_unlock(&itv->serialize_lock); | |
| 1177 | 1192 | ivtv_waitq(&itv->vsync_waitq); |
| 1193 | + mutex_lock(&itv->serialize_lock); | |
| 1178 | 1194 | |
| 1179 | 1195 | yi->running = 0; |
| 1180 | 1196 | atomic_set(&yi->next_dma_frame, -1); |
| @@ -1042,7 +1042,8 @@ static int vidioc_querycap(struct file *file, void *fh, · 1041 unmodified lines | ||
| 1042 | 1042 | strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); |
| 1043 | 1043 | strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); |
| 1044 | 1044 | cap->bus_info[0] = '\0'; |
| 1045 | − cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; | |
| 1045 | + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | | |
| 1046 | + V4L2_CAP_VIDEO_OUTPUT_OVERLAY; | |
| 1046 | 1047 | |
| 1047 | 1048 | return 0; |
| 1048 | 1049 | } |
| @@ -1825,7 +1826,9 @@ static int vidioc_g_fbuf(struct file *file, void *fh, · 776 unmodified lines | ||
| 1825 | 1826 | ovid = &vout->vid_info; |
| 1826 | 1827 | ovl = ovid->overlays[0]; |
| 1827 | 1828 | |
| 1828 | − a->flags = 0x0; | |
| 1829 | + /* The video overlay must stay within the framebuffer and can't be | |
| 1830 | + positioned independently. */ | |
| 1831 | + a->flags = V4L2_FBUF_FLAG_OVERLAY; | |
| 1829 | 1832 | a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY |
| 1830 | 1833 | | V4L2_FBUF_CAP_SRC_CHROMAKEY; |
| 1831 | 1834 | |
| @@ -104,47 +104,16 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = · 103 unmodified lines | ||
| 104 | 104 | |
| 105 | 105 | /****************************************************************************/ |
| 106 | 106 | |
| 107 | −static int _send_control_msg(struct pwc_device *pdev, | |
| 108 | − u8 request, u16 value, int index, void *buf, int buflen) | |
| 109 | −{ | |
| 110 | − int rc; | |
| 111 | − void *kbuf = NULL; | |
| 112 | − | |
| 113 | − if (buflen) { | |
| 114 | − kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */ | |
| 115 | − if (kbuf == NULL) | |
| 116 | − return -ENOMEM; | |
| 117 | − } | |
| 118 | − | |
| 119 | − rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | |
| 120 | − request, | |
| 121 | − USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 122 | − value, | |
| 123 | − index, | |
| 124 | − kbuf, buflen, USB_CTRL_SET_TIMEOUT); | |
| 125 | − | |
| 126 | − kfree(kbuf); | |
| 127 | − return rc; | |
| 128 | −} | |
| 129 | − | |
| 130 | 107 | static int recv_control_msg(struct pwc_device *pdev, |
| 131 | − u8 request, u16 value, void *buf, int buflen) | |
| 108 | + u8 request, u16 value, int recv_count) | |
| 132 | 109 | { |
| 133 | 110 | int rc; |
| 134 | − void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ | |
| 135 | − | |
| 136 | − if (kbuf == NULL) | |
| 137 | − return -ENOMEM; | |
| 138 | 111 | |
| 139 | 112 | rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), |
| 140 | 113 | request, |
| 141 | 114 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 142 | − value, | |
| 143 | − pdev->vcinterface, | |
| 144 | − kbuf, buflen, USB_CTRL_GET_TIMEOUT); | |
| 145 | − memcpy(buf, kbuf, buflen); | |
| 146 | − kfree(kbuf); | |
| 147 | − | |
| 115 | + value, pdev->vcinterface, | |
| 116 | + pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT); | |
| 148 | 117 | if (rc < 0) |
| 149 | 118 | PWC_ERROR("recv_control_msg error %d req %02x val %04x\n", |
| 150 | 119 | rc, request, value); |
| @@ -152,27 +121,39 @@ static int recv_control_msg(struct pwc_device *pdev, · 1 unmodified line | ||
| 152 | 121 | } |
| 153 | 122 | |
| 154 | 123 | static inline int send_video_command(struct pwc_device *pdev, |
| 155 | − int index, void *buf, int buflen) | |
| 124 | + int index, const unsigned char *buf, int buflen) | |
| 156 | 125 | { |
| 157 | − return _send_control_msg(pdev, | |
| 158 | − SET_EP_STREAM_CTL, | |
| 159 | − VIDEO_OUTPUT_CONTROL_FORMATTER, | |
| 160 | − index, | |
| 161 | − buf, buflen); | |
| 126 | + int rc; | |
| 127 | + | |
| 128 | + memcpy(pdev->ctrl_buf, buf, buflen); | |
| 129 | + | |
| 130 | + rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | |
| 131 | + SET_EP_STREAM_CTL, | |
| 132 | + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 133 | + VIDEO_OUTPUT_CONTROL_FORMATTER, index, | |
| 134 | + pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT); | |
| 135 | + if (rc >= 0) | |
| 136 | + memcpy(pdev->cmd_buf, buf, buflen); | |
| 137 | + else | |
| 138 | + PWC_ERROR("send_video_command error %d\n", rc); | |
| 139 | + | |
| 140 | + return rc; | |
| 162 | 141 | } |
| 163 | 142 | |
| 164 | 143 | int send_control_msg(struct pwc_device *pdev, |
| 165 | 144 | u8 request, u16 value, void *buf, int buflen) |
| 166 | 145 | { |
| 167 | − return _send_control_msg(pdev, | |
| 168 | − request, value, pdev->vcinterface, buf, buflen); | |
| 146 | + return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | |
| 147 | + request, | |
| 148 | + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
| 149 | + value, pdev->vcinterface, | |
| 150 | + buf, buflen, USB_CTRL_SET_TIMEOUT); | |
| 169 | 151 | } |
| 170 | 152 | |
| 171 | −static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames, | |
| 172 | − int *compression) | |
| 153 | +static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt, | |
| 154 | + int frames, int *compression, int send_to_cam) | |
| 173 | 155 | { |
| 174 | − unsigned char buf[3]; | |
| 175 | − int ret, fps; | |
| 156 | + int fps, ret = 0; | |
| 176 | 157 | struct Nala_table_entry *pEntry; |
| 177 | 158 | int frames2frames[31] = |
| 178 | 159 | { /* closest match of framerate */ |
| @@ -194,30 +175,29 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames, · 15 unmodified lines | ||
| 194 | 175 | 7 /* 30 */ |
| 195 | 176 | }; |
| 196 | 177 | |
| 197 | − if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) | |
| 178 | + if (size < 0 || size > PSZ_CIF) | |
| 198 | 179 | return -EINVAL; |
| 180 | + if (frames < 4) | |
| 181 | + frames = 4; | |
| 182 | + else if (frames > 25) | |
| 183 | + frames = 25; | |
| 199 | 184 | frames = frames2frames[frames]; |
| 200 | 185 | fps = frames2table[frames]; |
| 201 | 186 | pEntry = &Nala_table[size][fps]; |
| 202 | 187 | if (pEntry->alternate == 0) |
| 203 | 188 | return -EINVAL; |
| 204 | 189 | |
| 205 | − memcpy(buf, pEntry->mode, 3); | |
| 206 | − ret = send_video_command(pdev, pdev->vendpoint, buf, 3); | |
| 207 | − if (ret < 0) { | |
| 208 | − PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); | |
| 190 | + if (send_to_cam) | |
| 191 | + ret = send_video_command(pdev, pdev->vendpoint, | |
| 192 | + pEntry->mode, 3); | |
| 193 | + if (ret < 0) | |
| 209 | 194 | return ret; |
| 210 | − } | |
| 211 | − if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) { | |
| 212 | − ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf); | |
| 213 | − if (ret < 0) | |
| 214 | − return ret; | |
| 215 | − } | |
| 216 | 195 | |
| 217 | − pdev->cmd_len = 3; | |
| 218 | − memcpy(pdev->cmd_buf, buf, 3); | |
| 196 | + if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420) | |
| 197 | + pwc_dec1_init(pdev, pEntry->mode); | |
| 219 | 198 | |
| 220 | 199 | /* Set various parameters */ |
| 200 | + pdev->pixfmt = pixfmt; | |
| 221 | 201 | pdev->vframes = frames; |
| 222 | 202 | pdev->valternate = pEntry->alternate; |
| 223 | 203 | pdev->width = pwc_image_sizes[size][0]; |
| @@ -243,18 +223,20 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames, · 19 unmodified lines | ||
| 243 | 223 | } |
| 244 | 224 | |
| 245 | 225 | |
| 246 | −static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, | |
| 247 | − int *compression) | |
| 226 | +static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, | |
| 227 | + int frames, int *compression, int send_to_cam) | |
| 248 | 228 | { |
| 249 | − unsigned char buf[13]; | |
| 250 | 229 | const struct Timon_table_entry *pChoose; |
| 251 | − int ret, fps; | |
| 230 | + int fps, ret = 0; | |
| 252 | 231 | |
| 253 | − if (size >= PSZ_MAX || frames < 5 || frames > 30 || | |
| 254 | − *compression < 0 || *compression > 3) | |
| 255 | − return -EINVAL; | |
| 256 | − if (size == PSZ_VGA && frames > 15) | |
| 232 | + if (size >= PSZ_MAX || *compression < 0 || *compression > 3) | |
| 257 | 233 | return -EINVAL; |
| 234 | + if (frames < 5) | |
| 235 | + frames = 5; | |
| 236 | + else if (size == PSZ_VGA && frames > 15) | |
| 237 | + frames = 15; | |
| 238 | + else if (frames > 30) | |
| 239 | + frames = 30; | |
| 258 | 240 | fps = (frames / 5) - 1; |
| 259 | 241 | |
| 260 | 242 | /* Find a supported framerate with progressively higher compression */ |
| @@ -268,22 +250,18 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, · 7 unmodified lines | ||
| 268 | 250 | if (pChoose == NULL || pChoose->alternate == 0) |
| 269 | 251 | return -ENOENT; /* Not supported. */ |
| 270 | 252 | |
| 271 | − memcpy(buf, pChoose->mode, 13); | |
| 272 | − ret = send_video_command(pdev, pdev->vendpoint, buf, 13); | |
| 253 | + if (send_to_cam) | |
| 254 | + ret = send_video_command(pdev, pdev->vendpoint, | |
| 255 | + pChoose->mode, 13); | |
| 273 | 256 | if (ret < 0) |
| 274 | 257 | return ret; |
| 275 | 258 | |
| 276 | − if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) { | |
| 277 | − ret = pwc_dec23_init(pdev, pdev->type, buf); | |
| 278 | − if (ret < 0) | |
| 279 | − return ret; | |
| 280 | − } | |
| 281 | − | |
| 282 | − pdev->cmd_len = 13; | |
| 283 | − memcpy(pdev->cmd_buf, buf, 13); | |
| 259 | + if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) | |
| 260 | + pwc_dec23_init(pdev, pChoose->mode); | |
| 284 | 261 | |
| 285 | 262 | /* Set various parameters */ |
| 286 | − pdev->vframes = frames; | |
| 263 | + pdev->pixfmt = pixfmt; | |
| 264 | + pdev->vframes = (fps + 1) * 5; | |
| 287 | 265 | pdev->valternate = pChoose->alternate; |
| 288 | 266 | pdev->width = pwc_image_sizes[size][0]; |
| 289 | 267 | pdev->height = pwc_image_sizes[size][1]; |
| @@ -296,18 +274,20 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, · 6 unmodified lines | ||
| 296 | 274 | } |
| 297 | 275 | |
| 298 | 276 | |
| 299 | −static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, | |
| 300 | − int *compression) | |
| 277 | +static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, | |
| 278 | + int frames, int *compression, int send_to_cam) | |
| 301 | 279 | { |
| 302 | 280 | const struct Kiara_table_entry *pChoose = NULL; |
| 303 | − int fps, ret; | |
| 304 | − unsigned char buf[12]; | |
| 281 | + int fps, ret = 0; | |
| 305 | 282 | |
| 306 | − if (size >= PSZ_MAX || frames < 5 || frames > 30 || | |
| 307 | − *compression < 0 || *compression > 3) | |
| 308 | − return -EINVAL; | |
| 309 | − if (size == PSZ_VGA && frames > 15) | |
| 283 | + if (size >= PSZ_MAX || *compression < 0 || *compression > 3) | |
| 310 | 284 | return -EINVAL; |
| 285 | + if (frames < 5) | |
| 286 | + frames = 5; | |
| 287 | + else if (size == PSZ_VGA && frames > 15) | |
| 288 | + frames = 15; | |
| 289 | + else if (frames > 30) | |
| 290 | + frames = 30; | |
| 311 | 291 | fps = (frames / 5) - 1; |
| 312 | 292 | |
| 313 | 293 | /* Find a supported framerate with progressively higher compression */ |
| @@ -320,26 +300,18 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, · 6 unmodified lines | ||
| 320 | 300 | if (pChoose == NULL || pChoose->alternate == 0) |
| 321 | 301 | return -ENOENT; /* Not supported. */ |
| 322 | 302 | |
| 323 | − PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate); | |
| 324 | − | |
| 325 | − /* usb_control_msg won't take staticly allocated arrays as argument?? */ | |
| 326 | − memcpy(buf, pChoose->mode, 12); | |
| 327 | − | |
| 328 | 303 | /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ |
| 329 | − ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12); | |
| 304 | + if (send_to_cam) | |
| 305 | + ret = send_video_command(pdev, 4, pChoose->mode, 12); | |
| 330 | 306 | if (ret < 0) |
| 331 | 307 | return ret; |
| 332 | 308 | |
| 333 | − if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) { | |
| 334 | − ret = pwc_dec23_init(pdev, pdev->type, buf); | |
| 335 | − if (ret < 0) | |
| 336 | − return ret; | |
| 337 | − } | |
| 309 | + if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) | |
| 310 | + pwc_dec23_init(pdev, pChoose->mode); | |
| 338 | 311 | |
| 339 | − pdev->cmd_len = 12; | |
| 340 | − memcpy(pdev->cmd_buf, buf, 12); | |
| 341 | 312 | /* All set and go */ |
| 342 | − pdev->vframes = frames; | |
| 313 | + pdev->pixfmt = pixfmt; | |
| 314 | + pdev->vframes = (fps + 1) * 5; | |
| 343 | 315 | pdev->valternate = pChoose->alternate; |
| 344 | 316 | pdev->width = pwc_image_sizes[size][0]; |
| 345 | 317 | pdev->height = pwc_image_sizes[size][1]; |
| @@ -354,22 +326,24 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, · 8 unmodified lines | ||
| 354 | 326 | } |
| 355 | 327 | |
| 356 | 328 | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, |
| 357 | − int frames, int *compression) | |
| 329 | + int pixfmt, int frames, int *compression, int send_to_cam) | |
| 358 | 330 | { |
| 359 | 331 | int ret, size; |
| 360 | 332 | |
| 361 | − PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); | |
| 333 | + PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", | |
| 334 | + width, height, frames, pixfmt); | |
| 362 | 335 | size = pwc_get_size(pdev, width, height); |
| 363 | 336 | PWC_TRACE("decode_size = %d.\n", size); |
| 364 | 337 | |
| 365 | 338 | if (DEVICE_USE_CODEC1(pdev->type)) { |
| 366 | − ret = set_video_mode_Nala(pdev, size, frames, compression); | |
| 367 | − | |
| 339 | + ret = set_video_mode_Nala(pdev, size, pixfmt, frames, | |
| 340 | + compression, send_to_cam); | |
| 368 | 341 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
| 369 | − ret = set_video_mode_Kiara(pdev, size, frames, compression); | |
| 370 | − | |
| 342 | + ret = set_video_mode_Kiara(pdev, size, pixfmt, frames, | |
| 343 | + compression, send_to_cam); | |
| 371 | 344 | } else { |
| 372 | − ret = set_video_mode_Timon(pdev, size, frames, compression); | |
| 345 | + ret = set_video_mode_Timon(pdev, size, pixfmt, frames, | |
| 346 | + compression, send_to_cam); | |
| 373 | 347 | } |
| 374 | 348 | if (ret < 0) { |
| 375 | 349 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); |
| @@ -436,13 +410,12 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i · 60 unmodified lines | ||
| 436 | 410 | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) |
| 437 | 411 | { |
| 438 | 412 | int ret; |
| 439 | − u8 buf; | |
| 440 | 413 | |
| 441 | − ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf)); | |
| 414 | + ret = recv_control_msg(pdev, request, value, 1); | |
| 442 | 415 | if (ret < 0) |
| 443 | 416 | return ret; |
| 444 | 417 | |
| 445 | − *data = buf; | |
| 418 | + *data = pdev->ctrl_buf[0]; | |
| 446 | 419 | return 0; |
| 447 | 420 | } |
| 448 | 421 | |
| @@ -450,7 +423,8 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data) · 1 unmodified line | ||
| 450 | 423 | { |
| 451 | 424 | int ret; |
| 452 | 425 | |
| 453 | − ret = send_control_msg(pdev, request, value, &data, sizeof(data)); | |
| 426 | + pdev->ctrl_buf[0] = data; | |
| 427 | + ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1); | |
| 454 | 428 | if (ret < 0) |
| 455 | 429 | return ret; |
| 456 | 430 | |
| @@ -460,37 +434,34 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data) · 3 unmodified lines | ||
| 460 | 434 | int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) |
| 461 | 435 | { |
| 462 | 436 | int ret; |
| 463 | − s8 buf; | |
| 464 | 437 | |
| 465 | − ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf)); | |
| 438 | + ret = recv_control_msg(pdev, request, value, 1); | |
| 466 | 439 | if (ret < 0) |
| 467 | 440 | return ret; |
| 468 | 441 | |
| 469 | − *data = buf; | |
| 442 | + *data = ((s8 *)pdev->ctrl_buf)[0]; | |
| 470 | 443 | return 0; |
| 471 | 444 | } |
| 472 | 445 | |
| 473 | 446 | int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) |
| 474 | 447 | { |
| 475 | 448 | int ret; |
| 476 | − u8 buf[2]; | |
| 477 | 449 | |
| 478 | − ret = recv_control_msg(pdev, request, value, buf, sizeof(buf)); | |
| 450 | + ret = recv_control_msg(pdev, request, value, 2); | |
| 479 | 451 | if (ret < 0) |
| 480 | 452 | return ret; |
| 481 | 453 | |
| 482 | − *data = (buf[1] << 8) | buf[0]; | |
| 454 | + *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0]; | |
| 483 | 455 | return 0; |
| 484 | 456 | } |
| 485 | 457 | |
| 486 | 458 | int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data) |
| 487 | 459 | { |
| 488 | 460 | int ret; |
| 489 | − u8 buf[2]; | |
| 490 | 461 | |
| 491 | − buf[0] = data & 0xff; | |
| 492 | − buf[1] = data >> 8; | |
| 493 | − ret = send_control_msg(pdev, request, value, buf, sizeof(buf)); | |
| 462 | + pdev->ctrl_buf[0] = data & 0xff; | |
| 463 | + pdev->ctrl_buf[1] = data >> 8; | |
| 464 | + ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2); | |
| 494 | 465 | if (ret < 0) |
| 495 | 466 | return ret; |
| 496 | 467 | |
| @@ -511,7 +482,6 @@ int pwc_button_ctrl(struct pwc_device *pdev, u16 value) · 14 unmodified lines | ||
| 511 | 482 | /* POWER */ |
| 512 | 483 | void pwc_camera_power(struct pwc_device *pdev, int power) |
| 513 | 484 | { |
| 514 | − char buf; | |
| 515 | 485 | int r; |
| 516 | 486 | |
| 517 | 487 | if (!pdev->power_save) |
| @@ -521,13 +491,11 @@ void pwc_camera_power(struct pwc_device *pdev, int power) · 3 unmodified lines | ||
| 521 | 491 | return; /* Not supported by Nala or Timon < release 6 */ |
| 522 | 492 | |
| 523 | 493 | if (power) |
| 524 | − buf = 0x00; /* active */ | |
| 494 | + pdev->ctrl_buf[0] = 0x00; /* active */ | |
| 525 | 495 | else |
| 526 | − buf = 0xFF; /* power save */ | |
| 527 | − r = send_control_msg(pdev, | |
| 528 | − SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, | |
| 529 | − &buf, sizeof(buf)); | |
| 530 | − | |
| 496 | + pdev->ctrl_buf[0] = 0xFF; /* power save */ | |
| 497 | + r = send_control_msg(pdev, SET_STATUS_CTL, | |
| 498 | + SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1); | |
| 531 | 499 | if (r < 0) |
| 532 | 500 | PWC_ERROR("Failed to power %s camera (%d)\n", |
| 533 | 501 | power ? "on" : "off", r); |
| @@ -535,7 +503,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power) · 1 unmodified line | ||
| 535 | 503 | |
| 536 | 504 | int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) |
| 537 | 505 | { |
| 538 | − unsigned char buf[2]; | |
| 539 | 506 | int r; |
| 540 | 507 | |
| 541 | 508 | if (pdev->type < 730) |
| @@ -551,11 +518,11 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) · 9 unmodified lines | ||
| 551 | 518 | if (off_value > 0xff) |
| 552 | 519 | off_value = 0xff; |
| 553 | 520 | |
| 554 | − buf[0] = on_value; | |
| 555 | − buf[1] = off_value; | |
| 521 | + pdev->ctrl_buf[0] = on_value; | |
| 522 | + pdev->ctrl_buf[1] = off_value; | |
| 556 | 523 | |
| 557 | 524 | r = send_control_msg(pdev, |
| 558 | − SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); | |
| 525 | + SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2); | |
| 559 | 526 | if (r < 0) |
| 560 | 527 | PWC_ERROR("Failed to set LED on/off time (%d)\n", r); |
| 561 | 528 | |
| @@ -565,7 +532,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) · 3 unmodified lines | ||
| 565 | 532 | #ifdef CONFIG_USB_PWC_DEBUG |
| 566 | 533 | int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) |
| 567 | 534 | { |
| 568 | − unsigned char buf; | |
| 569 | 535 | int ret = -1, request; |
| 570 | 536 | |
| 571 | 537 | if (pdev->type < 675) |
| @@ -575,14 +541,13 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) · 3 unmodified lines | ||
| 575 | 541 | else |
| 576 | 542 | request = SENSOR_TYPE_FORMATTER2; |
| 577 | 543 | |
| 578 | − ret = recv_control_msg(pdev, | |
| 579 | − GET_STATUS_CTL, request, &buf, sizeof(buf)); | |
| 544 | + ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1); | |
| 580 | 545 | if (ret < 0) |
| 581 | 546 | return ret; |
| 582 | 547 | if (pdev->type < 675) |
| 583 | − *sensor = buf | 0x100; | |
| 548 | + *sensor = pdev->ctrl_buf[0] | 0x100; | |
| 584 | 549 | else |
| 585 | − *sensor = buf; | |
| 550 | + *sensor = pdev->ctrl_buf[0]; | |
| 586 | 551 | return 0; |
| 587 | 552 | } |
| 588 | 553 | #endif |
| @@ -22,19 +22,11 @@ · 21 unmodified lines | ||
| 22 | 22 | along with this program; if not, write to the Free Software |
| 23 | 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 24 | 24 | */ |
| 25 | −#include "pwc-dec1.h" | |
| 25 | +#include "pwc.h" | |
| 26 | 26 | |
| 27 | −int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer) | |
| 27 | +void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd) | |
| 28 | 28 | { |
| 29 | − struct pwc_dec1_private *pdec; | |
| 29 | + struct pwc_dec1_private *pdec = &pdev->dec1; | |
| 30 | 30 | |
| 31 | − if (pwc->decompress_data == NULL) { | |
| 32 | − pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL); | |
| 33 | − if (pdec == NULL) | |
| 34 | − return -ENOMEM; | |
| 35 | − pwc->decompress_data = pdec; | |
| 36 | − } | |
| 37 | − pdec = pwc->decompress_data; | |
| 38 | − | |
| 39 | − return 0; | |
| 31 | + pdec->version = pdev->release; | |
| 40 | 32 | } |
| @@ -25,13 +25,15 @@ · 24 unmodified lines | ||
| 25 | 25 | #ifndef PWC_DEC1_H |
| 26 | 26 | #define PWC_DEC1_H |
| 27 | 27 | |
| 28 | −#include "pwc.h" | |
| 28 | +#include <linux/mutex.h> | |
| 29 | + | |
| 30 | +struct pwc_device; | |
| 29 | 31 | |
| 30 | 32 | struct pwc_dec1_private |
| 31 | 33 | { |
| 32 | 34 | int version; |
| 33 | 35 | }; |
| 34 | 36 | |
| 35 | −int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer); | |
| 37 | +void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd); | |
| 36 | 38 | |
| 37 | 39 | #endif |
| @@ -294,22 +294,17 @@ static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; · 293 unmodified lines | ||
| 294 | 294 | |
| 295 | 295 | |
| 296 | 296 | /* If the type or the command change, we rebuild the lookup table */ |
| 297 | −int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) | |
| 297 | +void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd) | |
| 298 | 298 | { |
| 299 | 299 | int flags, version, shift, i; |
| 300 | − struct pwc_dec23_private *pdec; | |
| 301 | − | |
| 302 | − if (pwc->decompress_data == NULL) { | |
| 303 | − pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); | |
| 304 | − if (pdec == NULL) | |
| 305 | − return -ENOMEM; | |
| 306 | − pwc->decompress_data = pdec; | |
| 307 | − } | |
| 308 | − pdec = pwc->decompress_data; | |
| 300 | + struct pwc_dec23_private *pdec = &pdev->dec23; | |
| 309 | 301 | |
| 310 | 302 | mutex_init(&pdec->lock); |
| 311 | 303 | |
| 312 | − if (DEVICE_USE_CODEC3(type)) { | |
| 304 | + if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2]) | |
| 305 | + return; | |
| 306 | + | |
| 307 | + if (DEVICE_USE_CODEC3(pdev->type)) { | |
| 313 | 308 | flags = cmd[2] & 0x18; |
| 314 | 309 | if (flags == 8) |
| 315 | 310 | pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ |
| @@ -356,7 +351,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) · 40 unmodified lines | ||
| 356 | 351 | pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255; |
| 357 | 352 | #endif |
| 358 | 353 | |
| 359 | − return 0; | |
| 354 | + pdec->last_cmd = cmd[2]; | |
| 355 | + pdec->last_cmd_valid = 1; | |
| 360 | 356 | } |
| 361 | 357 | |
| 362 | 358 | /* |
| @@ -659,12 +655,12 @@ static void DecompressBand23(struct pwc_dec23_private *pdec, · 296 unmodified lines | ||
| 659 | 655 | * src: raw data |
| 660 | 656 | * dst: image output |
| 661 | 657 | */ |
| 662 | −void pwc_dec23_decompress(const struct pwc_device *pwc, | |
| 658 | +void pwc_dec23_decompress(struct pwc_device *pdev, | |
| 663 | 659 | const void *src, |
| 664 | 660 | void *dst) |
| 665 | 661 | { |
| 666 | 662 | int bandlines_left, bytes_per_block; |
| 667 | − struct pwc_dec23_private *pdec = pwc->decompress_data; | |
| 663 | + struct pwc_dec23_private *pdec = &pdev->dec23; | |
| 668 | 664 | |
| 669 | 665 | /* YUV420P image format */ |
| 670 | 666 | unsigned char *pout_planar_y; |
| @@ -674,23 +670,22 @@ void pwc_dec23_decompress(const struct pwc_device *pwc, · 3 unmodified lines | ||
| 674 | 670 | |
| 675 | 671 | mutex_lock(&pdec->lock); |
| 676 | 672 | |
| 677 | − bandlines_left = pwc->height / 4; | |
| 678 | − bytes_per_block = pwc->width * 4; | |
| 679 | − plane_size = pwc->height * pwc->width; | |
| 673 | + bandlines_left = pdev->height / 4; | |
| 674 | + bytes_per_block = pdev->width * 4; | |
| 675 | + plane_size = pdev->height * pdev->width; | |
| 680 | 676 | |
| 681 | 677 | pout_planar_y = dst; |
| 682 | 678 | pout_planar_u = dst + plane_size; |
| 683 | 679 | pout_planar_v = dst + plane_size + plane_size / 4; |
| 684 | 680 | |
| 685 | 681 | while (bandlines_left--) { |
| 686 | − DecompressBand23(pwc->decompress_data, | |
| 687 | − src, | |
| 682 | + DecompressBand23(pdec, src, | |
| 688 | 683 | pout_planar_y, pout_planar_u, pout_planar_v, |
| 689 | − pwc->width, pwc->width); | |
| 690 | − src += pwc->vbandlength; | |
| 684 | + pdev->width, pdev->width); | |
| 685 | + src += pdev->vbandlength; | |
| 691 | 686 | pout_planar_y += bytes_per_block; |
| 692 | − pout_planar_u += pwc->width; | |
| 693 | − pout_planar_v += pwc->width; | |
| 687 | + pout_planar_u += pdev->width; | |
| 688 | + pout_planar_v += pdev->width; | |
| 694 | 689 | } |
| 695 | 690 | mutex_unlock(&pdec->lock); |
| 696 | 691 | } |
| @@ -25,17 +25,20 @@ · 24 unmodified lines | ||
| 25 | 25 | #ifndef PWC_DEC23_H |
| 26 | 26 | #define PWC_DEC23_H |
| 27 | 27 | |
| 28 | −#include "pwc.h" | |
| 28 | +struct pwc_device; | |
| 29 | 29 | |
| 30 | 30 | struct pwc_dec23_private |
| 31 | 31 | { |
| 32 | 32 | struct mutex lock; |
| 33 | 33 | |
| 34 | + unsigned char last_cmd, last_cmd_valid; | |
| 35 | + | |
| 34 | 36 | unsigned int scalebits; |
| 35 | 37 | unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ |
| 36 | 38 | |
| 37 | 39 | unsigned int reservoir; |
| 38 | 40 | unsigned int nbits_in_reservoir; |
| 41 | + | |
| 39 | 42 | const unsigned char *stream; |
| 40 | 43 | int temp_colors[16]; |
| 41 | 44 | |
| @@ -51,8 +54,8 @@ struct pwc_dec23_private · 9 unmodified lines | ||
| 51 | 54 | |
| 52 | 55 | }; |
| 53 | 56 | |
| 54 | −int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); | |
| 55 | −void pwc_dec23_decompress(const struct pwc_device *pwc, | |
| 57 | +void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd); | |
| 58 | +void pwc_dec23_decompress(struct pwc_device *pdev, | |
| 56 | 59 | const void *src, |
| 57 | 60 | void *dst); |
| 58 | 61 | #endif |
| @@ -128,18 +128,11 @@ static struct usb_driver pwc_driver = { · 127 unmodified lines | ||
| 128 | 128 | #define MAX_DEV_HINTS 20 |
| 129 | 129 | #define MAX_ISOC_ERRORS 20 |
| 130 | 130 | |
| 131 | −static int default_fps = 10; | |
| 132 | 131 | #ifdef CONFIG_USB_PWC_DEBUG |
| 133 | 132 | int pwc_trace = PWC_DEBUG_LEVEL; |
| 134 | 133 | #endif |
| 135 | 134 | static int power_save = -1; |
| 136 | −static int led_on = 100, led_off; /* defaults to LED that is on while in use */ | |
| 137 | −static struct { | |
| 138 | − int type; | |
| 139 | − char serial_number[30]; | |
| 140 | − int device_node; | |
| 141 | − struct pwc_device *pdev; | |
| 142 | −} device_hint[MAX_DEV_HINTS]; | |
| 135 | +static int leds[2] = { 100, 0 }; | |
| 143 | 136 | |
| 144 | 137 | /***/ |
| 145 | 138 | |
| @@ -386,8 +379,8 @@ static int pwc_isoc_init(struct pwc_device *pdev) · 240 unmodified lines | ||
| 386 | 379 | retry: |
| 387 | 380 | /* We first try with low compression and then retry with a higher |
| 388 | 381 | compression setting if there is not enough bandwidth. */ |
| 389 | − ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, | |
| 390 | − pdev->vframes, &compression); | |
| 382 | + ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt, | |
| 383 | + pdev->vframes, &compression, 1); | |
| 391 | 384 | |
| 392 | 385 | /* Get the current alternate interface, adjust packet size */ |
| 393 | 386 | intf = usb_ifnum_to_if(udev, 0); |
| @@ -597,23 +590,9 @@ leave: · 203 unmodified lines | ||
| 597 | 590 | static void pwc_video_release(struct v4l2_device *v) |
| 598 | 591 | { |
| 599 | 592 | struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); |
| 600 | − int hint; | |
| 601 | − | |
| 602 | − /* search device_hint[] table if we occupy a slot, by any chance */ | |
| 603 | − for (hint = 0; hint < MAX_DEV_HINTS; hint++) | |
| 604 | − if (device_hint[hint].pdev == pdev) | |
| 605 | − device_hint[hint].pdev = NULL; | |
| 606 | − | |
| 607 | − /* Free intermediate decompression buffer & tables */ | |
| 608 | − if (pdev->decompress_data != NULL) { | |
| 609 | − PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", | |
| 610 | − pdev->decompress_data); | |
| 611 | − kfree(pdev->decompress_data); | |
| 612 | − pdev->decompress_data = NULL; | |
| 613 | − } | |
| 614 | 593 | |
| 615 | 594 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); |
| 616 | − | |
| 595 | + kfree(pdev->ctrl_buf); | |
| 617 | 596 | kfree(pdev); |
| 618 | 597 | } |
| 619 | 598 | |
| @@ -758,7 +737,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 138 unmodified lines | ||
| 758 | 737 | |
| 759 | 738 | /* Turn on camera and set LEDS on */ |
| 760 | 739 | pwc_camera_power(pdev, 1); |
| 761 | − pwc_set_leds(pdev, led_on, led_off); | |
| 740 | + pwc_set_leds(pdev, leds[0], leds[1]); | |
| 762 | 741 | |
| 763 | 742 | r = pwc_isoc_init(pdev); |
| 764 | 743 | if (r) { |
| @@ -813,10 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id · 48 unmodified lines | ||
| 813 | 792 | struct usb_device *udev = interface_to_usbdev(intf); |
| 814 | 793 | struct pwc_device *pdev = NULL; |
| 815 | 794 | int vendor_id, product_id, type_id; |
| 816 | − int hint, rc; | |
| 795 | + int rc; | |
| 817 | 796 | int features = 0; |
| 818 | 797 | int compression = 0; |
| 819 | − int video_nr = -1; /* default: use next available device */ | |
| 820 | 798 | int my_power_save = power_save; |
| 821 | 799 | char serial_number[30], *name; |
| 822 | 800 | |
| @@ -1076,7 +1054,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id · 253 unmodified lines | ||
| 1076 | 1054 | return -ENOMEM; |
| 1077 | 1055 | } |
| 1078 | 1056 | pdev->type = type_id; |
| 1079 | − pdev->vframes = default_fps; | |
| 1080 | 1057 | pdev->features = features; |
| 1081 | 1058 | pwc_construct(pdev); /* set min/max sizes correct */ |
| 1082 | 1059 | |
| @@ -1107,24 +1084,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id · 24 unmodified lines | ||
| 1107 | 1084 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); |
| 1108 | 1085 | PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); |
| 1109 | 1086 | |
| 1110 | − /* Now search device_hint[] table for a match, so we can hint a node number. */ | |
| 1111 | − for (hint = 0; hint < MAX_DEV_HINTS; hint++) { | |
| 1112 | − if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) && | |
| 1113 | − (device_hint[hint].pdev == NULL)) { | |
| 1114 | − /* so far, so good... try serial number */ | |
| 1115 | − if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { | |
| 1116 | − /* match! */ | |
| 1117 | − video_nr = device_hint[hint].device_node; | |
| 1118 | − PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr); | |
| 1119 | − break; | |
| 1120 | − } | |
| 1121 | − } | |
| 1087 | + /* Allocate USB command buffers */ | |
| 1088 | + pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL); | |
| 1089 | + if (!pdev->ctrl_buf) { | |
| 1090 | + PWC_ERROR("Oops, could not allocate memory for pwc_device.\n"); | |
| 1091 | + rc = -ENOMEM; | |
| 1092 | + goto err_free_mem; | |
| 1122 | 1093 | } |
| 1123 | 1094 | |
| 1124 | − /* occupy slot */ | |
| 1125 | − if (hint < MAX_DEV_HINTS) | |
| 1126 | − device_hint[hint].pdev = pdev; | |
| 1127 | − | |
| 1128 | 1095 | #ifdef CONFIG_USB_PWC_DEBUG |
| 1129 | 1096 | /* Query sensor type */ |
| 1130 | 1097 | if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { |
| @@ -1138,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id · 7 unmodified lines | ||
| 1138 | 1105 | pwc_set_leds(pdev, 0, 0); |
| 1139 | 1106 | |
| 1140 | 1107 | /* Setup intial videomode */ |
| 1141 | − rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes, | |
| 1142 | − &compression); | |
| 1108 | + rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, | |
| 1109 | + V4L2_PIX_FMT_YUV420, 30, &compression, 1); | |
| 1143 | 1110 | if (rc) |
| 1144 | 1111 | goto err_free_mem; |
| 1145 | 1112 | |
| @@ -1164,7 +1131,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id · 18 unmodified lines | ||
| 1164 | 1131 | pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; |
| 1165 | 1132 | pdev->vdev.v4l2_dev = &pdev->v4l2_dev; |
| 1166 | 1133 | |
| 1167 | − rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); | |
| 1134 | + rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1); | |
| 1168 | 1135 | if (rc < 0) { |
| 1169 | 1136 | PWC_ERROR("Failed to register as video device (%d).\n", rc); |
| 1170 | 1137 | goto err_unregister_v4l2_dev; |
| @@ -1207,8 +1174,7 @@ err_unregister_v4l2_dev: · 36 unmodified lines | ||
| 1207 | 1174 | err_free_controls: |
| 1208 | 1175 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); |
| 1209 | 1176 | err_free_mem: |
| 1210 | − if (hint < MAX_DEV_HINTS) | |
| 1211 | − device_hint[hint].pdev = NULL; | |
| 1177 | + kfree(pdev->ctrl_buf); | |
| 1212 | 1178 | kfree(pdev); |
| 1213 | 1179 | return rc; |
| 1214 | 1180 | } |
| @@ -1243,27 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf) · 28 unmodified lines | ||
| 1243 | 1209 | * Initialization code & module stuff |
| 1244 | 1210 | */ |
| 1245 | 1211 | |
| 1246 | −static int fps; | |
| 1247 | −static int leds[2] = { -1, -1 }; | |
| 1248 | 1212 | static unsigned int leds_nargs; |
| 1249 | −static char *dev_hint[MAX_DEV_HINTS]; | |
| 1250 | −static unsigned int dev_hint_nargs; | |
| 1251 | 1213 | |
| 1252 | −module_param(fps, int, 0444); | |
| 1253 | 1214 | #ifdef CONFIG_USB_PWC_DEBUG |
| 1254 | 1215 | module_param_named(trace, pwc_trace, int, 0644); |
| 1255 | 1216 | #endif |
| 1256 | 1217 | module_param(power_save, int, 0644); |
| 1257 | 1218 | module_param_array(leds, int, &leds_nargs, 0444); |
| 1258 | −module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); | |
| 1259 | 1219 | |
| 1260 | −MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); | |
| 1261 | 1220 | #ifdef CONFIG_USB_PWC_DEBUG |
| 1262 | 1221 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
| 1263 | 1222 | #endif |
| 1264 | 1223 | MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); |
| 1265 | 1224 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); |
| 1266 | −MODULE_PARM_DESC(dev_hint, "Device node hints"); | |
| 1267 | 1225 | |
| 1268 | 1226 | MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); |
| 1269 | 1227 | MODULE_AUTHOR("Luc Saillard <luc@saillard.org>"); |
| @@ -1273,114 +1231,13 @@ MODULE_VERSION( PWC_VERSION ); · 3 unmodified lines | ||
| 1273 | 1231 | |
| 1274 | 1232 | static int __init usb_pwc_init(void) |
| 1275 | 1233 | { |
| 1276 | − int i; | |
| 1277 | − | |
| 1278 | −#ifdef CONFIG_USB_PWC_DEBUG | |
| 1279 | − PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n"); | |
| 1280 | − PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); | |
| 1281 | − PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); | |
| 1282 | − PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); | |
| 1283 | − | |
| 1284 | − if (pwc_trace >= 0) { | |
| 1285 | − PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace); | |
| 1286 | − } | |
| 1287 | −#endif | |
| 1288 | − | |
| 1289 | − if (fps) { | |
| 1290 | − if (fps < 4 || fps > 30) { | |
| 1291 | − PWC_ERROR("Framerate out of bounds (4-30).\n"); | |
| 1292 | − return -EINVAL; | |
| 1293 | − } | |
| 1294 | − default_fps = fps; | |
| 1295 | − PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); | |
| 1296 | − } | |
| 1297 | − | |
| 1298 | − if (leds[0] >= 0) | |
| 1299 | − led_on = leds[0]; | |
| 1300 | − if (leds[1] >= 0) | |
| 1301 | − led_off = leds[1]; | |
| 1302 | − | |
| 1303 | − /* Big device node whoopla. Basically, it allows you to assign a | |
| 1304 | − device node (/dev/videoX) to a camera, based on its type | |
| 1305 | − & serial number. The format is [type[.serialnumber]:]node. | |
| 1306 | − | |
| 1307 | − Any camera that isn't matched by these rules gets the next | |
| 1308 | − available free device node. | |
| 1309 | − */ | |
| 1310 | − for (i = 0; i < MAX_DEV_HINTS; i++) { | |
| 1311 | − char *s, *colon, *dot; | |
| 1312 | − | |
| 1313 | − /* This loop also initializes the array */ | |
| 1314 | − device_hint[i].pdev = NULL; | |
| 1315 | − s = dev_hint[i]; | |
| 1316 | − if (s != NULL && *s != '\0') { | |
| 1317 | − device_hint[i].type = -1; /* wildcard */ | |
| 1318 | − strcpy(device_hint[i].serial_number, "*"); | |
| 1319 | − | |
| 1320 | − /* parse string: chop at ':' & '/' */ | |
| 1321 | − colon = dot = s; | |
| 1322 | − while (*colon != '\0' && *colon != ':') | |
| 1323 | − colon++; | |
| 1324 | − while (*dot != '\0' && *dot != '.') | |
| 1325 | − dot++; | |
| 1326 | − /* Few sanity checks */ | |
| 1327 | − if (*dot != '\0' && dot > colon) { | |
| 1328 | − PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n"); | |
| 1329 | − return -EINVAL; | |
| 1330 | − } | |
| 1331 | − | |
| 1332 | − if (*colon == '\0') { | |
| 1333 | − /* No colon */ | |
| 1334 | − if (*dot != '\0') { | |
| 1335 | − PWC_ERROR("Malformed camera hint: no colon + device node given.\n"); | |
| 1336 | − return -EINVAL; | |
| 1337 | − } | |
| 1338 | − else { | |
| 1339 | − /* No type or serial number specified, just a number. */ | |
| 1340 | − device_hint[i].device_node = | |
| 1341 | − simple_strtol(s, NULL, 10); | |
| 1342 | − } | |
| 1343 | − } | |
| 1344 | − else { | |
| 1345 | − /* There's a colon, so we have at least a type and a device node */ | |
| 1346 | − device_hint[i].type = | |
| 1347 | − simple_strtol(s, NULL, 10); | |
| 1348 | − device_hint[i].device_node = | |
| 1349 | − simple_strtol(colon + 1, NULL, 10); | |
| 1350 | − if (*dot != '\0') { | |
| 1351 | − /* There's a serial number as well */ | |
| 1352 | − int k; | |
| 1353 | − | |
| 1354 | − dot++; | |
| 1355 | − k = 0; | |
| 1356 | − while (*dot != ':' && k < 29) { | |
| 1357 | − device_hint[i].serial_number[k++] = *dot; | |
| 1358 | − dot++; | |
| 1359 | − } | |
| 1360 | − device_hint[i].serial_number[k] = '\0'; | |
| 1361 | − } | |
| 1362 | − } | |
| 1363 | − PWC_TRACE("device_hint[%d]:\n", i); | |
| 1364 | − PWC_TRACE(" type : %d\n", device_hint[i].type); | |
| 1365 | − PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number); | |
| 1366 | − PWC_TRACE(" node : %d\n", device_hint[i].device_node); | |
| 1367 | − } | |
| 1368 | − else | |
| 1369 | − device_hint[i].type = 0; /* not filled */ | |
| 1370 | − } /* ..for MAX_DEV_HINTS */ | |
| 1371 | − | |
| 1372 | − PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver); | |
| 1373 | 1234 | return usb_register(&pwc_driver); |
| 1374 | 1235 | } |
| 1375 | 1236 | |
| 1376 | 1237 | static void __exit usb_pwc_exit(void) |
| 1377 | 1238 | { |
| 1378 | − PWC_DEBUG_MODULE("Deregistering driver.\n"); | |
| 1379 | 1239 | usb_deregister(&pwc_driver); |
| 1380 | − PWC_INFO("Philips webcam module removed.\n"); | |
| 1381 | 1240 | } |
| 1382 | 1241 | |
| 1383 | 1242 | module_init(usb_pwc_init); |
| 1384 | 1243 | module_exit(usb_pwc_exit); |
| 1385 | − | |
| 1386 | −/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | |
| @@ -90,5 +90,4 @@ void pwc_construct(struct pwc_device *pdev) · 89 unmodified lines | ||
| 90 | 90 | pdev->frame_header_size = 0; |
| 91 | 91 | pdev->frame_trailer_size = 0; |
| 92 | 92 | } |
| 93 | − pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ | |
| 94 | 93 | } |
| @@ -493,16 +493,11 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) · 492 unmodified lines | ||
| 493 | 493 | (pixelformat>>24)&255); |
| 494 | 494 | |
| 495 | 495 | ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height, |
| 496 | − pdev->vframes, &compression); | |
| 496 | + pixelformat, 30, &compression, 0); | |
| 497 | 497 | |
| 498 | 498 | PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); |
| 499 | 499 | |
| 500 | − if (ret == 0) { | |
| 501 | − pdev->pixfmt = pixelformat; | |
| 502 | − pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, | |
| 503 | − pdev->pixfmt); | |
| 504 | − } | |
| 505 | − | |
| 500 | + pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); | |
| 506 | 501 | leave: |
| 507 | 502 | mutex_unlock(&pdev->udevlock); |
| 508 | 503 | return ret; |
| @@ -777,33 +772,33 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev) · 268 unmodified lines | ||
| 777 | 772 | static int pwc_set_motor(struct pwc_device *pdev) |
| 778 | 773 | { |
| 779 | 774 | int ret; |
| 780 | − u8 buf[4]; | |
| 781 | 775 | |
| 782 | − buf[0] = 0; | |
| 776 | + pdev->ctrl_buf[0] = 0; | |
| 783 | 777 | if (pdev->motor_pan_reset->is_new) |
| 784 | − buf[0] |= 0x01; | |
| 778 | + pdev->ctrl_buf[0] |= 0x01; | |
| 785 | 779 | if (pdev->motor_tilt_reset->is_new) |
| 786 | − buf[0] |= 0x02; | |
| 780 | + pdev->ctrl_buf[0] |= 0x02; | |
| 787 | 781 | if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) { |
| 788 | 782 | ret = send_control_msg(pdev, SET_MPT_CTL, |
| 789 | − PT_RESET_CONTROL_FORMATTER, buf, 1); | |
| 783 | + PT_RESET_CONTROL_FORMATTER, | |
| 784 | + pdev->ctrl_buf, 1); | |
| 790 | 785 | if (ret < 0) |
| 791 | 786 | return ret; |
| 792 | 787 | } |
| 793 | 788 | |
| 794 | − memset(buf, 0, sizeof(buf)); | |
| 789 | + memset(pdev->ctrl_buf, 0, 4); | |
| 795 | 790 | if (pdev->motor_pan->is_new) { |
| 796 | − buf[0] = pdev->motor_pan->val & 0xFF; | |
| 797 | − buf[1] = (pdev->motor_pan->val >> 8); | |
| 791 | + pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF; | |
| 792 | + pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8); | |
| 798 | 793 | } |
| 799 | 794 | if (pdev->motor_tilt->is_new) { |
| 800 | − buf[2] = pdev->motor_tilt->val & 0xFF; | |
| 801 | − buf[3] = (pdev->motor_tilt->val >> 8); | |
| 795 | + pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF; | |
| 796 | + pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8); | |
| 802 | 797 | } |
| 803 | 798 | if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) { |
| 804 | 799 | ret = send_control_msg(pdev, SET_MPT_CTL, |
| 805 | 800 | PT_RELATIVE_CONTROL_FORMATTER, |
| 806 | − buf, sizeof(buf)); | |
| 801 | + pdev->ctrl_buf, 4); | |
| 807 | 802 | if (ret < 0) |
| 808 | 803 | return ret; |
| 809 | 804 | } |
| @@ -1094,6 +1089,63 @@ static int pwc_enum_frameintervals(struct file *file, void *fh, · 284 unmodified lines | ||
| 1094 | 1089 | return 0; |
| 1095 | 1090 | } |
| 1096 | 1091 | |
| 1092 | +static int pwc_g_parm(struct file *file, void *fh, | |
| 1093 | + struct v4l2_streamparm *parm) | |
| 1094 | +{ | |
| 1095 | + struct pwc_device *pdev = video_drvdata(file); | |
| 1096 | + | |
| 1097 | + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
| 1098 | + return -EINVAL; | |
| 1099 | + | |
| 1100 | + memset(parm, 0, sizeof(*parm)); | |
| 1101 | + | |
| 1102 | + parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| 1103 | + parm->parm.capture.readbuffers = MIN_FRAMES; | |
| 1104 | + parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME; | |
| 1105 | + parm->parm.capture.timeperframe.denominator = pdev->vframes; | |
| 1106 | + parm->parm.capture.timeperframe.numerator = 1; | |
| 1107 | + | |
| 1108 | + return 0; | |
| 1109 | +} | |
| 1110 | + | |
| 1111 | +static int pwc_s_parm(struct file *file, void *fh, | |
| 1112 | + struct v4l2_streamparm *parm) | |
| 1113 | +{ | |
| 1114 | + struct pwc_device *pdev = video_drvdata(file); | |
| 1115 | + int compression = 0; | |
| 1116 | + int ret, fps; | |
| 1117 | + | |
| 1118 | + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | |
| 1119 | + parm->parm.capture.timeperframe.numerator == 0) | |
| 1120 | + return -EINVAL; | |
| 1121 | + | |
| 1122 | + if (pwc_test_n_set_capt_file(pdev, file)) | |
| 1123 | + return -EBUSY; | |
| 1124 | + | |
| 1125 | + fps = parm->parm.capture.timeperframe.denominator / | |
| 1126 | + parm->parm.capture.timeperframe.numerator; | |
| 1127 | + | |
| 1128 | + mutex_lock(&pdev->udevlock); | |
| 1129 | + if (!pdev->udev) { | |
| 1130 | + ret = -ENODEV; | |
| 1131 | + goto leave; | |
| 1132 | + } | |
| 1133 | + | |
| 1134 | + if (pdev->iso_init) { | |
| 1135 | + ret = -EBUSY; | |
| 1136 | + goto leave; | |
| 1137 | + } | |
| 1138 | + | |
| 1139 | + ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt, | |
| 1140 | + fps, &compression, 0); | |
| 1141 | + | |
| 1142 | + pwc_g_parm(file, fh, parm); | |
| 1143 | + | |
| 1144 | +leave: | |
| 1145 | + mutex_unlock(&pdev->udevlock); | |
| 1146 | + return ret; | |
| 1147 | +} | |
| 1148 | + | |
| 1097 | 1149 | static int pwc_log_status(struct file *file, void *priv) |
| 1098 | 1150 | { |
| 1099 | 1151 | struct pwc_device *pdev = video_drvdata(file); |
| @@ -1120,4 +1172,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { · 20 unmodified lines | ||
| 1120 | 1172 | .vidioc_log_status = pwc_log_status, |
| 1121 | 1173 | .vidioc_enum_framesizes = pwc_enum_framesizes, |
| 1122 | 1174 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, |
| 1175 | + .vidioc_g_parm = pwc_g_parm, | |
| 1176 | + .vidioc_s_parm = pwc_s_parm, | |
| 1123 | 1177 | }; |
| @@ -44,6 +44,8 @@ · 43 unmodified lines | ||
| 44 | 44 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
| 45 | 45 | #include <linux/input.h> |
| 46 | 46 | #endif |
| 47 | +#include "pwc-dec1.h" | |
| 48 | +#include "pwc-dec23.h" | |
| 47 | 49 | |
| 48 | 50 | /* Version block */ |
| 49 | 51 | #define PWC_VERSION "10.0.15" |
| @@ -132,9 +134,6 @@ · 82 unmodified lines | ||
| 132 | 134 | #define DEVICE_USE_CODEC3(x) ((x)>=700) |
| 133 | 135 | #define DEVICE_USE_CODEC23(x) ((x)>=675) |
| 134 | 136 | |
| 135 | −/* from pwc-dec.h */ | |
| 136 | −#define PWCX_FLAG_PLANAR 0x0001 | |
| 137 | − | |
| 138 | 137 | /* Request types: video */ |
| 139 | 138 | #define SET_LUM_CTL 0x01 |
| 140 | 139 | #define GET_LUM_CTL 0x02 |
| @@ -248,8 +247,8 @@ struct pwc_device · 107 unmodified lines | ||
| 248 | 247 | char vmirror; /* for ToUCaM series */ |
| 249 | 248 | char power_save; /* Do powersaving for this cam */ |
| 250 | 249 | |
| 251 | − int cmd_len; | |
| 252 | 250 | unsigned char cmd_buf[13]; |
| 251 | + unsigned char *ctrl_buf; | |
| 253 | 252 | |
| 254 | 253 | struct urb *urbs[MAX_ISO_BUFS]; |
| 255 | 254 | char iso_init; |
| @@ -272,7 +271,10 @@ struct pwc_device · 16 unmodified lines | ||
| 272 | 271 | int frame_total_size; /* including header & trailer */ |
| 273 | 272 | int drop_frames; |
| 274 | 273 | |
| 275 | − void *decompress_data; /* private data for decompression engine */ | |
| 274 | + union { /* private data for decompression engine */ | |
| 275 | + struct pwc_dec1_private dec1; | |
| 276 | + struct pwc_dec23_private dec23; | |
| 277 | + }; | |
| 276 | 278 | |
| 277 | 279 | /* |
| 278 | 280 | * We have an 'image' and a 'view', where 'image' is the fixed-size img |
| @@ -364,7 +366,7 @@ void pwc_construct(struct pwc_device *pdev); · 85 unmodified lines | ||
| 364 | 366 | /** Functions in pwc-ctrl.c */ |
| 365 | 367 | /* Request a certain video mode. Returns < 0 if not possible */ |
| 366 | 368 | extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, |
| 367 | − int frames, int *compression); | |
| 369 | + int pixfmt, int frames, int *compression, int send_to_cam); | |
| 368 | 370 | extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size); |
| 369 | 371 | extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); |
| 370 | 372 | extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); |
| @@ -693,7 +693,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, · 692 unmodified lines | ||
| 693 | 693 | mf->code = 0; |
| 694 | 694 | continue; |
| 695 | 695 | } |
| 696 | − if (mf->width != tfmt->width || mf->width != tfmt->width) { | |
| 696 | + if (mf->width != tfmt->width || mf->height != tfmt->height) { | |
| 697 | 697 | u32 fcc = ffmt->fourcc; |
| 698 | 698 | tfmt->width = mf->width; |
| 699 | 699 | tfmt->height = mf->height; |
| @@ -702,7 +702,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, · 2 unmodified lines | ||
| 702 | 702 | NULL, &fcc, FIMC_SD_PAD_SOURCE); |
| 703 | 703 | if (ffmt && ffmt->mbus_code) |
| 704 | 704 | mf->code = ffmt->mbus_code; |
| 705 | − if (mf->width != tfmt->width || mf->width != tfmt->width) | |
| 705 | + if (mf->width != tfmt->width || | |
| 706 | + mf->height != tfmt->height) | |
| 706 | 707 | continue; |
| 707 | 708 | tfmt->code = mf->code; |
| 708 | 709 | } |
| @@ -710,7 +711,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, · 1 unmodified line | ||
| 710 | 711 | ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt); |
| 711 | 712 | |
| 712 | 713 | if (mf->code == tfmt->code && |
| 713 | − mf->width == tfmt->width && mf->width == tfmt->width) | |
| 714 | + mf->width == tfmt->width && mf->height == tfmt->height) | |
| 714 | 715 | break; |
| 715 | 716 | } |
| 716 | 717 | |
| @@ -848,11 +848,11 @@ int fimc_ctrls_create(struct fimc_ctx *ctx) · 847 unmodified lines | ||
| 848 | 848 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4); |
| 849 | 849 | |
| 850 | 850 | ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, |
| 851 | − V4L2_CID_HFLIP, 0, 1, 1, 0); | |
| 851 | + V4L2_CID_ROTATE, 0, 270, 90, 0); | |
| 852 | 852 | ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, |
| 853 | − V4L2_CID_VFLIP, 0, 1, 1, 0); | |
| 853 | + V4L2_CID_HFLIP, 0, 1, 1, 0); | |
| 854 | 854 | ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, |
| 855 | − V4L2_CID_ROTATE, 0, 270, 90, 0); | |
| 855 | + V4L2_CID_VFLIP, 0, 1, 1, 0); | |
| 856 | 856 | if (variant->has_alpha) |
| 857 | 857 | ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler, |
| 858 | 858 | &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, |
| @@ -21,7 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/pm_runtime.h> |
| 22 | 22 | #include <linux/types.h> |
| 23 | 23 | #include <linux/slab.h> |
| 24 | −#include <linux/version.h> | |
| 25 | 24 | #include <media/v4l2-ctrls.h> |
| 26 | 25 | #include <media/media-device.h> |
| 27 | 26 | |
| @@ -184,6 +184,7 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) · 183 unmodified lines | ||
| 184 | 184 | ctx->rop = ROP4_INVERT; |
| 185 | 185 | else |
| 186 | 186 | ctx->rop = ROP4_COPY; |
| 187 | + break; | |
| 187 | 188 | default: |
| 188 | 189 | v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); |
| 189 | 190 | return -EINVAL; |
| @@ -989,9 +989,10 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { · 988 unmodified lines | ||
| 989 | 989 | * ============================================================================ |
| 990 | 990 | */ |
| 991 | 991 | |
| 992 | −static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, | |
| 993 | − unsigned int *nplanes, unsigned int sizes[], | |
| 994 | − void *alloc_ctxs[]) | |
| 992 | +static int s5p_jpeg_queue_setup(struct vb2_queue *vq, | |
| 993 | + const struct v4l2_format *fmt, | |
| 994 | + unsigned int *nbuffers, unsigned int *nplanes, | |
| 995 | + unsigned int sizes[], void *alloc_ctxs[]) | |
| 995 | 996 | { |
| 996 | 997 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); |
| 997 | 998 | struct s5p_jpeg_q_data *q_data = NULL; |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/platform_device.h> |
| 19 | 19 | #include <linux/sched.h> |
| 20 | 20 | #include <linux/slab.h> |
| 21 | −#include <linux/version.h> | |
| 22 | 21 | #include <linux/videodev2.h> |
| 23 | 22 | #include <linux/workqueue.h> |
| 24 | 23 | #include <media/videobuf2-core.h> |
| @@ -475,7 +474,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx, · 450 unmodified lines | ||
| 475 | 474 | ctx->mv_size = 0; |
| 476 | 475 | } |
| 477 | 476 | ctx->dpb_count = s5p_mfc_get_dpb_count(); |
| 478 | − if (ctx->img_width == 0 || ctx->img_width == 0) | |
| 477 | + if (ctx->img_width == 0 || ctx->img_height == 0) | |
| 479 | 478 | ctx->state = MFCINST_ERROR; |
| 480 | 479 | else |
| 481 | 480 | ctx->state = MFCINST_HEAD_PARSED; |
| @@ -165,7 +165,7 @@ static struct mfc_control controls[] = { · 164 unmodified lines | ||
| 165 | 165 | .maximum = 32, |
| 166 | 166 | .step = 1, |
| 167 | 167 | .default_value = 1, |
| 168 | − .flags = V4L2_CTRL_FLAG_VOLATILE, | |
| 168 | + .is_volatile = 1, | |
| 169 | 169 | }, |
| 170 | 170 | }; |
| 171 | 171 | |
| @@ -269,8 +269,6 @@ struct saa7164_board saa7164_boards[] = { · 268 unmodified lines | ||
| 269 | 269 | .portb = SAA7164_MPEG_DVB, |
| 270 | 270 | .portc = SAA7164_MPEG_ENCODER, |
| 271 | 271 | .portd = SAA7164_MPEG_ENCODER, |
| 272 | − .portc = SAA7164_MPEG_ENCODER, | |
| 273 | − .portd = SAA7164_MPEG_ENCODER, | |
| 274 | 272 | .porte = SAA7164_MPEG_VBI, |
| 275 | 273 | .portf = SAA7164_MPEG_VBI, |
| 276 | 274 | .chiprev = SAA7164_CHIP_REV3, |
| @@ -333,8 +331,6 @@ struct saa7164_board saa7164_boards[] = { · 56 unmodified lines | ||
| 333 | 331 | .portd = SAA7164_MPEG_ENCODER, |
| 334 | 332 | .porte = SAA7164_MPEG_VBI, |
| 335 | 333 | .portf = SAA7164_MPEG_VBI, |
| 336 | − .porte = SAA7164_MPEG_VBI, | |
| 337 | − .portf = SAA7164_MPEG_VBI, | |
| 338 | 334 | .chiprev = SAA7164_CHIP_REV3, |
| 339 | 335 | .unit = {{ |
| 340 | 336 | .id = 0x28, |
| @@ -374,7 +374,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) · 373 unmodified lines | ||
| 374 | 374 | } |
| 375 | 375 | #endif |
| 376 | 376 | |
| 377 | −static bool check_firmware(struct usb_device *udev, int *down_firmware) | |
| 377 | +static int check_firmware(struct usb_device *udev, int *down_firmware) | |
| 378 | 378 | { |
| 379 | 379 | void *buf; |
| 380 | 380 | int ret; |
| @@ -398,7 +398,7 @@ static bool check_firmware(struct usb_device *udev, int *down_firmware) · 17 unmodified lines | ||
| 398 | 398 | *down_firmware = 1; |
| 399 | 399 | return firmware_download(udev); |
| 400 | 400 | } |
| 401 | − return ret; | |
| 401 | + return 0; | |
| 402 | 402 | } |
| 403 | 403 | |
| 404 | 404 | static int poseidon_probe(struct usb_interface *interface, |
| @@ -465,8 +465,8 @@ const char *v4l2_ctrl_get_name(u32 id) · 464 unmodified lines | ||
| 465 | 465 | case V4L2_CID_CHROMA_GAIN: return "Chroma Gain"; |
| 466 | 466 | case V4L2_CID_ILLUMINATORS_1: return "Illuminator 1"; |
| 467 | 467 | case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; |
| 468 | − case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers"; | |
| 469 | − case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers"; | |
| 468 | + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Min Number of Capture Buffers"; | |
| 469 | + case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min Number of Output Buffers"; | |
| 470 | 470 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; |
| 471 | 471 | |
| 472 | 472 | /* MPEG controls */ |
| @@ -506,25 +506,25 @@ const char *v4l2_ctrl_get_name(u32 id) · 33 unmodified lines | ||
| 506 | 506 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; |
| 507 | 507 | case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface"; |
| 508 | 508 | case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable"; |
| 509 | − case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "The Number of Intra Refresh MBs"; | |
| 509 | + case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs"; | |
| 510 | 510 | case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable"; |
| 511 | 511 | case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control"; |
| 512 | 512 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode"; |
| 513 | − case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "The Max Number of Reference Picture"; | |
| 513 | + case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics"; | |
| 514 | 514 | case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value"; |
| 515 | − case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P frame QP Value"; | |
| 516 | − case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B frame QP Value"; | |
| 515 | + case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value"; | |
| 516 | + case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value"; | |
| 517 | 517 | case V4L2_CID_MPEG_VIDEO_H263_MIN_QP: return "H263 Minimum QP Value"; |
| 518 | 518 | case V4L2_CID_MPEG_VIDEO_H263_MAX_QP: return "H263 Maximum QP Value"; |
| 519 | 519 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: return "H264 I-Frame QP Value"; |
| 520 | − case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P frame QP Value"; | |
| 521 | − case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B frame QP Value"; | |
| 520 | + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P-Frame QP Value"; | |
| 521 | + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B-Frame QP Value"; | |
| 522 | 522 | case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: return "H264 Maximum QP Value"; |
| 523 | 523 | case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: return "H264 Minimum QP Value"; |
| 524 | 524 | case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: return "H264 8x8 Transform Enable"; |
| 525 | 525 | case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: return "H264 CPB Buffer Size"; |
| 526 | − case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entorpy Mode"; | |
| 527 | − case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I Period"; | |
| 526 | + case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entropy Mode"; | |
| 527 | + case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I-Frame Period"; | |
| 528 | 528 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: return "H264 Level"; |
| 529 | 529 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: return "H264 Loop Filter Alpha Offset"; |
| 530 | 530 | case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: return "H264 Loop Filter Beta Offset"; |
| @@ -535,16 +535,16 @@ const char *v4l2_ctrl_get_name(u32 id) · 4 unmodified lines | ||
| 535 | 535 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable"; |
| 536 | 536 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC"; |
| 537 | 537 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; |
| 538 | − case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P frame QP Value"; | |
| 539 | − case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B frame QP Value"; | |
| 538 | + case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; | |
| 539 | + case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; | |
| 540 | 540 | case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: return "MPEG4 Minimum QP Value"; |
| 541 | 541 | case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: return "MPEG4 Maximum QP Value"; |
| 542 | 542 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: return "MPEG4 Level"; |
| 543 | 543 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: return "MPEG4 Profile"; |
| 544 | 544 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: return "Quarter Pixel Search Enable"; |
| 545 | − case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "The Maximum Bytes Per Slice"; | |
| 546 | − case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "The Number of MB in a Slice"; | |
| 547 | − case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "The Slice Partitioning Method"; | |
| 545 | + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "Maximum Bytes in a Slice"; | |
| 546 | + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; | |
| 547 | + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; | |
| 548 | 548 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; |
| 549 | 549 | |
| 550 | 550 | /* CAMERA controls */ |
| @@ -580,7 +580,7 @@ const char *v4l2_ctrl_get_name(u32 id) · 29 unmodified lines | ||
| 580 | 580 | case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled"; |
| 581 | 581 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time"; |
| 582 | 582 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation"; |
| 583 | − case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled"; | |
| 583 | + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled"; | |
| 584 | 584 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain"; |
| 585 | 585 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold"; |
| 586 | 586 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time"; |
| @@ -588,24 +588,24 @@ const char *v4l2_ctrl_get_name(u32 id) · 1 unmodified line | ||
| 588 | 588 | case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; |
| 589 | 589 | case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; |
| 590 | 590 | case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; |
| 591 | − case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; | |
| 591 | + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis"; | |
| 592 | 592 | case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; |
| 593 | 593 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; |
| 594 | 594 | |
| 595 | 595 | /* Flash controls */ |
| 596 | − case V4L2_CID_FLASH_CLASS: return "Flash controls"; | |
| 597 | − case V4L2_CID_FLASH_LED_MODE: return "LED mode"; | |
| 598 | − case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe source"; | |
| 596 | + case V4L2_CID_FLASH_CLASS: return "Flash Controls"; | |
| 597 | + case V4L2_CID_FLASH_LED_MODE: return "LED Mode"; | |
| 598 | + case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source"; | |
| 599 | 599 | case V4L2_CID_FLASH_STROBE: return "Strobe"; |
| 600 | − case V4L2_CID_FLASH_STROBE_STOP: return "Stop strobe"; | |
| 601 | − case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe status"; | |
| 602 | − case V4L2_CID_FLASH_TIMEOUT: return "Strobe timeout"; | |
| 603 | − case V4L2_CID_FLASH_INTENSITY: return "Intensity, flash mode"; | |
| 604 | − case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, torch mode"; | |
| 605 | − case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator"; | |
| 600 | + case V4L2_CID_FLASH_STROBE_STOP: return "Stop Strobe"; | |
| 601 | + case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe Status"; | |
| 602 | + case V4L2_CID_FLASH_TIMEOUT: return "Strobe Timeout"; | |
| 603 | + case V4L2_CID_FLASH_INTENSITY: return "Intensity, Flash Mode"; | |
| 604 | + case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, Torch Mode"; | |
| 605 | + case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator"; | |
| 606 | 606 | case V4L2_CID_FLASH_FAULT: return "Faults"; |
| 607 | 607 | case V4L2_CID_FLASH_CHARGE: return "Charge"; |
| 608 | − case V4L2_CID_FLASH_READY: return "Ready to strobe"; | |
| 608 | + case V4L2_CID_FLASH_READY: return "Ready to Strobe"; | |
| 609 | 609 | |
| 610 | 610 | default: |
| 611 | 611 | return NULL; |
| @@ -1871,6 +1871,7 @@ static long __video_do_ioctl(struct file *file, · 1870 unmodified lines | ||
| 1871 | 1871 | case VIDIOC_S_FREQUENCY: |
| 1872 | 1872 | { |
| 1873 | 1873 | struct v4l2_frequency *p = arg; |
| 1874 | + enum v4l2_tuner_type type; | |
| 1874 | 1875 | |
| 1875 | 1876 | if (!ops->vidioc_s_frequency) |
| 1876 | 1877 | break; |
| @@ -1878,9 +1879,14 @@ static long __video_do_ioctl(struct file *file, · 1 unmodified line | ||
| 1878 | 1879 | ret = ret_prio; |
| 1879 | 1880 | break; |
| 1880 | 1881 | } |
| 1882 | + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? | |
| 1883 | + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | |
| 1881 | 1884 | dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", |
| 1882 | 1885 | p->tuner, p->type, p->frequency); |
| 1883 | − ret = ops->vidioc_s_frequency(file, fh, p); | |
| 1886 | + if (p->type != type) | |
| 1887 | + ret = -EINVAL; | |
| 1888 | + else | |
| 1889 | + ret = ops->vidioc_s_frequency(file, fh, p); | |
| 1884 | 1890 | break; |
| 1885 | 1891 | } |
| 1886 | 1892 | case VIDIOC_G_SLICED_VBI_CAP: |
| @@ -1958,7 +1958,6 @@ static int zoran_g_fbuf(struct file *file, void *__fh, · 1957 unmodified lines | ||
| 1958 | 1958 | mutex_unlock(&zr->resource_lock); |
| 1959 | 1959 | fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; |
| 1960 | 1960 | fb->fmt.field = V4L2_FIELD_INTERLACED; |
| 1961 | − fb->flags = V4L2_FBUF_FLAG_OVERLAY; | |
| 1962 | 1961 | fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; |
| 1963 | 1962 | |
| 1964 | 1963 | return 0; |
| @@ -127,7 +127,6 @@ · 126 unmodified lines | ||
| 127 | 127 | #define TUNER_PHILIPS_FMD1216MEX_MK3 78 |
| 128 | 128 | #define TUNER_PHILIPS_FM1216MK5 79 |
| 129 | 129 | #define TUNER_PHILIPS_FQ1216LME_MK3 80 /* Active loopthrough, no FM */ |
| 130 | −#define TUNER_XC4000 81 /* Xceive Silicon Tuner */ | |
| 131 | 130 | |
| 132 | 131 | #define TUNER_PARTSNIC_PTI_5NF05 81 |
| 133 | 132 | #define TUNER_PHILIPS_CU1216L 82 |
| @@ -136,6 +135,8 @@ · 2 unmodified lines | ||
| 136 | 135 | #define TUNER_PHILIPS_FQ1236_MK5 85 /* NTSC, TDA9885, no FM radio */ |
| 137 | 136 | #define TUNER_TENA_TNF_5337 86 |
| 138 | 137 | |
| 138 | +#define TUNER_XC4000 87 /* Xceive Silicon Tuner */ | |
| 139 | + | |
| 139 | 140 | /* tv card specific */ |
| 140 | 141 | #define TDA9887_PRESENT (1<<0) |
| 141 | 142 | #define TDA9887_PORT1_INACTIVE (1<<1) |