Merge branch linux-tegra-2.6.36 into android-tegra-2.6.36

Change-Id: Iff6fb3eee3b96120f3973ccada4c0b0772dbc2b3
This commit is contained in:
Erik Gilling
2010-11-18 16:36:48 -08:00
5 changed files with 137 additions and 28 deletions

View File

@@ -86,7 +86,10 @@ struct tegra_dc_win {
void *virt_addr;
dma_addr_t phys_addr;
unsigned offset_u;
unsigned offset_v;
unsigned stride;
unsigned stride_uv;
unsigned x;
unsigned y;
unsigned w;

View File

@@ -75,12 +75,15 @@ static inline int tegra_dc_fmt_bpp(int fmt)
case TEGRA_WIN_FMT_R6x2G6x2B6x2A8:
return 32;
case TEGRA_WIN_FMT_YCbCr422:
case TEGRA_WIN_FMT_YUV422:
/* for planar formats, size of the Y plane, 8bit */
case TEGRA_WIN_FMT_YCbCr420P:
case TEGRA_WIN_FMT_YUV420P:
case TEGRA_WIN_FMT_YCbCr422P:
case TEGRA_WIN_FMT_YUV422P:
return 8;
case TEGRA_WIN_FMT_YCbCr422:
case TEGRA_WIN_FMT_YUV422:
case TEGRA_WIN_FMT_YCbCr422R:
case TEGRA_WIN_FMT_YUV422R:
case TEGRA_WIN_FMT_YCbCr422RA:
@@ -91,6 +94,18 @@ static inline int tegra_dc_fmt_bpp(int fmt)
return 0;
}
static inline bool tegra_dc_is_yuv_planar(int fmt)
{
switch (fmt) {
case TEGRA_WIN_FMT_YUV420P:
case TEGRA_WIN_FMT_YCbCr420P:
case TEGRA_WIN_FMT_YCbCr422P:
case TEGRA_WIN_FMT_YUV422P:
return true;
}
return false;
}
#define DUMP_REG(a) do { \
snprintf(buff, sizeof(buff), "%-32s\t%03x\t%08lx\n", \
#a, a, tegra_dc_readl(dc, a)); \
@@ -219,15 +234,26 @@ static void _dump_regs(struct tegra_dc *dc, void *data,
DUMP_REG(DC_WIN_DDA_INCREMENT);
DUMP_REG(DC_WIN_LINE_STRIDE);
DUMP_REG(DC_WIN_BUF_STRIDE);
DUMP_REG(DC_WIN_UV_BUF_STRIDE);
DUMP_REG(DC_WIN_BLEND_NOKEY);
DUMP_REG(DC_WIN_BLEND_1WIN);
DUMP_REG(DC_WIN_BLEND_2WIN_X);
DUMP_REG(DC_WIN_BLEND_2WIN_Y);
DUMP_REG(DC_WIN_BLEND_3WIN_XY);
DUMP_REG(DC_WINBUF_START_ADDR);
DUMP_REG(DC_WINBUF_START_ADDR_U);
DUMP_REG(DC_WINBUF_START_ADDR_V);
DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
DUMP_REG(DC_WINBUF_UFLOW_STATUS);
DUMP_REG(DC_WIN_CSC_YOF);
DUMP_REG(DC_WIN_CSC_KYRGB);
DUMP_REG(DC_WIN_CSC_KUR);
DUMP_REG(DC_WIN_CSC_KVR);
DUMP_REG(DC_WIN_CSC_KUG);
DUMP_REG(DC_WIN_CSC_KVG);
DUMP_REG(DC_WIN_CSC_KUB);
DUMP_REG(DC_WIN_CSC_KVB);
}
tegra_dc_io_end(dc);
@@ -414,6 +440,35 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *bl
}
}
static void tegra_dc_set_csc(struct tegra_dc *dc)
{
tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
}
static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
{
unsigned i;
unsigned v0 = 128;
unsigned v1 = 0;
/* linear horizontal and vertical filters */
for (i = 0; i < 16; i++) {
tegra_dc_writel(dc, (v1 << 16) | (v0 << 8),
DC_WIN_H_FILTER_P(i));
tegra_dc_writel(dc, v0,
DC_WIN_V_FILTER_P(i));
v0 -= 8;
v1 += 8;
}
}
/* does not support updating windows on multiple dcs in one call */
int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
{
@@ -441,6 +496,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
struct tegra_dc_win *win = windows[i];
unsigned h_dda;
unsigned v_dda;
bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
if (win->z != dc->blend.z[win->idx]) {
dc->blend.z[win->idx] = win->z;
@@ -467,10 +523,6 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
tegra_dc_writel(dc, win->fmt, DC_WIN_COLOR_DEPTH);
tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
/* TODO: implement filter on settings */
h_dda = (win->w * 0x1000) / max_t(int, win->out_w - 1, 1);
v_dda = (win->h * 0x1000) / max_t(int, win->out_h - 1, 1);
tegra_dc_writel(dc,
V_POSITION(win->out_y) | H_POSITION(win->out_x),
DC_WIN_POSITION);
@@ -479,24 +531,53 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
DC_WIN_SIZE);
tegra_dc_writel(dc,
V_PRESCALED_SIZE(win->h) |
H_PRESCALED_SIZE(win->w*tegra_dc_fmt_bpp(win->fmt)/8),
H_PRESCALED_SIZE(win->w * tegra_dc_fmt_bpp(win->fmt) / 8),
DC_WIN_PRESCALED_SIZE);
tegra_dc_writel(dc, 0, DC_WIN_H_INITIAL_DDA);
tegra_dc_writel(dc, 0, DC_WIN_V_INITIAL_DDA);
h_dda = ((win->w - 1) * 0x1000) / max_t(int, win->out_w - 1, 1);
v_dda = ((win->h - 1) * 0x1000) / max_t(int, win->out_h - 1, 1);
tegra_dc_writel(dc, V_DDA_INC(v_dda) | H_DDA_INC(h_dda),
DC_WIN_DDA_INCREMENT);
tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
tegra_dc_writel(dc, 0, DC_WIN_H_INITIAL_DDA);
tegra_dc_writel(dc, 0, DC_WIN_V_INITIAL_DDA);
tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
tegra_dc_writel(dc, (unsigned long)win->phys_addr,
DC_WINBUF_START_ADDR);
tegra_dc_writel(dc, win->x, DC_WINBUF_ADDR_H_OFFSET);
if (!yuvp) {
tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
} else {
tegra_dc_writel(dc,
(unsigned long)win->phys_addr +
(unsigned long)win->offset_u,
DC_WINBUF_START_ADDR_U);
tegra_dc_writel(dc,
(unsigned long)win->phys_addr +
(unsigned long)win->offset_v,
DC_WINBUF_START_ADDR_V);
tegra_dc_writel(dc,
LINE_STRIDE(win->stride) |
UV_LINE_STRIDE(win->stride_uv),
DC_WIN_LINE_STRIDE);
}
tegra_dc_writel(dc, win->x * tegra_dc_fmt_bpp(win->fmt) / 8,
DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, win->y, DC_WINBUF_ADDR_V_OFFSET);
val = WIN_ENABLE;
if (tegra_dc_fmt_bpp(win->fmt) < 24)
if (yuvp)
val |= CSC_ENABLE;
else if (tegra_dc_fmt_bpp(win->fmt) < 24)
val |= COLOR_EXPAND;
if (win->w != win->out_w)
val |= H_FILTER_ENABLE;
if (win->h != win->out_h)
val |= V_FILTER_ENABLE;
tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
win->dirty = no_vsync ? 0 : 1;
@@ -812,6 +893,7 @@ static void tegra_dc_init(struct tegra_dc *dc)
{
u32 disp_syncpt;
u32 vblank_syncpt;
int i;
tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
if (dc->ndev->id == 0) {
@@ -855,6 +937,13 @@ static void tegra_dc_init(struct tegra_dc *dc)
tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
tegra_dc_set_color_control(dc);
for (i = 0; i < DC_N_WINDOWS; i++) {
tegra_dc_writel(dc, WINDOW_A_SELECT << i,
DC_CMD_DISPLAY_WINDOW_HEADER);
tegra_dc_set_csc(dc);
tegra_dc_set_scaling_filter(dc);
}
dc->syncpt_id = disp_syncpt;

View File

@@ -309,26 +309,29 @@
#define DC_DISP_DAC_CRT_CTRL 0x4c0
#define DC_DISP_DISP_MISC_CONTROL 0x4c1
#define DC_WINC_COLOR_PALETTE(x) (0x500 + (x))
#define DC_WIN_COLOR_PALETTE(x) (0x500 + (x))
#define DC_WINC_PALETTE_COLOR_EXT 0x600
#define DC_WINC_H_FILTER_P(x) (0x601 + (x))
#define DC_WINC_CSC_YOF 0x611
#define DC_WINC_CSC_KYRGB 0x612
#define DC_WINC_CSC_KUR 0x613
#define DC_WINC_CSC_KVR 0x614
#define DC_WINC_CSC_KUG 0x615
#define DC_WINC_CSC_KVG 0x616
#define DC_WINC_CSC_KUB 0x617
#define DC_WINC_CSC_KVB 0x618
#define DC_WINC_V_FILTER_P(x) (0x619 + (x))
#define DC_WIN_PALETTE_COLOR_EXT 0x600
#define DC_WIN_H_FILTER_P(x) (0x601 + (x))
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_V_FILTER_P(x) (0x619 + (x))
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION_INCREMENT (0 << 0)
#define H_DIRECTION_DECREMENTT (1 << 0)
#define V_DIRECTION_INCREMENT (0 << 2)
#define V_DIRECTION_DECREMENTT (1 << 2)
#define COLOR_EXPAND (1 << 6)
#define H_FILTER_ENABLE (1 << 8)
#define V_FILTER_ENABLE (1 << 10)
#define CP_ENABLE (1 << 16)
#define CSC_ENABLE (1 << 18)
#define DV_ENABLE (1 << 20)
#define WIN_ENABLE (1 << 30)
@@ -366,6 +369,8 @@
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70a
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_BUF_STRIDE 0x70b
#define DC_WIN_UV_BUF_STRIDE 0x70c
#define DC_WIN_BUFFER_ADDR_MODE 0x70d

View File

@@ -149,6 +149,9 @@ static int tegra_fb_set_par(struct fb_info *info)
}
info->fix.line_length = var->xres * var->bits_per_pixel / 8;
tegra_fb->win->stride = info->fix.line_length;
tegra_fb->win->stride_uv = 0;
tegra_fb->win->offset_u = 0;
tegra_fb->win->offset_v = 0;
}
if (var->pixclock) {
@@ -176,9 +179,9 @@ static int tegra_fb_set_par(struct fb_info *info)
tegra_dc_set_mode(tegra_fb->win->dc, &mode);
tegra_fb->win->w = info->mode->xres;
tegra_fb->win->h = info->mode->xres;
tegra_fb->win->h = info->mode->yres;
tegra_fb->win->out_w = info->mode->xres;
tegra_fb->win->out_h = info->mode->xres;
tegra_fb->win->out_h = info->mode->yres;
}
return 0;
}
@@ -372,7 +375,10 @@ static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
/* STOPSHIP verify that this won't read outside of the surface */
win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
win->offset_u = flip_win->attr.offset_u + flip_win->attr.offset;
win->offset_v = flip_win->attr.offset_v + flip_win->attr.offset;
win->stride = flip_win->attr.stride;
win->stride_uv = flip_win->attr.stride_uv;
if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
@@ -737,7 +743,10 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
win->z = 0;
win->phys_addr = fb_phys;
win->virt_addr = fb_base;
win->offset_u = 0;
win->offset_v = 0;
win->stride = fb_data->xres * fb_data->bits_per_pixel / 8;
win->stride_uv = 0;
win->flags = TEGRA_WIN_FLAG_ENABLED;
if (fb_mem)

View File

@@ -55,7 +55,10 @@ struct tegra_fb_windowattr {
__u32 buff_id;
__u32 blend;
__u32 offset;
__u32 offset_u;
__u32 offset_v;
__u32 stride;
__u32 stride_uv;
__u32 pixformat;
__u32 x;
__u32 y;