[RFC PATCH 0/3] PCI: rockchip: Move PCIE_WAKE handling into rockchip pcie driver
Currently we are handling pcie wake in mrvl wifi driver. But Brian suggests to move it into rockchip pcie driver. Tested on my chromebook bob(with cros 4.4 kernel and mrvl wifi). Jeffy Chen (3): PCI: rockchip: Add support for pcie wake irq dt-bindings: PCI: rockchip: Add support for pcie wake irq arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru .../devicetree/bindings/pci/rockchip-pcie.txt | 11 ++-- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 17 --- drivers/pci/host/pcie-rockchip.c | 58 ++ 3 files changed, 76 insertions(+), 10 deletions(-) -- 2.11.0
[RFC PATCH 1/3] PCI: rockchip: Add support for pcie wake irq
Add support for PCIE_WAKE pin in rockchip pcie driver. Signed-off-by: Jeffy Chen --- drivers/pci/host/pcie-rockchip.c | 58 1 file changed, 58 insertions(+) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 7bb9870f6d8c..f969a6d3cd85 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -38,6 +38,7 @@ #include #include #include +#include /* * The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16 @@ -226,6 +227,8 @@ struct rockchip_pcie { struct regulator *vpcie1v8; /* 1.8V power supply */ struct regulator *vpcie0v9; /* 0.9V power supply */ struct gpio_desc *ep_gpio; + int wake_irq; + boolwake_by_pcie; u32 lanes; u8 root_bus_nr; int link_gen; @@ -853,6 +856,20 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static irqreturn_t rockchip_pcie_wake_irq_handler(int irq, void *arg) +{ + struct rockchip_pcie *rockchip = arg; + + rockchip->wake_by_pcie = true; + + disable_irq_nosync(rockchip->wake_irq); + disable_irq_wake(rockchip->wake_irq); + + pm_wakeup_event(rockchip->dev, 0); + pm_system_wakeup(); + + return IRQ_HANDLED; +} /** * rockchip_pcie_parse_dt - Parse Device Tree @@ -868,6 +885,7 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) struct resource *regs; int irq; int err; + bool wakeup = 0; regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -1018,6 +1036,21 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) return err; } + rockchip->wake_irq = platform_get_irq_byname(pdev, "wake"); + if (rockchip->wake_irq >= 0) { + err = devm_request_irq(dev, rockchip->wake_irq, + rockchip_pcie_wake_irq_handler, + 0, "pcie-wake", rockchip); + if (err) { + dev_err(dev, "failed to request PCIe wake IRQ\n"); + return err; + } + + disable_irq(rockchip->wake_irq); + wakeup = device_property_read_bool(dev, "wakeup-source"); + } + device_init_wakeup(dev, wakeup); + rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); if (IS_ERR(rockchip->vpcie3v3)) { if (PTR_ERR(rockchip->vpcie3v3) == -EPROBE_DEFER) @@ -1270,6 +1303,30 @@ static int rockchip_pcie_wait_l2(struct rockchip_pcie *rockchip) return 0; } +static int __maybe_unused rockchip_pcie_suspend(struct device *dev) +{ + struct rockchip_pcie *rockchip = dev_get_drvdata(dev); + + rockchip->wake_by_pcie = false; + + if (device_may_wakeup(dev)) { + enable_irq_wake(rockchip->wake_irq); + enable_irq(rockchip->wake_irq); + } + return 0; +} + +static int __maybe_unused rockchip_pcie_resume(struct device *dev) +{ + struct rockchip_pcie *rockchip = dev_get_drvdata(dev); + + if (device_may_wakeup(dev) && !rockchip->wake_by_pcie) { + disable_irq(rockchip->wake_irq); + disable_irq_wake(rockchip->wake_irq); + } + return 0; +} + static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) { struct rockchip_pcie *rockchip = dev_get_drvdata(dev); @@ -1548,6 +1605,7 @@ static int rockchip_pcie_remove(struct platform_device *pdev) } static const struct dev_pm_ops rockchip_pcie_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(rockchip_pcie_suspend, rockchip_pcie_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_pcie_suspend_noirq, rockchip_pcie_resume_noirq) }; -- 2.11.0
[RFC PATCH 2/3] dt-bindings: PCI: rockchip: Add support for pcie wake irq
Add an optional interrupt for PCIE_WAKE pin. Signed-off-by: Jeffy Chen --- Documentation/devicetree/bindings/pci/rockchip-pcie.txt | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt index 1453a734c2f5..6ef9903567db 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt +++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt @@ -22,10 +22,13 @@ Required properties: - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. - phy-names: MUST be "pcie-phy". - interrupts: Three interrupt entries must be specified. -- interrupt-names: Must include the following names - - "sys" - - "legacy" - - "client" +- interrupt-names: Include the following names + Required: + - "sys" + - "legacy" + - "client" + Optional: + - "wake" - resets: Must contain seven entries for each entry in reset-names. See ../reset/reset.txt for details. - reset-names: Must include the following names -- 2.11.0
[RFC PATCH 3/3] arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru
Currently we are handling pcie wake irq in mrvl wifi driver. Move it to rockchip pcie driver for Gru boards. Signed-off-by: Jeffy Chen --- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index d48e98b62d09..7a5e1517a496 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -712,11 +712,21 @@ ap_i2c_audio: &i2c8 { ep-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqn_cpm>, <&wifi_perst_l>; + pinctrl-0 = <&pcie_clkreqn_cpm>, <&wlan_host_wake_l>, <&wifi_perst_l>; + + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wake"; + /delete-property/ interrupts; + vpcie3v3-supply = <&pp3300_wifi_bt>; vpcie1v8-supply = <&wlan_pd_n>; /* HACK: see &wlan_pd_n */ vpcie0v9-supply = <&pp900_pcie>; + wakeup-source; + pci_rootport: pcie@0,0 { reg = <0x8300 0x0 0x 0x0 0x>; #address-cells = <3>; @@ -727,11 +737,6 @@ ap_i2c_audio: &i2c8 { compatible = "pci1b4b,2b42"; reg = <0x8301 0x0 0x 0x0 0x0010 0x8301 0x0 0x0010 0x0 0x0010>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&wlan_host_wake_l>; - wakeup-source; }; }; }; -- 2.11.0
[PATCH] arm64: dts: rockchip: Assign mic irq to correct device for Gru
Currently we are assigning mic irq to rt5514 i2c driver, which is wrong. Assign it to rt5514 spi driver instead. Signed-off-by: Jeffy Chen --- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index d48e98b62d09..d7723a77ae03 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -612,12 +612,8 @@ ap_i2c_mic: &i2c1 { headsetcodec: rt5514@57 { compatible = "realtek,rt5514"; reg = <0x57>; - interrupt-parent = <&gpio1>; - interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&mic_int>; + realtek,dmic-init-delay = <20>; - wakeup-source; }; }; @@ -826,9 +822,13 @@ ap_i2c_audio: &i2c8 { wacky_spi_audio: spi2@0 { compatible = "realtek,rt5514"; reg = <0>; - + interrupt-parent = <&gpio1>; + interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mic_int>; /* May run faster once verified. */ spi-max-frequency = <1000>; + wakeup-source; }; }; -- 2.11.0
[PATCH v3 0/9] ASoC: rockchip: Parse dai links from dts
Currently we are using a fixed list of dai links in the driver. This serial of patches would let the driver parse dai links from dts, so that we can make some of them optional for future boards. Tested on my chromebook bob(with cros 4.4 kernel), it still works after disabled rt5514 codecs in the dts. Changes in v3: Use compatible to match audio codecs -- Suggested-by Matthias Kaehlcke Changes in v2: Let rockchip,codec-names be a required property, because we plan to add more supported codecs to the fixed dai link list in the driver. Jeffy Chen (9): ASoC: rt5514: Switch to snd_soc_register_codec ASoC: rockchip: Remove obsolete dmic-delay ASoC: rockchip: Use codec of_node and dai_name for rt5514 dsp arm64: dts: rockchip: Add rt5514 dsp for Gru arm64: dts: rockchip: Update rt5514 devices' compatible for Gru ASoC: rockchip: Parse dai links from dts ASoC: rockchip: Add support for DP codec ASoC: rockchip: Add support for DMIC codec dt-bindings: ASoC: rockchip: Update description of rockchip,codec .../bindings/sound/rockchip,rk3399-gru-sound.txt | 9 +- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 7 +- sound/soc/codecs/rt5514-spi.c | 19 +- sound/soc/rockchip/Kconfig | 2 + sound/soc/rockchip/rk3399_gru_sound.c | 263 ++--- 5 files changed, 196 insertions(+), 104 deletions(-) -- 2.11.0
[PATCH v3 1/9] ASoC: rt5514: Switch to snd_soc_register_codec
Currently we are using devm_snd_soc_register_component, which would use legacy dai name. Switch to snd_soc_register_codec to use dai driver name. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None sound/soc/codecs/rt5514-spi.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 640193d845be..ad6bc51dd82a 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -277,8 +277,10 @@ static struct snd_soc_platform_driver rt5514_spi_platform = { .ops = &rt5514_spi_pcm_ops, }; -static const struct snd_soc_component_driver rt5514_spi_dai_component = { - .name = "rt5514-spi-dai", +static const struct snd_soc_codec_driver rt5514_spi_dai_codec = { + .component_driver = { + .name = "rt5514-spi-dai", + }, }; /** @@ -426,9 +428,8 @@ static int rt5514_spi_probe(struct spi_device *spi) return ret; } - ret = devm_snd_soc_register_component(&spi->dev, - &rt5514_spi_dai_component, - &rt5514_spi_dai, 1); + ret = snd_soc_register_codec(&spi->dev, &rt5514_spi_dai_codec, +&rt5514_spi_dai, 1); if (ret < 0) { dev_err(&spi->dev, "Failed to register component.\n"); return ret; @@ -437,6 +438,13 @@ static int rt5514_spi_probe(struct spi_device *spi) return 0; } +static int rt5514_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + + return 0; +} + static const struct of_device_id rt5514_of_match[] = { { .compatible = "realtek,rt5514", }, {}, @@ -449,6 +457,7 @@ static struct spi_driver rt5514_spi_driver = { .of_match_table = of_match_ptr(rt5514_of_match), }, .probe = rt5514_spi_probe, + .remove = rt5514_spi_remove, }; module_spi_driver(rt5514_spi_driver); -- 2.11.0
[PATCH v3 2/9] ASoC: rockchip: Remove obsolete dmic-delay
This property is no longer used. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None .../bindings/sound/rockchip,rk3399-gru-sound.txt | 7 --- sound/soc/rockchip/rk3399_gru_sound.c | 14 -- 2 files changed, 21 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt index eac91db07178..f19b6c830a34 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -6,17 +6,10 @@ Required properties: connected to the codecs - rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs -Optional properties: -- dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready. - If this option is specified, which means it's required dmic need - delay for DMIC to ready so that rt5514 can avoid recording before - DMIC send valid data - Example: sound { compatible = "rockchip,rk3399-gru-sound"; rockchip,cpu = <&i2s0>; rockchip,codec = <&max98357a &rt5514 &da7219>; - dmic-wakeup-delay-ms = <20>; }; diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 3475c61a5fa0..70876d3c34e6 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -38,8 +38,6 @@ #define SOUND_FS 256 -static unsigned int rt5514_dmic_delay; - static struct snd_soc_jack rockchip_sound_jack; static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { @@ -125,9 +123,6 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, return ret; } - /* Wait for DMIC stable */ - msleep(rt5514_dmic_delay); - return 0; } @@ -348,15 +343,6 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -ENODEV; } - /* Set DMIC delay */ - ret = device_property_read_u32(&pdev->dev, "dmic-delay", - &rt5514_dmic_delay); - if (ret) { - rt5514_dmic_delay = 0; - dev_dbg(&pdev->dev, - "no optional property 'dmic-delay' found, default: no delay\n"); - } - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); -- 2.11.0
[PATCH v3 3/9] ASoC: rockchip: Use codec of_node and dai_name for rt5514 dsp
Currently we are using codec name for rt5514 dsp dai link, use codec of_node instead. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None sound/soc/rockchip/rk3399_gru_sound.c | 34 ++ 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 70876d3c34e6..9b7e28703bfb 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -242,8 +242,6 @@ enum { DAILINK_RT5514_DSP, }; -#define DAILINK_ENTITIES (DAILINK_DA7219 + 1) - static struct snd_soc_dai_link rockchip_dailinks[] = { [DAILINK_MAX98357A] = { .name = "MAX98357A", @@ -277,8 +275,7 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { [DAILINK_RT5514_DSP] = { .name = "RT5514 DSP", .stream_name = "Wake on Voice", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", + .codec_dai_name = "rt5514-dsp-cpu-dai", }, }; @@ -295,17 +292,10 @@ static struct snd_soc_card rockchip_sound_card = { .num_controls = ARRAY_SIZE(rockchip_controls), }; -static int rockchip_sound_match_stub(struct device *dev, void *data) -{ - return 1; -} - static int rockchip_sound_probe(struct platform_device *pdev) { struct snd_soc_card *card = &rockchip_sound_card; struct device_node *cpu_node; - struct device *dev; - struct device_driver *drv; int i, ret; cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); @@ -314,7 +304,7 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -EINVAL; } - for (i = 0; i < DAILINK_ENTITIES; i++) { + for (i = 0; i < ARRAY_SIZE(rockchip_dailinks); i++) { rockchip_dailinks[i].platform_of_node = cpu_node; rockchip_dailinks[i].cpu_of_node = cpu_node; @@ -327,26 +317,6 @@ static int rockchip_sound_probe(struct platform_device *pdev) } } - /** -* To acquire the spi driver of the rt5514 and set the dai-links names -* for soc_bind_dai_link -*/ - drv = driver_find("rt5514", &spi_bus_type); - if (!drv) { - dev_err(&pdev->dev, "Can not find the rt5514 driver at the spi bus\n"); - return -EINVAL; - } - - dev = driver_find_device(drv, NULL, NULL, rockchip_sound_match_stub); - if (!dev) { - dev_err(&pdev->dev, "Can not find the rt5514 device\n"); - return -ENODEV; - } - - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - card->dev = &pdev->dev; platform_set_drvdata(pdev, card); -- 2.11.0
[PATCH v3 5/9] arm64: dts: rockchip: Update rt5514 devices' compatible for Gru
Currently the rt5514 i2c driver and rt5514 spi driver are using the same compatible string. Add additional unused compatible strings to identify them for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 2713129722a1..275ccf64dfb9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -611,7 +611,7 @@ ap_i2c_mic: &i2c1 { i2c-scl-rising-time-ns = <300>; headsetcodec: rt5514@57 { - compatible = "realtek,rt5514"; + compatible = "realtek,rt5514", "realtek,rt5514-i2c"; reg = <0x57>; interrupt-parent = <&gpio1>; interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; @@ -825,7 +825,7 @@ ap_i2c_audio: &i2c8 { status = "okay"; wacky_spi_audio: spi2@0 { - compatible = "realtek,rt5514"; + compatible = "realtek,rt5514", "realtek,rt5514-spi"; reg = <0>; /* May run faster once verified. */ -- 2.11.0
[PATCH v3 7/9] ASoC: rockchip: Add support for DP codec
Add support for optional cdn dp codec. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None sound/soc/rockchip/Kconfig| 1 + sound/soc/rockchip/rk3399_gru_sound.c | 59 +-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index c84487805876..8f0d0d8d34e6 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -68,6 +68,7 @@ config SND_SOC_RK3399_GRU_SOUND select SND_SOC_RT5514 select SND_SOC_DA7219 select SND_SOC_RT5514_SPI + select SND_SOC_HDMI_CODEC help Say Y or M here if you want to add support multiple codecs for SoC audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index d532336871d7..8ffae1934b94 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -223,6 +223,45 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int mclk, ret; + + /* in bypass mode, the mclk has to be one of the frequencies below */ + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 32000: + case 48000: + case 64000: + case 96000: + mclk = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + default: + return -EINVAL; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, +SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret); + return ret; + } + + return 0; +} + static const struct snd_soc_ops rockchip_sound_max98357a_ops = { .hw_params = rockchip_sound_max98357a_hw_params, }; @@ -235,6 +274,10 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = { .hw_params = rockchip_sound_da7219_hw_params, }; +static struct snd_soc_ops rockchip_sound_cdndp_ops = { + .hw_params = rockchip_sound_cdndp_hw_params, +}; + static struct snd_soc_card rockchip_sound_card = { .name = "rk3399-gru-sound", .owner = THIS_MODULE, @@ -247,6 +290,7 @@ static struct snd_soc_card rockchip_sound_card = { }; enum { + DAILINK_CDNDP, DAILINK_DA7219, DAILINK_MAX98357A, DAILINK_RT5514, @@ -254,6 +298,7 @@ enum { }; static const char * const dailink_compat[] = { + [DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp", [DAILINK_DA7219] = "dlg,da7219", [DAILINK_MAX98357A] = "maxim,max98357a", [DAILINK_RT5514] = "realtek,rt5514-i2c", @@ -261,6 +306,14 @@ static const char * const dailink_compat[] = { }; static const struct snd_soc_dai_link rockchip_dais[] = { + [DAILINK_CDNDP] = { + .name = "DP", + .stream_name = "DP PCM", + .codec_dai_name = "i2s-hifi", + .ops = &rockchip_sound_cdndp_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_DA7219] = { .name = "DA7219", .stream_name = "DA7219 PCM", @@ -311,7 +364,7 @@ static int rockchip_sound_codec_node_match(struct device_node *np_codec) static int rockchip_sound_of_parse_dais(struct device *dev, struct snd_soc_card *card) { - struct device_node *np_cpu; + struct device_node *np_cpu, *np_cpu0, *np_cpu1; struct device_node *np_codec; struct snd_soc_dai_link *dai; int i, index; @@ -321,7 +374,8 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (!card->dai_link) return -ENOMEM; - np_cpu = of_parse_phandle(dev->of_node, "rockchip,cpu", 0); + np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0); + np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1); card->num_links = 0; for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) { @@ -337,6 +391,7 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (index < 0)
[PATCH v3 4/9] arm64: dts: rockchip: Add rt5514 dsp for Gru
Add rt5514 dsp of_node to codec list for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index d48e98b62d09..2713129722a1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -514,7 +514,8 @@ sound { compatible = "rockchip,rk3399-gru-sound"; rockchip,cpu = <&i2s0 &i2s2>; - rockchip,codec = <&max98357a &headsetcodec &codec>; + rockchip,codec = <&max98357a &headsetcodec + &codec &wacky_spi_audio>; }; }; -- 2.11.0
[PATCH v3 8/9] ASoC: rockchip: Add support for DMIC codec
Add support for optional dmic codec. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None sound/soc/rockchip/Kconfig| 1 + sound/soc/rockchip/rk3399_gru_sound.c | 33 + 2 files changed, 34 insertions(+) diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index 8f0d0d8d34e6..b0825370d262 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -69,6 +69,7 @@ config SND_SOC_RK3399_GRU_SOUND select SND_SOC_DA7219 select SND_SOC_RT5514_SPI select SND_SOC_HDMI_CODEC + select SND_SOC_DMIC help Say Y or M here if you want to add support multiple codecs for SoC audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 8ffae1934b94..0be3e5c1386f 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -262,6 +262,25 @@ static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream, return 0; } +static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int mclk; + int ret; + + mclk = params_rate(params) * SOUND_FS; + + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0); + if (ret) { + dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", + __func__, mclk, ret); + return ret; + } + + return 0; +} + static const struct snd_soc_ops rockchip_sound_max98357a_ops = { .hw_params = rockchip_sound_max98357a_hw_params, }; @@ -278,6 +297,10 @@ static struct snd_soc_ops rockchip_sound_cdndp_ops = { .hw_params = rockchip_sound_cdndp_hw_params, }; +static struct snd_soc_ops rockchip_sound_dmic_ops = { + .hw_params = rockchip_sound_dmic_hw_params, +}; + static struct snd_soc_card rockchip_sound_card = { .name = "rk3399-gru-sound", .owner = THIS_MODULE, @@ -292,6 +315,7 @@ static struct snd_soc_card rockchip_sound_card = { enum { DAILINK_CDNDP, DAILINK_DA7219, + DAILINK_DMIC, DAILINK_MAX98357A, DAILINK_RT5514, DAILINK_RT5514_DSP, @@ -300,6 +324,7 @@ enum { static const char * const dailink_compat[] = { [DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp", [DAILINK_DA7219] = "dlg,da7219", + [DAILINK_DMIC] = "dmic-codec", [DAILINK_MAX98357A] = "maxim,max98357a", [DAILINK_RT5514] = "realtek,rt5514-i2c", [DAILINK_RT5514_DSP] = "realtek,rt5514-spi", @@ -324,6 +349,14 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, }, + [DAILINK_DMIC] = { + .name = "DMIC", + .stream_name = "DMIC PCM", + .codec_dai_name = "dmic-hifi", + .ops = &rockchip_sound_dmic_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_MAX98357A] = { .name = "MAX98357A", .stream_name = "MAX98357A PCM", -- 2.11.0
[PATCH v3 9/9] dt-bindings: ASoC: rockchip: Update description of rockchip,codec
Update description for newly added optional audio codecs. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt index f19b6c830a34..f54b4e91e97c 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -4,7 +4,7 @@ Required properties: - compatible: "rockchip,rk3399-gru-sound" - rockchip,cpu: The phandle of the Rockchip I2S controller that's connected to the codecs -- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs +- rockchip,codec: The phandle of the audio codecs Example: -- 2.11.0
[PATCH v3 6/9] ASoC: rockchip: Parse dai links from dts
Refactor rockchip_sound_probe, parse dai links from dts instead of hard coding them. Signed-off-by: Jeffy Chen --- Changes in v3: Use compatible to match audio codecs -- Suggested-by Matthias Kaehlcke Changes in v2: Let rockchip,codec-names be a required property, because we plan to add more supported codecs to the fixed dai link list in the driver. sound/soc/rockchip/rk3399_gru_sound.c | 139 ++ 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 9b7e28703bfb..d532336871d7 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -235,14 +235,42 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = { .hw_params = rockchip_sound_da7219_hw_params, }; +static struct snd_soc_card rockchip_sound_card = { + .name = "rk3399-gru-sound", + .owner = THIS_MODULE, + .dapm_widgets = rockchip_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets), + .dapm_routes = rockchip_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes), + .controls = rockchip_controls, + .num_controls = ARRAY_SIZE(rockchip_controls), +}; + enum { + DAILINK_DA7219, DAILINK_MAX98357A, DAILINK_RT5514, - DAILINK_DA7219, DAILINK_RT5514_DSP, }; -static struct snd_soc_dai_link rockchip_dailinks[] = { +static const char * const dailink_compat[] = { + [DAILINK_DA7219] = "dlg,da7219", + [DAILINK_MAX98357A] = "maxim,max98357a", + [DAILINK_RT5514] = "realtek,rt5514-i2c", + [DAILINK_RT5514_DSP] = "realtek,rt5514-spi", +}; + +static const struct snd_soc_dai_link rockchip_dais[] = { + [DAILINK_DA7219] = { + .name = "DA7219", + .stream_name = "DA7219 PCM", + .codec_dai_name = "da7219-hifi", + .init = rockchip_sound_da7219_init, + .ops = &rockchip_sound_da7219_ops, + /* set da7219 as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_MAX98357A] = { .name = "MAX98357A", .stream_name = "MAX98357A PCM", @@ -261,16 +289,6 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, }, - [DAILINK_DA7219] = { - .name = "DA7219", - .stream_name = "DA7219 PCM", - .codec_dai_name = "da7219-hifi", - .init = rockchip_sound_da7219_init, - .ops = &rockchip_sound_da7219_ops, - /* set da7219 as slave */ - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - }, /* RT5514 DSP for voice wakeup via spi bus */ [DAILINK_RT5514_DSP] = { .name = "RT5514 DSP", @@ -279,53 +297,78 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { }, }; -static struct snd_soc_card rockchip_sound_card = { - .name = "rk3399-gru-sound", - .owner = THIS_MODULE, - .dai_link = rockchip_dailinks, - .num_links = ARRAY_SIZE(rockchip_dailinks), - .dapm_widgets = rockchip_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets), - .dapm_routes = rockchip_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes), - .controls = rockchip_controls, - .num_controls = ARRAY_SIZE(rockchip_controls), -}; - -static int rockchip_sound_probe(struct platform_device *pdev) +static int rockchip_sound_codec_node_match(struct device_node *np_codec) { - struct snd_soc_card *card = &rockchip_sound_card; - struct device_node *cpu_node; - int i, ret; + int i; - cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); - if (!cpu_node) { - dev_err(&pdev->dev, "Property 'rockchip,cpu' missing or invalid\n"); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(dailink_compat); i++) { + if (of_device_is_compatible(np_codec, dailink_compat[i])) + return i; } + return -1; +} - for (i = 0; i < ARRAY_SIZE(rockchip_dailinks); i++) { - rockchip_dailinks[i].platform_of_node = cpu_node; - rockchip_dailinks[i].cpu_of_node = cpu_node; - - rockchip_dailinks[i].codec_of_node = - of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i); - if (!rockch
[RFC PATCH v2 2/3] dt-bindings: PCI: rockchip: Add support for pcie wake irq
Add an optional interrupt for PCIE_WAKE pin. Signed-off-by: Jeffy Chen --- Changes in v2: None .../devicetree/bindings/pci/rockchip-pcie.txt| 20 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt index 1453a734c2f5..edd779f842fa 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt +++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt @@ -22,10 +22,13 @@ Required properties: - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. - phy-names: MUST be "pcie-phy". - interrupts: Three interrupt entries must be specified. -- interrupt-names: Must include the following names - - "sys" - - "legacy" - - "client" +- interrupt-names: Include the following names + Required: + - "sys" + - "legacy" + - "client" + Optional: + - "wake" - resets: Must contain seven entries for each entry in reset-names. See ../reset/reset.txt for details. - reset-names: Must include the following names @@ -76,10 +79,11 @@ pcie0: pcie@f800 { clock-names = "aclk", "aclk-perf", "hclk", "pm"; bus-range = <0x0 0x1>; - interrupts = , -, -; - interrupt-names = "sys", "legacy", "client"; + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wake"; assigned-clocks = <&cru SCLK_PCIEPHY_REF>; assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; assigned-clock-rates = <1>; -- 2.11.0
[RFC PATCH v2 3/3] arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru
Currently we are handling pcie wake irq in mrvl wifi driver. Move it to rockchip pcie driver for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index d48e98b62d09..42158512e979 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -712,7 +712,15 @@ ap_i2c_audio: &i2c8 { ep-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqn_cpm>, <&wifi_perst_l>; + pinctrl-0 = <&pcie_clkreqn_cpm>, <&wlan_host_wake_l>, <&wifi_perst_l>; + + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wake"; + /delete-property/ interrupts; + vpcie3v3-supply = <&pp3300_wifi_bt>; vpcie1v8-supply = <&wlan_pd_n>; /* HACK: see &wlan_pd_n */ vpcie0v9-supply = <&pp900_pcie>; @@ -727,11 +735,6 @@ ap_i2c_audio: &i2c8 { compatible = "pci1b4b,2b42"; reg = <0x8301 0x0 0x 0x0 0x0010 0x8301 0x0 0x0010 0x0 0x0010>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&wlan_host_wake_l>; - wakeup-source; }; }; }; -- 2.11.0
[RFC PATCH v2 0/3] PCI: rockchip: Move PCIE_WAKE handling into rockchip pcie driver
Currently we are handling pcie wake in mrvl wifi driver. But Brian suggests to move it into rockchip pcie driver. Tested on my chromebook bob(with cros 4.4 kernel and mrvl wifi). Changes in v2: Use dev_pm_set_dedicated_wake_irq -- Suggested by Brian Norris Jeffy Chen (3): PCI: rockchip: Add support for pcie wake irq dt-bindings: PCI: rockchip: Add support for pcie wake irq arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru .../devicetree/bindings/pci/rockchip-pcie.txt| 20 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 +-- drivers/pci/host/pcie-rockchip.c | 13 - 3 files changed, 33 insertions(+), 15 deletions(-) -- 2.11.0
[RFC PATCH v2 1/3] PCI: rockchip: Add support for pcie wake irq
Add support for PCIE_WAKE pin in rockchip pcie driver. Signed-off-by: Jeffy Chen --- Changes in v2: Use dev_pm_set_dedicated_wake_irq -- Suggested by Brian Norris drivers/pci/host/pcie-rockchip.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 7bb9870f6d8c..c2b973c738fe 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -853,7 +854,6 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } - /** * rockchip_pcie_parse_dt - Parse Device Tree * @rockchip: PCIe port information @@ -1018,6 +1018,14 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) return err; } + device_init_wakeup(dev, true); + irq = platform_get_irq_byname(pdev, "wake"); + if (irq >= 0) { + err = dev_pm_set_dedicated_wake_irq(dev, irq); + if (err) + dev_err(dev, "failed to setup PCIe wake IRQ\n"); + } + rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); if (IS_ERR(rockchip->vpcie3v3)) { if (PTR_ERR(rockchip->vpcie3v3) == -EPROBE_DEFER) @@ -1524,6 +1532,9 @@ static int rockchip_pcie_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rockchip_pcie *rockchip = dev_get_drvdata(dev); + dev_pm_clear_wake_irq(dev); + device_init_wakeup(dev, false); + pci_stop_root_bus(rockchip->root_bus); pci_remove_root_bus(rockchip->root_bus); pci_unmap_iospace(rockchip->io); -- 2.11.0
[PATCH v4 0/9] ASoC: rockchip: Parse dai links from dts
Currently we are using a fixed list of dai links in the driver. This serial of patches would let the driver parse dai links from dts, so that we can make some of them optional for future boards. Tested on my chromebook bob(with cros 4.4 kernel), it still works after disabled rt5514 codecs in the dts. Changes in v4: Use non-zero drv id to avoid legacy dai naming instead of switching to snd_soc_register_codec. Changes in v3: Use compatible to match audio codecs -- Suggested-by Matthias Kaehlcke Changes in v2: Let rockchip,codec-names be a required property, because we plan to add more supported codecs to the fixed dai link list in the driver. Jeffy Chen (9): ASoC: rt5514: Avoid legacy dai naming ASoC: rockchip: Remove obsolete dmic-delay ASoC: rockchip: Use codec of_node and dai_name for rt5514 dsp arm64: dts: rockchip: Add rt5514 dsp for Gru arm64: dts: rockchip: Update rt5514 devices' compatible for Gru ASoC: rockchip: Parse dai links from dts ASoC: rockchip: Add support for DP codec ASoC: rockchip: Add support for DMIC codec dt-bindings: ASoC: rockchip: Update description of rockchip,codec .../bindings/sound/rockchip,rk3399-gru-sound.txt | 9 +- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 7 +- sound/soc/codecs/rt5514-spi.c | 2 +- sound/soc/rockchip/Kconfig | 2 + sound/soc/rockchip/rk3399_gru_sound.c | 263 ++--- 5 files changed, 183 insertions(+), 100 deletions(-) -- 2.11.0
[PATCH v4 1/9] ASoC: rt5514: Avoid legacy dai naming
Currently we are using devm_snd_soc_register_component, which would use legacy dai naming when dai drv id is zero. Set a non-zero dai drv id to use dai drv name for dai name. Signed-off-by: Jeffy Chen --- Changes in v4: Use non-zero drv id to avoid legacy dai naming instead of switching to snd_soc_register_codec. Changes in v3: None Changes in v2: None sound/soc/codecs/rt5514-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 640193d845be..4eb08f636f93 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -62,7 +62,7 @@ static const struct snd_pcm_hardware rt5514_spi_pcm_hardware = { static struct snd_soc_dai_driver rt5514_spi_dai = { .name = "rt5514-dsp-cpu-dai", - .id = 0, + .id = 1, /* Set a non-zero drv id to avoid legacy dai naming */ .capture = { .stream_name = "DSP Capture", .channels_min = 1, -- 2.11.0
[PATCH v4 2/9] ASoC: rockchip: Remove obsolete dmic-delay
This property is no longer used. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None .../bindings/sound/rockchip,rk3399-gru-sound.txt | 7 --- sound/soc/rockchip/rk3399_gru_sound.c | 14 -- 2 files changed, 21 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt index eac91db07178..f19b6c830a34 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -6,17 +6,10 @@ Required properties: connected to the codecs - rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs -Optional properties: -- dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready. - If this option is specified, which means it's required dmic need - delay for DMIC to ready so that rt5514 can avoid recording before - DMIC send valid data - Example: sound { compatible = "rockchip,rk3399-gru-sound"; rockchip,cpu = <&i2s0>; rockchip,codec = <&max98357a &rt5514 &da7219>; - dmic-wakeup-delay-ms = <20>; }; diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 3475c61a5fa0..70876d3c34e6 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -38,8 +38,6 @@ #define SOUND_FS 256 -static unsigned int rt5514_dmic_delay; - static struct snd_soc_jack rockchip_sound_jack; static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { @@ -125,9 +123,6 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, return ret; } - /* Wait for DMIC stable */ - msleep(rt5514_dmic_delay); - return 0; } @@ -348,15 +343,6 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -ENODEV; } - /* Set DMIC delay */ - ret = device_property_read_u32(&pdev->dev, "dmic-delay", - &rt5514_dmic_delay); - if (ret) { - rt5514_dmic_delay = 0; - dev_dbg(&pdev->dev, - "no optional property 'dmic-delay' found, default: no delay\n"); - } - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); -- 2.11.0
[PATCH v4 3/9] ASoC: rockchip: Use codec of_node and dai_name for rt5514 dsp
Currently we are using codec name for rt5514 dsp dai link, use codec of_node instead. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None sound/soc/rockchip/rk3399_gru_sound.c | 34 ++ 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 70876d3c34e6..9b7e28703bfb 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -242,8 +242,6 @@ enum { DAILINK_RT5514_DSP, }; -#define DAILINK_ENTITIES (DAILINK_DA7219 + 1) - static struct snd_soc_dai_link rockchip_dailinks[] = { [DAILINK_MAX98357A] = { .name = "MAX98357A", @@ -277,8 +275,7 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { [DAILINK_RT5514_DSP] = { .name = "RT5514 DSP", .stream_name = "Wake on Voice", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", + .codec_dai_name = "rt5514-dsp-cpu-dai", }, }; @@ -295,17 +292,10 @@ static struct snd_soc_card rockchip_sound_card = { .num_controls = ARRAY_SIZE(rockchip_controls), }; -static int rockchip_sound_match_stub(struct device *dev, void *data) -{ - return 1; -} - static int rockchip_sound_probe(struct platform_device *pdev) { struct snd_soc_card *card = &rockchip_sound_card; struct device_node *cpu_node; - struct device *dev; - struct device_driver *drv; int i, ret; cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); @@ -314,7 +304,7 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -EINVAL; } - for (i = 0; i < DAILINK_ENTITIES; i++) { + for (i = 0; i < ARRAY_SIZE(rockchip_dailinks); i++) { rockchip_dailinks[i].platform_of_node = cpu_node; rockchip_dailinks[i].cpu_of_node = cpu_node; @@ -327,26 +317,6 @@ static int rockchip_sound_probe(struct platform_device *pdev) } } - /** -* To acquire the spi driver of the rt5514 and set the dai-links names -* for soc_bind_dai_link -*/ - drv = driver_find("rt5514", &spi_bus_type); - if (!drv) { - dev_err(&pdev->dev, "Can not find the rt5514 driver at the spi bus\n"); - return -EINVAL; - } - - dev = driver_find_device(drv, NULL, NULL, rockchip_sound_match_stub); - if (!dev) { - dev_err(&pdev->dev, "Can not find the rt5514 device\n"); - return -ENODEV; - } - - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); - card->dev = &pdev->dev; platform_set_drvdata(pdev, card); -- 2.11.0
[PATCH v4 5/9] arm64: dts: rockchip: Update rt5514 devices' compatible for Gru
Currently the rt5514 i2c driver and rt5514 spi driver are using the same compatible string. Add additional unused compatible strings to identify them for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 72717e77a0fc..c489c78b2b5b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -611,7 +611,7 @@ ap_i2c_mic: &i2c1 { i2c-scl-rising-time-ns = <300>; headsetcodec: rt5514@57 { - compatible = "realtek,rt5514"; + compatible = "realtek,rt5514", "realtek,rt5514-i2c"; reg = <0x57>; interrupt-parent = <&gpio1>; interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; @@ -828,7 +828,7 @@ ap_i2c_audio: &i2c8 { status = "okay"; wacky_spi_audio: spi2@0 { - compatible = "realtek,rt5514"; + compatible = "realtek,rt5514", "realtek,rt5514-spi"; reg = <0>; /* May run faster once verified. */ -- 2.11.0
[PATCH v4 7/9] ASoC: rockchip: Add support for DP codec
Add support for optional cdn dp codec. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None sound/soc/rockchip/Kconfig| 1 + sound/soc/rockchip/rk3399_gru_sound.c | 59 +-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index c84487805876..8f0d0d8d34e6 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -68,6 +68,7 @@ config SND_SOC_RK3399_GRU_SOUND select SND_SOC_RT5514 select SND_SOC_DA7219 select SND_SOC_RT5514_SPI + select SND_SOC_HDMI_CODEC help Say Y or M here if you want to add support multiple codecs for SoC audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index d532336871d7..8ffae1934b94 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -223,6 +223,45 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) return 0; } +static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int mclk, ret; + + /* in bypass mode, the mclk has to be one of the frequencies below */ + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 32000: + case 48000: + case 64000: + case 96000: + mclk = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + default: + return -EINVAL; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, +SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret); + return ret; + } + + return 0; +} + static const struct snd_soc_ops rockchip_sound_max98357a_ops = { .hw_params = rockchip_sound_max98357a_hw_params, }; @@ -235,6 +274,10 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = { .hw_params = rockchip_sound_da7219_hw_params, }; +static struct snd_soc_ops rockchip_sound_cdndp_ops = { + .hw_params = rockchip_sound_cdndp_hw_params, +}; + static struct snd_soc_card rockchip_sound_card = { .name = "rk3399-gru-sound", .owner = THIS_MODULE, @@ -247,6 +290,7 @@ static struct snd_soc_card rockchip_sound_card = { }; enum { + DAILINK_CDNDP, DAILINK_DA7219, DAILINK_MAX98357A, DAILINK_RT5514, @@ -254,6 +298,7 @@ enum { }; static const char * const dailink_compat[] = { + [DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp", [DAILINK_DA7219] = "dlg,da7219", [DAILINK_MAX98357A] = "maxim,max98357a", [DAILINK_RT5514] = "realtek,rt5514-i2c", @@ -261,6 +306,14 @@ static const char * const dailink_compat[] = { }; static const struct snd_soc_dai_link rockchip_dais[] = { + [DAILINK_CDNDP] = { + .name = "DP", + .stream_name = "DP PCM", + .codec_dai_name = "i2s-hifi", + .ops = &rockchip_sound_cdndp_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_DA7219] = { .name = "DA7219", .stream_name = "DA7219 PCM", @@ -311,7 +364,7 @@ static int rockchip_sound_codec_node_match(struct device_node *np_codec) static int rockchip_sound_of_parse_dais(struct device *dev, struct snd_soc_card *card) { - struct device_node *np_cpu; + struct device_node *np_cpu, *np_cpu0, *np_cpu1; struct device_node *np_codec; struct snd_soc_dai_link *dai; int i, index; @@ -321,7 +374,8 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (!card->dai_link) return -ENOMEM; - np_cpu = of_parse_phandle(dev->of_node, "rockchip,cpu", 0); + np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0); + np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1); card->num_links = 0; for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) { @@ -337,6 +391,7 @@ static int rockchip_sound_of_parse_dais(struct device *dev, if (index < 0)
[PATCH v4 4/9] arm64: dts: rockchip: Add rt5514 dsp for Gru
Add rt5514 dsp of_node to codec list for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 690a43f46641..72717e77a0fc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -514,7 +514,8 @@ sound { compatible = "rockchip,rk3399-gru-sound"; rockchip,cpu = <&i2s0 &i2s2>; - rockchip,codec = <&max98357a &headsetcodec &codec>; + rockchip,codec = <&max98357a &headsetcodec + &codec &wacky_spi_audio>; }; }; -- 2.11.0
[PATCH v4 8/9] ASoC: rockchip: Add support for DMIC codec
Add support for optional dmic codec. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None sound/soc/rockchip/Kconfig| 1 + sound/soc/rockchip/rk3399_gru_sound.c | 33 + 2 files changed, 34 insertions(+) diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index 8f0d0d8d34e6..b0825370d262 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -69,6 +69,7 @@ config SND_SOC_RK3399_GRU_SOUND select SND_SOC_DA7219 select SND_SOC_RT5514_SPI select SND_SOC_HDMI_CODEC + select SND_SOC_DMIC help Say Y or M here if you want to add support multiple codecs for SoC audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 8ffae1934b94..0be3e5c1386f 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -262,6 +262,25 @@ static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream, return 0; } +static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int mclk; + int ret; + + mclk = params_rate(params) * SOUND_FS; + + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0); + if (ret) { + dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", + __func__, mclk, ret); + return ret; + } + + return 0; +} + static const struct snd_soc_ops rockchip_sound_max98357a_ops = { .hw_params = rockchip_sound_max98357a_hw_params, }; @@ -278,6 +297,10 @@ static struct snd_soc_ops rockchip_sound_cdndp_ops = { .hw_params = rockchip_sound_cdndp_hw_params, }; +static struct snd_soc_ops rockchip_sound_dmic_ops = { + .hw_params = rockchip_sound_dmic_hw_params, +}; + static struct snd_soc_card rockchip_sound_card = { .name = "rk3399-gru-sound", .owner = THIS_MODULE, @@ -292,6 +315,7 @@ static struct snd_soc_card rockchip_sound_card = { enum { DAILINK_CDNDP, DAILINK_DA7219, + DAILINK_DMIC, DAILINK_MAX98357A, DAILINK_RT5514, DAILINK_RT5514_DSP, @@ -300,6 +324,7 @@ enum { static const char * const dailink_compat[] = { [DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp", [DAILINK_DA7219] = "dlg,da7219", + [DAILINK_DMIC] = "dmic-codec", [DAILINK_MAX98357A] = "maxim,max98357a", [DAILINK_RT5514] = "realtek,rt5514-i2c", [DAILINK_RT5514_DSP] = "realtek,rt5514-spi", @@ -324,6 +349,14 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, }, + [DAILINK_DMIC] = { + .name = "DMIC", + .stream_name = "DMIC PCM", + .codec_dai_name = "dmic-hifi", + .ops = &rockchip_sound_dmic_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_MAX98357A] = { .name = "MAX98357A", .stream_name = "MAX98357A PCM", -- 2.11.0
[PATCH v4 6/9] ASoC: rockchip: Parse dai links from dts
Refactor rockchip_sound_probe, parse dai links from dts instead of hard coding them. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: Use compatible to match audio codecs -- Suggested-by Matthias Kaehlcke Changes in v2: Let rockchip,codec-names be a required property, because we plan to add more supported codecs to the fixed dai link list in the driver. sound/soc/rockchip/rk3399_gru_sound.c | 139 ++ 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 9b7e28703bfb..d532336871d7 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -235,14 +235,42 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops = { .hw_params = rockchip_sound_da7219_hw_params, }; +static struct snd_soc_card rockchip_sound_card = { + .name = "rk3399-gru-sound", + .owner = THIS_MODULE, + .dapm_widgets = rockchip_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets), + .dapm_routes = rockchip_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes), + .controls = rockchip_controls, + .num_controls = ARRAY_SIZE(rockchip_controls), +}; + enum { + DAILINK_DA7219, DAILINK_MAX98357A, DAILINK_RT5514, - DAILINK_DA7219, DAILINK_RT5514_DSP, }; -static struct snd_soc_dai_link rockchip_dailinks[] = { +static const char * const dailink_compat[] = { + [DAILINK_DA7219] = "dlg,da7219", + [DAILINK_MAX98357A] = "maxim,max98357a", + [DAILINK_RT5514] = "realtek,rt5514-i2c", + [DAILINK_RT5514_DSP] = "realtek,rt5514-spi", +}; + +static const struct snd_soc_dai_link rockchip_dais[] = { + [DAILINK_DA7219] = { + .name = "DA7219", + .stream_name = "DA7219 PCM", + .codec_dai_name = "da7219-hifi", + .init = rockchip_sound_da7219_init, + .ops = &rockchip_sound_da7219_ops, + /* set da7219 as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, [DAILINK_MAX98357A] = { .name = "MAX98357A", .stream_name = "MAX98357A PCM", @@ -261,16 +289,6 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, }, - [DAILINK_DA7219] = { - .name = "DA7219", - .stream_name = "DA7219 PCM", - .codec_dai_name = "da7219-hifi", - .init = rockchip_sound_da7219_init, - .ops = &rockchip_sound_da7219_ops, - /* set da7219 as slave */ - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - }, /* RT5514 DSP for voice wakeup via spi bus */ [DAILINK_RT5514_DSP] = { .name = "RT5514 DSP", @@ -279,53 +297,78 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { }, }; -static struct snd_soc_card rockchip_sound_card = { - .name = "rk3399-gru-sound", - .owner = THIS_MODULE, - .dai_link = rockchip_dailinks, - .num_links = ARRAY_SIZE(rockchip_dailinks), - .dapm_widgets = rockchip_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets), - .dapm_routes = rockchip_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes), - .controls = rockchip_controls, - .num_controls = ARRAY_SIZE(rockchip_controls), -}; - -static int rockchip_sound_probe(struct platform_device *pdev) +static int rockchip_sound_codec_node_match(struct device_node *np_codec) { - struct snd_soc_card *card = &rockchip_sound_card; - struct device_node *cpu_node; - int i, ret; + int i; - cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); - if (!cpu_node) { - dev_err(&pdev->dev, "Property 'rockchip,cpu' missing or invalid\n"); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(dailink_compat); i++) { + if (of_device_is_compatible(np_codec, dailink_compat[i])) + return i; } + return -1; +} - for (i = 0; i < ARRAY_SIZE(rockchip_dailinks); i++) { - rockchip_dailinks[i].platform_of_node = cpu_node; - rockchip_dailinks[i].cpu_of_node = cpu_node; - - rockchip_dailinks[i].codec_of_node = - of_parse_phandle(pdev->dev.of_node, "rockchip,co
[PATCH v4 9/9] dt-bindings: ASoC: rockchip: Update description of rockchip,codec
Update description for newly added optional audio codecs. Signed-off-by: Jeffy Chen Acked-by: Rob Herring --- Changes in v4: None Changes in v3: None Changes in v2: None Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt index f19b6c830a34..f54b4e91e97c 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -4,7 +4,7 @@ Required properties: - compatible: "rockchip,rk3399-gru-sound" - rockchip,cpu: The phandle of the Rockchip I2S controller that's connected to the codecs -- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs +- rockchip,codec: The phandle of the audio codecs Example: -- 2.11.0
[PATCH v3 0/4] PCI: rockchip: Move PCIE_WAKE handling into rockchip pcie driver
Currently we are handling pcie wake in mrvl wifi driver. But Brian suggests to move it into rockchip pcie driver. Tested on my chromebook bob(with cros 4.4 kernel and mrvl wifi). Changes in v3: Fix error handling Changes in v2: Use dev_pm_set_dedicated_wake_irq -- Suggested by Brian Norris Jeffy Chen (4): PCI: rockchip: Fix error handlings PCI: rockchip: Add support for pcie wake irq dt-bindings: PCI: rockchip: Add support for pcie wake irq arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru .../devicetree/bindings/pci/rockchip-pcie.txt | 20 ++-- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 ++- drivers/pci/host/pcie-rockchip.c | 122 + 3 files changed, 96 insertions(+), 61 deletions(-) -- 2.11.0
[PATCH v3 1/4] PCI: rockchip: Fix error handlings
Fix error handlings in probe & resume. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None drivers/pci/host/pcie-rockchip.c | 103 ++- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 7bb9870f6d8c..e9867bcff1ff 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -546,25 +546,25 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) err = reset_control_assert(rockchip->core_rst); if (err) { dev_err(dev, "assert core_rst err %d\n", err); - return err; + goto err_exit_phy; } err = reset_control_assert(rockchip->mgmt_rst); if (err) { dev_err(dev, "assert mgmt_rst err %d\n", err); - return err; + goto err_exit_phy; } err = reset_control_assert(rockchip->mgmt_sticky_rst); if (err) { dev_err(dev, "assert mgmt_sticky_rst err %d\n", err); - return err; + goto err_exit_phy; } err = reset_control_assert(rockchip->pipe_rst); if (err) { dev_err(dev, "assert pipe_rst err %d\n", err); - return err; + goto err_exit_phy; } udelay(10); @@ -572,19 +572,19 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) err = reset_control_deassert(rockchip->pm_rst); if (err) { dev_err(dev, "deassert pm_rst err %d\n", err); - return err; + goto err_exit_phy; } err = reset_control_deassert(rockchip->aclk_rst); if (err) { dev_err(dev, "deassert aclk_rst err %d\n", err); - return err; + goto err_exit_phy; } err = reset_control_deassert(rockchip->pclk_rst); if (err) { dev_err(dev, "deassert pclk_rst err %d\n", err); - return err; + goto err_exit_phy; } if (rockchip->link_gen == 2) @@ -605,7 +605,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) err = phy_power_on(rockchip->phy); if (err) { dev_err(dev, "fail to power on phy, err %d\n", err); - return err; + goto err_exit_phy; } /* @@ -615,25 +615,25 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) err = reset_control_deassert(rockchip->mgmt_sticky_rst); if (err) { dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err); - return err; + goto err_power_off_phy; } err = reset_control_deassert(rockchip->core_rst); if (err) { dev_err(dev, "deassert core_rst err %d\n", err); - return err; + goto err_power_off_phy; } err = reset_control_deassert(rockchip->mgmt_rst); if (err) { dev_err(dev, "deassert mgmt_rst err %d\n", err); - return err; + goto err_power_off_phy; } err = reset_control_deassert(rockchip->pipe_rst); if (err) { dev_err(dev, "deassert pipe_rst err %d\n", err); - return err; + goto err_power_off_phy; } /* Fix the transmitted FTS count desired to exit from L0s. */ @@ -666,7 +666,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) 500 * USEC_PER_MSEC); if (err) { dev_err(dev, "PCIe link training gen1 timeout!\n"); - return -ETIMEDOUT; + goto err_power_off_phy; } if (rockchip->link_gen == 2) { @@ -715,6 +715,11 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); return 0; +err_power_off_phy: + phy_power_off(rockchip->phy); +err_exit_phy: + phy_exit(rockchip->phy); + return err; } static irqreturn_t rockchip_pcie_subsys_irq_handler(int irq, void *arg) @@ -1051,7 +1056,7 @@ static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip) err = regulator_enable(rockchip->vpcie3v3); if (err) { dev_err(dev, "fail to enable vpcie3v3 regulator\n"); - goto err_out; + return err; } } @@ -1072,14 +1077,12 @@ static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip) } return 0; - err_disable_1v8:
[PATCH v3 2/4] PCI: rockchip: Add support for pcie wake irq
Add support for PCIE_WAKE pin in rockchip pcie driver. Signed-off-by: Jeffy Chen --- Changes in v3: Fix error handling Changes in v2: Use dev_pm_set_dedicated_wake_irq -- Suggested by Brian Norris drivers/pci/host/pcie-rockchip.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index e9867bcff1ff..d52318458060 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -858,7 +859,6 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } - /** * rockchip_pcie_parse_dt - Parse Device Tree * @rockchip: PCIe port information @@ -1023,6 +1023,14 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) return err; } + device_init_wakeup(dev, true); + irq = platform_get_irq_byname(pdev, "wake"); + if (irq >= 0) { + err = dev_pm_set_dedicated_wake_irq(dev, irq); + if (err) + dev_err(dev, "failed to setup PCIe wake IRQ\n"); + } + rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); if (IS_ERR(rockchip->vpcie3v3)) { if (PTR_ERR(rockchip->vpcie3v3) == -EPROBE_DEFER) @@ -1390,12 +1398,13 @@ static int rockchip_pcie_probe(struct platform_device *pdev) err = rockchip_pcie_parse_dt(rockchip); if (err) - return err; + /* It's safe to disable wake even not enabled */ + goto err_disable_wake; err = clk_prepare_enable(rockchip->aclk_pcie); if (err) { dev_err(dev, "unable to enable aclk_pcie clock\n"); - return err; + goto err_disable_wake; } err = clk_prepare_enable(rockchip->aclk_perf_pcie); @@ -1529,6 +1538,9 @@ static int rockchip_pcie_probe(struct platform_device *pdev) clk_disable_unprepare(rockchip->aclk_perf_pcie); err_disable_aclk_pcie: clk_disable_unprepare(rockchip->aclk_pcie); +err_disable_wake: + dev_pm_clear_wake_irq(dev); + device_init_wakeup(dev, false); return err; } @@ -1557,6 +1569,9 @@ static int rockchip_pcie_remove(struct platform_device *pdev) if (!IS_ERR(rockchip->vpcie0v9)) regulator_disable(rockchip->vpcie0v9); + dev_pm_clear_wake_irq(dev); + device_init_wakeup(dev, false); + return 0; } -- 2.11.0
[PATCH v3 3/4] dt-bindings: PCI: rockchip: Add support for pcie wake irq
Add an optional interrupt for PCIE_WAKE pin. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None .../devicetree/bindings/pci/rockchip-pcie.txt| 20 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt index 1453a734c2f5..edd779f842fa 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt +++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt @@ -22,10 +22,13 @@ Required properties: - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. - phy-names: MUST be "pcie-phy". - interrupts: Three interrupt entries must be specified. -- interrupt-names: Must include the following names - - "sys" - - "legacy" - - "client" +- interrupt-names: Include the following names + Required: + - "sys" + - "legacy" + - "client" + Optional: + - "wake" - resets: Must contain seven entries for each entry in reset-names. See ../reset/reset.txt for details. - reset-names: Must include the following names @@ -76,10 +79,11 @@ pcie0: pcie@f800 { clock-names = "aclk", "aclk-perf", "hclk", "pm"; bus-range = <0x0 0x1>; - interrupts = , -, -; - interrupt-names = "sys", "legacy", "client"; + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wake"; assigned-clocks = <&cru SCLK_PCIEPHY_REF>; assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; assigned-clock-rates = <1>; -- 2.11.0
[PATCH v3 4/4] arm64: dts: rockchip: Handle pcie wake in pcie driver for Gru
Currently we are handling pcie wake irq in mrvl wifi driver. Move it to rockchip pcie driver for Gru boards. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index d48e98b62d09..42158512e979 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -712,7 +712,15 @@ ap_i2c_audio: &i2c8 { ep-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqn_cpm>, <&wifi_perst_l>; + pinctrl-0 = <&pcie_clkreqn_cpm>, <&wlan_host_wake_l>, <&wifi_perst_l>; + + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wake"; + /delete-property/ interrupts; + vpcie3v3-supply = <&pp3300_wifi_bt>; vpcie1v8-supply = <&wlan_pd_n>; /* HACK: see &wlan_pd_n */ vpcie0v9-supply = <&pp900_pcie>; @@ -727,11 +735,6 @@ ap_i2c_audio: &i2c8 { compatible = "pci1b4b,2b42"; reg = <0x8301 0x0 0x 0x0 0x0010 0x8301 0x0 0x0010 0x0 0x0010>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&wlan_host_wake_l>; - wakeup-source; }; }; }; -- 2.11.0
[RFC PATCH v3 0/6] Report wakeup events in cros_ec_keyb and make cros-ec-spi wakeup optional
We are enabling wakeup unconditionally for cros-ec-spi, it would be good to make it optional. And we also need to enable wakeup for cros_ec_keyb, so the userspace could disable keyboard wakeup along with other cros-ec sub devices. Changes in v3: Use wakeup-source property to enable wakeup. Suggested by Dmitry Torokhov . Jeffy Chen (6): spi: core: add support for wakeup-source dts property dt-bindings: spi/core: add wakeup-source optional property ARM/arm64: dts: enable wakeup for cros-ec-spi devices mfd: cros ec: spi: remove unconditionally wakeup enable input: cros_ec_keyb: report wakeup events ARM: dts: cros-ec-keyboard: enable as wakeup source Documentation/devicetree/bindings/spi/spi-bus.txt | 1 + arch/arm/boot/dts/cros-ec-keyboard.dtsi | 1 + arch/arm/boot/dts/exynos5420-peach-pit.dts| 1 + arch/arm/boot/dts/exynos5800-peach-pi.dts | 1 + arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi | 1 + arch/arm/boot/dts/tegra124-nyan.dtsi | 1 + arch/arm/boot/dts/tegra124-venice2.dts| 1 + arch/arm64/boot/dts/nvidia/tegra132-norrin.dts| 1 + arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 1 + drivers/input/keyboard/cros_ec_keyb.c | 8 drivers/mfd/cros_ec_spi.c | 2 -- drivers/spi/spi.c | 15 +++ 12 files changed, 28 insertions(+), 6 deletions(-) -- 2.1.4
[RFC PATCH v3 1/6] spi: core: add support for wakeup-source dts property
Use generic wakeup-source property to enable spi device wakeup. Signed-off-by: Jeffy Chen --- Changes in v3: None drivers/spi/spi.c | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c3f6b52..a510bba 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -547,11 +547,16 @@ int spi_add_device(struct spi_device *spi) /* Device may be bound to an active driver when this returns */ status = device_add(&spi->dev); - if (status < 0) + if (status < 0) { dev_err(dev, "can't add %s, status %d\n", - dev_name(&spi->dev), status); - else - dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev)); + dev_name(&spi->dev), status); + goto done; + } + + dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev)); + + if (device_property_read_bool(&spi->dev, "wakeup-source")) + device_init_wakeup(&spi->dev, true); done: mutex_unlock(&spi_add_lock); @@ -638,6 +643,8 @@ void spi_unregister_device(struct spi_device *spi) if (!spi) return; + device_init_wakeup(&spi->dev, false); + if (spi->dev.of_node) { of_node_clear_flag(spi->dev.of_node, OF_POPULATED); of_node_put(spi->dev.of_node); -- 2.1.4
[RFC PATCH v3 2/6] dt-bindings: spi/core: add wakeup-source optional property
Update document devicetree bindings to support "wakeup-source" property. Signed-off-by: Jeffy Chen --- Changes in v3: None Documentation/devicetree/bindings/spi/spi-bus.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt index 1f6e86f..0fa1ccf 100644 --- a/Documentation/devicetree/bindings/spi/spi-bus.txt +++ b/Documentation/devicetree/bindings/spi/spi-bus.txt @@ -77,6 +77,7 @@ All slave nodes can contain the following optional properties: Defaults to 1 if not present. - spi-rx-delay-us - Microsecond delay after a read transfer. - spi-tx-delay-us - Microsecond delay after a write transfer. +- wakeup-source - Device can be used as a wakeup source. Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4 -- 2.1.4
[RFC PATCH v3 3/6] ARM/arm64: dts: enable wakeup for cros-ec-spi devices
We used to enable wakeup for cros-ec-spi devices unconditionally. Now we are using the more generic wakeup-source property to enable it. Signed-off-by: Jeffy Chen --- Changes in v3: None arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 + arch/arm/boot/dts/exynos5800-peach-pi.dts | 1 + arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi | 1 + arch/arm/boot/dts/tegra124-nyan.dtsi| 1 + arch/arm/boot/dts/tegra124-venice2.dts | 1 + arch/arm64/boot/dts/nvidia/tegra132-norrin.dts | 1 + arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi| 1 + 7 files changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index f9a75bf..a65ec2a 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -950,6 +950,7 @@ reg = <0>; spi-max-frequency = <3125000>; google,has-vbc-nvram; + wakeup-source; controller-data { samsung,spi-feedback-delay = <1>; diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 953dc86..5209832 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -919,6 +919,7 @@ reg = <0>; spi-max-frequency = <3125000>; google,has-vbc-nvram; + wakeup-source; controller-data { samsung,spi-feedback-delay = <1>; diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi index d752a31..94924df 100644 --- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi +++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi @@ -232,6 +232,7 @@ pinctrl-names = "default"; pinctrl-0 = <&ec_int>; spi-max-frequency = <300>; + wakeup-source; i2c_tunnel: i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi index 5cf987b..198fc30 100644 --- a/arch/arm/boot/dts/tegra124-nyan.dtsi +++ b/arch/arm/boot/dts/tegra124-nyan.dtsi @@ -318,6 +318,7 @@ reg = <0>; google,cros-ec-spi-msg-delay = <2000>; + wakeup-source; i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts index 6e59cec..008574d 100644 --- a/arch/arm/boot/dts/tegra124-venice2.dts +++ b/arch/arm/boot/dts/tegra124-venice2.dts @@ -845,6 +845,7 @@ reg = <0>; google,cros-ec-spi-msg-delay = <2000>; + wakeup-source; i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; diff --git a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts index 759af96..e0e54a9 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts +++ b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts @@ -758,6 +758,7 @@ reg = <0>; google,cros-ec-spi-msg-delay = <2000>; + wakeup-source; i2c_20: i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index eb50593..409199b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -798,6 +798,7 @@ ap_i2c_audio: &i2c8 { pinctrl-names = "default"; pinctrl-0 = <&ec_ap_int_l>; spi-max-frequency = <300>; + wakeup-source; i2c_tunnel: i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; -- 2.1.4
[RFC PATCH v3 6/6] ARM: dts: cros-ec-keyboard: enable as wakeup source
Enable cros-ec-keyboard as a wakeup source. Signed-off-by: Jeffy Chen --- Changes in v3: None arch/arm/boot/dts/cros-ec-keyboard.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/cros-ec-keyboard.dtsi b/arch/arm/boot/dts/cros-ec-keyboard.dtsi index c0451051..3168a5e 100644 --- a/arch/arm/boot/dts/cros-ec-keyboard.dtsi +++ b/arch/arm/boot/dts/cros-ec-keyboard.dtsi @@ -16,6 +16,7 @@ keypad,num-rows = <8>; keypad,num-columns = <13>; google,needs-ghost-filter; + wakeup-source; linux,keymap = < MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA) -- 2.1.4
[RFC PATCH v3 5/6] input: cros_ec_keyb: report wakeup events
Report wakeup events when process events. Signed-off-by: Jeffy Chen --- Changes in v3: Use wakeup-source property to enable wakeup. Suggested by Dmitry Torokhov . drivers/input/keyboard/cros_ec_keyb.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 79eb295..5dc387b 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -293,6 +293,9 @@ static int cros_ec_keyb_work(struct notifier_block *nb, return NOTIFY_DONE; } + if (device_may_wakeup(ckdev->dev)) + pm_wakeup_event(ckdev->dev, 0); + return NOTIFY_OK; } @@ -639,6 +642,9 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) return err; } + if (device_property_read_bool(dev, "wakeup-source")) + device_init_wakeup(dev, true); + return 0; } @@ -649,6 +655,8 @@ static int cros_ec_keyb_remove(struct platform_device *pdev) blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, &ckdev->notifier); + device_init_wakeup(&pdev->dev, false); + return 0; } -- 2.1.4
[RFC PATCH v3 4/6] mfd: cros ec: spi: remove unconditionally wakeup enable
We used to enable wakeup for cros-ec-spi devices unconditionally. Now we are using the more generic wakeup-source property to enable it. Signed-off-by: Jeffy Chen --- Changes in v3: None drivers/mfd/cros_ec_spi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c index c971407..0be7051 100644 --- a/drivers/mfd/cros_ec_spi.c +++ b/drivers/mfd/cros_ec_spi.c @@ -674,8 +674,6 @@ static int cros_ec_spi_probe(struct spi_device *spi) return err; } - device_init_wakeup(&spi->dev, true); - return 0; } -- 2.1.4
[RFC PATCH] Bluetooth: btusb: Fix memory leak in play_deferred
Currently in play_deferred, we are calling usb_submit_urb directly to submit deferred tx urb after unanchor it. So the usb_giveback_urb_bh would failed to unref it in usb_unanchor_urb and cause memory leak: unreferenced object 0xffc0ce0fa400 (size 256): ... backtrace: [] __save_stack_trace+0x48/0x6c [] create_object+0x138/0x254 [] kmemleak_alloc+0x58/0x8c [] __kmalloc+0x1d4/0x2a0 [] usb_alloc_urb+0x30/0x60 [] alloc_ctrl_urb+0x38/0x120 [btusb] [] btusb_send_frame+0x64/0xf8 [btusb] Use submit_tx_urb instead for better error handling and avoid the leak. Signed-off-by: Jeffy Chen --- drivers/bluetooth/btusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 278e811..b469f9b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3254,11 +3254,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) static void play_deferred(struct btusb_data *data) { + struct hci_dev *hdev = data->hdev; struct urb *urb; int err; while ((urb = usb_get_from_anchor(&data->deferred))) { - err = usb_submit_urb(urb, GFP_ATOMIC); + err = submit_tx_urb(hdev, urb); if (err < 0) break; -- 2.1.4
[PATCH 1/5] arm64: dts: rockchip: Enable edp disaplay on kevin
Add edp panel and enable related nodes on kevin. Signed-off-by: Jeffy Chen --- arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + 2 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index a3d3cea7dc4f..bc67b19f0af5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -93,6 +93,18 @@ pwm-delay-us = <1>; }; + edp_panel: edp-panel { + compatible = "sharp,lq123p1jx31", "simple-panel"; + backlight = <&backlight>; + power-supply = <&pp3300_disp>; + + ports { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu { compatible = "murata,ncp15wb473"; pullup-uv = <180>; @@ -264,6 +276,23 @@ ap_i2c_dig: &i2c2 { }; }; +&edp { + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &ppvar_bigcpu_pwm { regulator-min-microvolt = <798674>; regulator-max-microvolt = <1302172>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..470105d651c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -927,6 +927,22 @@ ap_i2c_audio: &i2c8 { dr_mode = "host"; }; +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + #include #include -- 2.11.0
[PATCH 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin backlight: pwm_bl: Add device link for pwm_bl and pwm drm/rockchip: Fix error handling path in rockchip_dp_bind() drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 --- drivers/gpu/drm/exynos/exynos_dp.c | 26 +- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++-- drivers/video/backlight/pwm_bl.c | 2 + include/drm/bridge/analogix_dp.h | 19 +--- 8 files changed, 151 insertions(+), 72 deletions(-) -- 2.11.0
[RESEND PATCH v2 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin backlight: pwm_bl: Add device link for pwm_bl and pwm drm/rockchip: Fix error handling path in rockchip_dp_bind() drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 --- drivers/gpu/drm/exynos/exynos_dp.c | 26 +- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 ++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 +++-- drivers/video/backlight/pwm_bl.c | 2 + include/drm/bridge/analogix_dp.h | 19 +--- 8 files changed, 151 insertions(+), 72 deletions(-) -- 2.11.0
[RESEND PATCH v2 1/5] arm64: dts: rockchip: Enable edp disaplay on kevin
Add edp panel and enable related nodes on kevin. Signed-off-by: Jeffy Chen --- Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + 2 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index a3d3cea7dc4f..bc67b19f0af5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -93,6 +93,18 @@ pwm-delay-us = <1>; }; + edp_panel: edp-panel { + compatible = "sharp,lq123p1jx31", "simple-panel"; + backlight = <&backlight>; + power-supply = <&pp3300_disp>; + + ports { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu { compatible = "murata,ncp15wb473"; pullup-uv = <180>; @@ -264,6 +276,23 @@ ap_i2c_dig: &i2c2 { }; }; +&edp { + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &ppvar_bigcpu_pwm { regulator-min-microvolt = <798674>; regulator-max-microvolt = <1302172>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..470105d651c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -927,6 +927,22 @@ ap_i2c_audio: &i2c8 { dr_mode = "host"; }; +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + #include #include -- 2.11.0
[RESEND PATCH v2 2/5] backlight: pwm_bl: Add device link for pwm_bl and pwm
When the pwm driver is unbound, the pwm_bl driver would still hold a reference to that pwm, and crash the kernel later(if someone trying to access that invalid pwm). Add a device link to avoid this. Signed-off-by: Jeffy Chen --- Changes in v2: None drivers/video/backlight/pwm_bl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 9bd17682655a..a76f147a26e7 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -328,6 +328,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) goto err_alloc; } + device_link_add(&pdev->dev, pb->pwm->chip->dev, DL_FLAG_AUTOREMOVE); + dev_dbg(&pdev->dev, "got pwm for backlight\n"); /* -- 2.11.0
[RESEND PATCH v2 3/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen --- Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..cb8941e8bcdd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_deinit_dp; } dp->plat_data.encoder = &dp->encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(&dp->encoder); + rockchip_dp_drm_encoder_destroy(&dp->encoder); +err_deinit_dp: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0
[RESEND PATCH v2 4/5] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa Signed-off-by: Jeffy Chen --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "hpd_gpio"); if (ret) { dev_err(&pdev->dev, "failed to get h
[RESEND PATCH v2 5/5] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen --- Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, &match, compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, &rockchip_drm_ops, match); + ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, &dev->links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(&pdev->dev, &rockchip_drm_ops); + list_for_each_entry(link, &pdev->dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0
[RFC PATCH v3 1/5] arm64: dts: rockchip: Enable edp disaplay on kevin
Add edp panel and enable related nodes on kevin. Signed-off-by: Jeffy Chen Reviewed-by: Mark Yao --- Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + 2 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index a3d3cea7dc4f..bc67b19f0af5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -93,6 +93,18 @@ pwm-delay-us = <1>; }; + edp_panel: edp-panel { + compatible = "sharp,lq123p1jx31", "simple-panel"; + backlight = <&backlight>; + power-supply = <&pp3300_disp>; + + ports { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu { compatible = "murata,ncp15wb473"; pullup-uv = <180>; @@ -264,6 +276,23 @@ ap_i2c_dig: &i2c2 { }; }; +&edp { + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &ppvar_bigcpu_pwm { regulator-min-microvolt = <798674>; regulator-max-microvolt = <1302172>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..470105d651c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -927,6 +927,22 @@ ap_i2c_audio: &i2c8 { dr_mode = "host"; }; +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + #include #include -- 2.11.0
[RFC PATCH v3 3/5] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa Signed-off-by: Jeffy Chen Reviewed-by: Andrzej Hajda --- Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "hpd_gpio"); if (ret) {
[RFC PATCH v3 5/5] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, &match, compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, &rockchip_drm_ops, match); + ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, &dev->links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(&pdev->dev, &rockchip_drm_ops); + list_for_each_entry(link, &pdev->dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0
[RFC PATCH v3 4/5] pwm: Add dummy pwmchip for orphan pwms
When the pwm driver is unbound while the pwm is still requested, the pwm core would not actually remove the pwmchip(return -EBUSY instead). So it would hold some references to the invalid resources(e.g. pwmchip). And the customer who requested the pwm would have those references too, and may crash the kernel when trying to access them later. Add a dummy pwmchip, and assign orphan pwms to it to avoid that. Signed-off-by: Jeffy Chen --- Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: None drivers/pwm/core.c | 84 +- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 1581f6ab1b1f..4d8504b90a98 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -41,6 +41,21 @@ static LIST_HEAD(pwm_chips); static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); static RADIX_TREE(pwm_tree, GFP_KERNEL); +static int dummy_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + return -ENOTSUPP; +} + +static const struct pwm_ops dummy_pwm_ops = { + .apply = dummy_pwm_apply, + .owner = THIS_MODULE, +}; + +static struct device dummy_pwm_dev = { + .init_name = "dummy-pwm", +}; + static struct pwm_device *pwm_to_device(unsigned int pwm) { return radix_tree_lookup(&pwm_tree, pwm); @@ -334,6 +349,33 @@ int pwmchip_add(struct pwm_chip *chip) } EXPORT_SYMBOL_GPL(pwmchip_add); +static int pwmchip_convert_dummy(struct pwm_chip *chip) +{ + struct pwm_chip *dummy; + unsigned int i; + + dummy = kzalloc(sizeof(*dummy), GFP_KERNEL); + if (!dummy) + return -ENOMEM; + + dummy->dev = &dummy_pwm_dev; + dummy->ops = &dummy_pwm_ops; + dummy->npwm = chip->npwm; + dummy->pwms = chip->pwms; + + INIT_LIST_HEAD(&dummy->list); + list_add(&dummy->list, &pwm_chips); + + for (i = 0; i < dummy->npwm; i++) { + struct pwm_device *pwm = &dummy->pwms[i]; + + pwm->chip = dummy; + pwm->state.enabled = false; + } + + return 0; +} + /** * pwmchip_remove() - remove a PWM chip * @chip: the PWM chip to remove @@ -346,7 +388,7 @@ EXPORT_SYMBOL_GPL(pwmchip_add); int pwmchip_remove(struct pwm_chip *chip) { unsigned int i; - int ret = 0; + int ret = 0, requested = 0; pwmchip_sysfs_unexport_children(chip); @@ -356,21 +398,28 @@ int pwmchip_remove(struct pwm_chip *chip) struct pwm_device *pwm = &chip->pwms[i]; if (test_bit(PWMF_REQUESTED, &pwm->flags)) { - ret = -EBUSY; - goto out; + requested = 1; + + if (pwm->chip->ops->free) + pwm->chip->ops->free(pwm->chip, pwm); + + module_put(pwm->chip->ops->owner); } } + if (requested) + pwmchip_convert_dummy(chip); + else + free_pwms(chip); + +out: list_del_init(&chip->list); if (IS_ENABLED(CONFIG_OF)) of_pwmchip_remove(chip); - free_pwms(chip); - pwmchip_sysfs_unexport(chip); -out: mutex_unlock(&pwm_lock); return ret; } @@ -855,6 +904,24 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) } EXPORT_SYMBOL_GPL(pwm_get); +static int pwmchip_remove_dummy(struct pwm_chip *dummy) +{ + unsigned int i; + + for (i = 0; i < dummy->npwm; i++) { + struct pwm_device *pwm = &dummy->pwms[i]; + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + return -EBUSY; + } + + free_pwms(dummy); + list_del_init(&dummy->list); + kfree(dummy); + + return 0; +} + /** * pwm_put() - release a PWM device * @pwm: PWM device @@ -876,7 +943,10 @@ void pwm_put(struct pwm_device *pwm) pwm->label = NULL; - module_put(pwm->chip->ops->owner); + if (pwm->chip->ops == &dummy_pwm_ops) + pwmchip_remove_dummy(pwm->chip); + else + module_put(pwm->chip->ops->owner); out: mutex_unlock(&pwm_lock); } -- 2.11.0
[RFC PATCH v3 2/5] drm/rockchip: Fix error handling path in rockchip_dp_bind()
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen --- Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..cb8941e8bcdd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_deinit_dp; } dp->plat_data.encoder = &dp->encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(&dp->encoder); + rockchip_dp_drm_encoder_destroy(&dp->encoder); +err_deinit_dp: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0
[RFC PATCH v3 0/5] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (4): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: Fix error handling path in rockchip_dp_bind() pwm: Add dummy pwmchip for orphan pwms drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++--- drivers/gpu/drm/exynos/exynos_dp.c | 26 --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +-- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++- drivers/pwm/core.c | 84 -- include/drm/bridge/analogix_dp.h | 19 ++--- 8 files changed, 226 insertions(+), 79 deletions(-) -- 2.11.0
[RFC PATCH v4 3/8] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..a17ff0f6f489 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(&dsi->dsi_host); -err_cleanup: +err_disable_pm_runtime: + pm_runtime_disable(dev); drm_encoder_cleanup(&dsi->encoder); drm_connector_cleanup(&dsi->connector); -err_pllref: +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(&dsi->dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(&dsi->connector); + dsi->encoder.funcs->destroy(&dsi->encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0
[RFC PATCH v4 5/8] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/inno_hdmi.c | 20 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9c258b05dfa5 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + drm_connector_cleanup(&hdmi->connector); + drm_encoder_cleanup(&hdmi->encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } -- 2.11.0
[RFC PATCH v4 0/8] rockchip: kevin: Enable edp display
Make edp display works on chromebook kevin(at least for boot animation). Also solve some issues i meet during the bringup. Changes in v4: Fix compile warning. Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. Jeffy Chen (7): arm64: dts: rockchip: Enable edp disaplay on kevin drm/rockchip: analogix_dp: Fix error handling path drm/rockchip: dw-mipi-dsi: Fix error handling path drm/rockchip: dw_hdmi: Fix error handling path drm/rockchip: inno_hdmi: Fix error handling path pwm: Add dummy pwmchip for orphan pwms drm/rockchip: Add device links for master and components Tomasz Figa (1): drm/bridge/analogix: Do not use device's drvdata arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 ++--- drivers/gpu/drm/exynos/exynos_dp.c | 26 --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 57 +-- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 17 +++-- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 4 +- drivers/gpu/drm/rockchip/inno_hdmi.c | 20 -- drivers/gpu/drm/rockchip/rockchip_drm_drv.c| 24 ++- drivers/pwm/core.c | 81 -- include/drm/bridge/analogix_dp.h | 19 ++--- 11 files changed, 254 insertions(+), 89 deletions(-) -- 2.11.0
[RFC PATCH v4 2/8] drm/rockchip: analogix_dp: Fix error handling path
Add missing error handling in rockchip_dp_bind(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..4b689c0f3fc1 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -371,7 +371,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, ret = rockchip_dp_drm_create_encoder(dp); if (ret) { DRM_ERROR("failed to create drm encoder\n"); - return ret; + goto err_disable_pclk; } dp->plat_data.encoder = &dp->encoder; @@ -387,7 +387,17 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + ret = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); + if (ret < 0) + goto err_unreg_psr; + return 0; + +err_unreg_psr: + rockchip_drm_psr_unregister(&dp->encoder); + rockchip_dp_drm_encoder_destroy(&dp->encoder); +err_disable_pclk: + clk_disable_unprepare(dp->pclk); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, -- 2.11.0
[RFC PATCH v4 7/8] pwm: Add dummy pwmchip for orphan pwms
When the pwm driver is unbound while the pwm is still requested, the pwm core would not actually remove the pwmchip(return -EBUSY instead). So it would hold some references to the invalid resources(e.g. pwmchip). And the customer who requested the pwm would have those references too, and may crash the kernel when trying to access them later. Add a dummy pwmchip, and assign orphan pwms to it to avoid that. Signed-off-by: Jeffy Chen --- Changes in v4: Fix compile warning. Changes in v3: Assign orphan pwms to dummy pwmchip instead of adding device link in the customer driver. Changes in v2: None drivers/pwm/core.c | 81 ++ 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 1581f6ab1b1f..0b6697bc8ab8 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -41,6 +41,21 @@ static LIST_HEAD(pwm_chips); static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); static RADIX_TREE(pwm_tree, GFP_KERNEL); +static int dummy_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + return -ENOTSUPP; +} + +static const struct pwm_ops dummy_pwm_ops = { + .apply = dummy_pwm_apply, + .owner = THIS_MODULE, +}; + +static struct device dummy_pwm_dev = { + .init_name = "dummy-pwm", +}; + static struct pwm_device *pwm_to_device(unsigned int pwm) { return radix_tree_lookup(&pwm_tree, pwm); @@ -334,6 +349,33 @@ int pwmchip_add(struct pwm_chip *chip) } EXPORT_SYMBOL_GPL(pwmchip_add); +static int pwmchip_convert_dummy(struct pwm_chip *chip) +{ + struct pwm_chip *dummy; + unsigned int i; + + dummy = kzalloc(sizeof(*dummy), GFP_KERNEL); + if (!dummy) + return -ENOMEM; + + dummy->dev = &dummy_pwm_dev; + dummy->ops = &dummy_pwm_ops; + dummy->npwm = chip->npwm; + dummy->pwms = chip->pwms; + + INIT_LIST_HEAD(&dummy->list); + list_add(&dummy->list, &pwm_chips); + + for (i = 0; i < dummy->npwm; i++) { + struct pwm_device *pwm = &dummy->pwms[i]; + + pwm->chip = dummy; + pwm->state.enabled = false; + } + + return 0; +} + /** * pwmchip_remove() - remove a PWM chip * @chip: the PWM chip to remove @@ -346,7 +388,7 @@ EXPORT_SYMBOL_GPL(pwmchip_add); int pwmchip_remove(struct pwm_chip *chip) { unsigned int i; - int ret = 0; + int ret = 0, requested = 0; pwmchip_sysfs_unexport_children(chip); @@ -356,8 +398,12 @@ int pwmchip_remove(struct pwm_chip *chip) struct pwm_device *pwm = &chip->pwms[i]; if (test_bit(PWMF_REQUESTED, &pwm->flags)) { - ret = -EBUSY; - goto out; + requested = 1; + + if (pwm->chip->ops->free) + pwm->chip->ops->free(pwm->chip, pwm); + + module_put(pwm->chip->ops->owner); } } @@ -366,11 +412,13 @@ int pwmchip_remove(struct pwm_chip *chip) if (IS_ENABLED(CONFIG_OF)) of_pwmchip_remove(chip); - free_pwms(chip); + if (requested) + pwmchip_convert_dummy(chip); + else + free_pwms(chip); pwmchip_sysfs_unexport(chip); -out: mutex_unlock(&pwm_lock); return ret; } @@ -855,6 +903,24 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) } EXPORT_SYMBOL_GPL(pwm_get); +static int pwmchip_remove_dummy(struct pwm_chip *dummy) +{ + unsigned int i; + + for (i = 0; i < dummy->npwm; i++) { + struct pwm_device *pwm = &dummy->pwms[i]; + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + return -EBUSY; + } + + free_pwms(dummy); + list_del_init(&dummy->list); + kfree(dummy); + + return 0; +} + /** * pwm_put() - release a PWM device * @pwm: PWM device @@ -876,7 +942,10 @@ void pwm_put(struct pwm_device *pwm) pwm->label = NULL; - module_put(pwm->chip->ops->owner); + if (pwm->chip->ops == &dummy_pwm_ops) + pwmchip_remove_dummy(pwm->chip); + else + module_put(pwm->chip->ops->owner); out: mutex_unlock(&pwm_lock); } -- 2.11.0
[RFC PATCH v4 6/8] drm/bridge/analogix: Do not use device's drvdata
From: Tomasz Figa The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa Signed-off-by: Jeffy Chen Reviewed-by: Andrzej Hajda --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 47 +++- include/drm/bridge/analogix_dp.h | 19 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "hpd_gpio"); if (ret) {
[RFC PATCH v4 8/8] drm/rockchip: Add device links for master and components
Since we are trying to access components' resources in the master's suspend/resume PM callbacks(e.g. panel), add device links to correct the suspend/resume and shutdown ordering. Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: Use device link to correct the suspend/resume and shutdown ordering, instead of converting rockchip spi's suspend/resume PM callbacks to late suspend/resume PM callbacks. drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 76d63de5921d..af18967f699b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -337,6 +337,8 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) if (!d) break; + + device_link_add(dev, d, DL_FLAG_STATELESS); component_match_add(dev, &match, compare_dev, d); } while (true); } @@ -406,6 +408,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev) static int rockchip_drm_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_link *link; struct component_match *match = NULL; int ret; @@ -414,16 +417,31 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) return ret; match = rockchip_drm_match_add(dev); - if (IS_ERR(match)) - return PTR_ERR(match); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_cleanup_dev_links; + } - return component_master_add_with_match(dev, &rockchip_drm_ops, match); + ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); + if (ret < 0) + goto err_cleanup_dev_links; + + return 0; +err_cleanup_dev_links: + list_for_each_entry(link, &dev->links.consumers, s_node) + device_link_del(link); + return ret; } static int rockchip_drm_platform_remove(struct platform_device *pdev) { + struct device_link *link; + component_master_del(&pdev->dev, &rockchip_drm_ops); + list_for_each_entry(link, &pdev->dev.links.consumers, s_node) + device_link_del(link); + return 0; } -- 2.11.0
[RFC PATCH v4 4/8] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path. Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 1eb02a82fd91..582283da7861 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -383,8 +383,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), * which would have called the encoder cleanup. Do it manually. */ - if (ret) + if (ret) { drm_encoder_cleanup(encoder); + clk_disable_unprepare(hdmi->vpll_clk); + } return ret; } -- 2.11.0
[RFC PATCH v4 1/8] arm64: dts: rockchip: Enable edp disaplay on kevin
Add edp panel and enable related nodes on kevin. Signed-off-by: Jeffy Chen Reviewed-by: Mark Yao --- Changes in v4: None Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + 2 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index a3d3cea7dc4f..bc67b19f0af5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -93,6 +93,18 @@ pwm-delay-us = <1>; }; + edp_panel: edp-panel { + compatible = "sharp,lq123p1jx31", "simple-panel"; + backlight = <&backlight>; + power-supply = <&pp3300_disp>; + + ports { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu { compatible = "murata,ncp15wb473"; pullup-uv = <180>; @@ -264,6 +276,23 @@ ap_i2c_dig: &i2c2 { }; }; +&edp { + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &ppvar_bigcpu_pwm { regulator-min-microvolt = <798674>; regulator-max-microvolt = <1302172>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..470105d651c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -927,6 +927,22 @@ ap_i2c_audio: &i2c8 { dr_mode = "host"; }; +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + #include #include -- 2.11.0
[PATCH v2] drm/rockchip: Don't allow zero sized gem buffer
Currently we only call this from dumb_create, which would guarantee the size is non-zero. But it would be harmless to add a sanity check for it for further extension. This is much the same as: 1a5dff5 drm/msm: Don't allow zero sized buffer objects v2: Rewrite commit message. Signed-off-by: Jeffy Chen --- Changes in v2: Rewrite commit message. drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e570..8917922 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -315,6 +315,11 @@ struct rockchip_gem_object * struct drm_gem_object *obj; int ret; + if (!size) { + DRM_ERROR("gem buffer size is zero\n"); + return ERR_PTR(-EINVAL); + } + size = round_up(size, PAGE_SIZE); rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL); -- 2.1.4
[PATCH] genirq: Check irq disabled & masked states in irq_shutdown
If irq is already disabled and masked, we would hit a unbalanced irq shutdown/disable/mask when freeing it. Add a state check in irq_shutdown to prevent this. Signed-off-by: Jeffy Chen --- kernel/irq/chip.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 686be4b..816da03 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -206,14 +206,20 @@ int irq_startup(struct irq_desc *desc, bool resend) void irq_shutdown(struct irq_desc *desc) { - irq_state_set_disabled(desc); desc->depth = 1; + + if (unlikely(irqd_irq_disabled(&desc->irq_data) && + irqd_irq_masked(&desc->irq_data))) + goto out; + + irq_state_set_disabled(desc); if (desc->irq_data.chip->irq_shutdown) desc->irq_data.chip->irq_shutdown(&desc->irq_data); else if (desc->irq_data.chip->irq_disable) desc->irq_data.chip->irq_disable(&desc->irq_data); else desc->irq_data.chip->irq_mask(&desc->irq_data); +out: irq_domain_deactivate_irq(&desc->irq_data); irq_state_set_masked(desc); } -- 2.1.4
[PATCH v2] genirq: Check irq disabled & masked states in irq_shutdown
If a irq is already disabled & masked, free_irq may cause a unbalanced irq shutdown/disable/mask, for example: devm_request_irq->irq_startup->irq_enable disable_irq <-- disabled and masked devm_free_irq->irq_shutdown <-- try to disable it again This would confuse some pinctrl drivers which would control clk in irq_enable/irq_disable, for example pinctrl-rockchip/pinctrl-nomadik. This patch add a state check in irq_shutdown to prevent that. v2: Rewrite commit message. Signed-off-by: Jeffy Chen --- Changes in v2: Rewrite commit message. kernel/irq/chip.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 686be4b..816da03 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -206,14 +206,20 @@ int irq_startup(struct irq_desc *desc, bool resend) void irq_shutdown(struct irq_desc *desc) { - irq_state_set_disabled(desc); desc->depth = 1; + + if (unlikely(irqd_irq_disabled(&desc->irq_data) && + irqd_irq_masked(&desc->irq_data))) + goto out; + + irq_state_set_disabled(desc); if (desc->irq_data.chip->irq_shutdown) desc->irq_data.chip->irq_shutdown(&desc->irq_data); else if (desc->irq_data.chip->irq_disable) desc->irq_data.chip->irq_disable(&desc->irq_data); else desc->irq_data.chip->irq_mask(&desc->irq_data); +out: irq_domain_deactivate_irq(&desc->irq_data); irq_state_set_masked(desc); } -- 2.1.4
[PATCH v3] genirq: Check irq disabled & masked states in irq_shutdown
If a irq is already disabled, irq_shutdown may try to disable it again, for example: devm_request_irq->irq_startup->irq_enable disable_irq <-- disabled devm_free_irq->irq_shutdown <-- disable it again This would confuse some chips which require balanced irq enable and disable, for example pinctrl-rockchip & pinctrl-nomadik. Add a state check before calling irq_disable to prevent that. v2: Rewrite commit message. v3: Rewrite commit message and not skip irq_shutdown. Signed-off-by: Jeffy Chen --- Changes in v3: Rewrite commit message and not skip irq_shutdown. Changes in v2: Rewrite commit message. kernel/irq/chip.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 686be4b..0ac0c56 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -206,13 +206,23 @@ int irq_startup(struct irq_desc *desc, bool resend) void irq_shutdown(struct irq_desc *desc) { + int irq_disabled = irqd_irq_disabled(&desc->irq_data); + irq_state_set_disabled(desc); desc->depth = 1; if (desc->irq_data.chip->irq_shutdown) desc->irq_data.chip->irq_shutdown(&desc->irq_data); - else if (desc->irq_data.chip->irq_disable) + /* +* 1/ Some chips may require balanced irq enable &_disable. +* 2/ Due to the lazy disable approach, a irq could be +*disabled but unmasked. +* +* So if this irq is already disabled, let's mask it instead +* of trying to call irq_disable again. +*/ + else if (desc->irq_data.chip->irq_disable && !irq_disabled) desc->irq_data.chip->irq_disable(&desc->irq_data); - else + else if (desc->irq_data.chip->irq_mask) desc->irq_data.chip->irq_mask(&desc->irq_data); irq_domain_deactivate_irq(&desc->irq_data); irq_state_set_masked(desc); -- 2.1.4
[PATCH] scsi: .gitignore: Add scsi_devinfo_tbl.c
Add generated scsi_devinfo_tbl.c into .gitignore. Signed-off-by: Jeffy Chen --- drivers/scsi/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/.gitignore b/drivers/scsi/.gitignore index c89ae9a04399..e2956741fbd1 100644 --- a/drivers/scsi/.gitignore +++ b/drivers/scsi/.gitignore @@ -1 +1,2 @@ 53c700_d.h +scsi_devinfo_tbl.c -- 2.11.0
[RFC PATCH v8 1/7] dt-bindings: PCI: Add definition of PCIe WAKE# irq and PCI irq
Add optional interrupts for PCIe WAKE# pin and PCI interrupt pin. Signed-off-by: Jeffy Chen --- Changes in v8: Add optional "pci", and rewrite commit message. Changes in v7: None Changes in v6: None Changes in v5: Move to pci.txt Changes in v3: None Changes in v2: None Documentation/devicetree/bindings/pci/pci.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/pci.txt b/Documentation/devicetree/bindings/pci/pci.txt index c77981c5dd18..faed405811cd 100644 --- a/Documentation/devicetree/bindings/pci/pci.txt +++ b/Documentation/devicetree/bindings/pci/pci.txt @@ -24,3 +24,6 @@ driver implementation may support the following properties: unsupported link speed, for instance, trying to do training for unsupported link speed, etc. Must be '4' for gen4, '3' for gen3, '2' for gen2, and '1' for gen1. Any other values are invalid. +- interrupts: Interrupt specifier for each name in interrupt-names. +- interrupt-names: May contains "wakeup" for PCIe WAKE# interrupt and "pci" + for PCI interrupt. -- 2.11.0
[RFC PATCH v8 2/7] mwifiex: Disable wakeup irq handling for pcie
We are going to handle the wakeup irq in the pci core. Signed-off-by: Jeffy Chen --- Changes in v8: None Changes in v7: None Changes in v6: None Changes in v5: None Changes in v3: None Changes in v2: None drivers/net/wireless/marvell/mwifiex/main.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index ee40b739b289..ba081c16f85c 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1568,6 +1568,10 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter) goto err_exit; adapter->dt_node = dev->of_node; + + if (adapter->iface_type != MWIFIEX_PCIE) + goto err_exit; + adapter->irq_wakeup = irq_of_parse_and_map(adapter->dt_node, 0); if (!adapter->irq_wakeup) { dev_dbg(dev, "fail to parse irq_wakeup from device tree\n"); -- 2.11.0
[RFC PATCH v8 0/7] PCI: rockchip: Move PCIe WAKE# handling into pci core
Currently we are handling wake irq in mrvl wifi driver. Move it into pci core. Tested on my chromebook bob(with cros 4.4 kernel and mrvl wifi). Changes in v8: Add optional "pci", and rewrite commit message. Rewrite the commit message. Add pci-of.c and use platform_pm_ops to handle the PCIe WAKE# signal. Changes in v7: Move PCIE_WAKE handling into pci core. Changes in v6: Fix device_init_wake error handling, and add some comments. Changes in v5: Move to pci.txt Use "wakeup" instead of "wake" Rebase. Changes in v3: Fix error handling. Changes in v2: Use dev_pm_set_dedicated_wake_irq. Jeffy Chen (7): dt-bindings: PCI: Add definition of PCIe WAKE# irq and PCI irq mwifiex: Disable wakeup irq handling for pcie arm64: dts: rockchip: Handle PCIe WAKE# signal in pcie driver for Gru of/irq: Adjust of pci irq parsing for multiple interrupts PCI: Make pci_platform_pm_ops's callbacks optional PCI / PM: Move acpi wakeup code to pci core PCI / PM: Add support for the PCIe WAKE# signal for OF Documentation/devicetree/bindings/pci/pci.txt | 3 + arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 +-- drivers/net/wireless/marvell/mwifiex/main.c | 4 + drivers/of/of_pci_irq.c | 13 ++- drivers/pci/Makefile | 2 +- drivers/pci/pci-acpi.c| 121 +++ drivers/pci/pci-driver.c | 9 ++ drivers/pci/pci-of.c | 136 ++ drivers/pci/pci.c | 112 + drivers/pci/pci.h | 31 -- drivers/pci/probe.c | 12 ++- drivers/pci/remove.c | 2 + include/linux/pci.h | 2 + 13 files changed, 365 insertions(+), 97 deletions(-) create mode 100644 drivers/pci/pci-of.c -- 2.11.0
[RFC PATCH v8 4/7] of/irq: Adjust of pci irq parsing for multiple interrupts
Currently we are considering the first irq as the PCI interrupt pin, but a pci device may have multiple interrupts(e.g. PCIe WAKE# pin). Only parse the PCI interrupt pin when the irq is unnamed or named as "pci". Signed-off-by: Jeffy Chen --- Changes in v8: None Changes in v7: None Changes in v6: None Changes in v5: None Changes in v3: None Changes in v2: None drivers/of/of_pci_irq.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 3a05568f65df..8b69211f0b88 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -27,7 +27,18 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq */ dn = pci_device_to_OF_node(pdev); if (dn) { - rc = of_irq_parse_one(dn, 0, out_irq); + struct property *prop; + const char *name; + int index = 0; + + prop = of_find_property(dn, "interrupt-names", NULL); + for (name = of_prop_next_string(prop, NULL); name; +name = of_prop_next_string(prop, name), index++) { + if (!strcmp(name, "pci")) + break; + } + + rc = of_irq_parse_one(dn, index, out_irq); if (!rc) return rc; } -- 2.11.0
[RFC PATCH v8 7/7] PCI / PM: Add support for the PCIe WAKE# signal for OF
Add pci-of.c to handle the PCIe WAKE# interrupt. Also use the dedicated wakeirq infrastructure to simplify it. Signed-off-by: Jeffy Chen --- Changes in v8: Add pci-of.c and use platform_pm_ops to handle the PCIe WAKE# signal. Changes in v7: Move PCIE_WAKE handling into pci core. Changes in v6: Fix device_init_wake error handling, and add some comments. Changes in v5: Rebase. Changes in v3: Fix error handling. Changes in v2: Use dev_pm_set_dedicated_wake_irq. drivers/pci/Makefile | 2 +- drivers/pci/pci-of.c | 136 +++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 drivers/pci/pci-of.c diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 66a21acad952..4f76dbdb024c 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_PCI_ECAM) += ecam.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o -obj-$(CONFIG_OF) += of.o +obj-$(CONFIG_OF) += of.o pci-of.o ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG diff --git a/drivers/pci/pci-of.c b/drivers/pci/pci-of.c new file mode 100644 index ..55a33206fc84 --- /dev/null +++ b/drivers/pci/pci-of.c @@ -0,0 +1,136 @@ +/* + * OF PCI PM support + * + * Copyright (c) 2017 Rockchip, Inc. + * + * Author: Jeffy Chen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include "pci.h" + +struct of_pci_pm_data { + struct device *dev; + unsigned intwakeup_irq; + atomic_twakeup_cnt; +}; + +static void *of_pci_setup(struct device *dev) +{ + struct of_pci_pm_data *data; + int irq; + + if (!dev->of_node) + return NULL; + + data = devm_kzalloc(dev, sizeof(struct of_pci_pm_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + irq = of_irq_get_byname(dev->of_node, "wakeup"); + if (irq < 0) { + if (irq == -EPROBE_DEFER) + return ERR_PTR(irq); + + return NULL; + } + + data->wakeup_irq = irq; + data->dev = dev; + + device_init_wakeup(dev, false); + + dev_info(dev, "Wakeup IRQ %d\n", irq); + return data; +} + +static void *of_pci_setup_dev(struct pci_dev *pci_dev) +{ + return of_pci_setup(&pci_dev->dev); +} + +static void *of_pci_setup_host_bridge(struct pci_host_bridge *bridge) +{ + return of_pci_setup(bridge->dev.parent); +} + +static void of_pci_cleanup(void *pmdata) +{ + struct of_pci_pm_data *data = pmdata; + + if (IS_ERR_OR_NULL(data)) { + device_init_wakeup(data->dev, false); + dev_pm_clear_wake_irq(data->dev); + } +} + +static bool of_pci_can_wakeup(void *pmdata) +{ + struct of_pci_pm_data *data = pmdata; + + if (IS_ERR_OR_NULL(data)) + return false; + + return data->wakeup_irq > 0; +} + +static int of_pci_dev_wakeup(void *pmdata, bool enable) +{ + struct of_pci_pm_data *data = pmdata; + struct device *dev = data->dev; + int ret; + + if (!enable) { + dev_pm_clear_wake_irq(dev); + return device_set_wakeup_enable(dev, false); + } + + ret = device_set_wakeup_enable(dev, true); + if (ret < 0) + return ret; + + ret = dev_pm_set_dedicated_wake_irq(dev, data->wakeup_irq); + if (ret < 0) { + device_set_wakeup_enable(dev, false); + return ret; + } + + return 0; +} + +static int of_pci_bridge_wakeup(void *pmdata, bool enable) +{ + struct of_pci_pm_data *data = pmdata; + + if (enable && atomic_inc_return(&data->wakeup_cnt) != 1) + return 0; + + if (!enable && atomic_dec_return(&data->wakeup_cnt) != 0) + return 0; + + return of_pci_dev_wakeup(pmdata, enable); +} + +static const struct pci_platform_pm_ops of_pci_platform_pm = { + .setup_dev = of_pci_setup_dev, + .setup_host_bridge = of_pci_setup_host_bridge, + .cleanup= of_pci_cleanup, + .can_wakeup = of_pci_can_wakeup, + .dev_wakeup = of_pci_dev_wakeup, + .bridge_wakeup = of_pci_bridge_wakeup, +}; + +static int __init of_pci_init(void) +{ + pci_set_platform_pm(&of_pci_platform_pm); + return 0; +} +arch_initcall(of_pci_init); -- 2.11.0
[RFC PATCH v8 6/7] PCI / PM: Move acpi wakeup code to pci core
Move acpi wakeup code to pci core as pci_set_wakeup(), so that other platform could reuse it. Also add .setup_dev() / .setup_host_bridge() / .cleanup() platform pm ops's callbacks to setup and cleanup pci devices and host bridge for wakeup. Signed-off-by: Jeffy Chen --- Changes in v8: None Changes in v7: None Changes in v6: None Changes in v5: None Changes in v3: None Changes in v2: None drivers/pci/pci-acpi.c | 121 +++ drivers/pci/pci-driver.c | 9 drivers/pci/pci.c| 84 drivers/pci/pci.h| 28 +-- drivers/pci/probe.c | 12 - drivers/pci/remove.c | 2 + include/linux/pci.h | 2 + 7 files changed, 180 insertions(+), 78 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 4708eb9df71b..ee96e7afe1ac 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -569,31 +569,6 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) return state_conv[state]; } -static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable) -{ - while (bus->parent) { - if (acpi_pm_device_can_wakeup(&bus->self->dev)) - return acpi_pm_set_bridge_wakeup(&bus->self->dev, enable); - - bus = bus->parent; - } - - /* We have reached the root bus. */ - if (bus->bridge) { - if (acpi_pm_device_can_wakeup(bus->bridge)) - return acpi_pm_set_bridge_wakeup(bus->bridge, enable); - } - return 0; -} - -static int acpi_pci_wakeup(struct pci_dev *dev, bool enable) -{ - if (acpi_pm_device_can_wakeup(&dev->dev)) - return acpi_pm_set_device_wakeup(&dev->dev, enable); - - return acpi_pci_propagate_wakeup(dev->bus, enable); -} - static bool acpi_pci_need_resume(struct pci_dev *dev) { struct acpi_device *adev = ACPI_COMPANION(&dev->dev); @@ -610,14 +585,29 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) return !!adev->power.flags.dsw_present; } -static const struct pci_platform_pm_ops acpi_pci_platform_pm = { - .is_manageable = acpi_pci_power_manageable, - .set_state = acpi_pci_set_power_state, - .get_state = acpi_pci_get_power_state, - .choose_state = acpi_pci_choose_state, - .set_wakeup = acpi_pci_wakeup, - .need_resume = acpi_pci_need_resume, -}; +static bool acpi_pci_can_wakeup(void *pmdata) +{ + struct device *dev = pmdata; + + if (!dev) + return false; + + return acpi_pm_device_can_wakeup(dev); +} + +static int acpi_pci_dev_wakeup(void *pmdata, bool enable) +{ + struct device *dev = pmdata; + + return acpi_pm_set_device_wakeup(dev, enable); +} + +static int acpi_pci_bridge_wakeup(void *pmdata, bool enable) +{ + struct device *dev = pmdata; + + return acpi_pm_set_bridge_wakeup(dev, enable); +} void acpi_pci_add_bus(struct pci_bus *bus) { @@ -658,20 +648,6 @@ void acpi_pci_remove_bus(struct pci_bus *bus) acpi_pci_slot_remove(bus); } -/* ACPI bus type */ -static struct acpi_device *acpi_pci_find_companion(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - bool check_children; - u64 addr; - - check_children = pci_is_bridge(pci_dev); - /* Please ref to ACPI spec for the syntax of _ADR */ - addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); - return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, - check_children); -} - /** * pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI * @pdev: the PCI device whose delay is to be updated @@ -723,34 +699,55 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev, ACPI_FREE(obj); } -static void pci_acpi_setup(struct device *dev) +static void *acpi_pci_setup_dev(struct pci_dev *pci_dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_device *adev = ACPI_COMPANION(&pci_dev->dev); if (!adev) - return; + return NULL; pci_acpi_optimize_delay(pci_dev, adev->handle); pci_acpi_add_pm_notifier(adev, pci_dev); if (!adev->wakeup.flags.valid) - return; + return NULL; + + device_set_wakeup_capable(&pci_dev->dev, true); + acpi_pm_set_device_wakeup(&pci_dev->dev, false); - device_set_wakeup_capable(dev, true); - acpi_pci_wakeup(pci_dev, false); + return &pci_dev->dev; } -static void pci_acpi_cleanup(struct device *dev) +static void *acpi_pci_setup_host_bridge(struct pci_host_bridge *bridge) { - struct acpi_device *adev = ACPI_COMPANION(dev); +
[RFC PATCH v8 5/7] PCI: Make pci_platform_pm_ops's callbacks optional
Allow platforms not to provide some of the pci_platform_pm_ops's callbacks. Also change the return value -ENOSYS to -ENODEV for: warning: drivers/pci/pci.c,594: ENOSYS means 'invalid syscall nr' and nothing else Signed-off-by: Jeffy Chen --- Changes in v8: None Changes in v7: None Changes in v6: None Changes in v5: None Changes in v3: None Changes in v2: None drivers/pci/pci.c | 38 +- drivers/pci/pci.h | 5 + 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f0d68066c726..e120b00a9017 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -572,46 +572,58 @@ static void pci_restore_bars(struct pci_dev *dev) static const struct pci_platform_pm_ops *pci_platform_pm; -int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) +void pci_set_platform_pm(const struct pci_platform_pm_ops *ops) { - if (!ops->is_manageable || !ops->set_state || !ops->get_state || - !ops->choose_state || !ops->set_wakeup || !ops->need_resume) - return -EINVAL; pci_platform_pm = ops; - return 0; } static inline bool platform_pci_power_manageable(struct pci_dev *dev) { - return pci_platform_pm ? pci_platform_pm->is_manageable(dev) : false; + if (pci_platform_pm && pci_platform_pm->is_manageable) + return pci_platform_pm->is_manageable(dev); + + return false; } static inline int platform_pci_set_power_state(struct pci_dev *dev, pci_power_t t) { - return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS; + if (pci_platform_pm && pci_platform_pm->set_state) + return pci_platform_pm->set_state(dev, t); + + return -ENODEV; } static inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev) { - return pci_platform_pm ? pci_platform_pm->get_state(dev) : PCI_UNKNOWN; + if (pci_platform_pm && pci_platform_pm->get_state) + return pci_platform_pm->get_state(dev); + + return PCI_UNKNOWN; } static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) { - return pci_platform_pm ? - pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; + if (pci_platform_pm && pci_platform_pm->choose_state) + return pci_platform_pm->choose_state(dev); + + return PCI_POWER_ERROR; } static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable) { - return pci_platform_pm ? - pci_platform_pm->set_wakeup(dev, enable) : -ENODEV; + if (pci_platform_pm && pci_platform_pm->set_wakeup) + return pci_platform_pm->set_wakeup(dev, enable); + + return -ENODEV; } static inline bool platform_pci_need_resume(struct pci_dev *dev) { - return pci_platform_pm ? pci_platform_pm->need_resume(dev) : false; + if (pci_platform_pm && pci_platform_pm->need_resume) + return pci_platform_pm->need_resume(dev); + + return false; } /** diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e816a13e6259..048668271014 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -52,9 +52,6 @@ int pci_probe_reset_function(struct pci_dev *dev); * @need_resume: returns 'true' if the given device (which is currently * suspended) needs to be resumed to be configured for system * wakeup. - * - * If given platform is generally capable of power managing PCI devices, all of - * these callbacks are mandatory. */ struct pci_platform_pm_ops { bool (*is_manageable)(struct pci_dev *dev); @@ -65,7 +62,7 @@ struct pci_platform_pm_ops { bool (*need_resume)(struct pci_dev *dev); }; -int pci_set_platform_pm(const struct pci_platform_pm_ops *ops); +void pci_set_platform_pm(const struct pci_platform_pm_ops *ops); void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_power_up(struct pci_dev *dev); void pci_disable_enabled_device(struct pci_dev *dev); -- 2.11.0
[RFC PATCH v8 3/7] arm64: dts: rockchip: Handle PCIe WAKE# signal in pcie driver for Gru
Currently we are handling PCIe WAKE# signal in mrvl wifi driver. Move it to rockchip pcie driver for Gru boards. Also avoid this irq been considered as the PCI interrupt pin in the of_irq_parse_pci(). Signed-off-by: Jeffy Chen --- Changes in v8: Rewrite the commit message. Changes in v7: None Changes in v6: None Changes in v5: Use "wakeup" instead of "wake" Changes in v3: None Changes in v2: None arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..8e37da69f693 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -708,7 +708,15 @@ ap_i2c_audio: &i2c8 { ep-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqn_cpm>, <&wifi_perst_l>; + pinctrl-0 = <&pcie_clkreqn_cpm>, <&wlan_host_wake_l>, <&wifi_perst_l>; + + interrupts-extended = <&gic GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <&gic GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>, + <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sys", "legacy", "client", "wakeup"; + /delete-property/ interrupts; + vpcie3v3-supply = <&pp3300_wifi_bt>; vpcie1v8-supply = <&wlan_pd_n>; /* HACK: see &wlan_pd_n */ vpcie0v9-supply = <&pp900_pcie>; @@ -723,11 +731,6 @@ ap_i2c_audio: &i2c8 { compatible = "pci1b4b,2b42"; reg = <0x8301 0x0 0x 0x0 0x0010 0x8301 0x0 0x0010 0x0 0x0010>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&wlan_host_wake_l>; - wakeup-source; }; }; }; -- 2.11.0
[PATCH] ARM: Fix zImage file size not aligned with CONFIG_EFI_STUB enabled
The zImage file size should be aligned. Fixes: e4bae4d0b5f3 ("arm/efi: Split zImage code and data into separate PE/COFF sections") Signed-off-by: Jeffy Chen --- arch/arm/boot/compressed/vmlinux.lds.S | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index b38dcef90756..1636fa259577 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S @@ -70,10 +70,6 @@ SECTIONS .got : { *(.got) } _got_end = .; - /* ensure the zImage file size is always a multiple of 64 bits */ - /* (without a dummy byte, ld just ignores the empty section) */ - .pad : { BYTE(0); . = ALIGN(8); } - #ifdef CONFIG_EFI_STUB .data : ALIGN(4096) { __pecoff_data_start = .; @@ -93,6 +89,10 @@ SECTIONS __pecoff_data_rawsize = . - ADDR(.data); #endif + /* ensure the zImage file size is always a multiple of 64 bits */ + /* (without a dummy byte, ld just ignores the empty section) */ + .pad : { BYTE(0); . = ALIGN(8); } + _edata = .; _magic_sig = ZIMAGE_MAGIC(0x016f2818); -- 2.11.0
[PATCH] driver core: Make sure device detached from driver before deleting it
There are cases we call device_del() without detaching it from the driver(e.g. spi core del children devices). Signed-off-by: Jeffy Chen --- drivers/base/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 12ebd055724c..717efc3020af 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1951,6 +1951,8 @@ void device_del(struct device *dev) struct kobject *glue_dir = NULL; struct class_interface *class_intf; + device_release_driver(dev); + /* Notify clients of device removal. This call must come * before dpm_sysfs_remove(). */ -- 2.11.0
[PATCH] spi: Detach spi device from driver when unregister it
Make sure spi device detached before unregistering it. Signed-off-by: Jeffy Chen --- drivers/spi/spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6e65524cbfd9..9114efb2eb8c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -648,6 +648,8 @@ void spi_unregister_device(struct spi_device *spi) } if (ACPI_COMPANION(&spi->dev)) acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev)); + + device_release_driver(&spi->dev); device_unregister(&spi->dev); } EXPORT_SYMBOL_GPL(spi_unregister_device); -- 2.11.0
[PATCH] driver core: Move device_links_purge() after bus_remove_device()
Currently we are unbinding device link consumers when detaching the supplier. So we need to make sure the detaching happens before purging the supplier's device links. Move device_links_purge() after bus_remove_device() in device_del() for that. Signed-off-by: Jeffy Chen --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 12ebd055724c..2e683cdf4a08 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1958,7 +1958,6 @@ void device_del(struct device *dev) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); - device_links_purge(dev); dpm_sysfs_remove(dev); if (parent) klist_del(&dev->p->knode_parent); @@ -1986,6 +1985,7 @@ void device_del(struct device *dev) device_pm_remove(dev); driver_deferred_probe_del(dev); device_remove_properties(dev); + device_links_purge(dev); /* Notify the platform of the removal, in case they * need to do anything... -- 2.11.0
[PATCH v5 3/9] drm/bridge: analogix: Do not use device's drvdata
The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa Signed-off-by: Jeffy Chen Reviewed-by: Andrzej Hajda Reviewed-by: Sean Paul Acked-by: Jingoo Han Acked-by: Archit Taneja --- Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 - include/drm/bridge/analogix_dp.h | 19 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "hpd_gpio"); if (ret) {
[PATCH v5 4/9] drm/bridge: analogix_dp: Fix connector & encoder cleanup
Since we are initing connector in the core driver and encoder in the plat driver, let's clean them up in the right places. Signed-off-by: Jeffy Chen --- Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 -- drivers/gpu/drm/exynos/exynos_dp.c | 7 +-- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 15 ++- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 74d274b6d31d..3f910ab36ff6 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1409,7 +1409,6 @@ analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_create_bridge(drm_dev, dp); if (ret) { DRM_ERROR("failed to create bridge (%d)\n", ret); - drm_encoder_cleanup(dp->encoder); goto err_disable_pm_runtime; } @@ -1432,7 +1431,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) { analogix_dp_bridge_disable(dp->bridge); dp->connector.funcs->destroy(&dp->connector); - dp->encoder->funcs->destroy(dp->encoder); if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index f7e5b2c405ed..33319a858f3a 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c @@ -185,8 +185,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) dp->plat_data.encoder = encoder; dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(&dp->encoder); return PTR_ERR(dp->adp); + } return 0; } @@ -196,7 +198,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, { struct exynos_dp_device *dp = dev_get_drvdata(dev); - return analogix_dp_unbind(dp->adp); + analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(&dp->encoder); } static const struct component_ops exynos_dp_ops = { diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index fa0365de31d2..c0fb3f3748f4 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -261,13 +261,8 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; -static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { - .destroy = rockchip_dp_drm_encoder_destroy, + .destroy = drm_encoder_cleanup, }; static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) @@ -361,12 +356,13 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; INIT_WORK(&dp->psr_work, analogix_dp_psr_work); - rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); - if (IS_ERR(dp->adp)) + if (IS_ERR(dp->adp)) { + dp->encoder.funcs->destroy(&dp->encoder); return PTR_ERR(dp->adp); + } + rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); return 0; } @@ -377,6 +373,7 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(&dp->encoder); analogix_dp_unbind(dp->adp); + dp->encoder.funcs->destroy(&dp->encoder); } static const struct component_ops rockchip_dp_component_ops = { -- 2.11.0
[PATCH v5 2/9] drm/rockchip: analogix_dp: Remove unnecessary init code
Remove unnecessary init code, since we would do it in the power_on() callback. Also move of parse code to probe(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen --- Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++--- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..8cae5ad926cd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { .destroy = rockchip_dp_drm_encoder_destroy, }; -static int rockchip_dp_init(struct rockchip_dp_device *dp) +static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) { struct device *dev = dp->dev; struct device_node *np = dev->of_node; @@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) return PTR_ERR(dp->rst); } - ret = clk_prepare_enable(dp->pclk); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); - return ret; - } - - ret = rockchip_dp_pre_init(dp); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); - clk_disable_unprepare(dp->pclk); - return ret; - } - return 0; } @@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, if (!dp_data) return -ENODEV; - ret = rockchip_dp_init(dp); - if (ret < 0) - return ret; - dp->data = dp_data; dp->drm_dev = drm_dev; @@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(&dp->encoder); analogix_dp_unbind(dev, master, data); - clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { @@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev) int ret; ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); - if (ret) + if (ret < 0) return ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); @@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev) return -ENOMEM; dp->dev = dev; - dp->plat_data.panel = panel; + ret = rockchip_dp_of_probe(dp); + if (ret < 0) + return ret; + /* * We just use the drvdata until driver run into component * add function, and then we would set drvdata to null, so -- 2.11.0
[PATCH v5 6/9] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen --- Changes in v5: Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9a96ff6b022b 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + hdmi->connector.funcs->destroy(&hdmi->connector); + hdmi->encoder.funcs->destroy(&hdmi->encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } @@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, hdmi->connector.funcs->destroy(&hdmi->connector); hdmi->encoder.funcs->destroy(&hdmi->encoder); - clk_disable_unprepare(hdmi->pclk); i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); } static const struct component_ops inno_hdmi_ops = { -- 2.11.0
[PATCH v5 8/9] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
Let plat drivers own the drvdata, so that they could cleanup resources in their unbind(). Signed-off-by: Jeffy Chen --- Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++--- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +-- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++ drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 -- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 --- include/drm/bridge/dw_hdmi.h| 17 ++-- 6 files changed, 77 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ff1b3d2b5d06..6fbfafc5832b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } -void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) { mutex_lock(&hdmi->mutex); @@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) } mutex_unlock(&hdmi->mutex); } - -void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) -{ - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - - __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); -} EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) @@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) */ if (intr_stat & (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - __dw_hdmi_setup_rx_sense(hdmi, -phy_stat & HDMI_PHY_HPD, -phy_stat & HDMI_PHY_RX_SENSE); + dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) cec_notifier_set_phys_addr(hdmi->cec_notifier, @@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev, if (hdmi->i2c) dw_hdmi_i2c_init(hdmi); - platform_set_drvdata(pdev, hdmi); - return hdmi; err_iahb: @@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) /* - * Probe/remove API, used from platforms based on the DRM bridge API. */ -int dw_hdmi_probe(struct platform_device *pdev, - const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; drm_bridge_add(&hdmi->bridge); - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_probe); -void dw_hdmi_remove(struct platform_device *pdev) +void dw_hdmi_remove(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = platform_get_drvdata(pdev); - drm_bridge_remove(&hdmi->bridge); __dw_hdmi_remove(hdmi); @@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove); /* - * Bind/unbind API, used from platforms based on the component framework. */ -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, -const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; int ret; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); if (ret) { __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); - return ret; + return ERR_PTR(ret); } - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_bind); -void dw_hdmi_unbind(struct device *dev) +void dw_hdmi_unbind(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - __dw_hdmi_remove(hdmi); } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index b62763aa8706..b01d03e02ce0 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.
[PATCH v5 7/9] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
We inited connector in attach(), so need a detach() to cleanup. Also fix wrong use of dw_hdmi_remove() in bind(). Signed-off-by: Jeffy Chen --- Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index bf14214fa464..ff1b3d2b5d06 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) return 0; } +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +{ + struct dw_hdmi *hdmi = bridge->driver_private; + + drm_connector_cleanup(&hdmi->connector); +} + static enum drm_mode_status dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) @@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .attach = dw_hdmi_bridge_attach, + .detach = dw_hdmi_bridge_detach, .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, .mode_set = dw_hdmi_bridge_mode_set, @@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); if (ret) { - dw_hdmi_remove(pdev); + __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); return ret; } -- 2.11.0
[PATCH v5 9/9] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path and unbind(). Also inline clk_prepare_enable() with bind(). Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen --- Changes in v5: Add disable to unbind(), and inline clk_prepare_enable() with bind(). drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 791ab938f998..e936dfe6c03d 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->grf_clk); } - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Failed to enable HDMI vpll: %d\n", ret); - return ret; - } - return 0; } @@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, return ret; } + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); @@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); if (IS_ERR(hdmi->hdmi)) { encoder->funcs->destroy(encoder); + clk_disable_unprepare(hdmi->vpll_clk); return PTR_ERR(hdmi->hdmi); } @@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, dw_hdmi_unbind(hdmi->hdmi); hdmi->encoder.funcs->destroy(&hdmi->encoder); + clk_disable_unprepare(hdmi->vpll_clk); } static const struct component_ops dw_hdmi_rockchip_ops = { -- 2.11.0
[PATCH v5 5/9] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen --- Changes in v5: Call the destroy hook in the error handling path like in unbind(). drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..e72d4e2b61aa 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(&dsi->dsi_host); -err_cleanup: - drm_encoder_cleanup(&dsi->encoder); - drm_connector_cleanup(&dsi->connector); -err_pllref: +err_disable_pm_runtime: + pm_runtime_disable(dev); + dsi->connector.funcs->destroy(&dsi->connector); + dsi->encoder.funcs->destroy(&dsi->encoder); +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(&dsi->dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(&dsi->connector); + dsi->encoder.funcs->destroy(&dsi->encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0
[PATCH v5 1/9] arm64: dts: rockchip: Enable edp disaplay on kevin
Add edp panel and enable related nodes on kevin. Signed-off-by: Jeffy Chen Reviewed-by: Mark Yao --- Changes in v5: None arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 29 +++ arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 16 + 2 files changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index a3d3cea7dc4f..bc67b19f0af5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -93,6 +93,18 @@ pwm-delay-us = <1>; }; + edp_panel: edp-panel { + compatible = "sharp,lq123p1jx31", "simple-panel"; + backlight = <&backlight>; + power-supply = <&pp3300_disp>; + + ports { + panel_in_edp: endpoint { + remote-endpoint = <&edp_out_panel>; + }; + }; + }; + thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu { compatible = "murata,ncp15wb473"; pullup-uv = <180>; @@ -264,6 +276,23 @@ ap_i2c_dig: &i2c2 { }; }; +&edp { + status = "okay"; + + ports { + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + edp_out_panel: endpoint@0 { + reg = <0>; + remote-endpoint = <&panel_in_edp>; + }; + }; + }; +}; + &ppvar_bigcpu_pwm { regulator-min-microvolt = <798674>; regulator-max-microvolt = <1302172>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 5772c52fbfd3..470105d651c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -927,6 +927,22 @@ ap_i2c_audio: &i2c8 { dr_mode = "host"; }; +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + #include #include -- 2.11.0
[PATCH v2] driver core: Move device_links_purge() after bus_remove_device()
The current ordering of code in device_del() triggers a WARN_ON() in device_links_purge(), because of an unexpected link status. The device_links_unbind_consumers() call in device_release_driver() has to take place before device_links_purge() for the status of all links to be correct, so move the device_links_purge() call in device_del() after the invocation of bus_remove_device() which calls device_release_driver(). Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeffy Chen --- Changes in v2: Update commit message provided by Rafael. drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 12ebd055724c..2e683cdf4a08 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1958,7 +1958,6 @@ void device_del(struct device *dev) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); - device_links_purge(dev); dpm_sysfs_remove(dev); if (parent) klist_del(&dev->p->knode_parent); @@ -1986,6 +1985,7 @@ void device_del(struct device *dev) device_pm_remove(dev); driver_deferred_probe_del(dev); device_remove_properties(dev); + device_links_purge(dev); /* Notify the platform of the removal, in case they * need to do anything... -- 2.11.0
[PATCH v6 02/10] drm/rockchip: analogix_dp: Remove unnecessary init code
Remove unnecessary init code, since we would do it in the power_on() callback. Also move of parse code to probe(). Fixes: 9e32e16e9e98 ("drm: rockchip: dp: add rockchip platform dp driver") Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 27 ++--- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 4d3f6ad0abdd..8cae5ad926cd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -269,7 +269,7 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { .destroy = rockchip_dp_drm_encoder_destroy, }; -static int rockchip_dp_init(struct rockchip_dp_device *dp) +static int rockchip_dp_of_probe(struct rockchip_dp_device *dp) { struct device *dev = dp->dev; struct device_node *np = dev->of_node; @@ -303,19 +303,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) return PTR_ERR(dp->rst); } - ret = clk_prepare_enable(dp->pclk); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); - return ret; - } - - ret = rockchip_dp_pre_init(dp); - if (ret < 0) { - DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); - clk_disable_unprepare(dp->pclk); - return ret; - } - return 0; } @@ -361,10 +348,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, if (!dp_data) return -ENODEV; - ret = rockchip_dp_init(dp); - if (ret < 0) - return ret; - dp->data = dp_data; dp->drm_dev = drm_dev; @@ -398,7 +381,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, rockchip_drm_psr_unregister(&dp->encoder); analogix_dp_unbind(dev, master, data); - clk_disable_unprepare(dp->pclk); } static const struct component_ops rockchip_dp_component_ops = { @@ -414,7 +396,7 @@ static int rockchip_dp_probe(struct platform_device *pdev) int ret; ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); - if (ret) + if (ret < 0) return ret; dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); @@ -422,9 +404,12 @@ static int rockchip_dp_probe(struct platform_device *pdev) return -ENOMEM; dp->dev = dev; - dp->plat_data.panel = panel; + ret = rockchip_dp_of_probe(dp); + if (ret < 0) + return ret; + /* * We just use the drvdata until driver run into component * add function, and then we would set drvdata to null, so -- 2.11.0
[PATCH v6 03/10] drm/bridge: analogix: Do not use device's drvdata
The driver that instantiates the bridge should own the drvdata, as all driver model callbacks (probe, remove, shutdown, PM ops, etc.) are also owned by its driver struct. Moreover, storing two different pointer types in driver data depending on driver initialization status is barely a good practice and in fact has led to many bugs in this driver. Let's clean up this mess and change Analogix entry points to simply accept some opaque struct pointer, adjusting their users at the same time to avoid breaking the compilation. Signed-off-by: Tomasz Figa Signed-off-by: Jeffy Chen Reviewed-by: Andrzej Hajda Reviewed-by: Sean Paul Acked-by: Jingoo Han Acked-by: Archit Taneja --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 50 +- drivers/gpu/drm/exynos/exynos_dp.c | 26 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 49 - include/drm/bridge/analogix_dp.h | 19 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 5dd3f1cd074a..74d274b6d31d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_supported(struct device *dev) +int analogix_dp_psr_supported(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); return dp->psr_support; } EXPORT_SYMBOL_GPL(analogix_dp_psr_supported); -int analogix_dp_enable_psr(struct device *dev) +int analogix_dp_enable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; if (!dp->psr_support) @@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev) } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); -int analogix_dp_disable_psr(struct device *dev) +int analogix_dp_disable_psr(struct analogix_dp_device *dp) { - struct analogix_dp_device *dp = dev_get_drvdata(dev); struct edp_vsc_psr psr_vsc; int ret; @@ -1281,8 +1278,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, return analogix_dp_transfer(dp, msg); } -int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, -struct analogix_dp_plat_data *plat_data) +struct analogix_dp_device * +analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, +struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; @@ -1292,14 +1290,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (!plat_data) { dev_err(dev, "Invalided input plat_data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); if (!dp) - return -ENOMEM; - - dev_set_drvdata(dev, dp); + return ERR_PTR(-ENOMEM); dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; @@ -1316,7 +1312,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, ret = analogix_dp_dt_parse_pdata(dp); if (ret) - return ret; + return ERR_PTR(ret); dp->phy = devm_phy_get(dp->dev, "dp"); if (IS_ERR(dp->phy)) { @@ -1330,14 +1326,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (ret == -ENOSYS || ret == -ENODEV) dp->phy = NULL; else - return ret; + return ERR_PTR(ret); } } dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(dp->clock); + return ERR_CAST(dp->clock); } clk_prepare_enable(dp->clock); @@ -1346,7 +1342,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dp->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dp->reg_base)) - return PTR_ERR(dp->reg_base); + return ERR_CAST(dp->reg_base); dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd"); @@ -1367,7 +1363,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, "h
[PATCH v6 05/10] drm/rockchip: analogix_dp: Add a sanity check for rockchip_drm_psr_register()
The rockchip_drm_psr_register() can fail, so add a sanity check for that. Also reorder the calls in unbind() to match bind(). Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: None drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 117585df73e1..bd3567ad8b53 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -356,15 +356,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; INIT_WORK(&dp->psr_work, analogix_dp_psr_work); - rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); + ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); + if (ret < 0) + goto err_cleanup_encoder; dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); if (IS_ERR(dp->adp)) { - dp->encoder.funcs->destroy(&dp->encoder); - return PTR_ERR(dp->adp); + ret = PTR_ERR(dp->adp); + goto err_unreg_psr; } return 0; +err_unreg_psr: + rockchip_drm_psr_unregister(&dp->encoder); +err_cleanup_encoder: + dp->encoder.funcs->destroy(&dp->encoder); + return ret; } static void rockchip_dp_unbind(struct device *dev, struct device *master, @@ -372,8 +379,8 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, { struct rockchip_dp_device *dp = dev_get_drvdata(dev); - rockchip_drm_psr_unregister(&dp->encoder); analogix_dp_unbind(dp->adp); + rockchip_drm_psr_unregister(&dp->encoder); dp->encoder.funcs->destroy(&dp->encoder); } -- 2.11.0
[PATCH v6 07/10] drm/rockchip: inno_hdmi: Fix error handling path
Add missing error handling in bind(). Fixes: 412d4ae6b7a5 ("drm/rockchip: hdmi: add Innosilicon HDMI support") Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: Call the destroy hook in the error handling path like in unbind(). Update cleanup order in unbind(). drivers/gpu/drm/rockchip/inno_hdmi.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index ee584d87111f..9a96ff6b022b 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -851,8 +851,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto err_disable_clk; + } inno_hdmi_reset(hdmi); @@ -860,7 +862,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->ddc)) { ret = PTR_ERR(hdmi->ddc); hdmi->ddc = NULL; - return ret; + goto err_disable_clk; } /* @@ -874,7 +876,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = inno_hdmi_register(drm, hdmi); if (ret) - return ret; + goto err_put_adapter; dev_set_drvdata(dev, hdmi); @@ -884,7 +886,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq, inno_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); + if (ret < 0) + goto err_cleanup_hdmi; + return 0; +err_cleanup_hdmi: + hdmi->connector.funcs->destroy(&hdmi->connector); + hdmi->encoder.funcs->destroy(&hdmi->encoder); +err_put_adapter: + i2c_put_adapter(hdmi->ddc); +err_disable_clk: + clk_disable_unprepare(hdmi->pclk); return ret; } @@ -896,8 +908,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master, hdmi->connector.funcs->destroy(&hdmi->connector); hdmi->encoder.funcs->destroy(&hdmi->encoder); - clk_disable_unprepare(hdmi->pclk); i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); } static const struct component_ops inno_hdmi_ops = { -- 2.11.0
[PATCH v6 09/10] drm/bridge/synopsys: dw-hdmi: Do not use device's drvdata
Let plat drivers own the drvdata, so that they could cleanup resources in their unbind(). Signed-off-by: Jeffy Chen Reviewed-by: Neil Armstrong --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 43 ++--- drivers/gpu/drm/imx/dw_hdmi-imx.c | 22 +-- drivers/gpu/drm/meson/meson_dw_hdmi.c | 20 ++ drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 14 -- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 23 --- include/drm/bridge/dw_hdmi.h| 17 ++-- 6 files changed, 77 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ff1b3d2b5d06..6fbfafc5832b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2072,7 +2072,7 @@ static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) return ret; } -void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) +void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) { mutex_lock(&hdmi->mutex); @@ -2098,13 +2098,6 @@ void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) } mutex_unlock(&hdmi->mutex); } - -void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) -{ - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - - __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); -} EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) @@ -2140,9 +2133,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) */ if (intr_stat & (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { - __dw_hdmi_setup_rx_sense(hdmi, -phy_stat & HDMI_PHY_HPD, -phy_stat & HDMI_PHY_RX_SENSE); + dw_hdmi_setup_rx_sense(hdmi, phy_stat & HDMI_PHY_HPD, + phy_stat & HDMI_PHY_RX_SENSE); if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) cec_notifier_set_phys_addr(hdmi->cec_notifier, @@ -2512,8 +2504,6 @@ __dw_hdmi_probe(struct platform_device *pdev, if (hdmi->i2c) dw_hdmi_i2c_init(hdmi); - platform_set_drvdata(pdev, hdmi); - return hdmi; err_iahb: @@ -2559,25 +2549,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) /* - * Probe/remove API, used from platforms based on the DRM bridge API. */ -int dw_hdmi_probe(struct platform_device *pdev, - const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; drm_bridge_add(&hdmi->bridge); - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_probe); -void dw_hdmi_remove(struct platform_device *pdev) +void dw_hdmi_remove(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = platform_get_drvdata(pdev); - drm_bridge_remove(&hdmi->bridge); __dw_hdmi_remove(hdmi); @@ -2587,31 +2575,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove); /* - * Bind/unbind API, used from platforms based on the component framework. */ -int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, -const struct dw_hdmi_plat_data *plat_data) +struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data) { struct dw_hdmi *hdmi; int ret; hdmi = __dw_hdmi_probe(pdev, plat_data); if (IS_ERR(hdmi)) - return PTR_ERR(hdmi); + return hdmi; ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); if (ret) { __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); - return ret; + return ERR_PTR(ret); } - return 0; + return hdmi; } EXPORT_SYMBOL_GPL(dw_hdmi_bind); -void dw_hdmi_unbind(struct device *dev) +void dw_hdmi_unbind(struct dw_hdmi *hdmi) { - struct dw_hdmi *hdmi = dev_get_drvdata(dev); - __dw_hdmi_remove(hdmi); } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index b62763aa8706..b01d03e02ce0 10064
[PATCH v6 08/10] drm/bridge/synopsys: dw-hdmi: Add missing bridge detach
We inited connector in attach(), so need a detach() to cleanup. Also fix wrong use of dw_hdmi_remove() in bind(). Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: None drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index bf14214fa464..ff1b3d2b5d06 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1966,6 +1966,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) return 0; } +static void dw_hdmi_bridge_detach(struct drm_bridge *bridge) +{ + struct dw_hdmi *hdmi = bridge->driver_private; + + drm_connector_cleanup(&hdmi->connector); +} + static enum drm_mode_status dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) @@ -2022,6 +2029,7 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .attach = dw_hdmi_bridge_attach, + .detach = dw_hdmi_bridge_detach, .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, .mode_set = dw_hdmi_bridge_mode_set, @@ -2591,7 +2599,7 @@ int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); if (ret) { - dw_hdmi_remove(pdev); + __dw_hdmi_remove(hdmi); DRM_ERROR("Failed to initialize bridge with drm\n"); return ret; } -- 2.11.0
[PATCH v6 10/10] drm/rockchip: dw_hdmi: Fix error handling path
Add missing clk_disable_unprepare() in bind()'s error handling path and unbind(). Also inline clk_prepare_enable() with bind(). Fixes: 12b9f204e804 ("drm: bridge/dw_hdmi: add rockchip rk3288 support") Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: Add disable to unbind(), and inline clk_prepare_enable() with bind(). drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 791ab938f998..e936dfe6c03d 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -193,13 +193,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) return PTR_ERR(hdmi->grf_clk); } - ret = clk_prepare_enable(hdmi->vpll_clk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, - "Failed to enable HDMI vpll: %d\n", ret); - return ret; - } - return 0; } @@ -374,6 +367,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, return ret; } + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); @@ -381,6 +381,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); if (IS_ERR(hdmi->hdmi)) { encoder->funcs->destroy(encoder); + clk_disable_unprepare(hdmi->vpll_clk); return PTR_ERR(hdmi->hdmi); } @@ -396,6 +397,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, dw_hdmi_unbind(hdmi->hdmi); hdmi->encoder.funcs->destroy(&hdmi->encoder); + clk_disable_unprepare(hdmi->vpll_clk); } static const struct component_ops dw_hdmi_rockchip_ops = { -- 2.11.0
[PATCH v6 06/10] drm/rockchip: dw-mipi-dsi: Fix error handling path
Add missing pm_runtime_disable() in bind()'s error handling path. Also cleanup encoder & connector in unbind(). Fixes: 80a9a059d4e4 ("drm/rockchip/dsi: add dw-mipi power domain support") Signed-off-by: Jeffy Chen --- Changes in v6: None Changes in v5: Call the destroy hook in the error handling path like in unbind(). drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b15755b6129c..e72d4e2b61aa 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -1282,7 +1282,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = dw_mipi_dsi_register(drm, dsi); if (ret) { DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); - goto err_pllref; + goto err_disable_pllref; } pm_runtime_enable(dev); @@ -1292,23 +1292,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); - goto err_cleanup; + goto err_disable_pm_runtime; } if (!dsi->panel) { ret = -EPROBE_DEFER; - goto err_mipi_dsi_host; + goto err_unreg_mipi_dsi_host; } dev_set_drvdata(dev, dsi); return 0; -err_mipi_dsi_host: +err_unreg_mipi_dsi_host: mipi_dsi_host_unregister(&dsi->dsi_host); -err_cleanup: - drm_encoder_cleanup(&dsi->encoder); - drm_connector_cleanup(&dsi->connector); -err_pllref: +err_disable_pm_runtime: + pm_runtime_disable(dev); + dsi->connector.funcs->destroy(&dsi->connector); + dsi->encoder.funcs->destroy(&dsi->encoder); +err_disable_pllref: clk_disable_unprepare(dsi->pllref_clk); return ret; } @@ -1320,6 +1321,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, mipi_dsi_host_unregister(&dsi->dsi_host); pm_runtime_disable(dev); + + dsi->connector.funcs->destroy(&dsi->connector); + dsi->encoder.funcs->destroy(&dsi->encoder); + clk_disable_unprepare(dsi->pllref_clk); } -- 2.11.0