diff options
author | Olof Johansson <olof@lixom.net> | 2016-06-20 01:39:15 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2016-06-20 01:39:15 -0400 |
commit | d41bde8818ff8405d7d4a051c9d809f026cd6863 (patch) | |
tree | b47791f94c9de594d269d5cda6ad437066709be9 | |
parent | d8d8126f22d167a8ab89929f31443dabbb679587 (diff) | |
parent | 96167bd37dd604cbba0aed341765dda8556405b2 (diff) |
Merge tag 'samsung-drivers-exynos-mfc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into next/drivers
Topic branch for Exynos MFC changes for v4.8:
Pull s5p-mfc changes from media tree so the arm/mach-exynos code
could be removed. The bindings are converted to generic reserved memory
bindings.
* tag 'samsung-drivers-exynos-mfc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
ARM: dts: exynos: Enable MFC device on Exynos4412 Odroid boards
ARM: dts: exynos: Convert MFC device to generic reserved memory bindings
ARM: EXYNOS: Remove code for MFC custom reserved memory handling
media: s5p-mfc: add iommu support
media: s5p-mfc: replace custom reserved memory handling code with generic one
media: s5p-mfc: use generic reserved memory bindings
of: reserved_mem: add support for using more than one region for given device
media: set proper max seg size for devices on Exynos SoCs
media: vb2-dma-contig: add helper for setting dma max seg size
s5p-mfc: Fix race between s5p_mfc_probe() and s5p_mfc_open()
s5p-mfc: Add release callback for memory region devs
s5p-mfc: Set device name for reserved memory region devs
Signed-off-by: Olof Johansson <olof@lixom.net>
32 files changed, 438 insertions, 270 deletions
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt index 2d5787eac91a..92c94f5ecbf1 100644 --- a/Documentation/devicetree/bindings/media/s5p-mfc.txt +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt | |||
@@ -21,15 +21,18 @@ Required properties: | |||
21 | - clock-names : from common clock binding: must contain "mfc", | 21 | - clock-names : from common clock binding: must contain "mfc", |
22 | corresponding to entry in the clocks property. | 22 | corresponding to entry in the clocks property. |
23 | 23 | ||
24 | - samsung,mfc-r : Base address of the first memory bank used by MFC | ||
25 | for DMA contiguous memory allocation and its size. | ||
26 | |||
27 | - samsung,mfc-l : Base address of the second memory bank used by MFC | ||
28 | for DMA contiguous memory allocation and its size. | ||
29 | |||
30 | Optional properties: | 24 | Optional properties: |
31 | - power-domains : power-domain property defined with a phandle | 25 | - power-domains : power-domain property defined with a phandle |
32 | to respective power domain. | 26 | to respective power domain. |
27 | - memory-region : from reserved memory binding: phandles to two reserved | ||
28 | memory regions, first is for "left" mfc memory bus interfaces, | ||
29 | second if for the "right" mfc memory bus, used when no SYSMMU | ||
30 | support is available | ||
31 | |||
32 | Obsolete properties: | ||
33 | - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region | ||
34 | property instead | ||
35 | |||
33 | 36 | ||
34 | Example: | 37 | Example: |
35 | SoC specific DT entry: | 38 | SoC specific DT entry: |
@@ -43,9 +46,29 @@ mfc: codec@13400000 { | |||
43 | clock-names = "mfc"; | 46 | clock-names = "mfc"; |
44 | }; | 47 | }; |
45 | 48 | ||
49 | Reserved memory specific DT entry for given board (see reserved memory binding | ||
50 | for more information): | ||
51 | |||
52 | reserved-memory { | ||
53 | #address-cells = <1>; | ||
54 | #size-cells = <1>; | ||
55 | ranges; | ||
56 | |||
57 | mfc_left: region@51000000 { | ||
58 | compatible = "shared-dma-pool"; | ||
59 | no-map; | ||
60 | reg = <0x51000000 0x800000>; | ||
61 | }; | ||
62 | |||
63 | mfc_right: region@43000000 { | ||
64 | compatible = "shared-dma-pool"; | ||
65 | no-map; | ||
66 | reg = <0x43000000 0x800000>; | ||
67 | }; | ||
68 | }; | ||
69 | |||
46 | Board specific DT entry: | 70 | Board specific DT entry: |
47 | 71 | ||
48 | codec@13400000 { | 72 | codec@13400000 { |
49 | samsung,mfc-r = <0x43000000 0x800000>; | 73 | memory-region = <&mfc_left>, <&mfc_right>; |
50 | samsung,mfc-l = <0x51000000 0x800000>; | ||
51 | }; | 74 | }; |
diff --git a/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi b/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi new file mode 100644 index 000000000000..c4d063ae6b74 --- /dev/null +++ b/arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Samsung's Exynos SoC MFC (Video Codec) reserved memory common definition. | ||
3 | * | ||
4 | * Copyright (c) 2016 Samsung Electronics Co., Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | / { | ||
12 | reserved-memory { | ||
13 | #address-cells = <1>; | ||
14 | #size-cells = <1>; | ||
15 | ranges; | ||
16 | |||
17 | mfc_left: region@51000000 { | ||
18 | compatible = "shared-dma-pool"; | ||
19 | no-map; | ||
20 | reg = <0x51000000 0x800000>; | ||
21 | }; | ||
22 | |||
23 | mfc_right: region@43000000 { | ||
24 | compatible = "shared-dma-pool"; | ||
25 | no-map; | ||
26 | reg = <0x43000000 0x800000>; | ||
27 | }; | ||
28 | }; | ||
29 | }; | ||
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts index ad7394c1d67a..f5e4eb23aa21 100644 --- a/arch/arm/boot/dts/exynos4210-origen.dts +++ b/arch/arm/boot/dts/exynos4210-origen.dts | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "exynos4210.dtsi" | 18 | #include "exynos4210.dtsi" |
19 | #include <dt-bindings/gpio/gpio.h> | 19 | #include <dt-bindings/gpio/gpio.h> |
20 | #include <dt-bindings/input/input.h> | 20 | #include <dt-bindings/input/input.h> |
21 | #include "exynos-mfc-reserved-memory.dtsi" | ||
21 | 22 | ||
22 | / { | 23 | / { |
23 | model = "Insignal Origen evaluation board based on Exynos4210"; | 24 | model = "Insignal Origen evaluation board based on Exynos4210"; |
@@ -288,8 +289,7 @@ | |||
288 | }; | 289 | }; |
289 | 290 | ||
290 | &mfc { | 291 | &mfc { |
291 | samsung,mfc-r = <0x43000000 0x800000>; | 292 | memory-region = <&mfc_left>, <&mfc_right>; |
292 | samsung,mfc-l = <0x51000000 0x800000>; | ||
293 | status = "okay"; | 293 | status = "okay"; |
294 | }; | 294 | }; |
295 | 295 | ||
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts index 94ca7d36ab37..de917f0d907d 100644 --- a/arch/arm/boot/dts/exynos4210-smdkv310.dts +++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts | |||
@@ -17,6 +17,7 @@ | |||
17 | /dts-v1/; | 17 | /dts-v1/; |
18 | #include "exynos4210.dtsi" | 18 | #include "exynos4210.dtsi" |
19 | #include <dt-bindings/gpio/gpio.h> | 19 | #include <dt-bindings/gpio/gpio.h> |
20 | #include "exynos-mfc-reserved-memory.dtsi" | ||
20 | 21 | ||
21 | / { | 22 | / { |
22 | model = "Samsung smdkv310 evaluation board based on Exynos4210"; | 23 | model = "Samsung smdkv310 evaluation board based on Exynos4210"; |
@@ -133,8 +134,7 @@ | |||
133 | }; | 134 | }; |
134 | 135 | ||
135 | &mfc { | 136 | &mfc { |
136 | samsung,mfc-r = <0x43000000 0x800000>; | 137 | memory-region = <&mfc_left>, <&mfc_right>; |
137 | samsung,mfc-l = <0x51000000 0x800000>; | ||
138 | status = "okay"; | 138 | status = "okay"; |
139 | }; | 139 | }; |
140 | 140 | ||
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index ec7619a384a2..276ac9a7bb82 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "exynos4412.dtsi" | 13 | #include "exynos4412.dtsi" |
14 | #include "exynos4412-ppmu-common.dtsi" | 14 | #include "exynos4412-ppmu-common.dtsi" |
15 | #include <dt-bindings/gpio/gpio.h> | 15 | #include <dt-bindings/gpio/gpio.h> |
16 | #include "exynos-mfc-reserved-memory.dtsi" | ||
16 | 17 | ||
17 | / { | 18 | / { |
18 | chosen { | 19 | chosen { |
@@ -499,6 +500,11 @@ | |||
499 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; | 500 | clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; |
500 | }; | 501 | }; |
501 | 502 | ||
503 | &mfc { | ||
504 | memory-region = <&mfc_left>, <&mfc_right>; | ||
505 | status = "okay"; | ||
506 | }; | ||
507 | |||
502 | &mixer { | 508 | &mixer { |
503 | status = "okay"; | 509 | status = "okay"; |
504 | }; | 510 | }; |
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index 8bca699b7f20..cd363d7e4e34 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "exynos4412.dtsi" | 16 | #include "exynos4412.dtsi" |
17 | #include <dt-bindings/gpio/gpio.h> | 17 | #include <dt-bindings/gpio/gpio.h> |
18 | #include <dt-bindings/input/input.h> | 18 | #include <dt-bindings/input/input.h> |
19 | #include "exynos-mfc-reserved-memory.dtsi" | ||
19 | 20 | ||
20 | / { | 21 | / { |
21 | model = "Insignal Origen evaluation board based on Exynos4412"; | 22 | model = "Insignal Origen evaluation board based on Exynos4412"; |
@@ -466,8 +467,7 @@ | |||
466 | }; | 467 | }; |
467 | 468 | ||
468 | &mfc { | 469 | &mfc { |
469 | samsung,mfc-r = <0x43000000 0x800000>; | 470 | memory-region = <&mfc_left>, <&mfc_right>; |
470 | samsung,mfc-l = <0x51000000 0x800000>; | ||
471 | status = "okay"; | 471 | status = "okay"; |
472 | }; | 472 | }; |
473 | 473 | ||
diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts index a51069f3c03b..9b6d561dbdac 100644 --- a/arch/arm/boot/dts/exynos4412-smdk4412.dts +++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | /dts-v1/; | 15 | /dts-v1/; |
16 | #include "exynos4412.dtsi" | 16 | #include "exynos4412.dtsi" |
17 | #include "exynos-mfc-reserved-memory.dtsi" | ||
17 | 18 | ||
18 | / { | 19 | / { |
19 | model = "Samsung SMDK evaluation board based on Exynos4412"; | 20 | model = "Samsung SMDK evaluation board based on Exynos4412"; |
@@ -112,8 +113,7 @@ | |||
112 | }; | 113 | }; |
113 | 114 | ||
114 | &mfc { | 115 | &mfc { |
115 | samsung,mfc-r = <0x43000000 0x800000>; | 116 | memory-region = <&mfc_left>, <&mfc_right>; |
116 | samsung,mfc-l = <0x51000000 0x800000>; | ||
117 | status = "okay"; | 117 | status = "okay"; |
118 | }; | 118 | }; |
119 | 119 | ||
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 85dad29c08dc..39940f4bd556 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <dt-bindings/interrupt-controller/irq.h> | 14 | #include <dt-bindings/interrupt-controller/irq.h> |
15 | #include <dt-bindings/input/input.h> | 15 | #include <dt-bindings/input/input.h> |
16 | #include "exynos5250.dtsi" | 16 | #include "exynos5250.dtsi" |
17 | #include "exynos-mfc-reserved-memory.dtsi" | ||
17 | 18 | ||
18 | / { | 19 | / { |
19 | model = "Insignal Arndale evaluation board based on EXYNOS5250"; | 20 | model = "Insignal Arndale evaluation board based on EXYNOS5250"; |
@@ -516,8 +517,7 @@ | |||
516 | }; | 517 | }; |
517 | 518 | ||
518 | &mfc { | 519 | &mfc { |
519 | samsung,mfc-r = <0x43000000 0x800000>; | 520 | memory-region = <&mfc_left>, <&mfc_right>; |
520 | samsung,mfc-l = <0x51000000 0x800000>; | ||
521 | }; | 521 | }; |
522 | 522 | ||
523 | &mmc_0 { | 523 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index b7992b13c9de..9fac874af5eb 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <dt-bindings/gpio/gpio.h> | 13 | #include <dt-bindings/gpio/gpio.h> |
14 | #include <dt-bindings/interrupt-controller/irq.h> | 14 | #include <dt-bindings/interrupt-controller/irq.h> |
15 | #include "exynos5250.dtsi" | 15 | #include "exynos5250.dtsi" |
16 | #include "exynos-mfc-reserved-memory.dtsi" | ||
16 | 17 | ||
17 | / { | 18 | / { |
18 | model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; | 19 | model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; |
@@ -344,8 +345,7 @@ | |||
344 | }; | 345 | }; |
345 | 346 | ||
346 | &mfc { | 347 | &mfc { |
347 | samsung,mfc-r = <0x43000000 0x800000>; | 348 | memory-region = <&mfc_left>, <&mfc_right>; |
348 | samsung,mfc-l = <0x51000000 0x800000>; | ||
349 | }; | 349 | }; |
350 | 350 | ||
351 | &mmc_0 { | 351 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index ac291f540812..784130bdb6a3 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <dt-bindings/interrupt-controller/irq.h> | 14 | #include <dt-bindings/interrupt-controller/irq.h> |
15 | #include <dt-bindings/input/input.h> | 15 | #include <dt-bindings/input/input.h> |
16 | #include "exynos5250.dtsi" | 16 | #include "exynos5250.dtsi" |
17 | #include "exynos-mfc-reserved-memory.dtsi" | ||
17 | 18 | ||
18 | / { | 19 | / { |
19 | model = "Google Spring"; | 20 | model = "Google Spring"; |
@@ -425,8 +426,7 @@ | |||
425 | }; | 426 | }; |
426 | 427 | ||
427 | &mfc { | 428 | &mfc { |
428 | samsung,mfc-r = <0x43000000 0x800000>; | 429 | memory-region = <&mfc_left>, <&mfc_right>; |
429 | samsung,mfc-l = <0x51000000 0x800000>; | ||
430 | }; | 430 | }; |
431 | 431 | ||
432 | &mmc_0 { | 432 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index 60bc861d0f9d..b8b5f3ae2942 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <dt-bindings/interrupt-controller/irq.h> | 16 | #include <dt-bindings/interrupt-controller/irq.h> |
17 | #include <dt-bindings/input/input.h> | 17 | #include <dt-bindings/input/input.h> |
18 | #include <dt-bindings/clock/samsung,s2mps11.h> | 18 | #include <dt-bindings/clock/samsung,s2mps11.h> |
19 | #include "exynos-mfc-reserved-memory.dtsi" | ||
19 | 20 | ||
20 | / { | 21 | / { |
21 | model = "Insignal Arndale Octa evaluation board based on EXYNOS5420"; | 22 | model = "Insignal Arndale Octa evaluation board based on EXYNOS5420"; |
@@ -347,8 +348,7 @@ | |||
347 | }; | 348 | }; |
348 | 349 | ||
349 | &mfc { | 350 | &mfc { |
350 | samsung,mfc-r = <0x43000000 0x800000>; | 351 | memory-region = <&mfc_left>, <&mfc_right>; |
351 | samsung,mfc-l = <0x51000000 0x800000>; | ||
352 | }; | 352 | }; |
353 | 353 | ||
354 | &mmc_0 { | 354 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index f9d2e4f1a0e0..d530b4f5f1e9 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <dt-bindings/regulator/maxim,max77802.h> | 16 | #include <dt-bindings/regulator/maxim,max77802.h> |
17 | #include "exynos5420.dtsi" | 17 | #include "exynos5420.dtsi" |
18 | #include "exynos5420-cpus.dtsi" | 18 | #include "exynos5420-cpus.dtsi" |
19 | #include "exynos-mfc-reserved-memory.dtsi" | ||
19 | 20 | ||
20 | / { | 21 | / { |
21 | model = "Google Peach Pit Rev 6+"; | 22 | model = "Google Peach Pit Rev 6+"; |
@@ -695,8 +696,7 @@ | |||
695 | }; | 696 | }; |
696 | 697 | ||
697 | &mfc { | 698 | &mfc { |
698 | samsung,mfc-r = <0x43000000 0x800000>; | 699 | memory-region = <&mfc_left>, <&mfc_right>; |
699 | samsung,mfc-l = <0x51000000 0x800000>; | ||
700 | }; | 700 | }; |
701 | 701 | ||
702 | &mmc_0 { | 702 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 2e748d19322f..5206f41e548d 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "exynos5420.dtsi" | 13 | #include "exynos5420.dtsi" |
14 | #include "exynos5420-cpus.dtsi" | 14 | #include "exynos5420-cpus.dtsi" |
15 | #include <dt-bindings/gpio/gpio.h> | 15 | #include <dt-bindings/gpio/gpio.h> |
16 | #include "exynos-mfc-reserved-memory.dtsi" | ||
16 | 17 | ||
17 | / { | 18 | / { |
18 | model = "Samsung SMDK5420 board based on EXYNOS5420"; | 19 | model = "Samsung SMDK5420 board based on EXYNOS5420"; |
@@ -355,8 +356,7 @@ | |||
355 | }; | 356 | }; |
356 | 357 | ||
357 | &mfc { | 358 | &mfc { |
358 | samsung,mfc-r = <0x43000000 0x800000>; | 359 | memory-region = <&mfc_left>, <&mfc_right>; |
359 | samsung,mfc-l = <0x51000000 0x800000>; | ||
360 | }; | 360 | }; |
361 | 361 | ||
362 | &mmc_0 { | 362 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 2a4e10bc8801..7c2335f18bfc 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "exynos5800.dtsi" | 17 | #include "exynos5800.dtsi" |
18 | #include "exynos5422-cpus.dtsi" | 18 | #include "exynos5422-cpus.dtsi" |
19 | #include "exynos5422-cpu-thermal.dtsi" | 19 | #include "exynos5422-cpu-thermal.dtsi" |
20 | #include "exynos-mfc-reserved-memory.dtsi" | ||
20 | 21 | ||
21 | / { | 22 | / { |
22 | memory { | 23 | memory { |
@@ -406,8 +407,7 @@ | |||
406 | }; | 407 | }; |
407 | 408 | ||
408 | &mfc { | 409 | &mfc { |
409 | samsung,mfc-r = <0x43000000 0x800000>; | 410 | memory-region = <&mfc_left>, <&mfc_right>; |
410 | samsung,mfc-l = <0x51000000 0x800000>; | ||
411 | }; | 411 | }; |
412 | 412 | ||
413 | &mmc_0 { | 413 | &mmc_0 { |
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 62ceb89e073f..1f735963ca98 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <dt-bindings/regulator/maxim,max77802.h> | 16 | #include <dt-bindings/regulator/maxim,max77802.h> |
17 | #include "exynos5800.dtsi" | 17 | #include "exynos5800.dtsi" |
18 | #include "exynos5420-cpus.dtsi" | 18 | #include "exynos5420-cpus.dtsi" |
19 | #include "exynos-mfc-reserved-memory.dtsi" | ||
19 | 20 | ||
20 | / { | 21 | / { |
21 | model = "Google Peach Pi Rev 10+"; | 22 | model = "Google Peach Pi Rev 10+"; |
@@ -670,8 +671,7 @@ | |||
670 | }; | 671 | }; |
671 | 672 | ||
672 | &mfc { | 673 | &mfc { |
673 | samsung,mfc-r = <0x43000000 0x800000>; | 674 | memory-region = <&mfc_left>, <&mfc_right>; |
674 | samsung,mfc-l = <0x51000000 0x800000>; | ||
675 | }; | 675 | }; |
676 | 676 | ||
677 | &mmc_0 { | 677 | &mmc_0 { |
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 838249d4ff5c..9ea6c54645ad 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile | |||
@@ -22,5 +22,3 @@ AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec) | |||
22 | 22 | ||
23 | obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o | 23 | obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o |
24 | CFLAGS_mcpm-exynos.o += -march=armv7-a | 24 | CFLAGS_mcpm-exynos.o += -march=armv7-a |
25 | |||
26 | obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o | ||
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 52ccf247e079..a8620c6eb723 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <mach/map.h> | 27 | #include <mach/map.h> |
28 | 28 | ||
29 | #include "common.h" | 29 | #include "common.h" |
30 | #include "mfc.h" | ||
31 | 30 | ||
32 | static struct map_desc exynos4_iodesc[] __initdata = { | 31 | static struct map_desc exynos4_iodesc[] __initdata = { |
33 | { | 32 | { |
@@ -237,23 +236,6 @@ static char const *const exynos_dt_compat[] __initconst = { | |||
237 | NULL | 236 | NULL |
238 | }; | 237 | }; |
239 | 238 | ||
240 | static void __init exynos_reserve(void) | ||
241 | { | ||
242 | #ifdef CONFIG_S5P_DEV_MFC | ||
243 | int i; | ||
244 | char *mfc_mem[] = { | ||
245 | "samsung,mfc-v5", | ||
246 | "samsung,mfc-v6", | ||
247 | "samsung,mfc-v7", | ||
248 | "samsung,mfc-v8", | ||
249 | }; | ||
250 | |||
251 | for (i = 0; i < ARRAY_SIZE(mfc_mem); i++) | ||
252 | if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i])) | ||
253 | break; | ||
254 | #endif | ||
255 | } | ||
256 | |||
257 | static void __init exynos_dt_fixup(void) | 239 | static void __init exynos_dt_fixup(void) |
258 | { | 240 | { |
259 | /* | 241 | /* |
@@ -275,6 +257,5 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") | |||
275 | .init_machine = exynos_dt_machine_init, | 257 | .init_machine = exynos_dt_machine_init, |
276 | .init_late = exynos_init_late, | 258 | .init_late = exynos_init_late, |
277 | .dt_compat = exynos_dt_compat, | 259 | .dt_compat = exynos_dt_compat, |
278 | .reserve = exynos_reserve, | ||
279 | .dt_fixup = exynos_dt_fixup, | 260 | .dt_fixup = exynos_dt_fixup, |
280 | MACHINE_END | 261 | MACHINE_END |
diff --git a/arch/arm/mach-exynos/mfc.h b/arch/arm/mach-exynos/mfc.h deleted file mode 100644 index dec93cd5b3c6..000000000000 --- a/arch/arm/mach-exynos/mfc.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Samsung Electronics Co.Ltd | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef __MACH_EXYNOS_MFC_H | ||
11 | #define __MACH_EXYNOS_MFC_H __FILE__ | ||
12 | |||
13 | int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname, | ||
14 | int depth, void *data); | ||
15 | |||
16 | #endif /* __MACH_EXYNOS_MFC_H */ | ||
diff --git a/arch/arm/mach-exynos/s5p-dev-mfc.c b/arch/arm/mach-exynos/s5p-dev-mfc.c deleted file mode 100644 index 8ef1f3ee4e98..000000000000 --- a/arch/arm/mach-exynos/s5p-dev-mfc.c +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd | ||
3 | * | ||
4 | * Base S5P MFC resource and device definitions | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/memblock.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/of_fdt.h> | ||
17 | #include <linux/of.h> | ||
18 | |||
19 | static struct platform_device s5p_device_mfc_l; | ||
20 | static struct platform_device s5p_device_mfc_r; | ||
21 | |||
22 | struct s5p_mfc_dt_meminfo { | ||
23 | unsigned long loff; | ||
24 | unsigned long lsize; | ||
25 | unsigned long roff; | ||
26 | unsigned long rsize; | ||
27 | char *compatible; | ||
28 | }; | ||
29 | |||
30 | struct s5p_mfc_reserved_mem { | ||
31 | phys_addr_t base; | ||
32 | unsigned long size; | ||
33 | struct device *dev; | ||
34 | }; | ||
35 | |||
36 | static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata; | ||
37 | |||
38 | |||
39 | static void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, | ||
40 | phys_addr_t lbase, unsigned int lsize) | ||
41 | { | ||
42 | int i; | ||
43 | |||
44 | s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev; | ||
45 | s5p_mfc_mem[0].base = rbase; | ||
46 | s5p_mfc_mem[0].size = rsize; | ||
47 | |||
48 | s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev; | ||
49 | s5p_mfc_mem[1].base = lbase; | ||
50 | s5p_mfc_mem[1].size = lsize; | ||
51 | |||
52 | for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { | ||
53 | struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; | ||
54 | if (memblock_remove(area->base, area->size)) { | ||
55 | printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n", | ||
56 | area->size, (unsigned long) area->base); | ||
57 | area->base = 0; | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname, | ||
63 | int depth, void *data) | ||
64 | { | ||
65 | const __be32 *prop; | ||
66 | int len; | ||
67 | struct s5p_mfc_dt_meminfo mfc_mem; | ||
68 | |||
69 | if (!data) | ||
70 | return 0; | ||
71 | |||
72 | if (!of_flat_dt_is_compatible(node, data)) | ||
73 | return 0; | ||
74 | |||
75 | prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); | ||
76 | if (!prop || (len != 2 * sizeof(unsigned long))) | ||
77 | return 0; | ||
78 | |||
79 | mfc_mem.loff = be32_to_cpu(prop[0]); | ||
80 | mfc_mem.lsize = be32_to_cpu(prop[1]); | ||
81 | |||
82 | prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); | ||
83 | if (!prop || (len != 2 * sizeof(unsigned long))) | ||
84 | return 0; | ||
85 | |||
86 | mfc_mem.roff = be32_to_cpu(prop[0]); | ||
87 | mfc_mem.rsize = be32_to_cpu(prop[1]); | ||
88 | |||
89 | s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, | ||
90 | mfc_mem.loff, mfc_mem.lsize); | ||
91 | |||
92 | return 1; | ||
93 | } | ||
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index c04973669a47..c9d2009c2476 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c | |||
@@ -1124,6 +1124,7 @@ static int gsc_probe(struct platform_device *pdev) | |||
1124 | goto err_m2m; | 1124 | goto err_m2m; |
1125 | 1125 | ||
1126 | /* Initialize continious memory allocator */ | 1126 | /* Initialize continious memory allocator */ |
1127 | vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); | ||
1127 | gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev); | 1128 | gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev); |
1128 | if (IS_ERR(gsc->alloc_ctx)) { | 1129 | if (IS_ERR(gsc->alloc_ctx)) { |
1129 | ret = PTR_ERR(gsc->alloc_ctx); | 1130 | ret = PTR_ERR(gsc->alloc_ctx); |
@@ -1153,6 +1154,7 @@ static int gsc_remove(struct platform_device *pdev) | |||
1153 | v4l2_device_unregister(&gsc->v4l2_dev); | 1154 | v4l2_device_unregister(&gsc->v4l2_dev); |
1154 | 1155 | ||
1155 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); | 1156 | vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); |
1157 | vb2_dma_contig_clear_max_seg_size(&pdev->dev); | ||
1156 | pm_runtime_disable(&pdev->dev); | 1158 | pm_runtime_disable(&pdev->dev); |
1157 | gsc_clk_put(gsc); | 1159 | gsc_clk_put(gsc); |
1158 | 1160 | ||
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index b1c1cea82a27..368f44f24d4c 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c | |||
@@ -1019,6 +1019,7 @@ static int fimc_probe(struct platform_device *pdev) | |||
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | /* Initialize contiguous memory allocator */ | 1021 | /* Initialize contiguous memory allocator */ |
1022 | vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); | ||
1022 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); | 1023 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); |
1023 | if (IS_ERR(fimc->alloc_ctx)) { | 1024 | if (IS_ERR(fimc->alloc_ctx)) { |
1024 | ret = PTR_ERR(fimc->alloc_ctx); | 1025 | ret = PTR_ERR(fimc->alloc_ctx); |
@@ -1124,6 +1125,7 @@ static int fimc_remove(struct platform_device *pdev) | |||
1124 | 1125 | ||
1125 | fimc_unregister_capture_subdev(fimc); | 1126 | fimc_unregister_capture_subdev(fimc); |
1126 | vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); | 1127 | vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); |
1128 | vb2_dma_contig_clear_max_seg_size(&pdev->dev); | ||
1127 | 1129 | ||
1128 | clk_disable(fimc->clock[CLK_BUS]); | 1130 | clk_disable(fimc->clock[CLK_BUS]); |
1129 | fimc_clk_put(fimc); | 1131 | fimc_clk_put(fimc); |
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 979c388ebf60..bd98b56318b7 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c | |||
@@ -847,6 +847,7 @@ static int fimc_is_probe(struct platform_device *pdev) | |||
847 | if (ret < 0) | 847 | if (ret < 0) |
848 | goto err_pm; | 848 | goto err_pm; |
849 | 849 | ||
850 | vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); | ||
850 | is->alloc_ctx = vb2_dma_contig_init_ctx(dev); | 851 | is->alloc_ctx = vb2_dma_contig_init_ctx(dev); |
851 | if (IS_ERR(is->alloc_ctx)) { | 852 | if (IS_ERR(is->alloc_ctx)) { |
852 | ret = PTR_ERR(is->alloc_ctx); | 853 | ret = PTR_ERR(is->alloc_ctx); |
@@ -940,6 +941,7 @@ static int fimc_is_remove(struct platform_device *pdev) | |||
940 | free_irq(is->irq, is); | 941 | free_irq(is->irq, is); |
941 | fimc_is_unregister_subdevs(is); | 942 | fimc_is_unregister_subdevs(is); |
942 | vb2_dma_contig_cleanup_ctx(is->alloc_ctx); | 943 | vb2_dma_contig_cleanup_ctx(is->alloc_ctx); |
944 | vb2_dma_contig_clear_max_seg_size(dev); | ||
943 | fimc_is_put_clocks(is); | 945 | fimc_is_put_clocks(is); |
944 | fimc_is_debugfs_remove(is); | 946 | fimc_is_debugfs_remove(is); |
945 | release_firmware(is->fw.f_w); | 947 | release_firmware(is->fw.f_w); |
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index dc1b929f7a33..27cb620cb714 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c | |||
@@ -1551,6 +1551,7 @@ static int fimc_lite_probe(struct platform_device *pdev) | |||
1551 | goto err_sd; | 1551 | goto err_sd; |
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); | ||
1554 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); | 1555 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); |
1555 | if (IS_ERR(fimc->alloc_ctx)) { | 1556 | if (IS_ERR(fimc->alloc_ctx)) { |
1556 | ret = PTR_ERR(fimc->alloc_ctx); | 1557 | ret = PTR_ERR(fimc->alloc_ctx); |
@@ -1652,6 +1653,7 @@ static int fimc_lite_remove(struct platform_device *pdev) | |||
1652 | pm_runtime_set_suspended(dev); | 1653 | pm_runtime_set_suspended(dev); |
1653 | fimc_lite_unregister_capture_subdev(fimc); | 1654 | fimc_lite_unregister_capture_subdev(fimc); |
1654 | vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); | 1655 | vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); |
1656 | vb2_dma_contig_clear_max_seg_size(dev); | ||
1655 | fimc_lite_clk_put(fimc); | 1657 | fimc_lite_clk_put(fimc); |
1656 | 1658 | ||
1657 | dev_info(dev, "Driver unloaded\n"); | 1659 | dev_info(dev, "Driver unloaded\n"); |
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 612d1ea514f1..d3e3469db8de 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c | |||
@@ -681,6 +681,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
681 | goto put_clk_gate; | 681 | goto put_clk_gate; |
682 | } | 682 | } |
683 | 683 | ||
684 | vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); | ||
684 | dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 685 | dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
685 | if (IS_ERR(dev->alloc_ctx)) { | 686 | if (IS_ERR(dev->alloc_ctx)) { |
686 | ret = PTR_ERR(dev->alloc_ctx); | 687 | ret = PTR_ERR(dev->alloc_ctx); |
@@ -757,6 +758,7 @@ static int g2d_remove(struct platform_device *pdev) | |||
757 | video_unregister_device(dev->vfd); | 758 | video_unregister_device(dev->vfd); |
758 | v4l2_device_unregister(&dev->v4l2_dev); | 759 | v4l2_device_unregister(&dev->v4l2_dev); |
759 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 760 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
761 | vb2_dma_contig_clear_max_seg_size(&pdev->dev); | ||
760 | clk_unprepare(dev->gate); | 762 | clk_unprepare(dev->gate); |
761 | clk_put(dev->gate); | 763 | clk_put(dev->gate); |
762 | clk_unprepare(dev->clk); | 764 | clk_unprepare(dev->clk); |
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index caa19b408551..17bc94092864 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c | |||
@@ -2843,6 +2843,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) | |||
2843 | goto device_register_rollback; | 2843 | goto device_register_rollback; |
2844 | } | 2844 | } |
2845 | 2845 | ||
2846 | vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); | ||
2846 | jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 2847 | jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
2847 | if (IS_ERR(jpeg->alloc_ctx)) { | 2848 | if (IS_ERR(jpeg->alloc_ctx)) { |
2848 | v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n"); | 2849 | v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n"); |
@@ -2942,6 +2943,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev) | |||
2942 | video_unregister_device(jpeg->vfd_decoder); | 2943 | video_unregister_device(jpeg->vfd_decoder); |
2943 | video_unregister_device(jpeg->vfd_encoder); | 2944 | video_unregister_device(jpeg->vfd_encoder); |
2944 | vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx); | 2945 | vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx); |
2946 | vb2_dma_contig_clear_max_seg_size(&pdev->dev); | ||
2945 | v4l2_m2m_release(jpeg->m2m_dev); | 2947 | v4l2_m2m_release(jpeg->m2m_dev); |
2946 | v4l2_device_unregister(&jpeg->v4l2_dev); | 2948 | v4l2_device_unregister(&jpeg->v4l2_dev); |
2947 | 2949 | ||
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index b16466fe35ee..6ee620ee8cd5 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <media/v4l2-event.h> | 22 | #include <media/v4l2-event.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_reserved_mem.h> | ||
25 | #include <media/videobuf2-v4l2.h> | 26 | #include <media/videobuf2-v4l2.h> |
26 | #include "s5p_mfc_common.h" | 27 | #include "s5p_mfc_common.h" |
27 | #include "s5p_mfc_ctrl.h" | 28 | #include "s5p_mfc_ctrl.h" |
@@ -29,6 +30,7 @@ | |||
29 | #include "s5p_mfc_dec.h" | 30 | #include "s5p_mfc_dec.h" |
30 | #include "s5p_mfc_enc.h" | 31 | #include "s5p_mfc_enc.h" |
31 | #include "s5p_mfc_intr.h" | 32 | #include "s5p_mfc_intr.h" |
33 | #include "s5p_mfc_iommu.h" | ||
32 | #include "s5p_mfc_opr.h" | 34 | #include "s5p_mfc_opr.h" |
33 | #include "s5p_mfc_cmd.h" | 35 | #include "s5p_mfc_cmd.h" |
34 | #include "s5p_mfc_pm.h" | 36 | #include "s5p_mfc_pm.h" |
@@ -1043,55 +1045,94 @@ static const struct v4l2_file_operations s5p_mfc_fops = { | |||
1043 | .mmap = s5p_mfc_mmap, | 1045 | .mmap = s5p_mfc_mmap, |
1044 | }; | 1046 | }; |
1045 | 1047 | ||
1046 | static int match_child(struct device *dev, void *data) | 1048 | /* DMA memory related helper functions */ |
1049 | static void s5p_mfc_memdev_release(struct device *dev) | ||
1047 | { | 1050 | { |
1048 | if (!dev_name(dev)) | 1051 | of_reserved_mem_device_release(dev); |
1049 | return 0; | ||
1050 | return !strcmp(dev_name(dev), (char *)data); | ||
1051 | } | 1052 | } |
1052 | 1053 | ||
1053 | static void *mfc_get_drv_data(struct platform_device *pdev); | 1054 | static struct device *s5p_mfc_alloc_memdev(struct device *dev, |
1054 | 1055 | const char *name, unsigned int idx) | |
1055 | static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev) | ||
1056 | { | 1056 | { |
1057 | unsigned int mem_info[2] = { }; | 1057 | struct device *child; |
1058 | int ret; | ||
1058 | 1059 | ||
1059 | dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev, | 1060 | child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL); |
1060 | sizeof(struct device), GFP_KERNEL); | 1061 | if (!child) |
1061 | if (!dev->mem_dev_l) { | 1062 | return NULL; |
1062 | mfc_err("Not enough memory\n"); | 1063 | |
1063 | return -ENOMEM; | 1064 | device_initialize(child); |
1064 | } | 1065 | dev_set_name(child, "%s:%s", dev_name(dev), name); |
1065 | device_initialize(dev->mem_dev_l); | 1066 | child->parent = dev; |
1066 | of_property_read_u32_array(dev->plat_dev->dev.of_node, | 1067 | child->bus = dev->bus; |
1067 | "samsung,mfc-l", mem_info, 2); | 1068 | child->coherent_dma_mask = dev->coherent_dma_mask; |
1068 | if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0], | 1069 | child->dma_mask = dev->dma_mask; |
1069 | mem_info[0], mem_info[1], | 1070 | child->release = s5p_mfc_memdev_release; |
1070 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { | 1071 | |
1071 | mfc_err("Failed to declare coherent memory for\n" | 1072 | if (device_add(child) == 0) { |
1072 | "MFC device\n"); | 1073 | ret = of_reserved_mem_device_init_by_idx(child, dev->of_node, |
1073 | return -ENOMEM; | 1074 | idx); |
1075 | if (ret == 0) | ||
1076 | return child; | ||
1074 | } | 1077 | } |
1075 | 1078 | ||
1076 | dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev, | 1079 | put_device(child); |
1077 | sizeof(struct device), GFP_KERNEL); | 1080 | return NULL; |
1078 | if (!dev->mem_dev_r) { | 1081 | } |
1079 | mfc_err("Not enough memory\n"); | 1082 | |
1080 | return -ENOMEM; | 1083 | static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) |
1084 | { | ||
1085 | struct device *dev = &mfc_dev->plat_dev->dev; | ||
1086 | |||
1087 | /* | ||
1088 | * When IOMMU is available, we cannot use the default configuration, | ||
1089 | * because of MFC firmware requirements: address space limited to | ||
1090 | * 256M and non-zero default start address. | ||
1091 | * This is still simplified, not optimal configuration, but for now | ||
1092 | * IOMMU core doesn't allow to configure device's IOMMUs channel | ||
1093 | * separately. | ||
1094 | */ | ||
1095 | if (exynos_is_iommu_available(dev)) { | ||
1096 | int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, | ||
1097 | S5P_MFC_IOMMU_DMA_SIZE); | ||
1098 | if (ret == 0) | ||
1099 | mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev; | ||
1100 | return ret; | ||
1081 | } | 1101 | } |
1082 | device_initialize(dev->mem_dev_r); | 1102 | |
1083 | of_property_read_u32_array(dev->plat_dev->dev.of_node, | 1103 | /* |
1084 | "samsung,mfc-r", mem_info, 2); | 1104 | * Create and initialize virtual devices for accessing |
1085 | if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0], | 1105 | * reserved memory regions. |
1086 | mem_info[0], mem_info[1], | 1106 | */ |
1087 | DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { | 1107 | mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left", |
1088 | pr_err("Failed to declare coherent memory for\n" | 1108 | MFC_BANK1_ALLOC_CTX); |
1089 | "MFC device\n"); | 1109 | if (!mfc_dev->mem_dev_l) |
1090 | return -ENOMEM; | 1110 | return -ENODEV; |
1111 | mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right", | ||
1112 | MFC_BANK2_ALLOC_CTX); | ||
1113 | if (!mfc_dev->mem_dev_r) { | ||
1114 | device_unregister(mfc_dev->mem_dev_l); | ||
1115 | return -ENODEV; | ||
1091 | } | 1116 | } |
1117 | |||
1092 | return 0; | 1118 | return 0; |
1093 | } | 1119 | } |
1094 | 1120 | ||
1121 | static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) | ||
1122 | { | ||
1123 | struct device *dev = &mfc_dev->plat_dev->dev; | ||
1124 | |||
1125 | if (exynos_is_iommu_available(dev)) { | ||
1126 | exynos_unconfigure_iommu(dev); | ||
1127 | return; | ||
1128 | } | ||
1129 | |||
1130 | device_unregister(mfc_dev->mem_dev_l); | ||
1131 | device_unregister(mfc_dev->mem_dev_r); | ||
1132 | } | ||
1133 | |||
1134 | static void *mfc_get_drv_data(struct platform_device *pdev); | ||
1135 | |||
1095 | /* MFC probe function */ | 1136 | /* MFC probe function */ |
1096 | static int s5p_mfc_probe(struct platform_device *pdev) | 1137 | static int s5p_mfc_probe(struct platform_device *pdev) |
1097 | { | 1138 | { |
@@ -1117,12 +1158,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1117 | 1158 | ||
1118 | dev->variant = mfc_get_drv_data(pdev); | 1159 | dev->variant = mfc_get_drv_data(pdev); |
1119 | 1160 | ||
1120 | ret = s5p_mfc_init_pm(dev); | ||
1121 | if (ret < 0) { | ||
1122 | dev_err(&pdev->dev, "failed to get mfc clock source\n"); | ||
1123 | return ret; | ||
1124 | } | ||
1125 | |||
1126 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1161 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1127 | 1162 | ||
1128 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); | 1163 | dev->regs_base = devm_ioremap_resource(&pdev->dev, res); |
@@ -1143,32 +1178,25 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1143 | goto err_res; | 1178 | goto err_res; |
1144 | } | 1179 | } |
1145 | 1180 | ||
1146 | if (pdev->dev.of_node) { | 1181 | ret = s5p_mfc_configure_dma_memory(dev); |
1147 | ret = s5p_mfc_alloc_memdevs(dev); | 1182 | if (ret < 0) { |
1148 | if (ret < 0) | 1183 | dev_err(&pdev->dev, "failed to configure DMA memory\n"); |
1149 | goto err_res; | 1184 | return ret; |
1150 | } else { | ||
1151 | dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, | ||
1152 | "s5p-mfc-l", match_child); | ||
1153 | if (!dev->mem_dev_l) { | ||
1154 | mfc_err("Mem child (L) device get failed\n"); | ||
1155 | ret = -ENODEV; | ||
1156 | goto err_res; | ||
1157 | } | ||
1158 | dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, | ||
1159 | "s5p-mfc-r", match_child); | ||
1160 | if (!dev->mem_dev_r) { | ||
1161 | mfc_err("Mem child (R) device get failed\n"); | ||
1162 | ret = -ENODEV; | ||
1163 | goto err_res; | ||
1164 | } | ||
1165 | } | 1185 | } |
1166 | 1186 | ||
1187 | ret = s5p_mfc_init_pm(dev); | ||
1188 | if (ret < 0) { | ||
1189 | dev_err(&pdev->dev, "failed to get mfc clock source\n"); | ||
1190 | return ret; | ||
1191 | } | ||
1192 | |||
1193 | vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32)); | ||
1167 | dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); | 1194 | dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); |
1168 | if (IS_ERR(dev->alloc_ctx[0])) { | 1195 | if (IS_ERR(dev->alloc_ctx[0])) { |
1169 | ret = PTR_ERR(dev->alloc_ctx[0]); | 1196 | ret = PTR_ERR(dev->alloc_ctx[0]); |
1170 | goto err_res; | 1197 | goto err_res; |
1171 | } | 1198 | } |
1199 | vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); | ||
1172 | dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); | 1200 | dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); |
1173 | if (IS_ERR(dev->alloc_ctx[1])) { | 1201 | if (IS_ERR(dev->alloc_ctx[1])) { |
1174 | ret = PTR_ERR(dev->alloc_ctx[1]); | 1202 | ret = PTR_ERR(dev->alloc_ctx[1]); |
@@ -1201,14 +1229,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1201 | vfd->vfl_dir = VFL_DIR_M2M; | 1229 | vfd->vfl_dir = VFL_DIR_M2M; |
1202 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME); | 1230 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME); |
1203 | dev->vfd_dec = vfd; | 1231 | dev->vfd_dec = vfd; |
1204 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | ||
1205 | if (ret) { | ||
1206 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
1207 | video_device_release(vfd); | ||
1208 | goto err_dec_reg; | ||
1209 | } | ||
1210 | v4l2_info(&dev->v4l2_dev, | ||
1211 | "decoder registered as /dev/video%d\n", vfd->num); | ||
1212 | video_set_drvdata(vfd, dev); | 1232 | video_set_drvdata(vfd, dev); |
1213 | 1233 | ||
1214 | /* encoder */ | 1234 | /* encoder */ |
@@ -1226,14 +1246,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1226 | vfd->vfl_dir = VFL_DIR_M2M; | 1246 | vfd->vfl_dir = VFL_DIR_M2M; |
1227 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); | 1247 | snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); |
1228 | dev->vfd_enc = vfd; | 1248 | dev->vfd_enc = vfd; |
1229 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | ||
1230 | if (ret) { | ||
1231 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
1232 | video_device_release(vfd); | ||
1233 | goto err_enc_reg; | ||
1234 | } | ||
1235 | v4l2_info(&dev->v4l2_dev, | ||
1236 | "encoder registered as /dev/video%d\n", vfd->num); | ||
1237 | video_set_drvdata(vfd, dev); | 1249 | video_set_drvdata(vfd, dev); |
1238 | platform_set_drvdata(pdev, dev); | 1250 | platform_set_drvdata(pdev, dev); |
1239 | 1251 | ||
@@ -1250,15 +1262,34 @@ static int s5p_mfc_probe(struct platform_device *pdev) | |||
1250 | s5p_mfc_init_hw_cmds(dev); | 1262 | s5p_mfc_init_hw_cmds(dev); |
1251 | s5p_mfc_init_regs(dev); | 1263 | s5p_mfc_init_regs(dev); |
1252 | 1264 | ||
1265 | /* Register decoder and encoder */ | ||
1266 | ret = video_register_device(dev->vfd_dec, VFL_TYPE_GRABBER, 0); | ||
1267 | if (ret) { | ||
1268 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
1269 | video_device_release(dev->vfd_dec); | ||
1270 | goto err_dec_reg; | ||
1271 | } | ||
1272 | v4l2_info(&dev->v4l2_dev, | ||
1273 | "decoder registered as /dev/video%d\n", dev->vfd_dec->num); | ||
1274 | |||
1275 | ret = video_register_device(dev->vfd_enc, VFL_TYPE_GRABBER, 0); | ||
1276 | if (ret) { | ||
1277 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
1278 | video_device_release(dev->vfd_enc); | ||
1279 | goto err_enc_reg; | ||
1280 | } | ||
1281 | v4l2_info(&dev->v4l2_dev, | ||
1282 | "encoder registered as /dev/video%d\n", dev->vfd_enc->num); | ||
1283 | |||
1253 | pr_debug("%s--\n", __func__); | 1284 | pr_debug("%s--\n", __func__); |
1254 | return 0; | 1285 | return 0; |
1255 | 1286 | ||
1256 | /* Deinit MFC if probe had failed */ | 1287 | /* Deinit MFC if probe had failed */ |
1257 | err_enc_reg: | 1288 | err_enc_reg: |
1258 | video_device_release(dev->vfd_enc); | ||
1259 | err_enc_alloc: | ||
1260 | video_unregister_device(dev->vfd_dec); | 1289 | video_unregister_device(dev->vfd_dec); |
1261 | err_dec_reg: | 1290 | err_dec_reg: |
1291 | video_device_release(dev->vfd_enc); | ||
1292 | err_enc_alloc: | ||
1262 | video_device_release(dev->vfd_dec); | 1293 | video_device_release(dev->vfd_dec); |
1263 | err_dec_alloc: | 1294 | err_dec_alloc: |
1264 | v4l2_device_unregister(&dev->v4l2_dev); | 1295 | v4l2_device_unregister(&dev->v4l2_dev); |
@@ -1293,10 +1324,9 @@ static int s5p_mfc_remove(struct platform_device *pdev) | |||
1293 | s5p_mfc_release_firmware(dev); | 1324 | s5p_mfc_release_firmware(dev); |
1294 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); | 1325 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); |
1295 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); | 1326 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); |
1296 | if (pdev->dev.of_node) { | 1327 | s5p_mfc_unconfigure_dma_memory(dev); |
1297 | put_device(dev->mem_dev_l); | 1328 | vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l); |
1298 | put_device(dev->mem_dev_r); | 1329 | vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r); |
1299 | } | ||
1300 | 1330 | ||
1301 | s5p_mfc_final_pm(dev); | 1331 | s5p_mfc_final_pm(dev); |
1302 | return 0; | 1332 | return 0; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h new file mode 100644 index 000000000000..5d1d1c2922e8 --- /dev/null +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Samsung Electronics Co.Ltd | ||
3 | * Authors: Marek Szyprowski <m.szyprowski@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef S5P_MFC_IOMMU_H_ | ||
12 | #define S5P_MFC_IOMMU_H_ | ||
13 | |||
14 | #define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu | ||
15 | #define S5P_MFC_IOMMU_DMA_SIZE SZ_256M | ||
16 | |||
17 | #ifdef CONFIG_EXYNOS_IOMMU | ||
18 | |||
19 | #include <asm/dma-iommu.h> | ||
20 | |||
21 | static inline bool exynos_is_iommu_available(struct device *dev) | ||
22 | { | ||
23 | return dev->archdata.iommu != NULL; | ||
24 | } | ||
25 | |||
26 | static inline void exynos_unconfigure_iommu(struct device *dev) | ||
27 | { | ||
28 | struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); | ||
29 | |||
30 | arm_iommu_detach_device(dev); | ||
31 | arm_iommu_release_mapping(mapping); | ||
32 | } | ||
33 | |||
34 | static inline int exynos_configure_iommu(struct device *dev, | ||
35 | unsigned int base, unsigned int size) | ||
36 | { | ||
37 | struct dma_iommu_mapping *mapping = NULL; | ||
38 | int ret; | ||
39 | |||
40 | /* Disable the default mapping created by device core */ | ||
41 | if (to_dma_iommu_mapping(dev)) | ||
42 | exynos_unconfigure_iommu(dev); | ||
43 | |||
44 | mapping = arm_iommu_create_mapping(dev->bus, base, size); | ||
45 | if (IS_ERR(mapping)) { | ||
46 | pr_warn("Failed to create IOMMU mapping for device %s\n", | ||
47 | dev_name(dev)); | ||
48 | return PTR_ERR(mapping); | ||
49 | } | ||
50 | |||
51 | ret = arm_iommu_attach_device(dev, mapping); | ||
52 | if (ret) { | ||
53 | pr_warn("Failed to attached device %s to IOMMU_mapping\n", | ||
54 | dev_name(dev)); | ||
55 | arm_iommu_release_mapping(mapping); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | #else | ||
63 | |||
64 | static inline bool exynos_is_iommu_available(struct device *dev) | ||
65 | { | ||
66 | return false; | ||
67 | } | ||
68 | |||
69 | static inline int exynos_configure_iommu(struct device *dev, | ||
70 | unsigned int base, unsigned int size) | ||
71 | { | ||
72 | return -ENOSYS; | ||
73 | } | ||
74 | |||
75 | static inline void exynos_unconfigure_iommu(struct device *dev) { } | ||
76 | |||
77 | #endif | ||
78 | |||
79 | #endif /* S5P_MFC_IOMMU_H_ */ | ||
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 7ab5578a0405..123d27107f60 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c | |||
@@ -80,6 +80,7 @@ int mxr_acquire_video(struct mxr_device *mdev, | |||
80 | goto fail; | 80 | goto fail; |
81 | } | 81 | } |
82 | 82 | ||
83 | vb2_dma_contig_set_max_seg_size(mdev->dev, DMA_BIT_MASK(32)); | ||
83 | mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev); | 84 | mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev); |
84 | if (IS_ERR(mdev->alloc_ctx)) { | 85 | if (IS_ERR(mdev->alloc_ctx)) { |
85 | mxr_err(mdev, "could not acquire vb2 allocator\n"); | 86 | mxr_err(mdev, "could not acquire vb2 allocator\n"); |
@@ -152,6 +153,7 @@ void mxr_release_video(struct mxr_device *mdev) | |||
152 | kfree(mdev->output[i]); | 153 | kfree(mdev->output[i]); |
153 | 154 | ||
154 | vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx); | 155 | vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx); |
156 | vb2_dma_contig_clear_max_seg_size(mdev->dev); | ||
155 | v4l2_device_unregister(&mdev->v4l2_dev); | 157 | v4l2_device_unregister(&mdev->v4l2_dev); |
156 | } | 158 | } |
157 | 159 | ||
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 5361197f3e57..e3e47ace7daf 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c | |||
@@ -753,6 +753,59 @@ void vb2_dma_contig_cleanup_ctx(void *alloc_ctx) | |||
753 | } | 753 | } |
754 | EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx); | 754 | EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx); |
755 | 755 | ||
756 | /** | ||
757 | * vb2_dma_contig_set_max_seg_size() - configure DMA max segment size | ||
758 | * @dev: device for configuring DMA parameters | ||
759 | * @size: size of DMA max segment size to set | ||
760 | * | ||
761 | * To allow mapping the scatter-list into a single chunk in the DMA | ||
762 | * address space, the device is required to have the DMA max segment | ||
763 | * size parameter set to a value larger than the buffer size. Otherwise, | ||
764 | * the DMA-mapping subsystem will split the mapping into max segment | ||
765 | * size chunks. This function sets the DMA max segment size | ||
766 | * parameter to let DMA-mapping map a buffer as a single chunk in DMA | ||
767 | * address space. | ||
768 | * This code assumes that the DMA-mapping subsystem will merge all | ||
769 | * scatterlist segments if this is really possible (for example when | ||
770 | * an IOMMU is available and enabled). | ||
771 | * Ideally, this parameter should be set by the generic bus code, but it | ||
772 | * is left with the default 64KiB value due to historical litmiations in | ||
773 | * other subsystems (like limited USB host drivers) and there no good | ||
774 | * place to set it to the proper value. | ||
775 | * This function should be called from the drivers, which are known to | ||
776 | * operate on platforms with IOMMU and provide access to shared buffers | ||
777 | * (either USERPTR or DMABUF). This should be done before initializing | ||
778 | * videobuf2 queue. | ||
779 | */ | ||
780 | int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size) | ||
781 | { | ||
782 | if (!dev->dma_parms) { | ||
783 | dev->dma_parms = kzalloc(sizeof(dev->dma_parms), GFP_KERNEL); | ||
784 | if (!dev->dma_parms) | ||
785 | return -ENOMEM; | ||
786 | } | ||
787 | if (dma_get_max_seg_size(dev) < size) | ||
788 | return dma_set_max_seg_size(dev, size); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size); | ||
793 | |||
794 | /* | ||
795 | * vb2_dma_contig_clear_max_seg_size() - release resources for DMA parameters | ||
796 | * @dev: device for configuring DMA parameters | ||
797 | * | ||
798 | * This function releases resources allocated to configure DMA parameters | ||
799 | * (see vb2_dma_contig_set_max_seg_size() function). It should be called from | ||
800 | * device drivers on driver remove. | ||
801 | */ | ||
802 | void vb2_dma_contig_clear_max_seg_size(struct device *dev) | ||
803 | { | ||
804 | kfree(dev->dma_parms); | ||
805 | dev->dma_parms = NULL; | ||
806 | } | ||
807 | EXPORT_SYMBOL_GPL(vb2_dma_contig_clear_max_seg_size); | ||
808 | |||
756 | MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2"); | 809 | MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2"); |
757 | MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>"); | 810 | MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>"); |
758 | MODULE_LICENSE("GPL"); | 811 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index ed01c0172e4a..04e4fe58fb0c 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/sizes.h> | 21 | #include <linux/sizes.h> |
22 | #include <linux/of_reserved_mem.h> | 22 | #include <linux/of_reserved_mem.h> |
23 | #include <linux/sort.h> | 23 | #include <linux/sort.h> |
24 | #include <linux/slab.h> | ||
24 | 25 | ||
25 | #define MAX_RESERVED_REGIONS 16 | 26 | #define MAX_RESERVED_REGIONS 16 |
26 | static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; | 27 | static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; |
@@ -289,53 +290,95 @@ static inline struct reserved_mem *__find_rmem(struct device_node *node) | |||
289 | return NULL; | 290 | return NULL; |
290 | } | 291 | } |
291 | 292 | ||
293 | struct rmem_assigned_device { | ||
294 | struct device *dev; | ||
295 | struct reserved_mem *rmem; | ||
296 | struct list_head list; | ||
297 | }; | ||
298 | |||
299 | static LIST_HEAD(of_rmem_assigned_device_list); | ||
300 | static DEFINE_MUTEX(of_rmem_assigned_device_mutex); | ||
301 | |||
292 | /** | 302 | /** |
293 | * of_reserved_mem_device_init() - assign reserved memory region to given device | 303 | * of_reserved_mem_device_init_by_idx() - assign reserved memory region to |
304 | * given device | ||
305 | * @dev: Pointer to the device to configure | ||
306 | * @np: Pointer to the device_node with 'reserved-memory' property | ||
307 | * @idx: Index of selected region | ||
294 | * | 308 | * |
295 | * This function assign memory region pointed by "memory-region" device tree | 309 | * This function assigns respective DMA-mapping operations based on reserved |
296 | * property to the given device. | 310 | * memory region specified by 'memory-region' property in @np node to the @dev |
311 | * device. When driver needs to use more than one reserved memory region, it | ||
312 | * should allocate child devices and initialize regions by name for each of | ||
313 | * child device. | ||
314 | * | ||
315 | * Returns error code or zero on success. | ||
297 | */ | 316 | */ |
298 | int of_reserved_mem_device_init(struct device *dev) | 317 | int of_reserved_mem_device_init_by_idx(struct device *dev, |
318 | struct device_node *np, int idx) | ||
299 | { | 319 | { |
320 | struct rmem_assigned_device *rd; | ||
321 | struct device_node *target; | ||
300 | struct reserved_mem *rmem; | 322 | struct reserved_mem *rmem; |
301 | struct device_node *np; | ||
302 | int ret; | 323 | int ret; |
303 | 324 | ||
304 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | 325 | if (!np || !dev) |
305 | if (!np) | 326 | return -EINVAL; |
306 | return -ENODEV; | 327 | |
328 | target = of_parse_phandle(np, "memory-region", idx); | ||
329 | if (!target) | ||
330 | return -EINVAL; | ||
307 | 331 | ||
308 | rmem = __find_rmem(np); | 332 | rmem = __find_rmem(target); |
309 | of_node_put(np); | 333 | of_node_put(target); |
310 | 334 | ||
311 | if (!rmem || !rmem->ops || !rmem->ops->device_init) | 335 | if (!rmem || !rmem->ops || !rmem->ops->device_init) |
312 | return -EINVAL; | 336 | return -EINVAL; |
313 | 337 | ||
338 | rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL); | ||
339 | if (!rd) | ||
340 | return -ENOMEM; | ||
341 | |||
314 | ret = rmem->ops->device_init(rmem, dev); | 342 | ret = rmem->ops->device_init(rmem, dev); |
315 | if (ret == 0) | 343 | if (ret == 0) { |
344 | rd->dev = dev; | ||
345 | rd->rmem = rmem; | ||
346 | |||
347 | mutex_lock(&of_rmem_assigned_device_mutex); | ||
348 | list_add(&rd->list, &of_rmem_assigned_device_list); | ||
349 | mutex_unlock(&of_rmem_assigned_device_mutex); | ||
350 | |||
316 | dev_info(dev, "assigned reserved memory node %s\n", rmem->name); | 351 | dev_info(dev, "assigned reserved memory node %s\n", rmem->name); |
352 | } else { | ||
353 | kfree(rd); | ||
354 | } | ||
317 | 355 | ||
318 | return ret; | 356 | return ret; |
319 | } | 357 | } |
320 | EXPORT_SYMBOL_GPL(of_reserved_mem_device_init); | 358 | EXPORT_SYMBOL_GPL(of_reserved_mem_device_init_by_idx); |
321 | 359 | ||
322 | /** | 360 | /** |
323 | * of_reserved_mem_device_release() - release reserved memory device structures | 361 | * of_reserved_mem_device_release() - release reserved memory device structures |
362 | * @dev: Pointer to the device to deconfigure | ||
324 | * | 363 | * |
325 | * This function releases structures allocated for memory region handling for | 364 | * This function releases structures allocated for memory region handling for |
326 | * the given device. | 365 | * the given device. |
327 | */ | 366 | */ |
328 | void of_reserved_mem_device_release(struct device *dev) | 367 | void of_reserved_mem_device_release(struct device *dev) |
329 | { | 368 | { |
330 | struct reserved_mem *rmem; | 369 | struct rmem_assigned_device *rd; |
331 | struct device_node *np; | 370 | struct reserved_mem *rmem = NULL; |
332 | 371 | ||
333 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | 372 | mutex_lock(&of_rmem_assigned_device_mutex); |
334 | if (!np) | 373 | list_for_each_entry(rd, &of_rmem_assigned_device_list, list) { |
335 | return; | 374 | if (rd->dev == dev) { |
336 | 375 | rmem = rd->rmem; | |
337 | rmem = __find_rmem(np); | 376 | list_del(&rd->list); |
338 | of_node_put(np); | 377 | kfree(rd); |
378 | break; | ||
379 | } | ||
380 | } | ||
381 | mutex_unlock(&of_rmem_assigned_device_mutex); | ||
339 | 382 | ||
340 | if (!rmem || !rmem->ops || !rmem->ops->device_release) | 383 | if (!rmem || !rmem->ops || !rmem->ops->device_release) |
341 | return; | 384 | return; |
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h index ad2f67054372..1779cda99ef7 100644 --- a/include/linux/of_reserved_mem.h +++ b/include/linux/of_reserved_mem.h | |||
@@ -1,7 +1,8 @@ | |||
1 | #ifndef __OF_RESERVED_MEM_H | 1 | #ifndef __OF_RESERVED_MEM_H |
2 | #define __OF_RESERVED_MEM_H | 2 | #define __OF_RESERVED_MEM_H |
3 | 3 | ||
4 | struct device; | 4 | #include <linux/device.h> |
5 | |||
5 | struct of_phandle_args; | 6 | struct of_phandle_args; |
6 | struct reserved_mem_ops; | 7 | struct reserved_mem_ops; |
7 | 8 | ||
@@ -28,14 +29,17 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem); | |||
28 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) | 29 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) |
29 | 30 | ||
30 | #ifdef CONFIG_OF_RESERVED_MEM | 31 | #ifdef CONFIG_OF_RESERVED_MEM |
31 | int of_reserved_mem_device_init(struct device *dev); | 32 | |
33 | int of_reserved_mem_device_init_by_idx(struct device *dev, | ||
34 | struct device_node *np, int idx); | ||
32 | void of_reserved_mem_device_release(struct device *dev); | 35 | void of_reserved_mem_device_release(struct device *dev); |
33 | 36 | ||
34 | void fdt_init_reserved_mem(void); | 37 | void fdt_init_reserved_mem(void); |
35 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, | 38 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, |
36 | phys_addr_t base, phys_addr_t size); | 39 | phys_addr_t base, phys_addr_t size); |
37 | #else | 40 | #else |
38 | static inline int of_reserved_mem_device_init(struct device *dev) | 41 | static inline int of_reserved_mem_device_init_by_idx(struct device *dev, |
42 | struct device_node *np, int idx) | ||
39 | { | 43 | { |
40 | return -ENOSYS; | 44 | return -ENOSYS; |
41 | } | 45 | } |
@@ -46,4 +50,19 @@ static inline void fdt_reserved_mem_save_node(unsigned long node, | |||
46 | const char *uname, phys_addr_t base, phys_addr_t size) { } | 50 | const char *uname, phys_addr_t base, phys_addr_t size) { } |
47 | #endif | 51 | #endif |
48 | 52 | ||
53 | /** | ||
54 | * of_reserved_mem_device_init() - assign reserved memory region to given device | ||
55 | * @dev: Pointer to the device to configure | ||
56 | * | ||
57 | * This function assigns respective DMA-mapping operations based on the first | ||
58 | * reserved memory region specified by 'memory-region' property in device tree | ||
59 | * node of the given device. | ||
60 | * | ||
61 | * Returns error code or zero on success. | ||
62 | */ | ||
63 | static inline int of_reserved_mem_device_init(struct device *dev) | ||
64 | { | ||
65 | return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0); | ||
66 | } | ||
67 | |||
49 | #endif /* __OF_RESERVED_MEM_H */ | 68 | #endif /* __OF_RESERVED_MEM_H */ |
diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h index 2087c9a68be3..f7dc8401817e 100644 --- a/include/media/videobuf2-dma-contig.h +++ b/include/media/videobuf2-dma-contig.h | |||
@@ -35,6 +35,8 @@ static inline void *vb2_dma_contig_init_ctx(struct device *dev) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | void vb2_dma_contig_cleanup_ctx(void *alloc_ctx); | 37 | void vb2_dma_contig_cleanup_ctx(void *alloc_ctx); |
38 | int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size); | ||
39 | void vb2_dma_contig_clear_max_seg_size(struct device *dev); | ||
38 | 40 | ||
39 | extern const struct vb2_mem_ops vb2_dma_contig_memops; | 41 | extern const struct vb2_mem_ops vb2_dma_contig_memops; |
40 | 42 | ||