summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Huang <kevinh@nvidia.com>2013-01-25 11:31:17 -0800
committerMrutyunjay Sawant <msawant@nvidia.com>2013-04-02 04:06:07 -0700
commit99c727f3e4a8a6544bdd676ef37fda36f592ed69 (patch)
tree5314ddb83812a5afc42237cb68de072b1319af8e
parent1f26035e199eb6058db7f576a0de34cd3a37a2c7 (diff)
video: tegra: dc: add advanced cursor support
Support advanced display cursor for t11x. Change-Id: If5ef50401b8a2b2fd22500636d07506983aee0b5 Signed-off-by: Michael I Gold <gold@nvidia.com> Reviewed-on: http://git-master/r/213743 Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com> Reviewed-by: Robert Morell <rmorell@nvidia.com>
-rw-r--r--drivers/video/tegra/Kconfig5
-rw-r--r--drivers/video/tegra/dc/dc_reg.h10
-rw-r--r--drivers/video/tegra/dc/dc_sysfs.c62
-rw-r--r--drivers/video/tegra/dc/ext/cursor.c60
-rw-r--r--include/video/tegra_dc_ext.h12
5 files changed, 132 insertions, 17 deletions
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig
index 9ee0b5499707..ed50ee467c9f 100644
--- a/drivers/video/tegra/Kconfig
+++ b/drivers/video/tegra/Kconfig
@@ -42,6 +42,11 @@ config TEGRA_DC_CMU
default n if ARCH_TEGRA_2x_SOC || ARCH_TEGRA_3x_SOC
default y
+config TEGRA_DC_WIN_H
+ bool
+ default y if ARCH_TEGRA_14x_SOC
+ default n
+
config TEGRA_MIPI_CAL
bool
default n if ARCH_TEGRA_2x_SOC || ARCH_TEGRA_3x_SOC
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 1fdf7e066c1c..7ad07e45a478 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -110,6 +110,8 @@
#define WINDOW_A_SELECT (1 << 4)
#define WINDOW_B_SELECT (1 << 5)
#define WINDOW_C_SELECT (1 << 6)
+#define WINDOW_D_SELECT (1 << 7)
+#define WINDOW_H_SELECT (1 << 8)
#define DC_CMD_REG_ACT_CONTROL 0x043
@@ -379,7 +381,9 @@
#define DC_DISP_CURSOR_START_ADDR_NS 0x43f
#define CURSOR_START_ADDR_MASK (((1 << 22) - 1) << 10)
#define CURSOR_START_ADDR(_addr) ((_addr) >> 10)
-#define CURSOR_SIZE_64 (1 << 24)
+#define CURSOR_SIZE_64 (0x1 << 24)
+#define CURSOR_SIZE_128 (0x2 << 24)
+#define CURSOR_SIZE_256 (0x3 << 24)
#define DC_DISP_CURSOR_POSITION 0x440
#define CURSOR_POSITION(_x, _y) \
@@ -674,4 +678,8 @@
#define NUM_AGG_PRI_LVLS 4
#define SD_AGG_PRI_LVL(x) ((x) >> 3)
#define SD_GET_AGG(x) ((x) & 0x7)
+
+#define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1
+#define CURSOR_MODE_SELECT(x) (((x) & 0x1) << 24)
+
#endif
diff --git a/drivers/video/tegra/dc/dc_sysfs.c b/drivers/video/tegra/dc/dc_sysfs.c
index 6b34c4352986..f3dfd682ef5d 100644
--- a/drivers/video/tegra/dc/dc_sysfs.c
+++ b/drivers/video/tegra/dc/dc_sysfs.c
@@ -136,6 +136,62 @@ static ssize_t enable_store(struct device *dev,
static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, enable_show, enable_store);
+#ifdef CONFIG_TEGRA_DC_WIN_H
+static ssize_t win_h_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *ndev = to_platform_device(device);
+ struct tegra_dc *dc = platform_get_drvdata(ndev);
+ unsigned long val = 0;
+
+ mutex_lock(&dc->lock);
+ tegra_dc_io_start(dc);
+
+ val = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
+
+ tegra_dc_io_end(dc);
+ mutex_unlock(&dc->lock);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", !!(val & WINH_CURS_SELECT(1)));
+}
+
+/* win_h sysfs controls hybrid window.
+ *
+ * 0 = cursor mode and 1 = window mode (default on T14x) */
+static ssize_t win_h_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct platform_device *ndev = to_platform_device(dev);
+ struct tegra_dc *dc = platform_get_drvdata(ndev);
+ unsigned int val = 0;
+ unsigned long cursor_val = 0;
+
+ if (!dc->enabled) {
+ dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
+ return -EFAULT;
+ }
+
+ if (kstrtouint(buf, 10, &val) < 0)
+ return -EINVAL;
+
+ mutex_lock(&dc->lock);
+ tegra_dc_io_start(dc);
+
+ cursor_val = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
+ cursor_val &= ~WINH_CURS_SELECT(1);
+ if (val)
+ cursor_val |= WINH_CURS_SELECT(1);
+ tegra_dc_writel(dc, cursor_val, DC_DISP_BLEND_CURSOR_CONTROL);
+
+ tegra_dc_io_end(dc);
+ mutex_unlock(&dc->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(win_h, S_IRUGO|S_IWUSR, win_h_show, win_h_store);
+#endif
+
static ssize_t crc_checksum_latched_show(struct device *device,
struct device_attribute *attr, char *buf)
{
@@ -458,6 +514,9 @@ void __devexit tegra_dc_remove_sysfs(struct device *dev)
device_remove_file(dev, &dev_attr_stats_enable);
device_remove_file(dev, &dev_attr_crc_checksum_latched);
device_remove_file(dev, &dev_attr_colorbar);
+#ifdef CONFIG_TEGRA_DC_WIN_H
+ device_remove_file(dev, &dev_attr_win_h);
+#endif
#ifdef CONFIG_TEGRA_DC_CMU
device_remove_file(dev, &dev_attr_cmu_enable);
#endif
@@ -487,6 +546,9 @@ void tegra_dc_create_sysfs(struct device *dev)
error |= device_create_file(dev, &dev_attr_stats_enable);
error |= device_create_file(dev, &dev_attr_crc_checksum_latched);
error |= device_create_file(dev, &dev_attr_colorbar);
+#ifdef CONFIG_TEGRA_DC_WIN_H
+ error |= device_create_file(dev, &dev_attr_win_h);
+#endif
#ifdef CONFIG_TEGRA_DC_CMU
error |= device_create_file(dev, &dev_attr_cmu_enable);
#endif
diff --git a/drivers/video/tegra/dc/ext/cursor.c b/drivers/video/tegra/dc/ext/cursor.c
index ebfa6eb08ffa..17ce70fde35c 100644
--- a/drivers/video/tegra/dc/ext/cursor.c
+++ b/drivers/video/tegra/dc/ext/cursor.c
@@ -62,6 +62,7 @@ static void set_cursor_image_hw(struct tegra_dc *dc,
struct tegra_dc_ext_cursor_image *args,
dma_addr_t phys_addr)
{
+ unsigned long val;
int clip_win;
tegra_dc_writel(dc,
@@ -77,15 +78,37 @@ static void set_cursor_image_hw(struct tegra_dc *dc,
BUG_ON(phys_addr & ~CURSOR_START_ADDR_MASK);
+ switch (TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(args->flags)) {
+ case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64:
+ val = CURSOR_SIZE_64;
+ break;
+ case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128:
+ val = CURSOR_SIZE_128;
+ break;
+ case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256:
+ val = CURSOR_SIZE_256;
+ break;
+ default:
+ val = 0;
+ }
+
/* Get the cursor clip window number */
clip_win = CURSOR_CLIP_GET_WINDOW(tegra_dc_readl(dc,
DC_DISP_CURSOR_START_ADDR));
+ val |= clip_win;
- tegra_dc_writel(dc, CURSOR_CLIP_SHIFT_BITS(clip_win) |
- CURSOR_START_ADDR(((unsigned long) phys_addr)) |
- ((args->flags & TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) ?
- CURSOR_SIZE_64 : 0),
+ tegra_dc_writel(dc,
+ val | CURSOR_START_ADDR(((unsigned long) phys_addr)),
DC_DISP_CURSOR_START_ADDR);
+
+ if (args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL)
+ tegra_dc_writel(dc,
+ CURSOR_MODE_SELECT(1),
+ DC_DISP_BLEND_CURSOR_CONTROL);
+ else
+ tegra_dc_writel(dc,
+ CURSOR_MODE_SELECT(0),
+ DC_DISP_BLEND_CURSOR_CONTROL);
}
int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
@@ -101,12 +124,23 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
if (!user->nvmap)
return -EFAULT;
- size = args->flags & (TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 |
- TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64);
-
+ size = TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(args->flags);
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 &&
size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64)
return -EINVAL;
+#else
+ if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 &&
+ size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64 &&
+ size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128 &&
+ size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256)
+ return -EINVAL;
+#endif
+
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ if (args->flags && TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL)
+ return -EINVAL;
+#endif
mutex_lock(&ext->cursor.lock);
@@ -163,7 +197,7 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
{
struct tegra_dc_ext *ext = user->ext;
struct tegra_dc *dc = ext->dc;
- u32 win_options;
+ u32 val;
bool enable;
int ret;
@@ -185,12 +219,12 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
tegra_dc_io_start(dc);
tegra_dc_hold_dc_out(dc);
- win_options = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
- if (!!(win_options & CURSOR_ENABLE) != enable) {
- win_options &= ~CURSOR_ENABLE;
+ val = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+ if (!!(val & CURSOR_ENABLE) != enable) {
+ val &= ~CURSOR_ENABLE;
if (enable)
- win_options |= CURSOR_ENABLE;
- tegra_dc_writel(dc, win_options, DC_DISP_DISP_WIN_OPTIONS);
+ val |= CURSOR_ENABLE;
+ tegra_dc_writel(dc, val, DC_DISP_DISP_WIN_OPTIONS);
}
tegra_dc_writel(dc, CURSOR_POSITION(args->x, args->y),
diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h
index 52c9f21a5372..1306b2ff06b4 100644
--- a/include/video/tegra_dc_ext.h
+++ b/include/video/tegra_dc_ext.h
@@ -122,8 +122,14 @@ struct tegra_dc_ext_flip {
* 0 1 foreground color
* - Exactly one of the SIZE flags must be specified.
*/
-#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 1
-#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64 2
+
+#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 ((1 & 0x7) << 0)
+#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64 ((2 & 0x7) << 0)
+#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128 ((3 & 0x7) << 0)
+#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256 ((4 & 0x7) << 0)
+#define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(x) (((x) & 0x7) >> 0)
+#define TEGRA_DC_EXT_CURSOR_FLAGS_2BIT_LEGACY (0 << 16)
+#define TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL (1 << 16)
struct tegra_dc_ext_cursor_image {
struct {
__u8 r;
@@ -135,7 +141,7 @@ struct tegra_dc_ext_cursor_image {
};
/* Possible flags for struct nvdc_cursor's flags field */
-#define TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE 1
+#define TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE (1 << 0)
struct tegra_dc_ext_cursor {
__s16 x;