video: tegra: dc: Move PRISM update to V_PULSE2.
Kevin Huang [Tue, 16 Oct 2012 04:50:40 +0000 (21:50 -0700)]
Add support to update PRISM at V_PULSE2_INT. Use V_PULSE2 for PRISM
if the chip supports.

Bug 1156207

Signed-off-by: Kevin Huang <kevinh@nvidia.com>
Change-Id: I5b908b206d647c3efce7037578b0ed86e9bb2d22
Reviewed-on: http://git-master/r/159945
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv_defs.h
drivers/video/tegra/dc/dc_reg.h
drivers/video/tegra/dc/nvsd.c
drivers/video/tegra/dc/window.c

index 2696fc8..72744fb 100644 (file)
@@ -411,6 +411,7 @@ struct tegra_dc_sd_settings {
 
        bool sd_proc_control;
        bool soft_clipping_correction;
+       bool use_vpulse2;
 
        struct tegra_dc_sd_fc fc;
        struct tegra_dc_sd_blp blp;
@@ -512,9 +513,13 @@ struct tegra_dc_out {
 #define TEGRA_DC_ORDER_RED_BLUE                0
 #define TEGRA_DC_ORDER_BLUE_RED                1
 
+/* Errands use the interrupts */
 #define V_BLANK_FLIP           0
 #define V_BLANK_NVSD           1
 
+#define V_PULSE2_FLIP          0
+#define V_PULSE2_NVSD          1
+
 struct tegra_dc;
 struct nvmap_handle_ref;
 
index 43ea6e7..9396e85 100644 (file)
@@ -1081,7 +1081,6 @@ static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out)
 
        if (dc->out_ops && dc->out_ops->init)
                dc->out_ops->init(dc);
-
 }
 
 unsigned tegra_dc_get_out_height(const struct tegra_dc *dc)
@@ -1245,7 +1244,7 @@ static void tegra_dc_vblank(struct work_struct *work)
                clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
 
        /* Update the SD brightness */
-       if (dc->enabled && dc->out->sd_settings) {
+       if (dc->out->sd_settings && !dc->out->sd_settings->use_vpulse2) {
                nvsd_updated = nvsd_update_brightness(dc);
                /* Ref-count vblank if nvsd is on-going. Otherwise, clean the
                 * V_BLANK_NVSD bit of vblank ref-count. */
@@ -1368,6 +1367,35 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
        trace_underflow(dc);
 }
 
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+static void tegra_dc_vpulse2_locked(struct tegra_dc *dc)
+{
+       bool nvsd_updated = false;
+
+       if (!dc->enabled)
+               return;
+
+       /* Clear the V_PULSE2_FLIP if no update */
+       if (!tegra_dc_windows_are_dirty(dc))
+               clear_bit(V_PULSE2_FLIP, &dc->vpulse2_ref_count);
+
+       /* Update the SD brightness */
+       if (dc->out->sd_settings && dc->out->sd_settings->use_vpulse2) {
+               nvsd_updated = nvsd_update_brightness(dc);
+               if (nvsd_updated) {
+                       set_bit(V_PULSE2_NVSD, &dc->vpulse2_ref_count);
+                       tegra_dc_unmask_interrupt(dc, V_PULSE2_INT);
+               } else {
+                       clear_bit(V_PULSE2_NVSD, &dc->vpulse2_ref_count);
+               }
+       }
+
+       /* Mask vpulse2 interrupt if ref-count is zero. */
+       if (!dc->vpulse2_ref_count)
+               tegra_dc_mask_interrupt(dc, V_PULSE2_INT);
+}
+#endif
+
 #ifndef CONFIG_TEGRA_FPGA_PLATFORM
 static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
 {
@@ -1391,6 +1419,11 @@ static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
                if (!completion_done(&dc->frame_end_complete))
                        complete(&dc->frame_end_complete);
        }
+
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       if (status & V_PULSE2_INT)
+               tegra_dc_vpulse2_locked(dc);
+#endif
 }
 
 static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
@@ -1410,6 +1443,11 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
 
                tegra_dc_trigger_windows(dc);
        }
+
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       if (status & V_PULSE2_INT)
+               tegra_dc_vpulse2_locked(dc);
+#endif
 }
 
 /* XXX: Not sure if we limit look ahead to 1 frame */
@@ -1603,6 +1641,30 @@ static u32 get_syncpt(struct tegra_dc *dc, int idx)
        return syncpt_id;
 }
 
+static void tegra_dc_init_vpulse2_int(struct tegra_dc *dc)
+{
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       u32 start, end;
+       unsigned long val;
+
+       val = V_PULSE2_H_POSITION(0) | V_PULSE2_LAST(0x1);
+       tegra_dc_writel(dc, val, DC_DISP_V_PULSE2_CONTROL);
+
+       start = dc->mode.v_ref_to_sync + dc->mode.v_sync_width +
+               dc->mode.v_back_porch + dc->mode.v_active;
+       end = start + 1;
+       val = V_PULSE2_START_A(start) + V_PULSE2_END_A(end);
+       tegra_dc_writel(dc, val, DC_DISP_V_PULSE2_POSITION_A);
+
+       val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
+       val |= V_PULSE2_INT;
+       tegra_dc_writel(dc, val , DC_CMD_INT_ENABLE);
+
+       tegra_dc_mask_interrupt(dc, V_PULSE2_INT);
+       tegra_dc_writel(dc, V_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
+#endif
+}
+
 static int tegra_dc_init(struct tegra_dc *dc)
 {
        int i;
@@ -1641,6 +1703,7 @@ static int tegra_dc_init(struct tegra_dc *dc)
        }
        tegra_dc_writel(dc, 0x00000100 | dc->vblank_syncpt,
                        DC_CMD_CONT_SYNCPT_VSYNC);
+
        tegra_dc_writel(dc, 0x00004700, DC_CMD_INT_TYPE);
        tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY);
        tegra_dc_writel(dc, 0x00202020, DC_DISP_MEM_HIGH_PRIORITY);
@@ -1656,6 +1719,7 @@ static int tegra_dc_init(struct tegra_dc *dc)
 
        tegra_dc_writel(dc, int_enable, DC_CMD_INT_ENABLE);
        tegra_dc_writel(dc, ALL_UF_INT, DC_CMD_INT_MASK);
+       tegra_dc_init_vpulse2_int(dc);
 
        tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
 
@@ -1665,7 +1729,6 @@ static int tegra_dc_init(struct tegra_dc *dc)
        else
                tegra_dc_update_cmu(dc, &default_cmu);
 #endif
-
        tegra_dc_set_color_control(dc);
        for (i = 0; i < DC_N_WINDOWS; i++) {
                struct tegra_dc_win *win = &dc->windows[i];
@@ -2198,6 +2261,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
 #endif
        INIT_WORK(&dc->vblank_work, tegra_dc_vblank);
        dc->vblank_ref_count = 0;
+       dc->vpulse2_ref_count = 0;
        INIT_DELAYED_WORK(&dc->underflow_work, tegra_dc_underflow_worker);
        INIT_DELAYED_WORK(&dc->one_shot_work, tegra_dc_one_shot_worker);
 
@@ -2363,6 +2427,7 @@ static int __devexit tegra_dc_remove(struct nvhost_device *ndev)
                release_resource(dc->base_res);
        kfree(dc);
        tegra_dc_set(NULL, ndev->id);
+
        return 0;
 }
 
index 364f7c7..2cec658 100644 (file)
@@ -158,6 +158,7 @@ struct tegra_dc {
 
        struct work_struct              vblank_work;
        long                            vblank_ref_count;
+       long                            vpulse2_ref_count;
 
        struct {
                u64                     underflows;
index 4500bbd..1fdf7e0 100644 (file)
@@ -72,6 +72,7 @@
 #define  V_BLANK_INT           (1 << 2)
 #define  H_BLANK_INT           (1 << 3)
 #define  V_PULSE3_INT          (1 << 4)
+#define  V_PULSE2_INT          (1 << 5)
 #define  SPI_BUSY_INT          (1 << 7)
 #define  WIN_A_UF_INT          (1 << 8)
 #define  WIN_B_UF_INT          (1 << 9)
 #define DC_DISP_V_PULSE1_POSITION_B            0x420
 #define DC_DISP_V_PULSE1_POSITION_C            0x421
 #define DC_DISP_V_PULSE2_CONTROL               0x422
+#define  V_PULSE2_H_POSITION(x)                (((x) & 0x1fff) << 16)
+#define  V_PULSE2_LAST(x)              (((x) & 0x1) << 8)
 #define DC_DISP_V_PULSE2_POSITION_A            0x423
+#define  V_PULSE2_START_A(x)           (((x) & 0x1fff) << 0)
+#define  V_PULSE2_END_A(x)             (((x) & 0x1fff) << 16)
+
 #define DC_DISP_V_PULSE3_CONTROL               0x424
 #define DC_DISP_V_PULSE3_POSITION_A            0x425
 #define DC_DISP_M0_CONTROL                     0x426
index 05cc36c..8d54b91 100644 (file)
@@ -64,7 +64,7 @@ NVSD_ATTR(soft_clipping_enable);
 NVSD_ATTR(soft_clipping_threshold);
 NVSD_ATTR(smooth_k_enable);
 NVSD_ATTR(smooth_k_incr);
-NVSD_ATTR(sd_proc_control);
+NVSD_ATTR(use_vpulse2);
 #endif
 static struct kobj_attribute nvsd_attr_registers =
        __ATTR(registers, S_IRUGO, nvsd_registers_show, NULL);
@@ -94,7 +94,7 @@ static struct attribute *nvsd_attrs[] = {
        NVSD_ATTRS_ENTRY(soft_clipping_threshold),
        NVSD_ATTRS_ENTRY(smooth_k_enable),
        NVSD_ATTRS_ENTRY(smooth_k_incr),
-       NVSD_ATTRS_ENTRY(sd_proc_control),
+       NVSD_ATTRS_ENTRY(use_vpulse2),
 #endif
        NULL,
 };
@@ -572,7 +572,7 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings)
        /* Smooth K enable */
        val |= (settings->smooth_k_enable) ? SD_SMOOTH_K_ENABLE : 0;
        /* SD proc control */
-       val |= (settings->sd_proc_control) ? SD_VPULSE2 : SD_VSYNC;
+       val |= (settings->use_vpulse2) ? SD_VPULSE2 : SD_VSYNC;
 #endif
        /* Finally, Write SD Control */
        tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
@@ -878,9 +878,9 @@ static ssize_t nvsd_settings_show(struct kobject *kobj,
                else if (IS_NVSD_ATTR(smooth_k_incr))
                        res = snprintf(buf, PAGE_SIZE, "%d\n",
                                sd_settings->smooth_k_incr);
-               else if (IS_NVSD_ATTR(sd_proc_control))
+               else if (IS_NVSD_ATTR(use_vpulse2))
                        res = snprintf(buf, PAGE_SIZE, "%d\n",
-                               sd_settings->sd_proc_control);
+                               sd_settings->use_vpulse2);
 #endif
                else if (IS_NVSD_ATTR(lut))
                        res = nvsd_lut_show(sd_settings, buf, res);
@@ -1064,8 +1064,8 @@ static ssize_t nvsd_settings_store(struct kobject *kobj,
                        nvsd_check_and_update(0, 1, smooth_k_enable);
                } else if (IS_NVSD_ATTR(smooth_k_incr)) {
                        nvsd_check_and_update(0, 16320, smooth_k_incr);
-               } else if (IS_NVSD_ATTR(sd_proc_control)) {
-                       nvsd_check_and_update(0, 1, sd_proc_control);
+               } else if (IS_NVSD_ATTR(use_vpulse2)) {
+                       nvsd_check_and_update(0, 1, use_vpulse2);
 #endif
                } else if (IS_NVSD_ATTR(lut)) {
                        if (nvsd_lut_store(sd_settings, buf))
index a51b78e..42ddcd5 100644 (file)
@@ -522,9 +522,17 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                set_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
                tegra_dc_unmask_interrupt(dc,
                        FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+               set_bit(V_PULSE2_FLIP, &dc->vpulse2_ref_count);
+               tegra_dc_unmask_interrupt(dc, V_PULSE2_INT);
+#endif
        } else {
                clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
                tegra_dc_mask_interrupt(dc, V_BLANK_INT | ALL_UF_INT);
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+               clear_bit(V_PULSE2_FLIP, &dc->vpulse2_ref_count);
+               tegra_dc_mask_interrupt(dc, V_PULSE2_INT);
+#endif
                if (!atomic_read(&frame_end_ref))
                        tegra_dc_mask_interrupt(dc, FRAME_END_INT);
        }