summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/dc/dc.c46
-rw-r--r--drivers/video/tegra/dc/ext/dev.c71
-rw-r--r--include/video/tegra_dc_ext.h25
3 files changed, 141 insertions, 1 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index b1899a517..e2daa826e 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -665,6 +665,48 @@ int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
665} 665}
666EXPORT_SYMBOL(tegra_dc_update_csc); 666EXPORT_SYMBOL(tegra_dc_update_csc);
667 667
668static void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
669{
670 int i;
671 for(i=0; i<256; i++) {
672 lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
673 }
674}
675
676static void tegra_dc_set_lut(struct tegra_dc *dc,
677 struct tegra_dc_lut *lut,
678 int start,
679 int len)
680{
681 int i;
682 for (i = start, len += start; i < len; i++) {
683 u32 rgb = ((u32)lut->r[i]) |
684 ((u32)lut->g[i]<<8) |
685 ((u32)lut->b[i]<<16);
686 tegra_dc_writel(dc, rgb, DC_WIN_COLOR_PALETTE(i));
687 }
688}
689
690int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int start, int len)
691{
692 mutex_lock(&dc->lock);
693
694 if (!dc->enabled) {
695 mutex_unlock(&dc->lock);
696 return -EFAULT;
697 }
698
699 tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
700 DC_CMD_DISPLAY_WINDOW_HEADER);
701
702 tegra_dc_set_lut(dc, &dc->windows[win_idx].lut, start, len);
703
704 mutex_unlock(&dc->lock);
705
706 return 0;
707}
708EXPORT_SYMBOL(tegra_dc_update_lut);
709
668static void tegra_dc_set_scaling_filter(struct tegra_dc *dc) 710static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
669{ 711{
670 unsigned i; 712 unsigned i;
@@ -1075,7 +1117,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
1075 DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV, 1117 DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
1076 DC_WIN_BUFFER_ADDR_MODE); 1118 DC_WIN_BUFFER_ADDR_MODE);
1077 1119
1078 val = WIN_ENABLE; 1120 val = WIN_ENABLE | CP_ENABLE;
1079 if (yuvp) 1121 if (yuvp)
1080 val |= CSC_ENABLE; 1122 val |= CSC_ENABLE;
1081 else if (tegra_dc_fmt_bpp(win->fmt) < 24) 1123 else if (tegra_dc_fmt_bpp(win->fmt) < 24)
@@ -2155,6 +2197,8 @@ static void tegra_dc_init(struct tegra_dc *dc)
2155 DC_CMD_DISPLAY_WINDOW_HEADER); 2197 DC_CMD_DISPLAY_WINDOW_HEADER);
2156 tegra_dc_init_csc_defaults(&dc->windows[i].csc); 2198 tegra_dc_init_csc_defaults(&dc->windows[i].csc);
2157 tegra_dc_set_csc(dc, &dc->windows[i].csc); 2199 tegra_dc_set_csc(dc, &dc->windows[i].csc);
2200 tegra_dc_init_lut_defaults(&dc->windows[i].lut);
2201 tegra_dc_set_lut(dc, &dc->windows[i].lut, 0, 256);
2158 tegra_dc_set_scaling_filter(dc); 2202 tegra_dc_set_scaling_filter(dc);
2159 } 2203 }
2160 2204
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index 4e631d112..c0429b37f 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -521,6 +521,67 @@ static int tegra_dc_ext_set_csc(struct tegra_dc_ext_user *user,
521 return 0; 521 return 0;
522} 522}
523 523
524static int set_lut_channel(u16 *channel_from_user,
525 u8 *channel_to,
526 u32 start,
527 u32 len)
528{
529 int i;
530 u16 lut16bpp[256];
531
532 if (copy_from_user(lut16bpp, channel_from_user, len<<1))
533 return 1;
534
535 for (i=0; i<len; i++)
536 channel_to[start+i] = lut16bpp[i]>>8;
537
538 return 0;
539}
540
541static int tegra_dc_ext_set_lut(struct tegra_dc_ext_user *user,
542 struct tegra_dc_ext_lut *new_lut)
543{
544 int err;
545 unsigned int index = new_lut->win_index;
546 u32 start = new_lut->start;
547 u32 len = new_lut->len;
548
549 struct tegra_dc *dc = user->ext->dc;
550 struct tegra_dc_ext_win *ext_win;
551 struct tegra_dc_lut *lut;
552
553 if (index >= DC_N_WINDOWS)
554 return -EINVAL;
555
556 if ((start >= 256) || (len > 256) || ((start + len) > 256))
557 return -EINVAL;
558
559 ext_win = &user->ext->win[index];
560 lut = &dc->windows[index].lut;
561
562 mutex_lock(&ext_win->lock);
563
564 if (ext_win->user != user) {
565 mutex_unlock(&ext_win->lock);
566 return -EACCES;
567 }
568
569 err = set_lut_channel(new_lut->r, lut->r, start, len) |
570 set_lut_channel(new_lut->g, lut->g, start, len) |
571 set_lut_channel(new_lut->b, lut->b, start, len);
572
573 if (err) {
574 mutex_unlock(&ext_win->lock);
575 return -EFAULT;
576 }
577
578 tegra_dc_update_lut(dc, index, start, len);
579
580 mutex_unlock(&ext_win->lock);
581
582 return 0;
583}
584
524static u32 tegra_dc_ext_get_vblank_syncpt(struct tegra_dc_ext_user *user) 585static u32 tegra_dc_ext_get_vblank_syncpt(struct tegra_dc_ext_user *user)
525{ 586{
526 struct tegra_dc *dc = user->ext->dc; 587 struct tegra_dc *dc = user->ext->dc;
@@ -628,6 +689,16 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
628 return ret; 689 return ret;
629 } 690 }
630 691
692 case TEGRA_DC_EXT_SET_LUT:
693 {
694 struct tegra_dc_ext_lut args;
695
696 if (copy_from_user(&args, user_arg, sizeof(args)))
697 return -EFAULT;
698
699 return tegra_dc_ext_set_lut(user, &args);
700 }
701
631 default: 702 default:
632 return -EINVAL; 703 return -EINVAL;
633 } 704 }
diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h
index bdfebaeb3..77d4e62d7 100644
--- a/include/video/tegra_dc_ext.h
+++ b/include/video/tegra_dc_ext.h
@@ -164,6 +164,29 @@ struct tegra_dc_ext_csc {
164 __u16 kvb; /* s.2.8 */ 164 __u16 kvb; /* s.2.8 */
165}; 165};
166 166
167/*
168 * RGB Lookup table
169 *
170 * In true-color and YUV modes this is used for post-CSC RGB->RGB lookup, i.e.
171 * gamma-correction. In palette-indexed RGB modes, this table designates the
172 * mode's color palette.
173 *
174 * To convert 8-bit per channel RGB values to 16-bit, duplicate the 8 bits
175 * in low and high byte, e.g. r=r|(r<<8)
176 *
177 * Current Tegra DC hardware supports 8-bit per channel to 8-bit per channel,
178 * and each hardware window (overlay) uses its own lookup table.
179 *
180 */
181struct tegra_dc_ext_lut {
182 __u32 win_index; /* window index to set lut for */
183 __u32 start; /* start index to update lut from */
184 __u32 len; /* number of valid lut entries */
185 __u16* r; /* array of size 16-bit red values */
186 __u16* g; /* array of size 16-bit green values */
187 __u16* b; /* array of size 16-bit blue values */
188};
189
167 190
168#define TEGRA_DC_EXT_FLAGS_ENABLED 1 191#define TEGRA_DC_EXT_FLAGS_ENABLED 1
169struct tegra_dc_ext_status { 192struct tegra_dc_ext_status {
@@ -205,6 +228,8 @@ struct tegra_dc_ext_status {
205#define TEGRA_DC_EXT_GET_VBLANK_SYNCPT \ 228#define TEGRA_DC_EXT_GET_VBLANK_SYNCPT \
206 _IOR('D', 0x09, __u32) 229 _IOR('D', 0x09, __u32)
207 230
231#define TEGRA_DC_EXT_SET_LUT \
232 _IOR('D', 0x0A, struct tegra_dc_ext_lut)
208 233
209enum tegra_dc_ext_control_output_type { 234enum tegra_dc_ext_control_output_type {
210 TEGRA_DC_EXT_DSI, 235 TEGRA_DC_EXT_DSI,