aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/s5p-mfc
diff options
context:
space:
mode:
authorKamil Debski <k.debski@samsung.com>2013-01-03 09:02:07 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-01-06 06:57:57 -0500
commit2e731e443fcc8e4553201ad0573c1d5571e906ac (patch)
tree180458e6f6960f5980738ee5d0817bdae0c44d58 /drivers/media/platform/s5p-mfc
parent4a9c85aa495a35593eb7f3fd3dc259fd020308b4 (diff)
[media] s5p-mfc: Move firmware allocation point to avoid allocation problems
Move firmware allocation from open to probe to avoid problems when using CMA for allocation. In certain circumstances CMA may allocate buffer that is not in the beginning of the MFC memory area. Signed-off-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform/s5p-mfc')
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c29
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h10
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c149
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h3
4 files changed, 94 insertions, 97 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 3930177db125..9a679fab73e2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -793,14 +793,16 @@ static int s5p_mfc_open(struct file *file)
793 goto err_pwr_enable; 793 goto err_pwr_enable;
794 } 794 }
795 s5p_mfc_clock_on(); 795 s5p_mfc_clock_on();
796 ret = s5p_mfc_alloc_and_load_firmware(dev); 796 ret = s5p_mfc_load_firmware(dev);
797 if (ret) 797 if (ret) {
798 goto err_alloc_fw; 798 s5p_mfc_clock_off();
799 goto err_load_fw;
800 }
799 /* Init the FW */ 801 /* Init the FW */
800 ret = s5p_mfc_init_hw(dev); 802 ret = s5p_mfc_init_hw(dev);
803 s5p_mfc_clock_off();
801 if (ret) 804 if (ret)
802 goto err_init_hw; 805 goto err_init_hw;
803 s5p_mfc_clock_off();
804 } 806 }
805 /* Init videobuf2 queue for CAPTURE */ 807 /* Init videobuf2 queue for CAPTURE */
806 q = &ctx->vq_dst; 808 q = &ctx->vq_dst;
@@ -849,17 +851,16 @@ static int s5p_mfc_open(struct file *file)
849 return ret; 851 return ret;
850 /* Deinit when failure occured */ 852 /* Deinit when failure occured */
851err_queue_init: 853err_queue_init:
854 if (dev->num_inst == 1)
855 s5p_mfc_deinit_hw(dev);
852err_init_hw: 856err_init_hw:
853 s5p_mfc_release_firmware(dev); 857err_load_fw:
854err_alloc_fw:
855 dev->ctx[ctx->num] = NULL; 858 dev->ctx[ctx->num] = NULL;
856 del_timer_sync(&dev->watchdog_timer); 859 del_timer_sync(&dev->watchdog_timer);
857 s5p_mfc_clock_off();
858err_pwr_enable: 860err_pwr_enable:
859 if (dev->num_inst == 1) { 861 if (dev->num_inst == 1) {
860 if (s5p_mfc_power_off() < 0) 862 if (s5p_mfc_power_off() < 0)
861 mfc_err("power off failed\n"); 863 mfc_err("power off failed\n");
862 s5p_mfc_release_firmware(dev);
863 } 864 }
864err_ctrls_setup: 865err_ctrls_setup:
865 s5p_mfc_dec_ctrls_delete(ctx); 866 s5p_mfc_dec_ctrls_delete(ctx);
@@ -917,11 +918,8 @@ static int s5p_mfc_release(struct file *file)
917 clear_bit(0, &dev->hw_lock); 918 clear_bit(0, &dev->hw_lock);
918 dev->num_inst--; 919 dev->num_inst--;
919 if (dev->num_inst == 0) { 920 if (dev->num_inst == 0) {
920 mfc_debug(2, "Last instance - release firmware\n"); 921 mfc_debug(2, "Last instance\n");
921 /* reset <-> F/W release */
922 s5p_mfc_reset(dev);
923 s5p_mfc_deinit_hw(dev); 922 s5p_mfc_deinit_hw(dev);
924 s5p_mfc_release_firmware(dev);
925 del_timer_sync(&dev->watchdog_timer); 923 del_timer_sync(&dev->watchdog_timer);
926 if (s5p_mfc_power_off() < 0) 924 if (s5p_mfc_power_off() < 0)
927 mfc_err("Power off failed\n"); 925 mfc_err("Power off failed\n");
@@ -1149,6 +1147,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
1149 1147
1150 mutex_init(&dev->mfc_mutex); 1148 mutex_init(&dev->mfc_mutex);
1151 1149
1150 ret = s5p_mfc_alloc_firmware(dev);
1151 if (ret)
1152 goto err_alloc_fw;
1153
1152 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 1154 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
1153 if (ret) 1155 if (ret)
1154 goto err_v4l2_dev_reg; 1156 goto err_v4l2_dev_reg;
@@ -1230,6 +1232,8 @@ err_dec_reg:
1230err_dec_alloc: 1232err_dec_alloc:
1231 v4l2_device_unregister(&dev->v4l2_dev); 1233 v4l2_device_unregister(&dev->v4l2_dev);
1232err_v4l2_dev_reg: 1234err_v4l2_dev_reg:
1235 s5p_mfc_release_firmware(dev);
1236err_alloc_fw:
1233 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); 1237 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
1234err_mem_init_ctx_1: 1238err_mem_init_ctx_1:
1235 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); 1239 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
@@ -1255,6 +1259,7 @@ static int __devexit s5p_mfc_remove(struct platform_device *pdev)
1255 video_unregister_device(dev->vfd_enc); 1259 video_unregister_device(dev->vfd_enc);
1256 video_unregister_device(dev->vfd_dec); 1260 video_unregister_device(dev->vfd_dec);
1257 v4l2_device_unregister(&dev->v4l2_dev); 1261 v4l2_device_unregister(&dev->v4l2_dev);
1262 s5p_mfc_release_firmware(dev);
1258 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); 1263 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
1259 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); 1264 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
1260 1265
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 3b9b600a6182..0df6454e407e 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -278,8 +278,9 @@ struct s5p_mfc_priv_buf {
278 * @int_err: error number for last interrupt 278 * @int_err: error number for last interrupt
279 * @queue: waitqueue for waiting for completion of device commands 279 * @queue: waitqueue for waiting for completion of device commands
280 * @fw_size: size of firmware 280 * @fw_size: size of firmware
281 * @bank1: address of the beggining of bank 1 memory 281 * @fw_virt_addr: virtual firmware address
282 * @bank2: address of the beggining of bank 2 memory 282 * @bank1: address of the beginning of bank 1 memory
283 * @bank2: address of the beginning of bank 2 memory
283 * @hw_lock: used for hardware locking 284 * @hw_lock: used for hardware locking
284 * @ctx: array of driver contexts 285 * @ctx: array of driver contexts
285 * @curr_ctx: number of the currently running context 286 * @curr_ctx: number of the currently running context
@@ -318,8 +319,9 @@ struct s5p_mfc_dev {
318 unsigned int int_err; 319 unsigned int int_err;
319 wait_queue_head_t queue; 320 wait_queue_head_t queue;
320 size_t fw_size; 321 size_t fw_size;
321 size_t bank1; 322 void *fw_virt_addr;
322 size_t bank2; 323 dma_addr_t bank1;
324 dma_addr_t bank2;
323 unsigned long hw_lock; 325 unsigned long hw_lock;
324 struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; 326 struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
325 int curr_ctx; 327 int curr_ctx;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 585b7b0ed8ec..1682271c2453 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -22,16 +22,64 @@
22#include "s5p_mfc_opr.h" 22#include "s5p_mfc_opr.h"
23#include "s5p_mfc_pm.h" 23#include "s5p_mfc_pm.h"
24 24
25static void *s5p_mfc_bitproc_buf; 25/* Allocate memory for firmware */
26static size_t s5p_mfc_bitproc_phys; 26int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
27static unsigned char *s5p_mfc_bitproc_virt; 27{
28 void *bank2_virt;
29 dma_addr_t bank2_dma_addr;
30
31 dev->fw_size = dev->variant->buf_size->fw;
32
33 if (dev->fw_virt_addr) {
34 mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
35 return -ENOMEM;
36 }
37
38 dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size,
39 &dev->bank1, GFP_KERNEL);
40
41 if (IS_ERR(dev->fw_virt_addr)) {
42 dev->fw_virt_addr = NULL;
43 mfc_err("Allocating bitprocessor buffer failed\n");
44 return -ENOMEM;
45 }
46
47 dev->bank1 = dev->bank1;
48
49 if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
50 bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
51 &bank2_dma_addr, GFP_KERNEL);
52
53 if (IS_ERR(dev->fw_virt_addr)) {
54 mfc_err("Allocating bank2 base failed\n");
55 dma_free_coherent(dev->mem_dev_l, dev->fw_size,
56 dev->fw_virt_addr, dev->bank1);
57 dev->fw_virt_addr = NULL;
58 return -ENOMEM;
59 }
60
61 /* Valid buffers passed to MFC encoder with LAST_FRAME command
62 * should not have address of bank2 - MFC will treat it as a null frame.
63 * To avoid such situation we set bank2 address below the pool address.
64 */
65 dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER);
66
67 dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
68 bank2_virt, bank2_dma_addr);
69
70 } else {
71 /* In this case bank2 can point to the same address as bank1.
72 * Firmware will always occupy the beggining of this area so it is
73 * impossible having a video frame buffer with zero address. */
74 dev->bank2 = dev->bank1;
75 }
76 return 0;
77}
28 78
29/* Allocate and load firmware */ 79/* Load firmware */
30int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) 80int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
31{ 81{
32 struct firmware *fw_blob; 82 struct firmware *fw_blob;
33 size_t bank2_base_phys;
34 void *b_base;
35 int err; 83 int err;
36 84
37 /* Firmare has to be present as a separate file or compiled 85 /* Firmare has to be present as a separate file or compiled
@@ -44,77 +92,17 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
44 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); 92 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
45 return -EINVAL; 93 return -EINVAL;
46 } 94 }
47 dev->fw_size = dev->variant->buf_size->fw;
48 if (fw_blob->size > dev->fw_size) { 95 if (fw_blob->size > dev->fw_size) {
49 mfc_err("MFC firmware is too big to be loaded\n"); 96 mfc_err("MFC firmware is too big to be loaded\n");
50 release_firmware(fw_blob); 97 release_firmware(fw_blob);
51 return -ENOMEM; 98 return -ENOMEM;
52 } 99 }
53 if (s5p_mfc_bitproc_buf) { 100 if (!dev->fw_virt_addr) {
54 mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); 101 mfc_err("MFC firmware is not allocated\n");
55 release_firmware(fw_blob);
56 return -ENOMEM;
57 }
58 s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
59 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
60 if (IS_ERR(s5p_mfc_bitproc_buf)) {
61 s5p_mfc_bitproc_buf = NULL;
62 mfc_err("Allocating bitprocessor buffer failed\n");
63 release_firmware(fw_blob); 102 release_firmware(fw_blob);
64 return -ENOMEM; 103 return -EINVAL;
65 }
66 s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
67 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
68 if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
69 mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
70 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
71 s5p_mfc_bitproc_phys = 0;
72 s5p_mfc_bitproc_buf = NULL;
73 release_firmware(fw_blob);
74 return -EIO;
75 }
76 s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
77 if (!s5p_mfc_bitproc_virt) {
78 mfc_err("Bitprocessor memory remap failed\n");
79 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
80 s5p_mfc_bitproc_phys = 0;
81 s5p_mfc_bitproc_buf = NULL;
82 release_firmware(fw_blob);
83 return -EIO;
84 }
85 dev->bank1 = s5p_mfc_bitproc_phys;
86 if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
87 b_base = vb2_dma_contig_memops.alloc(
88 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
89 1 << MFC_BASE_ALIGN_ORDER);
90 if (IS_ERR(b_base)) {
91 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
92 s5p_mfc_bitproc_phys = 0;
93 s5p_mfc_bitproc_buf = NULL;
94 mfc_err("Allocating bank2 base failed\n");
95 release_firmware(fw_blob);
96 return -ENOMEM;
97 }
98 bank2_base_phys = s5p_mfc_mem_cookie(
99 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
100 vb2_dma_contig_memops.put(b_base);
101 if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
102 mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
103 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
104 s5p_mfc_bitproc_phys = 0;
105 s5p_mfc_bitproc_buf = NULL;
106 release_firmware(fw_blob);
107 return -EIO;
108 }
109 /* Valid buffers passed to MFC encoder with LAST_FRAME command
110 * should not have address of bank2 - MFC will treat it as a null frame.
111 * To avoid such situation we set bank2 address below the pool address.
112 */
113 dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
114 } else {
115 dev->bank2 = dev->bank1;
116 } 104 }
117 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); 105 memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
118 wmb(); 106 wmb();
119 release_firmware(fw_blob); 107 release_firmware(fw_blob);
120 mfc_debug_leave(); 108 mfc_debug_leave();
@@ -142,12 +130,12 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
142 release_firmware(fw_blob); 130 release_firmware(fw_blob);
143 return -ENOMEM; 131 return -ENOMEM;
144 } 132 }
145 if (s5p_mfc_bitproc_buf == NULL || s5p_mfc_bitproc_phys == 0) { 133 if (dev->fw_virt_addr) {
146 mfc_err("MFC firmware is not allocated or was not mapped correctly\n"); 134 mfc_err("MFC firmware is not allocated\n");
147 release_firmware(fw_blob); 135 release_firmware(fw_blob);
148 return -EINVAL; 136 return -EINVAL;
149 } 137 }
150 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); 138 memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
151 wmb(); 139 wmb();
152 release_firmware(fw_blob); 140 release_firmware(fw_blob);
153 mfc_debug_leave(); 141 mfc_debug_leave();
@@ -159,12 +147,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
159{ 147{
160 /* Before calling this function one has to make sure 148 /* Before calling this function one has to make sure
161 * that MFC is no longer processing */ 149 * that MFC is no longer processing */
162 if (!s5p_mfc_bitproc_buf) 150 if (!dev->fw_virt_addr)
163 return -EINVAL; 151 return -EINVAL;
164 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); 152 dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr,
165 s5p_mfc_bitproc_virt = NULL; 153 dev->bank1);
166 s5p_mfc_bitproc_phys = 0; 154 dev->fw_virt_addr = NULL;
167 s5p_mfc_bitproc_buf = NULL;
168 return 0; 155 return 0;
169} 156}
170 157
@@ -257,8 +244,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
257 int ret; 244 int ret;
258 245
259 mfc_debug_enter(); 246 mfc_debug_enter();
260 if (!s5p_mfc_bitproc_buf) 247 if (!dev->fw_virt_addr) {
248 mfc_err("Firmware memory is not allocated.\n");
261 return -EINVAL; 249 return -EINVAL;
250 }
262 251
263 /* 0. MFC reset */ 252 /* 0. MFC reset */
264 mfc_debug(2, "MFC reset..\n"); 253 mfc_debug(2, "MFC reset..\n");
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
index 90aa9b9886d5..6a9b6f8606bb 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
@@ -16,7 +16,8 @@
16#include "s5p_mfc_common.h" 16#include "s5p_mfc_common.h"
17 17
18int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); 18int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
19int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev); 19int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev);
20int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev);
20int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); 21int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
21 22
22int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); 23int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);