Lines Matching defs:ivc
6 #include <soc/tegra/ivc.h>
77 static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys)
79 if (!ivc->peer)
82 dma_sync_single_for_cpu(ivc->peer, phys, TEGRA_IVC_ALIGN,
86 static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys)
88 if (!ivc->peer)
91 dma_sync_single_for_device(ivc->peer, phys, TEGRA_IVC_ALIGN,
95 static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, struct iosys_map *map)
115 if (tx - rx > ivc->num_frames)
121 static inline bool tegra_ivc_full(struct tegra_ivc *ivc, struct iosys_map *map)
130 return tx - rx >= ivc->num_frames;
133 static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, struct iosys_map *map)
147 static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
149 unsigned int count = tegra_ivc_header_read_field(&ivc->tx.map, tx.count);
151 tegra_ivc_header_write_field(&ivc->tx.map, tx.count, count + 1);
153 if (ivc->tx.position == ivc->num_frames - 1)
154 ivc->tx.position = 0;
156 ivc->tx.position++;
159 static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
161 unsigned int count = tegra_ivc_header_read_field(&ivc->rx.map, rx.count);
163 tegra_ivc_header_write_field(&ivc->rx.map, rx.count, count + 1);
165 if (ivc->rx.position == ivc->num_frames - 1)
166 ivc->rx.position = 0;
168 ivc->rx.position++;
171 static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
184 state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
195 if (!tegra_ivc_empty(ivc, &ivc->rx.map))
198 tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
200 if (tegra_ivc_empty(ivc, &ivc->rx.map))
206 static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
211 state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
215 if (!tegra_ivc_full(ivc, &ivc->tx.map))
218 tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
220 if (tegra_ivc_full(ivc, &ivc->tx.map))
226 static int tegra_ivc_frame_virt(struct tegra_ivc *ivc, const struct iosys_map *header,
229 size_t offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
231 if (WARN_ON(frame >= ivc->num_frames))
239 static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc,
245 offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
250 static inline void tegra_ivc_invalidate_frame(struct tegra_ivc *ivc,
256 if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
259 phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
261 dma_sync_single_for_cpu(ivc->peer, phys, size, DMA_FROM_DEVICE);
264 static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
270 if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
273 phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
275 dma_sync_single_for_device(ivc->peer, phys, size, DMA_TO_DEVICE);
279 int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
283 if (WARN_ON(ivc == NULL))
286 err = tegra_ivc_check_read(ivc);
291 * Order observation of ivc->rx.position potentially indicating new
296 tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0,
297 ivc->frame_size);
299 return tegra_ivc_frame_virt(ivc, &ivc->rx.map, ivc->rx.position, map);
303 int tegra_ivc_read_advance(struct tegra_ivc *ivc)
314 err = tegra_ivc_check_read(ivc);
318 tegra_ivc_advance_rx(ivc);
320 tegra_ivc_flush(ivc, ivc->rx.phys + rx);
323 * Ensure our write to ivc->rx.position occurs before our read from
324 * ivc->tx.position.
333 tegra_ivc_invalidate(ivc, ivc->rx.phys + tx);
335 if (tegra_ivc_available(ivc, &ivc->rx.map) == ivc->num_frames - 1)
336 ivc->notify(ivc, ivc->notify_data);
343 int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
347 err = tegra_ivc_check_write(ivc);
351 return tegra_ivc_frame_virt(ivc, &ivc->tx.map, ivc->tx.position, map);
356 int tegra_ivc_write_advance(struct tegra_ivc *ivc)
362 err = tegra_ivc_check_write(ivc);
366 tegra_ivc_flush_frame(ivc, ivc->tx.phys, ivc->tx.position, 0,
367 ivc->frame_size);
371 * ivc->tx.position.
375 tegra_ivc_advance_tx(ivc);
376 tegra_ivc_flush(ivc, ivc->tx.phys + tx);
379 * Ensure our write to ivc->tx.position occurs before our read from
380 * ivc->rx.position.
389 tegra_ivc_invalidate(ivc, ivc->tx.phys + rx);
391 if (tegra_ivc_available(ivc, &ivc->tx.map) == 1)
392 ivc->notify(ivc, ivc->notify_data);
398 void tegra_ivc_reset(struct tegra_ivc *ivc)
402 tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_SYNC);
403 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
404 ivc->notify(ivc, ivc->notify_data);
428 int tegra_ivc_notified(struct tegra_ivc *ivc)
434 tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
435 rx_state = tegra_ivc_header_read_field(&ivc->rx.map, tx.state);
436 tx_state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
452 tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
453 tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
455 ivc->tx.position = 0;
456 ivc->rx.position = 0;
468 tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ACK);
469 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
474 ivc->notify(ivc, ivc->notify_data);
491 tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
492 tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
494 ivc->tx.position = 0;
495 ivc->rx.position = 0;
508 tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
509 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
514 ivc->notify(ivc, ivc->notify_data);
532 tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
533 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
538 ivc->notify(ivc, ivc->notify_data);
646 int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, const struct iosys_map *rx,
649 void (*notify)(struct tegra_ivc *ivc, void *data),
655 if (WARN_ON(!ivc || !notify))
673 ivc->rx.phys = dma_map_single(peer, iosys_map_get_vaddr(rx), queue_size,
675 if (dma_mapping_error(peer, ivc->rx.phys))
678 ivc->tx.phys = dma_map_single(peer, iosys_map_get_vaddr(tx), queue_size,
680 if (dma_mapping_error(peer, ivc->tx.phys)) {
681 dma_unmap_single(peer, ivc->rx.phys, queue_size,
686 ivc->rx.phys = rx_phys;
687 ivc->tx.phys = tx_phys;
690 iosys_map_copy(&ivc->rx.map, rx);
691 iosys_map_copy(&ivc->tx.map, tx);
692 ivc->peer = peer;
693 ivc->notify = notify;
694 ivc->notify_data = data;
695 ivc->frame_size = frame_size;
696 ivc->num_frames = num_frames;
702 ivc->tx.position = 0;
703 ivc->rx.position = 0;
709 void tegra_ivc_cleanup(struct tegra_ivc *ivc)
711 if (ivc->peer) {
712 size_t size = tegra_ivc_total_queue_size(ivc->num_frames *
713 ivc->frame_size);
715 dma_unmap_single(ivc->peer, ivc->rx.phys, size,
717 dma_unmap_single(ivc->peer, ivc->tx.phys, size,