Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.16 145 lines 3.4 kB view raw
1/* 2 * Copyright (C) 2013 Red Hat 3 * Author: Rob Clark <robdclark@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19#include "msm_drv.h" 20#include "mdp_kms.h" 21 22 23struct mdp_irq_wait { 24 struct mdp_irq irq; 25 int count; 26}; 27 28static DECLARE_WAIT_QUEUE_HEAD(wait_event); 29 30static DEFINE_SPINLOCK(list_lock); 31 32static void update_irq(struct mdp_kms *mdp_kms) 33{ 34 struct mdp_irq *irq; 35 uint32_t irqmask = mdp_kms->vblank_mask; 36 37 BUG_ON(!spin_is_locked(&list_lock)); 38 39 list_for_each_entry(irq, &mdp_kms->irq_list, node) 40 irqmask |= irq->irqmask; 41 42 mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); 43} 44 45static void update_irq_unlocked(struct mdp_kms *mdp_kms) 46{ 47 unsigned long flags; 48 spin_lock_irqsave(&list_lock, flags); 49 update_irq(mdp_kms); 50 spin_unlock_irqrestore(&list_lock, flags); 51} 52 53void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status) 54{ 55 struct mdp_irq *handler, *n; 56 unsigned long flags; 57 58 spin_lock_irqsave(&list_lock, flags); 59 mdp_kms->in_irq = true; 60 list_for_each_entry_safe(handler, n, &mdp_kms->irq_list, node) { 61 if (handler->irqmask & status) { 62 spin_unlock_irqrestore(&list_lock, flags); 63 handler->irq(handler, handler->irqmask & status); 64 spin_lock_irqsave(&list_lock, flags); 65 } 66 } 67 mdp_kms->in_irq = false; 68 update_irq(mdp_kms); 69 spin_unlock_irqrestore(&list_lock, flags); 70 71} 72 73void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable) 74{ 75 unsigned long flags; 76 77 spin_lock_irqsave(&list_lock, flags); 78 if (enable) 79 mdp_kms->vblank_mask |= mask; 80 else 81 mdp_kms->vblank_mask &= ~mask; 82 update_irq(mdp_kms); 83 spin_unlock_irqrestore(&list_lock, flags); 84} 85 86static void wait_irq(struct mdp_irq *irq, uint32_t irqstatus) 87{ 88 struct mdp_irq_wait *wait = 89 container_of(irq, struct mdp_irq_wait, irq); 90 wait->count--; 91 wake_up_all(&wait_event); 92} 93 94void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask) 95{ 96 struct mdp_irq_wait wait = { 97 .irq = { 98 .irq = wait_irq, 99 .irqmask = irqmask, 100 }, 101 .count = 1, 102 }; 103 mdp_irq_register(mdp_kms, &wait.irq); 104 wait_event_timeout(wait_event, (wait.count <= 0), 105 msecs_to_jiffies(100)); 106 mdp_irq_unregister(mdp_kms, &wait.irq); 107} 108 109void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq) 110{ 111 unsigned long flags; 112 bool needs_update = false; 113 114 spin_lock_irqsave(&list_lock, flags); 115 116 if (!irq->registered) { 117 irq->registered = true; 118 list_add(&irq->node, &mdp_kms->irq_list); 119 needs_update = !mdp_kms->in_irq; 120 } 121 122 spin_unlock_irqrestore(&list_lock, flags); 123 124 if (needs_update) 125 update_irq_unlocked(mdp_kms); 126} 127 128void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) 129{ 130 unsigned long flags; 131 bool needs_update = false; 132 133 spin_lock_irqsave(&list_lock, flags); 134 135 if (irq->registered) { 136 irq->registered = false; 137 list_del(&irq->node); 138 needs_update = !mdp_kms->in_irq; 139 } 140 141 spin_unlock_irqrestore(&list_lock, flags); 142 143 if (needs_update) 144 update_irq_unlocked(mdp_kms); 145}