aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 17:06:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 17:06:53 -0400
commit212fe84a6f215c39795a76517c1c02114d428681 (patch)
tree4692680312616d6a5c562f2d494c12d21b697237 /arch/arm/plat-omap
parent4a4743e840d06a5772be7c21110807165c5b3c9f (diff)
parent05301fe7de11dac87638f1728f8ee8b31bc1cf31 (diff)
Merge tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Arnd Bergmann: "This time around, the cleanup branch contains mostly code removal. A number of board files for at91, imx and msm have become obsolete because of the DT conversion and are now ready to be removed. The OMAP platform has traditionally had its own DMA engine abstraction and as this is being phased out, a lot of the original code is now unused and can be removed as well. S3C24xx can be simplified now that the restart code is a proper device driver. Finally, a number of cleanups in shmobile are done to prepare for the addition of new code in other branches" * tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (43 commits) ARM: at91: Remove the support for the RSI EWS board arm: mach-omap2: Convert pr_warning to pr_warn ARM: OMAP: Remove unused pieces of legacy DMA API ARM: at91: remove board file for Acme Systems Fox G20 ARM: orion5x: Convert pr_warning to pr_warn ARM: S3C24XX: remove separate restart code ARM: EXYNOS: Do not calculate boot address twice ARM: sunxi: Remove sun4i reboot code from mach directory ARM: imx: Remove mach-mxt_td60 board file ARM: shmobile: armadillo800eva legacy: Use rmobile_add_devices_to_domains() ARM: shmobile: r8a7740: Clean up pm domain table ARM: shmobile: r8a7740: Use rmobile_add_devices_to_domains() ARM: shmobile: sh7372: Make domain_devices[] static __initdata ARM: shmobile: mackerel: Make domain_devices[] static __initdata clocksource: tcb_clksrc: sanitize IRQ request ARM: at91/tclib: mask interruptions at shutdown and probe ARM: at91/tclib: move initialization from alloc to probe ARM: at91/tclib: prefer using of devm_* functions ARM: clps711x: Switch CLPS711X subarch to use clk and clocksource driver ARM: shmobile: r8a7791 is now called "R-Car M2-W" ...
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/dma.c737
1 files changed, 6 insertions, 731 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