OMAPDSS: remove uses of __init/__exit
[deliverable/linux.git] / drivers / video / fbdev / omap2 / dss / dispc.c
index 31b743c70272024fbe8e46553e59a674b0521404..e3417af63451a434a918d05da9674ca2c8256451 100644 (file)
@@ -123,6 +123,9 @@ static struct {
 
        struct regmap *syscon_pol;
        u32 syscon_pol_offset;
+
+       /* DISPC_CONTROL & DISPC_CONFIG lock*/
+       spinlock_t control_lock;
 } dispc;
 
 enum omap_color_component {
@@ -261,7 +264,16 @@ static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
 static void mgr_fld_write(enum omap_channel channel,
                                        enum mgr_reg_fields regfld, int val) {
        const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
+       const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG;
+       unsigned long flags;
+
+       if (need_lock)
+               spin_lock_irqsave(&dispc.control_lock, flags);
+
        REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
+
+       if (need_lock)
+               spin_unlock_irqrestore(&dispc.control_lock, flags);
 }
 
 #define SR(reg) \
@@ -1126,6 +1138,7 @@ static void dispc_init_fifos(void)
        int fifo;
        u8 start, end;
        u32 unit;
+       int i;
 
        unit = dss_feat_get_buffer_size_unit();
 
@@ -1165,6 +1178,20 @@ static void dispc_init_fifos(void)
                dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
                dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
        }
+
+       /*
+        * Setup default fifo thresholds.
+        */
+       for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
+               u32 low, high;
+               const bool use_fifomerge = false;
+               const bool manual_update = false;
+
+               dispc_ovl_compute_fifo_thresholds(i, &low, &high,
+                       use_fifomerge, manual_update);
+
+               dispc_ovl_set_fifo_threshold(i, low, high);
+       }
 }
 
 static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
@@ -1278,6 +1305,63 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 }
 EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);
 
+static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable)
+{
+       int bit;
+
+       if (plane == OMAP_DSS_GFX)
+               bit = 14;
+       else
+               bit = 23;
+
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
+}
+
+static void dispc_ovl_set_mflag_threshold(enum omap_plane plane,
+       int low, int high)
+{
+       dispc_write_reg(DISPC_OVL_MFLAG_THRESHOLD(plane),
+               FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
+}
+
+static void dispc_init_mflag(void)
+{
+       int i;
+
+       /*
+        * HACK: NV12 color format and MFLAG seem to have problems working
+        * together: using two displays, and having an NV12 overlay on one of
+        * the displays will cause underflows/synclosts when MFLAG_CTRL=2.
+        * Changing MFLAG thresholds and PRELOAD to certain values seem to
+        * remove the errors, but there doesn't seem to be a clear logic on
+        * which values work and which not.
+        *
+        * As a work-around, set force MFLAG to always on.
+        */
+       dispc_write_reg(DISPC_GLOBAL_MFLAG_ATTRIBUTE,
+               (1 << 0) |      /* MFLAG_CTRL = force always on */
+               (0 << 2));      /* MFLAG_START = disable */
+
+       for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
+               u32 size = dispc_ovl_get_fifo_size(i);
+               u32 unit = dss_feat_get_buffer_size_unit();
+               u32 low, high;
+
+               dispc_ovl_set_mflag(i, true);
+
+               /*
+                * Simulation team suggests below thesholds:
+                * HT = fifosize * 5 / 8;
+                * LT = fifosize * 4 / 8;
+                */
+
+               low = size * 4 / 8 / unit;
+               high = size * 5 / 8 / unit;
+
+               dispc_ovl_set_mflag_threshold(i, low, high);
+       }
+}
+
 static void dispc_ovl_set_fir(enum omap_plane plane,
                                int hinc, int vinc,
                                enum omap_color_component color_comp)
@@ -2322,6 +2406,11 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
        if (width == out_width && height == out_height)
                return 0;
 
+       if (pclk == 0 || mgr_timings->pixelclock == 0) {
+               DSSERR("cannot calculate scaling settings: pclk is zero\n");
+               return -EINVAL;
+       }
+
        if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
                return -EINVAL;
 
@@ -2441,7 +2530,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
        unsigned long pclk = dispc_plane_pclk_rate(plane);
        unsigned long lclk = dispc_plane_lclk_rate(plane);
 
-       if (paddr == 0)
+       if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
                return -EINVAL;
 
        out_width = out_width == 0 ? width : out_width;
@@ -2915,7 +3004,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
 
 {
        u32 timing_h, timing_v, l;
-       bool onoff, rf, ipc;
+       bool onoff, rf, ipc, vs, hs, de;
 
        timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
                        FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
@@ -2927,6 +3016,39 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
        dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
        dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
 
+       switch (vsync_level) {
+       case OMAPDSS_SIG_ACTIVE_LOW:
+               vs = true;
+               break;
+       case OMAPDSS_SIG_ACTIVE_HIGH:
+               vs = false;
+               break;
+       default:
+               BUG();
+       }
+
+       switch (hsync_level) {
+       case OMAPDSS_SIG_ACTIVE_LOW:
+               hs = true;
+               break;
+       case OMAPDSS_SIG_ACTIVE_HIGH:
+               hs = false;
+               break;
+       default:
+               BUG();
+       }
+
+       switch (de_level) {
+       case OMAPDSS_SIG_ACTIVE_LOW:
+               de = true;
+               break;
+       case OMAPDSS_SIG_ACTIVE_HIGH:
+               de = false;
+               break;
+       default:
+               BUG();
+       }
+
        switch (data_pclk_edge) {
        case OMAPDSS_DRIVE_SIG_RISING_EDGE:
                ipc = false;
@@ -2934,22 +3056,18 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
        case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
                ipc = true;
                break;
-       case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
        default:
                BUG();
        }
 
+       /* always use the 'rf' setting */
+       onoff = true;
+
        switch (sync_pclk_edge) {
-       case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
-               onoff = false;
-               rf = false;
-               break;
        case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
-               onoff = true;
                rf = false;
                break;
        case OMAPDSS_DRIVE_SIG_RISING_EDGE:
-               onoff = true;
                rf = true;
                break;
        default:
@@ -2958,10 +3076,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
 
        l = FLD_VAL(onoff, 17, 17) |
                FLD_VAL(rf, 16, 16) |
-               FLD_VAL(de_level, 15, 15) |
+               FLD_VAL(de, 15, 15) |
                FLD_VAL(ipc, 14, 14) |
-               FLD_VAL(hsync_level, 13, 13) |
-               FLD_VAL(vsync_level, 12, 12);
+               FLD_VAL(hs, 13, 13) |
+               FLD_VAL(vs, 12, 12);
 
        dispc_write_reg(DISPC_POL_FREQ(channel), l);
 
@@ -3569,9 +3687,12 @@ static void _omap_dispc_initial_config(void)
 
        if (dispc.feat->mstandby_workaround)
                REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);
+
+       if (dss_has_feature(FEAT_MFLAG))
+               dispc_init_mflag();
 }
 
-static const struct dispc_features omap24xx_dispc_feats __initconst = {
+static const struct dispc_features omap24xx_dispc_feats = {
        .sw_start               =       5,
        .fp_start               =       15,
        .bp_start               =       27,
@@ -3590,7 +3711,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
        .set_max_preload        =       false,
 };
 
-static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
+static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
        .sw_start               =       5,
        .fp_start               =       15,
        .bp_start               =       27,
@@ -3610,7 +3731,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
        .set_max_preload        =       false,
 };
 
-static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
+static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
        .sw_start               =       7,
        .fp_start               =       19,
        .bp_start               =       31,
@@ -3630,7 +3751,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
        .set_max_preload        =       false,
 };
 
-static const struct dispc_features omap44xx_dispc_feats __initconst = {
+static const struct dispc_features omap44xx_dispc_feats = {
        .sw_start               =       7,
        .fp_start               =       19,
        .bp_start               =       31,
@@ -3650,7 +3771,7 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
        .set_max_preload        =       true,
 };
 
-static const struct dispc_features omap54xx_dispc_feats __initconst = {
+static const struct dispc_features omap54xx_dispc_feats = {
        .sw_start               =       7,
        .fp_start               =       19,
        .bp_start               =       31,
@@ -3671,7 +3792,7 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = {
        .set_max_preload        =       true,
 };
 
-static int __init dispc_init_features(struct platform_device *pdev)
+static int dispc_init_features(struct platform_device *pdev)
 {
        const struct dispc_features *src;
        struct dispc_features *dst;
@@ -3761,7 +3882,7 @@ void dispc_free_irq(void *dev_id)
 EXPORT_SYMBOL(dispc_free_irq);
 
 /* DISPC HW IP initialisation */
-static int __init omap_dispchw_probe(struct platform_device *pdev)
+static int omap_dispchw_probe(struct platform_device *pdev)
 {
        u32 rev;
        int r = 0;
@@ -3770,6 +3891,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
        dispc.pdev = pdev;
 
+       spin_lock_init(&dispc.control_lock);
+
        r = dispc_init_features(dispc.pdev);
        if (r)
                return r;
@@ -3832,7 +3955,7 @@ err_runtime_get:
        return r;
 }
 
-static int __exit omap_dispchw_remove(struct platform_device *pdev)
+static int omap_dispchw_remove(struct platform_device *pdev)
 {
        pm_runtime_disable(&pdev->dev);
 
@@ -3890,7 +4013,7 @@ static const struct of_device_id dispc_of_match[] = {
 };
 
 static struct platform_driver omap_dispchw_driver = {
-       .remove         = __exit_p(omap_dispchw_remove),
+       .remove         = omap_dispchw_remove,
        .driver         = {
                .name   = "omapdss_dispc",
                .pm     = &dispc_pm_ops,
@@ -3904,7 +4027,7 @@ int __init dispc_init_platform_driver(void)
        return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
 }
 
-void __exit dispc_uninit_platform_driver(void)
+void dispc_uninit_platform_driver(void)
 {
        platform_driver_unregister(&omap_dispchw_driver);
 }
This page took 0.029595 seconds and 5 git commands to generate.