diff options
author | Laurence Harrison <lharrison@nvidia.com> | 2011-03-15 21:43:45 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:44:59 -0800 |
commit | f8756378e4ceaceccfc4cedf39d9c879380ee436 (patch) | |
tree | 51a939d15267b199383c5902dbf481314de3dbd0 /drivers/video/tegra/dc | |
parent | 0207f39caeabda56e3de6e3949c17faa01b2e20d (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/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 21 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_reg.h | 65 | ||||
-rw-r--r-- | drivers/video/tegra/dc/nvsd.c | 163 | ||||
-rw-r--r-- | drivers/video/tegra/dc/nvsd.h | 23 |
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 |