diff options
-rw-r--r-- | arch/arm/plat-omap/dma.c | 737 | ||||
-rw-r--r-- | include/linux/omap-dma.h | 37 |
2 files changed, 6 insertions, 768 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index c2baa8ede543..24770e5a5081 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -64,7 +64,9 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; | |||
64 | 64 | ||
65 | static struct omap_system_dma_plat_info *p; | 65 | static struct omap_system_dma_plat_info *p; |
66 | static struct omap_dma_dev_attr *d; | 66 | static struct omap_dma_dev_attr *d; |
67 | 67 | static void omap_clear_dma(int lch); | |
68 | static int omap_dma_set_prio_lch(int lch, unsigned char read_prio, | ||
69 | unsigned char write_prio); | ||
68 | static int enable_1510_mode; | 70 | static int enable_1510_mode; |
69 | static u32 errata; | 71 | static u32 errata; |
70 | 72 | ||
@@ -284,66 +286,6 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, | |||
284 | } | 286 | } |
285 | EXPORT_SYMBOL(omap_set_dma_transfer_params); | 287 | EXPORT_SYMBOL(omap_set_dma_transfer_params); |
286 | 288 | ||
287 | void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) | ||
288 | { | ||
289 | BUG_ON(omap_dma_in_1510_mode()); | ||
290 | |||
291 | if (dma_omap1()) { | ||
292 | u16 w; | ||
293 | |||
294 | w = p->dma_read(CCR2, lch); | ||
295 | w &= ~0x03; | ||
296 | |||
297 | switch (mode) { | ||
298 | case OMAP_DMA_CONSTANT_FILL: | ||
299 | w |= 0x01; | ||
300 | break; | ||
301 | case OMAP_DMA_TRANSPARENT_COPY: | ||
302 | w |= 0x02; | ||
303 | break; | ||
304 | case OMAP_DMA_COLOR_DIS: | ||
305 | break; | ||
306 | default: | ||
307 | BUG(); | ||
308 | } | ||
309 | p->dma_write(w, CCR2, lch); | ||
310 | |||
311 | w = p->dma_read(LCH_CTRL, lch); | ||
312 | w &= ~0x0f; | ||
313 | /* Default is channel type 2D */ | ||
314 | if (mode) { | ||
315 | p->dma_write(color, COLOR, lch); | ||
316 | w |= 1; /* Channel type G */ | ||
317 | } | ||
318 | p->dma_write(w, LCH_CTRL, lch); | ||
319 | } | ||
320 | |||
321 | if (dma_omap2plus()) { | ||
322 | u32 val; | ||
323 | |||
324 | val = p->dma_read(CCR, lch); | ||
325 | val &= ~((1 << 17) | (1 << 16)); | ||
326 | |||
327 | switch (mode) { | ||
328 | case OMAP_DMA_CONSTANT_FILL: | ||
329 | val |= 1 << 16; | ||
330 | break; | ||
331 | case OMAP_DMA_TRANSPARENT_COPY: | ||
332 | val |= 1 << 17; | ||
333 | break; | ||
334 | case OMAP_DMA_COLOR_DIS: | ||
335 | break; | ||
336 | default: | ||
337 | BUG(); | ||
338 | } | ||
339 | p->dma_write(val, CCR, lch); | ||
340 | |||
341 | color &= 0xffffff; | ||
342 | p->dma_write(color, COLOR, lch); | ||
343 | } | ||
344 | } | ||
345 | EXPORT_SYMBOL(omap_set_dma_color_mode); | ||
346 | |||
347 | void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) | 289 | void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) |
348 | { | 290 | { |
349 | if (dma_omap2plus()) { | 291 | if (dma_omap2plus()) { |
@@ -417,16 +359,6 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params *params) | |||
417 | } | 359 | } |
418 | EXPORT_SYMBOL(omap_set_dma_params); | 360 | EXPORT_SYMBOL(omap_set_dma_params); |
419 | 361 | ||
420 | void omap_set_dma_src_index(int lch, int eidx, int fidx) | ||
421 | { | ||
422 | if (dma_omap2plus()) | ||
423 | return; | ||
424 | |||
425 | p->dma_write(eidx, CSEI, lch); | ||
426 | p->dma_write(fidx, CSFI, lch); | ||
427 | } | ||
428 | EXPORT_SYMBOL(omap_set_dma_src_index); | ||
429 | |||
430 | void omap_set_dma_src_data_pack(int lch, int enable) | 362 | void omap_set_dma_src_data_pack(int lch, int enable) |
431 | { | 363 | { |
432 | u32 l; | 364 | u32 l; |
@@ -510,16 +442,6 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, | |||
510 | } | 442 | } |
511 | EXPORT_SYMBOL(omap_set_dma_dest_params); | 443 | EXPORT_SYMBOL(omap_set_dma_dest_params); |
512 | 444 | ||
513 | void omap_set_dma_dest_index(int lch, int eidx, int fidx) | ||
514 | { | ||
515 | if (dma_omap2plus()) | ||
516 | return; | ||
517 | |||
518 | p->dma_write(eidx, CDEI, lch); | ||
519 | p->dma_write(fidx, CDFI, lch); | ||
520 | } | ||
521 | EXPORT_SYMBOL(omap_set_dma_dest_index); | ||
522 | |||
523 | void omap_set_dma_dest_data_pack(int lch, int enable) | 445 | void omap_set_dma_dest_data_pack(int lch, int enable) |
524 | { | 446 | { |
525 | u32 l; | 447 | u32 l; |
@@ -843,7 +765,7 @@ EXPORT_SYMBOL(omap_dma_set_global_params); | |||
843 | * Both of the above can be set with one of the following values : | 765 | * Both of the above can be set with one of the following values : |
844 | * DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW | 766 | * DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW |
845 | */ | 767 | */ |
846 | int | 768 | static int |
847 | omap_dma_set_prio_lch(int lch, unsigned char read_prio, | 769 | omap_dma_set_prio_lch(int lch, unsigned char read_prio, |
848 | unsigned char write_prio) | 770 | unsigned char write_prio) |
849 | { | 771 | { |
@@ -864,13 +786,13 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, | |||
864 | 786 | ||
865 | return 0; | 787 | return 0; |
866 | } | 788 | } |
867 | EXPORT_SYMBOL(omap_dma_set_prio_lch); | 789 | |
868 | 790 | ||
869 | /* | 791 | /* |
870 | * Clears any DMA state so the DMA engine is ready to restart with new buffers | 792 | * Clears any DMA state so the DMA engine is ready to restart with new buffers |
871 | * through omap_start_dma(). Any buffers in flight are discarded. | 793 | * through omap_start_dma(). Any buffers in flight are discarded. |
872 | */ | 794 | */ |
873 | void omap_clear_dma(int lch) | 795 | static void omap_clear_dma(int lch) |
874 | { | 796 | { |
875 | unsigned long flags; | 797 | unsigned long flags; |
876 | 798 | ||
@@ -878,7 +800,6 @@ void omap_clear_dma(int lch) | |||
878 | p->clear_dma(lch); | 800 | p->clear_dma(lch); |
879 | local_irq_restore(flags); | 801 | local_irq_restore(flags); |
880 | } | 802 | } |
881 | EXPORT_SYMBOL(omap_clear_dma); | ||
882 | 803 | ||
883 | void omap_start_dma(int lch) | 804 | void omap_start_dma(int lch) |
884 | { | 805 | { |
@@ -1167,652 +1088,6 @@ void omap_dma_link_lch(int lch_head, int lch_queue) | |||
1167 | } | 1088 | } |
1168 | EXPORT_SYMBOL(omap_dma_link_lch); | 1089 | EXPORT_SYMBOL(omap_dma_link_lch); |
1169 | 1090 | ||
1170 | /* | ||
1171 | * Once the DMA queue is stopped, we can destroy it. | ||
1172 | */ | ||
1173 | void omap_dma_unlink_lch(int lch_head, int lch_queue) | ||
1174 | { | ||
1175 | if (omap_dma_in_1510_mode()) { | ||
1176 | if (lch_head == lch_queue) { | ||
1177 | p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), | ||
1178 | CCR, lch_head); | ||
1179 | return; | ||
1180 | } | ||
1181 | printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); | ||
1182 | BUG(); | ||
1183 | return; | ||
1184 | } | ||
1185 | |||
1186 | if (dma_chan[lch_head].next_lch != lch_queue || | ||
1187 | dma_chan[lch_head].next_lch == -1) { | ||
1188 | pr_err("omap_dma: trying to unlink non linked channels\n"); | ||
1189 | dump_stack(); | ||
1190 | } | ||
1191 | |||
1192 | if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) || | ||
1193 | (dma_chan[lch_queue].flags & OMAP_DMA_ACTIVE)) { | ||
1194 | pr_err("omap_dma: You need to stop the DMA channels before unlinking\n"); | ||
1195 | dump_stack(); | ||
1196 | } | ||
1197 | |||
1198 | dma_chan[lch_head].next_lch = -1; | ||
1199 | } | ||
1200 | EXPORT_SYMBOL(omap_dma_unlink_lch); | ||
1201 | |||
1202 | #ifndef CONFIG_ARCH_OMAP1 | ||
1203 | /* Create chain of DMA channesls */ | ||
1204 | static void create_dma_lch_chain(int lch_head, int lch_queue) | ||
1205 | { | ||
1206 | u32 l; | ||
1207 | |||
1208 | /* Check if this is the first link in chain */ | ||
1209 | if (dma_chan[lch_head].next_linked_ch == -1) { | ||
1210 | dma_chan[lch_head].next_linked_ch = lch_queue; | ||
1211 | dma_chan[lch_head].prev_linked_ch = lch_queue; | ||
1212 | dma_chan[lch_queue].next_linked_ch = lch_head; | ||
1213 | dma_chan[lch_queue].prev_linked_ch = lch_head; | ||
1214 | } | ||
1215 | |||
1216 | /* a link exists, link the new channel in circular chain */ | ||
1217 | else { | ||
1218 | dma_chan[lch_queue].next_linked_ch = | ||
1219 | dma_chan[lch_head].next_linked_ch; | ||
1220 | dma_chan[lch_queue].prev_linked_ch = lch_head; | ||
1221 | dma_chan[lch_head].next_linked_ch = lch_queue; | ||
1222 | dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch = | ||
1223 | lch_queue; | ||
1224 | } | ||
1225 | |||
1226 | l = p->dma_read(CLNK_CTRL, lch_head); | ||
1227 | l &= ~(0x1f); | ||
1228 | l |= lch_queue; | ||
1229 | p->dma_write(l, CLNK_CTRL, lch_head); | ||
1230 | |||
1231 | l = p->dma_read(CLNK_CTRL, lch_queue); | ||
1232 | l &= ~(0x1f); | ||
1233 | l |= (dma_chan[lch_queue].next_linked_ch); | ||
1234 | p->dma_write(l, CLNK_CTRL, lch_queue); | ||
1235 | } | ||
1236 | |||
1237 | /** | ||
1238 | * @brief omap_request_dma_chain : Request a chain of DMA channels | ||
1239 | * | ||
1240 | * @param dev_id - Device id using the dma channel | ||
1241 | * @param dev_name - Device name | ||
1242 | * @param callback - Call back function | ||
1243 | * @chain_id - | ||
1244 | * @no_of_chans - Number of channels requested | ||
1245 | * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN | ||
1246 | * OMAP_DMA_DYNAMIC_CHAIN | ||
1247 | * @params - Channel parameters | ||
1248 | * | ||
1249 | * @return - Success : 0 | ||
1250 | * Failure: -EINVAL/-ENOMEM | ||
1251 | */ | ||
1252 | int omap_request_dma_chain(int dev_id, const char *dev_name, | ||
1253 | void (*callback) (int lch, u16 ch_status, | ||
1254 | void *data), | ||
1255 | int *chain_id, int no_of_chans, int chain_mode, | ||
1256 | struct omap_dma_channel_params params) | ||
1257 | { | ||
1258 | int *channels; | ||
1259 | int i, err; | ||
1260 | |||
1261 | /* Is the chain mode valid ? */ | ||
1262 | if (chain_mode != OMAP_DMA_STATIC_CHAIN | ||
1263 | && chain_mode != OMAP_DMA_DYNAMIC_CHAIN) { | ||
1264 | printk(KERN_ERR "Invalid chain mode requested\n"); | ||
1265 | return -EINVAL; | ||
1266 | } | ||
1267 | |||
1268 | if (unlikely((no_of_chans < 1 | ||
1269 | || no_of_chans > dma_lch_count))) { | ||
1270 | printk(KERN_ERR "Invalid Number of channels requested\n"); | ||
1271 | return -EINVAL; | ||
1272 | } | ||
1273 | |||
1274 | /* | ||
1275 | * Allocate a queue to maintain the status of the channels | ||
1276 | * in the chain | ||
1277 | */ | ||
1278 | channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL); | ||
1279 | if (channels == NULL) { | ||
1280 | printk(KERN_ERR "omap_dma: No memory for channel queue\n"); | ||
1281 | return -ENOMEM; | ||
1282 | } | ||
1283 | |||
1284 | /* request and reserve DMA channels for the chain */ | ||
1285 | for (i = 0; i < no_of_chans; i++) { | ||
1286 | err = omap_request_dma(dev_id, dev_name, | ||
1287 | callback, NULL, &channels[i]); | ||
1288 | if (err < 0) { | ||
1289 | int j; | ||
1290 | for (j = 0; j < i; j++) | ||
1291 | omap_free_dma(channels[j]); | ||
1292 | kfree(channels); | ||
1293 | printk(KERN_ERR "omap_dma: Request failed %d\n", err); | ||
1294 | return err; | ||
1295 | } | ||
1296 | dma_chan[channels[i]].prev_linked_ch = -1; | ||
1297 | dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; | ||
1298 | |||
1299 | /* | ||
1300 | * Allowing client drivers to set common parameters now, | ||
1301 | * so that later only relevant (src_start, dest_start | ||
1302 | * and element count) can be set | ||
1303 | */ | ||
1304 | omap_set_dma_params(channels[i], ¶ms); | ||
1305 | } | ||
1306 | |||
1307 | *chain_id = channels[0]; | ||
1308 | dma_linked_lch[*chain_id].linked_dmach_q = channels; | ||
1309 | dma_linked_lch[*chain_id].chain_mode = chain_mode; | ||
1310 | dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED; | ||
1311 | dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans; | ||
1312 | |||
1313 | for (i = 0; i < no_of_chans; i++) | ||
1314 | dma_chan[channels[i]].chain_id = *chain_id; | ||
1315 | |||
1316 | /* Reset the Queue pointers */ | ||
1317 | OMAP_DMA_CHAIN_QINIT(*chain_id); | ||
1318 | |||
1319 | /* Set up the chain */ | ||
1320 | if (no_of_chans == 1) | ||
1321 | create_dma_lch_chain(channels[0], channels[0]); | ||
1322 | else { | ||
1323 | for (i = 0; i < (no_of_chans - 1); i++) | ||
1324 | create_dma_lch_chain(channels[i], channels[i + 1]); | ||
1325 | } | ||
1326 | |||
1327 | return 0; | ||
1328 | } | ||
1329 | EXPORT_SYMBOL(omap_request_dma_chain); | ||
1330 | |||
1331 | /** | ||
1332 | * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the | ||
1333 | * params after setting it. Dont do this while dma is running!! | ||
1334 | * | ||
1335 | * @param chain_id - Chained logical channel id. | ||
1336 | * @param params | ||
1337 | * | ||
1338 | * @return - Success : 0 | ||
1339 | * Failure : -EINVAL | ||
1340 | */ | ||
1341 | int omap_modify_dma_chain_params(int chain_id, | ||
1342 | struct omap_dma_channel_params params) | ||
1343 | { | ||
1344 | int *channels; | ||
1345 | u32 i; | ||
1346 | |||
1347 | /* Check for input params */ | ||
1348 | if (unlikely((chain_id < 0 | ||
1349 | || chain_id >= dma_lch_count))) { | ||
1350 | printk(KERN_ERR "Invalid chain id\n"); | ||
1351 | return -EINVAL; | ||
1352 | } | ||
1353 | |||
1354 | /* Check if the chain exists */ | ||
1355 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1356 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1357 | return -EINVAL; | ||
1358 | } | ||
1359 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1360 | |||
1361 | for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { | ||
1362 | /* | ||
1363 | * Allowing client drivers to set common parameters now, | ||
1364 | * so that later only relevant (src_start, dest_start | ||
1365 | * and element count) can be set | ||
1366 | */ | ||
1367 | omap_set_dma_params(channels[i], ¶ms); | ||
1368 | } | ||
1369 | |||
1370 | return 0; | ||
1371 | } | ||
1372 | EXPORT_SYMBOL(omap_modify_dma_chain_params); | ||
1373 | |||
1374 | /** | ||
1375 | * @brief omap_free_dma_chain - Free all the logical channels in a chain. | ||
1376 | * | ||
1377 | * @param chain_id | ||
1378 | * | ||
1379 | * @return - Success : 0 | ||
1380 | * Failure : -EINVAL | ||
1381 | */ | ||
1382 | int omap_free_dma_chain(int chain_id) | ||
1383 | { | ||
1384 | int *channels; | ||
1385 | u32 i; | ||
1386 | |||
1387 | /* Check for input params */ | ||
1388 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1389 | printk(KERN_ERR "Invalid chain id\n"); | ||
1390 | return -EINVAL; | ||
1391 | } | ||
1392 | |||
1393 | /* Check if the chain exists */ | ||
1394 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1395 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1400 | for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { | ||
1401 | dma_chan[channels[i]].next_linked_ch = -1; | ||
1402 | dma_chan[channels[i]].prev_linked_ch = -1; | ||
1403 | dma_chan[channels[i]].chain_id = -1; | ||
1404 | dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; | ||
1405 | omap_free_dma(channels[i]); | ||
1406 | } | ||
1407 | |||
1408 | kfree(channels); | ||
1409 | |||
1410 | dma_linked_lch[chain_id].linked_dmach_q = NULL; | ||
1411 | dma_linked_lch[chain_id].chain_mode = -1; | ||
1412 | dma_linked_lch[chain_id].chain_state = -1; | ||
1413 | |||
1414 | return (0); | ||
1415 | } | ||
1416 | EXPORT_SYMBOL(omap_free_dma_chain); | ||
1417 | |||
1418 | /** | ||
1419 | * @brief omap_dma_chain_status - Check if the chain is in | ||
1420 | * active / inactive state. | ||
1421 | * @param chain_id | ||
1422 | * | ||
1423 | * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE | ||
1424 | * Failure : -EINVAL | ||
1425 | */ | ||
1426 | int omap_dma_chain_status(int chain_id) | ||
1427 | { | ||
1428 | /* Check for input params */ | ||
1429 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1430 | printk(KERN_ERR "Invalid chain id\n"); | ||
1431 | return -EINVAL; | ||
1432 | } | ||
1433 | |||
1434 | /* Check if the chain exists */ | ||
1435 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1436 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1437 | return -EINVAL; | ||
1438 | } | ||
1439 | pr_debug("CHAINID=%d, qcnt=%d\n", chain_id, | ||
1440 | dma_linked_lch[chain_id].q_count); | ||
1441 | |||
1442 | if (OMAP_DMA_CHAIN_QEMPTY(chain_id)) | ||
1443 | return OMAP_DMA_CHAIN_INACTIVE; | ||
1444 | |||
1445 | return OMAP_DMA_CHAIN_ACTIVE; | ||
1446 | } | ||
1447 | EXPORT_SYMBOL(omap_dma_chain_status); | ||
1448 | |||
1449 | /** | ||
1450 | * @brief omap_dma_chain_a_transfer - Get a free channel from a chain, | ||
1451 | * set the params and start the transfer. | ||
1452 | * | ||
1453 | * @param chain_id | ||
1454 | * @param src_start - buffer start address | ||
1455 | * @param dest_start - Dest address | ||
1456 | * @param elem_count | ||
1457 | * @param frame_count | ||
1458 | * @param callbk_data - channel callback parameter data. | ||
1459 | * | ||
1460 | * @return - Success : 0 | ||
1461 | * Failure: -EINVAL/-EBUSY | ||
1462 | */ | ||
1463 | int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, | ||
1464 | int elem_count, int frame_count, void *callbk_data) | ||
1465 | { | ||
1466 | int *channels; | ||
1467 | u32 l, lch; | ||
1468 | int start_dma = 0; | ||
1469 | |||
1470 | /* | ||
1471 | * if buffer size is less than 1 then there is | ||
1472 | * no use of starting the chain | ||
1473 | */ | ||
1474 | if (elem_count < 1) { | ||
1475 | printk(KERN_ERR "Invalid buffer size\n"); | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | |||
1479 | /* Check for input params */ | ||
1480 | if (unlikely((chain_id < 0 | ||
1481 | || chain_id >= dma_lch_count))) { | ||
1482 | printk(KERN_ERR "Invalid chain id\n"); | ||
1483 | return -EINVAL; | ||
1484 | } | ||
1485 | |||
1486 | /* Check if the chain exists */ | ||
1487 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1488 | printk(KERN_ERR "Chain doesn't exist\n"); | ||
1489 | return -EINVAL; | ||
1490 | } | ||
1491 | |||
1492 | /* Check if all the channels in chain are in use */ | ||
1493 | if (OMAP_DMA_CHAIN_QFULL(chain_id)) | ||
1494 | return -EBUSY; | ||
1495 | |||
1496 | /* Frame count may be negative in case of indexed transfers */ | ||
1497 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1498 | |||
1499 | /* Get a free channel */ | ||
1500 | lch = channels[dma_linked_lch[chain_id].q_tail]; | ||
1501 | |||
1502 | /* Store the callback data */ | ||
1503 | dma_chan[lch].data = callbk_data; | ||
1504 | |||
1505 | /* Increment the q_tail */ | ||
1506 | OMAP_DMA_CHAIN_INCQTAIL(chain_id); | ||
1507 | |||
1508 | /* Set the params to the free channel */ | ||
1509 | if (src_start != 0) | ||
1510 | p->dma_write(src_start, CSSA, lch); | ||
1511 | if (dest_start != 0) | ||
1512 | p->dma_write(dest_start, CDSA, lch); | ||
1513 | |||
1514 | /* Write the buffer size */ | ||
1515 | p->dma_write(elem_count, CEN, lch); | ||
1516 | p->dma_write(frame_count, CFN, lch); | ||
1517 | |||
1518 | /* | ||
1519 | * If the chain is dynamically linked, | ||
1520 | * then we may have to start the chain if its not active | ||
1521 | */ | ||
1522 | if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) { | ||
1523 | |||
1524 | /* | ||
1525 | * In Dynamic chain, if the chain is not started, | ||
1526 | * queue the channel | ||
1527 | */ | ||
1528 | if (dma_linked_lch[chain_id].chain_state == | ||
1529 | DMA_CHAIN_NOTSTARTED) { | ||
1530 | /* Enable the link in previous channel */ | ||
1531 | if (dma_chan[dma_chan[lch].prev_linked_ch].state == | ||
1532 | DMA_CH_QUEUED) | ||
1533 | enable_lnk(dma_chan[lch].prev_linked_ch); | ||
1534 | dma_chan[lch].state = DMA_CH_QUEUED; | ||
1535 | } | ||
1536 | |||
1537 | /* | ||
1538 | * Chain is already started, make sure its active, | ||
1539 | * if not then start the chain | ||
1540 | */ | ||
1541 | else { | ||
1542 | start_dma = 1; | ||
1543 | |||
1544 | if (dma_chan[dma_chan[lch].prev_linked_ch].state == | ||
1545 | DMA_CH_STARTED) { | ||
1546 | enable_lnk(dma_chan[lch].prev_linked_ch); | ||
1547 | dma_chan[lch].state = DMA_CH_QUEUED; | ||
1548 | start_dma = 0; | ||
1549 | if (0 == ((1 << 7) & p->dma_read( | ||
1550 | CCR, dma_chan[lch].prev_linked_ch))) { | ||
1551 | disable_lnk(dma_chan[lch]. | ||
1552 | prev_linked_ch); | ||
1553 | pr_debug("\n prev ch is stopped\n"); | ||
1554 | start_dma = 1; | ||
1555 | } | ||
1556 | } | ||
1557 | |||
1558 | else if (dma_chan[dma_chan[lch].prev_linked_ch].state | ||
1559 | == DMA_CH_QUEUED) { | ||
1560 | enable_lnk(dma_chan[lch].prev_linked_ch); | ||
1561 | dma_chan[lch].state = DMA_CH_QUEUED; | ||
1562 | start_dma = 0; | ||
1563 | } | ||
1564 | omap_enable_channel_irq(lch); | ||
1565 | |||
1566 | l = p->dma_read(CCR, lch); | ||
1567 | |||
1568 | if ((0 == (l & (1 << 24)))) | ||
1569 | l &= ~(1 << 25); | ||
1570 | else | ||
1571 | l |= (1 << 25); | ||
1572 | if (start_dma == 1) { | ||
1573 | if (0 == (l & (1 << 7))) { | ||
1574 | l |= (1 << 7); | ||
1575 | dma_chan[lch].state = DMA_CH_STARTED; | ||
1576 | pr_debug("starting %d\n", lch); | ||
1577 | p->dma_write(l, CCR, lch); | ||
1578 | } else | ||
1579 | start_dma = 0; | ||
1580 | } else { | ||
1581 | if (0 == (l & (1 << 7))) | ||
1582 | p->dma_write(l, CCR, lch); | ||
1583 | } | ||
1584 | dma_chan[lch].flags |= OMAP_DMA_ACTIVE; | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | return 0; | ||
1589 | } | ||
1590 | EXPORT_SYMBOL(omap_dma_chain_a_transfer); | ||
1591 | |||
1592 | /** | ||
1593 | * @brief omap_start_dma_chain_transfers - Start the chain | ||
1594 | * | ||
1595 | * @param chain_id | ||
1596 | * | ||
1597 | * @return - Success : 0 | ||
1598 | * Failure : -EINVAL/-EBUSY | ||
1599 | */ | ||
1600 | int omap_start_dma_chain_transfers(int chain_id) | ||
1601 | { | ||
1602 | int *channels; | ||
1603 | u32 l, i; | ||
1604 | |||
1605 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1606 | printk(KERN_ERR "Invalid chain id\n"); | ||
1607 | return -EINVAL; | ||
1608 | } | ||
1609 | |||
1610 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1611 | |||
1612 | if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) { | ||
1613 | printk(KERN_ERR "Chain is already started\n"); | ||
1614 | return -EBUSY; | ||
1615 | } | ||
1616 | |||
1617 | if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) { | ||
1618 | for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; | ||
1619 | i++) { | ||
1620 | enable_lnk(channels[i]); | ||
1621 | omap_enable_channel_irq(channels[i]); | ||
1622 | } | ||
1623 | } else { | ||
1624 | omap_enable_channel_irq(channels[0]); | ||
1625 | } | ||
1626 | |||
1627 | l = p->dma_read(CCR, channels[0]); | ||
1628 | l |= (1 << 7); | ||
1629 | dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; | ||
1630 | dma_chan[channels[0]].state = DMA_CH_STARTED; | ||
1631 | |||
1632 | if ((0 == (l & (1 << 24)))) | ||
1633 | l &= ~(1 << 25); | ||
1634 | else | ||
1635 | l |= (1 << 25); | ||
1636 | p->dma_write(l, CCR, channels[0]); | ||
1637 | |||
1638 | dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; | ||
1639 | |||
1640 | return 0; | ||
1641 | } | ||
1642 | EXPORT_SYMBOL(omap_start_dma_chain_transfers); | ||
1643 | |||
1644 | /** | ||
1645 | * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain. | ||
1646 | * | ||
1647 | * @param chain_id | ||
1648 | * | ||
1649 | * @return - Success : 0 | ||
1650 | * Failure : EINVAL | ||
1651 | */ | ||
1652 | int omap_stop_dma_chain_transfers(int chain_id) | ||
1653 | { | ||
1654 | int *channels; | ||
1655 | u32 l, i; | ||
1656 | u32 sys_cf = 0; | ||
1657 | |||
1658 | /* Check for input params */ | ||
1659 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1660 | printk(KERN_ERR "Invalid chain id\n"); | ||
1661 | return -EINVAL; | ||
1662 | } | ||
1663 | |||
1664 | /* Check if the chain exists */ | ||
1665 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1666 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1667 | return -EINVAL; | ||
1668 | } | ||
1669 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1670 | |||
1671 | if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { | ||
1672 | sys_cf = p->dma_read(OCP_SYSCONFIG, 0); | ||
1673 | l = sys_cf; | ||
1674 | /* Middle mode reg set no Standby */ | ||
1675 | l &= ~((1 << 12)|(1 << 13)); | ||
1676 | p->dma_write(l, OCP_SYSCONFIG, 0); | ||
1677 | } | ||
1678 | |||
1679 | for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { | ||
1680 | |||
1681 | /* Stop the Channel transmission */ | ||
1682 | l = p->dma_read(CCR, channels[i]); | ||
1683 | l &= ~(1 << 7); | ||
1684 | p->dma_write(l, CCR, channels[i]); | ||
1685 | |||
1686 | /* Disable the link in all the channels */ | ||
1687 | disable_lnk(channels[i]); | ||
1688 | dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; | ||
1689 | |||
1690 | } | ||
1691 | dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED; | ||
1692 | |||
1693 | /* Reset the Queue pointers */ | ||
1694 | OMAP_DMA_CHAIN_QINIT(chain_id); | ||
1695 | |||
1696 | if (IS_DMA_ERRATA(DMA_ERRATA_i88)) | ||
1697 | p->dma_write(sys_cf, OCP_SYSCONFIG, 0); | ||
1698 | |||
1699 | return 0; | ||
1700 | } | ||
1701 | EXPORT_SYMBOL(omap_stop_dma_chain_transfers); | ||
1702 | |||
1703 | /* Get the index of the ongoing DMA in chain */ | ||
1704 | /** | ||
1705 | * @brief omap_get_dma_chain_index - Get the element and frame index | ||
1706 | * of the ongoing DMA in chain | ||
1707 | * | ||
1708 | * @param chain_id | ||
1709 | * @param ei - Element index | ||
1710 | * @param fi - Frame index | ||
1711 | * | ||
1712 | * @return - Success : 0 | ||
1713 | * Failure : -EINVAL | ||
1714 | */ | ||
1715 | int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) | ||
1716 | { | ||
1717 | int lch; | ||
1718 | int *channels; | ||
1719 | |||
1720 | /* Check for input params */ | ||
1721 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1722 | printk(KERN_ERR "Invalid chain id\n"); | ||
1723 | return -EINVAL; | ||
1724 | } | ||
1725 | |||
1726 | /* Check if the chain exists */ | ||
1727 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1728 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1729 | return -EINVAL; | ||
1730 | } | ||
1731 | if ((!ei) || (!fi)) | ||
1732 | return -EINVAL; | ||
1733 | |||
1734 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1735 | |||
1736 | /* Get the current channel */ | ||
1737 | lch = channels[dma_linked_lch[chain_id].q_head]; | ||
1738 | |||
1739 | *ei = p->dma_read(CCEN, lch); | ||
1740 | *fi = p->dma_read(CCFN, lch); | ||
1741 | |||
1742 | return 0; | ||
1743 | } | ||
1744 | EXPORT_SYMBOL(omap_get_dma_chain_index); | ||
1745 | |||
1746 | /** | ||
1747 | * @brief omap_get_dma_chain_dst_pos - Get the destination position of the | ||
1748 | * ongoing DMA in chain | ||
1749 | * | ||
1750 | * @param chain_id | ||
1751 | * | ||
1752 | * @return - Success : Destination position | ||
1753 | * Failure : -EINVAL | ||
1754 | */ | ||
1755 | int omap_get_dma_chain_dst_pos(int chain_id) | ||
1756 | { | ||
1757 | int lch; | ||
1758 | int *channels; | ||
1759 | |||
1760 | /* Check for input params */ | ||
1761 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1762 | printk(KERN_ERR "Invalid chain id\n"); | ||
1763 | return -EINVAL; | ||
1764 | } | ||
1765 | |||
1766 | /* Check if the chain exists */ | ||
1767 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1768 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1769 | return -EINVAL; | ||
1770 | } | ||
1771 | |||
1772 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1773 | |||
1774 | /* Get the current channel */ | ||
1775 | lch = channels[dma_linked_lch[chain_id].q_head]; | ||
1776 | |||
1777 | return p->dma_read(CDAC, lch); | ||
1778 | } | ||
1779 | EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); | ||
1780 | |||
1781 | /** | ||
1782 | * @brief omap_get_dma_chain_src_pos - Get the source position | ||
1783 | * of the ongoing DMA in chain | ||
1784 | * @param chain_id | ||
1785 | * | ||
1786 | * @return - Success : Destination position | ||
1787 | * Failure : -EINVAL | ||
1788 | */ | ||
1789 | int omap_get_dma_chain_src_pos(int chain_id) | ||
1790 | { | ||
1791 | int lch; | ||
1792 | int *channels; | ||
1793 | |||
1794 | /* Check for input params */ | ||
1795 | if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { | ||
1796 | printk(KERN_ERR "Invalid chain id\n"); | ||
1797 | return -EINVAL; | ||
1798 | } | ||
1799 | |||
1800 | /* Check if the chain exists */ | ||
1801 | if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { | ||
1802 | printk(KERN_ERR "Chain doesn't exists\n"); | ||
1803 | return -EINVAL; | ||
1804 | } | ||
1805 | |||
1806 | channels = dma_linked_lch[chain_id].linked_dmach_q; | ||
1807 | |||
1808 | /* Get the current channel */ | ||
1809 | lch = channels[dma_linked_lch[chain_id].q_head]; | ||
1810 | |||
1811 | return p->dma_read(CSAC, lch); | ||
1812 | } | ||
1813 | EXPORT_SYMBOL(omap_get_dma_chain_src_pos); | ||
1814 | #endif /* ifndef CONFIG_ARCH_OMAP1 */ | ||
1815 | |||
1816 | /*----------------------------------------------------------------------------*/ | 1091 | /*----------------------------------------------------------------------------*/ |
1817 | 1092 | ||
1818 | #ifdef CONFIG_ARCH_OMAP1 | 1093 | #ifdef CONFIG_ARCH_OMAP1 |
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 6f06f8bc612c..e5a70132a240 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h | |||
@@ -306,15 +306,12 @@ extern void omap_set_dma_transfer_params(int lch, int data_type, | |||
306 | int elem_count, int frame_count, | 306 | int elem_count, int frame_count, |
307 | int sync_mode, | 307 | int sync_mode, |
308 | int dma_trigger, int src_or_dst_synch); | 308 | int dma_trigger, int src_or_dst_synch); |
309 | extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, | ||
310 | u32 color); | ||
311 | extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode); | 309 | extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode); |
312 | extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode); | 310 | extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode); |
313 | 311 | ||
314 | extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, | 312 | extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, |
315 | unsigned long src_start, | 313 | unsigned long src_start, |
316 | int src_ei, int src_fi); | 314 | int src_ei, int src_fi); |
317 | extern void omap_set_dma_src_index(int lch, int eidx, int fidx); | ||
318 | extern void omap_set_dma_src_data_pack(int lch, int enable); | 315 | extern void omap_set_dma_src_data_pack(int lch, int enable); |
319 | extern void omap_set_dma_src_burst_mode(int lch, | 316 | extern void omap_set_dma_src_burst_mode(int lch, |
320 | enum omap_dma_burst_mode burst_mode); | 317 | enum omap_dma_burst_mode burst_mode); |
@@ -322,7 +319,6 @@ extern void omap_set_dma_src_burst_mode(int lch, | |||
322 | extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, | 319 | extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, |
323 | unsigned long dest_start, | 320 | unsigned long dest_start, |
324 | int dst_ei, int dst_fi); | 321 | int dst_ei, int dst_fi); |
325 | extern void omap_set_dma_dest_index(int lch, int eidx, int fidx); | ||
326 | extern void omap_set_dma_dest_data_pack(int lch, int enable); | 322 | extern void omap_set_dma_dest_data_pack(int lch, int enable); |
327 | extern void omap_set_dma_dest_burst_mode(int lch, | 323 | extern void omap_set_dma_dest_burst_mode(int lch, |
328 | enum omap_dma_burst_mode burst_mode); | 324 | enum omap_dma_burst_mode burst_mode); |
@@ -331,52 +327,19 @@ extern void omap_set_dma_params(int lch, | |||
331 | struct omap_dma_channel_params *params); | 327 | struct omap_dma_channel_params *params); |
332 | 328 | ||
333 | extern void omap_dma_link_lch(int lch_head, int lch_queue); | 329 | extern void omap_dma_link_lch(int lch_head, int lch_queue); |
334 | extern void omap_dma_unlink_lch(int lch_head, int lch_queue); | ||
335 | 330 | ||
336 | extern int omap_set_dma_callback(int lch, | 331 | extern int omap_set_dma_callback(int lch, |
337 | void (*callback)(int lch, u16 ch_status, void *data), | 332 | void (*callback)(int lch, u16 ch_status, void *data), |
338 | void *data); | 333 | void *data); |
339 | extern dma_addr_t omap_get_dma_src_pos(int lch); | 334 | extern dma_addr_t omap_get_dma_src_pos(int lch); |
340 | extern dma_addr_t omap_get_dma_dst_pos(int lch); | 335 | extern dma_addr_t omap_get_dma_dst_pos(int lch); |
341 | extern void omap_clear_dma(int lch); | ||
342 | extern int omap_get_dma_active_status(int lch); | 336 | extern int omap_get_dma_active_status(int lch); |
343 | extern int omap_dma_running(void); | 337 | extern int omap_dma_running(void); |
344 | extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, | 338 | extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, |
345 | int tparams); | 339 | int tparams); |
346 | extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio, | ||
347 | unsigned char write_prio); | ||
348 | extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype); | ||
349 | extern void omap_set_dma_src_endian_type(int lch, enum end_type etype); | ||
350 | extern int omap_get_dma_index(int lch, int *ei, int *fi); | ||
351 | |||
352 | void omap_dma_global_context_save(void); | 340 | void omap_dma_global_context_save(void); |
353 | void omap_dma_global_context_restore(void); | 341 | void omap_dma_global_context_restore(void); |
354 | 342 | ||
355 | extern void omap_dma_disable_irq(int lch); | ||
356 | |||
357 | /* Chaining APIs */ | ||
358 | #ifndef CONFIG_ARCH_OMAP1 | ||
359 | extern int omap_request_dma_chain(int dev_id, const char *dev_name, | ||
360 | void (*callback) (int lch, u16 ch_status, | ||
361 | void *data), | ||
362 | int *chain_id, int no_of_chans, | ||
363 | int chain_mode, | ||
364 | struct omap_dma_channel_params params); | ||
365 | extern int omap_free_dma_chain(int chain_id); | ||
366 | extern int omap_dma_chain_a_transfer(int chain_id, int src_start, | ||
367 | int dest_start, int elem_count, | ||
368 | int frame_count, void *callbk_data); | ||
369 | extern int omap_start_dma_chain_transfers(int chain_id); | ||
370 | extern int omap_stop_dma_chain_transfers(int chain_id); | ||
371 | extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi); | ||
372 | extern int omap_get_dma_chain_dst_pos(int chain_id); | ||
373 | extern int omap_get_dma_chain_src_pos(int chain_id); | ||
374 | |||
375 | extern int omap_modify_dma_chain_params(int chain_id, | ||
376 | struct omap_dma_channel_params params); | ||
377 | extern int omap_dma_chain_status(int chain_id); | ||
378 | #endif | ||
379 | |||
380 | #if defined(CONFIG_ARCH_OMAP1) && IS_ENABLED(CONFIG_FB_OMAP) | 343 | #if defined(CONFIG_ARCH_OMAP1) && IS_ENABLED(CONFIG_FB_OMAP) |
381 | #include <mach/lcd_dma.h> | 344 | #include <mach/lcd_dma.h> |
382 | #else | 345 | #else |