Commit 842807d5adac24fcc8bad8971e13525b8ea8db11
Exists in
smarc-l5.0.0_1.0.0-ga
Merge remote-tracking branch 'remotes/stash/imx_3.10.53_1.1.0_ga' into imx_3.10.y_android
Showing 13 changed files Side-by-side Diff
- Documentation/devicetree/bindings/usb/mxs-phy.txt
- arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
- arch/arm/boot/dts/imx6sx-sdb.dts
- arch/arm/boot/dts/imx6sx.dtsi
- arch/arm/mach-imx/clk-imx6q.c
- drivers/usb/chipidea/ci_hdrc_imx.c
- drivers/usb/chipidea/ci_hdrc_imx.h
- drivers/usb/chipidea/udc.c
- drivers/usb/chipidea/usbmisc_imx.c
- drivers/usb/phy/phy-mxs-usb.c
- include/linux/usb/chipidea.h
- sound/soc/fsl/fsl_sai.c
- sound/soc/fsl/fsl_ssi.c
Documentation/devicetree/bindings/usb/mxs-phy.txt
... | ... | @@ -7,11 +7,17 @@ |
7 | 7 | - interrupts: Should contain phy interrupt |
8 | 8 | - fsl,anatop: phandle for anatop register, it is only for imx6 SoC series |
9 | 9 | |
10 | +Optional properties: | |
11 | +- tx-d-cal: Try to adjust this value to improve signal quality, and pass | |
12 | + USB Certification, the value is from 0x0 to 0xf, and the register offset | |
13 | + is 0x10 (USBPHY_TX). | |
14 | + | |
10 | 15 | Example: |
11 | 16 | usbphy1: usbphy@020c9000 { |
12 | 17 | compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; |
13 | 18 | reg = <0x020c9000 0x1000>; |
14 | 19 | interrupts = <0 44 0x04>; |
15 | 20 | fsl,anatop = <&anatop>; |
21 | + tx-d-cal = <0x5>; | |
16 | 22 | }; |
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6sx.dtsi
... | ... | @@ -1274,6 +1274,28 @@ |
1274 | 1274 | status = "disabled"; |
1275 | 1275 | }; |
1276 | 1276 | |
1277 | + wdog3: wdog@02288000 { | |
1278 | + compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt"; | |
1279 | + reg = <0x02288000 0x4000>; | |
1280 | + interrupts = <0 11 0x04>; | |
1281 | + clocks = <&clks IMX6SX_CLK_DUMMY>; | |
1282 | + status = "disabled"; | |
1283 | + }; | |
1284 | + | |
1285 | + ecspi5: ecspi@0228c000 { | |
1286 | + #address-cells = <1>; | |
1287 | + #size-cells = <0>; | |
1288 | + compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; | |
1289 | + reg = <0x0228c000 0x4000>; | |
1290 | + interrupts = <0 18 0x04>; | |
1291 | + clocks = <&clks IMX6SX_CLK_ECSPI5>, | |
1292 | + <&clks IMX6SX_CLK_ECSPI5>; | |
1293 | + clock-names = "ipg", "per"; | |
1294 | + dmas = <&sdma 11 7 1>, <&sdma 12 7 2>; | |
1295 | + dma-names = "rx", "tx"; | |
1296 | + status = "disabled"; | |
1297 | + }; | |
1298 | + | |
1277 | 1299 | sema4: sema4@02290000 { /* sema4 */ |
1278 | 1300 | compatible = "fsl,imx6sx-sema4"; |
1279 | 1301 | reg = <0x02290000 0x4000>; |
arch/arm/mach-imx/clk-imx6q.c
... | ... | @@ -752,6 +752,9 @@ |
752 | 752 | /* Set pll4_audio to a value that can derive 5K-88.2KHz and 8K-96KHz */ |
753 | 753 | imx_clk_set_rate(clk[pll4_audio_div], 541900800); |
754 | 754 | |
755 | + /*Set enet_ref clock to 125M to supply for RGMII tx_clk */ | |
756 | + clk_set_rate(clk[enet_ref], 125000000); | |
757 | + | |
755 | 758 | #ifdef CONFIG_MX6_VPU_352M |
756 | 759 | /* |
757 | 760 | * If VPU 352M is enabled, then PLL2_PDF2 need to be |
drivers/usb/chipidea/ci_hdrc_imx.c
1 | 1 | /* |
2 | - * Copyright 2012-2014 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2012-2015 Freescale Semiconductor, Inc. | |
3 | 3 | * Copyright (C) 2012 Marek Vasut <marex@denx.de> |
4 | 4 | * on behalf of DENX Software Engineering GmbH |
5 | 5 | * |
6 | 6 | |
... | ... | @@ -198,18 +198,16 @@ |
198 | 198 | int ret = 0; |
199 | 199 | |
200 | 200 | switch (event) { |
201 | - case CI_HDRC_CONTROLLER_VBUS_EVENT: | |
202 | - if (data->usbmisc_data && ci->vbus_active) { | |
203 | - imx_usbmisc_vbus_handler(data->usbmisc_data, true); | |
204 | - if (data->imx6_usb_charger_detection) | |
205 | - ret = imx6_usb_vbus_connect(&data->charger); | |
201 | + case CI_HDRC_CONTROLLER_CHARGER_EVENT: | |
202 | + if (!data->imx6_usb_charger_detection) | |
203 | + return ret; | |
204 | + if (ci->vbus_active) { | |
205 | + ret = imx6_usb_vbus_connect(&data->charger); | |
206 | 206 | if (!ret && data->charger.psy.type |
207 | 207 | != POWER_SUPPLY_TYPE_USB) |
208 | 208 | ret = CI_HDRC_NOTIFY_RET_DEFER_EVENT; |
209 | - } else if (data->usbmisc_data && !ci->vbus_active) { | |
210 | - imx_usbmisc_vbus_handler(data->usbmisc_data, false); | |
211 | - if (data->imx6_usb_charger_detection) | |
212 | - ret = imx6_usb_vbus_disconnect(&data->charger); | |
209 | + } else { | |
210 | + ret = imx6_usb_vbus_disconnect(&data->charger); | |
213 | 211 | } |
214 | 212 | break; |
215 | 213 | case CI_HDRC_CONTROLLER_CHARGER_POST_EVENT: |
drivers/usb/chipidea/ci_hdrc_imx.h
1 | 1 | /* |
2 | - * Copyright 2012-2014 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2012-2015 Freescale Semiconductor, Inc. | |
3 | 3 | * |
4 | 4 | * The code contained herein is licensed under the GNU General Public |
5 | 5 | * License. You may obtain a copy of the GNU General Public License |
... | ... | @@ -35,7 +35,6 @@ |
35 | 35 | int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *); |
36 | 36 | int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool); |
37 | 37 | int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *); |
38 | -int imx_usbmisc_vbus_handler(struct imx_usbmisc_data *, bool); | |
39 | 38 | |
40 | 39 | #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ |
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
1 | 1 | /* |
2 | - * Copyright 2012-2014 Freescale Semiconductor, Inc. | |
2 | + * Copyright 2012-2015 Freescale Semiconductor, Inc. | |
3 | 3 | * |
4 | 4 | * The code contained herein is licensed under the GNU General Public |
5 | 5 | * License. You may obtain a copy of the GNU General Public License |
... | ... | @@ -65,11 +65,6 @@ |
65 | 65 | #define ANADIG_ANA_MISC0_SET 0x154 |
66 | 66 | #define ANADIG_ANA_MISC0_CLK_DELAY(x) ((x >> 26) & 0x7) |
67 | 67 | |
68 | -#define ANADIG_REG_3P0_SET 0x124 | |
69 | -#define ANADIG_REG_3P0_CLR 0x128 | |
70 | -#define ANADIG_REG_3P0_ENABLE_ILIMIT BIT(2) | |
71 | -#define ANADIG_REG_3P0_ENABLE_LINREG BIT(0) | |
72 | - | |
73 | 68 | struct usbmisc_ops { |
74 | 69 | /* It's called once when probe a usb device */ |
75 | 70 | int (*init)(struct imx_usbmisc_data *data); |
... | ... | @@ -83,8 +78,6 @@ |
83 | 78 | int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); |
84 | 79 | /* It's called when system resume from usb power lost */ |
85 | 80 | int (*power_lost_check)(struct imx_usbmisc_data *data); |
86 | - /* It's called when the vbus event happenes */ | |
87 | - int (*vbus_handler)(struct imx_usbmisc_data *data, bool active); | |
88 | 81 | }; |
89 | 82 | |
90 | 83 | struct imx_usbmisc { |
... | ... | @@ -376,27 +369,6 @@ |
376 | 369 | return ret; |
377 | 370 | } |
378 | 371 | |
379 | -static int usbmisc_imx6q_vbus_handler | |
380 | - (struct imx_usbmisc_data *data, bool active) | |
381 | -{ | |
382 | - if (!data->anatop) | |
383 | - return 0; | |
384 | - | |
385 | - if (active) { | |
386 | - regmap_write(data->anatop, ANADIG_REG_3P0_SET, | |
387 | - ANADIG_REG_3P0_ENABLE_LINREG); | |
388 | - regmap_write(data->anatop, ANADIG_REG_3P0_CLR, | |
389 | - ANADIG_REG_3P0_ENABLE_ILIMIT); | |
390 | - } else { | |
391 | - regmap_write(data->anatop, ANADIG_REG_3P0_CLR, | |
392 | - ANADIG_REG_3P0_ENABLE_LINREG); | |
393 | - regmap_write(data->anatop, ANADIG_REG_3P0_SET, | |
394 | - ANADIG_REG_3P0_ENABLE_ILIMIT); | |
395 | - } | |
396 | - | |
397 | - return 0; | |
398 | -} | |
399 | - | |
400 | 372 | static const struct usbmisc_ops imx25_usbmisc_ops = { |
401 | 373 | .post = usbmisc_imx25_post, |
402 | 374 | }; |
... | ... | @@ -410,7 +382,6 @@ |
410 | 382 | .set_wakeup = usbmisc_imx6q_set_wakeup, |
411 | 383 | .hsic_set_connect = usbmisc_imx6q_hsic_set_connect, |
412 | 384 | .hsic_set_clk = usbmisc_imx6q_hsic_set_clk, |
413 | - .vbus_handler = usbmisc_imx6q_vbus_handler, | |
414 | 385 | }; |
415 | 386 | |
416 | 387 | static const struct usbmisc_ops imx6sx_usbmisc_ops = { |
... | ... | @@ -419,7 +390,6 @@ |
419 | 390 | .hsic_set_connect = usbmisc_imx6q_hsic_set_connect, |
420 | 391 | .hsic_set_clk = usbmisc_imx6q_hsic_set_clk, |
421 | 392 | .power_lost_check = usbmisc_imx6sx_power_lost_check, |
422 | - .vbus_handler = usbmisc_imx6q_vbus_handler, | |
423 | 393 | }; |
424 | 394 | |
425 | 395 | int imx_usbmisc_init(struct imx_usbmisc_data *data) |
... | ... | @@ -481,16 +451,6 @@ |
481 | 451 | return usbmisc->ops->power_lost_check(data); |
482 | 452 | } |
483 | 453 | EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check); |
484 | - | |
485 | -int imx_usbmisc_vbus_handler(struct imx_usbmisc_data *data, bool active) | |
486 | -{ | |
487 | - if (!usbmisc) | |
488 | - return -ENODEV; | |
489 | - if (!usbmisc->ops->vbus_handler) | |
490 | - return 0; | |
491 | - return usbmisc->ops->vbus_handler(data, active); | |
492 | -} | |
493 | -EXPORT_SYMBOL_GPL(imx_usbmisc_vbus_handler); | |
494 | 454 | |
495 | 455 | static const struct of_device_id usbmisc_imx_dt_ids[] = { |
496 | 456 | { |
drivers/usb/phy/phy-mxs-usb.c
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | #define DRIVER_NAME "mxs_phy" |
29 | 29 | |
30 | 30 | #define HW_USBPHY_PWD 0x00 |
31 | +#define HW_USBPHY_TX 0x10 | |
31 | 32 | #define HW_USBPHY_CTRL 0x30 |
32 | 33 | #define HW_USBPHY_CTRL_SET 0x34 |
33 | 34 | #define HW_USBPHY_CTRL_CLR 0x38 |
... | ... | @@ -39,6 +40,8 @@ |
39 | 40 | #define HW_USBPHY_IP_SET 0x94 |
40 | 41 | #define HW_USBPHY_IP_CLR 0x98 |
41 | 42 | |
43 | +#define HW_USBPHY_TX_D_CAL_MASK 0xf | |
44 | + | |
42 | 45 | #define BM_USBPHY_CTRL_SFTRST BIT(31) |
43 | 46 | #define BM_USBPHY_CTRL_CLKGATE BIT(30) |
44 | 47 | #define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27) |
... | ... | @@ -120,6 +123,16 @@ |
120 | 123 | */ |
121 | 124 | #define MXS_PHY_PULLDOWN_LINE BIT(4) |
122 | 125 | |
126 | +/* | |
127 | + * At some versions, the PHY2's clock is controlled by hardware directly, | |
128 | + * eg, according to PHY's suspend status. In these PHYs, we only need to | |
129 | + * open the clock at the initialization and close it at its shutdown routine. | |
130 | + * It will be benefit for remote wakeup case which needs to send resume | |
131 | + * signal as soon as possible, and in this case, the resume signal can be sent | |
132 | + * out without software interfere. | |
133 | + */ | |
134 | +#define MXS_PHY_HARDWARE_CONTROL_PHY2_CLK BIT(5) | |
135 | + | |
123 | 136 | struct mxs_phy_data { |
124 | 137 | unsigned int flags; |
125 | 138 | }; |
126 | 139 | |
127 | 140 | |
... | ... | @@ -131,18 +144,21 @@ |
131 | 144 | static const struct mxs_phy_data imx6q_phy_data = { |
132 | 145 | .flags = MXS_PHY_SENDING_SOF_TOO_FAST | |
133 | 146 | MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | |
134 | - MXS_PHY_HAS_ANATOP, | |
147 | + MXS_PHY_HAS_ANATOP | | |
148 | + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, | |
135 | 149 | }; |
136 | 150 | |
137 | 151 | static const struct mxs_phy_data imx6sl_phy_data = { |
138 | 152 | .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | |
139 | - MXS_PHY_HAS_ANATOP, | |
153 | + MXS_PHY_HAS_ANATOP | | |
154 | + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, | |
140 | 155 | }; |
141 | 156 | |
142 | 157 | static const struct mxs_phy_data imx6sx_phy_data = { |
143 | 158 | .flags = MXS_PHY_HAS_ANATOP | |
144 | 159 | MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | |
145 | - MXS_PHY_PULLDOWN_LINE, | |
160 | + MXS_PHY_PULLDOWN_LINE | | |
161 | + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, | |
146 | 162 | }; |
147 | 163 | |
148 | 164 | static const struct of_device_id mxs_phy_dt_ids[] = { |
... | ... | @@ -161,6 +177,8 @@ |
161 | 177 | struct regmap *regmap_anatop; |
162 | 178 | int port_id; |
163 | 179 | struct regulator *phy_3p0; |
180 | + bool hardware_control_phy2_clk; | |
181 | + u32 tx_d_cal; | |
164 | 182 | }; |
165 | 183 | |
166 | 184 | static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy) |
... | ... | @@ -186,6 +204,7 @@ |
186 | 204 | { |
187 | 205 | int ret; |
188 | 206 | void __iomem *base = mxs_phy->phy.io_priv; |
207 | + u32 val; | |
189 | 208 | |
190 | 209 | ret = stmp_reset_block(base + HW_USBPHY_CTRL); |
191 | 210 | if (ret) |
... | ... | @@ -222,6 +241,13 @@ |
222 | 241 | if (is_imx6q_phy(mxs_phy) || is_imx6sl_phy(mxs_phy)) |
223 | 242 | writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET); |
224 | 243 | |
244 | + /* Change D_CAL if necessary */ | |
245 | + if (mxs_phy->tx_d_cal) { | |
246 | + val = readl(base + HW_USBPHY_TX); | |
247 | + val &= ~HW_USBPHY_TX_D_CAL_MASK; | |
248 | + writel(val | mxs_phy->tx_d_cal, base + HW_USBPHY_TX); | |
249 | + } | |
250 | + | |
225 | 251 | return 0; |
226 | 252 | } |
227 | 253 | |
... | ... | @@ -387,6 +413,7 @@ |
387 | 413 | { |
388 | 414 | struct mxs_phy *mxs_phy = to_mxs_phy(x); |
389 | 415 | bool low_speed_connection, vbus_is_on; |
416 | + int ret; | |
390 | 417 | |
391 | 418 | low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy); |
392 | 419 | vbus_is_on = mxs_phy_get_vbus_status(mxs_phy); |
393 | 420 | |
... | ... | @@ -409,10 +436,17 @@ |
409 | 436 | } |
410 | 437 | writel(BM_USBPHY_CTRL_CLKGATE, |
411 | 438 | x->io_priv + HW_USBPHY_CTRL_SET); |
412 | - clk_disable_unprepare(mxs_phy->clk); | |
439 | + if (!(mxs_phy->port_id == 1 && | |
440 | + mxs_phy->hardware_control_phy2_clk)) | |
441 | + clk_disable_unprepare(mxs_phy->clk); | |
413 | 442 | } else { |
414 | 443 | mxs_phy_clock_switch(); |
415 | - clk_prepare_enable(mxs_phy->clk); | |
444 | + if (!(mxs_phy->port_id == 1 && | |
445 | + mxs_phy->hardware_control_phy2_clk)) { | |
446 | + ret = clk_prepare_enable(mxs_phy->clk); | |
447 | + if (ret) | |
448 | + return ret; | |
449 | + } | |
416 | 450 | writel(BM_USBPHY_CTRL_CLKGATE, |
417 | 451 | x->io_priv + HW_USBPHY_CTRL_CLR); |
418 | 452 | writel(0, x->io_priv + HW_USBPHY_PWD); |
... | ... | @@ -593,6 +627,19 @@ |
593 | 627 | } |
594 | 628 | if (mxs_phy->phy_3p0) |
595 | 629 | regulator_set_voltage(mxs_phy->phy_3p0, 3200000, 3200000); |
630 | + | |
631 | + if (mxs_phy->data->flags & MXS_PHY_HARDWARE_CONTROL_PHY2_CLK) | |
632 | + mxs_phy->hardware_control_phy2_clk = true; | |
633 | + | |
634 | + if (of_find_property(np, "tx-d-cal", NULL)) { | |
635 | + ret = of_property_read_u32(np, "tx-d-cal", | |
636 | + &mxs_phy->tx_d_cal); | |
637 | + if (ret) { | |
638 | + dev_err(&pdev->dev, | |
639 | + "failed to get tx-d-cal value\n"); | |
640 | + return ret; | |
641 | + } | |
642 | + } | |
596 | 643 | |
597 | 644 | platform_set_drvdata(pdev, mxs_phy); |
598 | 645 |
include/linux/usb/chipidea.h
... | ... | @@ -38,7 +38,7 @@ |
38 | 38 | enum usb_dr_mode dr_mode; |
39 | 39 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 |
40 | 40 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 |
41 | -#define CI_HDRC_CONTROLLER_VBUS_EVENT 2 | |
41 | +#define CI_HDRC_CONTROLLER_CHARGER_EVENT 2 | |
42 | 42 | #define CI_HDRC_CONTROLLER_CHARGER_POST_EVENT 3 |
43 | 43 | #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 4 |
44 | 44 | #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 5 |
sound/soc/fsl/fsl_sai.c
... | ... | @@ -10,13 +10,16 @@ |
10 | 10 | * |
11 | 11 | */ |
12 | 12 | |
13 | +#include <linux/busfreq-imx6.h> | |
13 | 14 | #include <linux/clk.h> |
14 | 15 | #include <linux/delay.h> |
15 | 16 | #include <linux/dmaengine.h> |
16 | 17 | #include <linux/module.h> |
17 | 18 | #include <linux/of_address.h> |
19 | +#include <linux/pm_runtime.h> | |
18 | 20 | #include <linux/regmap.h> |
19 | 21 | #include <linux/slab.h> |
22 | + | |
20 | 23 | #include <sound/core.h> |
21 | 24 | #include <sound/dmaengine_pcm.h> |
22 | 25 | #include <sound/pcm_params.h> |
... | ... | @@ -27,6 +30,17 @@ |
27 | 30 | #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\ |
28 | 31 | FSL_SAI_CSR_FEIE) |
29 | 32 | |
33 | +static u32 fsl_sai_rates[] = { | |
34 | + 8000, 11025, 12000, 16000, 22050, | |
35 | + 24000, 32000, 44100, 48000, 64000, | |
36 | + 88200, 96000, | |
37 | +}; | |
38 | + | |
39 | +static struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = { | |
40 | + .count = ARRAY_SIZE(fsl_sai_rates), | |
41 | + .list = fsl_sai_rates, | |
42 | +}; | |
43 | + | |
30 | 44 | static irqreturn_t fsl_sai_isr(int irq, void *devid) |
31 | 45 | { |
32 | 46 | struct fsl_sai *sai = (struct fsl_sai *)devid; |
... | ... | @@ -459,6 +473,7 @@ |
459 | 473 | case SNDRV_PCM_TRIGGER_START: |
460 | 474 | case SNDRV_PCM_TRIGGER_RESUME: |
461 | 475 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
476 | + pm_runtime_get_sync(cpu_dai->dev); | |
462 | 477 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), |
463 | 478 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); |
464 | 479 | |
... | ... | @@ -510,6 +525,7 @@ |
510 | 525 | regmap_write(sai->regmap, FSL_SAI_TCSR, 0); |
511 | 526 | regmap_write(sai->regmap, FSL_SAI_RCSR, 0); |
512 | 527 | } |
528 | + pm_runtime_put_sync(cpu_dai->dev); | |
513 | 529 | break; |
514 | 530 | default: |
515 | 531 | return -EINVAL; |
... | ... | @@ -538,7 +554,10 @@ |
538 | 554 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, |
539 | 555 | FSL_SAI_CR3_TRCE); |
540 | 556 | |
541 | - return 0; | |
557 | + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, | |
558 | + SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints); | |
559 | + | |
560 | + return ret; | |
542 | 561 | } |
543 | 562 | |
544 | 563 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, |
545 | 564 | |
... | ... | @@ -587,13 +606,17 @@ |
587 | 606 | .playback = { |
588 | 607 | .channels_min = 1, |
589 | 608 | .channels_max = 2, |
590 | - .rates = SNDRV_PCM_RATE_8000_96000, | |
609 | + .rate_min = 8000, | |
610 | + .rate_max = 96000, | |
611 | + .rates = SNDRV_PCM_RATE_KNOT, | |
591 | 612 | .formats = FSL_SAI_FORMATS, |
592 | 613 | }, |
593 | 614 | .capture = { |
594 | 615 | .channels_min = 1, |
595 | 616 | .channels_max = 2, |
596 | - .rates = SNDRV_PCM_RATE_8000_96000, | |
617 | + .rate_min = 8000, | |
618 | + .rate_max = 96000, | |
619 | + .rates = SNDRV_PCM_RATE_KNOT, | |
597 | 620 | .formats = FSL_SAI_FORMATS, |
598 | 621 | }, |
599 | 622 | .ops = &fsl_sai_pcm_dai_ops, |
... | ... | @@ -789,6 +812,8 @@ |
789 | 812 | |
790 | 813 | platform_set_drvdata(pdev, sai); |
791 | 814 | |
815 | + pm_runtime_enable(&pdev->dev); | |
816 | + | |
792 | 817 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, |
793 | 818 | &fsl_sai_dai, 1); |
794 | 819 | if (ret) |
... | ... | @@ -808,6 +833,20 @@ |
808 | 833 | { /* sentinel */ } |
809 | 834 | }; |
810 | 835 | |
836 | +#ifdef CONFIG_PM_RUNTIME | |
837 | +static int fsl_sai_runtime_resume(struct device *dev) | |
838 | +{ | |
839 | + request_bus_freq(BUS_FREQ_AUDIO); | |
840 | + return 0; | |
841 | +} | |
842 | + | |
843 | +static int fsl_sai_runtime_suspend(struct device *dev) | |
844 | +{ | |
845 | + release_bus_freq(BUS_FREQ_AUDIO); | |
846 | + return 0; | |
847 | +} | |
848 | +#endif | |
849 | + | |
811 | 850 | #if CONFIG_PM_SLEEP |
812 | 851 | static int fsl_sai_suspend(struct device *dev) |
813 | 852 | { |
... | ... | @@ -834,6 +873,9 @@ |
834 | 873 | #endif /* CONFIG_PM_SLEEP */ |
835 | 874 | |
836 | 875 | static const struct dev_pm_ops fsl_sai_pm_ops = { |
876 | + SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend, | |
877 | + fsl_sai_runtime_resume, | |
878 | + NULL) | |
837 | 879 | SET_SYSTEM_SLEEP_PM_OPS(fsl_sai_suspend, fsl_sai_resume) |
838 | 880 | }; |
839 | 881 |
sound/soc/fsl/fsl_ssi.c
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | * |
4 | 4 | * Author: Timur Tabi <timur@freescale.com> |
5 | 5 | * |
6 | - * Copyright (C) 2007-2014 Freescale Semiconductor, Inc. | |
6 | + * Copyright (C) 2007-2015 Freescale Semiconductor, Inc. | |
7 | 7 | * |
8 | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | 9 | * version 2. This program is licensed "as is" without any warranty of any |
... | ... | @@ -356,8 +356,6 @@ |
356 | 356 | unsigned long flags; |
357 | 357 | |
358 | 358 | if (ssi_private->ssi_on_imx) { |
359 | - pm_runtime_get_sync(dai->dev); | |
360 | - | |
361 | 359 | clk_prepare_enable(ssi_private->coreclk); |
362 | 360 | |
363 | 361 | /* When using dual fifo mode, it would be safer if we ensure |
... | ... | @@ -572,6 +570,7 @@ |
572 | 570 | case SNDRV_PCM_TRIGGER_START: |
573 | 571 | case SNDRV_PCM_TRIGGER_RESUME: |
574 | 572 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
573 | + pm_runtime_get_sync(dai->dev); | |
575 | 574 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
576 | 575 | write_ssi_mask(&ssi->scr, 0, |
577 | 576 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); |
... | ... | @@ -600,6 +599,7 @@ |
600 | 599 | ssi_private->baudclk_locked = false; |
601 | 600 | spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); |
602 | 601 | } |
602 | + pm_runtime_put_sync(dai->dev); | |
603 | 603 | break; |
604 | 604 | |
605 | 605 | default: |
606 | 606 | |
... | ... | @@ -876,11 +876,8 @@ |
876 | 876 | write_ssi_mask(&ssi->sier, SIER_FLAGS, 0); |
877 | 877 | } |
878 | 878 | |
879 | - if (ssi_private->ssi_on_imx) { | |
879 | + if (ssi_private->ssi_on_imx) | |
880 | 880 | clk_disable_unprepare(ssi_private->coreclk); |
881 | - | |
882 | - pm_runtime_put_sync(dai->dev); | |
883 | - } | |
884 | 881 | } |
885 | 882 | |
886 | 883 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |