aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/dma.c737
-rw-r--r--include/linux/omap-dma.h37
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
65static struct omap_system_dma_plat_info *p; 65static struct omap_system_dma_plat_info *p;
66static struct omap_dma_dev_attr *d; 66static struct omap_dma_dev_attr *d;
67 67static void omap_clear_dma(int lch);
68static int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
69 unsigned char write_prio);
68static int enable_1510_mode; 70static int enable_1510_mode;
69static u32 errata; 71static u32 errata;
70 72
@@ -284,66 +286,6 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
284} 286}
285EXPORT_SYMBOL(omap_set_dma_transfer_params); 287EXPORT_SYMBOL(omap_set_dma_transfer_params);
286 288
287void 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}
345EXPORT_SYMBOL(omap_set_dma_color_mode);
346
347void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) 289void 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}
418EXPORT_SYMBOL(omap_set_dma_params); 360EXPORT_SYMBOL(omap_set_dma_params);
419 361
420void 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}
428EXPORT_SYMBOL(omap_set_dma_src_index);
429
430void omap_set_dma_src_data_pack(int lch, int enable) 362void 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}
511EXPORT_SYMBOL(omap_set_dma_dest_params); 443EXPORT_SYMBOL(omap_set_dma_dest_params);
512 444
513void 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}
521EXPORT_SYMBOL(omap_set_dma_dest_index);
522
523void omap_set_dma_dest_data_pack(int lch, int enable) 445void 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 */
846int 768static int
847omap_dma_set_prio_lch(int lch, unsigned char read_prio, 769omap_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}
867EXPORT_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 */
873void omap_clear_dma(int lch) 795static 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}
881EXPORT_SYMBOL(omap_clear_dma);
882 803
883void omap_start_dma(int lch) 804void omap_start_dma(int lch)
884{ 805{
@@ -1167,652 +1088,6 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
1167} 1088}
1168EXPORT_SYMBOL(omap_dma_link_lch); 1089EXPORT_SYMBOL(omap_dma_link_lch);
1169 1090
1170/*
1171 * Once the DMA queue is stopped, we can destroy it.
1172 */
1173void 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}
1200EXPORT_SYMBOL(omap_dma_unlink_lch);
1201
1202#ifndef CONFIG_ARCH_OMAP1
1203/* Create chain of DMA channesls */
1204static 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 */
1252int 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], &params);
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}
1329EXPORT_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 */
1341int 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], &params);
1368 }
1369
1370 return 0;
1371}
1372EXPORT_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 */
1382int 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}
1416EXPORT_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 */
1426int 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}
1447EXPORT_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 */
1463int 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}
1590EXPORT_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 */
1600int 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}
1642EXPORT_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 */
1652int 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}
1701EXPORT_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 */
1715int 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}
1744EXPORT_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 */
1755int 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}
1779EXPORT_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 */
1789int 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}
1813EXPORT_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);
309extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
310 u32 color);
311extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode); 309extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
312extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode); 310extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode);
313 311
314extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, 312extern 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);
317extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
318extern void omap_set_dma_src_data_pack(int lch, int enable); 315extern void omap_set_dma_src_data_pack(int lch, int enable);
319extern void omap_set_dma_src_burst_mode(int lch, 316extern 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,
322extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, 319extern 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);
325extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
326extern void omap_set_dma_dest_data_pack(int lch, int enable); 322extern void omap_set_dma_dest_data_pack(int lch, int enable);
327extern void omap_set_dma_dest_burst_mode(int lch, 323extern 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
333extern void omap_dma_link_lch(int lch_head, int lch_queue); 329extern void omap_dma_link_lch(int lch_head, int lch_queue);
334extern void omap_dma_unlink_lch(int lch_head, int lch_queue);
335 330
336extern int omap_set_dma_callback(int lch, 331extern 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);
339extern dma_addr_t omap_get_dma_src_pos(int lch); 334extern dma_addr_t omap_get_dma_src_pos(int lch);
340extern dma_addr_t omap_get_dma_dst_pos(int lch); 335extern dma_addr_t omap_get_dma_dst_pos(int lch);
341extern void omap_clear_dma(int lch);
342extern int omap_get_dma_active_status(int lch); 336extern int omap_get_dma_active_status(int lch);
343extern int omap_dma_running(void); 337extern int omap_dma_running(void);
344extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, 338extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
345 int tparams); 339 int tparams);
346extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
347 unsigned char write_prio);
348extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype);
349extern void omap_set_dma_src_endian_type(int lch, enum end_type etype);
350extern int omap_get_dma_index(int lch, int *ei, int *fi);
351
352void omap_dma_global_context_save(void); 340void omap_dma_global_context_save(void);
353void omap_dma_global_context_restore(void); 341void omap_dma_global_context_restore(void);
354 342
355extern void omap_dma_disable_irq(int lch);
356
357/* Chaining APIs */
358#ifndef CONFIG_ARCH_OMAP1
359extern 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);
365extern int omap_free_dma_chain(int chain_id);
366extern 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);
369extern int omap_start_dma_chain_transfers(int chain_id);
370extern int omap_stop_dma_chain_transfers(int chain_id);
371extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
372extern int omap_get_dma_chain_dst_pos(int chain_id);
373extern int omap_get_dma_chain_src_pos(int chain_id);
374
375extern int omap_modify_dma_chain_params(int chain_id,
376 struct omap_dma_channel_params params);
377extern 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