diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-05 11:32:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-05 11:32:01 -0400 |
commit | e7a2c3fa28576684d744e259a2fdb245f8bab0d7 (patch) | |
tree | c118ba72f571215f6c8e3eaa363c43ec925bf3cb | |
parent | 3c168909002eac649fb8b803d6a9babe758ec7c2 (diff) | |
parent | 3b766f45355775fc5c404b7ff88f3fd3e9d77f86 (diff) |
Merge tag 'usb-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
USB for v4.20
With 63 non-merge commits, this is not a large merge window for USB
peripheral. The largest changes go to the UVC gadget driver which a
few folks have been improving.
Apart from UVC changes, we have a few more devices being added to
Renesas USB3 and DWC3 controller drivers and a couple minor bug fixes
on other drivers.
* tag 'usb-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (63 commits)
USB: net2280: Remove ->disconnect() callback from net2280_pullup()
usb: dwc2: disable power_down on rockchip devices
usb: gadget: udc: renesas_usb3: add support for r8a77990
dt-bindings: usb: renesas_usb3: add bindings for r8a77990
usb: gadget: udc: renesas_usb3: Add r8a774a1 support
usb: gadget: udc: renesas_usb3: Fix b-device mode for "workaround"
usb: dwc2: gadget: Add handler for WkupAlert interrupt
usb: dwc2: gadget: enable WKUP_ALERT interrupt
usb: dwc2: gadget: Program GREFCLK register
usb: dwc2: gadget: Add parameters for GREFCLK register
usb: dwc2: Add definitions for new registers
usb: dwc2: Update target (u)frame calculation
usb: dwc2: Add dwc2_gadget_dec_frame_num_by_one() function
usb: dwc2: Add core parameter for service interval support
usb: dwc2: Update registers definitions to support service interval
usb: renesas_usbhs: add support for R-Car E3
dt-bindings: usb: renesas_usbhs: add bindings for r8a77990
usb: renesas_usbhs: rcar3: Use OTG mode for R-Car D3
Revert "usb: renesas_usbhs: set the mode by using extcon state for non-otg channel"
usb: gadget: f_uac2: disable IN/OUT ep if unused
...
31 files changed, 1464 insertions, 930 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 9281e2aa38df..809765bd9573 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc | |||
@@ -12,6 +12,10 @@ Date: Dec 2014 | |||
12 | KernelVersion: 4.0 | 12 | KernelVersion: 4.0 |
13 | Description: Control descriptors | 13 | Description: Control descriptors |
14 | 14 | ||
15 | All attributes read only: | ||
16 | bInterfaceNumber - USB interface number for this | ||
17 | streaming interface | ||
18 | |||
15 | What: /config/usb-gadget/gadget/functions/uvc.name/control/class | 19 | What: /config/usb-gadget/gadget/functions/uvc.name/control/class |
16 | Date: Dec 2014 | 20 | Date: Dec 2014 |
17 | KernelVersion: 4.0 | 21 | KernelVersion: 4.0 |
@@ -109,6 +113,10 @@ Date: Dec 2014 | |||
109 | KernelVersion: 4.0 | 113 | KernelVersion: 4.0 |
110 | Description: Streaming descriptors | 114 | Description: Streaming descriptors |
111 | 115 | ||
116 | All attributes read only: | ||
117 | bInterfaceNumber - USB interface number for this | ||
118 | streaming interface | ||
119 | |||
112 | What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class | 120 | What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class |
113 | Date: Dec 2014 | 121 | Date: Dec 2014 |
114 | KernelVersion: 4.0 | 122 | KernelVersion: 4.0 |
@@ -160,6 +168,10 @@ Description: Specific MJPEG format descriptors | |||
160 | 168 | ||
161 | All attributes read only, | 169 | All attributes read only, |
162 | except bmaControls and bDefaultFrameIndex: | 170 | except bmaControls and bDefaultFrameIndex: |
171 | bFormatIndex - unique id for this format descriptor; | ||
172 | only defined after parent header is | ||
173 | linked into the streaming class; | ||
174 | read-only | ||
163 | bmaControls - this format's data for bmaControls in | 175 | bmaControls - this format's data for bmaControls in |
164 | the streaming header | 176 | the streaming header |
165 | bmInterfaceFlags - specifies interlace information, | 177 | bmInterfaceFlags - specifies interlace information, |
@@ -177,6 +189,10 @@ Date: Dec 2014 | |||
177 | KernelVersion: 4.0 | 189 | KernelVersion: 4.0 |
178 | Description: Specific MJPEG frame descriptors | 190 | Description: Specific MJPEG frame descriptors |
179 | 191 | ||
192 | bFrameIndex - unique id for this framedescriptor; | ||
193 | only defined after parent format is | ||
194 | linked into the streaming header; | ||
195 | read-only | ||
180 | dwFrameInterval - indicates how frame interval can be | 196 | dwFrameInterval - indicates how frame interval can be |
181 | programmed; a number of values | 197 | programmed; a number of values |
182 | separated by newline can be specified | 198 | separated by newline can be specified |
@@ -204,6 +220,10 @@ Date: Dec 2014 | |||
204 | KernelVersion: 4.0 | 220 | KernelVersion: 4.0 |
205 | Description: Specific uncompressed format descriptors | 221 | Description: Specific uncompressed format descriptors |
206 | 222 | ||
223 | bFormatIndex - unique id for this format descriptor; | ||
224 | only defined after parent header is | ||
225 | linked into the streaming class; | ||
226 | read-only | ||
207 | bmaControls - this format's data for bmaControls in | 227 | bmaControls - this format's data for bmaControls in |
208 | the streaming header | 228 | the streaming header |
209 | bmInterfaceFlags - specifies interlace information, | 229 | bmInterfaceFlags - specifies interlace information, |
@@ -224,6 +244,10 @@ Date: Dec 2014 | |||
224 | KernelVersion: 4.0 | 244 | KernelVersion: 4.0 |
225 | Description: Specific uncompressed frame descriptors | 245 | Description: Specific uncompressed frame descriptors |
226 | 246 | ||
247 | bFrameIndex - unique id for this framedescriptor; | ||
248 | only defined after parent format is | ||
249 | linked into the streaming header; | ||
250 | read-only | ||
227 | dwFrameInterval - indicates how frame interval can be | 251 | dwFrameInterval - indicates how frame interval can be |
228 | programmed; a number of values | 252 | programmed; a number of values |
229 | separated by newline can be specified | 253 | separated by newline can be specified |
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 3e4c38b806ac..636630fb92d7 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt | |||
@@ -19,6 +19,7 @@ Exception for clocks: | |||
19 | "cavium,octeon-7130-usb-uctl" | 19 | "cavium,octeon-7130-usb-uctl" |
20 | "qcom,dwc3" | 20 | "qcom,dwc3" |
21 | "samsung,exynos5250-dwusb3" | 21 | "samsung,exynos5250-dwusb3" |
22 | "samsung,exynos5433-dwusb3" | ||
22 | "samsung,exynos7-dwusb3" | 23 | "samsung,exynos7-dwusb3" |
23 | "sprd,sc9860-dwc3" | 24 | "sprd,sc9860-dwc3" |
24 | "st,stih407-dwc3" | 25 | "st,stih407-dwc3" |
diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt index c97374315049..b7111f43fa59 100644 --- a/Documentation/devicetree/bindings/usb/exynos-usb.txt +++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt | |||
@@ -83,6 +83,8 @@ Required properties: | |||
83 | - compatible: should be one of the following - | 83 | - compatible: should be one of the following - |
84 | "samsung,exynos5250-dwusb3": for USB 3.0 DWC3 controller on | 84 | "samsung,exynos5250-dwusb3": for USB 3.0 DWC3 controller on |
85 | Exynos5250/5420. | 85 | Exynos5250/5420. |
86 | "samsung,exynos5433-dwusb3": for USB 3.0 DWC3 controller on | ||
87 | Exynos5433. | ||
86 | "samsung,exynos7-dwusb3": for USB 3.0 DWC3 controller on Exynos7. | 88 | "samsung,exynos7-dwusb3": for USB 3.0 DWC3 controller on Exynos7. |
87 | - #address-cells, #size-cells : should be '1' if the device has sub-nodes | 89 | - #address-cells, #size-cells : should be '1' if the device has sub-nodes |
88 | with 'reg' property. | 90 | with 'reg' property. |
diff --git a/Documentation/devicetree/bindings/usb/renesas_usb3.txt b/Documentation/devicetree/bindings/usb/renesas_usb3.txt index b22f0a519991..d366555166d0 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usb3.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usb3.txt | |||
@@ -6,6 +6,7 @@ Required properties: | |||
6 | - "renesas,r8a7795-usb3-peri" | 6 | - "renesas,r8a7795-usb3-peri" |
7 | - "renesas,r8a7796-usb3-peri" | 7 | - "renesas,r8a7796-usb3-peri" |
8 | - "renesas,r8a77965-usb3-peri" | 8 | - "renesas,r8a77965-usb3-peri" |
9 | - "renesas,r8a77990-usb3-peri" | ||
9 | - "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 or RZ/G2 | 10 | - "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 or RZ/G2 |
10 | compatible device | 11 | compatible device |
11 | 12 | ||
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index cc9c93affa14..30bab8463c96 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h | |||
@@ -393,6 +393,20 @@ enum dwc2_ep0_state { | |||
393 | * 0 - No | 393 | * 0 - No |
394 | * 1 - Yes | 394 | * 1 - Yes |
395 | * @hird_threshold: Value of BESL or HIRD Threshold. | 395 | * @hird_threshold: Value of BESL or HIRD Threshold. |
396 | * @ref_clk_per: Indicates in terms of pico seconds the period | ||
397 | * of ref_clk. | ||
398 | * 62500 - 16MHz | ||
399 | * 58823 - 17MHz | ||
400 | * 52083 - 19.2MHz | ||
401 | * 50000 - 20MHz | ||
402 | * 41666 - 24MHz | ||
403 | * 33333 - 30MHz (default) | ||
404 | * 25000 - 40MHz | ||
405 | * @sof_cnt_wkup_alert: Indicates in term of number of SOF's after which | ||
406 | * the controller should generate an interrupt if the | ||
407 | * device had been in L1 state until that period. | ||
408 | * This is used by SW to initiate Remote WakeUp in the | ||
409 | * controller so as to sync to the uF number from the host. | ||
396 | * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO | 410 | * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO |
397 | * register. | 411 | * register. |
398 | * 0 - Deactivate the transceiver (default) | 412 | * 0 - Deactivate the transceiver (default) |
@@ -416,6 +430,9 @@ enum dwc2_ep0_state { | |||
416 | * back to DWC2_SPEED_PARAM_HIGH while device is gone. | 430 | * back to DWC2_SPEED_PARAM_HIGH while device is gone. |
417 | * 0 - No (default) | 431 | * 0 - No (default) |
418 | * 1 - Yes | 432 | * 1 - Yes |
433 | * @service_interval: Enable service interval based scheduling. | ||
434 | * 0 - No | ||
435 | * 1 - Yes | ||
419 | * | 436 | * |
420 | * The following parameters may be specified when starting the module. These | 437 | * The following parameters may be specified when starting the module. These |
421 | * parameters define how the DWC_otg controller should be configured. A | 438 | * parameters define how the DWC_otg controller should be configured. A |
@@ -461,6 +478,7 @@ struct dwc2_core_params { | |||
461 | bool lpm_clock_gating; | 478 | bool lpm_clock_gating; |
462 | bool besl; | 479 | bool besl; |
463 | bool hird_threshold_en; | 480 | bool hird_threshold_en; |
481 | bool service_interval; | ||
464 | u8 hird_threshold; | 482 | u8 hird_threshold; |
465 | bool activate_stm_fs_transceiver; | 483 | bool activate_stm_fs_transceiver; |
466 | bool ipg_isoc_en; | 484 | bool ipg_isoc_en; |
@@ -468,6 +486,10 @@ struct dwc2_core_params { | |||
468 | u32 max_transfer_size; | 486 | u32 max_transfer_size; |
469 | u32 ahbcfg; | 487 | u32 ahbcfg; |
470 | 488 | ||
489 | /* GREFCLK parameters */ | ||
490 | u32 ref_clk_per; | ||
491 | u16 sof_cnt_wkup_alert; | ||
492 | |||
471 | /* Host parameters */ | 493 | /* Host parameters */ |
472 | bool host_dma; | 494 | bool host_dma; |
473 | bool dma_desc_enable; | 495 | bool dma_desc_enable; |
@@ -605,6 +627,10 @@ struct dwc2_core_params { | |||
605 | * FIFO sizing is enabled 16 to 32768 | 627 | * FIFO sizing is enabled 16 to 32768 |
606 | * Actual maximum value is autodetected and also | 628 | * Actual maximum value is autodetected and also |
607 | * the default. | 629 | * the default. |
630 | * @service_interval_mode: For enabling service interval based scheduling in the | ||
631 | * controller. | ||
632 | * 0 - Disable | ||
633 | * 1 - Enable | ||
608 | */ | 634 | */ |
609 | struct dwc2_hw_params { | 635 | struct dwc2_hw_params { |
610 | unsigned op_mode:3; | 636 | unsigned op_mode:3; |
@@ -635,6 +661,7 @@ struct dwc2_hw_params { | |||
635 | unsigned utmi_phy_data_width:2; | 661 | unsigned utmi_phy_data_width:2; |
636 | unsigned lpm_mode:1; | 662 | unsigned lpm_mode:1; |
637 | unsigned ipg_isoc_en:1; | 663 | unsigned ipg_isoc_en:1; |
664 | unsigned service_interval_mode:1; | ||
638 | u32 snpsid; | 665 | u32 snpsid; |
639 | u32 dev_ep_dirs; | 666 | u32 dev_ep_dirs; |
640 | u32 g_tx_fifo_size[MAX_EPS_CHANNELS]; | 667 | u32 g_tx_fifo_size[MAX_EPS_CHANNELS]; |
@@ -1354,6 +1381,7 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg); | |||
1354 | int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg); | 1381 | int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg); |
1355 | int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg); | 1382 | int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg); |
1356 | void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg); | 1383 | void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg); |
1384 | void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg); | ||
1357 | #else | 1385 | #else |
1358 | static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2) | 1386 | static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2) |
1359 | { return 0; } | 1387 | { return 0; } |
@@ -1388,6 +1416,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) | |||
1388 | static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) | 1416 | static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) |
1389 | { return 0; } | 1417 | { return 0; } |
1390 | static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {} | 1418 | static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {} |
1419 | static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {} | ||
1391 | #endif | 1420 | #endif |
1392 | 1421 | ||
1393 | #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) | 1422 | #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) |
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index 22d015b0424f..7f62f4cdc265 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c | |||
@@ -701,6 +701,7 @@ static int params_show(struct seq_file *seq, void *v) | |||
701 | print_param(seq, p, besl); | 701 | print_param(seq, p, besl); |
702 | print_param(seq, p, hird_threshold_en); | 702 | print_param(seq, p, hird_threshold_en); |
703 | print_param(seq, p, hird_threshold); | 703 | print_param(seq, p, hird_threshold); |
704 | print_param(seq, p, service_interval); | ||
704 | print_param(seq, p, host_dma); | 705 | print_param(seq, p, host_dma); |
705 | print_param(seq, p, g_dma); | 706 | print_param(seq, p, g_dma); |
706 | print_param(seq, p, g_dma_desc); | 707 | print_param(seq, p, g_dma_desc); |
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 220c0f9b89b0..2d6d2c8244de 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c | |||
@@ -123,6 +123,24 @@ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep) | |||
123 | } | 123 | } |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * dwc2_gadget_dec_frame_num_by_one - Decrements the targeted frame number | ||
127 | * by one. | ||
128 | * @hs_ep: The endpoint. | ||
129 | * | ||
130 | * This function used in service interval based scheduling flow to calculate | ||
131 | * descriptor frame number filed value. For service interval mode frame | ||
132 | * number in descriptor should point to last (u)frame in the interval. | ||
133 | * | ||
134 | */ | ||
135 | static inline void dwc2_gadget_dec_frame_num_by_one(struct dwc2_hsotg_ep *hs_ep) | ||
136 | { | ||
137 | if (hs_ep->target_frame) | ||
138 | hs_ep->target_frame -= 1; | ||
139 | else | ||
140 | hs_ep->target_frame = DSTS_SOFFN_LIMIT; | ||
141 | } | ||
142 | |||
143 | /** | ||
126 | * dwc2_hsotg_en_gsint - enable one or more of the general interrupt | 144 | * dwc2_hsotg_en_gsint - enable one or more of the general interrupt |
127 | * @hsotg: The device state | 145 | * @hsotg: The device state |
128 | * @ints: A bitmask of the interrupts to enable | 146 | * @ints: A bitmask of the interrupts to enable |
@@ -228,6 +246,27 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) | |||
228 | } | 246 | } |
229 | 247 | ||
230 | /** | 248 | /** |
249 | * dwc2_gadget_wkup_alert_handler - Handler for WKUP_ALERT interrupt | ||
250 | * | ||
251 | * @hsotg: Programming view of the DWC_otg controller | ||
252 | * | ||
253 | */ | ||
254 | static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg) | ||
255 | { | ||
256 | u32 gintsts2; | ||
257 | u32 gintmsk2; | ||
258 | |||
259 | gintsts2 = dwc2_readl(hsotg, GINTSTS2); | ||
260 | gintmsk2 = dwc2_readl(hsotg, GINTMSK2); | ||
261 | |||
262 | if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) { | ||
263 | dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__); | ||
264 | dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT); | ||
265 | dwc2_set_bit(hsotg, DCFG, DCTL_RMTWKUPSIG); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /** | ||
231 | * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode | 270 | * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode |
232 | * TX FIFOs | 271 | * TX FIFOs |
233 | * | 272 | * |
@@ -2812,6 +2851,23 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) | |||
2812 | if (using_desc_dma(hsotg)) { | 2851 | if (using_desc_dma(hsotg)) { |
2813 | hs_ep->target_frame = hsotg->frame_number; | 2852 | hs_ep->target_frame = hsotg->frame_number; |
2814 | dwc2_gadget_incr_frame_num(hs_ep); | 2853 | dwc2_gadget_incr_frame_num(hs_ep); |
2854 | |||
2855 | /* In service interval mode target_frame must | ||
2856 | * be set to last (u)frame of the service interval. | ||
2857 | */ | ||
2858 | if (hsotg->params.service_interval) { | ||
2859 | /* Set target_frame to the first (u)frame of | ||
2860 | * the service interval | ||
2861 | */ | ||
2862 | hs_ep->target_frame &= ~hs_ep->interval + 1; | ||
2863 | |||
2864 | /* Set target_frame to the last (u)frame of | ||
2865 | * the service interval | ||
2866 | */ | ||
2867 | dwc2_gadget_incr_frame_num(hs_ep); | ||
2868 | dwc2_gadget_dec_frame_num_by_one(hs_ep); | ||
2869 | } | ||
2870 | |||
2815 | dwc2_gadget_start_isoc_ddma(hs_ep); | 2871 | dwc2_gadget_start_isoc_ddma(hs_ep); |
2816 | return; | 2872 | return; |
2817 | } | 2873 | } |
@@ -3109,6 +3165,8 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, | |||
3109 | dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); | 3165 | dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); |
3110 | } | 3166 | } |
3111 | 3167 | ||
3168 | static int dwc2_hsotg_ep_disable(struct usb_ep *ep); | ||
3169 | |||
3112 | /** | 3170 | /** |
3113 | * dwc2_hsotg_disconnect - disconnect service | 3171 | * dwc2_hsotg_disconnect - disconnect service |
3114 | * @hsotg: The device state. | 3172 | * @hsotg: The device state. |
@@ -3127,13 +3185,12 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) | |||
3127 | hsotg->connected = 0; | 3185 | hsotg->connected = 0; |
3128 | hsotg->test_mode = 0; | 3186 | hsotg->test_mode = 0; |
3129 | 3187 | ||
3188 | /* all endpoints should be shutdown */ | ||
3130 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { | 3189 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { |
3131 | if (hsotg->eps_in[ep]) | 3190 | if (hsotg->eps_in[ep]) |
3132 | kill_all_requests(hsotg, hsotg->eps_in[ep], | 3191 | dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); |
3133 | -ESHUTDOWN); | ||
3134 | if (hsotg->eps_out[ep]) | 3192 | if (hsotg->eps_out[ep]) |
3135 | kill_all_requests(hsotg, hsotg->eps_out[ep], | 3193 | dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); |
3136 | -ESHUTDOWN); | ||
3137 | } | 3194 | } |
3138 | 3195 | ||
3139 | call_gadget(hsotg, disconnect); | 3196 | call_gadget(hsotg, disconnect); |
@@ -3191,13 +3248,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, | |||
3191 | u32 val; | 3248 | u32 val; |
3192 | u32 usbcfg; | 3249 | u32 usbcfg; |
3193 | u32 dcfg = 0; | 3250 | u32 dcfg = 0; |
3251 | int ep; | ||
3194 | 3252 | ||
3195 | /* Kill any ep0 requests as controller will be reinitialized */ | 3253 | /* Kill any ep0 requests as controller will be reinitialized */ |
3196 | kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); | 3254 | kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); |
3197 | 3255 | ||
3198 | if (!is_usb_reset) | 3256 | if (!is_usb_reset) { |
3199 | if (dwc2_core_reset(hsotg, true)) | 3257 | if (dwc2_core_reset(hsotg, true)) |
3200 | return; | 3258 | return; |
3259 | } else { | ||
3260 | /* all endpoints should be shutdown */ | ||
3261 | for (ep = 1; ep < hsotg->num_of_eps; ep++) { | ||
3262 | if (hsotg->eps_in[ep]) | ||
3263 | dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); | ||
3264 | if (hsotg->eps_out[ep]) | ||
3265 | dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); | ||
3266 | } | ||
3267 | } | ||
3201 | 3268 | ||
3202 | /* | 3269 | /* |
3203 | * we must now enable ep0 ready for host detection and then | 3270 | * we must now enable ep0 ready for host detection and then |
@@ -3312,6 +3379,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, | |||
3312 | dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK); | 3379 | dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK); |
3313 | } | 3380 | } |
3314 | 3381 | ||
3382 | /* Enable Service Interval mode if supported */ | ||
3383 | if (using_desc_dma(hsotg) && hsotg->params.service_interval) | ||
3384 | dwc2_set_bit(hsotg, DCTL, DCTL_SERVICE_INTERVAL_SUPPORTED); | ||
3385 | |||
3315 | dwc2_writel(hsotg, 0, DAINTMSK); | 3386 | dwc2_writel(hsotg, 0, DAINTMSK); |
3316 | 3387 | ||
3317 | dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", | 3388 | dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", |
@@ -3368,6 +3439,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, | |||
3368 | /* configure the core to support LPM */ | 3439 | /* configure the core to support LPM */ |
3369 | dwc2_gadget_init_lpm(hsotg); | 3440 | dwc2_gadget_init_lpm(hsotg); |
3370 | 3441 | ||
3442 | /* program GREFCLK register if needed */ | ||
3443 | if (using_desc_dma(hsotg) && hsotg->params.service_interval) | ||
3444 | dwc2_gadget_program_ref_clk(hsotg); | ||
3445 | |||
3371 | /* must be at-least 3ms to allow bus to see disconnect */ | 3446 | /* must be at-least 3ms to allow bus to see disconnect */ |
3372 | mdelay(3); | 3447 | mdelay(3); |
3373 | 3448 | ||
@@ -3676,6 +3751,10 @@ irq_retry: | |||
3676 | if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) | 3751 | if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) |
3677 | goto irq_retry; | 3752 | goto irq_retry; |
3678 | 3753 | ||
3754 | /* Check WKUP_ALERT interrupt*/ | ||
3755 | if (hsotg->params.service_interval) | ||
3756 | dwc2_gadget_wkup_alert_handler(hsotg); | ||
3757 | |||
3679 | spin_unlock(&hsotg->lock); | 3758 | spin_unlock(&hsotg->lock); |
3680 | 3759 | ||
3681 | return IRQ_HANDLED; | 3760 | return IRQ_HANDLED; |
@@ -3993,6 +4072,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
3993 | unsigned long flags; | 4072 | unsigned long flags; |
3994 | u32 epctrl_reg; | 4073 | u32 epctrl_reg; |
3995 | u32 ctrl; | 4074 | u32 ctrl; |
4075 | int locked; | ||
3996 | 4076 | ||
3997 | dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep); | 4077 | dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep); |
3998 | 4078 | ||
@@ -4008,7 +4088,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
4008 | 4088 | ||
4009 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); | 4089 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); |
4010 | 4090 | ||
4011 | spin_lock_irqsave(&hsotg->lock, flags); | 4091 | locked = spin_is_locked(&hsotg->lock); |
4092 | if (!locked) | ||
4093 | spin_lock_irqsave(&hsotg->lock, flags); | ||
4012 | 4094 | ||
4013 | ctrl = dwc2_readl(hsotg, epctrl_reg); | 4095 | ctrl = dwc2_readl(hsotg, epctrl_reg); |
4014 | 4096 | ||
@@ -4032,7 +4114,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
4032 | hs_ep->fifo_index = 0; | 4114 | hs_ep->fifo_index = 0; |
4033 | hs_ep->fifo_size = 0; | 4115 | hs_ep->fifo_size = 0; |
4034 | 4116 | ||
4035 | spin_unlock_irqrestore(&hsotg->lock, flags); | 4117 | if (!locked) |
4118 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
4119 | |||
4036 | return 0; | 4120 | return 0; |
4037 | } | 4121 | } |
4038 | 4122 | ||
@@ -4944,6 +5028,29 @@ void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) | |||
4944 | val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0; | 5028 | val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0; |
4945 | dwc2_writel(hsotg, val, GLPMCFG); | 5029 | dwc2_writel(hsotg, val, GLPMCFG); |
4946 | dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG)); | 5030 | dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG)); |
5031 | |||
5032 | /* Unmask WKUP_ALERT Interrupt */ | ||
5033 | if (hsotg->params.service_interval) | ||
5034 | dwc2_set_bit(hsotg, GINTMSK2, GINTMSK2_WKUP_ALERT_INT_MSK); | ||
5035 | } | ||
5036 | |||
5037 | /** | ||
5038 | * dwc2_gadget_program_ref_clk - Program GREFCLK register in device mode | ||
5039 | * | ||
5040 | * @hsotg: Programming view of DWC_otg controller | ||
5041 | * | ||
5042 | */ | ||
5043 | void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) | ||
5044 | { | ||
5045 | u32 val = 0; | ||
5046 | |||
5047 | val |= GREFCLK_REF_CLK_MODE; | ||
5048 | val |= hsotg->params.ref_clk_per << GREFCLK_REFCLKPER_SHIFT; | ||
5049 | val |= hsotg->params.sof_cnt_wkup_alert << | ||
5050 | GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT; | ||
5051 | |||
5052 | dwc2_writel(hsotg, val, GREFCLK); | ||
5053 | dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK)); | ||
4947 | } | 5054 | } |
4948 | 5055 | ||
4949 | /** | 5056 | /** |
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2bd6e6bfc241..dd82fa516f3f 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c | |||
@@ -358,16 +358,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) | |||
358 | 358 | ||
359 | static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) | 359 | static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) |
360 | { | 360 | { |
361 | int ret; | 361 | if (hsotg->vbus_supply) |
362 | 362 | return regulator_enable(hsotg->vbus_supply); | |
363 | hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); | ||
364 | if (IS_ERR(hsotg->vbus_supply)) { | ||
365 | ret = PTR_ERR(hsotg->vbus_supply); | ||
366 | hsotg->vbus_supply = NULL; | ||
367 | return ret == -ENODEV ? 0 : ret; | ||
368 | } | ||
369 | 363 | ||
370 | return regulator_enable(hsotg->vbus_supply); | 364 | return 0; |
371 | } | 365 | } |
372 | 366 | ||
373 | static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) | 367 | static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) |
@@ -1328,14 +1322,11 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, | |||
1328 | u32 remaining_count; | 1322 | u32 remaining_count; |
1329 | u32 byte_count; | 1323 | u32 byte_count; |
1330 | u32 dword_count; | 1324 | u32 dword_count; |
1331 | u32 __iomem *data_fifo; | ||
1332 | u32 *data_buf = (u32 *)chan->xfer_buf; | 1325 | u32 *data_buf = (u32 *)chan->xfer_buf; |
1333 | 1326 | ||
1334 | if (dbg_hc(chan)) | 1327 | if (dbg_hc(chan)) |
1335 | dev_vdbg(hsotg->dev, "%s()\n", __func__); | 1328 | dev_vdbg(hsotg->dev, "%s()\n", __func__); |
1336 | 1329 | ||
1337 | data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num)); | ||
1338 | |||
1339 | remaining_count = chan->xfer_len - chan->xfer_count; | 1330 | remaining_count = chan->xfer_len - chan->xfer_count; |
1340 | if (remaining_count > chan->max_packet) | 1331 | if (remaining_count > chan->max_packet) |
1341 | byte_count = chan->max_packet; | 1332 | byte_count = chan->max_packet; |
@@ -3564,6 +3555,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, | |||
3564 | u32 port_status; | 3555 | u32 port_status; |
3565 | u32 speed; | 3556 | u32 speed; |
3566 | u32 pcgctl; | 3557 | u32 pcgctl; |
3558 | u32 pwr; | ||
3567 | 3559 | ||
3568 | switch (typereq) { | 3560 | switch (typereq) { |
3569 | case ClearHubFeature: | 3561 | case ClearHubFeature: |
@@ -3612,8 +3604,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, | |||
3612 | dev_dbg(hsotg->dev, | 3604 | dev_dbg(hsotg->dev, |
3613 | "ClearPortFeature USB_PORT_FEAT_POWER\n"); | 3605 | "ClearPortFeature USB_PORT_FEAT_POWER\n"); |
3614 | hprt0 = dwc2_read_hprt0(hsotg); | 3606 | hprt0 = dwc2_read_hprt0(hsotg); |
3607 | pwr = hprt0 & HPRT0_PWR; | ||
3615 | hprt0 &= ~HPRT0_PWR; | 3608 | hprt0 &= ~HPRT0_PWR; |
3616 | dwc2_writel(hsotg, hprt0, HPRT0); | 3609 | dwc2_writel(hsotg, hprt0, HPRT0); |
3610 | if (pwr) | ||
3611 | dwc2_vbus_supply_exit(hsotg); | ||
3617 | break; | 3612 | break; |
3618 | 3613 | ||
3619 | case USB_PORT_FEAT_INDICATOR: | 3614 | case USB_PORT_FEAT_INDICATOR: |
@@ -3823,8 +3818,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, | |||
3823 | dev_dbg(hsotg->dev, | 3818 | dev_dbg(hsotg->dev, |
3824 | "SetPortFeature - USB_PORT_FEAT_POWER\n"); | 3819 | "SetPortFeature - USB_PORT_FEAT_POWER\n"); |
3825 | hprt0 = dwc2_read_hprt0(hsotg); | 3820 | hprt0 = dwc2_read_hprt0(hsotg); |
3821 | pwr = hprt0 & HPRT0_PWR; | ||
3826 | hprt0 |= HPRT0_PWR; | 3822 | hprt0 |= HPRT0_PWR; |
3827 | dwc2_writel(hsotg, hprt0, HPRT0); | 3823 | dwc2_writel(hsotg, hprt0, HPRT0); |
3824 | if (!pwr) | ||
3825 | dwc2_vbus_supply_init(hsotg); | ||
3828 | break; | 3826 | break; |
3829 | 3827 | ||
3830 | case USB_PORT_FEAT_RESET: | 3828 | case USB_PORT_FEAT_RESET: |
@@ -3841,6 +3839,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, | |||
3841 | dwc2_writel(hsotg, 0, PCGCTL); | 3839 | dwc2_writel(hsotg, 0, PCGCTL); |
3842 | 3840 | ||
3843 | hprt0 = dwc2_read_hprt0(hsotg); | 3841 | hprt0 = dwc2_read_hprt0(hsotg); |
3842 | pwr = hprt0 & HPRT0_PWR; | ||
3844 | /* Clear suspend bit if resetting from suspend state */ | 3843 | /* Clear suspend bit if resetting from suspend state */ |
3845 | hprt0 &= ~HPRT0_SUSP; | 3844 | hprt0 &= ~HPRT0_SUSP; |
3846 | 3845 | ||
@@ -3854,6 +3853,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, | |||
3854 | dev_dbg(hsotg->dev, | 3853 | dev_dbg(hsotg->dev, |
3855 | "In host mode, hprt0=%08x\n", hprt0); | 3854 | "In host mode, hprt0=%08x\n", hprt0); |
3856 | dwc2_writel(hsotg, hprt0, HPRT0); | 3855 | dwc2_writel(hsotg, hprt0, HPRT0); |
3856 | if (!pwr) | ||
3857 | dwc2_vbus_supply_init(hsotg); | ||
3857 | } | 3858 | } |
3858 | 3859 | ||
3859 | /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ | 3860 | /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ |
@@ -4393,6 +4394,8 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) | |||
4393 | struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); | 4394 | struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); |
4394 | struct usb_bus *bus = hcd_to_bus(hcd); | 4395 | struct usb_bus *bus = hcd_to_bus(hcd); |
4395 | unsigned long flags; | 4396 | unsigned long flags; |
4397 | u32 hprt0; | ||
4398 | int ret; | ||
4396 | 4399 | ||
4397 | dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); | 4400 | dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); |
4398 | 4401 | ||
@@ -4408,6 +4411,17 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) | |||
4408 | 4411 | ||
4409 | dwc2_hcd_reinit(hsotg); | 4412 | dwc2_hcd_reinit(hsotg); |
4410 | 4413 | ||
4414 | hprt0 = dwc2_read_hprt0(hsotg); | ||
4415 | /* Has vbus power been turned on in dwc2_core_host_init ? */ | ||
4416 | if (hprt0 & HPRT0_PWR) { | ||
4417 | /* Enable external vbus supply before resuming root hub */ | ||
4418 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
4419 | ret = dwc2_vbus_supply_init(hsotg); | ||
4420 | if (ret) | ||
4421 | return ret; | ||
4422 | spin_lock_irqsave(&hsotg->lock, flags); | ||
4423 | } | ||
4424 | |||
4411 | /* Initialize and connect root hub if one is not already attached */ | 4425 | /* Initialize and connect root hub if one is not already attached */ |
4412 | if (bus->root_hub) { | 4426 | if (bus->root_hub) { |
4413 | dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n"); | 4427 | dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n"); |
@@ -4417,7 +4431,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) | |||
4417 | 4431 | ||
4418 | spin_unlock_irqrestore(&hsotg->lock, flags); | 4432 | spin_unlock_irqrestore(&hsotg->lock, flags); |
4419 | 4433 | ||
4420 | return dwc2_vbus_supply_init(hsotg); | 4434 | return 0; |
4421 | } | 4435 | } |
4422 | 4436 | ||
4423 | /* | 4437 | /* |
@@ -4428,6 +4442,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) | |||
4428 | { | 4442 | { |
4429 | struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); | 4443 | struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); |
4430 | unsigned long flags; | 4444 | unsigned long flags; |
4445 | u32 hprt0; | ||
4431 | 4446 | ||
4432 | /* Turn off all host-specific interrupts */ | 4447 | /* Turn off all host-specific interrupts */ |
4433 | dwc2_disable_host_interrupts(hsotg); | 4448 | dwc2_disable_host_interrupts(hsotg); |
@@ -4436,6 +4451,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) | |||
4436 | synchronize_irq(hcd->irq); | 4451 | synchronize_irq(hcd->irq); |
4437 | 4452 | ||
4438 | spin_lock_irqsave(&hsotg->lock, flags); | 4453 | spin_lock_irqsave(&hsotg->lock, flags); |
4454 | hprt0 = dwc2_read_hprt0(hsotg); | ||
4439 | /* Ensure hcd is disconnected */ | 4455 | /* Ensure hcd is disconnected */ |
4440 | dwc2_hcd_disconnect(hsotg, true); | 4456 | dwc2_hcd_disconnect(hsotg, true); |
4441 | dwc2_hcd_stop(hsotg); | 4457 | dwc2_hcd_stop(hsotg); |
@@ -4444,7 +4460,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) | |||
4444 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 4460 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
4445 | spin_unlock_irqrestore(&hsotg->lock, flags); | 4461 | spin_unlock_irqrestore(&hsotg->lock, flags); |
4446 | 4462 | ||
4447 | dwc2_vbus_supply_exit(hsotg); | 4463 | /* keep balanced supply init/exit by checking HPRT0_PWR */ |
4464 | if (hprt0 & HPRT0_PWR) | ||
4465 | dwc2_vbus_supply_exit(hsotg); | ||
4448 | 4466 | ||
4449 | usleep_range(1000, 3000); | 4467 | usleep_range(1000, 3000); |
4450 | } | 4468 | } |
@@ -4482,7 +4500,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) | |||
4482 | hprt0 |= HPRT0_SUSP; | 4500 | hprt0 |= HPRT0_SUSP; |
4483 | hprt0 &= ~HPRT0_PWR; | 4501 | hprt0 &= ~HPRT0_PWR; |
4484 | dwc2_writel(hsotg, hprt0, HPRT0); | 4502 | dwc2_writel(hsotg, hprt0, HPRT0); |
4503 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
4485 | dwc2_vbus_supply_exit(hsotg); | 4504 | dwc2_vbus_supply_exit(hsotg); |
4505 | spin_lock_irqsave(&hsotg->lock, flags); | ||
4486 | } | 4506 | } |
4487 | 4507 | ||
4488 | /* Enter partial_power_down */ | 4508 | /* Enter partial_power_down */ |
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 0ca8e7bc7aaf..2b1ea441b7d4 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h | |||
@@ -312,6 +312,7 @@ | |||
312 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 | 312 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 |
313 | #define GHWCFG4_ACG_SUPPORTED BIT(12) | 313 | #define GHWCFG4_ACG_SUPPORTED BIT(12) |
314 | #define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11) | 314 | #define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11) |
315 | #define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10) | ||
315 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 | 316 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 |
316 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 | 317 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 |
317 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 | 318 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 |
@@ -404,6 +405,19 @@ | |||
404 | #define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0) | 405 | #define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0) |
405 | #define ADPCTL_PRB_DSCHRG_SHIFT 0 | 406 | #define ADPCTL_PRB_DSCHRG_SHIFT 0 |
406 | 407 | ||
408 | #define GREFCLK HSOTG_REG(0x0064) | ||
409 | #define GREFCLK_REFCLKPER_MASK (0x1ffff << 15) | ||
410 | #define GREFCLK_REFCLKPER_SHIFT 15 | ||
411 | #define GREFCLK_REF_CLK_MODE BIT(14) | ||
412 | #define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff) | ||
413 | #define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0 | ||
414 | |||
415 | #define GINTMSK2 HSOTG_REG(0x0068) | ||
416 | #define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0) | ||
417 | |||
418 | #define GINTSTS2 HSOTG_REG(0x006c) | ||
419 | #define GINTSTS2_WKUP_ALERT_INT BIT(0) | ||
420 | |||
407 | #define HPTXFSIZ HSOTG_REG(0x100) | 421 | #define HPTXFSIZ HSOTG_REG(0x100) |
408 | /* Use FIFOSIZE_* constants to access this register */ | 422 | /* Use FIFOSIZE_* constants to access this register */ |
409 | 423 | ||
@@ -443,6 +457,7 @@ | |||
443 | #define DCFG_DEVSPD_FS48 3 | 457 | #define DCFG_DEVSPD_FS48 3 |
444 | 458 | ||
445 | #define DCTL HSOTG_REG(0x804) | 459 | #define DCTL HSOTG_REG(0x804) |
460 | #define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19) | ||
446 | #define DCTL_PWRONPRGDONE BIT(11) | 461 | #define DCTL_PWRONPRGDONE BIT(11) |
447 | #define DCTL_CGOUTNAK BIT(10) | 462 | #define DCTL_CGOUTNAK BIT(10) |
448 | #define DCTL_SGOUTNAK BIT(9) | 463 | #define DCTL_SGOUTNAK BIT(9) |
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index bf7052e037d6..7c1b6938f212 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c | |||
@@ -81,6 +81,7 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) | |||
81 | p->host_perio_tx_fifo_size = 256; | 81 | p->host_perio_tx_fifo_size = 256; |
82 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << | 82 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << |
83 | GAHBCFG_HBSTLEN_SHIFT; | 83 | GAHBCFG_HBSTLEN_SHIFT; |
84 | p->power_down = 0; | ||
84 | } | 85 | } |
85 | 86 | ||
86 | static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) | 87 | static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) |
@@ -299,9 +300,12 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) | |||
299 | p->hird_threshold_en = true; | 300 | p->hird_threshold_en = true; |
300 | p->hird_threshold = 4; | 301 | p->hird_threshold = 4; |
301 | p->ipg_isoc_en = false; | 302 | p->ipg_isoc_en = false; |
303 | p->service_interval = false; | ||
302 | p->max_packet_count = hw->max_packet_count; | 304 | p->max_packet_count = hw->max_packet_count; |
303 | p->max_transfer_size = hw->max_transfer_size; | 305 | p->max_transfer_size = hw->max_transfer_size; |
304 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT; | 306 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT; |
307 | p->ref_clk_per = 33333; | ||
308 | p->sof_cnt_wkup_alert = 100; | ||
305 | 309 | ||
306 | if ((hsotg->dr_mode == USB_DR_MODE_HOST) || | 310 | if ((hsotg->dr_mode == USB_DR_MODE_HOST) || |
307 | (hsotg->dr_mode == USB_DR_MODE_OTG)) { | 311 | (hsotg->dr_mode == USB_DR_MODE_OTG)) { |
@@ -592,6 +596,7 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg) | |||
592 | CHECK_BOOL(besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)); | 596 | CHECK_BOOL(besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)); |
593 | CHECK_BOOL(hird_threshold_en, hsotg->params.lpm); | 597 | CHECK_BOOL(hird_threshold_en, hsotg->params.lpm); |
594 | CHECK_RANGE(hird_threshold, 0, hsotg->params.besl ? 12 : 7, 0); | 598 | CHECK_RANGE(hird_threshold, 0, hsotg->params.besl ? 12 : 7, 0); |
599 | CHECK_BOOL(service_interval, hw->service_interval_mode); | ||
595 | CHECK_RANGE(max_packet_count, | 600 | CHECK_RANGE(max_packet_count, |
596 | 15, hw->max_packet_count, | 601 | 15, hw->max_packet_count, |
597 | hw->max_packet_count); | 602 | hw->max_packet_count); |
@@ -780,6 +785,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) | |||
780 | GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; | 785 | GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; |
781 | hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED); | 786 | hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED); |
782 | hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED); | 787 | hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED); |
788 | hw->service_interval_mode = !!(hwcfg4 & | ||
789 | GHWCFG4_SERVICE_INTERVAL_SUPPORTED); | ||
783 | 790 | ||
784 | /* fifo sizes */ | 791 | /* fifo sizes */ |
785 | hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> | 792 | hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> |
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 577642895b57..c0b64d483552 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c | |||
@@ -432,6 +432,14 @@ static int dwc2_driver_probe(struct platform_device *dev) | |||
432 | if (retval) | 432 | if (retval) |
433 | return retval; | 433 | return retval; |
434 | 434 | ||
435 | hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); | ||
436 | if (IS_ERR(hsotg->vbus_supply)) { | ||
437 | retval = PTR_ERR(hsotg->vbus_supply); | ||
438 | hsotg->vbus_supply = NULL; | ||
439 | if (retval != -ENODEV) | ||
440 | return retval; | ||
441 | } | ||
442 | |||
435 | retval = dwc2_lowlevel_hw_enable(hsotg); | 443 | retval = dwc2_lowlevel_hw_enable(hsotg); |
436 | if (retval) | 444 | if (retval) |
437 | return retval; | 445 | return retval; |
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 518ead12458d..1a0404fda596 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig | |||
@@ -113,7 +113,7 @@ config USB_DWC3_ST | |||
113 | 113 | ||
114 | config USB_DWC3_QCOM | 114 | config USB_DWC3_QCOM |
115 | tristate "Qualcomm Platform" | 115 | tristate "Qualcomm Platform" |
116 | depends on ARCH_QCOM || COMPILE_TEST | 116 | depends on EXTCON && (ARCH_QCOM || COMPILE_TEST) |
117 | depends on OF | 117 | depends on OF |
118 | default USB_DWC3 | 118 | default USB_DWC3 |
119 | help | 119 | help |
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 88c80fcc39f5..becfbb87f791 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -756,7 +756,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) | |||
756 | 756 | ||
757 | /* check if current dwc3 is on simulation board */ | 757 | /* check if current dwc3 is on simulation board */ |
758 | if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { | 758 | if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { |
759 | dev_info(dwc->dev, "Running with FPGA optmizations\n"); | 759 | dev_info(dwc->dev, "Running with FPGA optimizations\n"); |
760 | dwc->is_fpga = true; | 760 | dwc->is_fpga = true; |
761 | } | 761 | } |
762 | 762 | ||
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index a94fb1ba8f2c..cb7fcd7c0ad8 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c | |||
@@ -13,80 +13,30 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/usb/otg.h> | ||
17 | #include <linux/usb/usb_phy_generic.h> | ||
18 | #include <linux/of.h> | 16 | #include <linux/of.h> |
19 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
20 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
21 | 19 | ||
20 | #define DWC3_EXYNOS_MAX_CLOCKS 4 | ||
21 | |||
22 | struct dwc3_exynos_driverdata { | ||
23 | const char *clk_names[DWC3_EXYNOS_MAX_CLOCKS]; | ||
24 | int num_clks; | ||
25 | int suspend_clk_idx; | ||
26 | }; | ||
27 | |||
22 | struct dwc3_exynos { | 28 | struct dwc3_exynos { |
23 | struct platform_device *usb2_phy; | ||
24 | struct platform_device *usb3_phy; | ||
25 | struct device *dev; | 29 | struct device *dev; |
26 | 30 | ||
27 | struct clk *clk; | 31 | const char **clk_names; |
28 | struct clk *susp_clk; | 32 | struct clk *clks[DWC3_EXYNOS_MAX_CLOCKS]; |
29 | struct clk *axius_clk; | 33 | int num_clks; |
34 | int suspend_clk_idx; | ||
30 | 35 | ||
31 | struct regulator *vdd33; | 36 | struct regulator *vdd33; |
32 | struct regulator *vdd10; | 37 | struct regulator *vdd10; |
33 | }; | 38 | }; |
34 | 39 | ||
35 | static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) | ||
36 | { | ||
37 | struct usb_phy_generic_platform_data pdata; | ||
38 | struct platform_device *pdev; | ||
39 | int ret; | ||
40 | |||
41 | memset(&pdata, 0x00, sizeof(pdata)); | ||
42 | |||
43 | pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO); | ||
44 | if (!pdev) | ||
45 | return -ENOMEM; | ||
46 | |||
47 | exynos->usb2_phy = pdev; | ||
48 | pdata.type = USB_PHY_TYPE_USB2; | ||
49 | pdata.gpio_reset = -1; | ||
50 | |||
51 | ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata)); | ||
52 | if (ret) | ||
53 | goto err1; | ||
54 | |||
55 | pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO); | ||
56 | if (!pdev) { | ||
57 | ret = -ENOMEM; | ||
58 | goto err1; | ||
59 | } | ||
60 | |||
61 | exynos->usb3_phy = pdev; | ||
62 | pdata.type = USB_PHY_TYPE_USB3; | ||
63 | |||
64 | ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata)); | ||
65 | if (ret) | ||
66 | goto err2; | ||
67 | |||
68 | ret = platform_device_add(exynos->usb2_phy); | ||
69 | if (ret) | ||
70 | goto err2; | ||
71 | |||
72 | ret = platform_device_add(exynos->usb3_phy); | ||
73 | if (ret) | ||
74 | goto err3; | ||
75 | |||
76 | return 0; | ||
77 | |||
78 | err3: | ||
79 | platform_device_del(exynos->usb2_phy); | ||
80 | |||
81 | err2: | ||
82 | platform_device_put(exynos->usb3_phy); | ||
83 | |||
84 | err1: | ||
85 | platform_device_put(exynos->usb2_phy); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int dwc3_exynos_remove_child(struct device *dev, void *unused) | 40 | static int dwc3_exynos_remove_child(struct device *dev, void *unused) |
91 | { | 41 | { |
92 | struct platform_device *pdev = to_platform_device(dev); | 42 | struct platform_device *pdev = to_platform_device(dev); |
@@ -101,47 +51,42 @@ static int dwc3_exynos_probe(struct platform_device *pdev) | |||
101 | struct dwc3_exynos *exynos; | 51 | struct dwc3_exynos *exynos; |
102 | struct device *dev = &pdev->dev; | 52 | struct device *dev = &pdev->dev; |
103 | struct device_node *node = dev->of_node; | 53 | struct device_node *node = dev->of_node; |
104 | 54 | const struct dwc3_exynos_driverdata *driver_data; | |
105 | int ret; | 55 | int i, ret; |
106 | 56 | ||
107 | exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); | 57 | exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); |
108 | if (!exynos) | 58 | if (!exynos) |
109 | return -ENOMEM; | 59 | return -ENOMEM; |
110 | 60 | ||
111 | platform_set_drvdata(pdev, exynos); | 61 | driver_data = of_device_get_match_data(dev); |
62 | exynos->dev = dev; | ||
63 | exynos->num_clks = driver_data->num_clks; | ||
64 | exynos->clk_names = (const char **)driver_data->clk_names; | ||
65 | exynos->suspend_clk_idx = driver_data->suspend_clk_idx; | ||
112 | 66 | ||
113 | exynos->dev = dev; | 67 | platform_set_drvdata(pdev, exynos); |
114 | 68 | ||
115 | exynos->clk = devm_clk_get(dev, "usbdrd30"); | 69 | for (i = 0; i < exynos->num_clks; i++) { |
116 | if (IS_ERR(exynos->clk)) { | 70 | exynos->clks[i] = devm_clk_get(dev, exynos->clk_names[i]); |
117 | dev_err(dev, "couldn't get clock\n"); | 71 | if (IS_ERR(exynos->clks[i])) { |
118 | return -EINVAL; | 72 | dev_err(dev, "failed to get clock: %s\n", |
73 | exynos->clk_names[i]); | ||
74 | return PTR_ERR(exynos->clks[i]); | ||
75 | } | ||
119 | } | 76 | } |
120 | ret = clk_prepare_enable(exynos->clk); | ||
121 | if (ret) | ||
122 | return ret; | ||
123 | 77 | ||
124 | exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk"); | 78 | for (i = 0; i < exynos->num_clks; i++) { |
125 | if (IS_ERR(exynos->susp_clk)) | 79 | ret = clk_prepare_enable(exynos->clks[i]); |
126 | exynos->susp_clk = NULL; | 80 | if (ret) { |
127 | ret = clk_prepare_enable(exynos->susp_clk); | 81 | while (--i > 0) |
128 | if (ret) | 82 | clk_disable_unprepare(exynos->clks[i]); |
129 | goto susp_clk_err; | 83 | return ret; |
130 | |||
131 | if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) { | ||
132 | exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk"); | ||
133 | if (IS_ERR(exynos->axius_clk)) { | ||
134 | dev_err(dev, "no AXI UpScaler clk specified\n"); | ||
135 | ret = -ENODEV; | ||
136 | goto axius_clk_err; | ||
137 | } | 84 | } |
138 | ret = clk_prepare_enable(exynos->axius_clk); | ||
139 | if (ret) | ||
140 | goto axius_clk_err; | ||
141 | } else { | ||
142 | exynos->axius_clk = NULL; | ||
143 | } | 85 | } |
144 | 86 | ||
87 | if (exynos->suspend_clk_idx >= 0) | ||
88 | clk_prepare_enable(exynos->clks[exynos->suspend_clk_idx]); | ||
89 | |||
145 | exynos->vdd33 = devm_regulator_get(dev, "vdd33"); | 90 | exynos->vdd33 = devm_regulator_get(dev, "vdd33"); |
146 | if (IS_ERR(exynos->vdd33)) { | 91 | if (IS_ERR(exynos->vdd33)) { |
147 | ret = PTR_ERR(exynos->vdd33); | 92 | ret = PTR_ERR(exynos->vdd33); |
@@ -164,12 +109,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev) | |||
164 | goto vdd10_err; | 109 | goto vdd10_err; |
165 | } | 110 | } |
166 | 111 | ||
167 | ret = dwc3_exynos_register_phys(exynos); | ||
168 | if (ret) { | ||
169 | dev_err(dev, "couldn't register PHYs\n"); | ||
170 | goto phys_err; | ||
171 | } | ||
172 | |||
173 | if (node) { | 112 | if (node) { |
174 | ret = of_platform_populate(node, NULL, NULL, dev); | 113 | ret = of_platform_populate(node, NULL, NULL, dev); |
175 | if (ret) { | 114 | if (ret) { |
@@ -185,32 +124,31 @@ static int dwc3_exynos_probe(struct platform_device *pdev) | |||
185 | return 0; | 124 | return 0; |
186 | 125 | ||
187 | populate_err: | 126 | populate_err: |
188 | platform_device_unregister(exynos->usb2_phy); | ||
189 | platform_device_unregister(exynos->usb3_phy); | ||
190 | phys_err: | ||
191 | regulator_disable(exynos->vdd10); | 127 | regulator_disable(exynos->vdd10); |
192 | vdd10_err: | 128 | vdd10_err: |
193 | regulator_disable(exynos->vdd33); | 129 | regulator_disable(exynos->vdd33); |
194 | vdd33_err: | 130 | vdd33_err: |
195 | clk_disable_unprepare(exynos->axius_clk); | 131 | for (i = exynos->num_clks - 1; i >= 0; i--) |
196 | axius_clk_err: | 132 | clk_disable_unprepare(exynos->clks[i]); |
197 | clk_disable_unprepare(exynos->susp_clk); | 133 | |
198 | susp_clk_err: | 134 | if (exynos->suspend_clk_idx >= 0) |
199 | clk_disable_unprepare(exynos->clk); | 135 | clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]); |
136 | |||
200 | return ret; | 137 | return ret; |
201 | } | 138 | } |
202 | 139 | ||
203 | static int dwc3_exynos_remove(struct platform_device *pdev) | 140 | static int dwc3_exynos_remove(struct platform_device *pdev) |
204 | { | 141 | { |
205 | struct dwc3_exynos *exynos = platform_get_drvdata(pdev); | 142 | struct dwc3_exynos *exynos = platform_get_drvdata(pdev); |
143 | int i; | ||
206 | 144 | ||
207 | device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child); | 145 | device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child); |
208 | platform_device_unregister(exynos->usb2_phy); | ||
209 | platform_device_unregister(exynos->usb3_phy); | ||
210 | 146 | ||
211 | clk_disable_unprepare(exynos->axius_clk); | 147 | for (i = exynos->num_clks - 1; i >= 0; i--) |
212 | clk_disable_unprepare(exynos->susp_clk); | 148 | clk_disable_unprepare(exynos->clks[i]); |
213 | clk_disable_unprepare(exynos->clk); | 149 | |
150 | if (exynos->suspend_clk_idx >= 0) | ||
151 | clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]); | ||
214 | 152 | ||
215 | regulator_disable(exynos->vdd33); | 153 | regulator_disable(exynos->vdd33); |
216 | regulator_disable(exynos->vdd10); | 154 | regulator_disable(exynos->vdd10); |
@@ -218,10 +156,36 @@ static int dwc3_exynos_remove(struct platform_device *pdev) | |||
218 | return 0; | 156 | return 0; |
219 | } | 157 | } |
220 | 158 | ||
159 | static const struct dwc3_exynos_driverdata exynos5250_drvdata = { | ||
160 | .clk_names = { "usbdrd30" }, | ||
161 | .num_clks = 1, | ||
162 | .suspend_clk_idx = -1, | ||
163 | }; | ||
164 | |||
165 | static const struct dwc3_exynos_driverdata exynos5433_drvdata = { | ||
166 | .clk_names = { "aclk", "susp_clk", "pipe_pclk", "phyclk" }, | ||
167 | .num_clks = 4, | ||
168 | .suspend_clk_idx = 1, | ||
169 | }; | ||
170 | |||
171 | static const struct dwc3_exynos_driverdata exynos7_drvdata = { | ||
172 | .clk_names = { "usbdrd30", "usbdrd30_susp_clk", "usbdrd30_axius_clk" }, | ||
173 | .num_clks = 3, | ||
174 | .suspend_clk_idx = 1, | ||
175 | }; | ||
176 | |||
221 | static const struct of_device_id exynos_dwc3_match[] = { | 177 | static const struct of_device_id exynos_dwc3_match[] = { |
222 | { .compatible = "samsung,exynos5250-dwusb3" }, | 178 | { |
223 | { .compatible = "samsung,exynos7-dwusb3" }, | 179 | .compatible = "samsung,exynos5250-dwusb3", |
224 | {}, | 180 | .data = &exynos5250_drvdata, |
181 | }, { | ||
182 | .compatible = "samsung,exynos5433-dwusb3", | ||
183 | .data = &exynos5433_drvdata, | ||
184 | }, { | ||
185 | .compatible = "samsung,exynos7-dwusb3", | ||
186 | .data = &exynos7_drvdata, | ||
187 | }, { | ||
188 | } | ||
225 | }; | 189 | }; |
226 | MODULE_DEVICE_TABLE(of, exynos_dwc3_match); | 190 | MODULE_DEVICE_TABLE(of, exynos_dwc3_match); |
227 | 191 | ||
@@ -229,9 +193,10 @@ MODULE_DEVICE_TABLE(of, exynos_dwc3_match); | |||
229 | static int dwc3_exynos_suspend(struct device *dev) | 193 | static int dwc3_exynos_suspend(struct device *dev) |
230 | { | 194 | { |
231 | struct dwc3_exynos *exynos = dev_get_drvdata(dev); | 195 | struct dwc3_exynos *exynos = dev_get_drvdata(dev); |
196 | int i; | ||
232 | 197 | ||
233 | clk_disable(exynos->axius_clk); | 198 | for (i = exynos->num_clks - 1; i >= 0; i--) |
234 | clk_disable(exynos->clk); | 199 | clk_disable_unprepare(exynos->clks[i]); |
235 | 200 | ||
236 | regulator_disable(exynos->vdd33); | 201 | regulator_disable(exynos->vdd33); |
237 | regulator_disable(exynos->vdd10); | 202 | regulator_disable(exynos->vdd10); |
@@ -242,7 +207,7 @@ static int dwc3_exynos_suspend(struct device *dev) | |||
242 | static int dwc3_exynos_resume(struct device *dev) | 207 | static int dwc3_exynos_resume(struct device *dev) |
243 | { | 208 | { |
244 | struct dwc3_exynos *exynos = dev_get_drvdata(dev); | 209 | struct dwc3_exynos *exynos = dev_get_drvdata(dev); |
245 | int ret; | 210 | int i, ret; |
246 | 211 | ||
247 | ret = regulator_enable(exynos->vdd33); | 212 | ret = regulator_enable(exynos->vdd33); |
248 | if (ret) { | 213 | if (ret) { |
@@ -255,13 +220,14 @@ static int dwc3_exynos_resume(struct device *dev) | |||
255 | return ret; | 220 | return ret; |
256 | } | 221 | } |
257 | 222 | ||
258 | clk_enable(exynos->clk); | 223 | for (i = 0; i < exynos->num_clks; i++) { |
259 | clk_enable(exynos->axius_clk); | 224 | ret = clk_prepare_enable(exynos->clks[i]); |
260 | 225 | if (ret) { | |
261 | /* runtime set active to reflect active state. */ | 226 | while (--i > 0) |
262 | pm_runtime_disable(dev); | 227 | clk_disable_unprepare(exynos->clks[i]); |
263 | pm_runtime_set_active(dev); | 228 | return ret; |
264 | pm_runtime_enable(dev); | 229 | } |
230 | } | ||
265 | 231 | ||
266 | return 0; | 232 | return 0; |
267 | } | 233 | } |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2b53194081ba..679c12e14522 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -270,27 +270,36 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | |||
270 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; | 270 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; |
271 | struct dwc3 *dwc = dep->dwc; | 271 | struct dwc3 *dwc = dep->dwc; |
272 | u32 timeout = 1000; | 272 | u32 timeout = 1000; |
273 | u32 saved_config = 0; | ||
273 | u32 reg; | 274 | u32 reg; |
274 | 275 | ||
275 | int cmd_status = 0; | 276 | int cmd_status = 0; |
276 | int susphy = false; | ||
277 | int ret = -EINVAL; | 277 | int ret = -EINVAL; |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if | 280 | * When operating in USB 2.0 speeds (HS/FS), if GUSB2PHYCFG.ENBLSLPM or |
281 | * we're issuing an endpoint command, we must check if | 281 | * GUSB2PHYCFG.SUSPHY is set, it must be cleared before issuing an |
282 | * GUSB2PHYCFG.SUSPHY bit is set. If it is, then we need to clear it. | 282 | * endpoint command. |
283 | * | 283 | * |
284 | * We will also set SUSPHY bit to what it was before returning as stated | 284 | * Save and clear both GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY |
285 | * by the same section on Synopsys databook. | 285 | * settings. Restore them after the command is completed. |
286 | * | ||
287 | * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2 | ||
286 | */ | 288 | */ |
287 | if (dwc->gadget.speed <= USB_SPEED_HIGH) { | 289 | if (dwc->gadget.speed <= USB_SPEED_HIGH) { |
288 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | 290 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); |
289 | if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { | 291 | if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { |
290 | susphy = true; | 292 | saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; |
291 | reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | 293 | reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; |
292 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
293 | } | 294 | } |
295 | |||
296 | if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) { | ||
297 | saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
298 | reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
299 | } | ||
300 | |||
301 | if (saved_config) | ||
302 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
294 | } | 303 | } |
295 | 304 | ||
296 | if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { | 305 | if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { |
@@ -389,9 +398,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | |||
389 | } | 398 | } |
390 | } | 399 | } |
391 | 400 | ||
392 | if (unlikely(susphy)) { | 401 | if (saved_config) { |
393 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | 402 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); |
394 | reg |= DWC3_GUSB2PHYCFG_SUSPHY; | 403 | reg |= saved_config; |
395 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | 404 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); |
396 | } | 405 | } |
397 | 406 | ||
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index d582921f7257..db2d4980cb35 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c | |||
@@ -22,12 +22,8 @@ | |||
22 | * controlled by two clock sources : | 22 | * controlled by two clock sources : |
23 | * CLK_5 := c_srate, and CLK_6 := p_srate | 23 | * CLK_5 := c_srate, and CLK_6 := p_srate |
24 | */ | 24 | */ |
25 | #define USB_OUT_IT_ID 1 | 25 | #define USB_OUT_CLK_ID (out_clk_src_desc.bClockID) |
26 | #define IO_IN_IT_ID 2 | 26 | #define USB_IN_CLK_ID (in_clk_src_desc.bClockID) |
27 | #define IO_OUT_OT_ID 3 | ||
28 | #define USB_IN_OT_ID 4 | ||
29 | #define USB_OUT_CLK_ID 5 | ||
30 | #define USB_IN_CLK_ID 6 | ||
31 | 27 | ||
32 | #define CONTROL_ABSENT 0 | 28 | #define CONTROL_ABSENT 0 |
33 | #define CONTROL_RDONLY 1 | 29 | #define CONTROL_RDONLY 1 |
@@ -43,6 +39,9 @@ | |||
43 | #define UNFLW_CTRL 8 | 39 | #define UNFLW_CTRL 8 |
44 | #define OVFLW_CTRL 10 | 40 | #define OVFLW_CTRL 10 |
45 | 41 | ||
42 | #define EPIN_EN(_opts) ((_opts)->p_chmask != 0) | ||
43 | #define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) | ||
44 | |||
46 | struct f_uac2 { | 45 | struct f_uac2 { |
47 | struct g_audio g_audio; | 46 | struct g_audio g_audio; |
48 | u8 ac_intf, as_in_intf, as_out_intf; | 47 | u8 ac_intf, as_in_intf, as_out_intf; |
@@ -135,7 +134,7 @@ static struct uac_clock_source_descriptor in_clk_src_desc = { | |||
135 | .bDescriptorType = USB_DT_CS_INTERFACE, | 134 | .bDescriptorType = USB_DT_CS_INTERFACE, |
136 | 135 | ||
137 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, | 136 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, |
138 | .bClockID = USB_IN_CLK_ID, | 137 | /* .bClockID = DYNAMIC */ |
139 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, | 138 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, |
140 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), | 139 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), |
141 | .bAssocTerminal = 0, | 140 | .bAssocTerminal = 0, |
@@ -147,7 +146,7 @@ static struct uac_clock_source_descriptor out_clk_src_desc = { | |||
147 | .bDescriptorType = USB_DT_CS_INTERFACE, | 146 | .bDescriptorType = USB_DT_CS_INTERFACE, |
148 | 147 | ||
149 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, | 148 | .bDescriptorSubtype = UAC2_CLOCK_SOURCE, |
150 | .bClockID = USB_OUT_CLK_ID, | 149 | /* .bClockID = DYNAMIC */ |
151 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, | 150 | .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, |
152 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), | 151 | .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), |
153 | .bAssocTerminal = 0, | 152 | .bAssocTerminal = 0, |
@@ -159,10 +158,10 @@ static struct uac2_input_terminal_descriptor usb_out_it_desc = { | |||
159 | .bDescriptorType = USB_DT_CS_INTERFACE, | 158 | .bDescriptorType = USB_DT_CS_INTERFACE, |
160 | 159 | ||
161 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, | 160 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, |
162 | .bTerminalID = USB_OUT_IT_ID, | 161 | /* .bTerminalID = DYNAMIC */ |
163 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), | 162 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), |
164 | .bAssocTerminal = 0, | 163 | .bAssocTerminal = 0, |
165 | .bCSourceID = USB_OUT_CLK_ID, | 164 | /* .bCSourceID = DYNAMIC */ |
166 | .iChannelNames = 0, | 165 | .iChannelNames = 0, |
167 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), | 166 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
168 | }; | 167 | }; |
@@ -173,10 +172,10 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = { | |||
173 | .bDescriptorType = USB_DT_CS_INTERFACE, | 172 | .bDescriptorType = USB_DT_CS_INTERFACE, |
174 | 173 | ||
175 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, | 174 | .bDescriptorSubtype = UAC_INPUT_TERMINAL, |
176 | .bTerminalID = IO_IN_IT_ID, | 175 | /* .bTerminalID = DYNAMIC */ |
177 | .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), | 176 | .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), |
178 | .bAssocTerminal = 0, | 177 | .bAssocTerminal = 0, |
179 | .bCSourceID = USB_IN_CLK_ID, | 178 | /* .bCSourceID = DYNAMIC */ |
180 | .iChannelNames = 0, | 179 | .iChannelNames = 0, |
181 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), | 180 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
182 | }; | 181 | }; |
@@ -187,11 +186,11 @@ static struct uac2_output_terminal_descriptor usb_in_ot_desc = { | |||
187 | .bDescriptorType = USB_DT_CS_INTERFACE, | 186 | .bDescriptorType = USB_DT_CS_INTERFACE, |
188 | 187 | ||
189 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, | 188 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, |
190 | .bTerminalID = USB_IN_OT_ID, | 189 | /* .bTerminalID = DYNAMIC */ |
191 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), | 190 | .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), |
192 | .bAssocTerminal = 0, | 191 | .bAssocTerminal = 0, |
193 | .bSourceID = IO_IN_IT_ID, | 192 | /* .bSourceID = DYNAMIC */ |
194 | .bCSourceID = USB_IN_CLK_ID, | 193 | /* .bCSourceID = DYNAMIC */ |
195 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), | 194 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
196 | }; | 195 | }; |
197 | 196 | ||
@@ -201,11 +200,11 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = { | |||
201 | .bDescriptorType = USB_DT_CS_INTERFACE, | 200 | .bDescriptorType = USB_DT_CS_INTERFACE, |
202 | 201 | ||
203 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, | 202 | .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, |
204 | .bTerminalID = IO_OUT_OT_ID, | 203 | /* .bTerminalID = DYNAMIC */ |
205 | .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), | 204 | .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), |
206 | .bAssocTerminal = 0, | 205 | .bAssocTerminal = 0, |
207 | .bSourceID = USB_OUT_IT_ID, | 206 | /* .bSourceID = DYNAMIC */ |
208 | .bCSourceID = USB_OUT_CLK_ID, | 207 | /* .bCSourceID = DYNAMIC */ |
209 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), | 208 | .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL), |
210 | }; | 209 | }; |
211 | 210 | ||
@@ -253,7 +252,7 @@ static struct uac2_as_header_descriptor as_out_hdr_desc = { | |||
253 | .bDescriptorType = USB_DT_CS_INTERFACE, | 252 | .bDescriptorType = USB_DT_CS_INTERFACE, |
254 | 253 | ||
255 | .bDescriptorSubtype = UAC_AS_GENERAL, | 254 | .bDescriptorSubtype = UAC_AS_GENERAL, |
256 | .bTerminalLink = USB_OUT_IT_ID, | 255 | /* .bTerminalLink = DYNAMIC */ |
257 | .bmControls = 0, | 256 | .bmControls = 0, |
258 | .bFormatType = UAC_FORMAT_TYPE_I, | 257 | .bFormatType = UAC_FORMAT_TYPE_I, |
259 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), | 258 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), |
@@ -330,7 +329,7 @@ static struct uac2_as_header_descriptor as_in_hdr_desc = { | |||
330 | .bDescriptorType = USB_DT_CS_INTERFACE, | 329 | .bDescriptorType = USB_DT_CS_INTERFACE, |
331 | 330 | ||
332 | .bDescriptorSubtype = UAC_AS_GENERAL, | 331 | .bDescriptorSubtype = UAC_AS_GENERAL, |
333 | .bTerminalLink = USB_IN_OT_ID, | 332 | /* .bTerminalLink = DYNAMIC */ |
334 | .bmControls = 0, | 333 | .bmControls = 0, |
335 | .bFormatType = UAC_FORMAT_TYPE_I, | 334 | .bFormatType = UAC_FORMAT_TYPE_I, |
336 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), | 335 | .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), |
@@ -471,6 +470,125 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, | |||
471 | le16_to_cpu(ep_desc->wMaxPacketSize))); | 470 | le16_to_cpu(ep_desc->wMaxPacketSize))); |
472 | } | 471 | } |
473 | 472 | ||
473 | /* Use macro to overcome line length limitation */ | ||
474 | #define USBDHDR(p) (struct usb_descriptor_header *)(p) | ||
475 | |||
476 | static void setup_descriptor(struct f_uac2_opts *opts) | ||
477 | { | ||
478 | /* patch descriptors */ | ||
479 | int i = 1; /* ID's start with 1 */ | ||
480 | |||
481 | if (EPOUT_EN(opts)) | ||
482 | usb_out_it_desc.bTerminalID = i++; | ||
483 | if (EPIN_EN(opts)) | ||
484 | io_in_it_desc.bTerminalID = i++; | ||
485 | if (EPOUT_EN(opts)) | ||
486 | io_out_ot_desc.bTerminalID = i++; | ||
487 | if (EPIN_EN(opts)) | ||
488 | usb_in_ot_desc.bTerminalID = i++; | ||
489 | if (EPOUT_EN(opts)) | ||
490 | out_clk_src_desc.bClockID = i++; | ||
491 | if (EPIN_EN(opts)) | ||
492 | in_clk_src_desc.bClockID = i++; | ||
493 | |||
494 | usb_out_it_desc.bCSourceID = out_clk_src_desc.bClockID; | ||
495 | usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID; | ||
496 | usb_in_ot_desc.bCSourceID = in_clk_src_desc.bClockID; | ||
497 | io_in_it_desc.bCSourceID = in_clk_src_desc.bClockID; | ||
498 | io_out_ot_desc.bCSourceID = out_clk_src_desc.bClockID; | ||
499 | io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID; | ||
500 | as_out_hdr_desc.bTerminalLink = usb_out_it_desc.bTerminalID; | ||
501 | as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID; | ||
502 | |||
503 | iad_desc.bInterfaceCount = 1; | ||
504 | ac_hdr_desc.wTotalLength = 0; | ||
505 | |||
506 | if (EPIN_EN(opts)) { | ||
507 | u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength); | ||
508 | |||
509 | len += sizeof(in_clk_src_desc); | ||
510 | len += sizeof(usb_in_ot_desc); | ||
511 | len += sizeof(io_in_it_desc); | ||
512 | ac_hdr_desc.wTotalLength = cpu_to_le16(len); | ||
513 | iad_desc.bInterfaceCount++; | ||
514 | } | ||
515 | if (EPOUT_EN(opts)) { | ||
516 | u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength); | ||
517 | |||
518 | len += sizeof(out_clk_src_desc); | ||
519 | len += sizeof(usb_out_it_desc); | ||
520 | len += sizeof(io_out_ot_desc); | ||
521 | ac_hdr_desc.wTotalLength = cpu_to_le16(len); | ||
522 | iad_desc.bInterfaceCount++; | ||
523 | } | ||
524 | |||
525 | i = 0; | ||
526 | fs_audio_desc[i++] = USBDHDR(&iad_desc); | ||
527 | fs_audio_desc[i++] = USBDHDR(&std_ac_if_desc); | ||
528 | fs_audio_desc[i++] = USBDHDR(&ac_hdr_desc); | ||
529 | if (EPIN_EN(opts)) | ||
530 | fs_audio_desc[i++] = USBDHDR(&in_clk_src_desc); | ||
531 | if (EPOUT_EN(opts)) { | ||
532 | fs_audio_desc[i++] = USBDHDR(&out_clk_src_desc); | ||
533 | fs_audio_desc[i++] = USBDHDR(&usb_out_it_desc); | ||
534 | } | ||
535 | if (EPIN_EN(opts)) { | ||
536 | fs_audio_desc[i++] = USBDHDR(&io_in_it_desc); | ||
537 | fs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc); | ||
538 | } | ||
539 | if (EPOUT_EN(opts)) { | ||
540 | fs_audio_desc[i++] = USBDHDR(&io_out_ot_desc); | ||
541 | fs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc); | ||
542 | fs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc); | ||
543 | fs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc); | ||
544 | fs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc); | ||
545 | fs_audio_desc[i++] = USBDHDR(&fs_epout_desc); | ||
546 | fs_audio_desc[i++] = USBDHDR(&as_iso_out_desc); | ||
547 | } | ||
548 | if (EPIN_EN(opts)) { | ||
549 | fs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc); | ||
550 | fs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc); | ||
551 | fs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc); | ||
552 | fs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc); | ||
553 | fs_audio_desc[i++] = USBDHDR(&fs_epin_desc); | ||
554 | fs_audio_desc[i++] = USBDHDR(&as_iso_in_desc); | ||
555 | } | ||
556 | fs_audio_desc[i] = NULL; | ||
557 | |||
558 | i = 0; | ||
559 | hs_audio_desc[i++] = USBDHDR(&iad_desc); | ||
560 | hs_audio_desc[i++] = USBDHDR(&std_ac_if_desc); | ||
561 | hs_audio_desc[i++] = USBDHDR(&ac_hdr_desc); | ||
562 | if (EPIN_EN(opts)) | ||
563 | hs_audio_desc[i++] = USBDHDR(&in_clk_src_desc); | ||
564 | if (EPOUT_EN(opts)) { | ||
565 | hs_audio_desc[i++] = USBDHDR(&out_clk_src_desc); | ||
566 | hs_audio_desc[i++] = USBDHDR(&usb_out_it_desc); | ||
567 | } | ||
568 | if (EPIN_EN(opts)) { | ||
569 | hs_audio_desc[i++] = USBDHDR(&io_in_it_desc); | ||
570 | hs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc); | ||
571 | } | ||
572 | if (EPOUT_EN(opts)) { | ||
573 | hs_audio_desc[i++] = USBDHDR(&io_out_ot_desc); | ||
574 | hs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc); | ||
575 | hs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc); | ||
576 | hs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc); | ||
577 | hs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc); | ||
578 | hs_audio_desc[i++] = USBDHDR(&hs_epout_desc); | ||
579 | hs_audio_desc[i++] = USBDHDR(&as_iso_out_desc); | ||
580 | } | ||
581 | if (EPIN_EN(opts)) { | ||
582 | hs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc); | ||
583 | hs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc); | ||
584 | hs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc); | ||
585 | hs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc); | ||
586 | hs_audio_desc[i++] = USBDHDR(&hs_epin_desc); | ||
587 | hs_audio_desc[i++] = USBDHDR(&as_iso_in_desc); | ||
588 | } | ||
589 | hs_audio_desc[i] = NULL; | ||
590 | } | ||
591 | |||
474 | static int | 592 | static int |
475 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | 593 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) |
476 | { | 594 | { |
@@ -530,25 +648,29 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
530 | uac2->ac_intf = ret; | 648 | uac2->ac_intf = ret; |
531 | uac2->ac_alt = 0; | 649 | uac2->ac_alt = 0; |
532 | 650 | ||
533 | ret = usb_interface_id(cfg, fn); | 651 | if (EPOUT_EN(uac2_opts)) { |
534 | if (ret < 0) { | 652 | ret = usb_interface_id(cfg, fn); |
535 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); | 653 | if (ret < 0) { |
536 | return ret; | 654 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
655 | return ret; | ||
656 | } | ||
657 | std_as_out_if0_desc.bInterfaceNumber = ret; | ||
658 | std_as_out_if1_desc.bInterfaceNumber = ret; | ||
659 | uac2->as_out_intf = ret; | ||
660 | uac2->as_out_alt = 0; | ||
537 | } | 661 | } |
538 | std_as_out_if0_desc.bInterfaceNumber = ret; | ||
539 | std_as_out_if1_desc.bInterfaceNumber = ret; | ||
540 | uac2->as_out_intf = ret; | ||
541 | uac2->as_out_alt = 0; | ||
542 | 662 | ||
543 | ret = usb_interface_id(cfg, fn); | 663 | if (EPIN_EN(uac2_opts)) { |
544 | if (ret < 0) { | 664 | ret = usb_interface_id(cfg, fn); |
545 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); | 665 | if (ret < 0) { |
546 | return ret; | 666 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
667 | return ret; | ||
668 | } | ||
669 | std_as_in_if0_desc.bInterfaceNumber = ret; | ||
670 | std_as_in_if1_desc.bInterfaceNumber = ret; | ||
671 | uac2->as_in_intf = ret; | ||
672 | uac2->as_in_alt = 0; | ||
547 | } | 673 | } |
548 | std_as_in_if0_desc.bInterfaceNumber = ret; | ||
549 | std_as_in_if1_desc.bInterfaceNumber = ret; | ||
550 | uac2->as_in_intf = ret; | ||
551 | uac2->as_in_alt = 0; | ||
552 | 674 | ||
553 | /* Calculate wMaxPacketSize according to audio bandwidth */ | 675 | /* Calculate wMaxPacketSize according to audio bandwidth */ |
554 | set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); | 676 | set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); |
@@ -556,16 +678,20 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
556 | set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); | 678 | set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); |
557 | set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); | 679 | set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); |
558 | 680 | ||
559 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); | 681 | if (EPOUT_EN(uac2_opts)) { |
560 | if (!agdev->out_ep) { | 682 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); |
561 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); | 683 | if (!agdev->out_ep) { |
562 | return -ENODEV; | 684 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
685 | return -ENODEV; | ||
686 | } | ||
563 | } | 687 | } |
564 | 688 | ||
565 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); | 689 | if (EPIN_EN(uac2_opts)) { |
566 | if (!agdev->in_ep) { | 690 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); |
567 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); | 691 | if (!agdev->in_ep) { |
568 | return -ENODEV; | 692 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
693 | return -ENODEV; | ||
694 | } | ||
569 | } | 695 | } |
570 | 696 | ||
571 | agdev->in_ep_maxpsize = max_t(u16, | 697 | agdev->in_ep_maxpsize = max_t(u16, |
@@ -578,6 +704,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
578 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; | 704 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; |
579 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; | 705 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; |
580 | 706 | ||
707 | setup_descriptor(uac2_opts); | ||
708 | |||
581 | ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, | 709 | ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, |
582 | NULL); | 710 | NULL); |
583 | if (ret) | 711 | if (ret) |
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index d8ce7868fe22..8c99392df593 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c | |||
@@ -197,12 +197,6 @@ static const struct usb_descriptor_header * const uvc_ss_streaming[] = { | |||
197 | NULL, | 197 | NULL, |
198 | }; | 198 | }; |
199 | 199 | ||
200 | void uvc_set_trace_param(unsigned int trace) | ||
201 | { | ||
202 | uvc_gadget_trace_param = trace; | ||
203 | } | ||
204 | EXPORT_SYMBOL(uvc_set_trace_param); | ||
205 | |||
206 | /* -------------------------------------------------------------------------- | 200 | /* -------------------------------------------------------------------------- |
207 | * Control requests | 201 | * Control requests |
208 | */ | 202 | */ |
@@ -232,13 +226,8 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | |||
232 | struct v4l2_event v4l2_event; | 226 | struct v4l2_event v4l2_event; |
233 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; | 227 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
234 | 228 | ||
235 | /* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n", | ||
236 | * ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue), | ||
237 | * le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength)); | ||
238 | */ | ||
239 | |||
240 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { | 229 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { |
241 | INFO(f->config->cdev, "invalid request type\n"); | 230 | uvcg_info(f, "invalid request type\n"); |
242 | return -EINVAL; | 231 | return -EINVAL; |
243 | } | 232 | } |
244 | 233 | ||
@@ -272,7 +261,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface) | |||
272 | { | 261 | { |
273 | struct uvc_device *uvc = to_uvc(f); | 262 | struct uvc_device *uvc = to_uvc(f); |
274 | 263 | ||
275 | INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface); | 264 | uvcg_info(f, "%s(%u)\n", __func__, interface); |
276 | 265 | ||
277 | if (interface == uvc->control_intf) | 266 | if (interface == uvc->control_intf) |
278 | return 0; | 267 | return 0; |
@@ -291,13 +280,13 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) | |||
291 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; | 280 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
292 | int ret; | 281 | int ret; |
293 | 282 | ||
294 | INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); | 283 | uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt); |
295 | 284 | ||
296 | if (interface == uvc->control_intf) { | 285 | if (interface == uvc->control_intf) { |
297 | if (alt) | 286 | if (alt) |
298 | return -EINVAL; | 287 | return -EINVAL; |
299 | 288 | ||
300 | INFO(cdev, "reset UVC Control\n"); | 289 | uvcg_info(f, "reset UVC Control\n"); |
301 | usb_ep_disable(uvc->control_ep); | 290 | usb_ep_disable(uvc->control_ep); |
302 | 291 | ||
303 | if (!uvc->control_ep->desc) | 292 | if (!uvc->control_ep->desc) |
@@ -348,7 +337,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) | |||
348 | if (!uvc->video.ep) | 337 | if (!uvc->video.ep) |
349 | return -EINVAL; | 338 | return -EINVAL; |
350 | 339 | ||
351 | INFO(cdev, "reset UVC\n"); | 340 | uvcg_info(f, "reset UVC\n"); |
352 | usb_ep_disable(uvc->video.ep); | 341 | usb_ep_disable(uvc->video.ep); |
353 | 342 | ||
354 | ret = config_ep_by_speed(f->config->cdev->gadget, | 343 | ret = config_ep_by_speed(f->config->cdev->gadget, |
@@ -373,7 +362,7 @@ uvc_function_disable(struct usb_function *f) | |||
373 | struct uvc_device *uvc = to_uvc(f); | 362 | struct uvc_device *uvc = to_uvc(f); |
374 | struct v4l2_event v4l2_event; | 363 | struct v4l2_event v4l2_event; |
375 | 364 | ||
376 | INFO(f->config->cdev, "uvc_function_disable\n"); | 365 | uvcg_info(f, "%s()\n", __func__); |
377 | 366 | ||
378 | memset(&v4l2_event, 0, sizeof(v4l2_event)); | 367 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
379 | v4l2_event.type = UVC_EVENT_DISCONNECT; | 368 | v4l2_event.type = UVC_EVENT_DISCONNECT; |
@@ -392,21 +381,19 @@ uvc_function_disable(struct usb_function *f) | |||
392 | void | 381 | void |
393 | uvc_function_connect(struct uvc_device *uvc) | 382 | uvc_function_connect(struct uvc_device *uvc) |
394 | { | 383 | { |
395 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | ||
396 | int ret; | 384 | int ret; |
397 | 385 | ||
398 | if ((ret = usb_function_activate(&uvc->func)) < 0) | 386 | if ((ret = usb_function_activate(&uvc->func)) < 0) |
399 | INFO(cdev, "UVC connect failed with %d\n", ret); | 387 | uvcg_info(&uvc->func, "UVC connect failed with %d\n", ret); |
400 | } | 388 | } |
401 | 389 | ||
402 | void | 390 | void |
403 | uvc_function_disconnect(struct uvc_device *uvc) | 391 | uvc_function_disconnect(struct uvc_device *uvc) |
404 | { | 392 | { |
405 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | ||
406 | int ret; | 393 | int ret; |
407 | 394 | ||
408 | if ((ret = usb_function_deactivate(&uvc->func)) < 0) | 395 | if ((ret = usb_function_deactivate(&uvc->func)) < 0) |
409 | INFO(cdev, "UVC disconnect failed with %d\n", ret); | 396 | uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret); |
410 | } | 397 | } |
411 | 398 | ||
412 | /* -------------------------------------------------------------------------- | 399 | /* -------------------------------------------------------------------------- |
@@ -605,7 +592,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
605 | struct f_uvc_opts *opts; | 592 | struct f_uvc_opts *opts; |
606 | int ret = -EINVAL; | 593 | int ret = -EINVAL; |
607 | 594 | ||
608 | INFO(cdev, "uvc_function_bind\n"); | 595 | uvcg_info(f, "%s()\n", __func__); |
609 | 596 | ||
610 | opts = fi_to_f_uvc_opts(f->fi); | 597 | opts = fi_to_f_uvc_opts(f->fi); |
611 | /* Sanity check the streaming endpoint module parameters. | 598 | /* Sanity check the streaming endpoint module parameters. |
@@ -618,8 +605,8 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
618 | if (opts->streaming_maxburst && | 605 | if (opts->streaming_maxburst && |
619 | (opts->streaming_maxpacket % 1024) != 0) { | 606 | (opts->streaming_maxpacket % 1024) != 0) { |
620 | opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024); | 607 | opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024); |
621 | INFO(cdev, "overriding streaming_maxpacket to %d\n", | 608 | uvcg_info(f, "overriding streaming_maxpacket to %d\n", |
622 | opts->streaming_maxpacket); | 609 | opts->streaming_maxpacket); |
623 | } | 610 | } |
624 | 611 | ||
625 | /* Fill in the FS/HS/SS Video Streaming specific descriptors from the | 612 | /* Fill in the FS/HS/SS Video Streaming specific descriptors from the |
@@ -658,7 +645,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
658 | /* Allocate endpoints. */ | 645 | /* Allocate endpoints. */ |
659 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); | 646 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); |
660 | if (!ep) { | 647 | if (!ep) { |
661 | INFO(cdev, "Unable to allocate control EP\n"); | 648 | uvcg_info(f, "Unable to allocate control EP\n"); |
662 | goto error; | 649 | goto error; |
663 | } | 650 | } |
664 | uvc->control_ep = ep; | 651 | uvc->control_ep = ep; |
@@ -672,7 +659,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
672 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); | 659 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); |
673 | 660 | ||
674 | if (!ep) { | 661 | if (!ep) { |
675 | INFO(cdev, "Unable to allocate streaming EP\n"); | 662 | uvcg_info(f, "Unable to allocate streaming EP\n"); |
676 | goto error; | 663 | goto error; |
677 | } | 664 | } |
678 | uvc->video.ep = ep; | 665 | uvc->video.ep = ep; |
@@ -699,12 +686,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
699 | uvc_iad.bFirstInterface = ret; | 686 | uvc_iad.bFirstInterface = ret; |
700 | uvc_control_intf.bInterfaceNumber = ret; | 687 | uvc_control_intf.bInterfaceNumber = ret; |
701 | uvc->control_intf = ret; | 688 | uvc->control_intf = ret; |
689 | opts->control_interface = ret; | ||
702 | 690 | ||
703 | if ((ret = usb_interface_id(c, f)) < 0) | 691 | if ((ret = usb_interface_id(c, f)) < 0) |
704 | goto error; | 692 | goto error; |
705 | uvc_streaming_intf_alt0.bInterfaceNumber = ret; | 693 | uvc_streaming_intf_alt0.bInterfaceNumber = ret; |
706 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; | 694 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; |
707 | uvc->streaming_intf = ret; | 695 | uvc->streaming_intf = ret; |
696 | opts->streaming_interface = ret; | ||
708 | 697 | ||
709 | /* Copy descriptors */ | 698 | /* Copy descriptors */ |
710 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); | 699 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); |
@@ -743,19 +732,19 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
743 | uvc->control_req->context = uvc; | 732 | uvc->control_req->context = uvc; |
744 | 733 | ||
745 | if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { | 734 | if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { |
746 | printk(KERN_INFO "v4l2_device_register failed\n"); | 735 | uvcg_err(f, "failed to register V4L2 device\n"); |
747 | goto error; | 736 | goto error; |
748 | } | 737 | } |
749 | 738 | ||
750 | /* Initialise video. */ | 739 | /* Initialise video. */ |
751 | ret = uvcg_video_init(&uvc->video); | 740 | ret = uvcg_video_init(&uvc->video, uvc); |
752 | if (ret < 0) | 741 | if (ret < 0) |
753 | goto error; | 742 | goto error; |
754 | 743 | ||
755 | /* Register a V4L2 device. */ | 744 | /* Register a V4L2 device. */ |
756 | ret = uvc_register_video(uvc); | 745 | ret = uvc_register_video(uvc); |
757 | if (ret < 0) { | 746 | if (ret < 0) { |
758 | printk(KERN_INFO "Unable to register video device\n"); | 747 | uvcg_err(f, "failed to register video device\n"); |
759 | goto error; | 748 | goto error; |
760 | } | 749 | } |
761 | 750 | ||
@@ -792,6 +781,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) | |||
792 | struct uvc_output_terminal_descriptor *od; | 781 | struct uvc_output_terminal_descriptor *od; |
793 | struct uvc_color_matching_descriptor *md; | 782 | struct uvc_color_matching_descriptor *md; |
794 | struct uvc_descriptor_header **ctl_cls; | 783 | struct uvc_descriptor_header **ctl_cls; |
784 | int ret; | ||
795 | 785 | ||
796 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | 786 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); |
797 | if (!opts) | 787 | if (!opts) |
@@ -868,7 +858,12 @@ static struct usb_function_instance *uvc_alloc_inst(void) | |||
868 | opts->streaming_interval = 1; | 858 | opts->streaming_interval = 1; |
869 | opts->streaming_maxpacket = 1024; | 859 | opts->streaming_maxpacket = 1024; |
870 | 860 | ||
871 | uvcg_attach_configfs(opts); | 861 | ret = uvcg_attach_configfs(opts); |
862 | if (ret < 0) { | ||
863 | kfree(opts); | ||
864 | return ERR_PTR(ret); | ||
865 | } | ||
866 | |||
872 | return &opts->func_inst; | 867 | return &opts->func_inst; |
873 | } | 868 | } |
874 | 869 | ||
@@ -886,7 +881,7 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f) | |||
886 | struct usb_composite_dev *cdev = c->cdev; | 881 | struct usb_composite_dev *cdev = c->cdev; |
887 | struct uvc_device *uvc = to_uvc(f); | 882 | struct uvc_device *uvc = to_uvc(f); |
888 | 883 | ||
889 | INFO(cdev, "%s\n", __func__); | 884 | uvcg_info(f, "%s\n", __func__); |
890 | 885 | ||
891 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); | 886 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); |
892 | video_unregister_device(&uvc->vdev); | 887 | video_unregister_device(&uvc->vdev); |
diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 2ed292e94fbc..5242d489e20a 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h | |||
@@ -25,6 +25,9 @@ struct f_uvc_opts { | |||
25 | unsigned int streaming_maxpacket; | 25 | unsigned int streaming_maxpacket; |
26 | unsigned int streaming_maxburst; | 26 | unsigned int streaming_maxburst; |
27 | 27 | ||
28 | unsigned int control_interface; | ||
29 | unsigned int streaming_interface; | ||
30 | |||
28 | /* | 31 | /* |
29 | * Control descriptors array pointers for full-/high-speed and | 32 | * Control descriptors array pointers for full-/high-speed and |
30 | * super-speed. They point by default to the uvc_fs_control_cls and | 33 | * super-speed. They point by default to the uvc_fs_control_cls and |
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 93cf78b420fe..099d650082e5 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h | |||
@@ -24,6 +24,7 @@ | |||
24 | struct usb_ep; | 24 | struct usb_ep; |
25 | struct usb_request; | 25 | struct usb_request; |
26 | struct uvc_descriptor_header; | 26 | struct uvc_descriptor_header; |
27 | struct uvc_device; | ||
27 | 28 | ||
28 | /* ------------------------------------------------------------------------ | 29 | /* ------------------------------------------------------------------------ |
29 | * Debugging, printing and logging | 30 | * Debugging, printing and logging |
@@ -51,14 +52,12 @@ extern unsigned int uvc_gadget_trace_param; | |||
51 | printk(KERN_DEBUG "uvcvideo: " msg); \ | 52 | printk(KERN_DEBUG "uvcvideo: " msg); \ |
52 | } while (0) | 53 | } while (0) |
53 | 54 | ||
54 | #define uvc_warn_once(dev, warn, msg...) \ | 55 | #define uvcg_dbg(f, fmt, args...) \ |
55 | do { \ | 56 | dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) |
56 | if (!test_and_set_bit(warn, &dev->warnings)) \ | 57 | #define uvcg_info(f, fmt, args...) \ |
57 | printk(KERN_INFO "uvcvideo: " msg); \ | 58 | dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) |
58 | } while (0) | 59 | #define uvcg_err(f, fmt, args...) \ |
59 | 60 | dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) | |
60 | #define uvc_printk(level, msg...) \ | ||
61 | printk(level "uvcvideo: " msg) | ||
62 | 61 | ||
63 | /* ------------------------------------------------------------------------ | 62 | /* ------------------------------------------------------------------------ |
64 | * Driver specific constants | 63 | * Driver specific constants |
@@ -73,6 +72,7 @@ extern unsigned int uvc_gadget_trace_param; | |||
73 | */ | 72 | */ |
74 | 73 | ||
75 | struct uvc_video { | 74 | struct uvc_video { |
75 | struct uvc_device *uvc; | ||
76 | struct usb_ep *ep; | 76 | struct usb_ep *ep; |
77 | 77 | ||
78 | /* Frame parameters */ | 78 | /* Frame parameters */ |
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index b51f0d278826..bc1e2af566c3 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c | |||
@@ -9,9 +9,16 @@ | |||
9 | * | 9 | * |
10 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 10 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> |
11 | */ | 11 | */ |
12 | |||
13 | #include <linux/sort.h> | ||
14 | |||
12 | #include "u_uvc.h" | 15 | #include "u_uvc.h" |
13 | #include "uvc_configfs.h" | 16 | #include "uvc_configfs.h" |
14 | 17 | ||
18 | /* ----------------------------------------------------------------------------- | ||
19 | * Global Utility Structures and Macros | ||
20 | */ | ||
21 | |||
15 | #define UVCG_STREAMING_CONTROL_SIZE 1 | 22 | #define UVCG_STREAMING_CONTROL_SIZE 1 |
16 | 23 | ||
17 | #define UVC_ATTR(prefix, cname, aname) \ | 24 | #define UVC_ATTR(prefix, cname, aname) \ |
@@ -31,13 +38,93 @@ static struct configfs_attribute prefix##attr_##cname = { \ | |||
31 | .show = prefix##cname##_show, \ | 38 | .show = prefix##cname##_show, \ |
32 | } | 39 | } |
33 | 40 | ||
41 | #define le8_to_cpu(x) (x) | ||
42 | #define cpu_to_le8(x) (x) | ||
43 | |||
44 | static int uvcg_config_compare_u32(const void *l, const void *r) | ||
45 | { | ||
46 | u32 li = *(const u32 *)l; | ||
47 | u32 ri = *(const u32 *)r; | ||
48 | |||
49 | return li < ri ? -1 : li == ri ? 0 : 1; | ||
50 | } | ||
51 | |||
34 | static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item) | 52 | static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item) |
35 | { | 53 | { |
36 | return container_of(to_config_group(item), struct f_uvc_opts, | 54 | return container_of(to_config_group(item), struct f_uvc_opts, |
37 | func_inst.group); | 55 | func_inst.group); |
38 | } | 56 | } |
39 | 57 | ||
40 | /* control/header/<NAME> */ | 58 | struct uvcg_config_group_type { |
59 | struct config_item_type type; | ||
60 | const char *name; | ||
61 | const struct uvcg_config_group_type **children; | ||
62 | int (*create_children)(struct config_group *group); | ||
63 | }; | ||
64 | |||
65 | static void uvcg_config_item_release(struct config_item *item) | ||
66 | { | ||
67 | struct config_group *group = to_config_group(item); | ||
68 | |||
69 | kfree(group); | ||
70 | } | ||
71 | |||
72 | static struct configfs_item_operations uvcg_config_item_ops = { | ||
73 | .release = uvcg_config_item_release, | ||
74 | }; | ||
75 | |||
76 | static int uvcg_config_create_group(struct config_group *parent, | ||
77 | const struct uvcg_config_group_type *type); | ||
78 | |||
79 | static int uvcg_config_create_children(struct config_group *group, | ||
80 | const struct uvcg_config_group_type *type) | ||
81 | { | ||
82 | const struct uvcg_config_group_type **child; | ||
83 | int ret; | ||
84 | |||
85 | if (type->create_children) | ||
86 | return type->create_children(group); | ||
87 | |||
88 | for (child = type->children; child && *child; ++child) { | ||
89 | ret = uvcg_config_create_group(group, *child); | ||
90 | if (ret < 0) | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int uvcg_config_create_group(struct config_group *parent, | ||
98 | const struct uvcg_config_group_type *type) | ||
99 | { | ||
100 | struct config_group *group; | ||
101 | |||
102 | group = kzalloc(sizeof(*group), GFP_KERNEL); | ||
103 | if (!group) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | config_group_init_type_name(group, type->name, &type->type); | ||
107 | configfs_add_default_group(group, parent); | ||
108 | |||
109 | return uvcg_config_create_children(group, type); | ||
110 | } | ||
111 | |||
112 | static void uvcg_config_remove_children(struct config_group *group) | ||
113 | { | ||
114 | struct config_group *child, *n; | ||
115 | |||
116 | list_for_each_entry_safe(child, n, &group->default_groups, group_entry) { | ||
117 | list_del(&child->group_entry); | ||
118 | uvcg_config_remove_children(child); | ||
119 | config_item_put(&child->cg_item); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /* ----------------------------------------------------------------------------- | ||
124 | * control/header/<NAME> | ||
125 | * control/header | ||
126 | */ | ||
127 | |||
41 | DECLARE_UVC_HEADER_DESCRIPTOR(1); | 128 | DECLARE_UVC_HEADER_DESCRIPTOR(1); |
42 | 129 | ||
43 | struct uvcg_control_header { | 130 | struct uvcg_control_header { |
@@ -51,9 +138,9 @@ static struct uvcg_control_header *to_uvcg_control_header(struct config_item *it | |||
51 | return container_of(item, struct uvcg_control_header, item); | 138 | return container_of(item, struct uvcg_control_header, item); |
52 | } | 139 | } |
53 | 140 | ||
54 | #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \ | 141 | #define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \ |
55 | static ssize_t uvcg_control_header_##cname##_show( \ | 142 | static ssize_t uvcg_control_header_##cname##_show( \ |
56 | struct config_item *item, char *page) \ | 143 | struct config_item *item, char *page) \ |
57 | { \ | 144 | { \ |
58 | struct uvcg_control_header *ch = to_uvcg_control_header(item); \ | 145 | struct uvcg_control_header *ch = to_uvcg_control_header(item); \ |
59 | struct f_uvc_opts *opts; \ | 146 | struct f_uvc_opts *opts; \ |
@@ -67,7 +154,7 @@ static ssize_t uvcg_control_header_##cname##_show( \ | |||
67 | opts = to_f_uvc_opts(opts_item); \ | 154 | opts = to_f_uvc_opts(opts_item); \ |
68 | \ | 155 | \ |
69 | mutex_lock(&opts->lock); \ | 156 | mutex_lock(&opts->lock); \ |
70 | result = sprintf(page, "%d\n", conv(ch->desc.aname)); \ | 157 | result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\ |
71 | mutex_unlock(&opts->lock); \ | 158 | mutex_unlock(&opts->lock); \ |
72 | \ | 159 | \ |
73 | mutex_unlock(su_mutex); \ | 160 | mutex_unlock(su_mutex); \ |
@@ -83,7 +170,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \ | |||
83 | struct config_item *opts_item; \ | 170 | struct config_item *opts_item; \ |
84 | struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\ | 171 | struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\ |
85 | int ret; \ | 172 | int ret; \ |
86 | uxx num; \ | 173 | u##bits num; \ |
87 | \ | 174 | \ |
88 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ | 175 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ |
89 | \ | 176 | \ |
@@ -96,7 +183,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \ | |||
96 | goto end; \ | 183 | goto end; \ |
97 | } \ | 184 | } \ |
98 | \ | 185 | \ |
99 | ret = str2u(page, 0, &num); \ | 186 | ret = kstrtou##bits(page, 0, &num); \ |
100 | if (ret) \ | 187 | if (ret) \ |
101 | goto end; \ | 188 | goto end; \ |
102 | \ | 189 | \ |
@@ -104,7 +191,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \ | |||
104 | ret = -EINVAL; \ | 191 | ret = -EINVAL; \ |
105 | goto end; \ | 192 | goto end; \ |
106 | } \ | 193 | } \ |
107 | ch->desc.aname = vnoc(num); \ | 194 | ch->desc.aname = cpu_to_le##bits(num); \ |
108 | ret = len; \ | 195 | ret = len; \ |
109 | end: \ | 196 | end: \ |
110 | mutex_unlock(&opts->lock); \ | 197 | mutex_unlock(&opts->lock); \ |
@@ -114,11 +201,9 @@ end: \ | |||
114 | \ | 201 | \ |
115 | UVC_ATTR(uvcg_control_header_, cname, aname) | 202 | UVC_ATTR(uvcg_control_header_, cname, aname) |
116 | 203 | ||
117 | UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16, | 204 | UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff); |
118 | 0xffff); | ||
119 | 205 | ||
120 | UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32, | 206 | UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff); |
121 | u32, cpu_to_le32, 0x7fffffff); | ||
122 | 207 | ||
123 | #undef UVCG_CTRL_HDR_ATTR | 208 | #undef UVCG_CTRL_HDR_ATTR |
124 | 209 | ||
@@ -129,6 +214,7 @@ static struct configfs_attribute *uvcg_control_header_attrs[] = { | |||
129 | }; | 214 | }; |
130 | 215 | ||
131 | static const struct config_item_type uvcg_control_header_type = { | 216 | static const struct config_item_type uvcg_control_header_type = { |
217 | .ct_item_ops = &uvcg_config_item_ops, | ||
132 | .ct_attrs = uvcg_control_header_attrs, | 218 | .ct_attrs = uvcg_control_header_attrs, |
133 | .ct_owner = THIS_MODULE, | 219 | .ct_owner = THIS_MODULE, |
134 | }; | 220 | }; |
@@ -153,60 +239,42 @@ static struct config_item *uvcg_control_header_make(struct config_group *group, | |||
153 | return &h->item; | 239 | return &h->item; |
154 | } | 240 | } |
155 | 241 | ||
156 | static void uvcg_control_header_drop(struct config_group *group, | ||
157 | struct config_item *item) | ||
158 | { | ||
159 | struct uvcg_control_header *h = to_uvcg_control_header(item); | ||
160 | |||
161 | kfree(h); | ||
162 | } | ||
163 | |||
164 | /* control/header */ | ||
165 | static struct uvcg_control_header_grp { | ||
166 | struct config_group group; | ||
167 | } uvcg_control_header_grp; | ||
168 | |||
169 | static struct configfs_group_operations uvcg_control_header_grp_ops = { | 242 | static struct configfs_group_operations uvcg_control_header_grp_ops = { |
170 | .make_item = uvcg_control_header_make, | 243 | .make_item = uvcg_control_header_make, |
171 | .drop_item = uvcg_control_header_drop, | ||
172 | }; | 244 | }; |
173 | 245 | ||
174 | static const struct config_item_type uvcg_control_header_grp_type = { | 246 | static const struct uvcg_config_group_type uvcg_control_header_grp_type = { |
175 | .ct_group_ops = &uvcg_control_header_grp_ops, | 247 | .type = { |
176 | .ct_owner = THIS_MODULE, | 248 | .ct_item_ops = &uvcg_config_item_ops, |
249 | .ct_group_ops = &uvcg_control_header_grp_ops, | ||
250 | .ct_owner = THIS_MODULE, | ||
251 | }, | ||
252 | .name = "header", | ||
177 | }; | 253 | }; |
178 | 254 | ||
179 | /* control/processing/default */ | 255 | /* ----------------------------------------------------------------------------- |
180 | static struct uvcg_default_processing { | 256 | * control/processing/default |
181 | struct config_group group; | 257 | */ |
182 | } uvcg_default_processing; | ||
183 | |||
184 | static inline struct uvcg_default_processing | ||
185 | *to_uvcg_default_processing(struct config_item *item) | ||
186 | { | ||
187 | return container_of(to_config_group(item), | ||
188 | struct uvcg_default_processing, group); | ||
189 | } | ||
190 | 258 | ||
191 | #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \ | 259 | #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \ |
192 | static ssize_t uvcg_default_processing_##cname##_show( \ | 260 | static ssize_t uvcg_default_processing_##cname##_show( \ |
193 | struct config_item *item, char *page) \ | 261 | struct config_item *item, char *page) \ |
194 | { \ | 262 | { \ |
195 | struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \ | 263 | struct config_group *group = to_config_group(item); \ |
196 | struct f_uvc_opts *opts; \ | 264 | struct f_uvc_opts *opts; \ |
197 | struct config_item *opts_item; \ | 265 | struct config_item *opts_item; \ |
198 | struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \ | 266 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ |
199 | struct uvc_processing_unit_descriptor *pd; \ | 267 | struct uvc_processing_unit_descriptor *pd; \ |
200 | int result; \ | 268 | int result; \ |
201 | \ | 269 | \ |
202 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ | 270 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ |
203 | \ | 271 | \ |
204 | opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \ | 272 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \ |
205 | opts = to_f_uvc_opts(opts_item); \ | 273 | opts = to_f_uvc_opts(opts_item); \ |
206 | pd = &opts->uvc_processing; \ | 274 | pd = &opts->uvc_processing; \ |
207 | \ | 275 | \ |
208 | mutex_lock(&opts->lock); \ | 276 | mutex_lock(&opts->lock); \ |
209 | result = sprintf(page, "%d\n", conv(pd->aname)); \ | 277 | result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \ |
210 | mutex_unlock(&opts->lock); \ | 278 | mutex_unlock(&opts->lock); \ |
211 | \ | 279 | \ |
212 | mutex_unlock(su_mutex); \ | 280 | mutex_unlock(su_mutex); \ |
@@ -215,37 +283,33 @@ static ssize_t uvcg_default_processing_##cname##_show( \ | |||
215 | \ | 283 | \ |
216 | UVC_ATTR_RO(uvcg_default_processing_, cname, aname) | 284 | UVC_ATTR_RO(uvcg_default_processing_, cname, aname) |
217 | 285 | ||
218 | #define identity_conv(x) (x) | 286 | UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8); |
219 | 287 | UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8); | |
220 | UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, identity_conv); | 288 | UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16); |
221 | UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, identity_conv); | 289 | UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8); |
222 | UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, le16_to_cpu); | ||
223 | UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv); | ||
224 | |||
225 | #undef identity_conv | ||
226 | 290 | ||
227 | #undef UVCG_DEFAULT_PROCESSING_ATTR | 291 | #undef UVCG_DEFAULT_PROCESSING_ATTR |
228 | 292 | ||
229 | static ssize_t uvcg_default_processing_bm_controls_show( | 293 | static ssize_t uvcg_default_processing_bm_controls_show( |
230 | struct config_item *item, char *page) | 294 | struct config_item *item, char *page) |
231 | { | 295 | { |
232 | struct uvcg_default_processing *dp = to_uvcg_default_processing(item); | 296 | struct config_group *group = to_config_group(item); |
233 | struct f_uvc_opts *opts; | 297 | struct f_uvc_opts *opts; |
234 | struct config_item *opts_item; | 298 | struct config_item *opts_item; |
235 | struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; | 299 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; |
236 | struct uvc_processing_unit_descriptor *pd; | 300 | struct uvc_processing_unit_descriptor *pd; |
237 | int result, i; | 301 | int result, i; |
238 | char *pg = page; | 302 | char *pg = page; |
239 | 303 | ||
240 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ | 304 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ |
241 | 305 | ||
242 | opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; | 306 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; |
243 | opts = to_f_uvc_opts(opts_item); | 307 | opts = to_f_uvc_opts(opts_item); |
244 | pd = &opts->uvc_processing; | 308 | pd = &opts->uvc_processing; |
245 | 309 | ||
246 | mutex_lock(&opts->lock); | 310 | mutex_lock(&opts->lock); |
247 | for (result = 0, i = 0; i < pd->bControlSize; ++i) { | 311 | for (result = 0, i = 0; i < pd->bControlSize; ++i) { |
248 | result += sprintf(pg, "%d\n", pd->bmControls[i]); | 312 | result += sprintf(pg, "%u\n", pd->bmControls[i]); |
249 | pg = page + result; | 313 | pg = page + result; |
250 | } | 314 | } |
251 | mutex_unlock(&opts->lock); | 315 | mutex_unlock(&opts->lock); |
@@ -266,54 +330,55 @@ static struct configfs_attribute *uvcg_default_processing_attrs[] = { | |||
266 | NULL, | 330 | NULL, |
267 | }; | 331 | }; |
268 | 332 | ||
269 | static const struct config_item_type uvcg_default_processing_type = { | 333 | static const struct uvcg_config_group_type uvcg_default_processing_type = { |
270 | .ct_attrs = uvcg_default_processing_attrs, | 334 | .type = { |
271 | .ct_owner = THIS_MODULE, | 335 | .ct_item_ops = &uvcg_config_item_ops, |
336 | .ct_attrs = uvcg_default_processing_attrs, | ||
337 | .ct_owner = THIS_MODULE, | ||
338 | }, | ||
339 | .name = "default", | ||
272 | }; | 340 | }; |
273 | 341 | ||
274 | /* struct uvcg_processing {}; */ | 342 | /* ----------------------------------------------------------------------------- |
275 | 343 | * control/processing | |
276 | /* control/processing */ | 344 | */ |
277 | static struct uvcg_processing_grp { | ||
278 | struct config_group group; | ||
279 | } uvcg_processing_grp; | ||
280 | 345 | ||
281 | static const struct config_item_type uvcg_processing_grp_type = { | 346 | static const struct uvcg_config_group_type uvcg_processing_grp_type = { |
282 | .ct_owner = THIS_MODULE, | 347 | .type = { |
348 | .ct_item_ops = &uvcg_config_item_ops, | ||
349 | .ct_owner = THIS_MODULE, | ||
350 | }, | ||
351 | .name = "processing", | ||
352 | .children = (const struct uvcg_config_group_type*[]) { | ||
353 | &uvcg_default_processing_type, | ||
354 | NULL, | ||
355 | }, | ||
283 | }; | 356 | }; |
284 | 357 | ||
285 | /* control/terminal/camera/default */ | 358 | /* ----------------------------------------------------------------------------- |
286 | static struct uvcg_default_camera { | 359 | * control/terminal/camera/default |
287 | struct config_group group; | 360 | */ |
288 | } uvcg_default_camera; | ||
289 | |||
290 | static inline struct uvcg_default_camera | ||
291 | *to_uvcg_default_camera(struct config_item *item) | ||
292 | { | ||
293 | return container_of(to_config_group(item), | ||
294 | struct uvcg_default_camera, group); | ||
295 | } | ||
296 | 361 | ||
297 | #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \ | 362 | #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \ |
298 | static ssize_t uvcg_default_camera_##cname##_show( \ | 363 | static ssize_t uvcg_default_camera_##cname##_show( \ |
299 | struct config_item *item, char *page) \ | 364 | struct config_item *item, char *page) \ |
300 | { \ | 365 | { \ |
301 | struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \ | 366 | struct config_group *group = to_config_group(item); \ |
302 | struct f_uvc_opts *opts; \ | 367 | struct f_uvc_opts *opts; \ |
303 | struct config_item *opts_item; \ | 368 | struct config_item *opts_item; \ |
304 | struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \ | 369 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ |
305 | struct uvc_camera_terminal_descriptor *cd; \ | 370 | struct uvc_camera_terminal_descriptor *cd; \ |
306 | int result; \ | 371 | int result; \ |
307 | \ | 372 | \ |
308 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ | 373 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ |
309 | \ | 374 | \ |
310 | opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \ | 375 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \ |
311 | ci_parent; \ | 376 | ci_parent; \ |
312 | opts = to_f_uvc_opts(opts_item); \ | 377 | opts = to_f_uvc_opts(opts_item); \ |
313 | cd = &opts->uvc_camera_terminal; \ | 378 | cd = &opts->uvc_camera_terminal; \ |
314 | \ | 379 | \ |
315 | mutex_lock(&opts->lock); \ | 380 | mutex_lock(&opts->lock); \ |
316 | result = sprintf(page, "%d\n", conv(cd->aname)); \ | 381 | result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \ |
317 | mutex_unlock(&opts->lock); \ | 382 | mutex_unlock(&opts->lock); \ |
318 | \ | 383 | \ |
319 | mutex_unlock(su_mutex); \ | 384 | mutex_unlock(su_mutex); \ |
@@ -323,44 +388,40 @@ static ssize_t uvcg_default_camera_##cname##_show( \ | |||
323 | \ | 388 | \ |
324 | UVC_ATTR_RO(uvcg_default_camera_, cname, aname) | 389 | UVC_ATTR_RO(uvcg_default_camera_, cname, aname) |
325 | 390 | ||
326 | #define identity_conv(x) (x) | 391 | UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8); |
327 | 392 | UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16); | |
328 | UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, identity_conv); | 393 | UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8); |
329 | UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, le16_to_cpu); | 394 | UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8); |
330 | UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv); | ||
331 | UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, identity_conv); | ||
332 | UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin, | 395 | UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin, |
333 | le16_to_cpu); | 396 | 16); |
334 | UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax, | 397 | UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax, |
335 | le16_to_cpu); | 398 | 16); |
336 | UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength, | 399 | UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength, |
337 | le16_to_cpu); | 400 | 16); |
338 | |||
339 | #undef identity_conv | ||
340 | 401 | ||
341 | #undef UVCG_DEFAULT_CAMERA_ATTR | 402 | #undef UVCG_DEFAULT_CAMERA_ATTR |
342 | 403 | ||
343 | static ssize_t uvcg_default_camera_bm_controls_show( | 404 | static ssize_t uvcg_default_camera_bm_controls_show( |
344 | struct config_item *item, char *page) | 405 | struct config_item *item, char *page) |
345 | { | 406 | { |
346 | struct uvcg_default_camera *dc = to_uvcg_default_camera(item); | 407 | struct config_group *group = to_config_group(item); |
347 | struct f_uvc_opts *opts; | 408 | struct f_uvc_opts *opts; |
348 | struct config_item *opts_item; | 409 | struct config_item *opts_item; |
349 | struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; | 410 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; |
350 | struct uvc_camera_terminal_descriptor *cd; | 411 | struct uvc_camera_terminal_descriptor *cd; |
351 | int result, i; | 412 | int result, i; |
352 | char *pg = page; | 413 | char *pg = page; |
353 | 414 | ||
354 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ | 415 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ |
355 | 416 | ||
356 | opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> | 417 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> |
357 | ci_parent; | 418 | ci_parent; |
358 | opts = to_f_uvc_opts(opts_item); | 419 | opts = to_f_uvc_opts(opts_item); |
359 | cd = &opts->uvc_camera_terminal; | 420 | cd = &opts->uvc_camera_terminal; |
360 | 421 | ||
361 | mutex_lock(&opts->lock); | 422 | mutex_lock(&opts->lock); |
362 | for (result = 0, i = 0; i < cd->bControlSize; ++i) { | 423 | for (result = 0, i = 0; i < cd->bControlSize; ++i) { |
363 | result += sprintf(pg, "%d\n", cd->bmControls[i]); | 424 | result += sprintf(pg, "%u\n", cd->bmControls[i]); |
364 | pg = page + result; | 425 | pg = page + result; |
365 | } | 426 | } |
366 | mutex_unlock(&opts->lock); | 427 | mutex_unlock(&opts->lock); |
@@ -383,54 +444,55 @@ static struct configfs_attribute *uvcg_default_camera_attrs[] = { | |||
383 | NULL, | 444 | NULL, |
384 | }; | 445 | }; |
385 | 446 | ||
386 | static const struct config_item_type uvcg_default_camera_type = { | 447 | static const struct uvcg_config_group_type uvcg_default_camera_type = { |
387 | .ct_attrs = uvcg_default_camera_attrs, | 448 | .type = { |
388 | .ct_owner = THIS_MODULE, | 449 | .ct_item_ops = &uvcg_config_item_ops, |
450 | .ct_attrs = uvcg_default_camera_attrs, | ||
451 | .ct_owner = THIS_MODULE, | ||
452 | }, | ||
453 | .name = "default", | ||
389 | }; | 454 | }; |
390 | 455 | ||
391 | /* struct uvcg_camera {}; */ | 456 | /* ----------------------------------------------------------------------------- |
392 | 457 | * control/terminal/camera | |
393 | /* control/terminal/camera */ | 458 | */ |
394 | static struct uvcg_camera_grp { | ||
395 | struct config_group group; | ||
396 | } uvcg_camera_grp; | ||
397 | 459 | ||
398 | static const struct config_item_type uvcg_camera_grp_type = { | 460 | static const struct uvcg_config_group_type uvcg_camera_grp_type = { |
399 | .ct_owner = THIS_MODULE, | 461 | .type = { |
462 | .ct_item_ops = &uvcg_config_item_ops, | ||
463 | .ct_owner = THIS_MODULE, | ||
464 | }, | ||
465 | .name = "camera", | ||
466 | .children = (const struct uvcg_config_group_type*[]) { | ||
467 | &uvcg_default_camera_type, | ||
468 | NULL, | ||
469 | }, | ||
400 | }; | 470 | }; |
401 | 471 | ||
402 | /* control/terminal/output/default */ | 472 | /* ----------------------------------------------------------------------------- |
403 | static struct uvcg_default_output { | 473 | * control/terminal/output/default |
404 | struct config_group group; | 474 | */ |
405 | } uvcg_default_output; | ||
406 | |||
407 | static inline struct uvcg_default_output | ||
408 | *to_uvcg_default_output(struct config_item *item) | ||
409 | { | ||
410 | return container_of(to_config_group(item), | ||
411 | struct uvcg_default_output, group); | ||
412 | } | ||
413 | 475 | ||
414 | #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \ | 476 | #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \ |
415 | static ssize_t uvcg_default_output_##cname##_show( \ | 477 | static ssize_t uvcg_default_output_##cname##_show( \ |
416 | struct config_item *item, char *page) \ | 478 | struct config_item *item, char *page) \ |
417 | { \ | 479 | { \ |
418 | struct uvcg_default_output *dout = to_uvcg_default_output(item); \ | 480 | struct config_group *group = to_config_group(item); \ |
419 | struct f_uvc_opts *opts; \ | 481 | struct f_uvc_opts *opts; \ |
420 | struct config_item *opts_item; \ | 482 | struct config_item *opts_item; \ |
421 | struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \ | 483 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ |
422 | struct uvc_output_terminal_descriptor *cd; \ | 484 | struct uvc_output_terminal_descriptor *cd; \ |
423 | int result; \ | 485 | int result; \ |
424 | \ | 486 | \ |
425 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ | 487 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ |
426 | \ | 488 | \ |
427 | opts_item = dout->group.cg_item.ci_parent->ci_parent-> \ | 489 | opts_item = group->cg_item.ci_parent->ci_parent-> \ |
428 | ci_parent->ci_parent; \ | 490 | ci_parent->ci_parent; \ |
429 | opts = to_f_uvc_opts(opts_item); \ | 491 | opts = to_f_uvc_opts(opts_item); \ |
430 | cd = &opts->uvc_output_terminal; \ | 492 | cd = &opts->uvc_output_terminal; \ |
431 | \ | 493 | \ |
432 | mutex_lock(&opts->lock); \ | 494 | mutex_lock(&opts->lock); \ |
433 | result = sprintf(page, "%d\n", conv(cd->aname)); \ | 495 | result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \ |
434 | mutex_unlock(&opts->lock); \ | 496 | mutex_unlock(&opts->lock); \ |
435 | \ | 497 | \ |
436 | mutex_unlock(su_mutex); \ | 498 | mutex_unlock(su_mutex); \ |
@@ -440,15 +502,11 @@ static ssize_t uvcg_default_output_##cname##_show( \ | |||
440 | \ | 502 | \ |
441 | UVC_ATTR_RO(uvcg_default_output_, cname, aname) | 503 | UVC_ATTR_RO(uvcg_default_output_, cname, aname) |
442 | 504 | ||
443 | #define identity_conv(x) (x) | 505 | UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8); |
444 | 506 | UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16); | |
445 | UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, identity_conv); | 507 | UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8); |
446 | UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, le16_to_cpu); | 508 | UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, 8); |
447 | UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv); | 509 | UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8); |
448 | UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, identity_conv); | ||
449 | UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv); | ||
450 | |||
451 | #undef identity_conv | ||
452 | 510 | ||
453 | #undef UVCG_DEFAULT_OUTPUT_ATTR | 511 | #undef UVCG_DEFAULT_OUTPUT_ATTR |
454 | 512 | ||
@@ -461,47 +519,68 @@ static struct configfs_attribute *uvcg_default_output_attrs[] = { | |||
461 | NULL, | 519 | NULL, |
462 | }; | 520 | }; |
463 | 521 | ||
464 | static const struct config_item_type uvcg_default_output_type = { | 522 | static const struct uvcg_config_group_type uvcg_default_output_type = { |
465 | .ct_attrs = uvcg_default_output_attrs, | 523 | .type = { |
466 | .ct_owner = THIS_MODULE, | 524 | .ct_item_ops = &uvcg_config_item_ops, |
525 | .ct_attrs = uvcg_default_output_attrs, | ||
526 | .ct_owner = THIS_MODULE, | ||
527 | }, | ||
528 | .name = "default", | ||
467 | }; | 529 | }; |
468 | 530 | ||
469 | /* struct uvcg_output {}; */ | 531 | /* ----------------------------------------------------------------------------- |
470 | 532 | * control/terminal/output | |
471 | /* control/terminal/output */ | 533 | */ |
472 | static struct uvcg_output_grp { | ||
473 | struct config_group group; | ||
474 | } uvcg_output_grp; | ||
475 | 534 | ||
476 | static const struct config_item_type uvcg_output_grp_type = { | 535 | static const struct uvcg_config_group_type uvcg_output_grp_type = { |
477 | .ct_owner = THIS_MODULE, | 536 | .type = { |
537 | .ct_item_ops = &uvcg_config_item_ops, | ||
538 | .ct_owner = THIS_MODULE, | ||
539 | }, | ||
540 | .name = "output", | ||
541 | .children = (const struct uvcg_config_group_type*[]) { | ||
542 | &uvcg_default_output_type, | ||
543 | NULL, | ||
544 | }, | ||
478 | }; | 545 | }; |
479 | 546 | ||
480 | /* control/terminal */ | 547 | /* ----------------------------------------------------------------------------- |
481 | static struct uvcg_terminal_grp { | 548 | * control/terminal |
482 | struct config_group group; | 549 | */ |
483 | } uvcg_terminal_grp; | ||
484 | 550 | ||
485 | static const struct config_item_type uvcg_terminal_grp_type = { | 551 | static const struct uvcg_config_group_type uvcg_terminal_grp_type = { |
486 | .ct_owner = THIS_MODULE, | 552 | .type = { |
553 | .ct_item_ops = &uvcg_config_item_ops, | ||
554 | .ct_owner = THIS_MODULE, | ||
555 | }, | ||
556 | .name = "terminal", | ||
557 | .children = (const struct uvcg_config_group_type*[]) { | ||
558 | &uvcg_camera_grp_type, | ||
559 | &uvcg_output_grp_type, | ||
560 | NULL, | ||
561 | }, | ||
487 | }; | 562 | }; |
488 | 563 | ||
489 | /* control/class/{fs} */ | 564 | /* ----------------------------------------------------------------------------- |
490 | static struct uvcg_control_class { | 565 | * control/class/{fs|ss} |
491 | struct config_group group; | 566 | */ |
492 | } uvcg_control_class_fs, uvcg_control_class_ss; | ||
493 | 567 | ||
568 | struct uvcg_control_class_group { | ||
569 | struct config_group group; | ||
570 | const char *name; | ||
571 | }; | ||
494 | 572 | ||
495 | static inline struct uvc_descriptor_header | 573 | static inline struct uvc_descriptor_header |
496 | **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o) | 574 | **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o) |
497 | { | 575 | { |
498 | struct uvcg_control_class *cl = container_of(to_config_group(i), | 576 | struct uvcg_control_class_group *group = |
499 | struct uvcg_control_class, group); | 577 | container_of(i, struct uvcg_control_class_group, |
578 | group.cg_item); | ||
500 | 579 | ||
501 | if (cl == &uvcg_control_class_fs) | 580 | if (!strcmp(group->name, "fs")) |
502 | return o->uvc_fs_control_cls; | 581 | return o->uvc_fs_control_cls; |
503 | 582 | ||
504 | if (cl == &uvcg_control_class_ss) | 583 | if (!strcmp(group->name, "ss")) |
505 | return o->uvc_ss_control_cls; | 584 | return o->uvc_ss_control_cls; |
506 | 585 | ||
507 | return NULL; | 586 | return NULL; |
@@ -544,6 +623,7 @@ static int uvcg_control_class_allow_link(struct config_item *src, | |||
544 | unlock: | 623 | unlock: |
545 | mutex_unlock(&opts->lock); | 624 | mutex_unlock(&opts->lock); |
546 | out: | 625 | out: |
626 | config_item_put(header); | ||
547 | mutex_unlock(su_mutex); | 627 | mutex_unlock(su_mutex); |
548 | return ret; | 628 | return ret; |
549 | } | 629 | } |
@@ -579,10 +659,12 @@ static void uvcg_control_class_drop_link(struct config_item *src, | |||
579 | unlock: | 659 | unlock: |
580 | mutex_unlock(&opts->lock); | 660 | mutex_unlock(&opts->lock); |
581 | out: | 661 | out: |
662 | config_item_put(header); | ||
582 | mutex_unlock(su_mutex); | 663 | mutex_unlock(su_mutex); |
583 | } | 664 | } |
584 | 665 | ||
585 | static struct configfs_item_operations uvcg_control_class_item_ops = { | 666 | static struct configfs_item_operations uvcg_control_class_item_ops = { |
667 | .release = uvcg_config_item_release, | ||
586 | .allow_link = uvcg_control_class_allow_link, | 668 | .allow_link = uvcg_control_class_allow_link, |
587 | .drop_link = uvcg_control_class_drop_link, | 669 | .drop_link = uvcg_control_class_drop_link, |
588 | }; | 670 | }; |
@@ -592,37 +674,99 @@ static const struct config_item_type uvcg_control_class_type = { | |||
592 | .ct_owner = THIS_MODULE, | 674 | .ct_owner = THIS_MODULE, |
593 | }; | 675 | }; |
594 | 676 | ||
595 | /* control/class */ | 677 | /* ----------------------------------------------------------------------------- |
596 | static struct uvcg_control_class_grp { | 678 | * control/class |
597 | struct config_group group; | 679 | */ |
598 | } uvcg_control_class_grp; | 680 | |
681 | static int uvcg_control_class_create_children(struct config_group *parent) | ||
682 | { | ||
683 | static const char * const names[] = { "fs", "ss" }; | ||
684 | unsigned int i; | ||
599 | 685 | ||
600 | static const struct config_item_type uvcg_control_class_grp_type = { | 686 | for (i = 0; i < ARRAY_SIZE(names); ++i) { |
601 | .ct_owner = THIS_MODULE, | 687 | struct uvcg_control_class_group *group; |
688 | |||
689 | group = kzalloc(sizeof(*group), GFP_KERNEL); | ||
690 | if (!group) | ||
691 | return -ENOMEM; | ||
692 | |||
693 | group->name = names[i]; | ||
694 | |||
695 | config_group_init_type_name(&group->group, group->name, | ||
696 | &uvcg_control_class_type); | ||
697 | configfs_add_default_group(&group->group, parent); | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static const struct uvcg_config_group_type uvcg_control_class_grp_type = { | ||
704 | .type = { | ||
705 | .ct_item_ops = &uvcg_config_item_ops, | ||
706 | .ct_owner = THIS_MODULE, | ||
707 | }, | ||
708 | .name = "class", | ||
709 | .create_children = uvcg_control_class_create_children, | ||
602 | }; | 710 | }; |
603 | 711 | ||
604 | /* control */ | 712 | /* ----------------------------------------------------------------------------- |
605 | static struct uvcg_control_grp { | 713 | * control |
606 | struct config_group group; | 714 | */ |
607 | } uvcg_control_grp; | 715 | |
716 | static ssize_t uvcg_default_control_b_interface_number_show( | ||
717 | struct config_item *item, char *page) | ||
718 | { | ||
719 | struct config_group *group = to_config_group(item); | ||
720 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; | ||
721 | struct config_item *opts_item; | ||
722 | struct f_uvc_opts *opts; | ||
723 | int result = 0; | ||
724 | |||
725 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ | ||
726 | |||
727 | opts_item = item->ci_parent; | ||
728 | opts = to_f_uvc_opts(opts_item); | ||
729 | |||
730 | mutex_lock(&opts->lock); | ||
731 | result += sprintf(page, "%u\n", opts->control_interface); | ||
732 | mutex_unlock(&opts->lock); | ||
733 | |||
734 | mutex_unlock(su_mutex); | ||
735 | |||
736 | return result; | ||
737 | } | ||
738 | |||
739 | UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber); | ||
608 | 740 | ||
609 | static const struct config_item_type uvcg_control_grp_type = { | 741 | static struct configfs_attribute *uvcg_default_control_attrs[] = { |
610 | .ct_owner = THIS_MODULE, | 742 | &uvcg_default_control_attr_b_interface_number, |
743 | NULL, | ||
611 | }; | 744 | }; |
612 | 745 | ||
613 | /* streaming/uncompressed */ | 746 | static const struct uvcg_config_group_type uvcg_control_grp_type = { |
614 | static struct uvcg_uncompressed_grp { | 747 | .type = { |
615 | struct config_group group; | 748 | .ct_item_ops = &uvcg_config_item_ops, |
616 | } uvcg_uncompressed_grp; | 749 | .ct_attrs = uvcg_default_control_attrs, |
750 | .ct_owner = THIS_MODULE, | ||
751 | }, | ||
752 | .name = "control", | ||
753 | .children = (const struct uvcg_config_group_type*[]) { | ||
754 | &uvcg_control_header_grp_type, | ||
755 | &uvcg_processing_grp_type, | ||
756 | &uvcg_terminal_grp_type, | ||
757 | &uvcg_control_class_grp_type, | ||
758 | NULL, | ||
759 | }, | ||
760 | }; | ||
617 | 761 | ||
618 | /* streaming/mjpeg */ | 762 | /* ----------------------------------------------------------------------------- |
619 | static struct uvcg_mjpeg_grp { | 763 | * streaming/uncompressed |
620 | struct config_group group; | 764 | * streaming/mjpeg |
621 | } uvcg_mjpeg_grp; | 765 | */ |
622 | 766 | ||
623 | static struct config_item *fmt_parent[] = { | 767 | static const char * const uvcg_format_names[] = { |
624 | &uvcg_uncompressed_grp.group.cg_item, | 768 | "uncompressed", |
625 | &uvcg_mjpeg_grp.group.cg_item, | 769 | "mjpeg", |
626 | }; | 770 | }; |
627 | 771 | ||
628 | enum uvcg_format_type { | 772 | enum uvcg_format_type { |
@@ -706,7 +850,11 @@ struct uvcg_format_ptr { | |||
706 | struct list_head entry; | 850 | struct list_head entry; |
707 | }; | 851 | }; |
708 | 852 | ||
709 | /* streaming/header/<NAME> */ | 853 | /* ----------------------------------------------------------------------------- |
854 | * streaming/header/<NAME> | ||
855 | * streaming/header | ||
856 | */ | ||
857 | |||
710 | struct uvcg_streaming_header { | 858 | struct uvcg_streaming_header { |
711 | struct config_item item; | 859 | struct config_item item; |
712 | struct uvc_input_header_descriptor desc; | 860 | struct uvc_input_header_descriptor desc; |
@@ -720,6 +868,8 @@ static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item | |||
720 | return container_of(item, struct uvcg_streaming_header, item); | 868 | return container_of(item, struct uvcg_streaming_header, item); |
721 | } | 869 | } |
722 | 870 | ||
871 | static void uvcg_format_set_indices(struct config_group *fmt); | ||
872 | |||
723 | static int uvcg_streaming_header_allow_link(struct config_item *src, | 873 | static int uvcg_streaming_header_allow_link(struct config_item *src, |
724 | struct config_item *target) | 874 | struct config_item *target) |
725 | { | 875 | { |
@@ -744,10 +894,22 @@ static int uvcg_streaming_header_allow_link(struct config_item *src, | |||
744 | goto out; | 894 | goto out; |
745 | } | 895 | } |
746 | 896 | ||
747 | for (i = 0; i < ARRAY_SIZE(fmt_parent); ++i) | 897 | /* |
748 | if (target->ci_parent == fmt_parent[i]) | 898 | * Linking is only allowed to direct children of the format nodes |
899 | * (streaming/uncompressed or streaming/mjpeg nodes). First check that | ||
900 | * the grand-parent of the target matches the grand-parent of the source | ||
901 | * (the streaming node), and then verify that the target parent is a | ||
902 | * format node. | ||
903 | */ | ||
904 | if (src->ci_parent->ci_parent != target->ci_parent->ci_parent) | ||
905 | goto out; | ||
906 | |||
907 | for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) { | ||
908 | if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i])) | ||
749 | break; | 909 | break; |
750 | if (i == ARRAY_SIZE(fmt_parent)) | 910 | } |
911 | |||
912 | if (i == ARRAY_SIZE(uvcg_format_names)) | ||
751 | goto out; | 913 | goto out; |
752 | 914 | ||
753 | target_fmt = container_of(to_config_group(target), struct uvcg_format, | 915 | target_fmt = container_of(to_config_group(target), struct uvcg_format, |
@@ -755,6 +917,8 @@ static int uvcg_streaming_header_allow_link(struct config_item *src, | |||
755 | if (!target_fmt) | 917 | if (!target_fmt) |
756 | goto out; | 918 | goto out; |
757 | 919 | ||
920 | uvcg_format_set_indices(to_config_group(target)); | ||
921 | |||
758 | format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL); | 922 | format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL); |
759 | if (!format_ptr) { | 923 | if (!format_ptr) { |
760 | ret = -ENOMEM; | 924 | ret = -ENOMEM; |
@@ -764,6 +928,7 @@ static int uvcg_streaming_header_allow_link(struct config_item *src, | |||
764 | format_ptr->fmt = target_fmt; | 928 | format_ptr->fmt = target_fmt; |
765 | list_add_tail(&format_ptr->entry, &src_hdr->formats); | 929 | list_add_tail(&format_ptr->entry, &src_hdr->formats); |
766 | ++src_hdr->num_fmt; | 930 | ++src_hdr->num_fmt; |
931 | ++target_fmt->linked; | ||
767 | 932 | ||
768 | out: | 933 | out: |
769 | mutex_unlock(&opts->lock); | 934 | mutex_unlock(&opts->lock); |
@@ -801,19 +966,22 @@ static void uvcg_streaming_header_drop_link(struct config_item *src, | |||
801 | break; | 966 | break; |
802 | } | 967 | } |
803 | 968 | ||
969 | --target_fmt->linked; | ||
970 | |||
804 | out: | 971 | out: |
805 | mutex_unlock(&opts->lock); | 972 | mutex_unlock(&opts->lock); |
806 | mutex_unlock(su_mutex); | 973 | mutex_unlock(su_mutex); |
807 | } | 974 | } |
808 | 975 | ||
809 | static struct configfs_item_operations uvcg_streaming_header_item_ops = { | 976 | static struct configfs_item_operations uvcg_streaming_header_item_ops = { |
810 | .allow_link = uvcg_streaming_header_allow_link, | 977 | .release = uvcg_config_item_release, |
811 | .drop_link = uvcg_streaming_header_drop_link, | 978 | .allow_link = uvcg_streaming_header_allow_link, |
979 | .drop_link = uvcg_streaming_header_drop_link, | ||
812 | }; | 980 | }; |
813 | 981 | ||
814 | #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \ | 982 | #define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \ |
815 | static ssize_t uvcg_streaming_header_##cname##_show( \ | 983 | static ssize_t uvcg_streaming_header_##cname##_show( \ |
816 | struct config_item *item, char *page) \ | 984 | struct config_item *item, char *page) \ |
817 | { \ | 985 | { \ |
818 | struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \ | 986 | struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \ |
819 | struct f_uvc_opts *opts; \ | 987 | struct f_uvc_opts *opts; \ |
@@ -827,7 +995,7 @@ static ssize_t uvcg_streaming_header_##cname##_show( \ | |||
827 | opts = to_f_uvc_opts(opts_item); \ | 995 | opts = to_f_uvc_opts(opts_item); \ |
828 | \ | 996 | \ |
829 | mutex_lock(&opts->lock); \ | 997 | mutex_lock(&opts->lock); \ |
830 | result = sprintf(page, "%d\n", conv(sh->desc.aname)); \ | 998 | result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\ |
831 | mutex_unlock(&opts->lock); \ | 999 | mutex_unlock(&opts->lock); \ |
832 | \ | 1000 | \ |
833 | mutex_unlock(su_mutex); \ | 1001 | mutex_unlock(su_mutex); \ |
@@ -836,16 +1004,11 @@ static ssize_t uvcg_streaming_header_##cname##_show( \ | |||
836 | \ | 1004 | \ |
837 | UVC_ATTR_RO(uvcg_streaming_header_, cname, aname) | 1005 | UVC_ATTR_RO(uvcg_streaming_header_, cname, aname) |
838 | 1006 | ||
839 | #define identity_conv(x) (x) | 1007 | UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8); |
840 | 1008 | UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8); | |
841 | UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, identity_conv); | 1009 | UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8); |
842 | UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, identity_conv); | 1010 | UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8); |
843 | UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, | 1011 | UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8); |
844 | identity_conv); | ||
845 | UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, identity_conv); | ||
846 | UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv); | ||
847 | |||
848 | #undef identity_conv | ||
849 | 1012 | ||
850 | #undef UVCG_STREAMING_HEADER_ATTR | 1013 | #undef UVCG_STREAMING_HEADER_ATTR |
851 | 1014 | ||
@@ -884,31 +1047,26 @@ static struct config_item | |||
884 | return &h->item; | 1047 | return &h->item; |
885 | } | 1048 | } |
886 | 1049 | ||
887 | static void uvcg_streaming_header_drop(struct config_group *group, | ||
888 | struct config_item *item) | ||
889 | { | ||
890 | struct uvcg_streaming_header *h = to_uvcg_streaming_header(item); | ||
891 | |||
892 | kfree(h); | ||
893 | } | ||
894 | |||
895 | /* streaming/header */ | ||
896 | static struct uvcg_streaming_header_grp { | ||
897 | struct config_group group; | ||
898 | } uvcg_streaming_header_grp; | ||
899 | |||
900 | static struct configfs_group_operations uvcg_streaming_header_grp_ops = { | 1050 | static struct configfs_group_operations uvcg_streaming_header_grp_ops = { |
901 | .make_item = uvcg_streaming_header_make, | 1051 | .make_item = uvcg_streaming_header_make, |
902 | .drop_item = uvcg_streaming_header_drop, | ||
903 | }; | 1052 | }; |
904 | 1053 | ||
905 | static const struct config_item_type uvcg_streaming_header_grp_type = { | 1054 | static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = { |
906 | .ct_group_ops = &uvcg_streaming_header_grp_ops, | 1055 | .type = { |
907 | .ct_owner = THIS_MODULE, | 1056 | .ct_item_ops = &uvcg_config_item_ops, |
1057 | .ct_group_ops = &uvcg_streaming_header_grp_ops, | ||
1058 | .ct_owner = THIS_MODULE, | ||
1059 | }, | ||
1060 | .name = "header", | ||
908 | }; | 1061 | }; |
909 | 1062 | ||
910 | /* streaming/<mode>/<format>/<NAME> */ | 1063 | /* ----------------------------------------------------------------------------- |
1064 | * streaming/<mode>/<format>/<NAME> | ||
1065 | */ | ||
1066 | |||
911 | struct uvcg_frame { | 1067 | struct uvcg_frame { |
1068 | struct config_item item; | ||
1069 | enum uvcg_format_type fmt_type; | ||
912 | struct { | 1070 | struct { |
913 | u8 b_length; | 1071 | u8 b_length; |
914 | u8 b_descriptor_type; | 1072 | u8 b_descriptor_type; |
@@ -924,8 +1082,6 @@ struct uvcg_frame { | |||
924 | u8 b_frame_interval_type; | 1082 | u8 b_frame_interval_type; |
925 | } __attribute__((packed)) frame; | 1083 | } __attribute__((packed)) frame; |
926 | u32 *dw_frame_interval; | 1084 | u32 *dw_frame_interval; |
927 | enum uvcg_format_type fmt_type; | ||
928 | struct config_item item; | ||
929 | }; | 1085 | }; |
930 | 1086 | ||
931 | static struct uvcg_frame *to_uvcg_frame(struct config_item *item) | 1087 | static struct uvcg_frame *to_uvcg_frame(struct config_item *item) |
@@ -933,7 +1089,7 @@ static struct uvcg_frame *to_uvcg_frame(struct config_item *item) | |||
933 | return container_of(item, struct uvcg_frame, item); | 1089 | return container_of(item, struct uvcg_frame, item); |
934 | } | 1090 | } |
935 | 1091 | ||
936 | #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \ | 1092 | #define UVCG_FRAME_ATTR(cname, aname, bits) \ |
937 | static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\ | 1093 | static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\ |
938 | { \ | 1094 | { \ |
939 | struct uvcg_frame *f = to_uvcg_frame(item); \ | 1095 | struct uvcg_frame *f = to_uvcg_frame(item); \ |
@@ -948,7 +1104,7 @@ static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\ | |||
948 | opts = to_f_uvc_opts(opts_item); \ | 1104 | opts = to_f_uvc_opts(opts_item); \ |
949 | \ | 1105 | \ |
950 | mutex_lock(&opts->lock); \ | 1106 | mutex_lock(&opts->lock); \ |
951 | result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \ | 1107 | result = sprintf(page, "%u\n", f->frame.cname); \ |
952 | mutex_unlock(&opts->lock); \ | 1108 | mutex_unlock(&opts->lock); \ |
953 | \ | 1109 | \ |
954 | mutex_unlock(su_mutex); \ | 1110 | mutex_unlock(su_mutex); \ |
@@ -963,8 +1119,8 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \ | |||
963 | struct config_item *opts_item; \ | 1119 | struct config_item *opts_item; \ |
964 | struct uvcg_format *fmt; \ | 1120 | struct uvcg_format *fmt; \ |
965 | struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\ | 1121 | struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\ |
1122 | typeof(f->frame.cname) num; \ | ||
966 | int ret; \ | 1123 | int ret; \ |
967 | u##bits num; \ | ||
968 | \ | 1124 | \ |
969 | ret = kstrtou##bits(page, 0, &num); \ | 1125 | ret = kstrtou##bits(page, 0, &num); \ |
970 | if (ret) \ | 1126 | if (ret) \ |
@@ -982,7 +1138,7 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \ | |||
982 | goto end; \ | 1138 | goto end; \ |
983 | } \ | 1139 | } \ |
984 | \ | 1140 | \ |
985 | f->frame.cname = to_little_endian(num); \ | 1141 | f->frame.cname = num; \ |
986 | ret = len; \ | 1142 | ret = len; \ |
987 | end: \ | 1143 | end: \ |
988 | mutex_unlock(&opts->lock); \ | 1144 | mutex_unlock(&opts->lock); \ |
@@ -992,20 +1148,48 @@ end: \ | |||
992 | \ | 1148 | \ |
993 | UVC_ATTR(uvcg_frame_, cname, aname); | 1149 | UVC_ATTR(uvcg_frame_, cname, aname); |
994 | 1150 | ||
995 | #define noop_conversion(x) (x) | 1151 | static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item, |
1152 | char *page) | ||
1153 | { | ||
1154 | struct uvcg_frame *f = to_uvcg_frame(item); | ||
1155 | struct uvcg_format *fmt; | ||
1156 | struct f_uvc_opts *opts; | ||
1157 | struct config_item *opts_item; | ||
1158 | struct config_item *fmt_item; | ||
1159 | struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex; | ||
1160 | int result; | ||
1161 | |||
1162 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ | ||
1163 | |||
1164 | fmt_item = f->item.ci_parent; | ||
1165 | fmt = to_uvcg_format(fmt_item); | ||
996 | 1166 | ||
997 | UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion, | 1167 | if (!fmt->linked) { |
998 | noop_conversion, 8); | 1168 | result = -EBUSY; |
999 | UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16); | 1169 | goto out; |
1000 | UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16); | 1170 | } |
1001 | UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32); | ||
1002 | UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32); | ||
1003 | UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, | ||
1004 | le32_to_cpu, cpu_to_le32, 32); | ||
1005 | UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, | ||
1006 | le32_to_cpu, cpu_to_le32, 32); | ||
1007 | 1171 | ||
1008 | #undef noop_conversion | 1172 | opts_item = fmt_item->ci_parent->ci_parent->ci_parent; |
1173 | opts = to_f_uvc_opts(opts_item); | ||
1174 | |||
1175 | mutex_lock(&opts->lock); | ||
1176 | result = sprintf(page, "%u\n", f->frame.b_frame_index); | ||
1177 | mutex_unlock(&opts->lock); | ||
1178 | |||
1179 | out: | ||
1180 | mutex_unlock(su_mutex); | ||
1181 | return result; | ||
1182 | } | ||
1183 | |||
1184 | UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex); | ||
1185 | |||
1186 | UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8); | ||
1187 | UVCG_FRAME_ATTR(w_width, wWidth, 16); | ||
1188 | UVCG_FRAME_ATTR(w_height, wHeight, 16); | ||
1189 | UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32); | ||
1190 | UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32); | ||
1191 | UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32); | ||
1192 | UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32); | ||
1009 | 1193 | ||
1010 | #undef UVCG_FRAME_ATTR | 1194 | #undef UVCG_FRAME_ATTR |
1011 | 1195 | ||
@@ -1026,8 +1210,7 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item, | |||
1026 | 1210 | ||
1027 | mutex_lock(&opts->lock); | 1211 | mutex_lock(&opts->lock); |
1028 | for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) { | 1212 | for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) { |
1029 | result += sprintf(pg, "%d\n", | 1213 | result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]); |
1030 | le32_to_cpu(frm->dw_frame_interval[i])); | ||
1031 | pg = page + result; | 1214 | pg = page + result; |
1032 | } | 1215 | } |
1033 | mutex_unlock(&opts->lock); | 1216 | mutex_unlock(&opts->lock); |
@@ -1052,7 +1235,7 @@ static inline int __uvcg_fill_frm_intrv(char *buf, void *priv) | |||
1052 | return ret; | 1235 | return ret; |
1053 | 1236 | ||
1054 | interv = priv; | 1237 | interv = priv; |
1055 | **interv = cpu_to_le32(num); | 1238 | **interv = num; |
1056 | ++*interv; | 1239 | ++*interv; |
1057 | 1240 | ||
1058 | return 0; | 1241 | return 0; |
@@ -1129,6 +1312,8 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item, | |||
1129 | kfree(ch->dw_frame_interval); | 1312 | kfree(ch->dw_frame_interval); |
1130 | ch->dw_frame_interval = frm_intrv; | 1313 | ch->dw_frame_interval = frm_intrv; |
1131 | ch->frame.b_frame_interval_type = n; | 1314 | ch->frame.b_frame_interval_type = n; |
1315 | sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval), | ||
1316 | uvcg_config_compare_u32, NULL); | ||
1132 | ret = len; | 1317 | ret = len; |
1133 | 1318 | ||
1134 | end: | 1319 | end: |
@@ -1140,6 +1325,7 @@ end: | |||
1140 | UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval); | 1325 | UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval); |
1141 | 1326 | ||
1142 | static struct configfs_attribute *uvcg_frame_attrs[] = { | 1327 | static struct configfs_attribute *uvcg_frame_attrs[] = { |
1328 | &uvcg_frame_attr_b_frame_index, | ||
1143 | &uvcg_frame_attr_bm_capabilities, | 1329 | &uvcg_frame_attr_bm_capabilities, |
1144 | &uvcg_frame_attr_w_width, | 1330 | &uvcg_frame_attr_w_width, |
1145 | &uvcg_frame_attr_w_height, | 1331 | &uvcg_frame_attr_w_height, |
@@ -1152,6 +1338,7 @@ static struct configfs_attribute *uvcg_frame_attrs[] = { | |||
1152 | }; | 1338 | }; |
1153 | 1339 | ||
1154 | static const struct config_item_type uvcg_frame_type = { | 1340 | static const struct config_item_type uvcg_frame_type = { |
1341 | .ct_item_ops = &uvcg_config_item_ops, | ||
1155 | .ct_attrs = uvcg_frame_attrs, | 1342 | .ct_attrs = uvcg_frame_attrs, |
1156 | .ct_owner = THIS_MODULE, | 1343 | .ct_owner = THIS_MODULE, |
1157 | }; | 1344 | }; |
@@ -1170,12 +1357,12 @@ static struct config_item *uvcg_frame_make(struct config_group *group, | |||
1170 | 1357 | ||
1171 | h->frame.b_descriptor_type = USB_DT_CS_INTERFACE; | 1358 | h->frame.b_descriptor_type = USB_DT_CS_INTERFACE; |
1172 | h->frame.b_frame_index = 1; | 1359 | h->frame.b_frame_index = 1; |
1173 | h->frame.w_width = cpu_to_le16(640); | 1360 | h->frame.w_width = 640; |
1174 | h->frame.w_height = cpu_to_le16(360); | 1361 | h->frame.w_height = 360; |
1175 | h->frame.dw_min_bit_rate = cpu_to_le32(18432000); | 1362 | h->frame.dw_min_bit_rate = 18432000; |
1176 | h->frame.dw_max_bit_rate = cpu_to_le32(55296000); | 1363 | h->frame.dw_max_bit_rate = 55296000; |
1177 | h->frame.dw_max_video_frame_buffer_size = cpu_to_le32(460800); | 1364 | h->frame.dw_max_video_frame_buffer_size = 460800; |
1178 | h->frame.dw_default_frame_interval = cpu_to_le32(666666); | 1365 | h->frame.dw_default_frame_interval = 666666; |
1179 | 1366 | ||
1180 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; | 1367 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; |
1181 | opts = to_f_uvc_opts(opts_item); | 1368 | opts = to_f_uvc_opts(opts_item); |
@@ -1203,7 +1390,6 @@ static struct config_item *uvcg_frame_make(struct config_group *group, | |||
1203 | 1390 | ||
1204 | static void uvcg_frame_drop(struct config_group *group, struct config_item *item) | 1391 | static void uvcg_frame_drop(struct config_group *group, struct config_item *item) |
1205 | { | 1392 | { |
1206 | struct uvcg_frame *h = to_uvcg_frame(item); | ||
1207 | struct uvcg_format *fmt; | 1393 | struct uvcg_format *fmt; |
1208 | struct f_uvc_opts *opts; | 1394 | struct f_uvc_opts *opts; |
1209 | struct config_item *opts_item; | 1395 | struct config_item *opts_item; |
@@ -1214,11 +1400,31 @@ static void uvcg_frame_drop(struct config_group *group, struct config_item *item | |||
1214 | mutex_lock(&opts->lock); | 1400 | mutex_lock(&opts->lock); |
1215 | fmt = to_uvcg_format(&group->cg_item); | 1401 | fmt = to_uvcg_format(&group->cg_item); |
1216 | --fmt->num_frames; | 1402 | --fmt->num_frames; |
1217 | kfree(h); | ||
1218 | mutex_unlock(&opts->lock); | 1403 | mutex_unlock(&opts->lock); |
1404 | |||
1405 | config_item_put(item); | ||
1406 | } | ||
1407 | |||
1408 | static void uvcg_format_set_indices(struct config_group *fmt) | ||
1409 | { | ||
1410 | struct config_item *ci; | ||
1411 | unsigned int i = 1; | ||
1412 | |||
1413 | list_for_each_entry(ci, &fmt->cg_children, ci_entry) { | ||
1414 | struct uvcg_frame *frm; | ||
1415 | |||
1416 | if (ci->ci_type != &uvcg_frame_type) | ||
1417 | continue; | ||
1418 | |||
1419 | frm = to_uvcg_frame(ci); | ||
1420 | frm->frame.b_frame_index = i++; | ||
1421 | } | ||
1219 | } | 1422 | } |
1220 | 1423 | ||
1221 | /* streaming/uncompressed/<NAME> */ | 1424 | /* ----------------------------------------------------------------------------- |
1425 | * streaming/uncompressed/<NAME> | ||
1426 | */ | ||
1427 | |||
1222 | struct uvcg_uncompressed { | 1428 | struct uvcg_uncompressed { |
1223 | struct uvcg_format fmt; | 1429 | struct uvcg_format fmt; |
1224 | struct uvc_format_uncompressed desc; | 1430 | struct uvc_format_uncompressed desc; |
@@ -1290,7 +1496,7 @@ end: | |||
1290 | 1496 | ||
1291 | UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat); | 1497 | UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat); |
1292 | 1498 | ||
1293 | #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \ | 1499 | #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \ |
1294 | static ssize_t uvcg_uncompressed_##cname##_show( \ | 1500 | static ssize_t uvcg_uncompressed_##cname##_show( \ |
1295 | struct config_item *item, char *page) \ | 1501 | struct config_item *item, char *page) \ |
1296 | { \ | 1502 | { \ |
@@ -1306,7 +1512,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \ | |||
1306 | opts = to_f_uvc_opts(opts_item); \ | 1512 | opts = to_f_uvc_opts(opts_item); \ |
1307 | \ | 1513 | \ |
1308 | mutex_lock(&opts->lock); \ | 1514 | mutex_lock(&opts->lock); \ |
1309 | result = sprintf(page, "%d\n", conv(u->desc.aname)); \ | 1515 | result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ |
1310 | mutex_unlock(&opts->lock); \ | 1516 | mutex_unlock(&opts->lock); \ |
1311 | \ | 1517 | \ |
1312 | mutex_unlock(su_mutex); \ | 1518 | mutex_unlock(su_mutex); \ |
@@ -1315,7 +1521,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \ | |||
1315 | \ | 1521 | \ |
1316 | UVC_ATTR_RO(uvcg_uncompressed_, cname, aname); | 1522 | UVC_ATTR_RO(uvcg_uncompressed_, cname, aname); |
1317 | 1523 | ||
1318 | #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \ | 1524 | #define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \ |
1319 | static ssize_t uvcg_uncompressed_##cname##_show( \ | 1525 | static ssize_t uvcg_uncompressed_##cname##_show( \ |
1320 | struct config_item *item, char *page) \ | 1526 | struct config_item *item, char *page) \ |
1321 | { \ | 1527 | { \ |
@@ -1331,7 +1537,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \ | |||
1331 | opts = to_f_uvc_opts(opts_item); \ | 1537 | opts = to_f_uvc_opts(opts_item); \ |
1332 | \ | 1538 | \ |
1333 | mutex_lock(&opts->lock); \ | 1539 | mutex_lock(&opts->lock); \ |
1334 | result = sprintf(page, "%d\n", conv(u->desc.aname)); \ | 1540 | result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ |
1335 | mutex_unlock(&opts->lock); \ | 1541 | mutex_unlock(&opts->lock); \ |
1336 | \ | 1542 | \ |
1337 | mutex_unlock(su_mutex); \ | 1543 | mutex_unlock(su_mutex); \ |
@@ -1378,16 +1584,12 @@ end: \ | |||
1378 | \ | 1584 | \ |
1379 | UVC_ATTR(uvcg_uncompressed_, cname, aname); | 1585 | UVC_ATTR(uvcg_uncompressed_, cname, aname); |
1380 | 1586 | ||
1381 | #define identity_conv(x) (x) | 1587 | UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8); |
1382 | 1588 | UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8); | |
1383 | UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv); | 1589 | UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8); |
1384 | UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, | 1590 | UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8); |
1385 | identity_conv); | 1591 | UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8); |
1386 | UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv); | 1592 | UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8); |
1387 | UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv); | ||
1388 | UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv); | ||
1389 | |||
1390 | #undef identity_conv | ||
1391 | 1593 | ||
1392 | #undef UVCG_UNCOMPRESSED_ATTR | 1594 | #undef UVCG_UNCOMPRESSED_ATTR |
1393 | #undef UVCG_UNCOMPRESSED_ATTR_RO | 1595 | #undef UVCG_UNCOMPRESSED_ATTR_RO |
@@ -1410,6 +1612,7 @@ uvcg_uncompressed_bma_controls_store(struct config_item *item, | |||
1410 | UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls); | 1612 | UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls); |
1411 | 1613 | ||
1412 | static struct configfs_attribute *uvcg_uncompressed_attrs[] = { | 1614 | static struct configfs_attribute *uvcg_uncompressed_attrs[] = { |
1615 | &uvcg_uncompressed_attr_b_format_index, | ||
1413 | &uvcg_uncompressed_attr_guid_format, | 1616 | &uvcg_uncompressed_attr_guid_format, |
1414 | &uvcg_uncompressed_attr_b_bits_per_pixel, | 1617 | &uvcg_uncompressed_attr_b_bits_per_pixel, |
1415 | &uvcg_uncompressed_attr_b_default_frame_index, | 1618 | &uvcg_uncompressed_attr_b_default_frame_index, |
@@ -1421,6 +1624,7 @@ static struct configfs_attribute *uvcg_uncompressed_attrs[] = { | |||
1421 | }; | 1624 | }; |
1422 | 1625 | ||
1423 | static const struct config_item_type uvcg_uncompressed_type = { | 1626 | static const struct config_item_type uvcg_uncompressed_type = { |
1627 | .ct_item_ops = &uvcg_config_item_ops, | ||
1424 | .ct_group_ops = &uvcg_uncompressed_group_ops, | 1628 | .ct_group_ops = &uvcg_uncompressed_group_ops, |
1425 | .ct_attrs = uvcg_uncompressed_attrs, | 1629 | .ct_attrs = uvcg_uncompressed_attrs, |
1426 | .ct_owner = THIS_MODULE, | 1630 | .ct_owner = THIS_MODULE, |
@@ -1457,25 +1661,23 @@ static struct config_group *uvcg_uncompressed_make(struct config_group *group, | |||
1457 | return &h->fmt.group; | 1661 | return &h->fmt.group; |
1458 | } | 1662 | } |
1459 | 1663 | ||
1460 | static void uvcg_uncompressed_drop(struct config_group *group, | ||
1461 | struct config_item *item) | ||
1462 | { | ||
1463 | struct uvcg_uncompressed *h = to_uvcg_uncompressed(item); | ||
1464 | |||
1465 | kfree(h); | ||
1466 | } | ||
1467 | |||
1468 | static struct configfs_group_operations uvcg_uncompressed_grp_ops = { | 1664 | static struct configfs_group_operations uvcg_uncompressed_grp_ops = { |
1469 | .make_group = uvcg_uncompressed_make, | 1665 | .make_group = uvcg_uncompressed_make, |
1470 | .drop_item = uvcg_uncompressed_drop, | ||
1471 | }; | 1666 | }; |
1472 | 1667 | ||
1473 | static const struct config_item_type uvcg_uncompressed_grp_type = { | 1668 | static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = { |
1474 | .ct_group_ops = &uvcg_uncompressed_grp_ops, | 1669 | .type = { |
1475 | .ct_owner = THIS_MODULE, | 1670 | .ct_item_ops = &uvcg_config_item_ops, |
1671 | .ct_group_ops = &uvcg_uncompressed_grp_ops, | ||
1672 | .ct_owner = THIS_MODULE, | ||
1673 | }, | ||
1674 | .name = "uncompressed", | ||
1476 | }; | 1675 | }; |
1477 | 1676 | ||
1478 | /* streaming/mjpeg/<NAME> */ | 1677 | /* ----------------------------------------------------------------------------- |
1678 | * streaming/mjpeg/<NAME> | ||
1679 | */ | ||
1680 | |||
1479 | struct uvcg_mjpeg { | 1681 | struct uvcg_mjpeg { |
1480 | struct uvcg_format fmt; | 1682 | struct uvcg_format fmt; |
1481 | struct uvc_format_mjpeg desc; | 1683 | struct uvc_format_mjpeg desc; |
@@ -1493,7 +1695,7 @@ static struct configfs_group_operations uvcg_mjpeg_group_ops = { | |||
1493 | .drop_item = uvcg_frame_drop, | 1695 | .drop_item = uvcg_frame_drop, |
1494 | }; | 1696 | }; |
1495 | 1697 | ||
1496 | #define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \ | 1698 | #define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \ |
1497 | static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ | 1699 | static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ |
1498 | { \ | 1700 | { \ |
1499 | struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ | 1701 | struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ |
@@ -1508,7 +1710,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ | |||
1508 | opts = to_f_uvc_opts(opts_item); \ | 1710 | opts = to_f_uvc_opts(opts_item); \ |
1509 | \ | 1711 | \ |
1510 | mutex_lock(&opts->lock); \ | 1712 | mutex_lock(&opts->lock); \ |
1511 | result = sprintf(page, "%d\n", conv(u->desc.aname)); \ | 1713 | result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ |
1512 | mutex_unlock(&opts->lock); \ | 1714 | mutex_unlock(&opts->lock); \ |
1513 | \ | 1715 | \ |
1514 | mutex_unlock(su_mutex); \ | 1716 | mutex_unlock(su_mutex); \ |
@@ -1517,7 +1719,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ | |||
1517 | \ | 1719 | \ |
1518 | UVC_ATTR_RO(uvcg_mjpeg_, cname, aname) | 1720 | UVC_ATTR_RO(uvcg_mjpeg_, cname, aname) |
1519 | 1721 | ||
1520 | #define UVCG_MJPEG_ATTR(cname, aname, conv) \ | 1722 | #define UVCG_MJPEG_ATTR(cname, aname, bits) \ |
1521 | static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ | 1723 | static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ |
1522 | { \ | 1724 | { \ |
1523 | struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ | 1725 | struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ |
@@ -1532,7 +1734,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ | |||
1532 | opts = to_f_uvc_opts(opts_item); \ | 1734 | opts = to_f_uvc_opts(opts_item); \ |
1533 | \ | 1735 | \ |
1534 | mutex_lock(&opts->lock); \ | 1736 | mutex_lock(&opts->lock); \ |
1535 | result = sprintf(page, "%d\n", conv(u->desc.aname)); \ | 1737 | result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ |
1536 | mutex_unlock(&opts->lock); \ | 1738 | mutex_unlock(&opts->lock); \ |
1537 | \ | 1739 | \ |
1538 | mutex_unlock(su_mutex); \ | 1740 | mutex_unlock(su_mutex); \ |
@@ -1579,16 +1781,12 @@ end: \ | |||
1579 | \ | 1781 | \ |
1580 | UVC_ATTR(uvcg_mjpeg_, cname, aname) | 1782 | UVC_ATTR(uvcg_mjpeg_, cname, aname) |
1581 | 1783 | ||
1582 | #define identity_conv(x) (x) | 1784 | UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8); |
1583 | 1785 | UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8); | |
1584 | UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, | 1786 | UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8); |
1585 | identity_conv); | 1787 | UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8); |
1586 | UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv); | 1788 | UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8); |
1587 | UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv); | 1789 | UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8); |
1588 | UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv); | ||
1589 | UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv); | ||
1590 | |||
1591 | #undef identity_conv | ||
1592 | 1790 | ||
1593 | #undef UVCG_MJPEG_ATTR | 1791 | #undef UVCG_MJPEG_ATTR |
1594 | #undef UVCG_MJPEG_ATTR_RO | 1792 | #undef UVCG_MJPEG_ATTR_RO |
@@ -1611,6 +1809,7 @@ uvcg_mjpeg_bma_controls_store(struct config_item *item, | |||
1611 | UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls); | 1809 | UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls); |
1612 | 1810 | ||
1613 | static struct configfs_attribute *uvcg_mjpeg_attrs[] = { | 1811 | static struct configfs_attribute *uvcg_mjpeg_attrs[] = { |
1812 | &uvcg_mjpeg_attr_b_format_index, | ||
1614 | &uvcg_mjpeg_attr_b_default_frame_index, | 1813 | &uvcg_mjpeg_attr_b_default_frame_index, |
1615 | &uvcg_mjpeg_attr_bm_flags, | 1814 | &uvcg_mjpeg_attr_bm_flags, |
1616 | &uvcg_mjpeg_attr_b_aspect_ratio_x, | 1815 | &uvcg_mjpeg_attr_b_aspect_ratio_x, |
@@ -1621,6 +1820,7 @@ static struct configfs_attribute *uvcg_mjpeg_attrs[] = { | |||
1621 | }; | 1820 | }; |
1622 | 1821 | ||
1623 | static const struct config_item_type uvcg_mjpeg_type = { | 1822 | static const struct config_item_type uvcg_mjpeg_type = { |
1823 | .ct_item_ops = &uvcg_config_item_ops, | ||
1624 | .ct_group_ops = &uvcg_mjpeg_group_ops, | 1824 | .ct_group_ops = &uvcg_mjpeg_group_ops, |
1625 | .ct_attrs = uvcg_mjpeg_attrs, | 1825 | .ct_attrs = uvcg_mjpeg_attrs, |
1626 | .ct_owner = THIS_MODULE, | 1826 | .ct_owner = THIS_MODULE, |
@@ -1651,56 +1851,42 @@ static struct config_group *uvcg_mjpeg_make(struct config_group *group, | |||
1651 | return &h->fmt.group; | 1851 | return &h->fmt.group; |
1652 | } | 1852 | } |
1653 | 1853 | ||
1654 | static void uvcg_mjpeg_drop(struct config_group *group, | ||
1655 | struct config_item *item) | ||
1656 | { | ||
1657 | struct uvcg_mjpeg *h = to_uvcg_mjpeg(item); | ||
1658 | |||
1659 | kfree(h); | ||
1660 | } | ||
1661 | |||
1662 | static struct configfs_group_operations uvcg_mjpeg_grp_ops = { | 1854 | static struct configfs_group_operations uvcg_mjpeg_grp_ops = { |
1663 | .make_group = uvcg_mjpeg_make, | 1855 | .make_group = uvcg_mjpeg_make, |
1664 | .drop_item = uvcg_mjpeg_drop, | ||
1665 | }; | 1856 | }; |
1666 | 1857 | ||
1667 | static const struct config_item_type uvcg_mjpeg_grp_type = { | 1858 | static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = { |
1668 | .ct_group_ops = &uvcg_mjpeg_grp_ops, | 1859 | .type = { |
1669 | .ct_owner = THIS_MODULE, | 1860 | .ct_item_ops = &uvcg_config_item_ops, |
1861 | .ct_group_ops = &uvcg_mjpeg_grp_ops, | ||
1862 | .ct_owner = THIS_MODULE, | ||
1863 | }, | ||
1864 | .name = "mjpeg", | ||
1670 | }; | 1865 | }; |
1671 | 1866 | ||
1672 | /* streaming/color_matching/default */ | 1867 | /* ----------------------------------------------------------------------------- |
1673 | static struct uvcg_default_color_matching { | 1868 | * streaming/color_matching/default |
1674 | struct config_group group; | 1869 | */ |
1675 | } uvcg_default_color_matching; | ||
1676 | |||
1677 | static inline struct uvcg_default_color_matching | ||
1678 | *to_uvcg_default_color_matching(struct config_item *item) | ||
1679 | { | ||
1680 | return container_of(to_config_group(item), | ||
1681 | struct uvcg_default_color_matching, group); | ||
1682 | } | ||
1683 | 1870 | ||
1684 | #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \ | 1871 | #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, bits) \ |
1685 | static ssize_t uvcg_default_color_matching_##cname##_show( \ | 1872 | static ssize_t uvcg_default_color_matching_##cname##_show( \ |
1686 | struct config_item *item, char *page) \ | 1873 | struct config_item *item, char *page) \ |
1687 | { \ | 1874 | { \ |
1688 | struct uvcg_default_color_matching *dc = \ | 1875 | struct config_group *group = to_config_group(item); \ |
1689 | to_uvcg_default_color_matching(item); \ | ||
1690 | struct f_uvc_opts *opts; \ | 1876 | struct f_uvc_opts *opts; \ |
1691 | struct config_item *opts_item; \ | 1877 | struct config_item *opts_item; \ |
1692 | struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \ | 1878 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ |
1693 | struct uvc_color_matching_descriptor *cd; \ | 1879 | struct uvc_color_matching_descriptor *cd; \ |
1694 | int result; \ | 1880 | int result; \ |
1695 | \ | 1881 | \ |
1696 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ | 1882 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ |
1697 | \ | 1883 | \ |
1698 | opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \ | 1884 | opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \ |
1699 | opts = to_f_uvc_opts(opts_item); \ | 1885 | opts = to_f_uvc_opts(opts_item); \ |
1700 | cd = &opts->uvc_color_matching; \ | 1886 | cd = &opts->uvc_color_matching; \ |
1701 | \ | 1887 | \ |
1702 | mutex_lock(&opts->lock); \ | 1888 | mutex_lock(&opts->lock); \ |
1703 | result = sprintf(page, "%d\n", conv(cd->aname)); \ | 1889 | result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \ |
1704 | mutex_unlock(&opts->lock); \ | 1890 | mutex_unlock(&opts->lock); \ |
1705 | \ | 1891 | \ |
1706 | mutex_unlock(su_mutex); \ | 1892 | mutex_unlock(su_mutex); \ |
@@ -1709,16 +1895,10 @@ static ssize_t uvcg_default_color_matching_##cname##_show( \ | |||
1709 | \ | 1895 | \ |
1710 | UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname) | 1896 | UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname) |
1711 | 1897 | ||
1712 | #define identity_conv(x) (x) | 1898 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8); |
1713 | |||
1714 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, | ||
1715 | identity_conv); | ||
1716 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics, | 1899 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics, |
1717 | bTransferCharacteristics, identity_conv); | 1900 | bTransferCharacteristics, 8); |
1718 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, | 1901 | UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8); |
1719 | identity_conv); | ||
1720 | |||
1721 | #undef identity_conv | ||
1722 | 1902 | ||
1723 | #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR | 1903 | #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR |
1724 | 1904 | ||
@@ -1729,41 +1909,54 @@ static struct configfs_attribute *uvcg_default_color_matching_attrs[] = { | |||
1729 | NULL, | 1909 | NULL, |
1730 | }; | 1910 | }; |
1731 | 1911 | ||
1732 | static const struct config_item_type uvcg_default_color_matching_type = { | 1912 | static const struct uvcg_config_group_type uvcg_default_color_matching_type = { |
1733 | .ct_attrs = uvcg_default_color_matching_attrs, | 1913 | .type = { |
1734 | .ct_owner = THIS_MODULE, | 1914 | .ct_item_ops = &uvcg_config_item_ops, |
1915 | .ct_attrs = uvcg_default_color_matching_attrs, | ||
1916 | .ct_owner = THIS_MODULE, | ||
1917 | }, | ||
1918 | .name = "default", | ||
1735 | }; | 1919 | }; |
1736 | 1920 | ||
1737 | /* struct uvcg_color_matching {}; */ | 1921 | /* ----------------------------------------------------------------------------- |
1738 | 1922 | * streaming/color_matching | |
1739 | /* streaming/color_matching */ | 1923 | */ |
1740 | static struct uvcg_color_matching_grp { | ||
1741 | struct config_group group; | ||
1742 | } uvcg_color_matching_grp; | ||
1743 | 1924 | ||
1744 | static const struct config_item_type uvcg_color_matching_grp_type = { | 1925 | static const struct uvcg_config_group_type uvcg_color_matching_grp_type = { |
1745 | .ct_owner = THIS_MODULE, | 1926 | .type = { |
1927 | .ct_item_ops = &uvcg_config_item_ops, | ||
1928 | .ct_owner = THIS_MODULE, | ||
1929 | }, | ||
1930 | .name = "color_matching", | ||
1931 | .children = (const struct uvcg_config_group_type*[]) { | ||
1932 | &uvcg_default_color_matching_type, | ||
1933 | NULL, | ||
1934 | }, | ||
1746 | }; | 1935 | }; |
1747 | 1936 | ||
1748 | /* streaming/class/{fs|hs|ss} */ | 1937 | /* ----------------------------------------------------------------------------- |
1749 | static struct uvcg_streaming_class { | 1938 | * streaming/class/{fs|hs|ss} |
1750 | struct config_group group; | 1939 | */ |
1751 | } uvcg_streaming_class_fs, uvcg_streaming_class_hs, uvcg_streaming_class_ss; | ||
1752 | 1940 | ||
1941 | struct uvcg_streaming_class_group { | ||
1942 | struct config_group group; | ||
1943 | const char *name; | ||
1944 | }; | ||
1753 | 1945 | ||
1754 | static inline struct uvc_descriptor_header | 1946 | static inline struct uvc_descriptor_header |
1755 | ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o) | 1947 | ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o) |
1756 | { | 1948 | { |
1757 | struct uvcg_streaming_class *cl = container_of(to_config_group(i), | 1949 | struct uvcg_streaming_class_group *group = |
1758 | struct uvcg_streaming_class, group); | 1950 | container_of(i, struct uvcg_streaming_class_group, |
1951 | group.cg_item); | ||
1759 | 1952 | ||
1760 | if (cl == &uvcg_streaming_class_fs) | 1953 | if (!strcmp(group->name, "fs")) |
1761 | return &o->uvc_fs_streaming_cls; | 1954 | return &o->uvc_fs_streaming_cls; |
1762 | 1955 | ||
1763 | if (cl == &uvcg_streaming_class_hs) | 1956 | if (!strcmp(group->name, "hs")) |
1764 | return &o->uvc_hs_streaming_cls; | 1957 | return &o->uvc_hs_streaming_cls; |
1765 | 1958 | ||
1766 | if (cl == &uvcg_streaming_class_ss) | 1959 | if (!strcmp(group->name, "ss")) |
1767 | return &o->uvc_ss_streaming_cls; | 1960 | return &o->uvc_ss_streaming_cls; |
1768 | 1961 | ||
1769 | return NULL; | 1962 | return NULL; |
@@ -1922,24 +2115,22 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, | |||
1922 | struct uvcg_format *fmt = priv1; | 2115 | struct uvcg_format *fmt = priv1; |
1923 | 2116 | ||
1924 | if (fmt->type == UVCG_UNCOMPRESSED) { | 2117 | if (fmt->type == UVCG_UNCOMPRESSED) { |
1925 | struct uvc_format_uncompressed *unc = *dest; | ||
1926 | struct uvcg_uncompressed *u = | 2118 | struct uvcg_uncompressed *u = |
1927 | container_of(fmt, struct uvcg_uncompressed, | 2119 | container_of(fmt, struct uvcg_uncompressed, |
1928 | fmt); | 2120 | fmt); |
1929 | 2121 | ||
2122 | u->desc.bFormatIndex = n + 1; | ||
2123 | u->desc.bNumFrameDescriptors = fmt->num_frames; | ||
1930 | memcpy(*dest, &u->desc, sizeof(u->desc)); | 2124 | memcpy(*dest, &u->desc, sizeof(u->desc)); |
1931 | *dest += sizeof(u->desc); | 2125 | *dest += sizeof(u->desc); |
1932 | unc->bNumFrameDescriptors = fmt->num_frames; | ||
1933 | unc->bFormatIndex = n + 1; | ||
1934 | } else if (fmt->type == UVCG_MJPEG) { | 2126 | } else if (fmt->type == UVCG_MJPEG) { |
1935 | struct uvc_format_mjpeg *mjp = *dest; | ||
1936 | struct uvcg_mjpeg *m = | 2127 | struct uvcg_mjpeg *m = |
1937 | container_of(fmt, struct uvcg_mjpeg, fmt); | 2128 | container_of(fmt, struct uvcg_mjpeg, fmt); |
1938 | 2129 | ||
2130 | m->desc.bFormatIndex = n + 1; | ||
2131 | m->desc.bNumFrameDescriptors = fmt->num_frames; | ||
1939 | memcpy(*dest, &m->desc, sizeof(m->desc)); | 2132 | memcpy(*dest, &m->desc, sizeof(m->desc)); |
1940 | *dest += sizeof(m->desc); | 2133 | *dest += sizeof(m->desc); |
1941 | mjp->bNumFrameDescriptors = fmt->num_frames; | ||
1942 | mjp->bFormatIndex = n + 1; | ||
1943 | } else { | 2134 | } else { |
1944 | return -EINVAL; | 2135 | return -EINVAL; |
1945 | } | 2136 | } |
@@ -2038,6 +2229,7 @@ static int uvcg_streaming_class_allow_link(struct config_item *src, | |||
2038 | unlock: | 2229 | unlock: |
2039 | mutex_unlock(&opts->lock); | 2230 | mutex_unlock(&opts->lock); |
2040 | out: | 2231 | out: |
2232 | config_item_put(header); | ||
2041 | mutex_unlock(su_mutex); | 2233 | mutex_unlock(su_mutex); |
2042 | return ret; | 2234 | return ret; |
2043 | } | 2235 | } |
@@ -2078,10 +2270,12 @@ static void uvcg_streaming_class_drop_link(struct config_item *src, | |||
2078 | unlock: | 2270 | unlock: |
2079 | mutex_unlock(&opts->lock); | 2271 | mutex_unlock(&opts->lock); |
2080 | out: | 2272 | out: |
2273 | config_item_put(header); | ||
2081 | mutex_unlock(su_mutex); | 2274 | mutex_unlock(su_mutex); |
2082 | } | 2275 | } |
2083 | 2276 | ||
2084 | static struct configfs_item_operations uvcg_streaming_class_item_ops = { | 2277 | static struct configfs_item_operations uvcg_streaming_class_item_ops = { |
2278 | .release = uvcg_config_item_release, | ||
2085 | .allow_link = uvcg_streaming_class_allow_link, | 2279 | .allow_link = uvcg_streaming_class_allow_link, |
2086 | .drop_link = uvcg_streaming_class_drop_link, | 2280 | .drop_link = uvcg_streaming_class_drop_link, |
2087 | }; | 2281 | }; |
@@ -2091,36 +2285,109 @@ static const struct config_item_type uvcg_streaming_class_type = { | |||
2091 | .ct_owner = THIS_MODULE, | 2285 | .ct_owner = THIS_MODULE, |
2092 | }; | 2286 | }; |
2093 | 2287 | ||
2094 | /* streaming/class */ | 2288 | /* ----------------------------------------------------------------------------- |
2095 | static struct uvcg_streaming_class_grp { | 2289 | * streaming/class |
2096 | struct config_group group; | 2290 | */ |
2097 | } uvcg_streaming_class_grp; | 2291 | |
2292 | static int uvcg_streaming_class_create_children(struct config_group *parent) | ||
2293 | { | ||
2294 | static const char * const names[] = { "fs", "hs", "ss" }; | ||
2295 | unsigned int i; | ||
2296 | |||
2297 | for (i = 0; i < ARRAY_SIZE(names); ++i) { | ||
2298 | struct uvcg_streaming_class_group *group; | ||
2299 | |||
2300 | group = kzalloc(sizeof(*group), GFP_KERNEL); | ||
2301 | if (!group) | ||
2302 | return -ENOMEM; | ||
2098 | 2303 | ||
2099 | static const struct config_item_type uvcg_streaming_class_grp_type = { | 2304 | group->name = names[i]; |
2100 | .ct_owner = THIS_MODULE, | 2305 | |
2306 | config_group_init_type_name(&group->group, group->name, | ||
2307 | &uvcg_streaming_class_type); | ||
2308 | configfs_add_default_group(&group->group, parent); | ||
2309 | } | ||
2310 | |||
2311 | return 0; | ||
2312 | } | ||
2313 | |||
2314 | static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = { | ||
2315 | .type = { | ||
2316 | .ct_item_ops = &uvcg_config_item_ops, | ||
2317 | .ct_owner = THIS_MODULE, | ||
2318 | }, | ||
2319 | .name = "class", | ||
2320 | .create_children = uvcg_streaming_class_create_children, | ||
2101 | }; | 2321 | }; |
2102 | 2322 | ||
2103 | /* streaming */ | 2323 | /* ----------------------------------------------------------------------------- |
2104 | static struct uvcg_streaming_grp { | 2324 | * streaming |
2105 | struct config_group group; | 2325 | */ |
2106 | } uvcg_streaming_grp; | ||
2107 | 2326 | ||
2108 | static const struct config_item_type uvcg_streaming_grp_type = { | 2327 | static ssize_t uvcg_default_streaming_b_interface_number_show( |
2109 | .ct_owner = THIS_MODULE, | 2328 | struct config_item *item, char *page) |
2329 | { | ||
2330 | struct config_group *group = to_config_group(item); | ||
2331 | struct mutex *su_mutex = &group->cg_subsys->su_mutex; | ||
2332 | struct config_item *opts_item; | ||
2333 | struct f_uvc_opts *opts; | ||
2334 | int result = 0; | ||
2335 | |||
2336 | mutex_lock(su_mutex); /* for navigating configfs hierarchy */ | ||
2337 | |||
2338 | opts_item = item->ci_parent; | ||
2339 | opts = to_f_uvc_opts(opts_item); | ||
2340 | |||
2341 | mutex_lock(&opts->lock); | ||
2342 | result += sprintf(page, "%u\n", opts->streaming_interface); | ||
2343 | mutex_unlock(&opts->lock); | ||
2344 | |||
2345 | mutex_unlock(su_mutex); | ||
2346 | |||
2347 | return result; | ||
2348 | } | ||
2349 | |||
2350 | UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber); | ||
2351 | |||
2352 | static struct configfs_attribute *uvcg_default_streaming_attrs[] = { | ||
2353 | &uvcg_default_streaming_attr_b_interface_number, | ||
2354 | NULL, | ||
2355 | }; | ||
2356 | |||
2357 | static const struct uvcg_config_group_type uvcg_streaming_grp_type = { | ||
2358 | .type = { | ||
2359 | .ct_item_ops = &uvcg_config_item_ops, | ||
2360 | .ct_attrs = uvcg_default_streaming_attrs, | ||
2361 | .ct_owner = THIS_MODULE, | ||
2362 | }, | ||
2363 | .name = "streaming", | ||
2364 | .children = (const struct uvcg_config_group_type*[]) { | ||
2365 | &uvcg_streaming_header_grp_type, | ||
2366 | &uvcg_uncompressed_grp_type, | ||
2367 | &uvcg_mjpeg_grp_type, | ||
2368 | &uvcg_color_matching_grp_type, | ||
2369 | &uvcg_streaming_class_grp_type, | ||
2370 | NULL, | ||
2371 | }, | ||
2110 | }; | 2372 | }; |
2111 | 2373 | ||
2112 | static void uvc_attr_release(struct config_item *item) | 2374 | /* ----------------------------------------------------------------------------- |
2375 | * UVC function | ||
2376 | */ | ||
2377 | |||
2378 | static void uvc_func_item_release(struct config_item *item) | ||
2113 | { | 2379 | { |
2114 | struct f_uvc_opts *opts = to_f_uvc_opts(item); | 2380 | struct f_uvc_opts *opts = to_f_uvc_opts(item); |
2115 | 2381 | ||
2382 | uvcg_config_remove_children(to_config_group(item)); | ||
2116 | usb_put_function_instance(&opts->func_inst); | 2383 | usb_put_function_instance(&opts->func_inst); |
2117 | } | 2384 | } |
2118 | 2385 | ||
2119 | static struct configfs_item_operations uvc_item_ops = { | 2386 | static struct configfs_item_operations uvc_func_item_ops = { |
2120 | .release = uvc_attr_release, | 2387 | .release = uvc_func_item_release, |
2121 | }; | 2388 | }; |
2122 | 2389 | ||
2123 | #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \ | 2390 | #define UVCG_OPTS_ATTR(cname, aname, limit) \ |
2124 | static ssize_t f_uvc_opts_##cname##_show( \ | 2391 | static ssize_t f_uvc_opts_##cname##_show( \ |
2125 | struct config_item *item, char *page) \ | 2392 | struct config_item *item, char *page) \ |
2126 | { \ | 2393 | { \ |
@@ -2128,7 +2395,7 @@ static ssize_t f_uvc_opts_##cname##_show( \ | |||
2128 | int result; \ | 2395 | int result; \ |
2129 | \ | 2396 | \ |
2130 | mutex_lock(&opts->lock); \ | 2397 | mutex_lock(&opts->lock); \ |
2131 | result = sprintf(page, "%d\n", conv(opts->cname)); \ | 2398 | result = sprintf(page, "%u\n", opts->cname); \ |
2132 | mutex_unlock(&opts->lock); \ | 2399 | mutex_unlock(&opts->lock); \ |
2133 | \ | 2400 | \ |
2134 | return result; \ | 2401 | return result; \ |
@@ -2139,8 +2406,8 @@ f_uvc_opts_##cname##_store(struct config_item *item, \ | |||
2139 | const char *page, size_t len) \ | 2406 | const char *page, size_t len) \ |
2140 | { \ | 2407 | { \ |
2141 | struct f_uvc_opts *opts = to_f_uvc_opts(item); \ | 2408 | struct f_uvc_opts *opts = to_f_uvc_opts(item); \ |
2409 | unsigned int num; \ | ||
2142 | int ret; \ | 2410 | int ret; \ |
2143 | uxx num; \ | ||
2144 | \ | 2411 | \ |
2145 | mutex_lock(&opts->lock); \ | 2412 | mutex_lock(&opts->lock); \ |
2146 | if (opts->refcnt) { \ | 2413 | if (opts->refcnt) { \ |
@@ -2148,7 +2415,7 @@ f_uvc_opts_##cname##_store(struct config_item *item, \ | |||
2148 | goto end; \ | 2415 | goto end; \ |
2149 | } \ | 2416 | } \ |
2150 | \ | 2417 | \ |
2151 | ret = str2u(page, 0, &num); \ | 2418 | ret = kstrtouint(page, 0, &num); \ |
2152 | if (ret) \ | 2419 | if (ret) \ |
2153 | goto end; \ | 2420 | goto end; \ |
2154 | \ | 2421 | \ |
@@ -2156,7 +2423,7 @@ f_uvc_opts_##cname##_store(struct config_item *item, \ | |||
2156 | ret = -EINVAL; \ | 2423 | ret = -EINVAL; \ |
2157 | goto end; \ | 2424 | goto end; \ |
2158 | } \ | 2425 | } \ |
2159 | opts->cname = vnoc(num); \ | 2426 | opts->cname = num; \ |
2160 | ret = len; \ | 2427 | ret = len; \ |
2161 | end: \ | 2428 | end: \ |
2162 | mutex_unlock(&opts->lock); \ | 2429 | mutex_unlock(&opts->lock); \ |
@@ -2165,16 +2432,9 @@ end: \ | |||
2165 | \ | 2432 | \ |
2166 | UVC_ATTR(f_uvc_opts_, cname, cname) | 2433 | UVC_ATTR(f_uvc_opts_, cname, cname) |
2167 | 2434 | ||
2168 | #define identity_conv(x) (x) | 2435 | UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16); |
2169 | 2436 | UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072); | |
2170 | UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv, | 2437 | UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15); |
2171 | kstrtou8, u8, identity_conv, 16); | ||
2172 | UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu, | ||
2173 | kstrtou16, u16, le16_to_cpu, 3072); | ||
2174 | UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv, | ||
2175 | kstrtou8, u8, identity_conv, 15); | ||
2176 | |||
2177 | #undef identity_conv | ||
2178 | 2438 | ||
2179 | #undef UVCG_OPTS_ATTR | 2439 | #undef UVCG_OPTS_ATTR |
2180 | 2440 | ||
@@ -2185,123 +2445,31 @@ static struct configfs_attribute *uvc_attrs[] = { | |||
2185 | NULL, | 2445 | NULL, |
2186 | }; | 2446 | }; |
2187 | 2447 | ||
2188 | static const struct config_item_type uvc_func_type = { | 2448 | static const struct uvcg_config_group_type uvc_func_type = { |
2189 | .ct_item_ops = &uvc_item_ops, | 2449 | .type = { |
2190 | .ct_attrs = uvc_attrs, | 2450 | .ct_item_ops = &uvc_func_item_ops, |
2191 | .ct_owner = THIS_MODULE, | 2451 | .ct_attrs = uvc_attrs, |
2452 | .ct_owner = THIS_MODULE, | ||
2453 | }, | ||
2454 | .name = "", | ||
2455 | .children = (const struct uvcg_config_group_type*[]) { | ||
2456 | &uvcg_control_grp_type, | ||
2457 | &uvcg_streaming_grp_type, | ||
2458 | NULL, | ||
2459 | }, | ||
2192 | }; | 2460 | }; |
2193 | 2461 | ||
2194 | int uvcg_attach_configfs(struct f_uvc_opts *opts) | 2462 | int uvcg_attach_configfs(struct f_uvc_opts *opts) |
2195 | { | 2463 | { |
2196 | config_group_init_type_name(&uvcg_control_header_grp.group, | 2464 | int ret; |
2197 | "header", | ||
2198 | &uvcg_control_header_grp_type); | ||
2199 | |||
2200 | config_group_init_type_name(&uvcg_default_processing.group, | ||
2201 | "default", &uvcg_default_processing_type); | ||
2202 | config_group_init_type_name(&uvcg_processing_grp.group, | ||
2203 | "processing", &uvcg_processing_grp_type); | ||
2204 | configfs_add_default_group(&uvcg_default_processing.group, | ||
2205 | &uvcg_processing_grp.group); | ||
2206 | |||
2207 | config_group_init_type_name(&uvcg_default_camera.group, | ||
2208 | "default", &uvcg_default_camera_type); | ||
2209 | config_group_init_type_name(&uvcg_camera_grp.group, | ||
2210 | "camera", &uvcg_camera_grp_type); | ||
2211 | configfs_add_default_group(&uvcg_default_camera.group, | ||
2212 | &uvcg_camera_grp.group); | ||
2213 | |||
2214 | config_group_init_type_name(&uvcg_default_output.group, | ||
2215 | "default", &uvcg_default_output_type); | ||
2216 | config_group_init_type_name(&uvcg_output_grp.group, | ||
2217 | "output", &uvcg_output_grp_type); | ||
2218 | configfs_add_default_group(&uvcg_default_output.group, | ||
2219 | &uvcg_output_grp.group); | ||
2220 | |||
2221 | config_group_init_type_name(&uvcg_terminal_grp.group, | ||
2222 | "terminal", &uvcg_terminal_grp_type); | ||
2223 | configfs_add_default_group(&uvcg_camera_grp.group, | ||
2224 | &uvcg_terminal_grp.group); | ||
2225 | configfs_add_default_group(&uvcg_output_grp.group, | ||
2226 | &uvcg_terminal_grp.group); | ||
2227 | |||
2228 | config_group_init_type_name(&uvcg_control_class_fs.group, | ||
2229 | "fs", &uvcg_control_class_type); | ||
2230 | config_group_init_type_name(&uvcg_control_class_ss.group, | ||
2231 | "ss", &uvcg_control_class_type); | ||
2232 | config_group_init_type_name(&uvcg_control_class_grp.group, | ||
2233 | "class", | ||
2234 | &uvcg_control_class_grp_type); | ||
2235 | configfs_add_default_group(&uvcg_control_class_fs.group, | ||
2236 | &uvcg_control_class_grp.group); | ||
2237 | configfs_add_default_group(&uvcg_control_class_ss.group, | ||
2238 | &uvcg_control_class_grp.group); | ||
2239 | |||
2240 | config_group_init_type_name(&uvcg_control_grp.group, | ||
2241 | "control", | ||
2242 | &uvcg_control_grp_type); | ||
2243 | configfs_add_default_group(&uvcg_control_header_grp.group, | ||
2244 | &uvcg_control_grp.group); | ||
2245 | configfs_add_default_group(&uvcg_processing_grp.group, | ||
2246 | &uvcg_control_grp.group); | ||
2247 | configfs_add_default_group(&uvcg_terminal_grp.group, | ||
2248 | &uvcg_control_grp.group); | ||
2249 | configfs_add_default_group(&uvcg_control_class_grp.group, | ||
2250 | &uvcg_control_grp.group); | ||
2251 | |||
2252 | config_group_init_type_name(&uvcg_streaming_header_grp.group, | ||
2253 | "header", | ||
2254 | &uvcg_streaming_header_grp_type); | ||
2255 | config_group_init_type_name(&uvcg_uncompressed_grp.group, | ||
2256 | "uncompressed", | ||
2257 | &uvcg_uncompressed_grp_type); | ||
2258 | config_group_init_type_name(&uvcg_mjpeg_grp.group, | ||
2259 | "mjpeg", | ||
2260 | &uvcg_mjpeg_grp_type); | ||
2261 | config_group_init_type_name(&uvcg_default_color_matching.group, | ||
2262 | "default", | ||
2263 | &uvcg_default_color_matching_type); | ||
2264 | config_group_init_type_name(&uvcg_color_matching_grp.group, | ||
2265 | "color_matching", | ||
2266 | &uvcg_color_matching_grp_type); | ||
2267 | configfs_add_default_group(&uvcg_default_color_matching.group, | ||
2268 | &uvcg_color_matching_grp.group); | ||
2269 | |||
2270 | config_group_init_type_name(&uvcg_streaming_class_fs.group, | ||
2271 | "fs", &uvcg_streaming_class_type); | ||
2272 | config_group_init_type_name(&uvcg_streaming_class_hs.group, | ||
2273 | "hs", &uvcg_streaming_class_type); | ||
2274 | config_group_init_type_name(&uvcg_streaming_class_ss.group, | ||
2275 | "ss", &uvcg_streaming_class_type); | ||
2276 | config_group_init_type_name(&uvcg_streaming_class_grp.group, | ||
2277 | "class", &uvcg_streaming_class_grp_type); | ||
2278 | configfs_add_default_group(&uvcg_streaming_class_fs.group, | ||
2279 | &uvcg_streaming_class_grp.group); | ||
2280 | configfs_add_default_group(&uvcg_streaming_class_hs.group, | ||
2281 | &uvcg_streaming_class_grp.group); | ||
2282 | configfs_add_default_group(&uvcg_streaming_class_ss.group, | ||
2283 | &uvcg_streaming_class_grp.group); | ||
2284 | |||
2285 | config_group_init_type_name(&uvcg_streaming_grp.group, | ||
2286 | "streaming", &uvcg_streaming_grp_type); | ||
2287 | configfs_add_default_group(&uvcg_streaming_header_grp.group, | ||
2288 | &uvcg_streaming_grp.group); | ||
2289 | configfs_add_default_group(&uvcg_uncompressed_grp.group, | ||
2290 | &uvcg_streaming_grp.group); | ||
2291 | configfs_add_default_group(&uvcg_mjpeg_grp.group, | ||
2292 | &uvcg_streaming_grp.group); | ||
2293 | configfs_add_default_group(&uvcg_color_matching_grp.group, | ||
2294 | &uvcg_streaming_grp.group); | ||
2295 | configfs_add_default_group(&uvcg_streaming_class_grp.group, | ||
2296 | &uvcg_streaming_grp.group); | ||
2297 | |||
2298 | config_group_init_type_name(&opts->func_inst.group, | ||
2299 | "", | ||
2300 | &uvc_func_type); | ||
2301 | configfs_add_default_group(&uvcg_control_grp.group, | ||
2302 | &opts->func_inst.group); | ||
2303 | configfs_add_default_group(&uvcg_streaming_grp.group, | ||
2304 | &opts->func_inst.group); | ||
2305 | 2465 | ||
2306 | return 0; | 2466 | config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name, |
2467 | &uvc_func_type.type); | ||
2468 | |||
2469 | ret = uvcg_config_create_children(&opts->func_inst.group, | ||
2470 | &uvc_func_type); | ||
2471 | if (ret < 0) | ||
2472 | config_group_put(&opts->func_inst.group); | ||
2473 | |||
2474 | return ret; | ||
2307 | } | 2475 | } |
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 7f1ca3b57823..a1183eccee22 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c | |||
@@ -115,8 +115,8 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt) | |||
115 | } | 115 | } |
116 | 116 | ||
117 | if (i == ARRAY_SIZE(uvc_formats)) { | 117 | if (i == ARRAY_SIZE(uvc_formats)) { |
118 | printk(KERN_INFO "Unsupported format 0x%08x.\n", | 118 | uvcg_info(&uvc->func, "Unsupported format 0x%08x.\n", |
119 | fmt->fmt.pix.pixelformat); | 119 | fmt->fmt.pix.pixelformat); |
120 | return -EINVAL; | 120 | return -EINVAL; |
121 | } | 121 | } |
122 | 122 | ||
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index d3567b90343a..5c042f380708 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c | |||
@@ -125,6 +125,23 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, | |||
125 | * Request handling | 125 | * Request handling |
126 | */ | 126 | */ |
127 | 127 | ||
128 | static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req) | ||
129 | { | ||
130 | int ret; | ||
131 | |||
132 | ret = usb_ep_queue(video->ep, req, GFP_ATOMIC); | ||
133 | if (ret < 0) { | ||
134 | uvcg_err(&video->uvc->func, "Failed to queue request (%d).\n", | ||
135 | ret); | ||
136 | |||
137 | /* Isochronous endpoints can't be halted. */ | ||
138 | if (usb_endpoint_xfer_bulk(video->ep->desc)) | ||
139 | usb_ep_set_halt(video->ep); | ||
140 | } | ||
141 | |||
142 | return ret; | ||
143 | } | ||
144 | |||
128 | /* | 145 | /* |
129 | * I somehow feel that synchronisation won't be easy to achieve here. We have | 146 | * I somehow feel that synchronisation won't be easy to achieve here. We have |
130 | * three events that control USB requests submission: | 147 | * three events that control USB requests submission: |
@@ -169,13 +186,14 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | |||
169 | break; | 186 | break; |
170 | 187 | ||
171 | case -ESHUTDOWN: /* disconnect from host. */ | 188 | case -ESHUTDOWN: /* disconnect from host. */ |
172 | printk(KERN_DEBUG "VS request cancelled.\n"); | 189 | uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); |
173 | uvcg_queue_cancel(queue, 1); | 190 | uvcg_queue_cancel(queue, 1); |
174 | goto requeue; | 191 | goto requeue; |
175 | 192 | ||
176 | default: | 193 | default: |
177 | printk(KERN_INFO "VS request completed with status %d.\n", | 194 | uvcg_info(&video->uvc->func, |
178 | req->status); | 195 | "VS request completed with status %d.\n", |
196 | req->status); | ||
179 | uvcg_queue_cancel(queue, 0); | 197 | uvcg_queue_cancel(queue, 0); |
180 | goto requeue; | 198 | goto requeue; |
181 | } | 199 | } |
@@ -189,14 +207,13 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | |||
189 | 207 | ||
190 | video->encode(req, video, buf); | 208 | video->encode(req, video, buf); |
191 | 209 | ||
192 | if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) { | 210 | ret = uvcg_video_ep_queue(video, req); |
193 | printk(KERN_INFO "Failed to queue request (%d).\n", ret); | 211 | spin_unlock_irqrestore(&video->queue.irqlock, flags); |
194 | usb_ep_set_halt(ep); | 212 | |
195 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 213 | if (ret < 0) { |
196 | uvcg_queue_cancel(queue, 0); | 214 | uvcg_queue_cancel(queue, 0); |
197 | goto requeue; | 215 | goto requeue; |
198 | } | 216 | } |
199 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | ||
200 | 217 | ||
201 | return; | 218 | return; |
202 | 219 | ||
@@ -316,15 +333,13 @@ int uvcg_video_pump(struct uvc_video *video) | |||
316 | video->encode(req, video, buf); | 333 | video->encode(req, video, buf); |
317 | 334 | ||
318 | /* Queue the USB request */ | 335 | /* Queue the USB request */ |
319 | ret = usb_ep_queue(video->ep, req, GFP_ATOMIC); | 336 | ret = uvcg_video_ep_queue(video, req); |
337 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
338 | |||
320 | if (ret < 0) { | 339 | if (ret < 0) { |
321 | printk(KERN_INFO "Failed to queue request (%d)\n", ret); | ||
322 | usb_ep_set_halt(video->ep); | ||
323 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
324 | uvcg_queue_cancel(queue, 0); | 340 | uvcg_queue_cancel(queue, 0); |
325 | break; | 341 | break; |
326 | } | 342 | } |
327 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
328 | } | 343 | } |
329 | 344 | ||
330 | spin_lock_irqsave(&video->req_lock, flags); | 345 | spin_lock_irqsave(&video->req_lock, flags); |
@@ -342,8 +357,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable) | |||
342 | int ret; | 357 | int ret; |
343 | 358 | ||
344 | if (video->ep == NULL) { | 359 | if (video->ep == NULL) { |
345 | printk(KERN_INFO "Video enable failed, device is " | 360 | uvcg_info(&video->uvc->func, |
346 | "uninitialized.\n"); | 361 | "Video enable failed, device is uninitialized.\n"); |
347 | return -ENODEV; | 362 | return -ENODEV; |
348 | } | 363 | } |
349 | 364 | ||
@@ -375,11 +390,12 @@ int uvcg_video_enable(struct uvc_video *video, int enable) | |||
375 | /* | 390 | /* |
376 | * Initialize the UVC video stream. | 391 | * Initialize the UVC video stream. |
377 | */ | 392 | */ |
378 | int uvcg_video_init(struct uvc_video *video) | 393 | int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) |
379 | { | 394 | { |
380 | INIT_LIST_HEAD(&video->req_free); | 395 | INIT_LIST_HEAD(&video->req_free); |
381 | spin_lock_init(&video->req_lock); | 396 | spin_lock_init(&video->req_lock); |
382 | 397 | ||
398 | video->uvc = uvc; | ||
383 | video->fcc = V4L2_PIX_FMT_YUYV; | 399 | video->fcc = V4L2_PIX_FMT_YUYV; |
384 | video->bpp = 16; | 400 | video->bpp = 16; |
385 | video->width = 320; | 401 | video->width = 320; |
diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h index 7d77122b0ff9..278dc52c7604 100644 --- a/drivers/usb/gadget/function/uvc_video.h +++ b/drivers/usb/gadget/function/uvc_video.h | |||
@@ -18,6 +18,6 @@ int uvcg_video_pump(struct uvc_video *video); | |||
18 | 18 | ||
19 | int uvcg_video_enable(struct uvc_video *video, int enable); | 19 | int uvcg_video_enable(struct uvc_video *video, int enable); |
20 | 20 | ||
21 | int uvcg_video_init(struct uvc_video *video); | 21 | int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc); |
22 | 22 | ||
23 | #endif /* __UVC_VIDEO_H__ */ | 23 | #endif /* __UVC_VIDEO_H__ */ |
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 17147b8c771e..11247322d587 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
@@ -2004,7 +2004,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2004 | struct usba_udc *udc) | 2004 | struct usba_udc *udc) |
2005 | { | 2005 | { |
2006 | u32 val; | 2006 | u32 val; |
2007 | const char *name; | ||
2008 | struct device_node *np = pdev->dev.of_node; | 2007 | struct device_node *np = pdev->dev.of_node; |
2009 | const struct of_device_id *match; | 2008 | const struct of_device_id *match; |
2010 | struct device_node *pp; | 2009 | struct device_node *pp; |
@@ -2018,6 +2017,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2018 | udc->errata = match->data; | 2017 | udc->errata = match->data; |
2019 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); | 2018 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); |
2020 | if (IS_ERR(udc->pmc)) | 2019 | if (IS_ERR(udc->pmc)) |
2020 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc"); | ||
2021 | if (IS_ERR(udc->pmc)) | ||
2021 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); | 2022 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); |
2022 | if (udc->errata && IS_ERR(udc->pmc)) | 2023 | if (udc->errata && IS_ERR(udc->pmc)) |
2023 | return ERR_CAST(udc->pmc); | 2024 | return ERR_CAST(udc->pmc); |
@@ -2094,11 +2095,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2094 | ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); | 2095 | ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); |
2095 | ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); | 2096 | ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); |
2096 | 2097 | ||
2097 | ret = of_property_read_string(pp, "name", &name); | ||
2098 | if (ret) { | ||
2099 | dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret); | ||
2100 | goto err; | ||
2101 | } | ||
2102 | sprintf(ep->name, "ep%d", ep->index); | 2098 | sprintf(ep->name, "ep%d", ep->index); |
2103 | ep->ep.name = ep->name; | 2099 | ep->ep.name = ep->name; |
2104 | 2100 | ||
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index af88b48c1cea..87d6b12779f2 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c | |||
@@ -690,6 +690,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_connect); | |||
690 | * as a disconnect (when a VBUS session is active). Not all systems | 690 | * as a disconnect (when a VBUS session is active). Not all systems |
691 | * support software pullup controls. | 691 | * support software pullup controls. |
692 | * | 692 | * |
693 | * Following a successful disconnect, invoke the ->disconnect() callback | ||
694 | * for the current gadget driver so that UDC drivers don't need to. | ||
695 | * | ||
693 | * Returns zero on success, else negative errno. | 696 | * Returns zero on success, else negative errno. |
694 | */ | 697 | */ |
695 | int usb_gadget_disconnect(struct usb_gadget *gadget) | 698 | int usb_gadget_disconnect(struct usb_gadget *gadget) |
@@ -711,8 +714,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget) | |||
711 | } | 714 | } |
712 | 715 | ||
713 | ret = gadget->ops->pullup(gadget, 0); | 716 | ret = gadget->ops->pullup(gadget, 0); |
714 | if (!ret) | 717 | if (!ret) { |
715 | gadget->connected = 0; | 718 | gadget->connected = 0; |
719 | gadget->udc->driver->disconnect(gadget); | ||
720 | } | ||
716 | 721 | ||
717 | out: | 722 | out: |
718 | trace_usb_gadget_disconnect(gadget, ret); | 723 | trace_usb_gadget_disconnect(gadget, ret); |
@@ -1281,7 +1286,6 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) | |||
1281 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); | 1286 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); |
1282 | 1287 | ||
1283 | usb_gadget_disconnect(udc->gadget); | 1288 | usb_gadget_disconnect(udc->gadget); |
1284 | udc->driver->disconnect(udc->gadget); | ||
1285 | udc->driver->unbind(udc->gadget); | 1289 | udc->driver->unbind(udc->gadget); |
1286 | usb_gadget_udc_stop(udc); | 1290 | usb_gadget_udc_stop(udc); |
1287 | 1291 | ||
@@ -1471,7 +1475,6 @@ static ssize_t soft_connect_store(struct device *dev, | |||
1471 | usb_gadget_connect(udc->gadget); | 1475 | usb_gadget_connect(udc->gadget); |
1472 | } else if (sysfs_streq(buf, "disconnect")) { | 1476 | } else if (sysfs_streq(buf, "disconnect")) { |
1473 | usb_gadget_disconnect(udc->gadget); | 1477 | usb_gadget_disconnect(udc->gadget); |
1474 | udc->driver->disconnect(udc->gadget); | ||
1475 | usb_gadget_udc_stop(udc); | 1478 | usb_gadget_udc_stop(udc); |
1476 | } else { | 1479 | } else { |
1477 | dev_err(dev, "unsupported command '%s'\n", buf); | 1480 | dev_err(dev, "unsupported command '%s'\n", buf); |
diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index 587c5037ff07..bc6abaea907d 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c | |||
@@ -741,7 +741,7 @@ static void fotg210_get_status(struct fotg210_udc *fotg210, | |||
741 | fotg210->ep0_req->length = 2; | 741 | fotg210->ep0_req->length = 2; |
742 | 742 | ||
743 | spin_unlock(&fotg210->lock); | 743 | spin_unlock(&fotg210->lock); |
744 | fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_KERNEL); | 744 | fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_ATOMIC); |
745 | spin_lock(&fotg210->lock); | 745 | spin_lock(&fotg210->lock); |
746 | } | 746 | } |
747 | 747 | ||
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index be59309e848c..20141c3096f6 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c | |||
@@ -2234,8 +2234,10 @@ static void fsl_udc_release(struct device *dev) | |||
2234 | Internal structure setup functions | 2234 | Internal structure setup functions |
2235 | *******************************************************************/ | 2235 | *******************************************************************/ |
2236 | /*------------------------------------------------------------------ | 2236 | /*------------------------------------------------------------------ |
2237 | * init resource for globle controller | 2237 | * init resource for global controller called by fsl_udc_probe() |
2238 | * Return the udc handle on success or NULL on failure | 2238 | * On success the udc handle is initialized, on failure it is |
2239 | * unchanged (reset). | ||
2240 | * Return 0 on success and -1 on allocation failure | ||
2239 | ------------------------------------------------------------------*/ | 2241 | ------------------------------------------------------------------*/ |
2240 | static int struct_udc_setup(struct fsl_udc *udc, | 2242 | static int struct_udc_setup(struct fsl_udc *udc, |
2241 | struct platform_device *pdev) | 2243 | struct platform_device *pdev) |
@@ -2247,8 +2249,10 @@ static int struct_udc_setup(struct fsl_udc *udc, | |||
2247 | udc->phy_mode = pdata->phy_mode; | 2249 | udc->phy_mode = pdata->phy_mode; |
2248 | 2250 | ||
2249 | udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL); | 2251 | udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL); |
2250 | if (!udc->eps) | 2252 | if (!udc->eps) { |
2251 | return -1; | 2253 | ERR("kmalloc udc endpoint status failed\n"); |
2254 | goto eps_alloc_failed; | ||
2255 | } | ||
2252 | 2256 | ||
2253 | /* initialized QHs, take care of alignment */ | 2257 | /* initialized QHs, take care of alignment */ |
2254 | size = udc->max_ep * sizeof(struct ep_queue_head); | 2258 | size = udc->max_ep * sizeof(struct ep_queue_head); |
@@ -2262,8 +2266,7 @@ static int struct_udc_setup(struct fsl_udc *udc, | |||
2262 | &udc->ep_qh_dma, GFP_KERNEL); | 2266 | &udc->ep_qh_dma, GFP_KERNEL); |
2263 | if (!udc->ep_qh) { | 2267 | if (!udc->ep_qh) { |
2264 | ERR("malloc QHs for udc failed\n"); | 2268 | ERR("malloc QHs for udc failed\n"); |
2265 | kfree(udc->eps); | 2269 | goto ep_queue_alloc_failed; |
2266 | return -1; | ||
2267 | } | 2270 | } |
2268 | 2271 | ||
2269 | udc->ep_qh_size = size; | 2272 | udc->ep_qh_size = size; |
@@ -2272,8 +2275,17 @@ static int struct_udc_setup(struct fsl_udc *udc, | |||
2272 | /* FIXME: fsl_alloc_request() ignores ep argument */ | 2275 | /* FIXME: fsl_alloc_request() ignores ep argument */ |
2273 | udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL), | 2276 | udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL), |
2274 | struct fsl_req, req); | 2277 | struct fsl_req, req); |
2278 | if (!udc->status_req) { | ||
2279 | ERR("kzalloc for udc status request failed\n"); | ||
2280 | goto udc_status_alloc_failed; | ||
2281 | } | ||
2282 | |||
2275 | /* allocate a small amount of memory to get valid address */ | 2283 | /* allocate a small amount of memory to get valid address */ |
2276 | udc->status_req->req.buf = kmalloc(8, GFP_KERNEL); | 2284 | udc->status_req->req.buf = kmalloc(8, GFP_KERNEL); |
2285 | if (!udc->status_req->req.buf) { | ||
2286 | ERR("kzalloc for udc request buffer failed\n"); | ||
2287 | goto udc_req_buf_alloc_failed; | ||
2288 | } | ||
2277 | 2289 | ||
2278 | udc->resume_state = USB_STATE_NOTATTACHED; | 2290 | udc->resume_state = USB_STATE_NOTATTACHED; |
2279 | udc->usb_state = USB_STATE_POWERED; | 2291 | udc->usb_state = USB_STATE_POWERED; |
@@ -2281,6 +2293,18 @@ static int struct_udc_setup(struct fsl_udc *udc, | |||
2281 | udc->remote_wakeup = 0; /* default to 0 on reset */ | 2293 | udc->remote_wakeup = 0; /* default to 0 on reset */ |
2282 | 2294 | ||
2283 | return 0; | 2295 | return 0; |
2296 | |||
2297 | udc_req_buf_alloc_failed: | ||
2298 | kfree(udc->status_req); | ||
2299 | udc_status_alloc_failed: | ||
2300 | kfree(udc->ep_qh); | ||
2301 | udc->ep_qh_size = 0; | ||
2302 | ep_queue_alloc_failed: | ||
2303 | kfree(udc->eps); | ||
2304 | eps_alloc_failed: | ||
2305 | udc->phy_mode = 0; | ||
2306 | return -1; | ||
2307 | |||
2284 | } | 2308 | } |
2285 | 2309 | ||
2286 | /*---------------------------------------------------------------- | 2310 | /*---------------------------------------------------------------- |
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 95f52232493b..cafde053788b 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c | |||
@@ -185,7 +185,7 @@ static int process_ep_req(struct mv_udc *udc, int index, | |||
185 | else | 185 | else |
186 | bit_pos = 1 << (16 + curr_req->ep->ep_num); | 186 | bit_pos = 1 << (16 + curr_req->ep->ep_num); |
187 | 187 | ||
188 | while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) { | 188 | while (curr_dqh->curr_dtd_ptr == curr_dtd->td_dma) { |
189 | if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) { | 189 | if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) { |
190 | while (readl(&udc->op_regs->epstatus) & bit_pos) | 190 | while (readl(&udc->op_regs->epstatus) & bit_pos) |
191 | udelay(1); | 191 | udelay(1); |
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index b02ab2a8d927..e7dae5379e04 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c | |||
@@ -1550,9 +1550,6 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on) | |||
1550 | 1550 | ||
1551 | spin_unlock_irqrestore(&dev->lock, flags); | 1551 | spin_unlock_irqrestore(&dev->lock, flags); |
1552 | 1552 | ||
1553 | if (!is_on && dev->driver) | ||
1554 | dev->driver->disconnect(&dev->gadget); | ||
1555 | |||
1556 | return 0; | 1553 | return 0; |
1557 | } | 1554 | } |
1558 | 1555 | ||
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index e1656f361e08..cdffbd1e0316 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c | |||
@@ -2437,6 +2437,9 @@ static ssize_t renesas_usb3_b_device_write(struct file *file, | |||
2437 | else | 2437 | else |
2438 | usb3->forced_b_device = false; | 2438 | usb3->forced_b_device = false; |
2439 | 2439 | ||
2440 | if (usb3->workaround_for_vbus) | ||
2441 | usb3_disconnect(usb3); | ||
2442 | |||
2440 | /* Let this driver call usb3_connect() anyway */ | 2443 | /* Let this driver call usb3_connect() anyway */ |
2441 | usb3_check_id(usb3); | 2444 | usb3_check_id(usb3); |
2442 | 2445 | ||
@@ -2600,6 +2603,13 @@ static const struct renesas_usb3_priv renesas_usb3_priv_gen3 = { | |||
2600 | .ramsize_per_pipe = SZ_4K, | 2603 | .ramsize_per_pipe = SZ_4K, |
2601 | }; | 2604 | }; |
2602 | 2605 | ||
2606 | static const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = { | ||
2607 | .ramsize_per_ramif = SZ_16K, | ||
2608 | .num_ramif = 4, | ||
2609 | .ramsize_per_pipe = SZ_4K, | ||
2610 | .workaround_for_vbus = true, | ||
2611 | }; | ||
2612 | |||
2603 | static const struct of_device_id usb3_of_match[] = { | 2613 | static const struct of_device_id usb3_of_match[] = { |
2604 | { | 2614 | { |
2605 | .compatible = "renesas,r8a7795-usb3-peri", | 2615 | .compatible = "renesas,r8a7795-usb3-peri", |
@@ -2618,6 +2628,10 @@ static const struct soc_device_attribute renesas_usb3_quirks_match[] = { | |||
2618 | .soc_id = "r8a7795", .revision = "ES1.*", | 2628 | .soc_id = "r8a7795", .revision = "ES1.*", |
2619 | .data = &renesas_usb3_priv_r8a7795_es1, | 2629 | .data = &renesas_usb3_priv_r8a7795_es1, |
2620 | }, | 2630 | }, |
2631 | { | ||
2632 | .soc_id = "r8a77990", | ||
2633 | .data = &renesas_usb3_priv_r8a77990, | ||
2634 | }, | ||
2621 | { /* sentinel */ }, | 2635 | { /* sentinel */ }, |
2622 | }; | 2636 | }; |
2623 | 2637 | ||
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h index ff6cc6cb4227..d854cb19c42c 100644 --- a/include/uapi/linux/usb/video.h +++ b/include/uapi/linux/usb/video.h | |||
@@ -192,14 +192,14 @@ struct uvc_descriptor_header { | |||
192 | 192 | ||
193 | /* 3.7.2. Video Control Interface Header Descriptor */ | 193 | /* 3.7.2. Video Control Interface Header Descriptor */ |
194 | struct uvc_header_descriptor { | 194 | struct uvc_header_descriptor { |
195 | __u8 bLength; | 195 | __u8 bLength; |
196 | __u8 bDescriptorType; | 196 | __u8 bDescriptorType; |
197 | __u8 bDescriptorSubType; | 197 | __u8 bDescriptorSubType; |
198 | __u16 bcdUVC; | 198 | __le16 bcdUVC; |
199 | __u16 wTotalLength; | 199 | __le16 wTotalLength; |
200 | __u32 dwClockFrequency; | 200 | __le32 dwClockFrequency; |
201 | __u8 bInCollection; | 201 | __u8 bInCollection; |
202 | __u8 baInterfaceNr[]; | 202 | __u8 baInterfaceNr[]; |
203 | } __attribute__((__packed__)); | 203 | } __attribute__((__packed__)); |
204 | 204 | ||
205 | #define UVC_DT_HEADER_SIZE(n) (12+(n)) | 205 | #define UVC_DT_HEADER_SIZE(n) (12+(n)) |
@@ -209,57 +209,57 @@ struct uvc_header_descriptor { | |||
209 | 209 | ||
210 | #define DECLARE_UVC_HEADER_DESCRIPTOR(n) \ | 210 | #define DECLARE_UVC_HEADER_DESCRIPTOR(n) \ |
211 | struct UVC_HEADER_DESCRIPTOR(n) { \ | 211 | struct UVC_HEADER_DESCRIPTOR(n) { \ |
212 | __u8 bLength; \ | 212 | __u8 bLength; \ |
213 | __u8 bDescriptorType; \ | 213 | __u8 bDescriptorType; \ |
214 | __u8 bDescriptorSubType; \ | 214 | __u8 bDescriptorSubType; \ |
215 | __u16 bcdUVC; \ | 215 | __le16 bcdUVC; \ |
216 | __u16 wTotalLength; \ | 216 | __le16 wTotalLength; \ |
217 | __u32 dwClockFrequency; \ | 217 | __le32 dwClockFrequency; \ |
218 | __u8 bInCollection; \ | 218 | __u8 bInCollection; \ |
219 | __u8 baInterfaceNr[n]; \ | 219 | __u8 baInterfaceNr[n]; \ |
220 | } __attribute__ ((packed)) | 220 | } __attribute__ ((packed)) |
221 | 221 | ||
222 | /* 3.7.2.1. Input Terminal Descriptor */ | 222 | /* 3.7.2.1. Input Terminal Descriptor */ |
223 | struct uvc_input_terminal_descriptor { | 223 | struct uvc_input_terminal_descriptor { |
224 | __u8 bLength; | 224 | __u8 bLength; |
225 | __u8 bDescriptorType; | 225 | __u8 bDescriptorType; |
226 | __u8 bDescriptorSubType; | 226 | __u8 bDescriptorSubType; |
227 | __u8 bTerminalID; | 227 | __u8 bTerminalID; |
228 | __u16 wTerminalType; | 228 | __le16 wTerminalType; |
229 | __u8 bAssocTerminal; | 229 | __u8 bAssocTerminal; |
230 | __u8 iTerminal; | 230 | __u8 iTerminal; |
231 | } __attribute__((__packed__)); | 231 | } __attribute__((__packed__)); |
232 | 232 | ||
233 | #define UVC_DT_INPUT_TERMINAL_SIZE 8 | 233 | #define UVC_DT_INPUT_TERMINAL_SIZE 8 |
234 | 234 | ||
235 | /* 3.7.2.2. Output Terminal Descriptor */ | 235 | /* 3.7.2.2. Output Terminal Descriptor */ |
236 | struct uvc_output_terminal_descriptor { | 236 | struct uvc_output_terminal_descriptor { |
237 | __u8 bLength; | 237 | __u8 bLength; |
238 | __u8 bDescriptorType; | 238 | __u8 bDescriptorType; |
239 | __u8 bDescriptorSubType; | 239 | __u8 bDescriptorSubType; |
240 | __u8 bTerminalID; | 240 | __u8 bTerminalID; |
241 | __u16 wTerminalType; | 241 | __le16 wTerminalType; |
242 | __u8 bAssocTerminal; | 242 | __u8 bAssocTerminal; |
243 | __u8 bSourceID; | 243 | __u8 bSourceID; |
244 | __u8 iTerminal; | 244 | __u8 iTerminal; |
245 | } __attribute__((__packed__)); | 245 | } __attribute__((__packed__)); |
246 | 246 | ||
247 | #define UVC_DT_OUTPUT_TERMINAL_SIZE 9 | 247 | #define UVC_DT_OUTPUT_TERMINAL_SIZE 9 |
248 | 248 | ||
249 | /* 3.7.2.3. Camera Terminal Descriptor */ | 249 | /* 3.7.2.3. Camera Terminal Descriptor */ |
250 | struct uvc_camera_terminal_descriptor { | 250 | struct uvc_camera_terminal_descriptor { |
251 | __u8 bLength; | 251 | __u8 bLength; |
252 | __u8 bDescriptorType; | 252 | __u8 bDescriptorType; |
253 | __u8 bDescriptorSubType; | 253 | __u8 bDescriptorSubType; |
254 | __u8 bTerminalID; | 254 | __u8 bTerminalID; |
255 | __u16 wTerminalType; | 255 | __le16 wTerminalType; |
256 | __u8 bAssocTerminal; | 256 | __u8 bAssocTerminal; |
257 | __u8 iTerminal; | 257 | __u8 iTerminal; |
258 | __u16 wObjectiveFocalLengthMin; | 258 | __le16 wObjectiveFocalLengthMin; |
259 | __u16 wObjectiveFocalLengthMax; | 259 | __le16 wObjectiveFocalLengthMax; |
260 | __u16 wOcularFocalLength; | 260 | __le16 wOcularFocalLength; |
261 | __u8 bControlSize; | 261 | __u8 bControlSize; |
262 | __u8 bmControls[3]; | 262 | __u8 bmControls[3]; |
263 | } __attribute__((__packed__)); | 263 | } __attribute__((__packed__)); |
264 | 264 | ||
265 | #define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n)) | 265 | #define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n)) |
@@ -293,15 +293,15 @@ struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \ | |||
293 | 293 | ||
294 | /* 3.7.2.5. Processing Unit Descriptor */ | 294 | /* 3.7.2.5. Processing Unit Descriptor */ |
295 | struct uvc_processing_unit_descriptor { | 295 | struct uvc_processing_unit_descriptor { |
296 | __u8 bLength; | 296 | __u8 bLength; |
297 | __u8 bDescriptorType; | 297 | __u8 bDescriptorType; |
298 | __u8 bDescriptorSubType; | 298 | __u8 bDescriptorSubType; |
299 | __u8 bUnitID; | 299 | __u8 bUnitID; |
300 | __u8 bSourceID; | 300 | __u8 bSourceID; |
301 | __u16 wMaxMultiplier; | 301 | __le16 wMaxMultiplier; |
302 | __u8 bControlSize; | 302 | __u8 bControlSize; |
303 | __u8 bmControls[2]; | 303 | __u8 bmControls[2]; |
304 | __u8 iProcessing; | 304 | __u8 iProcessing; |
305 | } __attribute__((__packed__)); | 305 | } __attribute__((__packed__)); |
306 | 306 | ||
307 | #define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n)) | 307 | #define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n)) |
@@ -343,29 +343,29 @@ struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \ | |||
343 | 343 | ||
344 | /* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */ | 344 | /* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */ |
345 | struct uvc_control_endpoint_descriptor { | 345 | struct uvc_control_endpoint_descriptor { |
346 | __u8 bLength; | 346 | __u8 bLength; |
347 | __u8 bDescriptorType; | 347 | __u8 bDescriptorType; |
348 | __u8 bDescriptorSubType; | 348 | __u8 bDescriptorSubType; |
349 | __u16 wMaxTransferSize; | 349 | __le16 wMaxTransferSize; |
350 | } __attribute__((__packed__)); | 350 | } __attribute__((__packed__)); |
351 | 351 | ||
352 | #define UVC_DT_CONTROL_ENDPOINT_SIZE 5 | 352 | #define UVC_DT_CONTROL_ENDPOINT_SIZE 5 |
353 | 353 | ||
354 | /* 3.9.2.1. Input Header Descriptor */ | 354 | /* 3.9.2.1. Input Header Descriptor */ |
355 | struct uvc_input_header_descriptor { | 355 | struct uvc_input_header_descriptor { |
356 | __u8 bLength; | 356 | __u8 bLength; |
357 | __u8 bDescriptorType; | 357 | __u8 bDescriptorType; |
358 | __u8 bDescriptorSubType; | 358 | __u8 bDescriptorSubType; |
359 | __u8 bNumFormats; | 359 | __u8 bNumFormats; |
360 | __u16 wTotalLength; | 360 | __le16 wTotalLength; |
361 | __u8 bEndpointAddress; | 361 | __u8 bEndpointAddress; |
362 | __u8 bmInfo; | 362 | __u8 bmInfo; |
363 | __u8 bTerminalLink; | 363 | __u8 bTerminalLink; |
364 | __u8 bStillCaptureMethod; | 364 | __u8 bStillCaptureMethod; |
365 | __u8 bTriggerSupport; | 365 | __u8 bTriggerSupport; |
366 | __u8 bTriggerUsage; | 366 | __u8 bTriggerUsage; |
367 | __u8 bControlSize; | 367 | __u8 bControlSize; |
368 | __u8 bmaControls[]; | 368 | __u8 bmaControls[]; |
369 | } __attribute__((__packed__)); | 369 | } __attribute__((__packed__)); |
370 | 370 | ||
371 | #define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p)) | 371 | #define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p)) |
@@ -375,32 +375,32 @@ struct uvc_input_header_descriptor { | |||
375 | 375 | ||
376 | #define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \ | 376 | #define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \ |
377 | struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \ | 377 | struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \ |
378 | __u8 bLength; \ | 378 | __u8 bLength; \ |
379 | __u8 bDescriptorType; \ | 379 | __u8 bDescriptorType; \ |
380 | __u8 bDescriptorSubType; \ | 380 | __u8 bDescriptorSubType; \ |
381 | __u8 bNumFormats; \ | 381 | __u8 bNumFormats; \ |
382 | __u16 wTotalLength; \ | 382 | __le16 wTotalLength; \ |
383 | __u8 bEndpointAddress; \ | 383 | __u8 bEndpointAddress; \ |
384 | __u8 bmInfo; \ | 384 | __u8 bmInfo; \ |
385 | __u8 bTerminalLink; \ | 385 | __u8 bTerminalLink; \ |
386 | __u8 bStillCaptureMethod; \ | 386 | __u8 bStillCaptureMethod; \ |
387 | __u8 bTriggerSupport; \ | 387 | __u8 bTriggerSupport; \ |
388 | __u8 bTriggerUsage; \ | 388 | __u8 bTriggerUsage; \ |
389 | __u8 bControlSize; \ | 389 | __u8 bControlSize; \ |
390 | __u8 bmaControls[p][n]; \ | 390 | __u8 bmaControls[p][n]; \ |
391 | } __attribute__ ((packed)) | 391 | } __attribute__ ((packed)) |
392 | 392 | ||
393 | /* 3.9.2.2. Output Header Descriptor */ | 393 | /* 3.9.2.2. Output Header Descriptor */ |
394 | struct uvc_output_header_descriptor { | 394 | struct uvc_output_header_descriptor { |
395 | __u8 bLength; | 395 | __u8 bLength; |
396 | __u8 bDescriptorType; | 396 | __u8 bDescriptorType; |
397 | __u8 bDescriptorSubType; | 397 | __u8 bDescriptorSubType; |
398 | __u8 bNumFormats; | 398 | __u8 bNumFormats; |
399 | __u16 wTotalLength; | 399 | __le16 wTotalLength; |
400 | __u8 bEndpointAddress; | 400 | __u8 bEndpointAddress; |
401 | __u8 bTerminalLink; | 401 | __u8 bTerminalLink; |
402 | __u8 bControlSize; | 402 | __u8 bControlSize; |
403 | __u8 bmaControls[]; | 403 | __u8 bmaControls[]; |
404 | } __attribute__((__packed__)); | 404 | } __attribute__((__packed__)); |
405 | 405 | ||
406 | #define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p)) | 406 | #define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p)) |
@@ -410,15 +410,15 @@ struct uvc_output_header_descriptor { | |||
410 | 410 | ||
411 | #define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \ | 411 | #define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \ |
412 | struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \ | 412 | struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \ |
413 | __u8 bLength; \ | 413 | __u8 bLength; \ |
414 | __u8 bDescriptorType; \ | 414 | __u8 bDescriptorType; \ |
415 | __u8 bDescriptorSubType; \ | 415 | __u8 bDescriptorSubType; \ |
416 | __u8 bNumFormats; \ | 416 | __u8 bNumFormats; \ |
417 | __u16 wTotalLength; \ | 417 | __le16 wTotalLength; \ |
418 | __u8 bEndpointAddress; \ | 418 | __u8 bEndpointAddress; \ |
419 | __u8 bTerminalLink; \ | 419 | __u8 bTerminalLink; \ |
420 | __u8 bControlSize; \ | 420 | __u8 bControlSize; \ |
421 | __u8 bmaControls[p][n]; \ | 421 | __u8 bmaControls[p][n]; \ |
422 | } __attribute__ ((packed)) | 422 | } __attribute__ ((packed)) |
423 | 423 | ||
424 | /* 3.9.2.6. Color matching descriptor */ | 424 | /* 3.9.2.6. Color matching descriptor */ |
@@ -473,19 +473,19 @@ struct uvc_format_uncompressed { | |||
473 | 473 | ||
474 | /* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */ | 474 | /* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */ |
475 | struct uvc_frame_uncompressed { | 475 | struct uvc_frame_uncompressed { |
476 | __u8 bLength; | 476 | __u8 bLength; |
477 | __u8 bDescriptorType; | 477 | __u8 bDescriptorType; |
478 | __u8 bDescriptorSubType; | 478 | __u8 bDescriptorSubType; |
479 | __u8 bFrameIndex; | 479 | __u8 bFrameIndex; |
480 | __u8 bmCapabilities; | 480 | __u8 bmCapabilities; |
481 | __u16 wWidth; | 481 | __le16 wWidth; |
482 | __u16 wHeight; | 482 | __le16 wHeight; |
483 | __u32 dwMinBitRate; | 483 | __le32 dwMinBitRate; |
484 | __u32 dwMaxBitRate; | 484 | __le32 dwMaxBitRate; |
485 | __u32 dwMaxVideoFrameBufferSize; | 485 | __le32 dwMaxVideoFrameBufferSize; |
486 | __u32 dwDefaultFrameInterval; | 486 | __le32 dwDefaultFrameInterval; |
487 | __u8 bFrameIntervalType; | 487 | __u8 bFrameIntervalType; |
488 | __u32 dwFrameInterval[]; | 488 | __le32 dwFrameInterval[]; |
489 | } __attribute__((__packed__)); | 489 | } __attribute__((__packed__)); |
490 | 490 | ||
491 | #define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n)) | 491 | #define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n)) |
@@ -495,19 +495,19 @@ struct uvc_frame_uncompressed { | |||
495 | 495 | ||
496 | #define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \ | 496 | #define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \ |
497 | struct UVC_FRAME_UNCOMPRESSED(n) { \ | 497 | struct UVC_FRAME_UNCOMPRESSED(n) { \ |
498 | __u8 bLength; \ | 498 | __u8 bLength; \ |
499 | __u8 bDescriptorType; \ | 499 | __u8 bDescriptorType; \ |
500 | __u8 bDescriptorSubType; \ | 500 | __u8 bDescriptorSubType; \ |
501 | __u8 bFrameIndex; \ | 501 | __u8 bFrameIndex; \ |
502 | __u8 bmCapabilities; \ | 502 | __u8 bmCapabilities; \ |
503 | __u16 wWidth; \ | 503 | __le16 wWidth; \ |
504 | __u16 wHeight; \ | 504 | __le16 wHeight; \ |
505 | __u32 dwMinBitRate; \ | 505 | __le32 dwMinBitRate; \ |
506 | __u32 dwMaxBitRate; \ | 506 | __le32 dwMaxBitRate; \ |
507 | __u32 dwMaxVideoFrameBufferSize; \ | 507 | __le32 dwMaxVideoFrameBufferSize; \ |
508 | __u32 dwDefaultFrameInterval; \ | 508 | __le32 dwDefaultFrameInterval; \ |
509 | __u8 bFrameIntervalType; \ | 509 | __u8 bFrameIntervalType; \ |
510 | __u32 dwFrameInterval[n]; \ | 510 | __le32 dwFrameInterval[n]; \ |
511 | } __attribute__ ((packed)) | 511 | } __attribute__ ((packed)) |
512 | 512 | ||
513 | /* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */ | 513 | /* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */ |
@@ -529,19 +529,19 @@ struct uvc_format_mjpeg { | |||
529 | 529 | ||
530 | /* MJPEG Payload - 3.1.2. MJPEG Video Frame Descriptor */ | 530 | /* MJPEG Payload - 3.1.2. MJPEG Video Frame Descriptor */ |
531 | struct uvc_frame_mjpeg { | 531 | struct uvc_frame_mjpeg { |
532 | __u8 bLength; | 532 | __u8 bLength; |
533 | __u8 bDescriptorType; | 533 | __u8 bDescriptorType; |
534 | __u8 bDescriptorSubType; | 534 | __u8 bDescriptorSubType; |
535 | __u8 bFrameIndex; | 535 | __u8 bFrameIndex; |
536 | __u8 bmCapabilities; | 536 | __u8 bmCapabilities; |
537 | __u16 wWidth; | 537 | __le16 wWidth; |
538 | __u16 wHeight; | 538 | __le16 wHeight; |
539 | __u32 dwMinBitRate; | 539 | __le32 dwMinBitRate; |
540 | __u32 dwMaxBitRate; | 540 | __le32 dwMaxBitRate; |
541 | __u32 dwMaxVideoFrameBufferSize; | 541 | __le32 dwMaxVideoFrameBufferSize; |
542 | __u32 dwDefaultFrameInterval; | 542 | __le32 dwDefaultFrameInterval; |
543 | __u8 bFrameIntervalType; | 543 | __u8 bFrameIntervalType; |
544 | __u32 dwFrameInterval[]; | 544 | __le32 dwFrameInterval[]; |
545 | } __attribute__((__packed__)); | 545 | } __attribute__((__packed__)); |
546 | 546 | ||
547 | #define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n)) | 547 | #define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n)) |
@@ -551,19 +551,19 @@ struct uvc_frame_mjpeg { | |||
551 | 551 | ||
552 | #define DECLARE_UVC_FRAME_MJPEG(n) \ | 552 | #define DECLARE_UVC_FRAME_MJPEG(n) \ |
553 | struct UVC_FRAME_MJPEG(n) { \ | 553 | struct UVC_FRAME_MJPEG(n) { \ |
554 | __u8 bLength; \ | 554 | __u8 bLength; \ |
555 | __u8 bDescriptorType; \ | 555 | __u8 bDescriptorType; \ |
556 | __u8 bDescriptorSubType; \ | 556 | __u8 bDescriptorSubType; \ |
557 | __u8 bFrameIndex; \ | 557 | __u8 bFrameIndex; \ |
558 | __u8 bmCapabilities; \ | 558 | __u8 bmCapabilities; \ |
559 | __u16 wWidth; \ | 559 | __le16 wWidth; \ |
560 | __u16 wHeight; \ | 560 | __le16 wHeight; \ |
561 | __u32 dwMinBitRate; \ | 561 | __le32 dwMinBitRate; \ |
562 | __u32 dwMaxBitRate; \ | 562 | __le32 dwMaxBitRate; \ |
563 | __u32 dwMaxVideoFrameBufferSize; \ | 563 | __le32 dwMaxVideoFrameBufferSize; \ |
564 | __u32 dwDefaultFrameInterval; \ | 564 | __le32 dwDefaultFrameInterval; \ |
565 | __u8 bFrameIntervalType; \ | 565 | __u8 bFrameIntervalType; \ |
566 | __u32 dwFrameInterval[n]; \ | 566 | __le32 dwFrameInterval[n]; \ |
567 | } __attribute__ ((packed)) | 567 | } __attribute__ ((packed)) |
568 | 568 | ||
569 | #endif /* __LINUX_USB_VIDEO_H */ | 569 | #endif /* __LINUX_USB_VIDEO_H */ |