cregit-Linux how code gets into the kernel

Release 4.11 drivers/video/fbdev/omap2/omapfb/dss/apply.c

/*
 * Copyright (C) 2011 Texas Instruments
 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#define DSS_SUBSYS_NAME "APPLY"

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>

#include <video/omapfb_dss.h>

#include "dss.h"
#include "dss_features.h"
#include "dispc-compat.h"

/*
 * We have 4 levels of cache for the dispc settings. First two are in SW and
 * the latter two in HW.
 *
 *       set_info()
 *          v
 * +--------------------+
 * |     user_info      |
 * +--------------------+
 *          v
 *        apply()
 *          v
 * +--------------------+
 * |       info         |
 * +--------------------+
 *          v
 *      write_regs()
 *          v
 * +--------------------+
 * |  shadow registers  |
 * +--------------------+
 *          v
 * VFP or lcd/digit_enable
 *          v
 * +--------------------+
 * |      registers     |
 * +--------------------+
 */


struct ovl_priv_data {

	
bool user_info_dirty;
	
struct omap_overlay_info user_info;

	
bool info_dirty;
	
struct omap_overlay_info info;

	
bool shadow_info_dirty;

	
bool extra_info_dirty;
	
bool shadow_extra_info_dirty;

	
bool enabled;
	

u32 fifo_low, fifo_high;

	/*
         * True if overlay is to be enabled. Used to check and calculate configs
         * for the overlay before it is enabled in the HW.
         */
	
bool enabling;
};


struct mgr_priv_data {

	
bool user_info_dirty;
	
struct omap_overlay_manager_info user_info;

	
bool info_dirty;
	
struct omap_overlay_manager_info info;

	
bool shadow_info_dirty;

	/* If true, GO bit is up and shadow registers cannot be written.
         * Never true for manual update displays */
	
bool busy;

	/* If true, dispc output is enabled */
	
bool updating;

	/* If true, a display is enabled using this manager */
	
bool enabled;

	
bool extra_info_dirty;
	
bool shadow_extra_info_dirty;

	
struct omap_video_timings timings;
	
struct dss_lcd_mgr_config lcd_config;

	
void (*framedone_handler)(void *);
	
void *framedone_handler_data;
};

static struct {
	
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
	
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];

	
bool irq_enabled;
} 
dss_data;

/* protects dss_data */

static spinlock_t data_lock;
/* lock for blocking functions */
static DEFINE_MUTEX(apply_lock);
static DECLARE_COMPLETION(extra_updated_completion);

static void dss_register_vsync_isr(void);


static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl) { return &dss_data.ovl_priv_data_array[ovl->id]; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen24100.00%1100.00%
Total24100.00%1100.00%


static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr) { return &dss_data.mgr_priv_data_array[mgr->id]; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen24100.00%1100.00%
Total24100.00%1100.00%


static void apply_init_priv(void) { const int num_ovls = dss_feat_get_num_ovls(); struct mgr_priv_data *mp; int i; spin_lock_init(&data_lock); for (i = 0; i < num_ovls; ++i) { struct ovl_priv_data *op; op = &dss_data.ovl_priv_data_array[i]; op->info.color_mode = OMAP_DSS_COLOR_RGB16; op->info.rotation_type = OMAP_DSS_ROT_DMA; op->info.global_alpha = 255; switch (i) { case 0: op->info.zorder = 0; break; case 1: op->info.zorder = dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; break; case 2: op->info.zorder = dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; break; case 3: op->info.zorder = dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; break; } op->user_info = op->info; } /* * Initialize some of the lcd_config fields for TV manager, this lets * us prevent checking if the manager is LCD or TV at some places */ mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT]; mp->lcd_config.video_port_width = 24; mp->lcd_config.clock_info.lck_div = 1; mp->lcd_config.clock_info.pck_div = 1; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen205100.00%1100.00%
Total205100.00%1100.00%

/* * A LCD manager's stallmode decides whether it is in manual or auto update. TV * manager is always auto update, stallmode field for TV manager is false by * default */
static bool ovl_manual_update(struct omap_overlay *ovl) { struct mgr_priv_data *mp = get_mgr_priv(ovl->manager); return mp->lcd_config.stallmode; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen30100.00%1100.00%
Total30100.00%1100.00%


static bool mgr_manual_update(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); return mp->lcd_config.stallmode; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen28100.00%1100.00%
Total28100.00%1100.00%


static int dss_check_settings_low(struct omap_overlay_manager *mgr, bool applying) { struct omap_overlay_info *oi; struct omap_overlay_manager_info *mi; struct omap_overlay *ovl; struct omap_overlay_info *ois[MAX_DSS_OVERLAYS]; struct ovl_priv_data *op; struct mgr_priv_data *mp; mp = get_mgr_priv(mgr); if (!mp->enabled) return 0; if (applying && mp->user_info_dirty) mi = &mp->user_info; else mi = &mp->info; /* collect the infos to be tested into the array */ list_for_each_entry(ovl, &mgr->overlays, list) { op = get_ovl_priv(ovl); if (!op->enabled && !op->enabling) oi = NULL; else if (applying && op->user_info_dirty) oi = &op->user_info; else oi = &op->info; ois[ovl->id] = oi; } return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen174100.00%1100.00%
Total174100.00%1100.00%

/* * check manager and overlay settings using overlay_info from data->info */
static int dss_check_settings(struct omap_overlay_manager *mgr) { return dss_check_settings_low(mgr, false); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen19100.00%1100.00%
Total19100.00%1100.00%

/* * check manager and overlay settings using overlay_info from ovl->info if * dirty and from data->info otherwise */
static int dss_check_settings_apply(struct omap_overlay_manager *mgr) { return dss_check_settings_low(mgr, true); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen19100.00%1100.00%
Total19100.00%1100.00%


static bool need_isr(void) { const int num_mgrs = dss_feat_get_num_mgrs(); int i; for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; struct omap_overlay *ovl; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mp->enabled) continue; if (mgr_manual_update(mgr)) { /* to catch FRAMEDONE */ if (mp->updating) return true; } else { /* to catch GO bit going down */ if (mp->busy) return true; /* to write new values to registers */ if (mp->info_dirty) return true; /* to set GO bit */ if (mp->shadow_info_dirty) return true; /* * NOTE: we don't check extra_info flags for disabled * managers, once the manager is enabled, the extra_info * related manager changes will be taken in by HW. */ /* to write new values to registers */ if (mp->extra_info_dirty) return true; /* to set GO bit */ if (mp->shadow_extra_info_dirty) return true; list_for_each_entry(ovl, &mgr->overlays, list) { struct ovl_priv_data *op; op = get_ovl_priv(ovl); /* * NOTE: we check extra_info flags even for * disabled overlays, as extra_infos need to be * always written. */ /* to write new values to registers */ if (op->extra_info_dirty) return true; /* to set GO bit */ if (op->shadow_extra_info_dirty) return true; if (!op->enabled) continue; /* to write new values to registers */ if (op->info_dirty) return true; /* to set GO bit */ if (op->shadow_info_dirty) return true; } } } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen217100.00%1100.00%
Total217100.00%1100.00%


static bool need_go(struct omap_overlay_manager *mgr) { struct omap_overlay *ovl; struct mgr_priv_data *mp; struct ovl_priv_data *op; mp = get_mgr_priv(mgr); if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty) return true; list_for_each_entry(ovl, &mgr->overlays, list) { op = get_ovl_priv(ovl); if (op->shadow_info_dirty || op->shadow_extra_info_dirty) return true; } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen79100.00%1100.00%
Total79100.00%1100.00%

/* returns true if an extra_info field is currently being updated */
static bool extra_info_update_ongoing(void) { const int num_mgrs = dss_feat_get_num_mgrs(); int i; for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct omap_overlay *ovl; struct mgr_priv_data *mp; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mp->enabled) continue; if (!mp->updating) continue; if (mp->extra_info_dirty || mp->shadow_extra_info_dirty) return true; list_for_each_entry(ovl, &mgr->overlays, list) { struct ovl_priv_data *op = get_ovl_priv(ovl); if (op->extra_info_dirty || op->shadow_extra_info_dirty) return true; } } return false; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen127100.00%1100.00%
Total127100.00%1100.00%

/* wait until no extra_info updates are pending */
static void wait_pending_extra_info_updates(void) { bool updating; unsigned long flags; unsigned long t; int r; spin_lock_irqsave(&data_lock, flags); updating = extra_info_update_ongoing(); if (!updating) { spin_unlock_irqrestore(&data_lock, flags); return; } init_completion(&extra_updated_completion); spin_unlock_irqrestore(&data_lock, flags); t = msecs_to_jiffies(500); r = wait_for_completion_timeout(&extra_updated_completion, t); if (r == 0) DSSWARN("timeout in wait_pending_extra_info_updates\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen93100.00%1100.00%
Total93100.00%1100.00%


static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) { struct omap_dss_device *dssdev; dssdev = mgr->output; if (dssdev == NULL) return NULL; while (dssdev->dst) dssdev = dssdev->dst; if (dssdev->driver) return dssdev; else return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen58100.00%1100.00%
Total58100.00%1100.00%


static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl) { return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen27100.00%1100.00%
Total27100.00%1100.00%


static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); u32 irq; int r; if (mgr->output == NULL) return -ENODEV; r = dispc_runtime_get(); if (r) return r; switch (mgr->output->id) { case OMAP_DSS_OUTPUT_VENC: irq = DISPC_IRQ_EVSYNC_ODD; break; case OMAP_DSS_OUTPUT_HDMI: irq = DISPC_IRQ_EVSYNC_EVEN; break; default: irq = dispc_mgr_get_vsync_irq(mgr->id); break; } r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); dispc_runtime_put(); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen102100.00%1100.00%
Total102100.00%1100.00%


static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); struct mgr_priv_data *mp = get_mgr_priv(mgr); u32 irq; unsigned long flags; int r; int i; spin_lock_irqsave(&data_lock, flags); if (mgr_manual_update(mgr)) { spin_unlock_irqrestore(&data_lock, flags); return 0; } if (!mp->enabled) { spin_unlock_irqrestore(&data_lock, flags); return 0; } spin_unlock_irqrestore(&data_lock, flags); r = dispc_runtime_get(); if (r) return r; irq = dispc_mgr_get_vsync_irq(mgr->id); i = 0; while (1) { bool shadow_dirty, dirty; spin_lock_irqsave(&data_lock, flags); dirty = mp->info_dirty; shadow_dirty = mp->shadow_info_dirty; spin_unlock_irqrestore(&data_lock, flags); if (!dirty && !shadow_dirty) { r = 0; break; } /* 4 iterations is the worst case: * 1 - initial iteration, dirty = true (between VFP and VSYNC) * 2 - first VSYNC, dirty = true * 3 - dirty = false, shadow_dirty = true * 4 - shadow_dirty = false */ if (i++ == 3) { DSSERR("mgr(%d)->wait_for_go() not finishing\n", mgr->id); r = 0; break; } r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); if (r == -ERESTARTSYS) break; if (r) { DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); break; } } dispc_runtime_put(); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen241100.00%1100.00%
Total241100.00%1100.00%


static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) { unsigned long timeout = msecs_to_jiffies(500); struct ovl_priv_data *op; struct mgr_priv_data *mp; u32 irq; unsigned long flags; int r; int i; if (!ovl->manager) return 0; mp = get_mgr_priv(ovl->manager); spin_lock_irqsave(&data_lock, flags); if (ovl_manual_update(ovl)) { spin_unlock_irqrestore(&data_lock, flags); return 0; } if (!mp->enabled) { spin_unlock_irqrestore(&data_lock, flags); return 0; } spin_unlock_irqrestore(&data_lock, flags); r = dispc_runtime_get(); if (r) return r; irq = dispc_mgr_get_vsync_irq(ovl->manager->id); op = get_ovl_priv(ovl); i = 0; while (1) { bool shadow_dirty, dirty; spin_lock_irqsave(&data_lock, flags); dirty = op->info_dirty; shadow_dirty = op->shadow_info_dirty; spin_unlock_irqrestore(&data_lock, flags); if (!dirty && !shadow_dirty) { r = 0; break; } /* 4 iterations is the worst case: * 1 - initial iteration, dirty = true (between VFP and VSYNC) * 2 - first VSYNC, dirty = true * 3 - dirty = false, shadow_dirty = true * 4 - shadow_dirty = false */ if (i++ == 3) { DSSERR("ovl(%d)->wait_for_go() not finishing\n", ovl->id); r = 0; break; } r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); if (r == -ERESTARTSYS) break; if (r) { DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); break; } } dispc_runtime_put(); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen269100.00%1100.00%
Total269100.00%1100.00%


static void dss_ovl_write_regs(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); struct omap_overlay_info *oi; bool replication; struct mgr_priv_data *mp; int r; DSSDBG("writing ovl %d regs\n", ovl->id); if (!op->enabled || !op->info_dirty) return; oi = &op->info; mp = get_mgr_priv(ovl->manager); replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false); if (r) { /* * We can't do much here, as this function can be called from * vsync interrupt. */ DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id); /* This will leave fifo configurations in a nonoptimal state */ op->enabled = false; dispc_ovl_enable(ovl->id, false); return; } op->info_dirty = false; if (mp->updating) op->shadow_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen159100.00%1100.00%
Total159100.00%1100.00%


static void dss_ovl_write_regs_extra(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); struct mgr_priv_data *mp; DSSDBG("writing ovl %d regs extra\n", ovl->id); if (!op->extra_info_dirty) return; /* note: write also when op->enabled == false, so that the ovl gets * disabled */ dispc_ovl_enable(ovl->id, op->enabled); dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high); mp = get_mgr_priv(ovl->manager); op->extra_info_dirty = false; if (mp->updating) op->shadow_extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen97100.00%1100.00%
Total97100.00%1100.00%


static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); struct omap_overlay *ovl; DSSDBG("writing mgr %d regs\n", mgr->id); if (!mp->enabled) return; WARN_ON(mp->busy); /* Commit overlay settings */ list_for_each_entry(ovl, &mgr->overlays, list) { dss_ovl_write_regs(ovl); dss_ovl_write_regs_extra(ovl); } if (mp->info_dirty) { dispc_mgr_setup(mgr->id, &mp->info); mp->info_dirty = false; if (mp->updating) mp->shadow_info_dirty = true; } }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen109100.00%1100.00%
Total109100.00%1100.00%


static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); DSSDBG("writing mgr %d regs extra\n", mgr->id); if (!mp->extra_info_dirty) return; dispc_mgr_set_timings(mgr->id, &mp->timings); /* lcd_config parameters */ if (dss_mgr_is_lcd(mgr->id)) dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config); mp->extra_info_dirty = false; if (mp->updating) mp->shadow_extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen90100.00%1100.00%
Total90100.00%1100.00%


static void dss_write_regs(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); int i; for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; int r; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) continue; r = dss_check_settings(mgr); if (r) { DSSERR("cannot write registers for manager %s: " "illegal configuration\n", mgr->name); continue; } dss_mgr_write_regs(mgr); dss_mgr_write_regs_extra(mgr); } }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen111100.00%1100.00%
Total111100.00%1100.00%


static void dss_set_go_bits(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); int i; for (i = 0; i < num_mgrs; ++i) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) continue; if (!need_go(mgr)) continue; mp->busy = true; if (!dss_data.irq_enabled && need_isr()) dss_register_vsync_isr(); dispc_mgr_go(mgr->id); } }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen109100.00%1100.00%
Total109100.00%1100.00%


static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr) { struct omap_overlay *ovl; struct mgr_priv_data *mp; struct ovl_priv_data *op; mp = get_mgr_priv(mgr); mp->shadow_info_dirty = false; mp->shadow_extra_info_dirty = false; list_for_each_entry(ovl, &mgr->overlays, list) { op = get_ovl_priv(ovl); op->shadow_info_dirty = false; op->shadow_extra_info_dirty = false; } }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen74100.00%1100.00%
Total74100.00%1100.00%


static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr, struct omap_dss_device *dst) { return mgr->set_output(mgr, dst); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen26100.00%1100.00%
Total26100.00%1100.00%


static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr, struct omap_dss_device *dst) { mgr->unset_output(mgr); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen23100.00%1100.00%
Total23100.00%1100.00%


static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; spin_lock_irqsave(&data_lock, flags); WARN_ON(mp->updating); r = dss_check_settings(mgr); if (r) { DSSERR("cannot start manual update: illegal configuration\n"); spin_unlock_irqrestore(&data_lock, flags); return; } dss_mgr_write_regs(mgr); dss_mgr_write_regs_extra(mgr); mp->updating = true; if (!dss_data.irq_enabled && need_isr()) dss_register_vsync_isr(); dispc_mgr_enable_sync(mgr->id); spin_unlock_irqrestore(&data_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen114100.00%1100.00%
Total114100.00%1100.00%

static void dss_apply_irq_handler(void *data, u32 mask);
static void dss_register_vsync_isr(void) { const int num_mgrs = dss_feat_get_num_mgrs(); u32 mask; int r, i; mask = 0; for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_vsync_irq(i); for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_framedone_irq(i); r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); WARN_ON(r); dss_data.irq_enabled = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen89100.00%1100.00%
Total89100.00%1100.00%


static void dss_unregister_vsync_isr(void) { const int num_mgrs = dss_feat_get_num_mgrs(); u32 mask; int r, i; mask = 0; for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_vsync_irq(i); for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_framedone_irq(i); r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask); WARN_ON(r); dss_data.irq_enabled = false; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen89100.00%1100.00%
Total89100.00%1100.00%


static void dss_apply_irq_handler(void *data, u32 mask) { const int num_mgrs = dss_feat_get_num_mgrs(); int i; bool extra_updating; spin_lock(&data_lock); /* clear busy, updating flags, shadow_dirty flags */ for (i = 0; i < num_mgrs; i++) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mp->enabled) continue; mp->updating = dispc_mgr_is_enabled(i); if (!mgr_manual_update(mgr)) { bool was_busy = mp->busy; mp->busy = dispc_mgr_go_busy(i); if (was_busy && !mp->busy) mgr_clear_shadow_dirty(mgr); } } dss_write_regs(); dss_set_go_bits(); extra_updating = extra_info_update_ongoing(); if (!extra_updating) complete_all(&extra_updated_completion); /* call framedone handlers for manual update displays */ for (i = 0; i < num_mgrs; i++) { struct omap_overlay_manager *mgr; struct mgr_priv_data *mp; mgr = omap_dss_get_overlay_manager(i); mp = get_mgr_priv(mgr); if (!mgr_manual_update(mgr) || !mp->framedone_handler) continue; if (mask & dispc_mgr_get_framedone_irq(i)) mp->framedone_handler(mp->framedone_handler_data); } if (!need_isr()) dss_unregister_vsync_isr(); spin_unlock(&data_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen238100.00%1100.00%
Total238100.00%1100.00%


static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl) { struct ovl_priv_data *op; op = get_ovl_priv(ovl); if (!op->user_info_dirty) return; op->user_info_dirty = false; op->info_dirty = true; op->info = op->user_info; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen51100.00%1100.00%
Total51100.00%1100.00%


static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp; mp = get_mgr_priv(mgr); if (!mp->user_info_dirty) return; mp->user_info_dirty = false; mp->info_dirty = true; mp->info = mp->user_info; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen51100.00%1100.00%
Total51100.00%1100.00%


static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) { unsigned long flags; struct omap_overlay *ovl; int r; DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); spin_lock_irqsave(&data_lock, flags); r = dss_check_settings_apply(mgr); if (r) { spin_unlock_irqrestore(&data_lock, flags); DSSERR("failed to apply settings: illegal configuration.\n"); return r; } /* Configure overlays */ list_for_each_entry(ovl, &mgr->overlays, list) omap_dss_mgr_apply_ovl(ovl); /* Configure manager */ omap_dss_mgr_apply_mgr(mgr); dss_write_regs(); dss_set_go_bits(); spin_unlock_irqrestore(&data_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen106100.00%1100.00%
Total106100.00%1100.00%


static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable) { struct ovl_priv_data *op; op = get_ovl_priv(ovl); if (op->enabled == enable) return; op->enabled = enable; op->extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen47100.00%1100.00%
Total47100.00%1100.00%


static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl, u32 fifo_low, u32 fifo_high) { struct ovl_priv_data *op = get_ovl_priv(ovl); if (op->fifo_low == fifo_low && op->fifo_high == fifo_high) return; op->fifo_low = fifo_low; op->fifo_high = fifo_high; op->extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen60100.00%1100.00%
Total60100.00%1100.00%


static void dss_ovl_setup_fifo(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); u32 fifo_low, fifo_high; bool use_fifo_merge = false; if (!op->enabled && !op->enabling) return; dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, use_fifo_merge, ovl_manual_update(ovl)); dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen73100.00%1100.00%
Total73100.00%1100.00%


static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) { struct omap_overlay *ovl; struct mgr_priv_data *mp; mp = get_mgr_priv(mgr); if (!mp->enabled) return; list_for_each_entry(ovl, &mgr->overlays, list) dss_ovl_setup_fifo(ovl); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen49100.00%1100.00%
Total49100.00%1100.00%


static void dss_setup_fifos(void) { const int num_mgrs = omap_dss_get_num_overlay_managers(); struct omap_overlay_manager *mgr; int i; for (i = 0; i < num_mgrs; ++i) { mgr = omap_dss_get_overlay_manager(i); dss_mgr_setup_fifos(mgr); } }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen50100.00%1100.00%
Total50100.00%1100.00%


static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; mutex_lock(&apply_lock); if (mp->enabled) goto out; spin_lock_irqsave(&data_lock, flags); mp->enabled = true; r = dss_check_settings(mgr); if (r) { DSSERR("failed to enable manager %d: check_settings failed\n", mgr->id); goto err; } dss_setup_fifos(); dss_write_regs(); dss_set_go_bits(); if (!mgr_manual_update(mgr)) mp->updating = true; if (!dss_data.irq_enabled && need_isr()) dss_register_vsync_isr(); spin_unlock_irqrestore(&data_lock, flags); if (!mgr_manual_update(mgr)) dispc_mgr_enable_sync(mgr->id); out: mutex_unlock(&apply_lock); return 0; err: mp->enabled = false; spin_unlock_irqrestore(&data_lock, flags); mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen177100.00%1100.00%
Total177100.00%1100.00%


static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; mutex_lock(&apply_lock); if (!mp->enabled) goto out; wait_pending_extra_info_updates(); if (!mgr_manual_update(mgr)) dispc_mgr_disable_sync(mgr->id); spin_lock_irqsave(&data_lock, flags); mp->updating = false; mp->enabled = false; spin_unlock_irqrestore(&data_lock, flags); out: mutex_unlock(&apply_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen95100.00%1100.00%
Total95100.00%1100.00%


static int dss_mgr_set_info(struct omap_overlay_manager *mgr, struct omap_overlay_manager_info *info) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; int r; r = dss_mgr_simple_check(mgr, info); if (r) return r; spin_lock_irqsave(&data_lock, flags); mp->user_info = *info; mp->user_info_dirty = true; spin_unlock_irqrestore(&data_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen81100.00%1100.00%
Total81100.00%1100.00%


static void dss_mgr_get_info(struct omap_overlay_manager *mgr, struct omap_overlay_manager_info *info) { struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; spin_lock_irqsave(&data_lock, flags); *info = mp->user_info; spin_unlock_irqrestore(&data_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen53100.00%1100.00%
Total53100.00%1100.00%


static int dss_mgr_set_output(struct omap_overlay_manager *mgr, struct omap_dss_device *output) { int r; mutex_lock(&apply_lock); if (mgr->output) { DSSERR("manager %s is already connected to an output\n", mgr->name); r = -EINVAL; goto err; } if ((mgr->supported_outputs & output->id) == 0) { DSSERR("output does not support manager %s\n", mgr->name); r = -EINVAL; goto err; } output->manager = mgr; mgr->output = output; mutex_unlock(&apply_lock); return 0; err: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen115100.00%1100.00%
Total115100.00%1100.00%


static int dss_mgr_unset_output(struct omap_overlay_manager *mgr) { int r; struct mgr_priv_data *mp = get_mgr_priv(mgr); unsigned long flags; mutex_lock(&apply_lock); if (!mgr->output) { DSSERR("failed to unset output, output not set\n"); r = -EINVAL; goto err; } spin_lock_irqsave(&data_lock, flags); if (mp->enabled) { DSSERR("output can't be unset when manager is enabled\n"); r = -EINVAL; goto err1; } spin_unlock_irqrestore(&data_lock, flags); mgr->output->manager = NULL; mgr->output = NULL; mutex_unlock(&apply_lock); return 0; err1: spin_unlock_irqrestore(&data_lock, flags); err: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen137100.00%1100.00%
Total137100.00%1100.00%


static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings) { struct mgr_priv_data *mp = get_mgr_priv(mgr); mp->timings = *timings; mp->extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen40100.00%1100.00%
Total40100.00%1100.00%


static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings) { unsigned long flags; struct mgr_priv_data *mp = get_mgr_priv(mgr); spin_lock_irqsave(&data_lock, flags); if (mp->updating) { DSSERR("cannot set timings for %s: manager needs to be disabled\n", mgr->name); goto out; } dss_apply_mgr_timings(mgr, timings); out: spin_unlock_irqrestore(&data_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen76100.00%1100.00%
Total76100.00%1100.00%


static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, const struct dss_lcd_mgr_config *config) { struct mgr_priv_data *mp = get_mgr_priv(mgr); mp->lcd_config = *config; mp->extra_info_dirty = true; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen40100.00%1100.00%
Total40100.00%1100.00%


static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr, const struct dss_lcd_mgr_config *config) { unsigned long flags; struct mgr_priv_data *mp = get_mgr_priv(mgr); spin_lock_irqsave(&data_lock, flags); if (mp->enabled) { DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", mgr->name); goto out; } dss_apply_mgr_lcd_config(mgr, config); out: spin_unlock_irqrestore(&data_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen76100.00%1100.00%
Total76100.00%1100.00%


static int dss_ovl_set_info(struct omap_overlay *ovl, struct omap_overlay_info *info) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; int r; r = dss_ovl_simple_check(ovl, info); if (r) return r; spin_lock_irqsave(&data_lock, flags); op->user_info = *info; op->user_info_dirty = true; spin_unlock_irqrestore(&data_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen81100.00%1100.00%
Total81100.00%1100.00%


static void dss_ovl_get_info(struct omap_overlay *ovl, struct omap_overlay_info *info) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; spin_lock_irqsave(&data_lock, flags); *info = op->user_info; spin_unlock_irqrestore(&data_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen53100.00%1100.00%
Total53100.00%1100.00%


static int dss_ovl_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; int r; if (!mgr) return -EINVAL; mutex_lock(&apply_lock); if (ovl->manager) { DSSERR("overlay '%s' already has a manager '%s'\n", ovl->name, ovl->manager->name); r = -EINVAL; goto err; } r = dispc_runtime_get(); if (r) goto err; spin_lock_irqsave(&data_lock, flags); if (op->enabled) { spin_unlock_irqrestore(&data_lock, flags); DSSERR("overlay has to be disabled to change the manager\n"); r = -EINVAL; goto err1; } dispc_ovl_set_channel_out(ovl->id, mgr->id); ovl->manager = mgr; list_add_tail(&ovl->list, &mgr->overlays); spin_unlock_irqrestore(&data_lock, flags); dispc_runtime_put(); mutex_unlock(&apply_lock); return 0; err1: dispc_runtime_put(); err: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen194100.00%1100.00%
Total194100.00%1100.00%


static int dss_ovl_unset_manager(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; int r; mutex_lock(&apply_lock); if (!ovl->manager) { DSSERR("failed to detach overlay: manager not set\n"); r = -EINVAL; goto err; } spin_lock_irqsave(&data_lock, flags); if (op->enabled) { spin_unlock_irqrestore(&data_lock, flags); DSSERR("overlay has to be disabled to unset the manager\n"); r = -EINVAL; goto err; } spin_unlock_irqrestore(&data_lock, flags); /* wait for pending extra_info updates to ensure the ovl is disabled */ wait_pending_extra_info_updates(); /* * For a manual update display, there is no guarantee that the overlay * is really disabled in HW, we may need an extra update from this * manager before the configurations can go in. Return an error if the * overlay needed an update from the manager. * * TODO: Instead of returning an error, try to do a dummy manager update * here to disable the overlay in hardware. Use the *GATED fields in * the DISPC_CONFIG registers to do a dummy update. */ spin_lock_irqsave(&data_lock, flags); if (ovl_manual_update(ovl) && op->extra_info_dirty) { spin_unlock_irqrestore(&data_lock, flags); DSSERR("need an update to change the manager\n"); r = -EINVAL; goto err; } ovl->manager = NULL; list_del(&ovl->list); spin_unlock_irqrestore(&data_lock, flags); mutex_unlock(&apply_lock); return 0; err: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen190100.00%1100.00%
Total190100.00%1100.00%


static bool dss_ovl_is_enabled(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; bool e; spin_lock_irqsave(&data_lock, flags); e = op->enabled; spin_unlock_irqrestore(&data_lock, flags); return e; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen53100.00%1100.00%
Total53100.00%1100.00%


static int dss_ovl_enable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; int r; mutex_lock(&apply_lock); if (op->enabled) { r = 0; goto err1; } if (ovl->manager == NULL || ovl->manager->output == NULL) { r = -EINVAL; goto err1; } spin_lock_irqsave(&data_lock, flags); op->enabling = true; r = dss_check_settings(ovl->manager); if (r) { DSSERR("failed to enable overlay %d: check_settings failed\n", ovl->id); goto err2; } dss_setup_fifos(); op->enabling = false; dss_apply_ovl_enable(ovl, true); dss_write_regs(); dss_set_go_bits(); spin_unlock_irqrestore(&data_lock, flags); mutex_unlock(&apply_lock); return 0; err2: op->enabling = false; spin_unlock_irqrestore(&data_lock, flags); err1: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen182100.00%1100.00%
Total182100.00%1100.00%


static int dss_ovl_disable(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); unsigned long flags; int r; mutex_lock(&apply_lock); if (!op->enabled) { r = 0; goto err; } if (ovl->manager == NULL || ovl->manager->output == NULL) { r = -EINVAL; goto err; } spin_lock_irqsave(&data_lock, flags); dss_apply_ovl_enable(ovl, false); dss_write_regs(); dss_set_go_bits(); spin_unlock_irqrestore(&data_lock, flags); mutex_unlock(&apply_lock); return 0; err: mutex_unlock(&apply_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen125100.00%1100.00%
Total125100.00%1100.00%


static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr, void (*handler)(void *), void *data) { struct mgr_priv_data *mp = get_mgr_priv(mgr); if (mp->framedone_handler) return -EBUSY; mp->framedone_handler = handler; mp->framedone_handler_data = data; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen60100.00%1100.00%
Total60100.00%1100.00%


static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr, void (*handler)(void *), void *data) { struct mgr_priv_data *mp = get_mgr_priv(mgr); WARN_ON(mp->framedone_handler != handler || mp->framedone_handler_data != data); mp->framedone_handler = NULL; mp->framedone_handler_data = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen62100.00%1100.00%
Total62100.00%1100.00%

static const struct dss_mgr_ops apply_mgr_ops = { .connect = dss_mgr_connect_compat, .disconnect = dss_mgr_disconnect_compat, .start_update = dss_mgr_start_update_compat, .enable = dss_mgr_enable_compat, .disable = dss_mgr_disable_compat, .set_timings = dss_mgr_set_timings_compat, .set_lcd_config = dss_mgr_set_lcd_config_compat, .register_framedone_handler = dss_mgr_register_framedone_handler_compat, .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat, }; static int compat_refcnt; static DEFINE_MUTEX(compat_init_lock);
int omapdss_compat_init(void) { struct platform_device *pdev = dss_get_core_pdev(); int i, r; mutex_lock(&compat_init_lock); if (compat_refcnt++ > 0) goto out; apply_init_priv(); dss_init_overlay_managers_sysfs(pdev); dss_init_overlays(pdev); for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) { struct omap_overlay_manager *mgr; mgr = omap_dss_get_overlay_manager(i); mgr->set_output = &dss_mgr_set_output; mgr->unset_output = &dss_mgr_unset_output; mgr->apply = &omap_dss_mgr_apply; mgr->set_manager_info = &dss_mgr_set_info; mgr->get_manager_info = &dss_mgr_get_info; mgr->wait_for_go = &dss_mgr_wait_for_go; mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; mgr->get_device = &dss_mgr_get_device; } for (i = 0; i < omap_dss_get_num_overlays(); i++) { struct omap_overlay *ovl = omap_dss_get_overlay(i); ovl->is_enabled = &dss_ovl_is_enabled; ovl->enable = &dss_ovl_enable; ovl->disable = &dss_ovl_disable; ovl->set_manager = &dss_ovl_set_manager; ovl->unset_manager = &dss_ovl_unset_manager; ovl->set_overlay_info = &dss_ovl_set_info; ovl->get_overlay_info = &dss_ovl_get_info; ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; ovl->get_device = &dss_ovl_get_device; } r = dss_install_mgr_ops(&apply_mgr_ops); if (r) goto err_mgr_ops; r = display_init_sysfs(pdev); if (r) goto err_disp_sysfs; dispc_runtime_get(); r = dss_dispc_initialize_irq(); if (r) goto err_init_irq; dispc_runtime_put(); out: mutex_unlock(&compat_init_lock); return 0; err_init_irq: dispc_runtime_put(); display_uninit_sysfs(pdev); err_disp_sysfs: dss_uninstall_mgr_ops(); err_mgr_ops: dss_uninit_overlay_managers_sysfs(pdev); dss_uninit_overlays(pdev); compat_refcnt--; mutex_unlock(&compat_init_lock); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen319100.00%1100.00%
Total319100.00%1100.00%

EXPORT_SYMBOL(omapdss_compat_init);
void omapdss_compat_uninit(void) { struct platform_device *pdev = dss_get_core_pdev(); mutex_lock(&compat_init_lock); if (--compat_refcnt > 0) goto out; dss_dispc_uninitialize_irq(); display_uninit_sysfs(pdev); dss_uninstall_mgr_ops(); dss_uninit_overlay_managers_sysfs(pdev); dss_uninit_overlays(pdev); out: mutex_unlock(&compat_init_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen60100.00%1100.00%
Total60100.00%1100.00%

EXPORT_SYMBOL(omapdss_compat_uninit);

Overall Contributors

PersonTokensPropCommitsCommitProp
Tomi Valkeinen609299.98%150.00%
Peter Ujfalusi10.02%150.00%
Total6093100.00%2100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.