summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc
diff options
context:
space:
mode:
authorLaurence Harrison <lharrison@nvidia.com>2011-03-15 21:43:45 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:44:59 -0800
commitf8756378e4ceaceccfc4cedf39d9c879380ee436 (patch)
tree51a939d15267b199383c5902dbf481314de3dbd0 /drivers/video/tegra/dc
parent0207f39caeabda56e3de6e3949c17faa01b2e20d (diff)
video: tegra: Added initial smartdimmer support
includes: 1.) changes to DC init to add SD functionality 2.) changes to DC flip to add SD functionality Original-Change-Id: I8c729e16e2b8a5a4158697b99cc4b3d07bf02001 Reviewed-on: http://git-master/r/21452 Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Jonathan Mayo <jmayo@nvidia.com> Tested-by: Jonathan Mayo <jmayo@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Original-Change-Id: I4ad3ee3778a0e859e0d2b0c36ee6369193795cd3 Rebase-Id: Rd133da1af5c8b283b1886b025b8b1880ec61fde0
Diffstat (limited to 'drivers/video/tegra/dc')
-rw-r--r--drivers/video/tegra/dc/Makefile1
-rw-r--r--drivers/video/tegra/dc/dc.c21
-rw-r--r--drivers/video/tegra/dc/dc_reg.h65
-rw-r--r--drivers/video/tegra/dc/nvsd.c163
-rw-r--r--drivers/video/tegra/dc/nvsd.h23
5 files changed, 273 insertions, 0 deletions
diff --git a/drivers/video/tegra/dc/Makefile b/drivers/video/tegra/dc/Makefile
index db675fd82e76..ea7671edfb0a 100644
--- a/drivers/video/tegra/dc/Makefile
+++ b/drivers/video/tegra/dc/Makefile
@@ -3,5 +3,6 @@ obj-y += rgb.o
obj-y += hdmi.o
obj-y += nvhdcp.o
obj-y += edid.o
+obj-y += nvsd.o
obj-$(CONFIG_TEGRA_DSI) += dsi.o
obj-$(CONFIG_TEGRA_OVERLAY) += overlay.o
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 541346a3bbee..0ba41a884cf8 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -30,6 +30,7 @@
#include <linux/ktime.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/backlight.h>
#include <mach/clk.h>
#include <mach/dc.h>
@@ -40,6 +41,7 @@
#include "dc_reg.h"
#include "dc_priv.h"
#include "overlay.h"
+#include "nvsd.h"
static int no_vsync;
@@ -482,6 +484,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
unsigned long update_mask = GENERAL_ACT_REQ;
unsigned long val;
bool update_blend = false;
+ bool nvsd_updated = false;
int i;
dc = windows[0]->dc;
@@ -643,8 +646,22 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
}
tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+
+ /* Update the SD brightness */
+ nvsd_updated = nvsd_update_brightness(dc);
+
mutex_unlock(&dc->lock);
+ /* Do the actual brightness update outside of the mutex */
+ if (nvsd_updated && dc->out->sd_settings &&
+ dc->out->sd_settings->bl_device) {
+
+ struct platform_device *pdev = dc->out->sd_settings->bl_device;
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ if (bl)
+ backlight_update_status(bl);
+ }
+
return 0;
}
EXPORT_SYMBOL(tegra_dc_update_windows);
@@ -1353,6 +1370,10 @@ static void tegra_dc_init(struct tegra_dc *dc)
if (dc->mode.pclk)
tegra_dc_program_mode(dc, &dc->mode);
+
+ /* Initialize SD AFTER the modeset.
+ nvsd_init handles the sd_settings = NULL case. */
+ nvsd_init(dc, dc->out->sd_settings);
}
static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 11bce9a4e3ea..c7f4a30223dc 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -450,4 +450,69 @@
#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
#define DC_WINBUF_UFLOW_STATUS 0x80a
+
+#define DC_DISP_SD_CONTROL 0x4c2
+#define SD_ENABLE_NORMAL (1 << 0)
+#define SD_ENABLE_ONESHOT (2 << 0)
+#define SD_USE_VID_LUMA (1 << 2)
+#define SD_BIN_WIDTH_ONE (0 << 3)
+#define SD_BIN_WIDTH_TWO (1 << 3)
+#define SD_BIN_WIDTH_FOUR (2 << 3)
+#define SD_BIN_WIDTH_EIGHT (3 << 3)
+#define SD_AGGRESSIVENESS(x) (((x) & 0x7) << 5)
+#define SD_HW_UPDATE_DLY(x) (((x) & 0x3) << 8)
+#define SD_ONESHOT_ENABLE (1 << 10)
+#define SD_CORRECTION_MODE_AUTO (0 << 11)
+#define SD_CORRECTION_MODE_MAN (1 << 11)
+
+#define DC_DISP_SD_CSC_COEFF 0x4c3
+#define SD_CSC_COEFF_R(x) (((x) & 0xf) << 4)
+#define SD_CSC_COEFF_G(x) (((x) & 0xf) << 12)
+#define SD_CSC_COEFF_B(x) (((x) & 0xf) << 20)
+
+#define DC_DISP_SD_LUT(i) (0x4c4 + i)
+#define DC_DISP_SD_LUT_NUM 9
+#define SD_LUT_R(x) (((x) & 0xff) << 0)
+#define SD_LUT_G(x) (((x) & 0xff) << 8)
+#define SD_LUT_B(x) (((x) & 0xff) << 16)
+
+#define DC_DISP_SD_FLICKER_CONTROL 0x4cd
+#define SD_FC_TIME_LIMIT(x) (((x) & 0xff) << 0)
+#define SD_FC_THRESHOLD(x) (((x) & 0xff) << 8)
+
+#define DC_DISP_SD_PIXEL_COUNT 0x4ce
+
+#define DC_DISP_SD_HISTOGRAM(i) (0x4cf + i)
+#define DC_DISP_SD_HISTOGRAM_NUM 8
+#define SD_HISTOGRAM_BIN_0(val) (((val) & (0xff << 0)) >> 0)
+#define SD_HISTOGRAM_BIN_1(val) (((val) & (0xff << 8)) >> 8)
+#define SD_HISTOGRAM_BIN_2(val) (((val) & (0xff << 16)) >> 16)
+#define SD_HISTOGRAM_BIN_3(val) (((val) & (0xff << 24)) >> 24)
+
+#define DC_DISP_SD_BL_PARAMETERS 0x4d7
+#define SD_BLP_TIME_CONSTANT(x) (((x) & 0x7ff) << 0)
+#define SD_BLP_STEP(x) (((x) & 0xff) << 8)
+
+#define DC_DISP_SD_BL_TF(i) (0x4d8 + i)
+#define DC_DISP_SD_BL_TF_NUM 4
+#define SD_BL_TF_POINT_0(x) (((x) & 0xff) << 0)
+#define SD_BL_TF_POINT_1(x) (((x) & 0xff) << 8)
+#define SD_BL_TF_POINT_2(x) (((x) & 0xff) << 16)
+#define SD_BL_TF_POINT_3(x) (((x) & 0xff) << 24)
+
+#define DC_DISP_SD_BL_CONTROL 0x4dc
+#define SD_BLC_MODE_MAN (0 << 0)
+#define SD_BLC_MODE_AUTO (1 << 1)
+#define SD_BLC_BRIGHTNESS(val) (((val) & (0xff << 8)) >> 8)
+
+#define DC_DISP_SD_HW_K_VALUES 0x4dd
+#define SD_HW_K_R(val) (((val) & (0x3ff << 0)) >> 0)
+#define SD_HW_K_G(val) (((val) & (0x3ff << 10)) >> 10)
+#define SD_HW_K_B(val) (((val) & (0x3ff << 20)) >> 20)
+
+#define DC_DISP_SD_MAN_K_VALUES 0x4de
+#define SD_MAN_K_R(x) (((x) & 0x3ff) << 0)
+#define SD_MAN_K_G(x) (((x) & 0x3ff) << 10)
+#define SD_MAN_K_B(x) (((x) & 0x3ff) << 20)
+
#endif
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
new file mode 100644
index 000000000000..40ab9c1c1702
--- /dev/null
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -0,0 +1,163 @@
+/*
+ * drivers/video/tegra/dc/nvsd.c
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <mach/dc.h>
+#include <linux/types.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+#include "nvsd.h"
+
+static atomic_t *sd_brightness = NULL;
+
+void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) {
+ u32 i = 0, val = 0;
+ /* TODO: check if HW says SD's available */
+
+ /* If SD's not present or disabled, clear the register and return. */
+ if (!settings || settings->enable == 0) {
+ /* clear the brightness val, too. */
+ if (sd_brightness)
+ atomic_set(sd_brightness, 255);
+ sd_brightness = NULL;
+
+ tegra_dc_writel(dc, 0, DC_DISP_SD_CONTROL);
+ return;
+ }
+
+ dev_dbg(&dc->ndev->dev, "===================\n");
+ dev_dbg(&dc->ndev->dev, "**** NVSD_INIT ****\n");
+
+ /* Write LUT */
+ for (i = 0; i < DC_DISP_SD_LUT_NUM; i++) {
+ val = SD_LUT_R(settings->lut[i].r) |
+ SD_LUT_G(settings->lut[i].g) |
+ SD_LUT_B(settings->lut[i].b);
+ tegra_dc_writel(dc, val, DC_DISP_SD_LUT(i));
+
+ dev_dbg(&dc->ndev->dev, "LUT(%d): 0x%08x\n", i, val);
+ }
+
+ /* Write BL TF */
+ for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) {
+ val = SD_BL_TF_POINT_0(settings->bltf[i][0]) |
+ SD_BL_TF_POINT_1(settings->bltf[i][1]) |
+ SD_BL_TF_POINT_2(settings->bltf[i][2]) |
+ SD_BL_TF_POINT_3(settings->bltf[i][3]);
+ tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i));
+
+ dev_dbg(&dc->ndev->dev, "BL_TF(%d): 0x%08x\n", i, val);
+ }
+
+ /* Write Coeff */
+ val = SD_CSC_COEFF_R(settings->coeff.r) |
+ SD_CSC_COEFF_G(settings->coeff.g) |
+ SD_CSC_COEFF_B(settings->coeff.b);
+ tegra_dc_writel(dc, val, DC_DISP_SD_CSC_COEFF);
+ dev_dbg(&dc->ndev->dev, "COEFF: 0x%08x\n", val);
+
+ /* Write BL Params */
+ val = SD_BLP_TIME_CONSTANT(settings->blp.time_constant) |
+ SD_BLP_STEP(settings->blp.step);
+ tegra_dc_writel(dc, val, DC_DISP_SD_BL_PARAMETERS);
+ dev_dbg(&dc->ndev->dev, "BLP: 0x%08x\n", val);
+
+ /* Write Auto/Manual PWM */
+ val = (settings->use_auto_pwm) ? SD_BLC_MODE_AUTO : SD_BLC_MODE_MAN;
+ tegra_dc_writel(dc, val, DC_DISP_SD_BL_CONTROL);
+ dev_dbg(&dc->ndev->dev, "BL_CONTROL: 0x%08x\n", val);
+
+ /* Write Flicker Control */
+ val = SD_FC_TIME_LIMIT(settings->fc.time_limit) |
+ SD_FC_THRESHOLD(settings->fc.threshold);
+ tegra_dc_writel(dc, val, DC_DISP_SD_FLICKER_CONTROL);
+ dev_dbg(&dc->ndev->dev, "FLICKER_CONTROL: 0x%08x\n", val);
+
+ /* Manage SD Control */
+ val = 0;
+ /* Enable / One-Shot */
+ val |= (settings->enable == 2) ?
+ (SD_ENABLE_ONESHOT | SD_ONESHOT_ENABLE) :
+ SD_ENABLE_NORMAL;
+ /* HW Update Delay */
+ val |= SD_HW_UPDATE_DLY(settings->hw_update_delay);
+ /* Video Luma */
+ val |= (settings->use_vid_luma) ? SD_USE_VID_LUMA : 0;
+ /* Aggressiveness */
+ val |= SD_AGGRESSIVENESS(settings->aggressiveness);
+ /* Bin Width */
+ switch (settings->bin_width) {
+ default: case 0:
+ /* A 0 bin-width indicates 'automatic'
+ based upon aggressiveness. */
+ switch (settings->aggressiveness) {
+ default: case 0: case 1:
+ val |= SD_BIN_WIDTH_ONE;
+ break;
+ case 2: case 3: case 4:
+ val |= SD_BIN_WIDTH_TWO;
+ break;
+ case 5:
+ val |= SD_BIN_WIDTH_FOUR;
+ break;
+ }
+ break;
+ case 1: val |= SD_BIN_WIDTH_ONE; break;
+ case 2: val |= SD_BIN_WIDTH_TWO; break;
+ case 4: val |= SD_BIN_WIDTH_FOUR; break;
+ case 8: val |= SD_BIN_WIDTH_EIGHT; break;
+ }
+
+ /* TODO: histogram reset WAR? */
+
+ /* Finally, Write SD Control */
+ tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
+ dev_dbg(&dc->ndev->dev, "SD_CONTROL: 0x%08x\n", val);
+
+ /* set the brightness pointer */
+ sd_brightness = settings->sd_brightness;
+ dev_dbg(&dc->ndev->dev, "sd_brightness: 0x%08x\n", (u32)sd_brightness);
+
+ dev_dbg(&dc->ndev->dev, "*******************\n");
+ dev_dbg(&dc->ndev->dev, "===================\n");
+}
+
+bool nvsd_update_brightness(struct tegra_dc *dc) {
+ u32 val = 0;
+ int cur_sd_brightness;
+
+ if (sd_brightness) {
+ /* TODO: histogram reset WAR? */
+
+ cur_sd_brightness = atomic_read(sd_brightness);
+
+ /* read brightness value */
+ val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL);
+ val = SD_BLC_BRIGHTNESS(val);
+
+ if (val != (u32)cur_sd_brightness)
+ {
+ /* set brightness value and note the update */
+ atomic_set(sd_brightness, (int)val);
+ return true;
+ }
+ /* TODO: log? */
+ }
+
+ /* No update needed. */
+ return false;
+}
diff --git a/drivers/video/tegra/dc/nvsd.h b/drivers/video/tegra/dc/nvsd.h
new file mode 100644
index 000000000000..6d082265d781
--- /dev/null
+++ b/drivers/video/tegra/dc/nvsd.h
@@ -0,0 +1,23 @@
+/*
+ * drivers/video/tegra/dc/nvsd.h
+ *
+ * Copyright (c) 2010-2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_VIDEO_TEGRA_DC_NVSD_H
+#define __DRIVERS_VIDEO_TEGRA_DC_NVSD_H
+
+void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings);
+bool nvsd_update_brightness(struct tegra_dc *dc);
+
+#endif